+
+int auth_sasl_ex(const char *method,
+ const char *initresponse,
+ const char *externalauth,
+ char *(*callback_func)(const char *, void *),
+ void *callback_arg,
+ char **authtype_ptr, /* Returned - AUTHTYPE */
+ char **authdata_ptr)
+{
+ char *uid;
+ int n;
+
+ if (strcmp(method, "EXTERNAL"))
+ return auth_sasl(method, initresponse, callback_func,
+ callback_arg,
+ authtype_ptr,
+ authdata_ptr);
+
+ if (!externalauth || !*externalauth)
+ return AUTHSASL_ERROR;
+
+ if (initresponse && !*initresponse)
+ initresponse=NULL;
+
+ if (initresponse && strcmp(initresponse, externalauth))
+ return AUTHSASL_ERROR;
+
+ if (!initresponse)
+ {
+ uid=callback_func("", callback_arg);
+
+ if (*uid == '*')
+ {
+ free(uid);
+ return (AUTHSASL_ABORTED);
+ }
+
+ n=authsasl_frombase64(uid);
+
+ if (n < 0)
+ {
+ free(uid);
+ return AUTHSASL_ABORTED;
+ }
+ uid[n]=0;
+
+ if (uid[0])
+ {
+ free(uid);
+ return AUTHSASL_ABORTED;
+ }
+ free(uid);
+ }
+
+ if ((*authtype_ptr=strdup("EXTERNAL")) == NULL)
+ return AUTHSASL_ABORTED;
+
+ if ((*authdata_ptr=strdup(externalauth)) == NULL)
+ {
+ free(authtype_ptr);
+ return AUTHSASL_ABORTED;
+ }
+
+ return 0;
+}
+
+char *auth_sasl_extract_userid(const char *authtype,
+ const char *authdata)
+{
+ struct cram_callback_info cci;
+ char *p;
+ char *t;
+ char *d;
+
+ if (strcmp(authtype, AUTHTYPE_LOGIN) == 0)
+ {
+ char *q;
+
+ p=strdup(authdata);
+
+ if (!p)
+ return NULL;
+
+ q=strchr(p, '\n');
+ if (q) *q=0;
+ return p;
+ }
+
+ if ((t=strdup(authtype)) == NULL)
+ return NULL;
+
+ if ((d=strdup(authdata)) == NULL)
+ {
+ free(t);
+ return NULL;
+ }
+
+ if (auth_get_cram_silent(t, d, &cci))
+ {
+ free(d);
+ free(t);
+ return (NULL);
+ }
+
+ p=strdup(cci.user);
+ free(d);
+ free(t);
+ return p;
+}