--- dict_ldap.c.orig	2006-03-06 18:57:44.387842400 -0800
+++ dict_ldap.c	2006-03-06 18:58:16.078501600 -0800
@@ -94,7 +94,20 @@
 /*	How to handle LDAP aliases. See ldap.h or ldap_open(3) man page.
 /* .IP version
 /*	Specifies the LDAP protocol version to use.  Default is version
-/*	\fI2\fR.
+/*	\fI3\fR.
+/* .IP sasl_mech
+/*	Specifies the LDAP SASL Mechanism to use.
+/* .IP  sasl_realm
+/*      The realm to use for SASL binds.
+/* .IP  sasl_authz_id
+/*      The SASL Authorization Identity to assert.
+/* .IP  sasl_props
+/*      The SASL properties to set.
+/* .IP  sasl_flags
+/*      The SASL flags to set. Defaults to LDAP_SASL_QUIET
+/* .IP  sasl_creds
+/*	Specifies the location of the Kerberos V credentials to use with SASL/GSSAPI authentication, and the environment variable.
+/*      EXAMPLE: KRB5CCNAME=/tmp/ldap_ticket.tgt
 /* .IP start_tls
 /*	Whether or not to issue STARTTLS upon connection to the server.
 /*	At this time, STARTTLS and LDAP SSL are only available if the
@@ -172,7 +185,7 @@
  /*
   * Older APIs have weird memory freeing behavior.
   */
-#if !defined(LDAP_API_VERSION) || (LDAP_API_VERSION < 2000)
+#if !defined(LDAP_API_VERSION) || (LDAP_API_VERSION < 2004)
 #error "Your LDAP version is too old"
 #endif
 
@@ -198,6 +211,11 @@
 #include "cfg_parser.h"
 #include "db_common.h"
 
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+/* SASL Library */
+#include "sasl/sasl.h"
+#endif
+
 /* Application-specific. */
 
 #include "dict_ldap.h"
@@ -236,7 +254,14 @@
     int     chase_referrals;
     int     debuglevel;
     int     version;
+    int     authtype;
 #ifdef LDAP_API_FEATURE_X_OPENLDAP
+    char   *sasl_mech;
+    char   *sasl_realm;
+    char   *sasl_authz_id;
+    char   *sasl_props;
+    unsigned sasl_flags;
+    char   *sasl_creds;
     int     ldap_ssl;
     int     start_tls;
     int     tls_require_cert;
