--- squid_ldap_group.c.orig	2010-05-30 15:21:11.000000000 +0200
+++ squid_ldap_group.c	2010-08-30 11:18:01.072325145 +0200
@@ -74,6 +74,9 @@
 
 #include <lber.h>
 #include <ldap.h>
+#if defined (CYRUS_SASL)
+#include <sasl/sasl.h>
+#endif
 
 #endif
 
@@ -115,6 +118,10 @@
 
 static int readSecret(const char *filename);
 
+#if defined (CYRUS_SASL)
+static int do_sasl_interact(LDAP * ld, unsigned flags, void *defaults, void *_interact);
+#endif
+
 /* Yuck.. we need to glue to different versions of the API */
 
 #ifndef LDAP_NO_ATTRS
@@ -220,6 +227,9 @@
     int strip_nt_domain = 0;
     int strip_kerberos_realm = 0;
     int err = 0;
+#if defined (CYRUS_SASL)
+    int use_sasl_bind = 0;
+#endif
 
     setbuf(stdout, NULL);
 
@@ -378,12 +388,18 @@
         case 'K':
             strip_kerberos_realm = 1;
             break;
+#if defined (CYRUS_SASL)
+        case 'k':
+            use_sasl_bind = 1;
+            break;
+#endif
         default:
             fprintf(stderr, PROGRAM_NAME " ERROR: Unknown command line option '%c'\n", option);
             exit(1);
         }
     }
 
+    version = 3;
     while (argc > 1) {
         char *value = argv[1];
         if (ldapServer) {
@@ -433,6 +449,9 @@
         fprintf(stderr, "\t-g\t\t\tfirst query parameter is base DN extension\n\t\t\t\tfor this query\n");
         fprintf(stderr, "\t-S\t\t\tStrip NT domain from usernames\n");
         fprintf(stderr, "\t-K\t\t\tStrip Kerberos realm from usernames\n");
+#if defined (CYRUS_SASL)
+        fprintf(stderr, "\t-k\t\t\tuse GSSAPI sasl authentication\n");
+#endif
         fprintf(stderr, "\t-d\t\t\tenable debug mode\n");
         fprintf(stderr, "\n");
         fprintf(stderr, "\tIf you need to bind as a user to perform searches then use the\n\t-D binddn -w bindpasswd or -D binddn -W secretfile options\n\n");
@@ -563,10 +582,23 @@
                 squid_ldap_set_timelimit(ld, timelimit);
                 squid_ldap_set_referrals(ld, !noreferrals);
                 squid_ldap_set_aliasderef(ld, aliasderef);
+
+#if defined (CYRUS_SASL)
+                if (use_sasl_bind) {
+                    rc = ldap_sasl_interactive_bind_s(ld, binddn, NULL, NULL, NULL, LDAP_SASL_QUIET, do_sasl_interact, (void *) bindpasswd);
+                    if (rc != LDAP_SUCCESS) {
+                    fprintf(stderr, PROGRAM_NAME " WARNING, could not bind to binddn '%s' (sasl)\n", ldap_err2string(rc));
+                    ldap_unbind(ld);
+                    ld = NULL;
+                    break;
+                    }
+                } else if (binddn && bindpasswd && *binddn && *bindpasswd) {
+#else
                 if (binddn && bindpasswd && *binddn && *bindpasswd) {
+#endif
                     rc = ldap_simple_bind_s(ld, binddn, bindpasswd);
                     if (rc != LDAP_SUCCESS) {
-                        fprintf(stderr, PROGRAM_NAME " WARNING, could not bind to binddn '%s'\n", ldap_err2string(rc));
+			 fprintf(stderr, PROGRAM_NAME " WARNING, could not bind to binddn '%s' (simple)\n", ldap_err2string(rc));
                         ldap_unbind(ld);
                         ld = NULL;
                         break;
@@ -829,3 +861,32 @@
 
     return 0;
 }
+
+#if defined (CYRUS_SASL)
+static int
+do_sasl_interact(LDAP * ld, unsigned flags, void *defaults, void *_interact)
+{
+    char *authzid = (char *) defaults;
+    sasl_interact_t *interact = (sasl_interact_t *) _interact;
+ 
+    while (interact->id != SASL_CB_LIST_END) {
+	if (interact->id == SASL_CB_USER) {
+	    if (authzid != NULL) {
+		interact->result = authzid;
+		interact->len = strlen(authzid);
+	    } else if (interact->defresult != NULL) {
+		interact->result = interact->defresult;
+		interact->len = strlen(interact->defresult);
+	    } else {
+		interact->result = "";
+		interact->len = 0;
+	    }
+	} else {
+	    return LDAP_PARAM_ERROR;
+	}
+	interact++;
+    }
+    return LDAP_SUCCESS;
+}
+#endif
+

