/* This is a proposed C API for support of SASL
*********************************IMPORTANT*******************************
* send email to chris.newman@innosoft.com and cyrus-bugs@andrew.cmu.edu *
* if you need to add new error codes, callback types, property values, *
* etc. It is important to keep the multiple implementations of this *
*********************************IMPORTANT*******************************
* sasl_conn_t Context for a SASL connection negotiation
* sasl_ssf_t Security layer Strength Factor
* sasl_callback_t A typed client/server callback function and context
* sasl_interact_t A client interaction descriptor
* sasl_secret_t A client password
* sasl_rand_t Random data context structure
* sasl_security_properties_t An application's required security level
* sasl_getopt_t client/server: Get an option value
* sasl_logmsg_t client/server: Log message handler
* sasl_getsimple_t client: Get user/language list
* sasl_getsecret_t client: Get authentication secret
* sasl_chalprompt_t client: Display challenge and prompt for response
* sasl_authorize_t user authorization policy callback
* sasl_getconfpath_t get path to search for config file
* sasl_server_userdb_checkpass check password and auxprops in userdb
* sasl_server_userdb_setpass set password in userdb
* sasl_server_canon_user canonicalize username routine
* Client/Server Function Summary:
* sasl_done Release all SASL global state
* sasl_dispose Connection done: Dispose of sasl_conn_t
* sasl_getprop Get property (e.g., user name, security layer info)
* sasl_setprop Set property (e.g., external ssf)
* sasl_errdetail Generate string from last error on connection
* sasl_errstring Translate sasl error code to a string
* sasl_encode Encode data to send using security layer
* sasl_decode Decode data received using security layer
* sasl_encode64 Encode data to send using MIME base64 encoding
* sasl_decode64 Decode data received using MIME base64 encoding
* sasl_erasebuffer Erase a buffer
* Client Function Summary:
* sasl_client_init Load and initialize client plug-ins (call once)
* sasl_client_new Initialize client connection context: sasl_conn_t
* sasl_client_start Select mechanism for connection
* sasl_client_step Perform one authentication step
* Server Function Summary
* sasl_server_init Load and initialize server plug-ins (call once)
* sasl_server_new Initialize server connection context: sasl_conn_t
* sasl_listmech Create list of available mechanisms
* sasl_server_start Begin an authentication exchange
* sasl_server_step Perform one authentication exchange step
* sasl_checkpass Check a plaintext passphrase
* sasl_checkapop Check an APOP challenge/response (uses pseudo "APOP"
* mechanism similar to CRAM-MD5 mechanism; optional)
* sasl_user_exists Check if user exists
* sasl_setpass Change a password or add a user entry
* sasl_auxprop_request Request auxiliary properties
* sasl_auxprop_getctx Get auxiliary property context for connection
* sasl_auxprop_store Store a set of auxiliary properties
* 1. client calls sasl_client_init() at startup to load plug-ins
* 2. when connection formed, call sasl_client_new()
* 3. once list of supported mechanisms received from server, client
* calls sasl_client_start(). goto 4a
* 4. client calls sasl_client_step()
* [4a. If SASL_INTERACT, fill in prompts and goto 4
* -- doesn't happen if callbacks provided]
* 4b. If SASL error, goto 7 or 3
* 4c. If SASL_OK, continue or goto 6 if last server response was success
* 5. send message to server, wait for response
* 5a. On data or success with server response, goto 4
* 5b. On failure goto 7 or 3
* 5c. On success with no server response continue
* 6. continue with application protocol until connection closes
* call sasl_getprop/sasl_encode/sasl_decode() if using security layer
* 7. call sasl_dispose(), may return to step 2
* 8. call sasl_done() when program terminates
* 1. call sasl_server_init() at startup to load plug-ins
* 2. On connection, call sasl_server_new()
* 3. call sasl_listmech() and send list to client]
* 4. after client AUTH command, call sasl_server_start(), goto 5a
* 5. call sasl_server_step()
* 5a. If SASL_CONTINUE, output to client, wait response, repeat 5
* 5b. If SASL error, then goto 7
* 5c. If SASL_OK, move on
* 6. continue with application protocol until connection closes
* call sasl_getprop to get username
* call sasl_getprop/sasl_encode/sasl_decode() if using security layer
* 7. call sasl_dispose(), may return to step 2
* 8. call sasl_done() when program terminates
*************************************************
* IMPORTANT NOTE: server realms / username syntax
* If a user name contains a "@", then the rightmost "@" in the user name
* separates the account name from the realm in which this account is
* located. A single server may support multiple realms. If the
* server knows the realm at connection creation time (e.g., a server
* with multiple IP addresses tightly binds one address to a specific
* realm) then that realm must be passed in the user_realm field of
* the sasl_server_new call. If user_realm is non-empty and an
* unqualified user name is supplied, then the canon_user facility is
* expected to append "@" and user_realm to the user name. The canon_user
* facility may treat other characters such as "%" as equivalent to "@".
* If the server forbids the use of "@" in user names for other
* purposes, this simplifies security validation.
#include <stddef.h> /* For size_t */
/* Keep in sync with win32/common.mak */
#define SASL_VERSION_MAJOR 2
#define SASL_VERSION_MINOR 1
#define SASL_VERSION_STEP 27
/* A convenience macro: same as was defined in the OpenLDAP LDAPDB */
#define SASL_VERSION_FULL ((SASL_VERSION_MAJOR << 16) |\
(SASL_VERSION_MINOR << 8) | SASL_VERSION_STEP)
#define SASL_CONTINUE 1 /* another step is needed in authentication */
#define SASL_OK 0 /* successful result */
#define SASL_FAIL -1 /* generic failure */
#define SASL_NOMEM -2 /* memory shortage failure */
#define SASL_BUFOVER -3 /* overflowed buffer */
#define SASL_NOMECH -4 /* mechanism not supported */
#define SASL_BADPROT -5 /* bad protocol / cancel */
#define SASL_NOTDONE -6 /* can't request info until later in exchange */
#define SASL_BADPARAM -7 /* invalid parameter supplied */
#define SASL_TRYAGAIN -8 /* transient failure (e.g., weak key) */
#define SASL_BADMAC -9 /* integrity check failed */
#define SASL_NOTINIT -12 /* SASL library not initialized */
/* -- client only codes -- */
#define SASL_INTERACT 2 /* needs user interaction */
#define SASL_BADSERV -10 /* server failed mutual authentication step */
#define SASL_WRONGMECH -11 /* mechanism doesn't support requested feature */
/* -- server only codes -- */
#define SASL_BADAUTH -13 /* authentication failure */
#define SASL_NOAUTHZ -14 /* authorization failure */
#define SASL_TOOWEAK -15 /* mechanism too weak for this user */
#define SASL_ENCRYPT -16 /* encryption needed to use mechanism */
#define SASL_TRANS -17 /* One time use of a plaintext password will
enable requested mechanism for user */
#define SASL_EXPIRED -18 /* passphrase expired, has to be reset */
#define SASL_DISABLED -19 /* account disabled */
#define SASL_NOUSER -20 /* user not found */
#define SASL_BADVERS -23 /* version mismatch with plug-in */
#define SASL_UNAVAIL -24 /* remote authentication server unavailable */
#define SASL_NOVERIFY -26 /* user exists, but no verifier for user */
/* -- codes for password setting -- */
#define SASL_PWLOCK -21 /* passphrase locked */
#define SASL_NOCHANGE -22 /* requested change was not needed */
#define SASL_WEAKPASS -27 /* passphrase is too weak for security policy */
#define SASL_NOUSERPASS -28 /* user supplied passwords not permitted */
#define SASL_NEED_OLD_PASSWD -29 /* sasl_setpass needs old password in order
to perform password change */
#define SASL_CONSTRAINT_VIOLAT -30 /* a property can't be stored,
because of some constrains/policy violation */
#define SASL_BADBINDING -32 /* channel binding failure */
#define SASL_CONFIGERR -100 /* error when parsing configuration file */
/* max size of a sasl mechanism name */
#define SASL_MECHNAMEMAX 20
/* Define to have the same layout as a WSABUF */
#ifndef STRUCT_IOVEC_DEFINED
#define STRUCT_IOVEC_DEFINED 1
struct iovec; /* Defined in OS headers */
/* per-connection SASL negotiation state for client or server
typedef struct sasl_conn sasl_conn_t;
/* Plain text password structure.
* len is the length of the password, data is the text.
typedef struct sasl_secret {
unsigned char data[1]; /* variable sized */
/* random data context structure
typedef struct sasl_rand_s sasl_rand_t;
/****************************
* Configure Basic Services *
****************************/
/* the following functions are used to adjust how allocation and mutexes work
* they must be called before all other SASL functions:
/* memory allocation functions which may optionally be replaced:
typedef void *sasl_malloc_t(size_t);
typedef void *sasl_calloc_t(size_t, size_t);
typedef void *sasl_realloc_t(void *, size_t);
typedef void sasl_free_t(void *);
LIBSASL_API void sasl_set_alloc(sasl_malloc_t *,
/* mutex functions which may optionally be replaced:
* sasl_mutex_alloc allocates a mutex structure
* sasl_mutex_lock blocks until mutex locked
* returns -1 on deadlock or parameter error
* sasl_mutex_unlock unlocks mutex if it's locked
* returns -1 if not locked or parameter error
* sasl_mutex_free frees a mutex structure
typedef void *sasl_mutex_alloc_t(void);
typedef int sasl_mutex_lock_t(void *mutex);
typedef int sasl_mutex_unlock_t(void *mutex);
typedef void sasl_mutex_free_t(void *mutex);
LIBSASL_API void sasl_set_mutex(sasl_mutex_alloc_t *, sasl_mutex_lock_t *,
sasl_mutex_unlock_t *, sasl_mutex_free_t *);
/*****************************
* Security preference types *
*****************************/
/* security layer strength factor -- an unsigned integer usable by the caller
* to specify approximate security layer strength desired. Roughly
* correlated to effective key length for encryption.
* 1 = integrity protection only
* 40 = 40-bit DES or 40-bit RC2/RC4
* 128 = 128-bit RC2/RC4/BLOWFISH
typedef unsigned sasl_ssf_t;
/* usage flags provided to sasl_server_new and sasl_client_new:
#define SASL_SUCCESS_DATA 0x0004 /* server supports data on success */
#define SASL_NEED_PROXY 0x0008 /* require a mech that allows proxying */
#define SASL_NEED_HTTP 0x0010 /* require a mech that can do HTTP auth */
/***************************
* Security Property Types *
***************************/
/* Structure specifying the client or server's security policy
* and optional additional properties.
/* These are the various security flags apps can specify. */
/* NOPLAINTEXT -- don't permit mechanisms susceptible to simple
* passive attack (e.g., PLAIN, LOGIN)
* NOACTIVE -- protection from active (non-dictionary) attacks
* during authentication exchange.
* NODICTIONARY -- don't permit mechanisms susceptible to passive
* FORWARD_SECRECY -- require forward secrecy between sessions
* (breaking one won't help break next)
* NOANONYMOUS -- don't permit mechanisms that allow anonymous login
* PASS_CREDENTIALS -- require mechanisms which pass client
* credentials, and allow mechanisms which can pass
* MUTUAL_AUTH -- require mechanisms which provide mutual
#define SASL_SEC_NOPLAINTEXT 0x0001
#define SASL_SEC_NOACTIVE 0x0002
#define SASL_SEC_NODICTIONARY 0x0004
#define SASL_SEC_FORWARD_SECRECY 0x0008
#define SASL_SEC_NOANONYMOUS 0x0010
#define SASL_SEC_PASS_CREDENTIALS 0x0020
#define SASL_SEC_MUTUAL_AUTH 0x0040
#define SASL_SEC_MAXIMUM 0x00FF
typedef struct sasl_security_properties
/* security strength factor
* min_ssf = minimum acceptable final level
* max_ssf = maximum acceptable final level
/* Maximum security layer receive buffer size.
* 0=security layer not supported
/* bitfield for attacks to protect against */
/* NULL terminated array of additional property names, values */
const char **property_names;
const char **property_values;
} sasl_security_properties_t;
* Extensible type for a client/server callbacks
* id -- identifies callback type
* proc -- procedure call arguments vary based on id
* context -- context passed to procedure
/* Note that any memory that is allocated by the callback needs to be
* freed by the application, be it via function call or interaction.
* It may be freed after sasl_*_step returns SASL_OK. if the mechanism
* requires this information to persist (for a security layer, for example)
* it must maintain a private copy.
typedef struct sasl_callback {
/* Identifies the type of the callback function.
* Mechanisms must ignore callbacks with id's they don't recognize.
int (*proc)(void); /* Callback function. Types of arguments vary by 'id' */
/* callback ids & functions:
#define SASL_CB_LIST_END 0 /* end of list */
/* option reading callback -- this allows a SASL configuration to be
* encapsulated in the caller's configuration system. Some implementations
* may use default config file(s) if this is omitted. Configuration items
* may be plugin-specific and are arbitrary strings.
* context -- option context from callback record
* plugin_name -- name of plugin (NULL = general SASL option)
* option -- name of option
* result -- set to result which persists until next getopt in
* same thread, unchanged if option not found
* len -- length of result (may be NULL)
typedef int sasl_getopt_t(void *context, const char *plugin_name,
const char **result, unsigned *len);
/* Logging levels for use with the logging callback function. */
#define SASL_LOG_NONE 0 /* don't log anything */
#define SASL_LOG_ERR 1 /* log unusual errors (default) */
#define SASL_LOG_FAIL 2 /* log all authentication failures */
#define SASL_LOG_WARN 3 /* log non-fatal warnings */
#define SASL_LOG_NOTE 4 /* more verbose than LOG_WARN */
#define SASL_LOG_DEBUG 5 /* more verbose than LOG_NOTE */
#define SASL_LOG_TRACE 6 /* traces of internal protocols */
#define SASL_LOG_PASS 7 /* traces of internal protocols, including
/* logging callback -- this allows plugins and the middleware to
* log operations they perform.
* context -- logging context from the callback record
* level -- logging level; see above
* message -- message to log
typedef int sasl_log_t(void *context,
/* getpath callback -- this allows applications to specify the
* colon-separated path to search for plugins (by default,
* taken from an implementation-specific location).
* context -- getpath context from the callback record
* path -- colon seperated path
typedef int sasl_getpath_t(void *context,
#define SASL_CB_GETPATH 3
/* verify file callback -- this allows applications to check if they
* want SASL to use files, file by file. This is intended to allow
* applications to sanity check the environment to make sure plugins
* or the configuration file can't be written to, etc.
* context -- verifypath context from the callback record
* file -- full path to file to verify
* type -- type of file to verify (see below)
* SASL_OK -- no error (file can safely be used)
* SASL_CONTINUE -- continue WITHOUT using this file
/* these are the types of files libsasl will ask about */
SASL_VRFY_PLUGIN=0, /* a DLL/shared library plug-in */
SASL_VRFY_CONF=1, /* a configuration file */
SASL_VRFY_PASSWD=2, /* a password storage file/db */
SASL_VRFY_OTHER=3 /* some other file */
typedef int sasl_verifyfile_t(void *context,
const char *file, sasl_verify_type_t type);
#define SASL_CB_VERIFYFILE 4
/* getconfpath callback -- this allows applications to specify the
* colon-separated path to search for config files (by default,
* taken from the SASL_CONF_PATH environment variable).
* context -- getconfpath context from the callback record
* path -- colon seperated path (allocated on the heap; the
* library will free it using the sasl_free_t *
* passed to sasl_set_callback, or the standard free()
typedef int sasl_getconfpath_t(void *context,
#define SASL_CB_GETCONFPATH 5
/* client/user interaction callbacks:
/* Simple prompt -- result must persist until next call to getsimple on
* same connection or until connection context is disposed
* context -- context from callback structure
* result -- set to NUL terminated string
* len -- length of result
typedef int sasl_getsimple_t(void *context, int id,
const char **result, unsigned *len);
#define SASL_CB_USER 0x4001 /* client user identity to login as */
#define SASL_CB_AUTHNAME 0x4002 /* client authentication name */
#define SASL_CB_LANGUAGE 0x4003 /* comma separated list of RFC 1766
* language codes in order of preference
* to be used to localize client prompts
* or server error codes */
#define SASL_CB_CNONCE 0x4007 /* caller supplies client-nonce