@@ -347,6 +372,53 @@
     (void) ldap_set_option(ld, LDAP_OPT_ERROR_NUMBER, &rc);
     return rc;
 }
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+/* We need to set up a structure, and a function to handle the
+ * SASL callbacks
+ */
+
+typedef struct bictx {
+    char *authcid;
+    char *passwd;
+    char *realm;
+    char *authzid;
+} bictx;
+
+static int
+ldap_b2_interact(LDAP *ld, unsigned flags, void *def, void *inter)
+{
+
+	 sasl_interact_t *in = inter;
+	 const char *p;
+	 bictx *ctx = def;
+
+	 for (;in->id != SASL_CB_LIST_END;in++)
+         {
+		 p = NULL;
+		 switch(in->id)
+                 {
+			 case SASL_CB_GETREALM:
+				 p = ctx->realm;
+				 break;
+                         case SASL_CB_AUTHNAME:
+				 p = ctx->authcid;
+				 break;
+                         case SASL_CB_USER:
+				 p = ctx->authzid;
+				 break;
+			 case SASL_CB_PASS:
+				 p = ctx->passwd;
+				 break;
+		 }
+		 if (p)
+		 {
+			 in->len = strlen(p);
+			 in->result = p;
+		 }
+	 }
+	 return LDAP_SUCCESS;
+}
+#endif
 
 /*
  * We need a version of ldap_bind that times out, otherwise all
@@ -357,11 +429,14 @@
     int     msgid;
     LDAPMessage *res;
     struct timeval mytimeval;
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+    bictx ctx;
+#endif
 
+#ifndef LDAP_API_FEATURE_X_OPENLDAP
     if ((msgid = ldap_bind(dict_ldap->ld, dict_ldap->bind_dn,
-			   dict_ldap->bind_pw, LDAP_AUTH_SIMPLE)) == -1)
+			   dict_ldap->bind_pw, dict_ldap->authtype)) == -1)
 	return (dict_ldap_get_errno(dict_ldap->ld));
-
     mytimeval.tv_sec = dict_ldap->timeout;
     mytimeval.tv_usec = 0;
 
@@ -373,6 +448,31 @@
 	return (dict_ldap_set_errno(dict_ldap->ld, LDAP_TIMEOUT));
     }
     return (ldap_result2error(dict_ldap->ld, res, 1));
+#else
+    if (dict_ldap->authtype == LDAP_AUTH_SASL) {
+            if (strcmp("", dict_ldap->sasl_creds) != 0) {
+                    putenv(dict_ldap->sasl_creds);
+            }
+	    if (strcmp("", dict_ldap->sasl_props) != 0) {
+		    msgid = ldap_set_option( dict_ldap->ld, LDAP_OPT_X_SASL_SECPROPS,
+				    (void *) dict_ldap->sasl_props);
+		    if(msgid != LDAP_OPT_SUCCESS) {
+			    return (ldap_result2error(dict_ldap->ld, res, 1));
+		    }
+	    }
+	    ctx.authcid = dict_ldap->bind_dn;
+	    ctx.passwd = dict_ldap->bind_pw;
+	    ctx.realm = dict_ldap->sasl_realm;
+	    ctx.authzid = dict_ldap->sasl_authz_id;
+	    msgid = ldap_sasl_interactive_bind_s(dict_ldap->ld, NULL, dict_ldap->sasl_mech, NULL, NULL, dict_ldap->sasl_flags, ldap_b2_interact, &ctx);
+    } else {
+	    msgid = ldap_bind_s(dict_ldap->ld, dict_ldap->bind_dn, dict_ldap->bind_pw, dict_ldap->authtype);
+    }
+    if (msgid != LDAP_SUCCESS) {
+	    return (ldap_result2error(dict_ldap->ld, res, 1));
+    }
+    return LDAP_SUCCESS;
+#endif
 }
 
 #ifdef LDAP_API_FEATURE_X_OPENLDAP
@@ -665,7 +765,14 @@
     ADDINT(keybuf, dict_ldap->chase_referrals);
     ADDINT(keybuf, dict_ldap->debuglevel);
     ADDINT(keybuf, dict_ldap->version);
+    ADDINT(keybuf, dict_ldap->authtype);
 #ifdef LDAP_API_FEATURE_X_OPENLDAP
+    ADDSTR(keybuf, dict_ldap->sasl_mech);
+    ADDSTR(keybuf, dict_ldap->sasl_realm);
+    ADDSTR(keybuf, dict_ldap->sasl_authz_id);
+    ADDSTR(keybuf, dict_ldap->sasl_props);
+    ADDINT(keybuf, dict_ldap->sasl_flags);
+    ADDSTR(keybuf, dict_ldap->sasl_creds);
     ADDINT(keybuf, dict_ldap->ldap_ssl);
     ADDINT(keybuf, dict_ldap->start_tls);
     ADDINT(keybuf, sslon ? dict_ldap->tls_require_cert : 0);
@@ -1137,6 +1244,11 @@
     if (dict_ldap->ctx)
 	db_common_free_ctx(dict_ldap->ctx);
 #ifdef LDAP_API_FEATURE_X_OPENLDAP
+    myfree(dict_ldap->sasl_mech);
+    myfree(dict_ldap->sasl_realm);
+    myfree(dict_ldap->sasl_authz_id);
+    myfree(dict_ldap->sasl_props);
+    myfree(dict_ldap->sasl_creds);
     myfree(dict_ldap->tls_ca_cert_file);
     myfree(dict_ldap->tls_ca_cert_dir);
     myfree(dict_ldap->tls_cert);
@@ -1186,7 +1298,7 @@
     /*
      * Define LDAP Version.
      */
-    dict_ldap->version = cfg_get_int(dict_ldap->parser, "version", 2, 2, 0);
+    dict_ldap->version = cfg_get_int(dict_ldap->parser, "version", 3, 2, 0);
     switch (dict_ldap->version) {
     case 2:
 	dict_ldap->version = LDAP_VERSION2;
@@ -1197,9 +1309,11 @@
     default:
 	msg_warn("%s: %s Unknown version %d.", myname, ldapsource,
 		 dict_ldap->version);
-	dict_ldap->version = LDAP_VERSION2;
+	dict_ldap->version = LDAP_VERSION3;
     }
 
+    dict_ldap->authtype = LDAP_AUTH_SIMPLE;
+
 #if defined(LDAP_API_FEATURE_X_OPENLDAP)
     dict_ldap->ldap_ssl = 0;
 #endif
@@ -1408,6 +1522,19 @@
 					      "chase_referrals", 0);
 
 #ifdef LDAP_API_FEATURE_X_OPENLDAP
+    /*
+     *  SASL options
+     */
+
+    dict_ldap->sasl_mech = cfg_get_str(dict_ldap->parser, "sasl_mech", "", 0, 0); 
+    if (strcmp("", dict_ldap->sasl_mech) !=0) {
+            dict_ldap->authtype=LDAP_AUTH_SASL;
+    }
+    dict_ldap->sasl_realm = cfg_get_str(dict_ldap->parser, "sasl_realm", "", 0, 0); 
+    dict_ldap->sasl_authz_id = cfg_get_str(dict_ldap->parser, "sasl_authz_id", "", 0, 0); 
+    dict_ldap->sasl_props = cfg_get_str(dict_ldap->parser, "sasl_props", "", 0, 0); 
+    dict_ldap->sasl_flags = cfg_get_int(dict_ldap->parser, "sasl_flags", LDAP_SASL_QUIET, 0, 0);
+    dict_ldap->sasl_creds = cfg_get_str(dict_ldap->parser, "sasl_creds", "", 0, 0);
 
     /*
      * TLS options
