debian/patches/0009_build_samples_on_debian.dpatch patches auto* generated file

Andreas Metzler ametzler at downhill.at.eu.org
Thu Oct 19 17:13:18 UTC 2006


On 2006-10-19 "Roberto C. Sanchez" <roberto at connexer.com> wrote:
> On Wed, Oct 18, 2006 at 08:10:04PM +0200, Andreas Metzler wrote:
>> On 2006-10-18 Andreas Metzler <ametzler at downhill.at.eu.org> wrote:
>>> (It makes debian/rules clean *after a
>>> successfull build fail.)

>> Similar problem with
>> debian/patches/0008_one_time_sasl_set_alloc.dpatch, it generates
>> trunk/lib/server.c.orig, the file is removed automaticall by dh_clean
>> and unpatch fails.
 

> Odd.  On my system, none of the patch/unpatch cycles fail.  Can you
> capture the output and post it?

-------------------
(SID)ametzler at argenau:/tmp/SASL/cyrus-sasl-2.1.22$ { time dpkg-buildpackage -uc -us -rfakeroot  ;}  2>&1 | tee ../buildlog.sasl1 && { time dpkg-buildpackage -uc -us -rfakeroot  ;} 2>&1 | tee ../buildlog.sasl2
[...]
dpkg-buildpackage: binary and diff upload (original source NOT included)
[...]
dpkg-buildpackage: source version without epoch 2.1.22-0.0~pre03
 fakeroot debian/rules clean
rm -f config.status config.cache config.log configure.lineno configure.status.lineno
rm -f Makefile
make[1]: Leaving directory `/tmp/SASL/cyrus-sasl-2.1.22'
rm -f config.h config.log autom4ate.cache
dh_clean
dpatch  deapply-all
reverting patch 0008_one_time_sasl_set_alloc from ./ ... failed.
make: *** [unpatch] Error 1
-------------------

The source is really the one I noted. The _bogus_
trunk/lib/server.c.orig generated by
debian/patches/0008_one_time_sasl_set_alloc.dpatch (the dpatch file
simply contains cruft) is removed by dh_clean and unpatching fails, as
trunk/lib/server.c.orig has already been removed.

Removing the cruft fixes the issue.[1]

thanks, cu andreas
[1] Well, unpatching works, rebuilding doesn't as there are a whole
bunch of newly added symlinks which dpkg-sorce cannot handle.
-- 
The 'Galactic Cleaning' policy undertaken by Emperor Zhark is a personal
vision of the emperor's, and its inclusion in this work does not constitute
tacit approval by the author or the publisher for any such projects,
howsoever undertaken.                                (c) Jasper Ffforde
-------------- next part --------------
Index: patches/0008_one_time_sasl_set_alloc.dpatch
===================================================================
--- patches/0008_one_time_sasl_set_alloc.dpatch	(Revision 74)
+++ patches/0008_one_time_sasl_set_alloc.dpatch	(Arbeitskopie)
@@ -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-debian-devel mailing list