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