23 #error Cyrus SASL implementation is not supported! It is included here only for the brave ones, that do know what they are doing. You need to remove this line to compile it.
25 #include <sys/types.h>
26 #include "sasl_switch_hit.h"
27 #include "auth_event.h"
41 # include <saslutil.h>
42 # include <saslplug.h>
44 # include <sasl/sasl.h>
45 # include <sasl/saslutil.h>
46 # include <sasl/saslplug.h>
79 const char *plugin_name,
84 if (strcmp(option,
"auxprop_plugin") == 0) {
85 *result =
"jabberdsx";
87 *len = strlen(
"jabberdsx");
97 static int _sx_sasl_getpath(
void *glob_context,
const char **path_dest) {
98 static char win32_path[MAX_PATH] =
"\0";
101 return SASL_BADPARAM;
106 GetModuleFileName(NULL, win32_path, MAX_PATH - 5);
107 if(!*win32_path || !(r = strrchr(win32_path,
'\\')))
109 strcpy(r + 1,
"sasl");
112 *path_dest = win32_path;
121 sasl_server_params_t *sparams,
125 const char *realm = NULL;
127 const struct propval *to_fetch, *current;
128 char *user_buf = NULL;
133 if (!sparams || !user)
140 user_buf = sparams->utils->malloc(ulen + 1);
144 memcpy(user_buf, user, ulen);
145 user_buf[ulen] =
'\0';
147 c = strchr(user_buf,
'@');
149 if (sparams->user_realm && sparams->user_realm[0])
150 realm = sparams->user_realm;
152 realm = sparams->serverFQDN;
159 to_fetch = sparams->utils->prop_get(sparams->propctx);
162 for (current = to_fetch; current->name; current++) {
163 if (strncmp(current->name, SASL_AUX_PASSWORD,
sizeof(SASL_AUX_PASSWORD)) == 0) {
165 if (current->values) {
166 if (flags & SASL_AUXPROP_OVERRIDE)
167 sparams->utils->prop_erase(sparams->propctx, current->name);
176 sparams->utils->prop_set(sparams->propctx, current->name,
177 value, strlen(value));
182 if (user_buf) sparams->utils->free(user_buf);
190 sasl_auxprop_plug_t **plug,
const char *plugname) {
192 if (!out_version || !plug)
193 return SASL_BADPARAM;
194 if (max_version < SASL_AUXPROP_PLUG_VERSION )
197 *out_version = SASL_AUXPROP_PLUG_VERSION;
207 static int _sx_sasl_checkpass(sasl_conn_t *conn,
void *ctx,
const char *user,
const char *
pass,
unsigned passlen,
struct propctx *propctx) {
241 static int _sx_sasl_canon_user(sasl_conn_t *conn,
void *ctx,
const char *user,
unsigned ulen,
unsigned flags,
const char *user_realm,
const char *out_user,
unsigned out_umax,
unsigned *out_ulen) {
243 char principal[3072];
246 char user_null_term[1024];
248 if (ulen > (
sizeof(user_null_term)-1)) {
249 _sx_debug(
ZONE,
"Got a SASL argument \"user\" that exceeds our maximum length, rejecting");
253 memcpy(user_null_term, user, ulen);
254 user_null_term[ulen] =
'\0';
256 sasl_getprop(conn, SASL_MECHNAME, (
const void **) &buf);
257 if (strncmp(buf,
"GSSAPI", 7) == 0) {
260 char adjusted_user[1024];
261 char *s = strdup(user_null_term);
263 char *c = strsep(&s,
"@");
265 strlcpy(adjusted_user, c,
sizeof(adjusted_user));
272 strlcat(adjusted_user,
"@",
sizeof(adjusted_user));
273 strlcat(adjusted_user, c,
sizeof(adjusted_user));
276 _sx_debug(
ZONE,
"Notice: unexpected format of SASL \"user\" argument: %s", user_null_term);
289 snprintf(principal,
sizeof(principal),
"%s@%s", adjusted_user, user_realm);
290 if (odkerb_get_im_handle(principal, sd->
stream->
req_to,
"JABBER:", out_buf,
291 ((out_umax >
sizeof(out_buf)) ?
sizeof(out_buf) : out_umax)) == 0) {
292 strlcpy(out_user, out_buf, out_umax);
293 *out_ulen = strlen(out_user);
294 _sx_debug(
ZONE,
"Got IM handle: %s for user %s, realm %s", out_buf, user_null_term, user_realm);
299 else if (strncmp(buf,
"ANONYMOUS", 10) == 0) {
301 strncpy(out_user, buf, out_umax);
302 out_user[out_umax]=
'\0';
303 *out_ulen=strlen(out_user);
305 memcpy(out_user,user,ulen);
315 static int _sx_sasl_proxy_policy(sasl_conn_t *conn,
void *ctx,
const char *requested_user,
int rlen,
const char *auth_identity,
int alen,
const char *
realm,
int urlen,
struct propctx *propctx) {
322 sasl_getprop(conn, SASL_MECHNAME, (
const void **) &buf);
323 if (strncmp(buf,
"ANONYMOUS", 10) == 0) {
329 if (!requested_user || !auth_identity || rlen == 0 || alen==0) {
330 sasl_seterror(conn, 0,
331 "Bad identities provided");
342 buf = malloc(urlen + 1);
343 strncpy(buf, realm?realm:
"", urlen);
357 buf = malloc(alen + 1);
358 strncpy(buf, auth_identity, alen);
360 c = strrchr(buf,
'@');
361 if (c && strcmp(c+1, creds.
realm) == 0)
373 buf = malloc(len + 1);
374 strncpy(buf, requested_user, rlen);
376 c = strrchr(buf,
'@');
377 if (c && strcmp(c + 1, creds.
realm) == 0)
392 free((
void *)creds.
realm);
397 sasl_seterror(conn, 0,
"Requested identity not permitted for authorization identity");
405 int *x, len, pos, reslen, maxbuf;
413 sasl_getprop(sasl, SASL_SSF, (
const void **) &x);
420 sasl_getprop(sasl, SASL_MAXOUTBUF, (
const void **) &x);
425 result = NULL; reslen = 0;
426 while(pos < buf->len) {
427 if((buf->
len - pos) < maxbuf)
428 maxbuf = buf->
len - pos;
430 sasl_ret = sasl_encode(sasl, &buf->
data[pos], maxbuf, (
const char **) &out, &len);
431 if (sasl_ret != SASL_OK) {
438 result = (
char *) realloc(result,
sizeof(
char) * (reslen + len));
439 memcpy(&result[reslen], out, len);
462 sasl_getprop(sasl, SASL_SSF, (
const void **) &x);
469 if (sasl_decode(sasl, buf->
data, buf->
len, (
const char **) &out, &len)
492 char *username = NULL;
498 sasl_getprop(sasl, SASL_MECHNAME, (
const void **) &buf);
500 static int first_time = 1;
503 sasl_switch_hit_register_apple_digest_md5();
507 method = (
char *) malloc(
sizeof(
char) * (strlen(buf) + 17));
508 sprintf(method,
"SASL/%s", buf);
512 sasl_getprop(sasl, SASL_SSF, (
const void **) &ssf);
518 sasl_getprop(sasl, SASL_USERNAME, (
const void **) &buf);
520 username = (
char *) malloc(
sizeof(
char) * (strlen(buf)+1));
521 strncpy(username, buf, strlen(buf)+1);
531 len = strlen(username);
533 len+=strlen(s->
req_to) + 2;
534 authzid = malloc(len + 1);
535 strcpy(authzid, username);
538 sasl_getprop(sasl, SASL_DEFUSERREALM, (
const void **) &buf);
540 realm = (
char *) malloc(
sizeof(
char) * (strlen(buf)+1));
541 strncpy(realm, buf, strlen(buf)+1);
544 c = strrchr(authzid,
'@');
545 if (c && realm && strcmp(c+1, realm) == 0)
547 if (s->
req_to && strchr(authzid,
'@') == 0) {
548 strcat(authzid,
"@");
549 strcat(authzid, s->
req_to);
561 if (username != NULL)
573 char *
realm = NULL, *ext_id, *mech;
574 sasl_security_properties_t sec_props;
582 _sx_debug(
ZONE,
"application did not request sasl offer, not offering for this conn");
596 sd->callbacks = calloc(
sizeof(sasl_callback_t),4);
598 sd->callbacks[0].id = SASL_CB_PROXY_POLICY;
600 sd->callbacks[0].context = sd;
602 sd->callbacks[1].id = SASL_CB_CANON_USER;
604 sd->callbacks[1].context = sd;
606 sd->callbacks[2].id = SASL_CB_SERVER_USERDB_CHECKPASS;
608 sd->callbacks[2].context = sd;
610 sd->callbacks[3].id = SASL_CB_LIST_END;
613 ret = sasl_server_new(ctx->
appname, NULL,
615 NULL, NULL, sd->callbacks,
618 _sx_debug(
ZONE,
"sasl_server_new failed (%s), not offering sasl for this conn", sasl_errstring(ret, NULL, NULL));
627 for(i = 0; i < s->env->nplugins; i++)
628 if(s->env->plugins[i]->magic ==
SX_SSL_MAGIC && s->plugin_data[s->env->plugins[i]->index] != NULL)
629 ext_id = ((_sx_ssl_conn_t) s->plugin_data[s->env->plugins[i]->index])->external_id;
633 ret = sasl_setprop(sasl, SASL_AUTH_EXTERNAL, ext_id);
635 ret = sasl_setprop(sasl, SASL_SSF_EXTERNAL, &s->ssf);
643 sec_props.max_ssf = 0;
646 ret = sasl_setprop(sasl, SASL_SEC_PROPS, &sec_props);
649 _sx_debug(
ZONE,
"sasl_setprop failed (%s), not offering sasl for this conn", sasl_errstring(ret, NULL, NULL));
658 sd->sasl_server_started = 0;
662 s->plugin_data[p->
index] = (
void *) sd;
673 if (sasl_getprop(sasl, SASL_MECHNAME, (
void *) &mech) == SASL_NOTDONE) {
674 _sx_debug(
ZONE,
"not auth'd, not advancing to auth'd state yet");
685 char *mechs, *mech, *c;
690 if((ret = sasl_getprop(sd->
sasl, SASL_MECHNAME, (
void *) &mech)) != SASL_NOTDONE) {
691 _sx_debug(
ZONE,
"already auth'd, not offering sasl mechanisms");
696 _sx_debug(
ZONE,
"application didn't ask us to offer sasl, so we won't");
702 _sx_debug(
ZONE,
"ssl not established yet but the app requires it, not offering mechanisms");
709 ret = sasl_listmech(sd->
sasl, NULL,
"",
"|",
"", (
const char **) &mechs, NULL, &nmechs);
711 _sx_debug(
ZONE,
"sasl_listmech failed (%s), not offering sasl for this conn", sasl_errstring(ret, NULL, NULL));
717 _sx_debug(
ZONE,
"sasl_listmech returned no mechanisms, not offering sasl for this conn");
724 while(mech != NULL) {
725 c = strchr(mech,
'|');
821 *out = (
char *) malloc(
sizeof(
char) * (2 * inlen));
822 sasl_decode64(in,inlen,*out,2*inlen,outlen);
827 *out = (
char *) malloc(
sizeof(
char) * (2 * inlen));
828 sasl_encode64(in,inlen,*out,2*inlen,outlen);
846 char *buf = NULL, *out = NULL, *user = NULL;
847 int buflen, outlen, ret;
853 _sx_debug(
ZONE,
"auth request from client (mechanism=%s)", mech);
855 _sx_debug(
ZONE,
"response from client (response: %.*s)", buflen, buf);
860 ret = sasl_server_start(sd->
sasl, mech, buf, buflen, (
const char **) &out, &outlen);
865 _sx_debug(
ZONE,
"response send before auth request enabling mechanism (decoded: %.*s)", buflen, buf);
867 if(buf != NULL) free(buf);
871 ret = sasl_server_step(sd->
sasl, buf, buflen, (
const char **) &out, &outlen);
874 if(buf != NULL) free(buf);
889 sasl_getprop(sd->
sasl, SASL_USERNAME, (
const void **) &user);
901 if(ret == SASL_CONTINUE) {
902 _sx_debug(
ZONE,
"sasl handshake in progress (challenge: %.*s)", outlen, out);
915 buf = (
char *) sasl_errdetail(sd->
sasl);
917 buf =
"[no error message available]";
923 sasl_getprop(sd->
sasl, SASL_USERNAME, (
const void **) &user);
938 int buflen, outlen, ret;
947 ret = sasl_client_step(sd->
sasl, buf, buflen, NULL, (
const char **) &out, &outlen);
948 if(buf != NULL) free(buf);
951 if(ret == SASL_OK || ret == SASL_CONTINUE) {
952 _sx_debug(
ZONE,
"sasl handshake in progress (response: %.*s)", outlen, out);
959 if(buf != NULL) free(buf);
965 err_buf = sasl_errdetail(sd->
sasl);
967 err_buf =
"[no error message available]";
981 char *ns = NULL, *to = NULL, *from = NULL, *version = NULL;
997 _sx_debug(
ZONE,
"they tried to do sasl, but we never offered it, ignoring");
1004 _sx_debug(
ZONE,
"they tried to do sasl, but they have to do starttls first, ignoring");
1013 if((attr =
nad_find_attr(nad, 0, -1,
"mechanism", NULL)) < 0) {
1052 _sx_debug(
ZONE,
"got sasl client packets, but they never started sasl, ignoring");
1074 if(s->
ns != NULL) ns = strdup(s->
ns);
1086 _sx_debug(
ZONE,
"restarting stream with sasl layer established");
1092 if(ns != NULL) free(ns);
1093 if(to != NULL) free(to);
1094 if(from != NULL) free(from);
1095 if(version != NULL) free(version);
1130 if(sd->
sasl != NULL) sasl_dispose(&sd->
sasl);
1131 if(sd->
user != NULL) free(sd->
user);
1162 appname = va_arg(args,
const char *);
1163 if(appname == NULL) {
1169 cbarg = va_arg(args,
void *);
1183 ctx->
appname = strdup(appname);
1189 _sx_auxprop_plugin.glob_context = (
void *) ctx;
1210 LDAP *ldap_con = NULL;
1211 ldap_initialize(&ldap_con,
"ldap://127.0.0.1");
1214 if(ret != SASL_OK) {
1215 _sx_debug(
ZONE,
"sasl_server_init_alt() failed (%s), disabling", sasl_errstring(ret, NULL, NULL));
1221 _sx_debug(
ZONE,
"sasl context initialised; appname=%s", appname);
1247 *len = strlen(*result);
1259 if(conn == NULL || psecret == NULL ||
id != SASL_CB_PASS)
1260 return SASL_BADPARAM;
1271 char *buf, *out, *ext_id;
1272 int i, ret, buflen, outlen, ns;
1273 sasl_security_properties_t sec_props;
1276 static sasl_callback_t win32_callbacks[2] = {
1277 {SASL_CB_GETPATH, &_sx_sasl_getpath, NULL},
1278 {SASL_CB_LIST_END, NULL, NULL}};
1281 assert((
int) (p != NULL));
1282 assert((
int) (s != NULL));
1283 assert((
int) (appname != NULL));
1284 assert((
int) (mech != NULL));
1287 _sx_debug(
ZONE,
"need client in stream state for sasl auth");
1293 ret = sasl_client_init(win32_callbacks);
1295 ret = sasl_client_init(NULL);
1297 if(ret != SASL_OK) {
1298 _sx_debug(
ZONE,
"sasl_client_init() failed (%s), not authing", sasl_errstring(ret, NULL, NULL));
1305 sd->user = strdup(user);
1308 sd->psecret = (sasl_secret_t *) malloc(
sizeof(sasl_secret_t) + strlen(
pass) + 1);
1309 strcpy(sd->psecret->data,
pass);
1310 sd->psecret->len = strlen(
pass);
1313 sd->callbacks=calloc(
sizeof(sasl_callback_t),4);
1316 sd->callbacks[0].id = SASL_CB_AUTHNAME;
1318 sd->callbacks[0].context = (
void *) sd;
1321 sd->callbacks[1].id = SASL_CB_PASS;
1323 sd->callbacks[1].context = (
void *) sd;
1326 sd->callbacks[2].id = SASL_CB_USER;
1328 sd->callbacks[2].context = (
void *) sd;
1331 sd->callbacks[3].id = SASL_CB_LIST_END;
1332 sd->callbacks[3].proc = NULL;
1333 sd->callbacks[3].context = NULL;
1336 ret = sasl_client_new(appname, (s->req_to != NULL) ? s->req_to :
"", NULL, NULL, sd->callbacks, 0, &sd->sasl);
1337 if(ret != SASL_OK) {
1338 _sx_debug(
ZONE,
"sasl_client_new failed, (%s), not authing", sasl_errstring(ret, NULL, NULL));
1340 if (sd->user != NULL) free(sd->user);
1341 if (sd->psecret != NULL) free(sd->psecret);
1342 free(sd->callbacks);
1351 for(i = 0; i < s->env->nplugins; i++)
1352 if(s->env->plugins[i]->magic ==
SX_SSL_MAGIC && s->plugin_data[s->env->plugins[i]->index] != NULL)
1353 ext_id = ((_sx_ssl_conn_t) s->plugin_data[s->env->plugins[i]->index])->external_id;
1364 if(ext_id != NULL) {
1365 ret = sasl_setprop(sd->sasl, SASL_AUTH_EXTERNAL, ext_id);
1366 if(ret == SASL_OK) ret = sasl_setprop(sd->sasl, SASL_SSF_EXTERNAL, &s->ssf);
1371 sec_props = ctx->sec_props;
1374 sec_props.max_ssf = 0;
1376 ret = sasl_setprop(sd->sasl, SASL_SEC_PROPS, &sec_props);
1377 if(ret != SASL_OK) {
1378 _sx_debug(
ZONE,
"sasl_setprop failed (%s), not authing", sasl_errstring(ret, NULL, NULL));
1380 sasl_dispose(&sd->sasl);
1382 if (sd->user != NULL) free(sd->user);
1383 if (sd->psecret != NULL) free(sd->psecret);
1384 free(sd->callbacks);
1391 ret = sasl_client_start(sd->sasl, mech, NULL, (
const char **) &out, &outlen, NULL);
1392 if(ret != SASL_OK && ret != SASL_CONTINUE) {
1393 _sx_debug(
ZONE,
"sasl_client_start failed (%s), not authing", sasl_errstring(ret, NULL, NULL));
1395 sasl_dispose(&sd->sasl);
1397 if (sd->user != NULL) free(sd->user);
1398 if (sd->psecret != NULL) free(sd->psecret);
1399 free(sd->callbacks);
1406 s->plugin_data[p->index] = (
void *) sd;
1409 _sx_debug(
ZONE,
"sending auth request to server, mech '%s': %.*s", mech, outlen, out);
sasl_callback_t * saslcallbacks
static int _sx_sasl_wio(sx_t s, sx_plugin_t p, sx_buf_t buf)
static void _sx_sasl_unload(sx_plugin_t p)
nad_t nad_new(void)
create a new nad
int nad_append_attr(nad_t nad, int ns, const char *name, const char *val)
attach new attr to the last elem
#define sx_sasl_cb_CHECK_MECH
struct _sx_sasl_data_st * _sx_sasl_data_t
#define _sx_event(s, e, data)
#define NAD_CDATA_L(N, E)
#define sx_nad_write(s, nad)
static int _sx_sasl_canon_user(sasl_conn_t *conn, void *ctx, const char *user, unsigned ulen, unsigned flags, const char *user_realm, const char *out_user, unsigned out_umax, unsigned *out_ulen)
static void _sx_sasl_stream(sx_t s, sx_plugin_t p)
make the stream authenticated second time round
static void _sx_sasl_free(sx_t, sx_plugin_t)
cleanup
static void _sx_sasl_client_process(sx_t s, sx_plugin_t p, const char *mech, const char *in, int inlen)
process handshake packets from the client
void nad_append_cdata(nad_t nad, const char *cdata, int len, int depth)
append new cdata to the last elem
static sasl_auxprop_plug_t _sx_auxprop_plugin
error info for event_ERROR
#define _sasl_err_ABORTED
static int _sx_sasl_cb_get_simple(void *ctx, int id, const char **result, unsigned *len)
int nad_add_namespace(nad_t nad, const char *uri, const char *prefix)
bring a new namespace into scope
#define _sasl_err_MALFORMED_REQUEST
void sx_server_init(sx_t s, unsigned int flags)
static int _sx_sasl_cb_get_secret(sasl_conn_t *conn, void *ctx, int id, sasl_secret_t **psecret)
auth_event_data_t auth_event_data
void _sx_chain_io_plugin(sx_t s, sx_plugin_t p)
void(* free)(sx_t s, sx_plugin_t p)
int nad_append_elem(nad_t nad, int ns, const char *name, int depth)
create a new elem on the list
void nad_free(nad_t nad)
free that nad
void(* features)(sx_t s, sx_plugin_t p, nad_t nad)
sasl_security_properties_t sec_props
#define sx_sasl_cb_CHECK_AUTHZID
sasl_callback_t * callbacks
holds the state for a single stream
#define SX_SSL_MAGIC
magic numbers, so plugins can find each other
void sx_client_init(sx_t s, unsigned int flags, const char *ns, const char *to, const char *from, const char *version)
#define NAD_ENAME_L(N, E)
static int _sx_sasl_getopt(void *glob_context, const char *plugin_name, const char *option, const char **result, unsigned *len)
#define NAD_NURI_L(N, NS)
static void _sx_sasl_features(sx_t s, sx_plugin_t p, nad_t nad)
static nad_t _sx_sasl_success(sx_t s)
utility: generate a success nad
static nad_t _sx_sasl_challenge(sx_t s, const char *data, int dlen)
utility: generate a challenge nad
static nad_t _sx_sasl_response(sx_t s, const char *data, int dlen)
utility: generate a response nad
static int _sx_sasl_process(sx_t s, sx_plugin_t p, nad_t nad)
main nad processor
static nad_t _sx_sasl_abort(sx_t s)
utility: generate an abort nad
struct _sx_plugin_st * sx_plugin_t
#define SX_SSL_STARTTLS_REQUIRE
struct _sx_sasl_st * _sx_sasl_t
our context
struct _sx_buf_st * sx_buf_t
utility: buffer
static int _sx_sasl_proxy_policy(sasl_conn_t *conn, void *ctx, const char *requested_user, int rlen, const char *auth_identity, int alen, const char *realm, int urlen, struct propctx *propctx)
JABBERD2_API int sx_sasl_init(sx_env_t env, sx_plugin_t p, va_list args)
init function
void _sx_reset(sx_t s)
utility; reset stream state
static int _sx_sasl_rio(sx_t s, sx_plugin_t p, sx_buf_t buf)
JABBERD2_API int sx_sasl_auth(sx_plugin_t p, sx_t s, const char *appname, const char *mech, const char *user, const char *pass)
trigger for client auth
#define sx_sasl_cb_GET_REALM
int(* rio)(sx_t s, sx_plugin_t p, sx_buf_t buf)
int(* sx_sasl_callback_t)(int cb, void *arg, void **res, sx_t s, void *cbarg)
the callback function
static void _sx_sasl_decode(char *in, int inlen, char **out, int *outlen)
utility: decode incoming handshake data
void(* stream)(sx_t s, sx_plugin_t p)
void(* unload)(sx_plugin_t p)
static void _sx_sasl_notify_success(sx_t s, void *arg)
auth done, restart the stream
#define _sasl_err_MECH_TOO_WEAK
static int sx_auxprop_init(const sasl_utils_t *utils, int max_version, int *out_version, sasl_auxprop_plug_t **plug, const char *plugname)
static int _sx_sasl_checkpass(sasl_conn_t *conn, void *ctx, const char *user, const char *pass, unsigned passlen, struct propctx *propctx)
int(* wio)(sx_t s, sx_plugin_t p, sx_buf_t buf)
#define _sx_gen_error(e, c, g, s)
helper macro to populate this struct
void _sx_buffer_set(sx_buf_t buf, char *newdata, int newlength, char *newheap)
utility: reset a sx_buf_t's contents.
#define sx_sasl_cb_GEN_AUTHZID
int nad_find_attr(nad_t nad, int elem, int ns, const char *name, const char *val)
get a matching attr on this elem, both name and optional val
static void _sx_auxprop_lookup(void *glob_context, sasl_server_params_t *sparams, unsigned flags, const char *user, unsigned ulen)
void _sx_sasl_open(sx_t s, sasl_conn_t *sasl, sx_plugin_t p)
move the stream to the auth state
static void _sx_sasl_server_process(sx_t s, sx_plugin_t p, const char *in, int inlen)
process handshake packets from the server
int _sx_nad_write(sx_t s, nad_t nad, int elem)
send a new nad out
static void _sx_sasl_encode(char *in, int inlen, char **out, int *outlen)
utility: encode outgoing handshake data
void sx_auth(sx_t s, const char *auth_method, const char *auth_id)
force advance into auth state
int(* process)(sx_t s, sx_plugin_t p, nad_t nad)
#define sx_sasl_cb_CHECK_PASS
#define sx_sasl_cb_GET_PASS
static nad_t _sx_sasl_failure(sx_t s, const char *err)
utility: generate a failure nad
#define _sasl_err_INVALID_MECHANISM