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