Home | History | Annotate | Download | only in include
      1 /*
      2  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 /* saslplug.h --  API for SASL plug-ins */
      7 
      8 #ifndef	_SASL_SASLPLUG_H
      9 #define	_SASL_SASLPLUG_H
     10 
     11 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     12 
     13 #ifndef	_SASL_SASL_H
     14 #include <sasl/sasl.h>
     15 #endif
     16 
     17 #ifndef _MD5_H
     18 #include <md5.h>
     19 #endif /* _MD5_H */
     20 
     21 #ifdef	__cplusplus
     22 extern "C" {
     23 #endif
     24 
     25 /* intermediate MD5 context */
     26 typedef struct HMAC_MD5_CTX_s {
     27     MD5_CTX ictx, octx;
     28 } HMAC_MD5_CTX;
     29 
     30 /*
     31  * intermediate HMAC state
     32  *  values stored in network byte order (Big Endian)
     33  */
     34 typedef struct HMAC_MD5_STATE_s {
     35     uint32_t istate[4];
     36     uint32_t ostate[4];
     37 } HMAC_MD5_STATE;
     38 
     39 /*
     40  * callback to lookup a sasl_callback_t for a connection
     41  * input:
     42  *  conn        -- the connection to lookup a callback for
     43  *  callbacknum -- the number of the callback
     44  * output:
     45  *  pproc       -- pointer to the callback function (set to NULL on failure)
     46  *  pcontext    -- pointer to the callback context (set to NULL on failure)
     47  * returns:
     48  *  SASL_OK -- no error
     49  *  SASL_FAIL -- unable to find a callback of the requested type
     50  *  SASL_INTERACT -- caller must use interaction to get data
     51  */
     52 typedef int sasl_getcallback_t(sasl_conn_t *conn,
     53 				unsigned long callbackid,
     54 				int (**pproc)(),
     55 				void **pcontext);
     56 
     57 /*
     58  * The sasl_utils structure will remain backwards compatible unless
     59  * the SASL_*_PLUG_VERSION is changed incompatibly
     60  * higher SASL_UTILS_VERSION numbers indicate more functions are available
     61  */
     62 #define	SASL_UTILS_VERSION 4
     63 
     64 /* utility function set for plug-ins */
     65 typedef struct sasl_utils {
     66     int version;
     67 
     68 	/* contexts */
     69     sasl_conn_t *conn;
     70     sasl_rand_t *rpool;
     71     void *getopt_context;
     72 
     73 	/* option function */
     74     sasl_getopt_t *getopt;
     75 
     76 	/* allocation functions: */
     77     sasl_malloc_t *malloc;
     78     sasl_calloc_t *calloc;
     79     sasl_realloc_t *realloc;
     80     sasl_free_t *free;
     81 
     82 	/* mutex functions: */
     83     sasl_mutex_alloc_t *mutex_alloc;
     84     sasl_mutex_lock_t *mutex_lock;
     85     sasl_mutex_unlock_t *mutex_unlock;
     86     sasl_mutex_free_t *mutex_free;
     87 
     88 	/* MD5 hash and HMAC functions */
     89     void (*MD5Init)(MD5_CTX *);
     90     void (*MD5Update)(MD5_CTX *, const unsigned char *text, unsigned int len);
     91     void (*MD5Final)(unsigned char [16], MD5_CTX *);
     92     void (*hmac_md5)(const unsigned char *text, int text_len,
     93 			const unsigned char *key, int key_len,
     94 			unsigned char [16]);
     95     void (*hmac_md5_init)(HMAC_MD5_CTX *, const unsigned char *key, int len);
     96 	/* hmac_md5_update() is just a call to MD5Update on inner context */
     97     void (*hmac_md5_final)(unsigned char [16], HMAC_MD5_CTX *);
     98     void (*hmac_md5_precalc)(HMAC_MD5_STATE *,
     99 				const unsigned char *key, int len);
    100     void (*hmac_md5_import)(HMAC_MD5_CTX *, HMAC_MD5_STATE *);
    101 
    102 	/* mechanism utility functions (same as above): */
    103     int (*mkchal)(sasl_conn_t *conn, char *buf, unsigned maxlen,
    104 		unsigned hostflag);
    105     int (*utf8verify)(const char *str, unsigned len);
    106     void (*rand)(sasl_rand_t *rpool, char *buf, unsigned len);
    107     void (*churn)(sasl_rand_t *rpool, const char *data, unsigned len);
    108 
    109 	/*
    110 	 * This allows recursive calls to the sasl_checkpass() routine from
    111 	 * within a SASL plug-in.  This MUST NOT be used in the PLAIN mechanism
    112 	 * as sasl_checkpass MAY be a front-end for the PLAIN mechanism.
    113 	 * This is intended for use by the non-standard LOGIN mechanism and
    114 	 * potentially by a future mechanism which uses public-key technology
    115 	 * to set up a lightweight encryption layer just for sending a
    116 	 * password.
    117 	 */
    118     int (*checkpass)(sasl_conn_t *conn,
    119 		    const char *user, unsigned userlen,
    120 		    const char *pass, unsigned passlen);
    121 
    122 	/* Access to base64 encode/decode routines */
    123     int (*decode64)(const char *in, unsigned inlen,
    124 		    char *out, unsigned outmax, unsigned *outlen);
    125     int (*encode64)(const char *in, unsigned inlen,
    126 		    char *out, unsigned outmax, unsigned *outlen);
    127 
    128 	/* erase a buffer */
    129     void (*erasebuffer)(char *buf, unsigned len);
    130 
    131 	/* callback to sasl_getprop() and sasl_setprop() */
    132     int (*getprop)(sasl_conn_t *conn, int propnum, const void **pvalue);
    133     int (*setprop)(sasl_conn_t *conn, int propnum, const void *value);
    134 
    135 	/* callback function */
    136     sasl_getcallback_t *getcallback;
    137 
    138 	/*
    139 	 * format a message and then pass it to the SASL_CB_LOG callback
    140 	 *
    141 	 * use syslog()-style formatting (printf with %m as most recent errno
    142 	 * error).  The implementation may use a fixed size buffer not smaller
    143 	 * than 512 octets if it securely truncates the message.
    144 	 *
    145 	 * level is a SASL_LOG_* level (see sasl.h)
    146 	 */
    147     void (*log)(sasl_conn_t *conn, int level, const char *fmt, ...);
    148 
    149 	/* callback to sasl_seterror() */
    150     void (*seterror)(sasl_conn_t *conn, unsigned flags, const char *fmt, ...);
    151 
    152 	/* spare function pointer */
    153     int *(*spare_fptr)();
    154 
    155 	/* auxiliary property utilities */
    156     struct propctx *(*prop_new)(unsigned estimate);
    157     int (*prop_dup)(struct propctx *src_ctx, struct propctx **dst_ctx);
    158     int (*prop_request)(struct propctx *ctx, const char **names);
    159     const struct propval *(*prop_get)(struct propctx *ctx);
    160     int (*prop_getnames)(struct propctx *ctx, const char **names,
    161 			struct propval *vals);
    162     void (*prop_clear)(struct propctx *ctx, int requests);
    163     void (*prop_dispose)(struct propctx **ctx);
    164     int (*prop_format)(struct propctx *ctx, const char *sep, int seplen,
    165 		    char *outbuf, unsigned outmax, unsigned *outlen);
    166     int (*prop_set)(struct propctx *ctx, const char *name,
    167 		    const char *value, int vallen);
    168     int (*prop_setvals)(struct propctx *ctx, const char *name,
    169 			const char **values);
    170     void (*prop_erase)(struct propctx *ctx, const char *name);
    171 
    172 	/* for additions which don't require a version upgrade; set to 0 */
    173     int (*spare_fptr1)();
    174     int (*spare_fptr2)();
    175     int (*spare_fptr3)();
    176 } sasl_utils_t;
    177 
    178 /*
    179  * output parameters from SASL API
    180  *
    181  * created / destroyed by the glue code, though probably filled in
    182  * by a combination of the plugin, the glue code, and the canon_user callback.
    183  *
    184  */
    185 typedef struct sasl_out_params {
    186     unsigned doneflag;		/* exchange complete */
    187 
    188     const char *user;		/* canonicalized user name */
    189     const char *authid;		/* canonicalized authentication id */
    190 
    191     unsigned ulen;		/* length of canonicalized user name */
    192     unsigned alen;		/* length of canonicalized authid */
    193 
    194 	/* security layer information */
    195     unsigned maxoutbuf;
    196     sasl_ssf_t mech_ssf;    /* Should be set non-zero if negotiation of a */
    197 			    /* security layer was *attempted*, even if */
    198 			    /* the negotiation failed */
    199     void *encode_context;
    200     int (*encode)(void *context, const struct iovec *invec, unsigned numiov,
    201 		const char **output, unsigned *outputlen);
    202     void *decode_context;
    203     int (*decode)(void *context, const char *input, unsigned inputlen,
    204 		const char **output, unsigned *outputlen);
    205 
    206 	/* for additions which don't require a version upgrade; set to 0 */
    207     void *spare_ptr1;
    208     void *spare_ptr2;
    209     void *spare_ptr3;
    210     void *spare_ptr4;
    211     int (*spare_fptr1)();
    212     int (*spare_fptr2)();
    213     int spare_int1;
    214     int spare_int2;
    215     int spare_int3;
    216     int spare_int4;
    217 
    218 	/*
    219 	 * set to 0 initially, this allows a plugin with extended parameters
    220 	 * to work with an older framework by updating version as parameters
    221 	 * are added.
    222 	 */
    223     int param_version;
    224 } sasl_out_params_t;
    225 
    226 /*
    227  * Client Mechanism Functions
    228  */
    229 
    230 /*
    231  * input parameters to client SASL plugin
    232  *
    233  * created / destroyed by the glue code
    234  *
    235  */
    236 typedef struct sasl_client_params {
    237     const char *service;	/* service name */
    238     const char *serverFQDN;	/* server fully qualified domain name */
    239     const char *clientFQDN;	/* client's fully qualified domain name */
    240     const sasl_utils_t *utils;	/* SASL API utility routines -- */
    241 				/* for a particular sasl_conn_t, */
    242 				/* MUST remain valid until mech_free is */
    243 				/* called */
    244     const sasl_callback_t *prompt_supp; /* client callback list */
    245     const char *iplocalport;	/* server IP domain literal & port */
    246     const char *ipremoteport;	/* client IP domain literal & port */
    247 
    248     unsigned servicelen;	/* length of service */
    249     unsigned slen;		/* length of serverFQDN */
    250     unsigned clen;		/* length of clientFQDN */
    251     unsigned iploclen;		/* length of iplocalport */
    252     unsigned ipremlen;		/* length of ipremoteport */
    253 
    254 	/* application's security requirements & info */
    255     sasl_security_properties_t props;
    256     sasl_ssf_t external_ssf;	/* external SSF active */
    257 
    258 	/* for additions which don't require a version upgrade; set to 0 */
    259     void *spare_ptr1;
    260     void *spare_ptr2;
    261     void *spare_ptr3;
    262     void *spare_ptr4;
    263 
    264 	/*
    265 	 * Canonicalize a user name from on-wire to internal format
    266 	 *  added rjs3 2001-05-23
    267 	 *  Must be called once user name aquired if canon_user is non-NULL.
    268 	 *  conn    connection context
    269 	 *  in	    user name from wire protocol (need not be NUL terminated)
    270 	 *  len	    length of user name from wire protocol (0 = strlen(user))
    271 	 *  flags   for SASL_CU_* flags
    272 	 *  oparams the user, authid, ulen, alen, fields are
    273 	 *	    set appropriately after canonicalization/copying and
    274 	 *	    authorization of arguments
    275 	 *
    276 	 *  responsible for setting user, ulen, authid, and alen in the oparams
    277 	 *  structure
    278 	 *
    279 	 *  default behavior is to strip leading and trailing whitespace, as
    280 	 *  well as allocating space for and copying the parameters.
    281 	 *
    282 	 * results:
    283 	 *  SASL_OK	  -- success
    284 	 *  SASL_NOMEM    -- out of memory
    285 	 *  SASL_BADPARAM -- invalid conn
    286 	 *  SASL_BADPROT  -- invalid user/authid
    287 	 */
    288     int (*canon_user)(sasl_conn_t *conn,
    289 		    const char *in, unsigned len,
    290 		    unsigned flags,
    291 		    sasl_out_params_t *oparams);
    292 
    293     int (*spare_fptr1)();
    294 
    295     int spare_int1;
    296     int spare_int2;
    297     int spare_int3;
    298 
    299 	/* flags field as passed to sasl_client_new */
    300     unsigned flags;
    301 
    302 	/*
    303 	 * set to 0 initially, this allows a plugin with extended parameters
    304 	 * to work with an older framework by updating version as parameters
    305 	 * are added.
    306 	 */
    307     int param_version;
    308 } sasl_client_params_t;
    309 
    310 /* features shared between client and server */
    311 /* These allow the glue code to handle client-first and server-last issues */
    312 
    313 /*
    314  * This indicates that the mechanism prefers to do client-send-first
    315  * if the protocol allows it.
    316  */
    317 #define	SASL_FEAT_WANT_CLIENT_FIRST 0x0002
    318 
    319 /*
    320  * This feature is deprecated, instead, plugins should set *serverout to
    321  * non-NULL and return SASL_OK intelligently to allow flexible use of
    322  * server-last semantics
    323  */
    324 /* #define	SASL_FEAT_WANT_SERVER_LAST 0x0004 */
    325 
    326 /*
    327  * This feature is deprecated, instead plugins should correctly set
    328  * SASL_FEAT_SERVER_FIRST as needed
    329  */
    330 /* #define	SASL_FEAT_INTERNAL_CLIENT_FIRST 0x0008 */
    331 
    332 /*
    333  * This indicates that the plugin is server-first only.
    334  * Not defining either of SASL_FEAT_SERVER_FIRST or
    335  * SASL_FEAT_WANT_CLIENT_FIRST indicates that the mechanism will take care
    336  * of the client-first situation internally.
    337  */
    338 #define	SASL_FEAT_SERVER_FIRST 0x0010
    339 
    340 /* This plugin allows proxying */
    341 #define	SASL_FEAT_ALLOWS_PROXY 0x0020
    342 
    343 /* client plug-in features */
    344 #define	SASL_FEAT_NEEDSERVERFQDN 0x0001
    345 
    346 /* a C object for a client mechanism */
    347 typedef struct sasl_client_plug {
    348 	/* mechanism name */
    349     const char *mech_name;
    350 
    351 	/* best mech additional security layer strength factor */
    352     sasl_ssf_t max_ssf;
    353 
    354 	/* best security flags, as defined in sasl_security_properties_t */
    355     unsigned security_flags;
    356 
    357 	/* features of plugin */
    358     unsigned features;
    359 
    360 	/* required prompt ids, NULL = user/pass only */
    361     const unsigned long *required_prompts;
    362 
    363 	/* global state for mechanism */
    364     void *glob_context;
    365 
    366 	/*
    367 	 * create context for mechanism, using params supplied
    368 	 *  glob_context   -- from above
    369 	 *  params	   -- params from sasl_client_new
    370 	 *  conn_context   -- context for one connection
    371 	 * returns:
    372 	 *  SASL_OK	   -- success
    373 	 *  SASL_NOMEM	   -- not enough memory
    374 	 *  SASL_WRONGMECH -- mech doesn't support security params
    375 	 */
    376     int (*mech_new)(void *glob_context,
    377 		    sasl_client_params_t *cparams,
    378 		    void **conn_context);
    379 
    380 	/*
    381 	 * perform one step of exchange.  NULL is passed for serverin on
    382 	 * first step.
    383 	 * returns:
    384 	 *  SASL_OK	   -- success
    385 	 *  SASL_INTERACT  -- user interaction needed to fill in prompts
    386 	 *  SASL_BADPROT   -- server protocol incorrect/cancelled
    387 	 *  SASL_BADSERV   -- server failed mutual auth
    388 	 */
    389     int (*mech_step)(void *conn_context,
    390 		    sasl_client_params_t *cparams,
    391 		    const char *serverin,
    392 		    unsigned serverinlen,
    393 		    sasl_interact_t **prompt_need,
    394 		    const char **clientout,
    395 		    unsigned *clientoutlen,
    396 		    sasl_out_params_t *oparams);
    397 
    398 	/* dispose of connection context from mech_new */
    399     void (*mech_dispose)(void *conn_context, const sasl_utils_t *utils);
    400 
    401 	/*
    402 	 * free all global space used by mechanism
    403 	 *  mech_dispose must be called on all mechanisms first
    404 	 */
    405     void (*mech_free)(void *glob_context, const sasl_utils_t *utils);
    406 
    407 	/*
    408 	 * perform precalculations during a network round-trip
    409 	 *  or idle period.  conn_context may be NULL
    410 	 *  returns 1 if action taken, 0 if no action taken
    411 	 */
    412     int (*idle)(void *glob_context,
    413 		void *conn_context,
    414 		sasl_client_params_t *cparams);
    415 
    416 	/* for additions which don't require a version upgrade; set to 0 */
    417     int (*spare_fptr1)();
    418     int (*spare_fptr2)();
    419 } sasl_client_plug_t;
    420 
    421 #define	SASL_CLIENT_PLUG_VERSION	4
    422 
    423 /*
    424  * plug-in entry point:
    425  *  utils       -- utility callback functions
    426  *  max_version -- highest client plug version supported
    427  * returns:
    428  *  out_version -- client plug version of result
    429  *  pluglist    -- list of mechanism plug-ins
    430  *  plugcount   -- number of mechanism plug-ins
    431  * results:
    432  *  SASL_OK       -- success
    433  *  SASL_NOMEM    -- failure
    434  *  SASL_BADVERS  -- max_version too small
    435  *  SASL_BADPARAM -- bad config string
    436  *  ...
    437  */
    438 typedef int sasl_client_plug_init_t(const sasl_utils_t *utils,
    439 				    int max_version,
    440 				    int *out_version,
    441 				    sasl_client_plug_t **pluglist,
    442 				    int *plugcount);
    443 
    444 /* add a client plug-in */
    445 LIBSASL_API int sasl_client_add_plugin(const char *plugname,
    446 				sasl_client_plug_init_t *cplugfunc);
    447 
    448 /*
    449  * Server Functions
    450  */
    451 
    452 /*
    453  * input parameters to server SASL plugin
    454  *
    455  * created / destroyed by the glue code
    456  *
    457  */
    458 typedef struct sasl_server_params {
    459     const char *service;	/* NULL = default service for user_exists */
    460 				/* and setpass */
    461     const char *appname;	/* name of calling application */
    462     const char *serverFQDN;	/* server default fully qualified domain name */
    463 				/* (e.g., gethostname) */
    464     const char *user_realm;	/* realm for user (NULL = client supplied) */
    465     const char *iplocalport;	/* server IP domain literal & port */
    466     const char *ipremoteport;	/* client IP domain literal & port */
    467 
    468     unsigned servicelen;	/* length of service */
    469     unsigned applen;		/* length of appname */
    470     unsigned slen;		/* length of serverFQDN */
    471     unsigned urlen;		/* length of user_realm */
    472     unsigned iploclen;		/* length of iplocalport */
    473     unsigned ipremlen;		/* length of ipremoteport */
    474 
    475 	/*
    476 	 * This indicates the level of logging desired.  See SASL_LOG_*
    477 	 * in sasl.h
    478 	 *
    479 	 * Plug-ins can ignore this and just pass their desired level to
    480 	 * the log callback.  This is primarily used to eliminate logging which
    481 	 * might be a performance problem (e.g., full protocol trace) and
    482 	 * to select between SASL_LOG_TRACE and SASL_LOG_PASS alternatives
    483 	 */
    484     int log_level;
    485 
    486     const sasl_utils_t *utils;	/* SASL API utility routines -- */
    487 				/* for a particular sasl_conn_t, */
    488 				/* MUST remain valid until mech_free is */
    489 				/* called */
    490 
    491     const sasl_callback_t *callbacks;	/* Callbacks from application */
    492 
    493 	/* application's security requirements */
    494     sasl_security_properties_t props;
    495     sasl_ssf_t external_ssf;	/* external SSF active */
    496 
    497 	/*
    498 	 * server plug-in calls this when it first has access to the plaintext
    499 	 *  passphrase.  This is used to transition users via setpass calls.
    500 	 *  If passlen is 0, it defaults to strlen(pass).
    501 	 *  returns 0 if no entry added, 1 if entry added
    502 	 */
    503     int (*transition)(sasl_conn_t *conn, const char *pass, unsigned passlen);
    504 
    505 	/*
    506 	 * Canonicalize a user name from on-wire to internal format
    507 	 *  added cjn 1999-09-21
    508 	 *  Must be called once user name aquired if canon_user is non-NULL.
    509 	 *  conn    connection context
    510 	 *  user    user name from wire protocol (need not be NUL terminated)
    511 	 *  ulen    length of user name from wire protocol (0 = strlen(user))
    512 	 *  flags   for SASL_CU_* flags
    513 	 *  oparams the user, authid, ulen, alen, fields are
    514 	 *	    set appropriately after canonicalization/copying and
    515 	 *	    authorization of arguments
    516 	 *
    517 	 *  responsible for setting user, ulen, authid, and alen in the oparams
    518 	 *  structure
    519 	 *
    520 	 *  default behavior is to strip leading and trailing whitespace, as
    521 	 *  well as allocating space for and copying the parameters.
    522 	 *
    523 	 * results:
    524 	 *  SASL_OK	  -- success
    525 	 *  SASL_NOMEM    -- out of memory
    526 	 *  SASL_BADPARAM -- invalid conn
    527 	 *  SASL_BADPROT  -- invalid user/authid
    528 	 */
    529     int (*canon_user)(sasl_conn_t *conn,
    530 		    const char *user, unsigned ulen,
    531 		    unsigned flags,
    532 		    sasl_out_params_t *oparams);
    533 
    534 	/*
    535 	 * auxiliary property context (see definitions in prop.h)
    536 	 *  added cjn 2000-01-30
    537 	 *
    538 	 * NOTE: these properties are the ones associated with the
    539 	 * canonicalized "user" (user to login as / authorization id), not
    540 	 * the "authid" (user whose credentials are used / authentication id)
    541 	 * Prefix the property name with a "*" if a property associated with
    542 	 * the "authid" is interesting.
    543 	 */
    544     struct propctx *propctx;
    545 
    546 	/* for additions which don't require a version upgrade; set to 0 */
    547     void *spare_ptr1;
    548     void *spare_ptr2;
    549     void *spare_ptr3;
    550     void *spare_ptr4;
    551     int (*spare_fptr1)();
    552     int (*spare_fptr2)();
    553     int spare_int1;
    554     int spare_int2;
    555     int spare_int3;
    556 
    557 	/* flags field as passed to sasl_server_new */
    558     unsigned flags;
    559 
    560 	/*
    561 	 * set to 0 initially, this allows a plugin with extended parameters
    562 	 * to work with an older framework by updating version as parameters
    563 	 * are added.
    564 	 */
    565     int param_version;
    566 } sasl_server_params_t;
    567 
    568 /* features for server plug-in */
    569 #define	SASL_FEAT_SERVICE    0x0200 /* service-specific passwords supported */
    570 #define	SASL_FEAT_GETSECRET  0x0400 /* sasl_server_{get,put}secret_t */
    571 				    /* callbacks required by plug-in */
    572 
    573 /* a C object for a server mechanism */
    574 typedef struct sasl_server_plug {
    575 	/* mechanism name */
    576     const char *mech_name;
    577 
    578 	/* best mech additional security layer strength factor */
    579     sasl_ssf_t max_ssf;
    580 
    581 	/* best security flags, as defined in sasl_security_properties_t */
    582     unsigned security_flags;
    583 
    584 	/* features of plugin */
    585     unsigned features;
    586 
    587 	/* global state for mechanism */
    588     void *glob_context;
    589 
    590 	/*
    591 	 * create a new mechanism handler
    592 	 *  glob_context  -- global context
    593 	 *  sparams	  -- server config params
    594 	 *  challenge	  -- server challenge from previous instance or NULL
    595 	 *  challen	  -- length of challenge from previous instance or 0
    596 	 * out:
    597 	 *  conn_context  -- connection context
    598 	 *  errinfo	  -- error information
    599 	 *
    600 	 * returns:
    601 	 *  SASL_OK	  -- successfully created mech instance
    602 	 *  SASL_*	  -- any other server error code
    603 	 */
    604     int (*mech_new)(void *glob_context,
    605 		    sasl_server_params_t *sparams,
    606 		    const char *challenge,
    607 		    unsigned challen,
    608 		    void **conn_context);
    609 
    610 	/*
    611 	 * perform one step in exchange
    612 	 *
    613 	 * returns:
    614 	 *  SASL_OK	  -- success, all done
    615 	 *  SASL_CONTINUE -- success, one more round trip
    616 	 *  SASL_*	  -- any other server error code
    617 	 */
    618     int (*mech_step)(void *conn_context,
    619 			sasl_server_params_t *sparams,
    620 			const char *clientin,
    621 			unsigned clientinlen,
    622 			const char **serverout,
    623 			unsigned *serveroutlen,
    624 			sasl_out_params_t *oparams);
    625 
    626 	/* dispose of a connection state */
    627     void (*mech_dispose)(void *conn_context, const sasl_utils_t *utils);
    628 
    629 	/*
    630 	 * free global state for mechanism
    631 	 *  mech_dispose must be called on all mechanisms first
    632 	 */
    633     void (*mech_free)(void *glob_context, const sasl_utils_t *utils);
    634 
    635 	/*
    636 	 * set a password (optional)
    637 	 *  glob_context  -- global context
    638 	 *  sparams	  -- service, middleware utilities, etc. props ignored
    639 	 *  user	  -- user name
    640 	 *  pass	  -- password/passphrase (NULL = disable/remove/delete)
    641 	 *  passlen	  -- length of password/passphrase
    642 	 *  oldpass	  -- old password/passphrase (NULL = transition)
    643 	 *  oldpasslen    -- length of password/passphrase
    644 	 *  flags	  -- see above
    645 	 *
    646 	 * returns:
    647 	 *  SASL_NOCHANGE -- no change was needed
    648 	 *  SASL_NOUSER   -- no entry for user
    649 	 *  SASL_NOVERIFY -- no mechanism compatible entry for user
    650 	 *  SASL_PWLOCK   -- password locked
    651 	 *  SASL_DIABLED  -- account disabled
    652 	 *  etc.
    653 	 */
    654     int (*setpass)(void *glob_context,
    655 		    sasl_server_params_t *sparams,
    656 		    const char *user,
    657 		    const char *pass, unsigned passlen,
    658 		    const char *oldpass, unsigned oldpasslen,
    659 		    unsigned flags);
    660 
    661 	/*
    662 	 * query which mechanisms are available for user
    663 	 *  glob_context  -- context
    664 	 *  sparams	  -- service, middleware utilities, etc. props ignored
    665 	 *  user	  -- NUL terminated user name
    666 	 *  maxmech	  -- max number of strings in mechlist (0 = no output)
    667 	 * output:
    668 	 *  mechlist	  -- an array of C string pointers, filled in with
    669 	 *		  mechanism names available to the user
    670 	 *
    671 	 * returns:
    672 	 *  SASL_OK	  -- success
    673 	 *  SASL_NOMEM    -- not enough memory
    674 	 *  SASL_FAIL	  -- lower level failure
    675 	 *  SASL_DISABLED -- account disabled
    676 	 *  SASL_NOUSER   -- user not found
    677 	 *  SASL_BUFOVER  -- maxmech is too small
    678 	 *  SASL_NOVERIFY -- user found, but no mechanisms available
    679 	 */
    680     int (*user_query)(void *glob_context,
    681 		    sasl_server_params_t *sparams,
    682 		    const char *user,
    683 		    int maxmech,
    684 		    const char **mechlist);
    685 
    686 	/*
    687 	 * perform precalculations during a network round-trip
    688 	 *  or idle period.  conn_context may be NULL (optional)
    689 	 *  returns 1 if action taken, 0 if no action taken
    690 	 */
    691     int (*idle)(void *glob_context,
    692 		void *conn_context,
    693 		sasl_server_params_t *sparams);
    694 
    695 	/*
    696 	 * check if mechanism is available
    697 	 * TODO - Is this correct?
    698 	 *  optional--if NULL, mechanism is available based on ENABLE=
    699 	 * in config
    700 	 *
    701 	 *  If this routine sets conn_context to a non-NULL value, then the call
    702 	 *  to mech_new will be skipped.  This should not be done unless
    703 	 *  there's a significant performance benefit, since it can cause
    704 	 *  additional memory allocation in SASL core code to keep track of
    705 	 *  contexts potentially for multiple mechanisms.
    706 	 *
    707 	 *  This is called by the first call to sasl_listmech() for a
    708 	 *  given connection context, thus for a given protocol it may
    709 	 *  never be called.  Note that if mech_avail returns SASL_NOMECH,
    710 	 *  then that mechanism is considered disabled for the remainder
    711 	 *  of the session.
    712 	 *
    713 	 *  returns SASL_OK on success,
    714 	 *	    SASL_NOMECH if mech disabled
    715 	 */
    716     int (*mech_avail)(void *glob_context,
    717 		    sasl_server_params_t *sparams,
    718 		    void **conn_context);
    719 
    720 	/* for additions which don't require a version upgrade; set to 0 */
    721     int (*spare_fptr2)();
    722 } sasl_server_plug_t;
    723 
    724 #define	SASL_SERVER_PLUG_VERSION 4
    725 
    726 /*
    727  * plug-in entry point:
    728  *  utils         -- utility callback functions
    729  *  plugname      -- name of plug-in (may be NULL)
    730  *  max_version   -- highest server plug version supported
    731  * returns:
    732  *  out_version   -- server plug-in version of result
    733  *  pluglist      -- list of mechanism plug-ins
    734  *  plugcount     -- number of mechanism plug-ins
    735  * results:
    736  *  SASL_OK       -- success
    737  *  SASL_NOMEM    -- failure
    738  *  SASL_BADVERS  -- max_version too small
    739  *  SASL_BADPARAM -- bad config string
    740  *  ...
    741  */
    742 typedef int sasl_server_plug_init_t(const sasl_utils_t *utils,
    743 				    int max_version,
    744 				    int *out_version,
    745 				    sasl_server_plug_t **pluglist,
    746 				    int *plugcount);
    747 
    748 /*
    749  * add a server plug-in
    750  */
    751 LIBSASL_API int sasl_server_add_plugin(const char *plugname,
    752 				sasl_server_plug_init_t *splugfunc);
    753 
    754 /*
    755  * user canonicalization plug-in -- added cjn 1999-09-29
    756  */
    757 
    758 typedef struct sasl_canonuser {
    759 	/* optional features of plugin (set to 0) */
    760     int features;
    761 
    762 	/* spare integer (set to 0) */
    763     int spare_int1;
    764 
    765 	/* global state for plugin */
    766     void *glob_context;
    767 
    768 	/* name of plugin */
    769     char *name;
    770 
    771 	/* free global state for plugin */
    772     void (*canon_user_free)(void *glob_context, const sasl_utils_t *utils);
    773 
    774 	/*
    775 	 * canonicalize a username
    776 	 *  glob_context    -- global context from this structure
    777 	 *  sparams	    -- server params, note user_realm&propctx elements
    778 	 *  user	    -- user to login as (may not be NUL terminated)
    779 	 *  len		    -- length of user name (0 = strlen(user))
    780 	 *  flags	    -- for SASL_CU_* flags
    781 	 *  out		    -- buffer to copy user name
    782 	 *  out_max	    -- max length of user name
    783 	 *  out_len	    -- set to length of user name
    784 	 *
    785 	 *  note that the output buffers MAY be the same as the input buffers.
    786 	 *
    787 	 * returns
    788 	 *  SASL_OK	    on success
    789 	 *  SASL_BADPROT    username contains invalid character
    790 	 */
    791     int (*canon_user_server)(void *glob_context,
    792 			    sasl_server_params_t *sparams,
    793 			    const char *user, unsigned len,
    794 			    unsigned flags,
    795 			    char *out,
    796 			    unsigned out_umax, unsigned *out_ulen);
    797 
    798     int (*canon_user_client)(void *glob_context,
    799 			    sasl_client_params_t *cparams,
    800 			    const char *user, unsigned len,
    801 			    unsigned flags,
    802 			    char *out,
    803 			    unsigned out_max, unsigned *out_len);
    804 
    805 	/* for additions which don't require a version upgrade; set to 0 */
    806     int (*spare_fptr1)();
    807     int (*spare_fptr2)();
    808     int (*spare_fptr3)();
    809 } sasl_canonuser_plug_t;
    810 
    811 #define	SASL_CANONUSER_PLUG_VERSION 5
    812 
    813 /*
    814  * default name for canonuser plug-in entry point is "sasl_canonuser_init"
    815  *  similar to sasl_server_plug_init model, except only returns one
    816  *  sasl_canonuser_plug_t structure;
    817  */
    818 typedef int sasl_canonuser_init_t(const sasl_utils_t *utils,
    819 				int max_version,
    820 				int *out_version,
    821 				sasl_canonuser_plug_t **plug,
    822 				const char *plugname);
    823 
    824 /* add a canonuser plugin */
    825 LIBSASL_API int sasl_canonuser_add_plugin(const char *plugname,
    826 				sasl_canonuser_init_t *canonuserfunc);
    827 
    828 /*
    829  * auxiliary property plug-in -- added cjn 1999-09-29
    830  */
    831 
    832 typedef struct sasl_auxprop_plug {
    833 	/* optional features of plugin (none defined yet, set to 0) */
    834     int features;
    835 
    836 	/* spare integer, must be set to 0 */
    837     int spare_int1;
    838 
    839 	/* global state for plugin */
    840     void *glob_context;
    841 
    842 	/* free global state for plugin (OPTIONAL) */
    843     void (*auxprop_free)(void *glob_context, const sasl_utils_t *utils);
    844 
    845 	/*
    846 	 * fill in fields of an auxiliary property context
    847 	 *  last element in array has id of SASL_AUX_END
    848 	 *  elements with non-0 len should be ignored.
    849 	 */
    850     void (*auxprop_lookup)(void *glob_context,
    851 			    sasl_server_params_t *sparams,
    852 			    unsigned flags,
    853 			    const char *user, unsigned ulen);
    854 
    855 	/* name of the auxprop plugin */
    856     char *name;
    857 
    858 	/* for additions which don't require a version upgrade; set to 0 */
    859     void (*spare_fptr1)();
    860 } sasl_auxprop_plug_t;
    861 
    862 /* auxprop lookup flags */
    863 #define	SASL_AUXPROP_OVERRIDE 0x01  /* if clear, ignore auxiliary properties */
    864 				    /* with non-zero len field.  If set, */
    865 				    /* override value of those properties */
    866 #define	SASL_AUXPROP_AUTHZID  0x02  /* if clear, we are looking up the */
    867 				    /* authid flags (prefixed with *), */
    868 				    /* otherwise we are looking up the */
    869 				    /* authzid flags (no prefix) */
    870 
    871 #define	SASL_AUXPROP_PLUG_VERSION 4
    872 
    873 /*
    874  * default name for auxprop plug-in entry point is "sasl_auxprop_init"
    875  *  similar to sasl_server_plug_init model, except only returns one
    876  *  sasl_auxprop_plug_t structure;
    877  */
    878 typedef int sasl_auxprop_init_t(const sasl_utils_t *utils,
    879 				int max_version,
    880 				int *out_version,
    881 				sasl_auxprop_plug_t **plug,
    882 				const char *plugname);
    883 
    884 /* add an auxiliary property plug-in */
    885 LIBSASL_API int sasl_auxprop_add_plugin(const char *plugname,
    886 					sasl_auxprop_init_t *auxpropfunc);
    887 
    888 #ifdef	__cplusplus
    889 }
    890 #endif
    891 
    892 #endif /* _SASL_SASLPLUG_H */
    893