[Pkg-cyrus-sasl2-commits] r78 - /cyrus-sasl-2.1/trunk/debian/patches/0008_one_time_sasl_set_alloc.dpatch

el_cubano-guest at users.alioth.debian.org el_cubano-guest at users.alioth.debian.org
Fri Oct 20 06:57:31 UTC 2006


Author: el_cubano-guest
Date: Fri Oct 20 01:03:24 2006
New Revision: 78

URL: http://svn.debian.org/wsvn/pkg-cyrus-sasl2/?sc=1&rev=78
Log:
Patch from Andreas to fix file getting clobbered during build

Modified:
    cyrus-sasl-2.1/trunk/debian/patches/0008_one_time_sasl_set_alloc.dpatch

Modified: cyrus-sasl-2.1/trunk/debian/patches/0008_one_time_sasl_set_alloc.dpatch
URL: http://svn.debian.org/wsvn/pkg-cyrus-sasl2/cyrus-sasl-2.1/trunk/debian/patches/0008_one_time_sasl_set_alloc.dpatch?rev=78&op=diff
==============================================================================
--- cyrus-sasl-2.1/trunk/debian/patches/0008_one_time_sasl_set_alloc.dpatch (original)
+++ cyrus-sasl-2.1/trunk/debian/patches/0008_one_time_sasl_set_alloc.dpatch Fri Oct 20 01:03:24 2006
@@ -75,2132 +75,3 @@
      /* we require the appname (if present) to be short enough to be a path */
      if (appname != NULL && strlen(appname) >= PATH_MAX)
  	return SASL_BADPARAM;
