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