_sasl_find_verifyfile_callback(const sasl_callback_t *callbacks)
{
static const sasl_callback_t default_verifyfile_cb = {
-diff -durN cyrus-sasl-2.1.10.orig/lib/common.c.orig cyrus-sasl-2.1.10/lib/common.c.orig
---- cyrus-sasl-2.1.10.orig/lib/common.c.orig Thu Jan 1 01:00:00 1970
-+++ cyrus-sasl-2.1.10/lib/common.c.orig Thu Dec 5 15:00:38 2002
-@@ -0,0 +1,1921 @@
-+/* common.c - Functions that are common to server and clinet
-+ * Rob Siemborski
-+ * Tim Martin
-+ * $Id$
-+ */
-+/*
-+ * Copyright (c) 2001 Carnegie Mellon University. All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * 1. Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ *
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in
-+ * the documentation and/or other materials provided with the
-+ * distribution.
-+ *
-+ * 3. The name "Carnegie Mellon University" must not be used to
-+ * endorse or promote products derived from this software without
-+ * prior written permission. For permission or any other legal
-+ * details, please contact
-+ * Office of Technology Transfer
-+ * Carnegie Mellon University
-+ * 5000 Forbes Avenue
-+ * Pittsburgh, PA 15213-3890
-+ * (412) 268-4387, fax: (412) 268-7395
-+ * tech-transfer@andrew.cmu.edu
-+ *
-+ * 4. Redistributions of any form whatsoever must retain the following
-+ * acknowledgment:
-+ * "This product includes software developed by Computing Services
-+ * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
-+ *
-+ * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
-+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-+ * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
-+ * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
-+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
-+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-+ */
-+
-+#include <config.h>
-+#include <stdio.h>
-+#include <string.h>
-+#include <stdlib.h>
-+#include <limits.h>
-+#ifdef HAVE_SYSLOG
-+#include <syslog.h>
-+#endif
-+#include <stdarg.h>
-+#include <ctype.h>
-+
-+#include <sasl.h>
-+#include <saslutil.h>
-+#include <saslplug.h>
-+#include "saslint.h"
-+
-+#ifdef WIN32
-+/* need to handle the fact that errno has been defined as a function
-+ in a dll, not an extern int */
-+# ifdef errno
-+# undef errno
-+# endif /* errno */
-+#endif /* WIN32 */
-+#ifdef HAVE_UNISTD_H
-+#include <unistd.h>
-+#endif
-+
-+static int _sasl_getpath(void *context __attribute__((unused)), const char **path);
-+
-+static const char build_ident[] = "$Build: libsasl " PACKAGE "-" VERSION " $";
-+
-+/* It turns out to be conveinent to have a shared sasl_utils_t */
-+LIBSASL_VAR const sasl_utils_t *sasl_global_utils = NULL;
-+
-+/* Should be a null-terminated array that lists the available mechanisms */
-+static char **global_mech_list = NULL;
-+
-+void *free_mutex = NULL;
-+
-+void (*_sasl_client_cleanup_hook)(void) = NULL;
-+void (*_sasl_server_cleanup_hook)(void) = NULL;
-+int (*_sasl_client_idle_hook)(sasl_conn_t *conn) = NULL;
-+int (*_sasl_server_idle_hook)(sasl_conn_t *conn) = NULL;
-+
-+sasl_allocation_utils_t _sasl_allocation_utils={
-+ (sasl_malloc_t *) &malloc,
-+ (sasl_calloc_t *) &calloc,
-+ (sasl_realloc_t *) &realloc,
-+ (sasl_free_t *) &free
-+};
-+
-+/* Intenal mutex functions do as little as possible (no thread protection) */
-+static void *sasl_mutex_alloc(void)
-+{
-+ return (void *)0x1;
-+}
-+
-+static int sasl_mutex_lock(void *mutex __attribute__((unused)))
-+{
-+ return SASL_OK;
-+}
-+
-+static int sasl_mutex_unlock(void *mutex __attribute__((unused)))
-+{
-+ return SASL_OK;
-+}
-+
-+static void sasl_mutex_free(void *mutex __attribute__((unused)))
-+{
-+ return;
-+}
-+
-+sasl_mutex_utils_t _sasl_mutex_utils={
-+ &sasl_mutex_alloc,
-+ &sasl_mutex_lock,
-+ &sasl_mutex_unlock,
-+ &sasl_mutex_free
-+};
-+
-+void sasl_set_mutex(sasl_mutex_alloc_t *n, sasl_mutex_lock_t *l,
-+ sasl_mutex_unlock_t *u, sasl_mutex_free_t *d)
-+{
-+ _sasl_mutex_utils.alloc=n;
-+ _sasl_mutex_utils.lock=l;
-+ _sasl_mutex_utils.unlock=u;
-+ _sasl_mutex_utils.free=d;
-+}
-+
-+/* copy a string to malloced memory */
-+int _sasl_strdup(const char *in, char **out, size_t *outlen)
-+{
-+ size_t len = strlen(in);
-+ if (outlen) *outlen = len;
-+ *out=sasl_ALLOC(len + 1);
-+ if (! *out) return SASL_NOMEM;
-+ strcpy((char *) *out, in);
-+ return SASL_OK;
-+}
-+
-+/* adds a string to the buffer; reallocing if need be */
-+int _sasl_add_string(char **out, size_t *alloclen,
-+ size_t *outlen, const char *add)
-+{
-+ size_t addlen;
-+
-+ if (add==NULL) add = "(null)";
-+
-+ addlen=strlen(add); /* only compute once */
-+ if (_buf_alloc(out, alloclen, (*outlen)+addlen)!=SASL_OK)
-+ return SASL_NOMEM;
-+
-+ strncpy(*out + *outlen, add, addlen);
-+ *outlen += addlen;
-+
-+ return SASL_OK;
-+}
-+
-+/* return the version of the cyrus sasl library as compiled,
-+ * using 32 bits: high byte is major version, second byte is minor version,
-+ * low 16 bits are step # */
-+void sasl_version(const char **implementation, int *version)
-+{
-+ const char *implementation_string = "Cyrus SASL";
-+ if(implementation) *implementation = implementation_string;
-+ if(version) *version = (SASL_VERSION_MAJOR << 24) |
-+ (SASL_VERSION_MINOR << 16) |
-+ (SASL_VERSION_STEP);
-+}
-+
-+/* security-encode a regular string. Mostly a wrapper for sasl_encodev */
-+/* output is only valid until next call to sasl_encode or sasl_encodev */
-+int sasl_encode(sasl_conn_t *conn, const char *input,
-+ unsigned inputlen,
-+ const char **output, unsigned *outputlen)
-+{
-+ int result;
-+ struct iovec tmp;
-+
-+ if(!conn) return SASL_BADPARAM;
-+ if(!input || !inputlen || !output || !outputlen)
-+ PARAMERROR(conn);
-+
-+ /* maxoutbuf checking is done in sasl_encodev */
-+
-+ /* Note: We are casting a const pointer here, but it's okay
-+ * because we believe people downstream of us are well-behaved, and the
-+ * alternative is an absolute mess, performance-wise. */
-+ tmp.iov_base = (void *)input;
-+ tmp.iov_len = inputlen;
-+
-+ result = sasl_encodev(conn, &tmp, 1, output, outputlen);
-+
-+ RETURN(conn, result);
-+}
-+
-+/* security-encode an iovec */
-+/* output is only valid until next call to sasl_encode or sasl_encodev */
-+int sasl_encodev(sasl_conn_t *conn,
-+ const struct iovec *invec, unsigned numiov,
-+ const char **output, unsigned *outputlen)
-+{
-+ int result;
-+ unsigned i;
-+ size_t total_size = 0;
-+
-+ if (!conn) return SASL_BADPARAM;
-+ if (! invec || ! output || ! outputlen || numiov < 1)
-+ PARAMERROR(conn);
-+
-+ if(!conn->props.maxbufsize) {
-+ sasl_seterror(conn, 0,
-+ "called sasl_encode[v] with application that does not support security layers");
-+ return SASL_TOOWEAK;
-+ }
-+
-+ /* This might be better to check on a per-plugin basis, but I think
-+ * it's cleaner and more effective here. It also encourages plugins
-+ * to be honest about what they accept */
-+
-+ for(i=0; i<numiov;i++) {
-+ total_size += invec[i].iov_len;
-+ }
-+ if(total_size > conn->oparams.maxoutbuf)
-+ PARAMERROR(conn);
-+
-+ if(conn->oparams.encode == NULL) {
-+ result = _iovec_to_buf(invec, numiov, &conn->encode_buf);
-+ if(result != SASL_OK) INTERROR(conn, result);
-+
-+ *output = conn->encode_buf->data;
-+ *outputlen = conn->encode_buf->curlen;
-+
-+ } else {
-+ result = conn->oparams.encode(conn->context, invec, numiov,
-+ output, outputlen);
-+ }
-+
-+ RETURN(conn, result);
-+}
-+
-+/* output is only valid until next call to sasl_decode */
-+int sasl_decode(sasl_conn_t *conn,
-+ const char *input, unsigned inputlen,
-+ const char **output, unsigned *outputlen)
-+{
-+ int result;
-+
-+ if(!conn) return SASL_BADPARAM;
-+ if(!input || !output || !outputlen)
-+ PARAMERROR(conn);
-+
-+ if(!conn->props.maxbufsize) {
-+ sasl_seterror(conn, 0,
-+ "called sasl_decode with application that does not support security layers");
-+ RETURN(conn, SASL_TOOWEAK);
-+ }
-+
-+ if(conn->oparams.decode == NULL)
-+ {
-+ /* Since we know how long the output is maximally, we can
-+ * just allocate it to begin with, and never need another
-+ * allocation! */
-+
-+ /* However, if they pass us more than they actually can take,
-+ * we cannot help them... */
-+ if(inputlen > conn->props.maxbufsize) {
-+ sasl_seterror(conn, 0,
-+ "input too large for default sasl_decode");
-+ RETURN(conn,SASL_BUFOVER);
-+ }
-+
-+ if(!conn->decode_buf)
-+ conn->decode_buf = sasl_ALLOC(conn->props.maxbufsize + 1);
-+ if(!conn->decode_buf)
-+ MEMERROR(conn);
-+
-+ memcpy(conn->decode_buf, input, inputlen);
-+ conn->decode_buf[inputlen] = '\0';
-+ *output = conn->decode_buf;
-+ *outputlen = inputlen;
-+
-+ return SASL_OK;
-+ } else {
-+ result = conn->oparams.decode(conn->context, input, inputlen,
-+ output, outputlen);
-+
-+ /* NULL an empty buffer (for misbehaved applications) */
-+ if (*outputlen == 0) *output = NULL;
-+
-+ RETURN(conn, result);
-+ }
-+
-+ INTERROR(conn, SASL_FAIL);
-+}
-+
-+
-+void
-+sasl_set_alloc(sasl_malloc_t *m,
-+ sasl_calloc_t *c,
-+ sasl_realloc_t *r,
-+ sasl_free_t *f)
-+{
-+ _sasl_allocation_utils.malloc=m;
-+ _sasl_allocation_utils.calloc=c;
-+ _sasl_allocation_utils.realloc=r;
-+ _sasl_allocation_utils.free=f;
-+}
-+
-+void sasl_done(void)
-+{
-+ if (_sasl_server_cleanup_hook)
-+ _sasl_server_cleanup_hook();
-+
-+ if (_sasl_client_cleanup_hook)
-+ _sasl_client_cleanup_hook();
-+
-+ _sasl_canonuser_free();
-+ _sasl_done_with_plugins();
-+
-+ sasl_MUTEX_FREE(free_mutex);
-+ free_mutex = NULL;
-+
-+ _sasl_free_utils(&sasl_global_utils);
-+
-+ sasl_FREE(global_mech_list);
-+ global_mech_list = NULL;
-+
-+ /* in case of another init/done */
-+ _sasl_server_cleanup_hook = NULL;
-+ _sasl_client_cleanup_hook = NULL;
-+
-+ _sasl_client_idle_hook = NULL;
-+ _sasl_server_idle_hook = NULL;
-+}
-+
-+/* fills in the base sasl_conn_t info */
-+int _sasl_conn_init(sasl_conn_t *conn,
-+ const char *service,
-+ unsigned int flags,
-+ enum Sasl_conn_type type,
-+ int (*idle_hook)(sasl_conn_t *conn),
-+ const char *serverFQDN,
-+ const char *iplocalport,
-+ const char *ipremoteport,
-+ const sasl_callback_t *callbacks,
-+ const sasl_global_callbacks_t *global_callbacks) {
-+ int result = SASL_OK;
-+
-+ conn->type = type;
-+
-+ result = _sasl_strdup(service, &conn->service, NULL);
-+ if (result != SASL_OK)
-+ MEMERROR(conn);
-+
-+ memset(&conn->oparams, 0, sizeof(sasl_out_params_t));
-+ memset(&conn->external, 0, sizeof(_sasl_external_properties_t));
-+
-+ conn->flags = flags;
-+
-+ result = sasl_setprop(conn, SASL_IPLOCALPORT, iplocalport);
-+ if(result != SASL_OK)
-+ RETURN(conn, result);
-+
-+ result = sasl_setprop(conn, SASL_IPREMOTEPORT, ipremoteport);
-+ if(result != SASL_OK)
-+ RETURN(conn, result);
-+
-+ conn->encode_buf = NULL;
-+ conn->context = NULL;
-+ conn->secret = NULL;
-+ conn->idle_hook = idle_hook;
-+ conn->callbacks = callbacks;
-+ conn->global_callbacks = global_callbacks;
-+
-+ memset(&conn->props, 0, sizeof(conn->props));
-+
-+ /* Start this buffer out as an empty string */
-+ conn->error_code = SASL_OK;
-+ conn->errdetail_buf = conn->error_buf = NULL;
-+ conn->errdetail_buf_len = conn->error_buf_len = 150;
-+
-+ result = _buf_alloc(&conn->error_buf, &conn->error_buf_len, 150);
-+ if(result != SASL_OK) MEMERROR(conn);
-+ result = _buf_alloc(&conn->errdetail_buf, &conn->errdetail_buf_len, 150);
-+ if(result != SASL_OK) MEMERROR(conn);
-+
-+ conn->error_buf[0] = '\0';
-+ conn->errdetail_buf[0] = '\0';
-+
-+ conn->decode_buf = NULL;
-+
-+ if(serverFQDN) {
-+ result = _sasl_strdup(serverFQDN, &conn->serverFQDN, NULL);
-+ } else if (conn->type == SASL_CONN_SERVER) {
-+ /* We can fake it because we *are* the server */
-+ char name[MAXHOSTNAMELEN];
-+ memset(name, 0, sizeof(name));
-+ gethostname(name, MAXHOSTNAMELEN);
-+
-+ result = _sasl_strdup(name, &conn->serverFQDN, NULL);
-+ } else {
-+ conn->serverFQDN = NULL;
-+ }
-+
-+
-+ if(result != SASL_OK) MEMERROR( conn );
-+
-+ RETURN(conn, SASL_OK);
-+}
-+
-+int _sasl_common_init(void)
-+{
-+ int result;
-+
-+ /* Setup the global utilities */
-+ if(!sasl_global_utils) {
-+ sasl_global_utils = _sasl_alloc_utils(NULL, NULL);
-+ if(sasl_global_utils == NULL) return SASL_NOMEM;
-+ }
-+
-+ /* Init the canon_user plugin */
-+ result = sasl_canonuser_add_plugin("INTERNAL", internal_canonuser_init);
-+ if(result != SASL_OK) return result;
-+
-+ if (!free_mutex)
-+ free_mutex = sasl_MUTEX_ALLOC();
-+ if (!free_mutex) return SASL_FAIL;
-+
-+ return SASL_OK;
-+}
-+
-+/* dispose connection state, sets it to NULL
-+ * checks for pointer to NULL
-+ */
-+void sasl_dispose(sasl_conn_t **pconn)
-+{
-+ int result;
-+
-+ if (! pconn) return;
-+ if (! *pconn) return;
-+
-+ /* serialize disposes. this is necessary because we can't
-+ dispose of conn->mutex if someone else is locked on it */
-+ result = sasl_MUTEX_LOCK(free_mutex);
-+ if (result!=SASL_OK) return;
-+
-+ /* *pconn might have become NULL by now */
-+ if (! (*pconn)) return;
-+
-+ (*pconn)->destroy_conn(*pconn);
-+ sasl_FREE(*pconn);
-+ *pconn=NULL;
-+
-+ sasl_MUTEX_UNLOCK(free_mutex);
-+}
-+
-+void _sasl_conn_dispose(sasl_conn_t *conn) {
-+ if (conn->serverFQDN)
-+ sasl_FREE(conn->serverFQDN);
-+
-+ if (conn->external.auth_id)
-+ sasl_FREE(conn->external.auth_id);
-+
-+ if(conn->encode_buf) {
-+ if(conn->encode_buf->data) sasl_FREE(conn->encode_buf->data);
-+ sasl_FREE(conn->encode_buf);
-+ }
-+
-+ if(conn->error_buf)
-+ sasl_FREE(conn->error_buf);
-+
-+ if(conn->errdetail_buf)
-+ sasl_FREE(conn->errdetail_buf);
-+
-+ if(conn->decode_buf)
-+ sasl_FREE(conn->decode_buf);
-+
-+ if(conn->mechlist_buf)
-+ sasl_FREE(conn->mechlist_buf);
-+
-+ if(conn->service)
-+ sasl_FREE(conn->service);
-+
-+ /* oparams sub-members should be freed by the plugin, in so much
-+ * as they were allocated by the plugin */
-+}
-+
-+
-+/* get property from SASL connection state
-+ * propnum -- property number
-+ * pvalue -- pointer to value
-+ * returns:
-+ * SASL_OK -- no error
-+ * SASL_NOTDONE -- property not available yet
-+ * SASL_BADPARAM -- bad property number
-+ */
-+int sasl_getprop(sasl_conn_t *conn, int propnum, const void **pvalue)
-+{
-+ int result = SASL_OK;
-+ sasl_getopt_t *getopt;
-+ void *context;
-+
-+ if (! conn) return SASL_BADPARAM;
-+ if (! pvalue) PARAMERROR(conn);
-+
-+ switch(propnum)
-+ {
-+ case SASL_SSF:
-+ *(sasl_ssf_t **)pvalue= &conn->oparams.mech_ssf;
-+ break;
-+ case SASL_MAXOUTBUF:
-+ *(unsigned **)pvalue = &conn->oparams.maxoutbuf;
-+ break;
-+ case SASL_GETOPTCTX:
-+ result = _sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context);
-+ if(result != SASL_OK) break;
-+
-+ *(void **)pvalue = context;
-+ break;
-+ case SASL_CALLBACK:
-+ *(const sasl_callback_t **)pvalue = conn->callbacks;
-+ break;
-+ case SASL_IPLOCALPORT:
-+ if(conn->got_ip_local)
-+ *(const char **)pvalue = conn->iplocalport;
-+ else {
-+ *(const char **)pvalue = NULL;
-+ result = SASL_NOTDONE;
-+ }
-+ break;
-+ case SASL_IPREMOTEPORT:
-+ if(conn->got_ip_remote)
-+ *(const char **)pvalue = conn->ipremoteport;
-+ else {
-+ *(const char **)pvalue = NULL;
-+ result = SASL_NOTDONE;
-+ }
-+ break;
-+ case SASL_USERNAME:
-+ if(! conn->oparams.user)
-+ result = SASL_NOTDONE;
-+ else
-+ *((const char **)pvalue) = conn->oparams.user;
-+ break;
-+ case SASL_AUTHUSER:
-+ if(! conn->oparams.authid)
-+ result = SASL_NOTDONE;
-+ else
-+ *((const char **)pvalue) = conn->oparams.authid;
-+ break;
-+ case SASL_SERVERFQDN:
-+ *((const char **)pvalue) = conn->serverFQDN;
-+ break;
-+ case SASL_DEFUSERREALM:
-+ if(conn->type != SASL_CONN_SERVER) result = SASL_BADPROT;
-+ else
-+ *((const char **)pvalue) = ((sasl_server_conn_t *)conn)->user_realm;
-+ break;
-+ case SASL_SERVICE:
-+ *((const char **)pvalue) = conn->service;
-+ break;
-+ case SASL_AUTHSOURCE: /* name of plugin (not name of mech) */
-+ if(conn->type == SASL_CONN_CLIENT) {
-+ if(!((sasl_client_conn_t *)conn)->mech) {
-+ result = SASL_NOTDONE;
-+ break;
-+ }
-+ *((const char **)pvalue) =
-+ ((sasl_client_conn_t *)conn)->mech->plugname;
-+ } else if (conn->type == SASL_CONN_SERVER) {
-+ if(!((sasl_server_conn_t *)conn)->mech) {
-+ result = SASL_NOTDONE;
-+ break;
-+ }
-+ *((const char **)pvalue) =
-+ ((sasl_server_conn_t *)conn)->mech->plugname;
-+ } else {
-+ result = SASL_BADPARAM;
-+ }
-+ break;
-+ case SASL_MECHNAME: /* name of mech */
-+ if(conn->type == SASL_CONN_CLIENT) {
-+ if(!((sasl_client_conn_t *)conn)->mech) {
-+ result = SASL_NOTDONE;
-+ break;
-+ }
-+ *((const char **)pvalue) =
-+ ((sasl_client_conn_t *)conn)->mech->plug->mech_name;
-+ } else if (conn->type == SASL_CONN_SERVER) {
-+ if(!((sasl_server_conn_t *)conn)->mech) {
-+ result = SASL_NOTDONE;
-+ break;
-+ }
-+ *((const char **)pvalue) =
-+ ((sasl_server_conn_t *)conn)->mech->plug->mech_name;
-+ } else {
-+ result = SASL_BADPARAM;
-+ }
-+
-+ if(!(*pvalue) && result == SASL_OK) result = SASL_NOTDONE;
-+ break;
-+ case SASL_PLUGERR:
-+ *((const char **)pvalue) = conn->error_buf;
-+ break;
-+ case SASL_SSF_EXTERNAL:
-+ *((const sasl_ssf_t **)pvalue) = &conn->external.ssf;
-+ break;
-+ case SASL_AUTH_EXTERNAL:
-+ *((const char **)pvalue) = conn->external.auth_id;
-+ break;
-+ case SASL_SEC_PROPS:
-+ *((const sasl_security_properties_t **)pvalue) = &conn->props;
-+ break;
-+ default:
-+ result = SASL_BADPARAM;
-+ }
-+
-+ if(result == SASL_BADPARAM) {
-+ PARAMERROR(conn);
-+ } else if(result == SASL_NOTDONE) {
-+ sasl_seterror(conn, SASL_NOLOG,
-+ "Information that was requested is not yet available.");
-+ RETURN(conn, result);
-+ } else if(result != SASL_OK) {
-+ INTERROR(conn, result);
-+ } else
-+ RETURN(conn, result);
-+}
-+
-+/* set property in SASL connection state
-+ * returns:
-+ * SASL_OK -- value set
-+ * SASL_BADPARAM -- invalid property or value
-+ */
-+int sasl_setprop(sasl_conn_t *conn, int propnum, const void *value)
-+{
-+ int result = SASL_OK;
-+ char *str;
-+
-+ /* make sure the sasl context is valid */
-+ if (!conn)
-+ return SASL_BADPARAM;
-+
-+ switch(propnum)
-+ {
-+ case SASL_SSF_EXTERNAL:
-+ conn->external.ssf = *((sasl_ssf_t *)value);
-+ break;
-+
-+ case SASL_AUTH_EXTERNAL:
-+ if(value && strlen(value)) {
-+ result = _sasl_strdup(value, &str, NULL);
-+ if(result != SASL_OK) MEMERROR(conn);
-+ } else {
-+ str = NULL;
-+ }
-+
-+ if(conn->external.auth_id)
-+ sasl_FREE(conn->external.auth_id);
-+
-+ conn->external.auth_id = str;
-+
-+ break;
-+
-+ case SASL_DEFUSERREALM:
-+ if(conn->type != SASL_CONN_SERVER) {
-+ sasl_seterror(conn, 0, "Tried to set realm on non-server connection");
-+ result = SASL_BADPROT;
-+ break;
-+ }
-+
-+ if(value && strlen(value)) {
-+ result = _sasl_strdup(value, &str, NULL);
-+ if(result != SASL_OK) MEMERROR(conn);
-+ } else {
-+ PARAMERROR(conn);
-+ }
-+
-+ if(((sasl_server_conn_t *)conn)->user_realm)
-+ sasl_FREE(((sasl_server_conn_t *)conn)->user_realm);
-+
-+ ((sasl_server_conn_t *)conn)->user_realm = str;
-+ ((sasl_server_conn_t *)conn)->sparams->user_realm = str;
-+
-+ break;
-+
-+ case SASL_SEC_PROPS:
-+ {
-+ sasl_security_properties_t *props = (sasl_security_properties_t *)value;
-+
-+ if(props->maxbufsize == 0 && props->min_ssf != 0) {
-+ sasl_seterror(conn, 0,
-+ "Attempt to disable security layers (maxoutbuf == 0) with min_ssf > 0");
-+ RETURN(conn, SASL_TOOWEAK);
-+ }
-+
-+ memcpy(&(conn->props), props,
-+ sizeof(sasl_security_properties_t));
-+
-+ break;
-+ }
-+
-+ case SASL_IPREMOTEPORT:
-+ {
-+ const char *ipremoteport = (const char *)value;
-+ if(!value) {
-+ conn->got_ip_remote = 0;
-+ } else if (_sasl_ipfromstring(ipremoteport, NULL, 0)
-+ != SASL_OK) {
-+ sasl_seterror(conn, 0, "Bad IPREMOTEPORT value");
-+ RETURN(conn, SASL_BADPARAM);
-+ } else {
-+ strcpy(conn->ipremoteport, ipremoteport);
-+ conn->got_ip_remote = 1;
-+ }
-+
-+ if(conn->got_ip_remote) {
-+ if(conn->type == SASL_CONN_CLIENT) {
-+ ((sasl_client_conn_t *)conn)->cparams->ipremoteport
-+ = conn->ipremoteport;
-+ ((sasl_client_conn_t *)conn)->cparams->ipremlen =
-+ strlen(conn->ipremoteport);
-+ } else if (conn->type == SASL_CONN_SERVER) {
-+ ((sasl_server_conn_t *)conn)->sparams->ipremoteport
-+ = conn->ipremoteport;
-+ ((sasl_server_conn_t *)conn)->sparams->ipremlen =
-+ strlen(conn->ipremoteport);
-+ }
-+ } else {
-+ if(conn->type == SASL_CONN_CLIENT) {
-+ ((sasl_client_conn_t *)conn)->cparams->ipremoteport
-+ = NULL;
-+ ((sasl_client_conn_t *)conn)->cparams->ipremlen = 0;
-+ } else if (conn->type == SASL_CONN_SERVER) {
-+ ((sasl_server_conn_t *)conn)->sparams->ipremoteport
-+ = NULL;
-+ ((sasl_server_conn_t *)conn)->sparams->ipremlen = 0;
-+ }
-+ }
-+
-+ break;
-+ }
-+
-+ case SASL_IPLOCALPORT:
-+ {
-+ const char *iplocalport = (const char *)value;
-+ if(!value) {
-+ conn->got_ip_local = 0;
-+ } else if (_sasl_ipfromstring(iplocalport, NULL, 0)
-+ != SASL_OK) {
-+ sasl_seterror(conn, 0, "Bad IPLOCALPORT value");
-+ RETURN(conn, SASL_BADPARAM);
-+ } else {
-+ strcpy(conn->iplocalport, iplocalport);
-+ conn->got_ip_local = 1;
-+ }
-+
-+ if(conn->got_ip_local) {
-+ if(conn->type == SASL_CONN_CLIENT) {
-+ ((sasl_client_conn_t *)conn)->cparams->iplocalport
-+ = conn->iplocalport;
-+ ((sasl_client_conn_t *)conn)->cparams->iploclen
-+ = strlen(conn->iplocalport);
-+ } else if (conn->type == SASL_CONN_SERVER) {
-+ ((sasl_server_conn_t *)conn)->sparams->iplocalport
-+ = conn->iplocalport;
-+ ((sasl_server_conn_t *)conn)->sparams->iploclen
-+ = strlen(conn->iplocalport);
-+ }
-+ } else {
-+ if(conn->type == SASL_CONN_CLIENT) {
-+ ((sasl_client_conn_t *)conn)->cparams->iplocalport
-+ = NULL;
-+ ((sasl_client_conn_t *)conn)->cparams->iploclen = 0;
-+ } else if (conn->type == SASL_CONN_SERVER) {
-+ ((sasl_server_conn_t *)conn)->sparams->iplocalport
-+ = NULL;
-+ ((sasl_server_conn_t *)conn)->sparams->iploclen = 0;
-+ }
-+ }
-+ break;
-+ }
-+
-+ default:
-+ sasl_seterror(conn, 0, "Unknown parameter type");
-+ result = SASL_BADPARAM;
-+ }
-+
-+ RETURN(conn, result);
-+}
-+
-+/* this is apparently no longer a user function */
-+static int sasl_usererr(int saslerr)
-+{
-+ /* Hide the difference in a username failure and a password failure */
-+ if (saslerr == SASL_NOUSER)
-+ return SASL_BADAUTH;
-+
-+ /* otherwise return the error given; no transform necessary */
-+ return saslerr;
-+}
-+
-+const char *sasl_errstring(int saslerr,
-+ const char *langlist __attribute__((unused)),
-+ const char **outlang)
-+{
-+ if (outlang) *outlang="en-us";
-+
-+ switch(saslerr)
-+ {
-+ case SASL_CONTINUE: return "another step is needed in authentication";
-+ case SASL_OK: return "successful result";
-+ case SASL_FAIL: return "generic failure";
-+ case SASL_NOMEM: return "no memory available";
-+ case SASL_BUFOVER: return "overflowed buffer";
-+ case SASL_NOMECH: return "no mechanism available";
-+ case SASL_BADPROT: return "bad protocol / cancel";
-+ case SASL_NOTDONE: return "can't request info until later in exchange";
-+ case SASL_BADPARAM: return "invalid parameter supplied";
-+ case SASL_TRYAGAIN: return "transient failure (e.g., weak key)";
-+ case SASL_BADMAC: return "integrity check failed";
-+ case SASL_NOTINIT: return "SASL library not initialized";
-+ /* -- client only codes -- */
-+ case SASL_INTERACT: return "needs user interaction";
-+ case SASL_BADSERV: return "server failed mutual authentication step";
-+ case SASL_WRONGMECH: return "mechanism doesn't support requested feature";
-+ /* -- server only codes -- */
-+ case SASL_BADAUTH: return "authentication failure";
-+ case SASL_NOAUTHZ: return "authorization failure";
-+ case SASL_TOOWEAK: return "mechanism too weak for this user";
-+ case SASL_ENCRYPT: return "encryption needed to use mechanism";
-+ case SASL_TRANS: return "One time use of a plaintext password will enable requested mechanism for user";
-+ case SASL_EXPIRED: return "passphrase expired, has to be reset";
-+ case SASL_DISABLED: return "account disabled";
-+ case SASL_NOUSER: return "user not found";
-+ case SASL_BADVERS: return "version mismatch with plug-in";
-+ case SASL_UNAVAIL: return "remote authentication server unavailable";
-+ case SASL_NOVERIFY: return "user exists, but no verifier for user";
-+ case SASL_PWLOCK: return "passphrase locked";
-+ case SASL_NOCHANGE: return "requested change was not needed";
-+ case SASL_WEAKPASS: return "passphrase is too weak for security policy";
-+ case SASL_NOUSERPASS: return "user supplied passwords are not permitted";
-+
-+ default: return "undefined error!";
-+ }
-+
-+}
-+
-+/* Return the sanitized error detail about the last error that occured for
-+ * a connection */
-+const char *sasl_errdetail(sasl_conn_t *conn)
-+{
-+ unsigned need_len;
-+ const char *errstr;
-+ char leader[128];
-+
-+ if(!conn) return NULL;
-+
-+ errstr = sasl_errstring(conn->error_code, NULL, NULL);
-+ snprintf(leader,128,"SASL(%d): %s: ",
-+ sasl_usererr(conn->error_code), errstr);
-+
-+ need_len = strlen(leader) + strlen(conn->error_buf) + 12;
-+ _buf_alloc(&conn->errdetail_buf, &conn->errdetail_buf_len, need_len);
-+
-+ snprintf(conn->errdetail_buf, need_len, "%s%s", leader, conn->error_buf);
-+
-+ return conn->errdetail_buf;
-+}
-+
-+
-+/* Note that this needs the global callbacks, so if you don't give getcallbacks
-+ * a sasl_conn_t, you're going to need to pass it yourself (or else we couldn't
-+ * have client and server at the same time */
-+static int _sasl_global_getopt(void *context,
-+ const char *plugin_name,
-+ const char *option,
-+ const char ** result,
-+ unsigned *len)
-+{
-+ const sasl_global_callbacks_t * global_callbacks;
-+ const sasl_callback_t *callback;
-+
-+ global_callbacks = (const sasl_global_callbacks_t *) context;
-+
-+ if (global_callbacks && global_callbacks->callbacks) {
-+ for (callback = global_callbacks->callbacks;
-+ callback->id != SASL_CB_LIST_END;
-+ callback++) {
-+ if (callback->id == SASL_CB_GETOPT
-+ && (((sasl_getopt_t *)(callback->proc))(callback->context,
-+ plugin_name,
-+ option,
-+ result,
-+ len)
-+ == SASL_OK))
-+ return SASL_OK;
-+ }
-+ }
-+
-+ /* look it up in our configuration file */
-+ *result = sasl_config_getstring(option, NULL);
-+ if (*result != NULL) {
-+ if (len) { *len = strlen(*result); }
-+ return SASL_OK;
-+ }
-+
-+ return SASL_FAIL;
-+}
-+
-+static int
-+_sasl_conn_getopt(void *context,
-+ const char *plugin_name,
-+ const char *option,
-+ const char ** result,
-+ unsigned *len)
-+{
-+ sasl_conn_t * conn;
-+ const sasl_callback_t *callback;
-+
-+ if (! context)
-+ return SASL_BADPARAM;
-+
-+ conn = (sasl_conn_t *) context;
-+
-+ if (conn->callbacks)
-+ for (callback = conn->callbacks;
-+ callback->id != SASL_CB_LIST_END;
-+ callback++)
-+ if (callback->id == SASL_CB_GETOPT
-+ && (((sasl_getopt_t *)(callback->proc))(callback->context,
-+ plugin_name,
-+ option,
-+ result,
-+ len)
-+ == SASL_OK))
-+ return SASL_OK;
-+
-+ /* If we made it here, we didn't find an appropriate callback
-+ * in the connection's callback list, or the callback we did
-+ * find didn't return SASL_OK. So we attempt to use the
-+ * global callback for this connection... */
-+ return _sasl_global_getopt((void *)conn->global_callbacks,
-+ plugin_name,
-+ option,
-+ result,
-+ len);
-+}
-+
-+#ifdef HAVE_SYSLOG
-+/* this is the default logging */
-+static int _sasl_syslog(void *context __attribute__((unused)),
-+ int priority,
-+ const char *message)
-+{
-+ int syslog_priority;
-+
-+ /* set syslog priority */
-+ switch(priority) {
-+ case SASL_LOG_NONE:
-+ return SASL_OK;
-+ break;
-+ case SASL_LOG_ERR:
-+ syslog_priority = LOG_ERR;
-+ break;
-+ case SASL_LOG_WARN:
-+ syslog_priority = LOG_WARNING;
-+ break;
-+ case SASL_LOG_NOTE:
-+ case SASL_LOG_FAIL:
-+ syslog_priority = LOG_NOTICE;
-+ break;
-+ case SASL_LOG_PASS:
-+ case SASL_LOG_TRACE:
-+ case SASL_LOG_DEBUG:
-+ default:
-+ syslog_priority = LOG_DEBUG;
-+ break;
-+ }
-+
-+ /* do the syslog call. do not need to call openlog */
-+ syslog(syslog_priority | LOG_AUTH, "%s", message);
-+
-+ return SASL_OK;
-+}
-+#endif /* HAVE_SYSLOG */
-+
-+static int
-+_sasl_getsimple(void *context,
-+ int id,
-+ const char ** result,
-+ size_t *len)
-+{
-+ const char *userid;
-+ sasl_conn_t *conn;
-+
-+ if (! context || ! result) return SASL_BADPARAM;
-+
-+ conn = (sasl_conn_t *)context;
-+
-+ switch(id) {
-+ case SASL_CB_AUTHNAME:
-+ userid = getenv("USER");
-+ if (userid != NULL) {
-+ *result = userid;
-+ if (len) *len = strlen(userid);
-+ return SASL_OK;
-+ }
-+ userid = getenv("USERNAME");
-+ if (userid != NULL) {
-+ *result = userid;
-+ if (len) *len = strlen(userid);
-+ return SASL_OK;
-+ }
-+#ifdef WIN32
-+ /* for win32, try using the GetUserName standard call */
-+ {
-+ DWORD i;
-+ BOOL rval;
-+ static char sender[128];
-+
-+ i = sizeof(sender);
-+ rval = GetUserName(sender, &i);
-+ if ( rval) { /* got a userid */
-+ *result = sender;
-+ if (len) *len = strlen(sender);
-+ return SASL_OK;
-+ }
-+ }
-+#endif /* WIN32 */
-+ return SASL_FAIL;
-+ default:
-+ return SASL_BADPARAM;
-+ }
-+}
-+
-+static int
-+_sasl_verifyfile(void *context __attribute__((unused)),
-+ char *file __attribute__((unused)),
-+ int type __attribute__((unused)))
-+{
-+ /* always say ok */
-+ return SASL_OK;
-+}
-+
-+
-+static int
-+_sasl_proxy_policy(sasl_conn_t *conn,
-+ void *context __attribute__((unused)),
-+ const char *requested_user, unsigned rlen,
-+ const char *auth_identity, unsigned alen,
-+ const char *def_realm __attribute__((unused)),
-+ unsigned urlen __attribute__((unused)),
-+ struct propctx *propctx __attribute__((unused)))
-+{
-+ if (!conn)
-+ return SASL_BADPARAM;
-+
-+ if (!requested_user || *requested_user == '\0')
-+ return SASL_OK;
-+
-+ if (!auth_identity || !requested_user || rlen != alen ||
-+ (memcmp(auth_identity, requested_user, rlen) != 0)) {
-+ sasl_seterror(conn, 0,
-+ "Requested identity not authenticated identity");
-+ RETURN(conn, SASL_BADAUTH);
-+ }
-+
-+ return SASL_OK;
-+}
-+
-+int _sasl_getcallback(sasl_conn_t * conn,
-+ unsigned long callbackid,
-+ int (**pproc)(),
-+ void **pcontext)
-+{
-+ const sasl_callback_t *callback;
-+
-+ if (!pproc || !pcontext)
-+ PARAMERROR(conn);
-+
-+ /* Some callbacks are always provided by the library */
-+ switch (callbackid) {
-+ case SASL_CB_LIST_END:
-+ /* Nothing ever gets to provide this */
-+ INTERROR(conn, SASL_FAIL);
-+ case SASL_CB_GETOPT:
-+ if (conn) {
-+ *pproc = &_sasl_conn_getopt;
-+ *pcontext = conn;
-+ } else {
-+ *pproc = &_sasl_global_getopt;
-+ *pcontext = NULL;
-+ }
-+ return SASL_OK;
-+ }
-+
-+ /* If it's not always provided by the library, see if there's
-+ * a version provided by the application for this connection... */
-+ if (conn && conn->callbacks) {
-+ for (callback = conn->callbacks; callback->id != SASL_CB_LIST_END;
-+ callback++) {
-+ if (callback->id == callbackid) {
-+ *pproc = callback->proc;
-+ *pcontext = callback->context;
-+ if (callback->proc) {
-+ return SASL_OK;
-+ } else {
-+ return SASL_INTERACT;
-+ }
-+ }
-+ }
-+ }
-+
-+ /* And, if not for this connection, see if there's one
-+ * for all {server,client} connections... */
-+ if (conn && conn->global_callbacks && conn->global_callbacks->callbacks) {
-+ for (callback = conn->global_callbacks->callbacks;
-+ callback->id != SASL_CB_LIST_END;
-+ callback++) {
-+ if (callback->id == callbackid) {
-+ *pproc = callback->proc;
-+ *pcontext = callback->context;
-+ if (callback->proc) {
-+ return SASL_OK;
-+ } else {
-+ return SASL_INTERACT;
-+ }
-+ }
-+ }
-+ }
-+
-+ /* Otherwise, see if the library provides a default callback. */
-+ switch (callbackid) {
-+#ifdef HAVE_SYSLOG
-+ case SASL_CB_LOG:
-+ *pproc = (int (*)()) &_sasl_syslog;
-+ *pcontext = NULL;
-+ return SASL_OK;
-+#endif /* HAVE_SYSLOG */
-+ case SASL_CB_GETPATH:
-+ *pproc = (int (*)()) &_sasl_getpath;
-+ *pcontext = NULL;
-+ return SASL_OK;
-+ case SASL_CB_AUTHNAME:
-+ *pproc = (int (*)()) &_sasl_getsimple;
-+ *pcontext = conn;
-+ return SASL_OK;
-+ case SASL_CB_VERIFYFILE:
-+ *pproc = & _sasl_verifyfile;
-+ *pcontext = NULL;
-+ return SASL_OK;
-+ case SASL_CB_PROXY_POLICY:
-+ *pproc = (int (*)()) &_sasl_proxy_policy;
-+ *pcontext = NULL;
-+ return SASL_OK;
-+ }
-+
-+ /* Unable to find a callback... */
-+ *pproc = NULL;
-+ *pcontext = NULL;
-+ sasl_seterror(conn, SASL_NOLOG, "Unable to find a callback: %d", callbackid);
-+ RETURN(conn,SASL_FAIL);
-+}
-+
-+
-+/*
-+ * This function is typically called from a plugin.
-+ * It creates a string from the formatting and varargs given
-+ * and calls the logging callback (syslog by default)
-+ *
-+ * %m will parse the value in the next argument as an errno string
-+ * %z will parse the next argument as a SASL error code.
-+ */
-+
-+void
-+_sasl_log (sasl_conn_t *conn,
-+ int level,
-+ const char *fmt,
-+ ...)
-+{
-+ char *out=(char *) sasl_ALLOC(250);
-+ size_t alloclen=100; /* current allocated length */
-+ size_t outlen=0; /* current length of output buffer */
-+ size_t formatlen;
-+ size_t pos=0; /* current position in format string */
-+ int result;
-+ sasl_log_t *log_cb;
-+ void *log_ctx;
-+
-+ int ival;
-+ char *cval;
-+ va_list ap; /* varargs thing */
-+
-+ if(!fmt) goto done;
-+ if(!out) return;
-+
-+ formatlen = strlen(fmt);
-+
-+ /* See if we have a logging callback... */
-+ result = _sasl_getcallback(conn, SASL_CB_LOG, &log_cb, &log_ctx);
-+ if (result == SASL_OK && ! log_cb)
-+ result = SASL_FAIL;
-+ if (result != SASL_OK) goto done;
-+
-+ va_start(ap, fmt); /* start varargs */
-+
-+ while(pos<formatlen)
-+ {
-+ if (fmt[pos]!='%') /* regular character */
-+ {
-+ result = _buf_alloc(&out, &alloclen, outlen+1);
-+ if (result != SASL_OK) goto done;
-+ out[outlen]=fmt[pos];
-+ outlen++;
-+ pos++;
-+
-+ } else { /* formating thing */
-+ int done=0;
-+ char frmt[10];
-+ int frmtpos=1;
-+ char tempbuf[21];
-+ frmt[0]='%';
-+ pos++;
-+
-+ while (done==0)
-+ {
-+ switch(fmt[pos])
-+ {
-+ case 's': /* need to handle this */
-+ cval = va_arg(ap, char *); /* get the next arg */
-+ result = _sasl_add_string(&out, &alloclen,
-+ &outlen, cval);
-+
-+ if (result != SASL_OK) /* add the string */
-+ goto done;
-+
-+ done=1;
-+ break;
-+
-+ case '%': /* double % output the '%' character */
-+ result = _buf_alloc(&out,&alloclen,outlen+1);
-+ if (result != SASL_OK)
-+ goto done;
-+
-+ out[outlen]='%';
-+ outlen++;
-+ done=1;
-+ break;
-+
-+ case 'm': /* insert the errno string */
-+ result = _sasl_add_string(&out, &alloclen, &outlen,
-+ strerror(va_arg(ap, int)));
-+ if (result != SASL_OK)
-+ goto done;
-+
-+ done=1;
-+ break;
-+
-+ case 'z': /* insert the sasl error string */
-+ result = _sasl_add_string(&out, &alloclen, &outlen,
-+ (char *) sasl_errstring(va_arg(ap, int),NULL,NULL));
-+ if (result != SASL_OK)
-+ goto done;
-+
-+ done=1;
-+ break;
-+
-+ case 'c':
-+ frmt[frmtpos++]=fmt[pos];
-+ frmt[frmtpos]=0;
-+ tempbuf[0] = (char) va_arg(ap, int); /* get the next arg */
-+ tempbuf[1]='\0';
-+
-+ /* now add the character */
-+ result = _sasl_add_string(&out, &alloclen, &outlen, tempbuf);
-+ if (result != SASL_OK)
-+ goto done;
-+
-+ done=1;
-+ break;
-+
-+ case 'd':
-+ case 'i':
-+ frmt[frmtpos++]=fmt[pos];
-+ frmt[frmtpos]=0;
-+ ival = va_arg(ap, int); /* get the next arg */
-+
-+ snprintf(tempbuf,20,frmt,ival); /* have snprintf do the work */
-+ /* now add the string */
-+ result = _sasl_add_string(&out, &alloclen, &outlen, tempbuf);
-+ if (result != SASL_OK)
-+ goto done;
-+
-+ done=1;
-+
-+ break;
-+ default:
-+ frmt[frmtpos++]=fmt[pos]; /* add to the formating */
-+ frmt[frmtpos]=0;
-+ if (frmtpos>9)
-+ done=1;
-+ }
-+ pos++;
-+ if (pos>formatlen)
-+ done=1;
-+ }
-+
-+ }
-+ }
-+
-+ /* put 0 at end */
-+ result = _buf_alloc(&out, &alloclen, outlen+1);
-+ if (result != SASL_OK) goto done;
-+ out[outlen]=0;
-+
-+ va_end(ap);
-+
-+ /* send log message */
-+ result = log_cb(log_ctx, level, out);
-+
-+ done:
-+ if(out) sasl_FREE(out);
-+}
-+
-+
-+
-+/* Allocate and Init a sasl_utils_t structure */
-+sasl_utils_t *
-+_sasl_alloc_utils(sasl_conn_t *conn,
-+ sasl_global_callbacks_t *global_callbacks)
-+{
-+ sasl_utils_t *utils;
-+ /* set util functions - need to do rest*/
-+ utils=sasl_ALLOC(sizeof(sasl_utils_t));
-+ if (utils==NULL)
-+ return NULL;
-+
-+ utils->conn = conn;
-+
-+ sasl_randcreate(&utils->rpool);
-+
-+ if (conn) {
-+ utils->getopt = &_sasl_conn_getopt;
-+ utils->getopt_context = conn;
-+ } else {
-+ utils->getopt = &_sasl_global_getopt;
-+ utils->getopt_context = global_callbacks;
-+ }
-+
-+ utils->malloc=_sasl_allocation_utils.malloc;
-+ utils->calloc=_sasl_allocation_utils.calloc;
-+ utils->realloc=_sasl_allocation_utils.realloc;
-+ utils->free=_sasl_allocation_utils.free;
-+
-+ utils->mutex_alloc = _sasl_mutex_utils.alloc;
-+ utils->mutex_lock = _sasl_mutex_utils.lock;
-+ utils->mutex_unlock = _sasl_mutex_utils.unlock;
-+ utils->mutex_free = _sasl_mutex_utils.free;
-+
-+ utils->MD5Init = &_sasl_MD5Init;
-+ utils->MD5Update= &_sasl_MD5Update;
-+ utils->MD5Final = &_sasl_MD5Final;
-+ utils->hmac_md5 = &_sasl_hmac_md5;
-+ utils->hmac_md5_init = &_sasl_hmac_md5_init;
-+ utils->hmac_md5_final = &_sasl_hmac_md5_final;
-+ utils->hmac_md5_precalc = &_sasl_hmac_md5_precalc;
-+ utils->hmac_md5_import = &_sasl_hmac_md5_import;
-+ utils->mkchal = &sasl_mkchal;
-+ utils->utf8verify = &sasl_utf8verify;
-+ utils->rand=&sasl_rand;
-+ utils->churn=&sasl_churn;
-+ utils->checkpass=NULL;
-+
-+ utils->encode64=&sasl_encode64;
-+ utils->decode64=&sasl_decode64;
-+
-+ utils->erasebuffer=&sasl_erasebuffer;
-+
-+ utils->getprop=&sasl_getprop;
-+ utils->setprop=&sasl_setprop;
-+
-+ utils->getcallback=&_sasl_getcallback;
-+
-+ utils->log=&_sasl_log;
-+
-+ utils->seterror=&sasl_seterror;
-+
-+#ifndef macintosh
-+ /* Aux Property Utilities */
-+ utils->prop_new=&prop_new;
-+ utils->prop_dup=&prop_dup;
-+ utils->prop_request=&prop_request;
-+ utils->prop_get=&prop_get;
-+ utils->prop_getnames=&prop_getnames;
-+ utils->prop_clear=&prop_clear;
-+ utils->prop_dispose=&prop_dispose;
-+ utils->prop_format=&prop_format;
-+ utils->prop_set=&prop_set;
-+ utils->prop_setvals=&prop_setvals;
-+ utils->prop_erase=&prop_erase;
-+#endif
-+
-+ /* Spares */
-+ utils->spare_fptr = NULL;
-+ utils->spare_fptr1 = utils->spare_fptr2 =
-+ utils->spare_fptr3 = NULL;
-+
-+ return utils;
-+}
-+
-+int
-+_sasl_free_utils(const sasl_utils_t ** utils)
-+{
-+ sasl_utils_t *nonconst;
-+
-+ if(!utils) return SASL_BADPARAM;
-+ if(!*utils) return SASL_OK;
-+
-+ /* I wish we could avoid this cast, it's pretty gratuitous but it
-+ * does make life easier to have it const everywhere else. */
-+ nonconst = (sasl_utils_t *)(*utils);
-+
-+ sasl_randfree(&(nonconst->rpool));
-+ sasl_FREE(nonconst);
-+
-+ *utils = NULL;
-+ return SASL_OK;
-+}
-+
-+int sasl_idle(sasl_conn_t *conn)
-+{
-+ if (! conn) {
-+ if (_sasl_server_idle_hook
-+ && _sasl_server_idle_hook(NULL))
-+ return 1;
-+ if (_sasl_client_idle_hook
-+ && _sasl_client_idle_hook(NULL))
-+ return 1;
-+ return 0;
-+ }
-+
-+ if (conn->idle_hook)
-+ return conn->idle_hook(conn);
-+
-+ return 0;
-+}
-+
-+const sasl_callback_t *
-+_sasl_find_getpath_callback(const sasl_callback_t *callbacks)
-+{
-+ static const sasl_callback_t default_getpath_cb = {
-+ SASL_CB_GETPATH,
-+ &_sasl_getpath,
-+ NULL
-+ };
-+
-+ if (callbacks)
-+ while (callbacks->id != SASL_CB_LIST_END)
-+ {
-+ if (callbacks->id == SASL_CB_GETPATH)
-+ {
-+ return callbacks;
-+ } else {
-+ ++callbacks;
-+ }
-+ }
-+
-+ return &default_getpath_cb;
-+}
-+
-+const sasl_callback_t *
-+_sasl_find_verifyfile_callback(const sasl_callback_t *callbacks)
-+{
-+ static const sasl_callback_t default_verifyfile_cb = {
-+ SASL_CB_VERIFYFILE,
-+ &_sasl_verifyfile,
-+ NULL
-+ };
-+
-+ if (callbacks)
-+ while (callbacks->id != SASL_CB_LIST_END)
-+ {
-+ if (callbacks->id == SASL_CB_VERIFYFILE)
-+ {
-+ return callbacks;
-+ } else {
-+ ++callbacks;
-+ }
-+ }
-+
-+ return &default_verifyfile_cb;
-+}
-+
-+/* Basically a conditional call to realloc(), if we need more */
-+int _buf_alloc(char **rwbuf, size_t *curlen, size_t newlen)
-+{
-+ if(!(*rwbuf)) {
-+ *rwbuf = sasl_ALLOC(newlen);
-+ if (*rwbuf == NULL) {
-+ *curlen = 0;
-+ return SASL_NOMEM;
-+ }
-+ *curlen = newlen;
-+ } else if(*rwbuf && *curlen < newlen) {
-+ size_t needed = 2*(*curlen);
-+
-+ while(needed < newlen)
-+ needed *= 2;
-+
-+ *rwbuf = sasl_REALLOC(*rwbuf, needed);
-+
-+ if (*rwbuf == NULL) {
-+ *curlen = 0;
-+ return SASL_NOMEM;
-+ }
-+ *curlen = needed;
-+ }
-+
-+ return SASL_OK;
-+}
-+
-+/* for the mac os x cfm glue: this lets the calling function
-+ get pointers to the error buffer without having to touch the sasl_conn_t struct */
-+void _sasl_get_errorbuf(sasl_conn_t *conn, char ***bufhdl, size_t **lenhdl)
-+{
-+ *bufhdl = &conn->error_buf;
-+ *lenhdl = &conn->error_buf_len;
-+}
-+
-+/* convert an iovec to a single buffer */
-+int _iovec_to_buf(const struct iovec *vec,
-+ unsigned numiov, buffer_info_t **output)
-+{
-+ unsigned i;
-+ int ret;
-+ buffer_info_t *out;
-+ char *pos;
-+
-+ if(!vec || !output) return SASL_BADPARAM;
-+
-+ if(!(*output)) {
-+ *output = sasl_ALLOC(sizeof(buffer_info_t));
-+ if(!*output) return SASL_NOMEM;
-+ memset(*output,0,sizeof(buffer_info_t));
-+ }
-+
-+ out = *output;
-+
-+ out->curlen = 0;
-+ for(i=0; i<numiov; i++)
-+ out->curlen += vec[i].iov_len;
-+
-+ ret = _buf_alloc(&out->data, &out->reallen, out->curlen);
-+
-+ if(ret != SASL_OK) return SASL_NOMEM;
-+
-+ memset(out->data, 0, out->reallen);
-+ pos = out->data;
-+
-+ for(i=0; i<numiov; i++) {
-+ memcpy(pos, vec[i].iov_base, vec[i].iov_len);
-+ pos += vec[i].iov_len;
-+ }
-+
-+ return SASL_OK;
-+}
-+
-+/* This code might be useful in the future, but it isn't now, so.... */
-+#if 0
-+int _sasl_iptostring(const struct sockaddr *addr, socklen_t addrlen,
-+ char *out, unsigned outlen) {
-+ char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
-+
-+ if(!addr || !out) return SASL_BADPARAM;
-+
-+ getnameinfo(addr, addrlen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
-+ NI_NUMERICHOST | NI_WITHSCOPEID | NI_NUMERICSERV);
-+
-+ if(outlen < strlen(hbuf) + strlen(pbuf) + 2)
-+ return SASL_BUFOVER;
-+
-+ snprintf(out, outlen, "%s;%s", hbuf, pbuf);
-+
-+ return SASL_OK;
-+}
-+#endif
-+
-+int _sasl_ipfromstring(const char *addr,
-+ struct sockaddr *out, socklen_t outlen)
-+{
-+ int i, j;
-+ struct addrinfo hints, *ai = NULL;
-+ char hbuf[NI_MAXHOST];
-+
-+ /* A NULL out pointer just implies we don't do a copy, just verify it */
-+
-+ if(!addr) return SASL_BADPARAM;
-+
-+ /* Parse the address */
-+ for (i = 0; addr[i] != '\0' && addr[i] != ';'; i++) {
-+ if (i >= NI_MAXHOST)
-+ return SASL_BADPARAM;
-+ hbuf[i] = addr[i];
-+ }
-+ hbuf[i] = '\0';
-+
-+ if (addr[i] == ';')
-+ i++;
-+ /* XXX: Do we need this check? */
-+ for (j = i; addr[j] != '\0'; j++)
-+ if (!isdigit((int)(addr[j])))
-+ return SASL_BADPARAM;
-+
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = PF_UNSPEC;
-+ hints.ai_socktype = SOCK_STREAM;
-+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
-+ if (getaddrinfo(hbuf, &addr[i], &hints, &ai) != 0)
-+ return SASL_BADPARAM;
-+
-+ if (out) {
-+ if (outlen < (socklen_t)ai->ai_addrlen) {
-+ freeaddrinfo(ai);
-+ return SASL_BUFOVER;
-+ }
-+ memcpy(out, ai->ai_addr, ai->ai_addrlen);
-+ }
-+
-+ freeaddrinfo(ai);
-+
-+ return SASL_OK;
-+}
-+
-+int _sasl_build_mechlist(void)
-+{
-+ int count = 0;
-+ sasl_string_list_t *clist = NULL, *slist = NULL, *olist = NULL;
-+ sasl_string_list_t *p, *q, **last, *p_next;
-+
-+ clist = _sasl_client_mechs();
-+ slist = _sasl_server_mechs();
-+
-+ if(!clist) {
-+ olist = slist;
-+ } else {
-+ int flag;
-+
-+ /* append slist to clist, and set olist to clist */
-+ for(p = slist; p; p = p_next) {
-+ flag = 0;
-+ p_next = p->next;
-+
-+ last = &clist;
-+ for(q = clist; q; q = q->next) {
-+ if(!strcmp(q->d, p->d)) {
-+ /* They match, set the flag */
-+ flag = 1;
-+ break;
-+ }
-+ last = &(q->next);
-+ }
-+
-+ if(!flag) {
-+ (*last)->next = p;
-+ p->next = NULL;
-+ } else {
-+ sasl_FREE(p);
-+ }
-+ }
-+
-+ olist = clist;
-+ }
-+
-+ if(!olist) {
-+ printf ("no olist");
-+ return SASL_FAIL;
-+ }
-+
-+ for (p = olist; p; p = p->next) count++;
-+
-+ if(global_mech_list) {
-+ sasl_FREE(global_mech_list);
-+ global_mech_list = NULL;
-+ }
-+
-+ global_mech_list = sasl_ALLOC((count + 1) * sizeof(char *));
-+ if(!global_mech_list) return SASL_NOMEM;
-+
-+ memset(global_mech_list, 0, (count + 1) * sizeof(char *));
-+
-+ count = 0;
-+ for (p = olist; p; p = p_next) {
-+ p_next = p->next;
-+
-+ global_mech_list[count++] = (char *) p->d;
-+
-+ sasl_FREE(p);
-+ }
-+
-+ return SASL_OK;
-+}
-+
-+const char ** sasl_global_listmech(void)
-+{
-+ return global_mech_list;
-+}
-+
-+int sasl_listmech(sasl_conn_t *conn,
-+ const char *user,
-+ const char *prefix,
-+ const char *sep,
-+ const char *suffix,
-+ const char **result,
-+ unsigned *plen,
-+ int *pcount)
-+{
-+ if(!conn) {
-+ return SASL_BADPARAM;
-+ } else if(conn->type == SASL_CONN_SERVER) {
-+ RETURN(conn, _sasl_server_listmech(conn, user, prefix, sep, suffix,
-+ result, plen, pcount));
-+ } else if (conn->type == SASL_CONN_CLIENT) {
-+ RETURN(conn, _sasl_client_listmech(conn, prefix, sep, suffix,
-+ result, plen, pcount));
-+ }
-+
-+ PARAMERROR(conn);
-+}
-+
-+
-+#ifndef WIN32
-+static int
-+_sasl_getpath(void *context __attribute__((unused)),
-+ const char **path)
-+{
-+ if (! path)
-+ return SASL_BADPARAM;
-+
-+ *path = getenv(SASL_PATH_ENV_VAR);
-+ if (! *path)
-+ *path = PLUGINDIR;
-+
-+ return SASL_OK;
-+}
-+
-+#else
-+/* Return NULL on failure */
-+static int
-+_sasl_getpath(void *context __attribute__((unused)), const char **path)
-+{
-+ /* Open registry entry, and find all registered SASL libraries.
-+ *
-+ * Registry location:
-+ *
-+ * SOFTWARE\\Carnegie Mellon\\Project Cyrus\\SASL Library
-+ *
-+ * Key - value:
-+ *
-+ * "SearchPath" - value: PATH like (';' delimited) list
-+ * of directories where to search for plugins
-+ * The list may contain references to environment
-+ * variables (e.g. %PATH%).
-+ *
-+ */
-+ HKEY hKey;
-+ DWORD ret;
-+ DWORD ValueType; /* value type */
-+ DWORD cbData; /* value size */
-+ BYTE * ValueData; /* value */
-+ DWORD cbExpandedData; /* "expanded" value size */
-+ BYTE * ExpandedValueData; /* "expanded" value */
-+ char * return_value; /* function return value */
-+ char * tmp;
-+
-+ /* Initialization */
-+ ExpandedValueData = NULL;
-+ ValueData = NULL;
-+ return_value = NULL;
-+
-+ /* Open the registry */
-+ ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-+ SASL_ROOT_KEY,
-+ 0,
-+ KEY_READ,
-+ &hKey);
-+
-+ if (ret != ERROR_SUCCESS) {
-+ /* no registry entry */
-+ *path = PLUGINDIR;
-+ return SASL_OK;
-+ }
-+
-+ /* figure out value type and required buffer size */
-+ /* the size will include space for terminating NUL if required */
-+ RegQueryValueEx (hKey,
-+ SASL_PATH_SUBKEY,
-+ NULL, /* reserved */
-+ &ValueType,
-+ NULL,
-+ &cbData);
-+
-+ /* Only accept string related types */
-+ if (ValueType != REG_EXPAND_SZ &&
-+ ValueType != REG_MULTI_SZ &&
-+ ValueType != REG_SZ) {
-+ return_value = NULL;
-+ goto CLEANUP;
-+ }
-+
-+ /* Any high water mark? */
-+ ValueData = sasl_ALLOC(cbData);
-+ if (ValueData == NULL) {
-+ return_value = NULL;
-+ goto CLEANUP;
-+ };
-+
-+ RegQueryValueEx (hKey,
-+ SASL_PATH_SUBKEY,
-+ NULL, /* reserved */
-+ &ValueType,
-+ ValueData,
-+ &cbData);
-+
-+ switch (ValueType) {
-+ case REG_EXPAND_SZ:
-+ /* : A random starting guess */
-+ cbExpandedData = cbData + 1024;
-+ ExpandedValueData = sasl_ALLOC(cbExpandedData);
-+ if (ExpandedValueData == NULL) {
-+ return_value = NULL;
-+ goto CLEANUP;
-+ };
-+
-+ cbExpandedData = ExpandEnvironmentStrings(
-+ ValueData,
-+ ExpandedValueData,
-+ cbExpandedData);
-+
-+ if (cbExpandedData == 0) {
-+ /* : GetLastError() contains the reason for failure */
-+ return_value = NULL;
-+ goto CLEANUP;
-+ }
-+
-+ /* : Must retry expansion with the bigger buffer */
-+ if (cbExpandedData > cbData + 1024) {
-+ /* : Memory leak here if can't realloc */
-+ ExpandedValueData = sasl_REALLOC(ExpandedValueData, cbExpandedData);
-+ if (ExpandedValueData == NULL) {
-+ return_value = NULL;
-+ goto CLEANUP;
-+ };
-+
-+ cbExpandedData = ExpandEnvironmentStrings(
-+ ValueData,
-+ ExpandedValueData,
-+ cbExpandedData);
-+
-+ /* : This should not happen */
-+ if (cbExpandedData == 0) {
-+ /* : GetLastError() contains the reason for failure */
-+ return_value = NULL;
-+ goto CLEANUP;
-+ }
-+ }
-+
-+ sasl_FREE(ValueData);
-+ ValueData = ExpandedValueData;
-+ /* : This is to prevent automatical freeing of this block on cleanup */
-+ ExpandedValueData = NULL;
-+
-+ break;
-+
-+ case REG_MULTI_SZ:
-+ tmp = ValueData;
-+
-+ /* : We shouldn't overflow here, as the buffer is guarantied
-+ : to contain at least two consequent NULs */
-+ while (1) {
-+ if (tmp[0] == '\0') {
-+ /* : Stop the process if we found the end of the string (two consequent NULs) */
-+ if (tmp[1] == '\0') {
-+ break;
-+ }
-+
-+ /* : Replace delimiting NUL with our delimiter characted */
-+ tmp[0] = PATHS_DELIMITER;
-+ }
-+ tmp += strlen(tmp);
-+ }
-+ break;
-+
-+ case REG_SZ:
-+ /* Do nothing, it is good as is */
-+ break;
-+
-+ default:
-+ return_value = NULL;
-+ goto CLEANUP;
-+ }
-+
-+ return_value = ValueData;
-+
-+ CLEANUP:
-+ RegCloseKey(hKey);
-+ if (ExpandedValueData != NULL) sasl_FREE(ExpandedValueData);
-+ if (return_value == NULL) {
-+ if (ValueData != NULL) sasl_FREE(ValueData);
-+ }
-+ *path = return_value;
-+
-+ return SASL_OK;
-+}
-+
-+#endif
-diff -durN cyrus-sasl-2.1.10.orig/lib/saslint.h cyrus-sasl-2.1.10/lib/saslint.h
---- cyrus-sasl-2.1.10.orig/lib/saslint.h Thu Dec 5 05:16:59 2002
-+++ cyrus-sasl-2.1.10/lib/saslint.h Thu Jan 9 11:42:29 2003
-@@ -356,6 +356,9 @@
- _sasl_find_getpath_callback(const sasl_callback_t *callbacks);
-
- extern const sasl_callback_t *
-+_sasl_find_getconfpath_callback(const sasl_callback_t *callbacks);
-+
-+extern const sasl_callback_t *
- _sasl_find_verifyfile_callback(const sasl_callback_t *callbacks);
-
- extern int _sasl_common_init(void);
-diff -durN cyrus-sasl-2.1.10.orig/lib/saslint.h.orig cyrus-sasl-2.1.10/lib/saslint.h.orig
---- cyrus-sasl-2.1.10.orig/lib/saslint.h.orig Thu Jan 1 01:00:00 1970
-+++ cyrus-sasl-2.1.10/lib/saslint.h.orig Thu Dec 5 05:16:59 2002
-@@ -0,0 +1,494 @@
-+/* saslint.h - internal SASL library definitions
-+ * Rob Siemborski
-+ * Tim Martin
-+ * $Id$
-+ */
-+/*
-+ * Copyright (c) 2001 Carnegie Mellon University. All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * 1. Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ *
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in
-+ * the documentation and/or other materials provided with the
-+ * distribution.
-+ *
-+ * 3. The name "Carnegie Mellon University" must not be used to
-+ * endorse or promote products derived from this software without
-+ * prior written permission. For permission or any other legal
-+ * details, please contact
-+ * Office of Technology Transfer
-+ * Carnegie Mellon University
-+ * 5000 Forbes Avenue
-+ * Pittsburgh, PA 15213-3890
-+ * (412) 268-4387, fax: (412) 268-7395
-+ * tech-transfer@andrew.cmu.edu
-+ *
-+ * 4. Redistributions of any form whatsoever must retain the following
-+ * acknowledgment:
-+ * "This product includes software developed by Computing Services
-+ * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
-+ *
-+ * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
-+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-+ * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
-+ * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
-+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
-+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-+ */
-+
-+#ifndef SASLINT_H
-+#define SASLINT_H
-+
-+#include <config.h>
-+#include "sasl.h"
-+#include "saslplug.h"
-+#include "saslutil.h"
-+#include "prop.h"
-+
-+/* #define'd constants */
-+#define CANON_BUF_SIZE 256
-+
-+/* Error Handling Foo */
-+/* Helpful Hints:
-+ * -Error strings are set as soon as possible (first function in stack trace
-+ * with a pointer to the sasl_conn_t.
-+ * -Error codes are set as late as possible (only in the sasl api functions),
-+ * thoug "as often as possible" also comes to mind to ensure correctness
-+ * -Errors from calls to _buf_alloc, _sasl_strdup, etc are assumed to be
-+ * memory errors.
-+ * -Only errors (error codes < SASL_OK) should be remembered
-+ */
-+#define RETURN(conn, val) { if(conn && (val) < SASL_OK) \
-+ (conn)->error_code = (val); \
-+ return (val); }
-+#define MEMERROR(conn) {\
-+ if(conn) sasl_seterror( (conn), 0, \
-+ "Out of Memory in " __FILE__ " near line %d", __LINE__ ); \
-+ RETURN(conn, SASL_NOMEM) }
-+#define PARAMERROR(conn) {\
-+ if(conn) sasl_seterror( (conn), SASL_NOLOG, \
-+ "Parameter error in " __FILE__ " near line %d", __LINE__ ); \
-+ RETURN(conn, SASL_BADPARAM) }
-+#define INTERROR(conn, val) {\
-+ if(conn) sasl_seterror( (conn), 0, \
-+ "Internal Error %d in " __FILE__ " near line %d", (val),\
-+ __LINE__ ); \
-+ RETURN(conn, (val)) }
-+
-+#ifndef PATH_MAX
-+# ifdef WIN32
-+# define PATH_MAX MAX_PATH
-+# else
-+# ifdef _POSIX_PATH_MAX
-+# define PATH_MAX _POSIX_PATH_MAX
-+# else
-+# define PATH_MAX 1024 /* arbitrary; probably big enough will
-+ * probably only be 256+64 on
-+ * pre-posix machines */
-+# endif /* _POSIX_PATH_MAX */
-+# endif /* WIN32 */
-+#endif
-+
-+/* : Define directory delimiter in SASL_PATH variable */
-+#ifdef WIN32
-+#define PATHS_DELIMITER ';'
-+#else
-+#define PATHS_DELIMITER ':'
-+#endif
-+
-+/* Datatype Definitions */
-+typedef struct {
-+ const sasl_callback_t *callbacks;
-+ const char *appname;
-+} sasl_global_callbacks_t;
-+
-+typedef struct _sasl_external_properties
-+{
-+ sasl_ssf_t ssf;
-+ char *auth_id;
-+} _sasl_external_properties_t;
-+
-+typedef struct sasl_string_list
-+{
-+ const char *d;
-+ struct sasl_string_list *next;
-+} sasl_string_list_t;
-+
-+typedef struct buffer_info
-+{
-+ char *data;
-+ size_t curlen;
-+ size_t reallen;
-+} buffer_info_t;
-+
-+typedef int add_plugin_t(const char *, void *);
-+
-+typedef struct add_plugin_list
-+{
-+ const char *entryname;
-+ add_plugin_t *add_plugin;
-+} add_plugin_list_t;
-+
-+enum Sasl_conn_type { SASL_CONN_UNKNOWN = 0,
-+ SASL_CONN_SERVER = 1,
-+ SASL_CONN_CLIENT = 2 };
-+
-+struct sasl_conn {
-+ enum Sasl_conn_type type;
-+
-+ void (*destroy_conn)(sasl_conn_t *); /* destroy function */
-+
-+ char *service;
-+
-+ unsigned int flags; /* flags passed to sasl_*_new */
-+
-+ /* IP information. A buffer of size 52 is adequate for this in its
-+ longest format (see sasl.h) */
-+ int got_ip_local, got_ip_remote;
-+ char iplocalport[NI_MAXHOST + NI_MAXSERV];
-+ char ipremoteport[NI_MAXHOST + NI_MAXSERV];
-+
-+ void *context;
-+ sasl_out_params_t oparams;
-+
-+ sasl_security_properties_t props;
-+ _sasl_external_properties_t external;
-+
-+ sasl_secret_t *secret;
-+
-+ int (*idle_hook)(sasl_conn_t *conn);
-+ const sasl_callback_t *callbacks;
-+ const sasl_global_callbacks_t *global_callbacks; /* global callbacks
-+ * connection */
-+ char *serverFQDN;
-+
-+ /* Pointers to memory that we are responsible for */
-+ buffer_info_t *encode_buf;
-+
-+ int error_code;
-+ char *error_buf, *errdetail_buf;
-+ size_t error_buf_len, errdetail_buf_len;
-+ char *mechlist_buf;
-+ size_t mechlist_buf_len;
-+
-+ char *decode_buf;
-+
-+ char user_buf[CANON_BUF_SIZE+1], authid_buf[CANON_BUF_SIZE+1];
-+};
-+
-+/* Server Conn Type Information */
-+
-+typedef struct mechanism
-+{
-+ int version;
-+ int condition; /* set to SASL_NOUSER if no available users;
-+ set to SASL_CONTINUE if delayed plugn loading */
-+ char *plugname; /* for AUTHSOURCE tracking */
-+ const sasl_server_plug_t *plug;
-+ struct mechanism *next;
-+ char *f; /* where should i load the mechanism from? */
-+} mechanism_t;
-+
-+typedef struct mech_list {
-+ const sasl_utils_t *utils; /* gotten from plug_init */
-+
-+ void *mutex; /* mutex for this data */
-+ mechanism_t *mech_list; /* list of mechanisms */
-+ int mech_length; /* number of mechanisms */
-+} mech_list_t;
-+
-+typedef struct context_list
-+{
-+ mechanism_t *mech;
-+ void *context; /* if NULL, this mech is disabled for this connection
-+ * otherwise, use this context instead of a call
-+ * to mech_new */
-+ struct context_list *next;
-+} context_list_t;
-+
-+typedef struct sasl_server_conn {
-+ sasl_conn_t base; /* parts common to server + client */
-+
-+ char *user_realm; /* domain the user authenticating is in */
-+ int sent_last; /* Have we already done the last send? */
-+ int authenticated;
-+ mechanism_t *mech; /* mechanism trying to use */
-+ sasl_server_params_t *sparams;
-+ context_list_t *mech_contexts;
-+} sasl_server_conn_t;
-+
-+/* Client Conn Type Information */
-+
-+typedef struct cmechanism
-+{
-+ int version;
-+
-+ char *plugname;
-+ const sasl_client_plug_t *plug;
-+
-+ struct cmechanism *next;
-+} cmechanism_t;
-+
-+typedef struct cmech_list {
-+ const sasl_utils_t *utils;
-+
-+ void *mutex; /* mutex for this data */
-+ cmechanism_t *mech_list; /* list of mechanisms */
-+ int mech_length; /* number of mechanisms */
-+
-+} cmech_list_t;
-+
-+typedef struct sasl_client_conn {
-+ sasl_conn_t base; /* parts common to server + client */
-+
-+ cmechanism_t *mech;
-+ sasl_client_params_t *cparams;
-+
-+ char *clientFQDN;
-+
-+} sasl_client_conn_t;
-+
-+typedef struct sasl_allocation_utils {
-+ sasl_malloc_t *malloc;
-+ sasl_calloc_t *calloc;
-+ sasl_realloc_t *realloc;
-+ sasl_free_t *free;
-+} sasl_allocation_utils_t;
-+
-+typedef struct sasl_mutex_utils {
-+ sasl_mutex_alloc_t *alloc;
-+ sasl_mutex_lock_t *lock;
-+ sasl_mutex_unlock_t *unlock;
-+ sasl_mutex_free_t *free;
-+} sasl_mutex_utils_t;
-+
-+typedef struct sasl_log_utils_s {
-+ sasl_log_t *log;
-+} sasl_log_utils_t;
-+
-+typedef int sasl_plaintext_verifier(sasl_conn_t *conn,
-+ const char *userid,
-+ const char *passwd,
-+ const char *service,
-+ const char *user_realm);
-+
-+struct sasl_verify_password_s {
-+ char *name;
-+ sasl_plaintext_verifier *verify;
-+};
-+
-+/*
-+ * globals & constants
-+ */
-+/*
-+ * common.c
-+ */
-+LIBSASL_API const sasl_utils_t *sasl_global_utils;
-+
-+extern void (*_sasl_client_cleanup_hook)(void);
-+extern void (*_sasl_server_cleanup_hook)(void);
-+extern int (*_sasl_client_idle_hook)(sasl_conn_t *conn);
-+extern int (*_sasl_server_idle_hook)(sasl_conn_t *conn);
-+
-+extern sasl_allocation_utils_t _sasl_allocation_utils;
-+extern sasl_mutex_utils_t _sasl_mutex_utils;
-+
-+/*
-+ * checkpw.c
-+ */
-+extern struct sasl_verify_password_s _sasl_verify_password[];
-+
-+/*
-+ * server.c
-+ */
-+/* (this is a function call to ensure this is read-only to the outside) */
-+extern int _is_sasl_server_active(void);
-+
-+/*
-+ * Allocation and Mutex utility macros
-+ */
-+#define sasl_ALLOC(__size__) (_sasl_allocation_utils.malloc((__size__)))
-+#define sasl_CALLOC(__nelem__, __size__) \
-+ (_sasl_allocation_utils.calloc((__nelem__), (__size__)))
-+#define sasl_REALLOC(__ptr__, __size__) \
-+ (_sasl_allocation_utils.realloc((__ptr__), (__size__)))
-+#define sasl_FREE(__ptr__) (_sasl_allocation_utils.free((__ptr__)))
-+
-+#define sasl_MUTEX_ALLOC() (_sasl_mutex_utils.alloc())
-+#define sasl_MUTEX_LOCK(__mutex__) (_sasl_mutex_utils.lock((__mutex__)))
-+#define sasl_MUTEX_UNLOCK(__mutex__) (_sasl_mutex_utils.unlock((__mutex__)))
-+#define sasl_MUTEX_FREE(__mutex__) \
-+ (_sasl_mutex_utils.free((__mutex__)))
-+
-+/* function prototypes */
-+/*
-+ * dlopen.c and staticopen.c
-+ */
-+/*
-+ * The differences here are:
-+ * _sasl_load_plugins loads all plugins from all files
-+ * _sasl_get_plugin loads the LIBRARY for an individual file
-+ * _sasl_done_with_plugins frees the LIBRARIES loaded by the above 2
-+ * _sasl_locate_entry locates an entrypoint in a given library
-+ */
-+extern int _sasl_load_plugins(const add_plugin_list_t *entrypoints,
-+ const sasl_callback_t *getpath_callback,
-+ const sasl_callback_t *verifyfile_callback);
-+extern int _sasl_get_plugin(const char *file,
-+ const sasl_callback_t *verifyfile_cb,
-+ void **libraryptr);
-+extern int _sasl_locate_entry(void *library, const char *entryname,
-+ void **entry_point);
-+extern int _sasl_done_with_plugins();
-+
-+
-+/*
-+ * common.c
-+ */
-+extern const sasl_callback_t *
-+_sasl_find_getpath_callback(const sasl_callback_t *callbacks);
-+
-+extern const sasl_callback_t *
-+_sasl_find_verifyfile_callback(const sasl_callback_t *callbacks);
-+
-+extern int _sasl_common_init(void);
-+
-+extern int _sasl_conn_init(sasl_conn_t *conn,
-+ const char *service,
-+ unsigned int flags,
-+ enum Sasl_conn_type type,
-+ int (*idle_hook)(sasl_conn_t *conn),
-+ const char *serverFQDN,
-+ const char *iplocalport,
-+ const char *ipremoteport,
-+ const sasl_callback_t *callbacks,
-+ const sasl_global_callbacks_t *global_callbacks);
-+extern void _sasl_conn_dispose(sasl_conn_t *conn);
-+
-+extern sasl_utils_t *
-+_sasl_alloc_utils(sasl_conn_t *conn,
-+ sasl_global_callbacks_t *global_callbacks);
-+extern int _sasl_free_utils(const sasl_utils_t ** utils);
-+
-+extern int
-+_sasl_getcallback(sasl_conn_t * conn,
-+ unsigned long callbackid,
-+ int (**pproc)(),
-+ void **pcontext);
-+
-+extern void
-+_sasl_log(sasl_conn_t *conn,
-+ int level,
-+ const char *fmt,
-+ ...);
-+
-+void _sasl_get_errorbuf(sasl_conn_t *conn, char ***bufhdl, size_t **lenhdl);
-+int _sasl_add_string(char **out, size_t *alloclen,
-+ size_t *outlen, const char *add);
-+
-+/* More Generic Utilities in common.c */
-+extern int _sasl_strdup(const char *in, char **out, size_t *outlen);
-+
-+/* Basically a conditional call to realloc(), if we need more */
-+int _buf_alloc(char **rwbuf, size_t *curlen, size_t newlen);
-+
-+/* convert an iovec to a single buffer */
-+int _iovec_to_buf(const struct iovec *vec,
-+ unsigned numiov, buffer_info_t **output);
-+
-+/* Convert between string formats and sockaddr formats */
-+int _sasl_iptostring(const struct sockaddr *addr, socklen_t addrlen,
-+ char *out, unsigned outlen);
-+int _sasl_ipfromstring(const char *addr, struct sockaddr *out,
-+ socklen_t outlen);
-+
-+/*
-+ * external plugin (external.c)
-+ */
-+int external_client_plug_init(const sasl_utils_t *utils,
-+ int max_version,
-+ int *out_version,
-+ sasl_client_plug_t **pluglist,
-+ int *plugcount);
-+int external_server_plug_init(const sasl_utils_t *utils,
-+ int max_version,
-+ int *out_version,
-+ sasl_server_plug_t **pluglist,
-+ int *plugcount);
-+
-+/* Mech Listing Functions */
-+int _sasl_build_mechlist(void);
-+int _sasl_server_listmech(sasl_conn_t *conn,
-+ const char *user,
-+ const char *prefix,
-+ const char *sep,
-+ const char *suffix,
-+ const char **result,
-+ unsigned *plen,
-+ int *pcount);
-+int _sasl_client_listmech(sasl_conn_t *conn,
-+ const char *prefix,
-+ const char *sep,
-+ const char *suffix,
-+ const char **result,
-+ unsigned *plen,
-+ int *pcount);
-+/* Just create a straight list of them */
-+sasl_string_list_t *_sasl_client_mechs(void);
-+sasl_string_list_t *_sasl_server_mechs(void);
-+
-+/*
-+ * config file declarations (config.c)
-+ */
-+extern int sasl_config_init(const char *filename);
-+extern const char *sasl_config_getstring(const char *key,const char *def);
-+extern int sasl_config_getint(const char *key,int def);
-+extern int sasl_config_getswitch(const char *key,int def);
-+
-+/* checkpw.c */
-+#ifdef DO_SASL_CHECKAPOP
-+extern int _sasl_auxprop_verify_apop(sasl_conn_t *conn,
-+ const char *userstr,
-+ const char *challenge,
-+ const char *response,
-+ const char *user_realm);
-+#endif /* DO_SASL_CHECKAPOP */
-+
-+/* Auxprop Plugin (checkpw.c) */
-+extern int sasldb_auxprop_plug_init(const sasl_utils_t *utils,
-+ int max_version,
-+ int *out_version,
-+ sasl_auxprop_plug_t **plug,
-+ const char *plugname);
-+
-+/*
-+ * auxprop.c
-+ */
-+extern int _sasl_auxprop_add_plugin(void *p, void *library);
-+extern void _sasl_auxprop_free(void);
-+extern void _sasl_auxprop_lookup(sasl_server_params_t *sparams,
-+ unsigned flags,
-+ const char *user, unsigned ulen);
-+
-+/*
-+ * canonusr.c
-+ */
-+void _sasl_canonuser_free();
-+extern int internal_canonuser_init(const sasl_utils_t *utils,
-+ int max_version,
-+ int *out_version,
-+ sasl_canonuser_plug_t **plug,
-+ const char *plugname);
-+extern int _sasl_canon_user(sasl_conn_t *conn,
-+ const char *user, unsigned ulen,
-+ unsigned flags,
-+ sasl_out_params_t *oparams);
-+
-+#endif /* SASLINT_H */
-diff -durN cyrus-sasl-2.1.10.orig/lib/server.c cyrus-sasl-2.1.10/lib/server.c
---- cyrus-sasl-2.1.10.orig/lib/server.c Thu Dec 5 05:16:59 2002
-+++ cyrus-sasl-2.1.10/lib/server.c Thu Jan 9 11:42:29 2003
-@@ -379,15 +379,15 @@
- char *c;
- char *config_filename=NULL;
- int len;
-- const sasl_callback_t *getpath_cb=NULL;
-+ const sasl_callback_t *getconfpath_cb=NULL;
-
- /* get the path to the plugins; for now the config file will reside there */
-- getpath_cb=_sasl_find_getpath_callback( global_callbacks.callbacks );
-- if (getpath_cb==NULL) return SASL_BADPARAM;
-+ getconfpath_cb=_sasl_find_getconfpath_callback( global_callbacks.callbacks );
-+ if (getconfpath_cb==NULL) return SASL_BADPARAM;
-
-- /* getpath_cb->proc MUST be a sasl_getpath_t; if only c had a type
-+ /* getconfpath_cb->proc MUST be a sasl_getconfpath_t; if only c had a type
- system */
-- result = ((sasl_getpath_t *)(getpath_cb->proc))(getpath_cb->context,
-+ result = ((sasl_getconfpath_t *)(getconfpath_cb->proc))(getconfpath_cb->context,
- &path_to_config);
- if (result!=SASL_OK) goto done;
- if (path_to_config == NULL) path_to_config = "";
-diff -durN cyrus-sasl-2.1.10.orig/lib/server.c.orig cyrus-sasl-2.1.10/lib/server.c.orig
---- cyrus-sasl-2.1.10.orig/lib/server.c.orig Thu Jan 1 01:00:00 1970
-+++ cyrus-sasl-2.1.10/lib/server.c.orig Thu Dec 5 05:16:59 2002
-@@ -0,0 +1,1734 @@
-+/* SASL server API implementation
-+ * Rob Siemborski
-+ * Tim Martin
-+ * $Id$
-+ */
-+/*
-+ * Copyright (c) 2001 Carnegie Mellon University. All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * 1. Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ *
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in
-+ * the documentation and/or other materials provided with the
-+ * distribution.
-+ *
-+ * 3. The name "Carnegie Mellon University" must not be used to
-+ * endorse or promote products derived from this software without
-+ * prior written permission. For permission or any other legal
-+ * details, please contact
-+ * Office of Technology Transfer
-+ * Carnegie Mellon University
-+ * 5000 Forbes Avenue
-+ * Pittsburgh, PA 15213-3890
-+ * (412) 268-4387, fax: (412) 268-7395
-+ * tech-transfer@andrew.cmu.edu
-+ *
-+ * 4. Redistributions of any form whatsoever must retain the following
-+ * acknowledgment:
-+ * "This product includes software developed by Computing Services
-+ * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
-+ *
-+ * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
-+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-+ * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
-+ * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
-+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
-+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-+ */
-+
-+/* local functions/structs don't start with sasl
-+ */
-+#include <config.h>
-+#include <errno.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <limits.h>
-+#ifndef macintosh
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#endif
-+#include <fcntl.h>
-+#include <string.h>
-+#include <ctype.h>
-+
-+#include "sasl.h"
-+#include "saslint.h"
-+#include "saslplug.h"
-+#include "saslutil.h"
-+
-+#ifdef sun
-+/* gotta define gethostname ourselves on suns */
-+extern int gethostname(char *, int);
-+#endif
-+
-+#define DEFAULT_CHECKPASS_MECH "auxprop"
-+
-+/* Contains functions:
-+ *
-+ * sasl_server_init
-+ * sasl_server_new
-+ * sasl_listmech
-+ * sasl_server_start
-+ * sasl_server_step
-+ * sasl_checkpass
-+ * sasl_checkapop
-+ * sasl_user_exists
-+ * sasl_setpass
-+ */
-+
-+/* if we've initialized the server sucessfully */
-+static int _sasl_server_active = 0;
-+
-+/* For access by other modules */
-+int _is_sasl_server_active(void) { return _sasl_server_active; }
-+
-+static int _sasl_checkpass(sasl_conn_t *conn, const char *service,
-+ const char *user, const char *pass);
-+
-+static mech_list_t *mechlist = NULL; /* global var which holds the list */
-+
-+static sasl_global_callbacks_t global_callbacks;
-+
-+/* set the password for a user
-+ * conn -- SASL connection
-+ * user -- user name
-+ * pass -- plaintext password, may be NULL to remove user
-+ * passlen -- length of password, 0 = strlen(pass)
-+ * oldpass -- NULL will sometimes work
-+ * oldpasslen -- length of password, 0 = strlen(oldpass)
-+ * flags -- see flags below
-+ *
-+ * returns:
-+ * SASL_NOCHANGE -- proper entry already exists
-+ * SASL_NOMECH -- no authdb supports password setting as configured
-+ * SASL_NOVERIFY -- user exists, but no settable password present
-+ * SASL_DISABLED -- account disabled
-+ * SASL_PWLOCK -- password locked
-+ * SASL_WEAKPASS -- password too weak for security policy
-+ * SASL_NOUSERPASS -- user-supplied passwords not permitted
-+ * SASL_FAIL -- OS error
-+ * SASL_BADPARAM -- password too long
-+ * SASL_OK -- successful
-+ */
-+
-+int sasl_setpass(sasl_conn_t *conn,
-+ const char *user,
-+ const char *pass, unsigned passlen,
-+ const char *oldpass,
-+ unsigned oldpasslen,
-+ unsigned flags)
-+{
-+ int result=SASL_OK, tmpresult;
-+ sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn;
-+ sasl_server_userdb_setpass_t *setpass_cb = NULL;
-+ void *context = NULL;
-+ mechanism_t *m;
-+
-+ if (!_sasl_server_active || !mechlist) return SASL_NOTINIT;
-+
-+ /* check params */
-+ if (!conn) return SASL_BADPARAM;
-+ if (conn->type != SASL_CONN_SERVER) PARAMERROR(conn);
-+
-+ if ((!(flags & SASL_SET_DISABLE) && passlen == 0)
-+ || ((flags & SASL_SET_CREATE) && (flags & SASL_SET_DISABLE)))
-+ PARAMERROR(conn);
-+
-+ /* call userdb callback function */
-+ result = _sasl_getcallback(conn, SASL_CB_SERVER_USERDB_SETPASS,
-+ &setpass_cb, &context);
-+ if(result == SASL_OK && setpass_cb) {
-+ tmpresult = setpass_cb(conn, context, user, pass, passlen,
-+ s_conn->sparams->propctx, flags);
-+ if(tmpresult != SASL_OK) {
-+ _sasl_log(conn, SASL_LOG_ERR,
-+ "setpass callback failed for %s: %z",
-+ user, tmpresult);
-+ } else {
-+ _sasl_log(conn, SASL_LOG_NOTE,
-+ "setpass callback succeeded for %s", user);
-+ }
-+ } else {
-+ result = SASL_OK;
-+ }
-+
-+ /* now we let the mechanisms set their secrets */
-+ for (m = mechlist->mech_list; m; m = m->next) {
-+ if (!m->plug->setpass) {
-+ /* can't set pass for this mech */
-+ continue;
-+ }
-+ tmpresult = m->plug->setpass(m->plug->glob_context,
-+ ((sasl_server_conn_t *)conn)->sparams,
-+ user,
-+ pass,
-+ passlen,
-+ oldpass, oldpasslen,
-+ flags);
-+ if (tmpresult == SASL_OK) {
-+ _sasl_log(conn, SASL_LOG_NOTE,
-+ "%s: set secret for %s", m->plug->mech_name, user);
-+
-+ m->condition = SASL_OK; /* if we previously thought the
-+ mechanism didn't have any user secrets
-+ we now think it does */
-+
-+ } else if (tmpresult == SASL_NOCHANGE) {
-+ _sasl_log(conn, SASL_LOG_NOTE,
-+ "%s: secret not changed for %s", m->plug->mech_name, user);
-+ } else {
-+ result = tmpresult;
-+ _sasl_log(conn, SASL_LOG_ERR,
-+ "%s: failed to set secret for %s: %z (%m)",
-+ m->plug->mech_name, user, tmpresult,
-+#ifndef WIN32
-+ errno
-+#else
-+ GetLastError()
-+#endif
-+ );
-+ }
-+ }
-+
-+ RETURN(conn, result);
-+}
-+
-+/* local mechanism which disposes of server */
-+static void server_dispose(sasl_conn_t *pconn)
-+{
-+ sasl_server_conn_t *s_conn= (sasl_server_conn_t *) pconn;
-+ context_list_t *cur, *cur_next;
-+
-+ if (s_conn->mech
-+ && s_conn->mech->plug->mech_dispose) {
-+ s_conn->mech->plug->mech_dispose(pconn->context,
-+ s_conn->sparams->utils);
-+ }
-+ pconn->context = NULL;
-+
-+ for(cur = s_conn->mech_contexts; cur; cur=cur_next) {
-+ cur_next = cur->next;
-+ if(cur->context)
-+ cur->mech->plug->mech_dispose(cur->context, s_conn->sparams->utils);
-+ sasl_FREE(cur);
-+ }
-+ s_conn->mech_contexts = NULL;
-+
-+ _sasl_free_utils(&s_conn->sparams->utils);
-+
-+ if (s_conn->sparams->propctx)
-+ prop_dispose(&s_conn->sparams->propctx);
-+
-+ if (s_conn->user_realm)
-+ sasl_FREE(s_conn->user_realm);
-+
-+ if (s_conn->sparams)
-+ sasl_FREE(s_conn->sparams);
-+
-+ _sasl_conn_dispose(pconn);
-+}
-+
-+static int init_mechlist(void)
-+{
-+ sasl_utils_t *newutils = NULL;
-+
-+ mechlist->mutex = sasl_MUTEX_ALLOC();
-+ if(!mechlist->mutex) return SASL_FAIL;
-+
-+ /* set util functions - need to do rest */
-+ newutils = _sasl_alloc_utils(NULL, &global_callbacks);
-+ if (newutils == NULL)
-+ return SASL_NOMEM;
-+
-+ newutils->checkpass = &sasl_checkpass;
-+
-+ mechlist->utils = newutils;
-+ mechlist->mech_list=NULL;
-+ mechlist->mech_length=0;
-+
-+ return SASL_OK;
-+}
-+
-+/*
-+ * parameters:
-+ * p - entry point
-+ */
-+int sasl_server_add_plugin(const char *plugname,
-+ sasl_server_plug_init_t *p)
-+{
-+ int plugcount;
-+ sasl_server_plug_t *pluglist;
-+ mechanism_t *mech;
-+ sasl_server_plug_init_t *entry_point;
-+ int result;
-+ int version;
-+ int lupe;
-+
-+ if(!plugname || !p) return SASL_BADPARAM;
-+
-+ entry_point = (sasl_server_plug_init_t *)p;
-+
-+ /* call into the shared library asking for information about it */
-+ /* version is filled in with the version of the plugin */
-+ result = entry_point(mechlist->utils, SASL_SERVER_PLUG_VERSION, &version,
-+ &pluglist, &plugcount);
-+
-+ if ((result != SASL_OK) && (result != SASL_NOUSER)) {
-+ _sasl_log(NULL, SASL_LOG_DEBUG,
-+ "server add_plugin entry_point error %z\n", result);
-+ return result;
-+ }
-+
-+ /* Make sure plugin is using the same SASL version as us */
-+ if (version != SASL_SERVER_PLUG_VERSION)
-+ {
-+ _sasl_log(NULL, SASL_LOG_ERR,
-+ "version mismatch on plugin");
-+ return SASL_BADVERS;
-+ }
-+
-+ for (lupe=0;lupe < plugcount ;lupe++)
-+ {
-+ mech = sasl_ALLOC(sizeof(mechanism_t));
-+ if (! mech) return SASL_NOMEM;
-+
-+ mech->plug=pluglist++;
-+ if(_sasl_strdup(plugname, &mech->plugname, NULL) != SASL_OK) {
-+ sasl_FREE(mech);
-+ return SASL_NOMEM;
-+ }
-+ mech->version = version;
-+
-+ /* wheather this mech actually has any users in it's db */
-+ mech->condition = result; /* SASL_OK or SASL_NOUSER */
-+
-+ mech->next = mechlist->mech_list;
-+ mechlist->mech_list = mech;
-+ mechlist->mech_length++;
-+ }
-+
-+ return SASL_OK;
-+}
-+
-+static void server_done(void) {
-+ mechanism_t *m;
-+ mechanism_t *prevm;
-+
-+ if (mechlist != NULL)
-+ {
-+ m=mechlist->mech_list; /* m point to beginning of the list */
-+
-+ while (m!=NULL)
-+ {
-+ prevm=m;
-+ m=m->next;
-+
-+ if (prevm->plug->mech_free) {
-+ prevm->plug->mech_free(prevm->plug->glob_context,
-+ mechlist->utils);
-+ }
-+
-+ sasl_FREE(prevm->plugname);
-+ sasl_FREE(prevm);
-+ }
-+ _sasl_free_utils(&mechlist->utils);
-+ sasl_MUTEX_FREE(mechlist->mutex);
-+ sasl_FREE(mechlist);
-+ mechlist = NULL;
-+ }
-+
-+ /* Free the auxprop plugins */
-+ _sasl_auxprop_free();
-+
-+ global_callbacks.callbacks = NULL;
-+ global_callbacks.appname = NULL;
-+
-+ /* no longer active. fail on listmech's etc. */
-+ _sasl_server_active = 0;
-+}
-+
-+static int
-+server_idle(sasl_conn_t *conn)
-+{
-+ mechanism_t *m;
-+ if (! mechlist)
-+ return 0;
-+
-+ for (m = mechlist->mech_list;
-+ m!=NULL;
-+ m = m->next)
-+ if (m->plug->idle
-+ && m->plug->idle(m->plug->glob_context,
-+ conn,
-+ conn ? ((sasl_server_conn_t *)conn)->sparams : NULL))
-+ return 1;
-+ return 0;
-+}
-+
-+static int load_config(const sasl_callback_t *verifyfile_cb)
-+{
-+ int result;
-+ const char *path_to_config=NULL;
-+ char *c;
-+ char *config_filename=NULL;
-+ int len;
-+ const sasl_callback_t *getpath_cb=NULL;
-+
-+ /* get the path to the plugins; for now the config file will reside there */
-+ getpath_cb=_sasl_find_getpath_callback( global_callbacks.callbacks );
-+ if (getpath_cb==NULL) return SASL_BADPARAM;
-+
-+ /* getpath_cb->proc MUST be a sasl_getpath_t; if only c had a type
-+ system */
-+ result = ((sasl_getpath_t *)(getpath_cb->proc))(getpath_cb->context,
-+ &path_to_config);
-+ if (result!=SASL_OK) goto done;
-+ if (path_to_config == NULL) path_to_config = "";
-+
-+ if ((c = strchr(path_to_config, PATHS_DELIMITER))) {
-+ *c = '\0';
-+ }
-+
-+ /* length = length of path + '/' + length of appname + ".conf" + 1
-+ for '\0' */
-+ len = strlen(path_to_config)+2+ strlen(global_callbacks.appname)+5+1;
-+
-+ if (len > PATH_MAX ) {
-+ result = SASL_FAIL;
-+ goto done;
-+ }
-+
-+ /* construct the filename for the config file */
-+ config_filename = sasl_ALLOC(len);
-+ if (! config_filename) {
-+ result = SASL_NOMEM;
-+ goto done;
-+ }
-+
-+ snprintf(config_filename, len, "%s/%s.conf", path_to_config,
-+ global_callbacks.appname);
-+
-+ /* Ask the application if it's safe to use this file */
-+ result = ((sasl_verifyfile_t *)(verifyfile_cb->proc))(verifyfile_cb->context,
-+ config_filename, SASL_VRFY_CONF);
-+
-+ /* returns continue if this file is to be skipped */
-+
-+ /* returns SASL_CONTINUE if doesn't exist
-+ * if doesn't exist we can continue using default behavior
-+ */
-+ if (result==SASL_OK)
-+ result=sasl_config_init(config_filename);
-+
-+ done:
-+ if (config_filename) sasl_FREE(config_filename);
-+
-+ return result;
-+}
-+
-+/*
-+ * Verify that all the callbacks are valid
-+ */
-+static int verify_server_callbacks(const sasl_callback_t *callbacks)
-+{
-+ if (callbacks == NULL) return SASL_OK;
-+
-+ while (callbacks->id != SASL_CB_LIST_END) {
-+ if (callbacks->proc==NULL) return SASL_FAIL;
-+
-+ callbacks++;
-+ }
-+
-+ return SASL_OK;
-+}
-+
-+static char *grab_field(char *line, char **eofield)
-+{
-+ int d = 0;
-+ char *field;
-+
-+ while (isspace((int) *line)) line++;
-+
-+ /* find end of field */
-+ while (line[d] && !isspace(((int) line[d]))) d++;
-+ field = sasl_ALLOC(d + 1);
-+ if (!field) { return NULL; }
-+ memcpy(field, line, d);
-+ field[d] = '\0';
-+ *eofield = line + d;
-+
-+ return field;
-+}
-+
-+struct secflag_map_s {
-+ char *name;
-+ int value;
-+};
-+
-+struct secflag_map_s secflag_map[] = {
-+ { "noplaintext", SASL_SEC_NOPLAINTEXT },
-+ { "noactive", SASL_SEC_NOACTIVE },
-+ { "nodictionary", SASL_SEC_NODICTIONARY },
-+ { "forward_secrecy", SASL_SEC_FORWARD_SECRECY },
-+ { "noanonymous", SASL_SEC_NOANONYMOUS },
-+ { "pass_credentials", SASL_SEC_PASS_CREDENTIALS },
-+ { "mutual_auth", SASL_SEC_MUTUAL_AUTH },
-+ { NULL, 0x0 }
-+};
-+
-+static int parse_mechlist_file(const char *mechlistfile)
-+{
-+ FILE *f;
-+ char buf[1024];
-+ char *t, *ptr;
-+ int r = 0;
-+
-+ f = fopen(mechlistfile, "r");
-+ if (!f) return SASL_FAIL;
-+
-+ r = SASL_OK;
-+ while (fgets(buf, sizeof(buf), f) != NULL) {
-+ mechanism_t *n = sasl_ALLOC(sizeof(mechanism_t));
-+ sasl_server_plug_t *nplug;
-+
-+ if (n == NULL) { r = SASL_NOMEM; break; }
-+ n->version = SASL_SERVER_PLUG_VERSION;
-+ n->condition = SASL_CONTINUE;
-+ nplug = sasl_ALLOC(sizeof(sasl_server_plug_t));
-+ if (nplug == NULL) { r = SASL_NOMEM; break; }
-+ memset(nplug, 0, sizeof(sasl_server_plug_t));
-+
-+ /* each line is:
-+ plugin-file WS mech_name WS max_ssf *(WS security_flag) RET
-+ */
-+
-+ /* grab file */
-+ n->f = grab_field(buf, &ptr);
-+
-+ /* grab mech_name */
-+ nplug->mech_name = grab_field(ptr, &ptr);
-+
-+ /* grab max_ssf */
-+ nplug->max_ssf = strtol(ptr, &ptr, 10);
-+
-+ /* grab security flags */
-+ while (*ptr != '\n') {
-+ struct secflag_map_s *map;
-+
-+ /* read security flag */
-+ t = grab_field(ptr, &ptr);
-+ map = secflag_map;
-+ while (map->name) {
-+ if (!strcasecmp(t, map->name)) {
-+ nplug->security_flags |= map->value;
-+ break;
-+ }
-+ map++;
-+ }
-+ if (!map->name) {
-+ _sasl_log(NULL, SASL_LOG_ERR,
-+ "%s: couldn't identify flag '%s'",
-+ nplug->mech_name, t);
-+ }
-+ free(t);
-+ }
-+
-+ /* insert mechanism into mechlist */
-+ n->plug = nplug;
-+ n->next = mechlist->mech_list;
-+ mechlist->mech_list = n;
-+ mechlist->mech_length++;
-+ }
-+
-+ fclose(f);
-+ return r;
-+}
-+
-+/* initialize server drivers, done once per process
-+ * callbacks -- callbacks for all server connections; must include
-+ * getopt callback
-+ * appname -- name of calling application (for lower level logging)
-+ * results:
-+ * state -- server state
-+ * returns:
-+ * SASL_OK -- success
-+ * SASL_BADPARAM -- error in config file
-+ * SASL_NOMEM -- memory failure
-+ * SASL_BADVERS -- Mechanism version mismatch
-+ */
-+
-+int sasl_server_init(const sasl_callback_t *callbacks,
-+ const char *appname)
-+{
-+ int ret;
-+ const sasl_callback_t *vf;
-+ const char *pluginfile = NULL;
-+#ifdef PIC
-+ sasl_getopt_t *getopt;
-+ void *context;
-+#endif
-+
-+ const add_plugin_list_t ep_list[] = {
-+ { "sasl_server_plug_init", (add_plugin_t *)sasl_server_add_plugin },
-+ { "sasl_auxprop_plug_init", (add_plugin_t *)sasl_auxprop_add_plugin },
-+ { "sasl_canonuser_init", (add_plugin_t *)sasl_canonuser_add_plugin },
-+ { NULL, NULL }
-+ };
-+
-+ /* we require the appname to be non-null */
-+ if (appname==NULL) return SASL_BADPARAM;
-+
-+ ret = _sasl_common_init();
-+ if (ret != SASL_OK)
-+ return ret;
-+
-+ _sasl_server_cleanup_hook = &server_done;
-+
-+ /* verify that the callbacks look ok */
-+ ret = verify_server_callbacks(callbacks);
-+ if (ret != SASL_OK) return ret;
-+
-+ global_callbacks.callbacks = callbacks;
-+ global_callbacks.appname = appname;
-+
-+ /* allocate mechlist and set it to empty */
-+ mechlist = sasl_ALLOC(sizeof(mech_list_t));
-+ if (mechlist == NULL) return SASL_NOMEM;
-+
-+ ret = init_mechlist();
-+ if (ret != SASL_OK) return ret;
-+
-+ vf = _sasl_find_verifyfile_callback(callbacks);
-+
-+ /* load config file if applicable */
-+ ret = load_config(vf);
-+ if ((ret != SASL_OK) && (ret != SASL_CONTINUE)) {
-+ return ret;
-+ }
-+
-+ /* load internal plugins */
-+ sasl_server_add_plugin("EXTERNAL", &external_server_plug_init);
-+
-+#ifdef PIC
-+ /* delayed loading of plugins? (DSO only, as it doesn't
-+ * make much [any] sense to delay in the static library case) */
-+ if (_sasl_getcallback(NULL, SASL_CB_GETOPT, &getopt, &context)
-+ == SASL_OK) {
-+ /* No sasl_conn_t was given to getcallback, so we provide the
-+ * global callbacks structure */
-+ ret = getopt(&global_callbacks, NULL, "plugin_list", &pluginfile, NULL);
-+ }
-+#endif
-+
-+ if (pluginfile != NULL) {
-+ /* this file should contain a list of plugins available.
-+ we'll load on demand. */
-+
-+ /* Ask the application if it's safe to use this file */
-+ ret = ((sasl_verifyfile_t *)(vf->proc))(vf->context,
-+ pluginfile,
-+ SASL_VRFY_CONF);
-+ if (ret != SASL_OK) {
-+ _sasl_log(NULL, SASL_LOG_ERR,
-+ "unable to load plugin list %s: %z", pluginfile, ret);
-+ }
-+
-+ if (ret == SASL_OK) {
-+ ret = parse_mechlist_file(pluginfile);
-+ }
-+ } else {
-+ /* load all plugins now */
-+ ret = _sasl_load_plugins(ep_list,
-+ _sasl_find_getpath_callback(callbacks),
-+ _sasl_find_verifyfile_callback(callbacks));
-+ }
-+
-+ if (ret == SASL_OK) {
-+ /* _sasl_server_active shows if we're active or not.
-+ server_done() sets it back to 0 */
-+ _sasl_server_active = 1;
-+ _sasl_server_idle_hook = &server_idle;
-+
-+ ret = _sasl_build_mechlist();
-+ }
-+
-+ return ret;
-+}
-+
-+/*
-+ * Once we have the users plaintext password we
-+ * may want to transition them. That is put entries
-+ * for them in the passwd database for other
-+ * stronger mechanism
-+ *
-+ * for example PLAIN -> CRAM-MD5
-+ */
-+static int
-+_sasl_transition(sasl_conn_t * conn,
-+ const char * pass,
-+ unsigned passlen)
-+{
-+ const char *dotrans = "n";
-+ sasl_getopt_t *getopt;
-+ int result = SASL_OK;
-+ void *context;
-+
-+ if (! conn)
-+ return SASL_BADPARAM;
-+
-+ if (! conn->oparams.authid)
-+ PARAMERROR(conn);
-+
-+ /* check if this is enabled: default to false */
-+ if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK)
-+ {
-+ getopt(context, NULL, "auto_transition", &dotrans, NULL);
-+ if (dotrans == NULL) dotrans = "n";
-+ }
-+
-+ if (*dotrans == '1' || *dotrans == 'y' ||
-+ (*dotrans == 'o' && dotrans[1] == 'n') || *dotrans == 't') {
-+ /* ok, it's on! */
-+ result = sasl_setpass(conn,
-+ conn->oparams.authid,
-+ pass,
-+ passlen,
-+ NULL, 0, 0);
-+ }
-+
-+ RETURN(conn,result);
-+}
-+
-+
-+/* create context for a single SASL connection
-+ * service -- registered name of the service using SASL (e.g. "imap")
-+ * serverFQDN -- Fully qualified domain name of server. NULL means use
-+ * gethostname() or equivalent.
-+ * Useful for multi-homed servers.
-+ * user_realm -- permits multiple user realms on server, NULL = default
-+ * iplocalport -- server IPv4/IPv6 domain literal string with port
-+ * (if NULL, then mechanisms requiring IPaddr are disabled)
-+ * ipremoteport -- client IPv4/IPv6 domain literal string with port
-+ * (if NULL, then mechanisms requiring IPaddr are disabled)
-+ * callbacks -- callbacks (e.g., authorization, lang, new getopt context)
-+ * flags -- usage flags (see above)
-+ * returns:
-+ * pconn -- new connection context
-+ *
-+ * returns:
-+ * SASL_OK -- success
-+ * SASL_NOMEM -- not enough memory
-+ */
-+
-+int sasl_server_new(const char *service,
-+ const char *serverFQDN,
-+ const char *user_realm,
-+ const char *iplocalport,
-+ const char *ipremoteport,
-+ const sasl_callback_t *callbacks,
-+ unsigned flags,
-+ sasl_conn_t **pconn)
-+{
-+ int result;
-+ sasl_server_conn_t *serverconn;
-+ sasl_utils_t *utils;
-+
-+ if (_sasl_server_active==0) return SASL_NOTINIT;
-+ if (! pconn) return SASL_FAIL;
-+ if (! service) return SASL_FAIL;
-+
-+ *pconn=sasl_ALLOC(sizeof(sasl_server_conn_t));
-+ if (*pconn==NULL) return SASL_NOMEM;
-+
-+ memset(*pconn, 0, sizeof(sasl_server_conn_t));
-+
-+ serverconn = (sasl_server_conn_t *)*pconn;
-+
-+ /* make sparams */
-+ serverconn->sparams=sasl_ALLOC(sizeof(sasl_server_params_t));
-+ if (serverconn->sparams==NULL)
-+ MEMERROR(*pconn);
-+
-+ memset(serverconn->sparams, 0, sizeof(sasl_server_params_t));
-+
-+ (*pconn)->destroy_conn = &server_dispose;
-+ result = _sasl_conn_init(*pconn, service, flags, SASL_CONN_SERVER,
-+ &server_idle, serverFQDN,
-+ iplocalport, ipremoteport,
-+ callbacks, &global_callbacks);
-+ if (result != SASL_OK)
-+ goto done_error;
-+
-+
-+ /* set util functions - need to do rest */
-+ utils=_sasl_alloc_utils(*pconn, &global_callbacks);
-+ if (!utils) {
-+ result = SASL_NOMEM;
-+ goto done_error;
-+ }
-+
-+ utils->checkpass = &sasl_checkpass;
-+
-+ /* Setup the propctx -> We'll assume the default size */
-+ serverconn->sparams->propctx=prop_new(0);
-+ if(!serverconn->sparams->propctx) {
-+ result = SASL_NOMEM;
-+ goto done_error;
-+ }
-+
-+ serverconn->sparams->service = (*pconn)->service;
-+ serverconn->sparams->servicelen = strlen((*pconn)->service);
-+
-+ serverconn->sparams->appname = global_callbacks.appname;
-+ serverconn->sparams->applen = strlen(global_callbacks.appname);
-+
-+ serverconn->sparams->serverFQDN = (*pconn)->serverFQDN;
-+ serverconn->sparams->slen = strlen((*pconn)->serverFQDN);
-+
-+ if (user_realm) {
-+ result = _sasl_strdup(user_realm, &serverconn->user_realm, NULL);
-+ serverconn->sparams->urlen = strlen(user_realm);
-+ serverconn->sparams->user_realm = serverconn->user_realm;
-+ } else {
-+ serverconn->user_realm = NULL;
-+ /* the sparams is already zeroed */
-+ }
-+
-+ serverconn->sparams->utils = utils;
-+ serverconn->sparams->transition = &_sasl_transition;
-+ serverconn->sparams->canon_user = &_sasl_canon_user;
-+ serverconn->sparams->props = serverconn->base.props;
-+ serverconn->sparams->flags = flags;
-+
-+ if(result == SASL_OK) return SASL_OK;
-+
-+ done_error:
-+ _sasl_conn_dispose(*pconn);
-+ sasl_FREE(*pconn);
-+ *pconn = NULL;
-+ return result;
-+}
-+
-+/*
-+ * The rule is:
-+ * IF mech strength + external strength < min ssf THEN FAIL
-+ * We also have to look at the security properties and make sure
-+ * that this mechanism has everything we want
-+ */
-+static int mech_permitted(sasl_conn_t *conn,
-+ mechanism_t *mech)
-+{
-+ sasl_server_conn_t *s_conn = (sasl_server_conn_t *)conn;
-+ const sasl_server_plug_t *plug;
-+ int myflags;
-+ context_list_t *cur;
-+ sasl_getopt_t *getopt;
-+ void *context;
-+ sasl_ssf_t minssf = 0;
-+
-+ if(!conn) return 0;
-+
-+ if(! mech || ! mech->plug) {
-+ PARAMERROR(conn);
-+ return 0;
-+ }
-+
-+ plug = mech->plug;
-+
-+ /* get the list of allowed mechanisms (default = all) */
-+ if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context)
-+ == SASL_OK) {
-+ const char *mlist;
-+
-+ getopt(context, NULL, "mech_list", &mlist, NULL);
-+
-+ /* if we have a list, check the plugin against it */
-+ if (mlist) {
-+ const char *cp;
-+
-+ while (*mlist) {
-+ for (cp = mlist; *cp && !isspace((int) *cp); cp++);
-+ if (((size_t) (cp - mlist) == strlen(plug->mech_name)) &&
-+ !strncasecmp(mlist, plug->mech_name,
-+ strlen(plug->mech_name))) {
-+ break;
-+ }
-+ mlist = cp;
-+ while (*mlist && isspace((int) *mlist)) mlist++;
-+ }
-+
-+ if (!*mlist) return 0; /* reached EOS -> not in our list */
-+ }
-+ }
-+
-+ /* setup parameters for the call to mech_avail */
-+ s_conn->sparams->serverFQDN=conn->serverFQDN;
-+ s_conn->sparams->service=conn->service;
-+ s_conn->sparams->user_realm=s_conn->user_realm;
-+ s_conn->sparams->props=conn->props;
-+ s_conn->sparams->external_ssf=conn->external.ssf;
-+
-+ /* Check if we have banished this one already */
-+ for(cur = s_conn->mech_contexts; cur; cur=cur->next) {
-+ if(cur->mech == mech) {
-+ /* If it's not mech_avail'd, then stop now */
-+ if(!cur->context) return 0;
-+ break;
-+ }
-+ }
-+
-+ if (!strcasecmp(plug->mech_name, "EXTERNAL")) {
-+ /* Special case for the external mechanism */
-+ if (conn->props.min_ssf > conn->external.ssf
-+ || ! conn->external.auth_id) {
-+ sasl_seterror(conn, SASL_NOLOG,
-+ "External SSF not good enough");
-+ return 0;
-+ }
-+ } else {
-+ if (conn->props.min_ssf < conn->external.ssf) {
-+ minssf = 0;
-+ } else {
-+ minssf = conn->props.min_ssf - conn->external.ssf;
-+ }
-+
-+ /* Generic mechanism */
-+ if (plug->max_ssf < minssf) {
-+ sasl_seterror(conn, SASL_NOLOG,
-+ "mech %s is too weak", plug->mech_name);
-+ return 0; /* too weak */
-+ }
-+
-+ }
-+
-+ context = NULL;
-+ if(plug->mech_avail
-+ && plug->mech_avail(plug->glob_context,
-+ s_conn->sparams, (void **)&context) != SASL_OK ) {
-+ /* Mark this mech as no good for this connection */
-+ cur = sasl_ALLOC(sizeof(context_list_t));
-+ if(!cur) {
-+ MEMERROR(conn);
-+ return 0;
-+ }
-+ cur->context = NULL;
-+ cur->mech = mech;
-+ cur->next = s_conn->mech_contexts;
-+ s_conn->mech_contexts = cur;
-+
-+ /* Error should be set by mech_avail call */
-+ return 0;
-+ } else if(context) {
-+ /* Save this context */
-+ cur = sasl_ALLOC(sizeof(context_list_t));
-+ if(!cur) {
-+ MEMERROR(conn);
-+ return 0;
-+ }
-+ cur->context = context;
-+ cur->mech = mech;
-+ cur->next = s_conn->mech_contexts;
-+ s_conn->mech_contexts = cur;
-+ }
-+
-+ /* Generic mechanism */
-+ if (plug->max_ssf < minssf) {
-+ sasl_seterror(conn, SASL_NOLOG, "too weak");
-+ return 0; /* too weak */
-+ }
-+
-+ /* if there are no users in the secrets database we can't use this
-+ mechanism */
-+ if (mech->condition == SASL_NOUSER) {
-+ sasl_seterror(conn, 0, "no users in secrets db");
-+ return 0;
-+ }
-+
-+ /* Can it meet our features? */
-+ if ((conn->flags & SASL_NEED_PROXY) &&
-+ !(plug->features & SASL_FEAT_ALLOWS_PROXY)) {
-+ return 0;
-+ }
-+
-+ /* security properties---if there are any flags that differ and are
-+ in what the connection are requesting, then fail */
-+
-+ /* special case plaintext */
-+ myflags = conn->props.security_flags;
-+
-+ /* if there's an external layer this is no longer plaintext */
-+ if ((conn->props.min_ssf <= conn->external.ssf) &&
-+ (conn->external.ssf > 1)) {
-+ myflags &= ~SASL_SEC_NOPLAINTEXT;
-+ }
-+
-+ /* do we want to special case SASL_SEC_PASS_CREDENTIALS? nah.. */
-+ if (((myflags ^ plug->security_flags) & myflags) != 0) {
-+ sasl_seterror(conn, SASL_NOLOG,
-+ "security flags do not match required");
-+ return 0;
-+ }
-+
-+ /* Check Features */
-+ if(plug->features & SASL_FEAT_GETSECRET) {
-+ /* We no longer support sasl_server_{get,put}secret */
-+ sasl_seterror(conn, 0,
-+ "mech %s requires unprovided secret facility",
-+ plug->mech_name);
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+/*
-+ * make the authorization
-+ *
-+ */
-+
-+static int do_authorization(sasl_server_conn_t *s_conn)
-+{
-+ int ret;
-+ sasl_authorize_t *authproc;
-+ void *auth_context;
-+
-+ /* now let's see if authname is allowed to proxy for username! */
-+
-+ /* check the proxy callback */
-+ if (_sasl_getcallback(&s_conn->base, SASL_CB_PROXY_POLICY,
-+ &authproc, &auth_context) != SASL_OK) {
-+ INTERROR(&s_conn->base, SASL_NOAUTHZ);
-+ }
-+
-+ ret = authproc(&(s_conn->base), auth_context,
-+ s_conn->base.oparams.user, s_conn->base.oparams.ulen,
-+ s_conn->base.oparams.authid, s_conn->base.oparams.alen,
-+ s_conn->user_realm,
-+ (s_conn->user_realm ? strlen(s_conn->user_realm) : 0),
-+ s_conn->sparams->propctx);
-+
-+ RETURN(&s_conn->base, ret);
-+}
-+
-+
-+/* start a mechanism exchange within a connection context
-+ * mech -- the mechanism name client requested
-+ * clientin -- client initial response (NUL terminated), NULL if empty
-+ * clientinlen -- length of initial response
-+ * serverout -- initial server challenge, NULL if done
-+ * (library handles freeing this string)
-+ * serveroutlen -- length of initial server challenge
-+ * output:
-+ * pconn -- the connection negotiation state on success
-+ *
-+ * Same returns as sasl_server_step() or
-+ * SASL_NOMECH if mechanism not available.
-+ */
-+int sasl_server_start(sasl_conn_t *conn,
-+ const char *mech,
-+ const char *clientin,
-+ unsigned clientinlen,
-+ const char **serverout,
-+ unsigned *serveroutlen)
-+{
-+ sasl_server_conn_t *s_conn=(sasl_server_conn_t *) conn;
-+ int result;
-+ context_list_t *cur, **prev;
-+ mechanism_t *m;
-+
-+ if (_sasl_server_active==0) return SASL_NOTINIT;
-+
-+ /* make sure mech is valid mechanism
-+ if not return appropriate error */
-+ m=mechlist->mech_list;
-+
-+ /* check parameters */
-+ if(!conn) return SASL_BADPARAM;
-+
-+ if (!mech || ((clientin==NULL) && (clientinlen>0)))
-+ PARAMERROR(conn);
-+
-+ if(serverout) *serverout = NULL;
-+ if(serveroutlen) *serveroutlen = 0;
-+
-+ while (m!=NULL)
-+ {
-+ if ( strcasecmp(mech,m->plug->mech_name)==0)
-+ {
-+ break;
-+ }
-+ m=m->next;
-+ }
-+
-+ if (m==NULL) {
-+ sasl_seterror(conn, 0, "Couldn't find mech %s", mech);
-+ result = SASL_NOMECH;
-+ goto done;
-+ }
-+
-+ /* Make sure that we're willing to use this mech */
-+ if (! mech_permitted(conn, m)) {
-+ result = SASL_NOMECH;
-+ goto done;
-+ }
-+
-+ if (m->condition == SASL_CONTINUE) {
-+ sasl_server_plug_init_t *entry_point;
-+ void *library = NULL;
-+ sasl_server_plug_t *pluglist;
-+ int version, plugcount;
-+ int l = 0;
-+
-+ /* need to load this plugin */
-+ result = _sasl_get_plugin(m->f,
-+ _sasl_find_verifyfile_callback(global_callbacks.callbacks),
-+ &library);
-+
-+ if (result == SASL_OK) {
-+ result = _sasl_locate_entry(library, "sasl_server_plug_init",
-+ (void **)&entry_point);
-+ }
-+
-+ if (result == SASL_OK) {
-+ result = entry_point(mechlist->utils, SASL_SERVER_PLUG_VERSION,
-+ &version, &pluglist, &plugcount);
-+ }
-+
-+ if (result == SASL_OK) {
-+ /* find the correct mechanism in this plugin */
-+ for (l = 0; l < plugcount; l++) {
-+ if (!strcasecmp(pluglist[l].mech_name,
-+ m->plug->mech_name)) break;
-+ }
-+ if (l == plugcount) {
-+ result = SASL_NOMECH;
-+ }
-+ }
-+ if (result == SASL_OK) {
-+ /* check that the parameters are the same */
-+ if ((pluglist[l].max_ssf != m->plug->max_ssf) ||
-+ (pluglist[l].security_flags != m->plug->security_flags)) {
-+ _sasl_log(conn, SASL_LOG_ERR,
-+ "%s: security parameters don't match mechlist file",
-+ pluglist[l].mech_name);
-+ result = SASL_NOMECH;
-+ }
-+ }
-+ if (result == SASL_OK) {
-+ /* copy mechlist over */
-+ sasl_FREE((sasl_server_plug_t *) m->plug);
-+ m->plug = &pluglist[l];
-+ m->condition = SASL_OK;
-+ }
-+
-+ if (result != SASL_OK) {
-+ /* The library will eventually be freed, don't sweat it */
-+ RETURN(conn, result);
-+ }
-+ }
-+
-+ /* We used to setup sparams HERE, but now it's done
-+ inside of mech_permitted (which is called above) */
-+ prev = &s_conn->mech_contexts;
-+ for(cur = *prev; cur; prev=&cur->next,cur=cur->next) {
-+ if(cur->mech == m) {
-+ if(!cur->context) {
-+ sasl_seterror(conn, 0,
-+ "Got past mech_permitted with a disallowed mech!");
-+ return SASL_NOMECH;
-+ }
-+ /* If we find it, we need to pull cur out of the
-+ list so it won't be freed later! */
-+ (*prev)->next = cur->next;
-+ conn->context = cur->context;
-+ sasl_FREE(cur);
-+ }
-+ }
-+
-+ s_conn->mech = m;
-+
-+ if(!conn->context) {
-+ /* Note that we don't hand over a new challenge */
-+ result = s_conn->mech->plug->mech_new(s_conn->mech->plug->glob_context,
-+ s_conn->sparams,
-+ NULL,
-+ 0,
-+ &(conn->context));
-+ } else {
-+ /* the work was already done by mech_avail! */
-+ result = SASL_OK;
-+ }
-+
-+ if (result == SASL_OK) {
-+ if(clientin) {
-+ if(s_conn->mech->plug->features & SASL_FEAT_SERVER_FIRST) {
-+ /* Remote sent first, but mechanism does not support it.
-+ * RFC 2222 says we fail at this point. */
-+ sasl_seterror(conn, 0,
-+ "Remote sent first but mech does not allow it.");
-+ result = SASL_BADPROT;
-+ } else {
-+ /* Mech wants client-first, so let them have it */
-+ result = sasl_server_step(conn,
-+ clientin, clientinlen,
-+ serverout, serveroutlen);
-+ }
-+ } else {
-+ if(s_conn->mech->plug->features & SASL_FEAT_WANT_CLIENT_FIRST) {
-+ /* Mech wants client first anyway, so we should do that */
-+ *serverout = "";
-+ *serveroutlen = 0;
-+ result = SASL_CONTINUE;
-+ } else {
-+ /* Mech wants server-first, so let them have it */
-+ result = sasl_server_step(conn,
-+ clientin, clientinlen,
-+ serverout, serveroutlen);
-+ }
-+ }
-+ }
-+
-+ done:
-+ if( result != SASL_OK
-+ && result != SASL_CONTINUE
-+ && result != SASL_INTERACT) {
-+ if(conn->context) {
-+ s_conn->mech->plug->mech_dispose(conn->context,
-+ s_conn->sparams->utils);
-+ conn->context = NULL;
-+ }
-+ }
-+
-+ RETURN(conn,result);
-+}
-+
-+
-+/* perform one step of the SASL exchange
-+ * inputlen & input -- client data
-+ * NULL on first step if no optional client step
-+ * outputlen & output -- set to the server data to transmit
-+ * to the client in the next step
-+ * (library handles freeing this)
-+ *
-+ * returns:
-+ * SASL_OK -- exchange is complete.
-+ * SASL_CONTINUE -- indicates another step is necessary.
-+ * SASL_TRANS -- entry for user exists, but not for mechanism
-+ * and transition is possible
-+ * SASL_BADPARAM -- service name needed
-+ * SASL_BADPROT -- invalid input from client
-+ * ...
-+ */
-+
-+int sasl_server_step(sasl_conn_t *conn,
-+ const char *clientin,
-+ unsigned clientinlen,
-+ const char **serverout,
-+ unsigned *serveroutlen)
-+{
-+ int ret;
-+ sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn; /* cast */
-+
-+ /* check parameters */
-+ if (_sasl_server_active==0) return SASL_NOTINIT;
-+ if (!conn) return SASL_BADPARAM;
-+ if ((clientin==NULL) && (clientinlen>0))
-+ PARAMERROR(conn);
-+
-+ /* If we've already done the last send, return! */
-+ if(s_conn->sent_last == 1) {
-+ return SASL_OK;
-+ }
-+
-+ /* Don't do another step if the plugin told us that we're done */
-+ if (conn->oparams.doneflag) {
-+ _sasl_log(conn, SASL_LOG_ERR, "attempting server step after doneflag");
-+ return SASL_FAIL;
-+ }
-+
-+ if(serverout) *serverout = NULL;
-+ if(serveroutlen) *serveroutlen = 0;
-+
-+ ret = s_conn->mech->plug->mech_step(conn->context,
-+ s_conn->sparams,
-+ clientin,
-+ clientinlen,
-+ serverout,
-+ serveroutlen,
-+ &conn->oparams);
-+
-+ if (ret == SASL_OK) {
-+ ret = do_authorization(s_conn);
-+ }
-+
-+ if (ret == SASL_OK) {
-+ /* if we're done, we need to watch out for the following:
-+ * 1. the mech does server-send-last
-+ * 2. the protocol does not
-+ *
-+ * in this case, return SASL_CONTINUE and remember we are done.
-+ */
-+ if(*serverout && !(conn->flags & SASL_SUCCESS_DATA)) {
-+ s_conn->sent_last = 1;
-+ ret = SASL_CONTINUE;
-+ }
-+ if(!conn->oparams.maxoutbuf) {
-+ conn->oparams.maxoutbuf = conn->props.maxbufsize;
-+ }
-+
-+ if(conn->oparams.user == NULL || conn->oparams.authid == NULL) {
-+ sasl_seterror(conn, 0,
-+ "mech did not call canon_user for both authzid " \
-+ "and authid");
-+ ret = SASL_BADPROT;
-+ }
-+ }
-+
-+ if( ret != SASL_OK
-+ && ret != SASL_CONTINUE
-+ && ret != SASL_INTERACT) {
-+ if(conn->context) {
-+ s_conn->mech->plug->mech_dispose(conn->context,
-+ s_conn->sparams->utils);
-+ conn->context = NULL;
-+ }
-+ }
-+
-+ RETURN(conn, ret);
-+}
-+
-+/* returns the length of all the mechanisms
-+ * added up
-+ */
-+
-+static unsigned mech_names_len()
-+{
-+ mechanism_t *listptr;
-+ unsigned result = 0;
-+
-+ for (listptr = mechlist->mech_list;
-+ listptr;
-+ listptr = listptr->next)
-+ result += strlen(listptr->plug->mech_name);
-+
-+ return result;
-+}
-+
-+/* This returns a list of mechanisms in a NUL-terminated string
-+ *
-+ * The default behavior is to seperate with spaces if sep==NULL
-+ */
-+int _sasl_server_listmech(sasl_conn_t *conn,
-+ const char *user __attribute__((unused)),
-+ const char *prefix,
-+ const char *sep,
-+ const char *suffix,
-+ const char **result,
-+ unsigned *plen,
-+ int *pcount)
-+{
-+ int lup;
-+ mechanism_t *listptr;
-+ int ret;
-+ int resultlen;
-+ int flag;
-+ const char *mysep;
-+
-+ /* if there hasn't been a sasl_sever_init() fail */
-+ if (_sasl_server_active==0) return SASL_NOTINIT;
-+ if (!conn) return SASL_BADPARAM;
-+ if (conn->type != SASL_CONN_SERVER) PARAMERROR(conn);
-+
-+ if (! result)
-+ PARAMERROR(conn);
-+
-+ if (plen != NULL)
-+ *plen = 0;
-+ if (pcount != NULL)
-+ *pcount = 0;
-+
-+ if (sep) {
-+ mysep = sep;
-+ } else {
-+ mysep = " ";
-+ }
-+
-+ if (! mechlist || mechlist->mech_length <= 0)
-+ INTERROR(conn, SASL_NOMECH);
-+
-+ resultlen = (prefix ? strlen(prefix) : 0)
-+ + (strlen(mysep) * (mechlist->mech_length - 1))
-+ + mech_names_len()
-+ + (suffix ? strlen(suffix) : 0)
-+ + 1;
-+ ret = _buf_alloc(&conn->mechlist_buf,
-+ &conn->mechlist_buf_len, resultlen);
-+ if(ret != SASL_OK) MEMERROR(conn);
-+
-+ if (prefix)
-+ strcpy (conn->mechlist_buf,prefix);
-+ else
-+ *(conn->mechlist_buf) = '\0';
-+
-+ listptr = mechlist->mech_list;
-+
-+ flag = 0;
-+ /* make list */
-+ for (lup = 0; lup < mechlist->mech_length; lup++) {
-+ /* currently, we don't use the "user" parameter for anything */
-+ if (mech_permitted(conn, listptr)) {
-+ if (pcount != NULL)
-+ (*pcount)++;
-+
-+ /* print seperator */
-+ if (flag) {
-+ strcat(conn->mechlist_buf, mysep);
-+ } else {
-+ flag = 1;
-+ }
-+
-+ /* now print the mechanism name */
-+ strcat(conn->mechlist_buf, listptr->plug->mech_name);
-+ }
-+
-+ listptr = listptr->next;
-+ }
-+
-+ if (suffix)
-+ strcat(conn->mechlist_buf,suffix);
-+
-+ if (plen!=NULL)
-+ *plen=strlen(conn->mechlist_buf);
-+
-+ *result = conn->mechlist_buf;
-+
-+ return SASL_OK;
-+
-+}
-+
-+sasl_string_list_t *_sasl_server_mechs(void)
-+{
-+ mechanism_t *listptr;
-+ sasl_string_list_t *retval = NULL, *next=NULL;
-+
-+ if(!_sasl_server_active) return NULL;
-+
-+ /* make list */
-+ for (listptr = mechlist->mech_list; listptr; listptr = listptr->next) {
-+ next = sasl_ALLOC(sizeof(sasl_string_list_t));
-+
-+ if(!next && !retval) return NULL;
-+ else if(!next) {
-+ next = retval->next;
-+ do {
-+ sasl_FREE(retval);
-+ retval = next;
-+ next = retval->next;
-+ } while(next);
-+ return NULL;
-+ }
-+
-+ next->d = listptr->plug->mech_name;
-+
-+ if(!retval) {
-+ next->next = NULL;
-+ retval = next;
-+ } else {
-+ next->next = retval;
-+ retval = next;
-+ }
-+ }
-+
-+ return retval;
-+}
-+
-+#define EOSTR(s,n) (((s)[n] == '\0') || ((s)[n] == ' ') || ((s)[n] == '\t'))
-+static int is_mech(const char *t, const char *m)
-+{
-+ int sl = strlen(m);
-+ return ((!strncasecmp(m, t, sl)) && EOSTR(t, sl));
-+}
-+
-+/* returns OK if it's valid */
-+static int _sasl_checkpass(sasl_conn_t *conn, const char *service,
-+ const char *user, const char *pass)
-+{
-+ sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn;
-+ int result;
-+ sasl_getopt_t *getopt;
-+ sasl_server_userdb_checkpass_t *checkpass_cb;
-+ void *context;
-+ const char *mlist, *mech;
-+ struct sasl_verify_password_s *v;
-+
-+ /* call userdb callback function, if available */
-+ result = _sasl_getcallback(conn, SASL_CB_SERVER_USERDB_CHECKPASS,
-+ &checkpass_cb, &context);
-+ if(result == SASL_OK && checkpass_cb) {
-+ result = checkpass_cb(conn, context, user, pass, strlen(pass),
-+ s_conn->sparams->propctx);
-+ if(result == SASL_OK)
-+ return SASL_OK;
-+ }
-+
-+ /* figure out how to check (i.e. auxprop or saslauthd or pwcheck) */
-+ if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context)
-+ == SASL_OK) {
-+ getopt(context, NULL, "pwcheck_method", &mlist, NULL);
-+ }
-+
-+ if(!mlist) mlist = DEFAULT_CHECKPASS_MECH;
-+
-+ result = SASL_NOMECH;
-+
-+ mech = mlist;
-+ while (*mech && result != SASL_OK) {
-+ for (v = _sasl_verify_password; v->name; v++) {
-+ if(is_mech(mech, v->name)) {
-+ result = v->verify(conn, user, pass, service,
-+ s_conn->user_realm);
-+ break;
-+ }
-+ }
-+ if (result != SASL_OK) {
-+ /* skip to next mech in list */
-+ while (*mech && !isspace((int) *mech)) mech++;
-+ while (*mech && isspace((int) *mech)) mech++;
-+ }
-+ }
-+
-+ if (result == SASL_NOMECH) {
-+ /* no mechanism available ?!? */
-+ _sasl_log(conn, SASL_LOG_ERR, "unknown password verifier %s", mech);
-+ }
-+
-+ if (result != SASL_OK)
-+ sasl_seterror(conn, SASL_NOLOG, "checkpass failed");
-+
-+ RETURN(conn, result);
-+}
-+
-+/* check if a plaintext password is valid
-+ * if user is NULL, check if plaintext passwords are enabled
-+ * inputs:
-+ * user -- user to query in current user_domain
-+ * userlen -- length of username, 0 = strlen(user)
-+ * pass -- plaintext password to check
-+ * passlen -- length of password, 0 = strlen(pass)
-+ * returns
-+ * SASL_OK -- success
-+ * SASL_NOMECH -- mechanism not supported
-+ * SASL_NOVERIFY -- user found, but no verifier
-+ * SASL_NOUSER -- user not found
-+ */
-+int sasl_checkpass(sasl_conn_t *conn,
-+ const char *user,
-+ unsigned userlen __attribute__((unused)),
-+ const char *pass,
-+ unsigned passlen)
-+{
-+ int result;
-+
-+ if (_sasl_server_active==0) return SASL_NOTINIT;
-+
-+ /* check if it's just a query if we are enabled */
-+ if (!user)
-+ return SASL_OK;
-+
-+ if (!conn) return SASL_BADPARAM;
-+
-+ /* check params */
-+ if (pass == NULL)
-+ PARAMERROR(conn);
-+
-+ result = _sasl_checkpass(conn, conn->service, user, pass);
-+
-+ if (result == SASL_OK) {
-+ strncpy(conn->authid_buf, user, CANON_BUF_SIZE);
-+ conn->oparams.authid = conn->authid_buf;
-+
-+ result = _sasl_transition(conn, pass, passlen);
-+ }
-+
-+ RETURN(conn,result);
-+}
-+
-+/* check if a user exists on server
-+ * conn -- connection context (may be NULL, used to hold last error)
-+ * service -- registered name of the service using SASL (e.g. "imap")
-+ * user_realm -- permits multiple user realms on server, NULL = default
-+ * user -- NUL terminated user name
-+ *
-+ * returns:
-+ * SASL_OK -- success
-+ * SASL_DISABLED -- account disabled [FIXME: currently not detected]
-+ * SASL_NOUSER -- user not found
-+ * SASL_NOVERIFY -- user found, but no usable mechanism [FIXME: not supported]
-+ * SASL_NOMECH -- no mechanisms enabled
-+ */
-+int sasl_user_exists(sasl_conn_t *conn,
-+ const char *service,
-+ const char *user_realm,
-+ const char *user)
-+{
-+ int result=SASL_NOMECH;
-+ const char *mlist, *mech;
-+ void *context;
-+ sasl_getopt_t *getopt;
-+ struct sasl_verify_password_s *v;
-+
-+ /* check params */
-+ if (_sasl_server_active==0) return SASL_NOTINIT;
-+ if (!conn) return SASL_BADPARAM;
-+ if (!user || conn->type != SASL_CONN_SERVER)
-+ PARAMERROR(conn);
-+
-+ if(!service) service = conn->service;
-+
-+ /* figure out how to check (i.e. auxprop or saslauthd or pwcheck) */
-+ if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context)
-+ == SASL_OK) {
-+ getopt(context, NULL, "pwcheck_method", &mlist, NULL);
-+ }
-+
-+ if(!mlist) mlist = DEFAULT_CHECKPASS_MECH;
-+
-+ result = SASL_NOMECH;
-+
-+ mech = mlist;
-+ while (*mech && result != SASL_OK) {
-+ for (v = _sasl_verify_password; v->name; v++) {
-+ if(is_mech(mech, v->name)) {
-+ result = v->verify(conn, user, NULL, service, user_realm);
-+ break;
-+ }
-+ }
-+ if (result != SASL_OK) {
-+ /* skip to next mech in list */
-+ while (*mech && !isspace((int) *mech)) mech++;
-+ while (*mech && isspace((int) *mech)) mech++;
-+ }
-+ }
-+
-+ /* Screen out the SASL_BADPARAM response
-+ * we'll get from not giving a password */
-+ if(result == SASL_BADPARAM) {
-+ result = SASL_OK;
-+ }
-+
-+ if (result == SASL_NOMECH) {
-+ /* no mechanism available ?!? */
-+ _sasl_log(conn, SASL_LOG_ERR, "no plaintext password verifier?");
-+ sasl_seterror(conn, SASL_NOLOG, "no plaintext password verifier?");
-+ }
-+
-+ RETURN(conn, result);
-+}
-+
-+/* check if an apop exchange is valid
-+ * (note this is an optional part of the SASL API)
-+ * if challenge is NULL, just check if APOP is enabled
-+ * inputs:
-+ * challenge -- challenge which was sent to client
-+ * challen -- length of challenge, 0 = strlen(challenge)
-+ * response -- client response, "<user> <digest>" (RFC 1939)
-+ * resplen -- length of response, 0 = strlen(response)
-+ * returns
-+ * SASL_OK -- success
-+ * SASL_BADAUTH -- authentication failed
-+ * SASL_BADPARAM -- missing challenge
-+ * SASL_BADPROT -- protocol error (e.g., response in wrong format)
-+ * SASL_NOVERIFY -- user found, but no verifier
-+ * SASL_NOMECH -- mechanism not supported
-+ * SASL_NOUSER -- user not found
-+ */
-+int sasl_checkapop(sasl_conn_t *conn,
-+#ifdef DO_SASL_CHECKAPOP
-+ const char *challenge,
-+ unsigned challen __attribute__((unused)),
-+ const char *response,
-+ unsigned resplen __attribute__((unused)))
-+#else
-+ const char *challenge __attribute__((unused)),
-+ unsigned challen __attribute__((unused)),
-+ const char *response __attribute__((unused)),
-+ unsigned resplen __attribute__((unused)))
-+#endif
-+{
-+#ifdef DO_SASL_CHECKAPOP
-+ sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn;
-+ char *user, *user_end;
-+ const char *password_request[] = { SASL_AUX_PASSWORD, NULL };
-+ size_t user_len;
-+ int result;
-+
-+ if (_sasl_server_active==0)
-+ return SASL_NOTINIT;
-+
-+ /* check if it's just a query if we are enabled */
-+ if(!challenge)
-+ return SASL_OK;
-+
-+ /* check params */
-+ if (!conn) return SASL_BADPARAM;
-+ if (!response)
-+ PARAMERROR(conn);
-+
-+ /* Parse out username and digest.
-+ *
-+ * Per RFC 1939, response must be "<user> <digest>", where
-+ * <digest> is a 16-octet value which is sent in hexadecimal
-+ * format, using lower-case ASCII characters.
-+ */
-+ user_end = strrchr(response, ' ');
-+ if (!user_end || strspn(user_end + 1, "0123456789abcdef") != 32)
-+ {
-+ sasl_seterror(conn, 0, "Bad Digest");
-+ RETURN(conn,SASL_BADPROT);
-+ }
-+
-+ user_len = (size_t)(user_end - response);
-+ user = sasl_ALLOC(user_len + 1);
-+ memcpy(user, response, user_len);
-+ user[user_len] = '\0';
-+
-+ result = prop_request(s_conn->sparams->propctx, password_request);
-+ if(result != SASL_OK)
-+ {
-+ sasl_FREE(user);
-+ RETURN(conn, result);
-+ }
-+
-+ /* Cannonify it */
-+ result = _sasl_canon_user(conn, user, user_len,
-+ SASL_CU_AUTHID | SASL_CU_AUTHZID,
-+ &(conn->oparams));
-+ sasl_FREE(user);
-+
-+ if(result != SASL_OK) RETURN(conn, result);
-+
-+ /* Do APOP verification */
-+ result = _sasl_auxprop_verify_apop(conn, conn->oparams.authid,
-+ challenge, user_end + 1, s_conn->user_realm);
-+
-+ /* If verification failed, we don't want to encourage getprop to work */
-+ if(result != SASL_OK) {
-+ conn->oparams.user = NULL;
-+ conn->oparams.authid = NULL;
-+ }
+diff -durN cyrus-sasl-2.1.10.orig/lib/saslint.h cyrus-sasl-2.1.10/lib/saslint.h
+--- cyrus-sasl-2.1.10.orig/lib/saslint.h Thu Dec 5 05:16:59 2002
++++ cyrus-sasl-2.1.10/lib/saslint.h Thu Jan 9 11:42:29 2003
+@@ -356,6 +356,9 @@
+ _sasl_find_getpath_callback(const sasl_callback_t *callbacks);
+
+ extern const sasl_callback_t *
++_sasl_find_getconfpath_callback(const sasl_callback_t *callbacks);
+
-+ RETURN(conn, result);
-+#else /* sasl_checkapop was disabled at compile time */
-+ sasl_seterror(conn, SASL_NOLOG,
-+ "sasl_checkapop called, but was disabled at compile time");
-+ RETURN(conn, SASL_NOMECH);
-+#endif /* DO_SASL_CHECKAPOP */
-+}
-+
++extern const sasl_callback_t *
+ _sasl_find_verifyfile_callback(const sasl_callback_t *callbacks);
+
+ extern int _sasl_common_init(void);
+diff -durN cyrus-sasl-2.1.10.orig/lib/server.c cyrus-sasl-2.1.10/lib/server.c
+--- cyrus-sasl-2.1.10.orig/lib/server.c Thu Dec 5 05:16:59 2002
++++ cyrus-sasl-2.1.10/lib/server.c Thu Jan 9 11:42:29 2003
+@@ -379,15 +379,15 @@
+ char *c;
+ char *config_filename=NULL;
+ int len;
+- const sasl_callback_t *getpath_cb=NULL;
++ const sasl_callback_t *getconfpath_cb=NULL;
+
+ /* get the path to the plugins; for now the config file will reside there */
+- getpath_cb=_sasl_find_getpath_callback( global_callbacks.callbacks );
+- if (getpath_cb==NULL) return SASL_BADPARAM;
++ getconfpath_cb=_sasl_find_getconfpath_callback( global_callbacks.callbacks );
++ if (getconfpath_cb==NULL) return SASL_BADPARAM;
+
+- /* getpath_cb->proc MUST be a sasl_getpath_t; if only c had a type
++ /* getconfpath_cb->proc MUST be a sasl_getconfpath_t; if only c had a type
+ system */
+- result = ((sasl_getpath_t *)(getpath_cb->proc))(getpath_cb->context,
++ result = ((sasl_getconfpath_t *)(getconfpath_cb->proc))(getconfpath_cb->context,
+ &path_to_config);
+ if (result!=SASL_OK) goto done;
+ if (path_to_config == NULL) path_to_config = "";
diff -durN cyrus-sasl-2.1.10.orig/man/sasl_getconfpath_t.3 cyrus-sasl-2.1.10/man/sasl_getconfpath_t.3
--- cyrus-sasl-2.1.10.orig/man/sasl_getconfpath_t.3 Thu Jan 1 01:00:00 1970
+++ cyrus-sasl-2.1.10/man/sasl_getconfpath_t.3 Thu Jan 9 11:42:29 2003