-diff -urNad trunk~/lib/server.c.orig trunk/lib/server.c.orig
---- trunk~/lib/server.c.orig	1970-01-01 02:00:00.000000000 +0200
-+++ trunk/lib/server.c.orig	2006-05-29 22:52:46.000000000 +0300
-@@ -0,0 +1,2125 @@
-+/* SASL server API implementation
-+ * Rob Siemborski
-+ * Tim Martin
-+ * $Id: server.c,v 1.146 2006/04/26 17:45:53 murch Exp $
-+ */
-+/* 
-+ * Copyright (c) 1998-2003 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 at 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 *user, unsigned userlen,
-+			   const char *pass, unsigned passlen);
-+
-+static mech_list_t *mechlist = NULL; /* global var which holds the list */
-+
-+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;
-+    const char *password_request[] = { SASL_AUX_PASSWORD_PROP, NULL };
-+    sasl_server_userdb_setpass_t *setpass_cb = NULL;
-+    void *context = NULL;
-+    int tried_setpass = 0;
-+    mechanism_t *sm;
-+    server_sasl_mechanism_t *m;
-+    char *current_mech;
-+     
-+    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);
-+
-+    /* Check that we have an active SASL mechanism */
-+    if (sasl_getprop (conn,
-+		      SASL_MECHNAME,
-+		      (const void **) &current_mech) != SASL_OK) {
-+	current_mech = NULL;
-+    }
-+
-+    if ( (flags & SASL_SET_CURMECH_ONLY) &&
-+	 (current_mech == NULL) ) {
-+	sasl_seterror( conn, SASL_NOLOG,
-+                  "No current SASL mechanism available");
-+	RETURN(conn, SASL_BADPARAM);
-+    }
-+
-+    /* Do we want to store SASL_AUX_PASSWORD_PROP (plain text)?  and
-+     * Do we have an auxprop backend that can store properties?
-+     */
-+    if ((flags & SASL_SET_DISABLE || !(flags & SASL_SET_NOPLAIN)) &&
-+	sasl_auxprop_store(NULL, NULL, NULL) == SASL_OK) {
-+
-+	tried_setpass++;
-+
-+	if (flags & SASL_SET_DISABLE) {
-+	    pass = NULL;
-+	    passlen = 0;
-+	}
-+
-+	result = prop_request(s_conn->sparams->propctx, password_request);
-+	if (result == SASL_OK) {
-+	    result = prop_set(s_conn->sparams->propctx, SASL_AUX_PASSWORD_PROP,
-+			      pass, passlen);
-+	}
-+	if (result == SASL_OK) {
-+	    result = sasl_auxprop_store(conn, s_conn->sparams->propctx, user);
-+	}
-+	if (result != SASL_OK) {
-+	    _sasl_log(conn, SASL_LOG_ERR,
-+		      "setpass failed for %s: %z",
-+		      user, result);
-+	} else {
-+	    _sasl_log(conn, SASL_LOG_NOTE,
-+		      "setpass succeeded for %s", user);
-+	}
-+    }
-+
-+    /* We want to preserve the current value of result, so we use tmpresult below */
-+
-+    /* call userdb callback function */
-+    tmpresult = _sasl_getcallback(conn, SASL_CB_SERVER_USERDB_SETPASS,
-+			       &setpass_cb, &context);
-+    if (tmpresult == SASL_OK && setpass_cb) {
-+
-+	tried_setpass++;
-+
-+	tmpresult = setpass_cb(conn, context, user, pass, passlen,
-+			    s_conn->sparams->propctx, flags);
-+	if(tmpresult != SASL_OK) {
-+	    result = tmpresult;
-+	    _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);
-+	}
-+    }
-+
-+    /* now we let the mechanisms set their secrets */
-+    for (sm = mechlist->mech_list; sm; sm = sm->next) {
-+	m = &sm->m;
-+
-+	if (!m->plug->setpass) {
-+	    /* can't set pass for this mech */
-+	    continue;
-+	}
-+
-+	/* Invoke only one setpass for the currently selected mechanism,
-+	   if SASL_SET_CURMECH_ONLY is specified */
-+	if ((flags & SASL_SET_CURMECH_ONLY) &&
-+	    (strcmp(current_mech, m->plug->mech_name) != 0)) {
-+	    continue;
-+	}
-+
-+	tried_setpass++;
-+
-+	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
-+		      );
-+	}
-+    }
-+
-+    if (!tried_setpass) {
-+	_sasl_log(conn, SASL_LOG_WARN,
-+		  "secret not changed for %s: "
-+		  "no writable auxprop plugin or setpass callback found",
-+		  user);
-+    }
-+
-+    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->m.plug->mech_dispose) {
-+    s_conn->mech->m.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->m.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->appname)
-+      sasl_FREE(s_conn->appname);
-+
-+  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)
-+        && (result != SASL_CONTINUE)) {
-+	_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;
-+        memset (mech, 0, sizeof(mechanism_t));
-+
-+	mech->m.plug = pluglist++;
-+	if(_sasl_strdup(plugname, &mech->m.plugname, NULL) != SASL_OK) {
-+	    sasl_FREE(mech);
-+	    return SASL_NOMEM;
-+	}
-+	mech->m.version = version;
-+
-+	/* wheather this mech actually has any users in it's db */
-+	mech->m.condition = result; /* SASL_OK, SASL_CONTINUE or SASL_NOUSER */
-+
-+        /* mech->m.f = NULL; */
-+
-+	mech->next = mechlist->mech_list;
-+	mechlist->mech_list = mech;
-+	mechlist->mech_length++;
-+    }
-+
-+    return SASL_OK;
-+}
-+
-+static int server_done(void) {
-+  mechanism_t *m;
-+  mechanism_t *prevm;
-+
-+  if(_sasl_server_active == 0)
-+      return SASL_NOTINIT;
-+  else
-+      _sasl_server_active--;
-+  
-+  if(_sasl_server_active) {
-+      /* Don't de-init yet! Our refcount is nonzero. */
-+      return SASL_CONTINUE;
-+  }
-+
-+  if (mechlist != NULL)
-+  {
-+      m=mechlist->mech_list; /* m point to beginning of the list */
-+
-+      while (m!=NULL)
-+      {
-+	  prevm=m;
-+	  m=m->next;
-+    
-+	  if (prevm->m.plug->mech_free) {
-+	      prevm->m.plug->mech_free(prevm->m.plug->glob_context,
-+				     mechlist->utils);
-+	  }
-+
-+	  sasl_FREE(prevm->m.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;
-+
-+  return SASL_OK;
-+}
-+
-+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->m.plug->idle
-+	    &&  m->m.plug->idle(m->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;
-+    size_t path_len;
-+    char *config_filename = NULL;
-+    size_t len;
-+    const sasl_callback_t *getconfpath_cb = NULL;
-+    const char * next;
-+
-+    /* If appname was not provided, behave as if there is no config file 
-+        (see also sasl_config_init() */
-+    if (global_callbacks.appname == NULL) {
-+        return SASL_CONTINUE;
-+    }
-+
-+    /* get the path to the config file */
-+    getconfpath_cb = _sasl_find_getconfpath_callback( global_callbacks.callbacks );
-+    if (getconfpath_cb == NULL) return SASL_BADPARAM;
-+
-+    /* getconfpath_cb->proc MUST be a sasl_getconfpath_t; if only C had a type
-+       system */
-+    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 = "";
-+
-+    next = path_to_config;
-+
-+    while (next != NULL) {
-+        next = strchr(path_to_config, PATHS_DELIMITER);
-+
-+        /* length = length of path + '/' + length of appname + ".conf" + 1
-+            for '\0' */
-+
-+        if (next != NULL) {
-+            path_len = next - path_to_config;
-+            next++; /* Skip to the next path */
-+        } else {
-+            path_len = strlen(path_to_config);
-+        }
-+
-+        len = path_len + 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((unsigned)len);
-+        if (! config_filename) {
-+            result = SASL_NOMEM;
-+            goto done;
-+        }
-+
-+        snprintf(config_filename, len, "%.*s%c%s.conf", path_len, path_to_config, 
-+	        HIER_DELIMITER, 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 SASL_CONTINUE if the config file doesn't exist */
-+        if (result == SASL_OK) {
-+            result = sasl_config_init(config_filename);
-+
-+            if (result != SASL_CONTINUE) {
-+                /* We are done */
-+                break;
-+            }
-+        }
-+
-+        if (config_filename) {
-+            sasl_FREE(config_filename);
-+            config_filename = NULL;
-+        }
-+
-+        path_to_config = next;
-+    }
-+
-+ 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->m.version = SASL_SERVER_PLUG_VERSION;
-+	n->m.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->m.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->m.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 and reading of the configuration file)
-+ * 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 (if present) to be short enough to be a path */
-+    if (appname != NULL && strlen(appname) >= PATH_MAX)
-+	return SASL_BADPARAM;
-+
-+    if (_sasl_server_active) {
-+	/* We're already active, just increase our refcount */
-+	/* xxx do something with the callback structure? */
-+	_sasl_server_active++;
-+	return SASL_OK;
-+    }
-+    
-+    ret = _sasl_common_init(&global_callbacks);
-+    if (ret != SASL_OK)
-+	return ret;
-+ 
-+    /* verify that the callbacks look ok */
-+    ret = verify_server_callbacks(callbacks);
-+    if (ret != SASL_OK)
-+	return ret;
-+
-+    global_callbacks.callbacks = callbacks;
-+    
-+    /* A shared library calling sasl_server_init will pass NULL as appname.
-+       This should retain the original appname. */
-+    if (appname != NULL) {
-+        global_callbacks.appname = appname;
-+    }
-+
-+    /* If we fail now, we have to call server_done */
-+    _sasl_server_active = 1;
-+
-+    /* allocate mechlist and set it to empty */
-+    mechlist = sasl_ALLOC(sizeof(mech_list_t));
-+    if (mechlist == NULL) {
-+	server_done();
-+	return SASL_NOMEM;
-+    }
-+
-+    ret = init_mechlist();
-+    if (ret != SASL_OK) {
-+	server_done();
-+	return ret;
-+    }
-+
-+    vf = _sasl_find_verifyfile_callback(callbacks);
-+
-+    /* load config file if applicable */
-+    ret = load_config(vf);
-+    if ((ret != SASL_OK) && (ret != SASL_CONTINUE)) {
-+	server_done();
-+	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_cleanup_hook = &server_done;
-+	_sasl_server_idle_hook = &server_idle;
-+
-+	ret = _sasl_build_mechlist();
-+    } else {
-+	server_done();
-+    }
-+
-+    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;
-+    unsigned flags = 0;
-+
-+    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 (!strcmp(dotrans, "noplain")) flags |= SASL_SET_NOPLAIN;
-+
-+    if (flags || *dotrans == '1' || *dotrans == 'y' ||
-+	(*dotrans == 'o' && dotrans[1] == 'n') || *dotrans == 't') {
-+	/* ok, it's on! */
-+	_sasl_log(conn, SASL_LOG_NOTE, 
-+		  "transitioning user %s to auxprop database",
-+		  conn->oparams.authid);
-+	result = sasl_setpass(conn,
-+			      conn->oparams.authid,
-+			      pass,
-+			      passlen,
-+			      NULL, 0, SASL_SET_CREATE | flags);
-+    }
-+
-+    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;
-+  sasl_getopt_t *getopt;
-+  void *context;
-+  const char *log_level, *auto_trans;
-+
-+  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 = (unsigned) strlen((*pconn)->service);
-+
-+  if (global_callbacks.appname && global_callbacks.appname[0] != '\0') {
-+    result = _sasl_strdup (global_callbacks.appname,
-+			   &serverconn->appname,
-+			   NULL);
-+    if (result != SASL_OK) {
-+      result = SASL_NOMEM;
-+      goto done_error;
-+    }
-+    serverconn->sparams->appname = serverconn->appname;
-+    serverconn->sparams->applen = (unsigned) strlen(serverconn->sparams->appname);
-+  } else {
-+    serverconn->appname = NULL;
-+    serverconn->sparams->appname = NULL;
-+    serverconn->sparams->applen = 0;
-+  }
-+
-+  serverconn->sparams->serverFQDN = (*pconn)->serverFQDN;
-+  serverconn->sparams->slen = (unsigned) strlen((*pconn)->serverFQDN);
-+
-+  if (user_realm) {
-+      result = _sasl_strdup(user_realm, &serverconn->user_realm, NULL);
-+      serverconn->sparams->urlen = (unsigned) strlen(user_realm);
-+      serverconn->sparams->user_realm = serverconn->user_realm;
-+  } else {
-+      serverconn->user_realm = NULL;
-+      /* the sparams is already zeroed */
-+  }
-+
-+  serverconn->sparams->callbacks = callbacks;
-+
-+  log_level = auto_trans = NULL;
-+  if(_sasl_getcallback(*pconn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) {
-+    getopt(context, NULL, "log_level", &log_level, NULL);
-+    getopt(context, NULL, "auto_transition", &auto_trans, NULL);
-+  }
-+  serverconn->sparams->log_level = log_level ? atoi(log_level) : SASL_LOG_ERR;
-+
-+  serverconn->sparams->utils = utils;
-+
-+  if (auto_trans &&
-+      (*auto_trans == '1' || *auto_trans == 'y' || *auto_trans == 't' ||
-+       (*auto_trans == 'o' && auto_trans[1] == 'n') ||
-+       !strcmp(auto_trans, "noplain")) &&
-+      sasl_auxprop_store(NULL, NULL, NULL) == SASL_OK) {
-+      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 ret;
-+    int myflags;
-+    context_list_t *cur;
-+    sasl_getopt_t *getopt;
-+    void *context;
-+    sasl_ssf_t minssf = 0;
-+
-+    if(!conn) return SASL_NOMECH;
-+
-+    if(! mech || ! mech->m.plug) {
-+	PARAMERROR(conn);
-+	return SASL_NOMECH;
-+    }
-+    
-+    plug = mech->m.plug;
-+
-+    /* get the list of allowed mechanisms (default = all) */
-+    if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context)
-+            == SASL_OK) {
-+	const char *mlist = NULL;
-+
-+	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 SASL_NOMECH;  /* 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 SASL_NOMECH;
-+	    break;
-+	}
-+    }
-+    
-+    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 SASL_TOOWEAK; /* too weak */
-+    }
-+
-+    context = NULL;
-+    if(plug->mech_avail
-+       && (ret = plug->mech_avail(plug->glob_context,
-+			   s_conn->sparams, (void **)&context)) != SASL_OK ) {
-+	if(ret == SASL_NOMECH) {
-+	    /* Mark this mech as no good for this connection */
-+	    cur = sasl_ALLOC(sizeof(context_list_t));
-+	    if(!cur) {
-+		MEMERROR(conn);
-+		return SASL_NOMECH;
-+	    }
-+	    cur->context = NULL;
-+	    cur->mech = mech;
-+	    cur->next = s_conn->mech_contexts;
-+	    s_conn->mech_contexts = cur;
-+	}
-+	
-+	/* SASL_NOTDONE might also get us here */
-+
-+	/* Error should be set by mech_avail call */
-+	return SASL_NOMECH;
-+    } else if(context) {
-+	/* Save this context */
-+	cur = sasl_ALLOC(sizeof(context_list_t));
-+	if(!cur) {
-+	    MEMERROR(conn);
-+	    return SASL_NOMECH;
-+	}
-+	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 SASL_TOOWEAK; /* too weak */
-+    }
-+
-+    /* if there are no users in the secrets database we can't use this 
-+       mechanism */
-+    if (mech->m.condition == SASL_NOUSER) {
-+	sasl_seterror(conn, 0, "no users in secrets db");
-+	return SASL_NOMECH;
-+    }
-+
-+    /* Can it meet our features? */
-+    if ((conn->flags & SASL_NEED_PROXY) &&
-+	!(plug->features & SASL_FEAT_ALLOWS_PROXY)) {
-+	return SASL_NOMECH;
-+    }
-+    
-+    /* 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 &= (myflags ^ plug->security_flags)) != 0) {
-+	sasl_seterror(conn, SASL_NOLOG,
-+		      "security flags do not match required");
-+	return (myflags & SASL_SEC_NOPLAINTEXT) ? SASL_ENCRYPT : SASL_NOMECH;
-+    }
-+
-+    /* 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 SASL_NOMECH;
-+    }
-+
-+    return SASL_OK;
-+}
-+
-+/*
-+ * 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 ? (unsigned) 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->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 ((result = mech_permitted(conn, m)) != SASL_OK) {
-+	goto done;
-+    }
-+
-+    if (m->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->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->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->m.plug->max_ssf) ||
-+		(pluglist[l].security_flags != m->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->m.plug);
-+	    m->m.plug = &pluglist[l];
-+	    m->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->m.plug->mech_new(s_conn->mech->m.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->m.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->m.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->m.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->m.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->m.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 += (unsigned) strlen(listptr->m.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;
-+  size_t 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) == SASL_OK) {
-+	  if (pcount != NULL)
-+	      (*pcount)++;
-+
-+	  /* print separator */
-+	  if (flag) {
-+	      strcat(conn->mechlist_buf, mysep);
-+	  } else {
-+	      flag = 1;
-+	  }
-+
-+	  /* now print the mechanism name */
-+	  strcat(conn->mechlist_buf, listptr->m.plug->mech_name);
-+      }
-+
-+      listptr = listptr->next;
-+  }
-+
-+  if (suffix)
-+      strcat(conn->mechlist_buf,suffix);
-+
-+  if (plen!=NULL)
-+      *plen = (unsigned) 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->m.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)
-+{
-+    size_t 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 *user,
-+			   unsigned userlen,
-+			   const char *pass,
-+			   unsigned passlen)
-+{
-+    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 = NULL, *mech = NULL;
-+    struct sasl_verify_password_s *v;
-+    const char *service = conn->service;
-+
-+    if (!userlen) userlen = (unsigned) strlen(user);
-+    if (!passlen) passlen = (unsigned) strlen(pass);
-+
-+    /* 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, passlen,
-+			      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++;
-+	}
-+	else if (!is_mech(mech, "auxprop") && s_conn->sparams->transition) {
-+	    s_conn->sparams->transition(conn, pass, passlen);
-+	}
-+    }
-+
-+    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,
-+		   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);
-+
-+    /* canonicalize the username */
-+    result = _sasl_canon_user(conn, user, userlen,
-+			      SASL_CU_AUTHID | SASL_CU_AUTHZID,
-+			      &(conn->oparams));
-+    if(result != SASL_OK) RETURN(conn, result);
-+    user = conn->oparams.user;
-+
-+    /* Check the password */
-+    result = _sasl_checkpass(conn, user, userlen, pass, passlen);
-+
-+    /* Do authorization */
-+    if(result == SASL_OK) {
-+      result = do_authorization((sasl_server_conn_t *)conn);
-+    }
-+
-+    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 = NULL, *mech = NULL;
-+    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);
-+    }
-+
-+    /* erase the plaintext password */
-+    s_conn->sparams->utils->prop_erase(s_conn->sparams->propctx,
-+				       password_request[0]);
-+
-+    /* 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);
-+
-+    /* Do authorization */
-+    if(result == SASL_OK) {
-+      result = do_authorization((sasl_server_conn_t *)conn);
-+    } else {
-+        /* If verification failed, we don't want to encourage getprop to work */
-+	conn->oparams.user = NULL;
-+	conn->oparams.authid = NULL;
-+    }
-+
-+    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 */
-+}
-+
-+/* It would be nice if we can show other information like Author, Company, Year, plugin version */
-+static void
-+_sasl_print_mechanism (
-+  server_sasl_mechanism_t *m,
-+  sasl_info_callback_stage_t stage,
-+  void *rock
-+)
-+{
-+    char delimiter;
-+
-+    if (stage == SASL_INFO_LIST_START) {
-+	printf ("List of server plugins follows\n");
-+	return;
-+    } else if (stage == SASL_INFO_LIST_END) {
-+	return;
-+    }
-+
-+    /* Process the mechanism */
-+    printf ("Plugin \"%s\" ", m->plugname);
-+
-+    switch (m->condition) {
-+	case SASL_OK:
-+	    printf ("[loaded]");
-+	    break;
-+
-+	case SASL_CONTINUE:
-+	    printf ("[delayed]");
-+	    break;
-+
-+	case SASL_NOUSER:
-+	    printf ("[no users]");
-+	    break;
-+
-+	default:
-+	    printf ("[unknown]");
-+	    break;
-+    }
-+
-+    printf (", \tAPI version: %d\n", m->version);
-+
-+    if (m->plug != NULL) {
-+	printf ("\tSASL mechanism: %s, best SSF: %d, supports setpass: %s\n",
-+		m->plug->mech_name,
-+		m->plug->max_ssf,
-+		(m->plug->setpass != NULL) ? "yes" : "no"
-+		);
-+
-+
-+	printf ("\tsecurity flags:");
-+	
-+	delimiter = ' ';
-+	if (m->plug->security_flags & SASL_SEC_NOANONYMOUS) {
-+	    printf ("%cNO_ANONYMOUS", delimiter);
-+	    delimiter = '|';
-+	}
-+
-+	if (m->plug->security_flags & SASL_SEC_NOPLAINTEXT) {
-+	    printf ("%cNO_PLAINTEXT", delimiter);
-+	    delimiter = '|';
-+	}
-+	
-+	if (m->plug->security_flags & SASL_SEC_NOACTIVE) {
-+	    printf ("%cNO_ACTIVE", delimiter);
-+	    delimiter = '|';
-+	}
-+
-+	if (m->plug->security_flags & SASL_SEC_NODICTIONARY) {
-+	    printf ("%cNO_DICTIONARY", delimiter);
-+	    delimiter = '|';
-+	}
-+
-+	if (m->plug->security_flags & SASL_SEC_FORWARD_SECRECY) {
-+	    printf ("%cFORWARD_SECRECY", delimiter);
-+	    delimiter = '|';
-+	}
-+
-+	if (m->plug->security_flags & SASL_SEC_PASS_CREDENTIALS) {
-+	    printf ("%cPASS_CREDENTIALS", delimiter);
-+	    delimiter = '|';
-+	}
-+
-+	if (m->plug->security_flags & SASL_SEC_MUTUAL_AUTH) {
-+	    printf ("%cMUTUAL_AUTH", delimiter);
-+	    delimiter = '|';
-+	}
-+
-+
-+
-+	printf ("\n\tfeatures:");
-+	
-+	delimiter = ' ';
-+	if (m->plug->features & SASL_FEAT_WANT_CLIENT_FIRST) {
-+	    printf ("%cWANT_CLIENT_FIRST", delimiter);
-+	    delimiter = '|';
-+	}
-+
-+	if (m->plug->features & SASL_FEAT_SERVER_FIRST) {
-+	    printf ("%cSERVER_FIRST", delimiter);
-+	    delimiter = '|';
-+	}
-+
-+	if (m->plug->features & SASL_FEAT_ALLOWS_PROXY) {
-+	    printf ("%cPROXY_AUTHENTICATION", delimiter);
-+	    delimiter = '|';
-+	}
-+
-+	if (m->plug->features & SASL_FEAT_NEEDSERVERFQDN) {
-+	    printf ("%cNEED_SERVER_FQDN", delimiter);
-+	    delimiter = '|';
-+	}
-+
-+        /* Is this one used? */
-+        if (m->plug->features & SASL_FEAT_SERVICE) {
-+	    printf ("%cSERVICE", delimiter);
-+	    delimiter = '|';
-+	}
-+
-+        if (m->plug->features & SASL_FEAT_GETSECRET) {
-+	    printf ("%cNEED_GETSECRET", delimiter);
-+	    delimiter = '|';
-+	}
-+    }
-+
-+    if (m->f) {
-+	printf ("\n\twill be loaded from \"%s\"", m->f);
-+    }
-+
-+    printf ("\n");
-+}
-+
-+/* Dump information about available server plugins (separate functions should be
-+   used for canon and auxprop plugins */
-+int sasl_server_plugin_info (
-+  const char *c_mech_list,		/* space separated mechanism list or NULL for ALL */
-+  sasl_server_info_callback_t *info_cb,
-+  void *info_cb_rock
-+)
-+{
-+    mechanism_t *m;
-+    server_sasl_mechanism_t plug_data;
-+    char * cur_mech;
-+    char *mech_list = NULL;
-+    char * p;
-+
-+    if (info_cb == NULL) {
-+	info_cb = _sasl_print_mechanism;
-+    }
-+
-+    if (mechlist != NULL) {
-+	info_cb (NULL, SASL_INFO_LIST_START, info_cb_rock);
-+
-+	if (c_mech_list == NULL) {
-+	    m = mechlist->mech_list; /* m point to beginning of the list */
-+
-+	    while (m != NULL) {
-+		memcpy (&plug_data, &m->m, sizeof(plug_data));
-+
-+		info_cb (&plug_data, SASL_INFO_LIST_MECH, info_cb_rock);
-+	    
-+		m = m->next;
-+	    }
-+	} else {
-+            mech_list = strdup(c_mech_list);
-+
-+	    cur_mech = mech_list;
-+
-+	    while (cur_mech != NULL) {
-+		p = strchr (cur_mech, ' ');
-+		if (p != NULL) {
-+		    *p = '\0';
-+		    p++;
-+		}
-+
-+		m = mechlist->mech_list; /* m point to beginning of the list */
-+
-+		while (m != NULL) {
-+		    if (strcasecmp (cur_mech, m->m.plug->mech_name) == 0) {
-+			memcpy (&plug_data, &m->m, sizeof(plug_data));
-+
-+			info_cb (&plug_data, SASL_INFO_LIST_MECH, info_cb_rock);
-+		    }
-+	    
-+		    m = m->next;
-+		}
-+
-+		cur_mech = p;
-+	    }
-+
-+            free (mech_list);
-+	}
-+
-+	info_cb (NULL, SASL_INFO_LIST_END, info_cb_rock);
-+
-+	return (SASL_OK);
-+    }
-+
-+    return (SASL_NOTINIT);
-+}




More information about the Pkg-cyrus-sasl2-commits mailing list