[dovecot-cvs] dovecot/src/auth auth-request.c, 1.41, 1.42 auth-worker-client.c, 1.18, 1.19 auth.c, 1.21, 1.22 db-ldap.c, 1.33, 1.34 db-ldap.h, 1.16, 1.17 passdb-ldap.c, 1.37, 1.38 passdb.c, 1.39, 1.40 passdb.h, 1.29, 1.30 userdb-ldap.c, 1.36, 1.37

cras at dovecot.org cras at dovecot.org
Fri Dec 30 17:43:45 EET 2005


Update of /var/lib/cvs/dovecot/src/auth
In directory talvi:/tmp/cvs-serv31655/src/auth

Modified Files:
	auth-request.c auth-worker-client.c auth.c db-ldap.c db-ldap.h 
	passdb-ldap.c passdb.c passdb.h userdb-ldap.c 
Log Message:
Added authentication bind support. Patch by J.M. Maurer.
Also cleaned up the LDAP code a bit and made it possible for passdbs to
disable lookup_credentials in runtime.



Index: auth-request.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-request.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -d -r1.41 -r1.42
--- auth-request.c	6 Dec 2005 14:37:15 -0000	1.41
+++ auth-request.c	30 Dec 2005 15:43:41 -0000	1.42
@@ -350,8 +350,8 @@
 	if (passdb->blocking)
 		passdb_blocking_verify_plain(request);
 	else {
-		passdb->iface->verify_plain(request, password,
-					    auth_request_verify_plain_callback);
+		passdb->iface.verify_plain(request, password,
+					   auth_request_verify_plain_callback);
 	}
 }
 
@@ -425,8 +425,8 @@
 
 	if (passdb->blocking)
 		passdb_blocking_lookup_credentials(request);
-	else if (passdb->iface->lookup_credentials != NULL) {
-		passdb->iface->lookup_credentials(request,
+	else if (passdb->iface.lookup_credentials != NULL) {
+		passdb->iface.lookup_credentials(request,
 			auth_request_lookup_credentials_callback);
 	} else {
 		/* this passdb doesn't support credentials */

Index: auth-worker-client.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-worker-client.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- auth-worker-client.c	20 Oct 2005 09:07:48 -0000	1.18
+++ auth-worker-client.c	30 Dec 2005 15:43:41 -0000	1.19
@@ -146,7 +146,7 @@
 		}
 	}
 
-	auth_request->passdb->passdb->iface->
+	auth_request->passdb->passdb->iface.
 		verify_plain(auth_request, password, verify_plain_callback);
 }
 
@@ -222,7 +222,7 @@
 		}
 	}
 
-	auth_request->passdb->passdb->iface->
+	auth_request->passdb->passdb->iface.
 		lookup_credentials(auth_request, lookup_credentials_callback);
 }
 

Index: auth.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- auth.c	28 Dec 2005 17:15:43 -0000	1.21
+++ auth.c	30 Dec 2005 15:43:41 -0000	1.22
@@ -106,7 +106,7 @@
 	struct auth_passdb *passdb;
 
 	for (passdb = auth->passdbs; passdb != NULL; passdb = passdb->next) {
-		if (passdb->passdb->iface->verify_plain != NULL)
+		if (passdb->passdb->iface.verify_plain != NULL)
 			return TRUE;
 	}
 	return FALSE;
@@ -117,7 +117,7 @@
 	struct auth_passdb *passdb;
 
 	for (passdb = auth->passdbs; passdb != NULL; passdb = passdb->next) {
-		if (passdb->passdb->iface->lookup_credentials != NULL)
+		if (passdb->passdb->iface.lookup_credentials != NULL)
 			return TRUE;
 	}
 	return FALSE;

Index: db-ldap.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/db-ldap.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- db-ldap.c	6 Dec 2005 16:48:20 -0000	1.33
+++ db-ldap.c	30 Dec 2005 15:43:41 -0000	1.34
@@ -33,6 +33,7 @@
 	DEF(SET_STR, uris),
 	DEF(SET_STR, dn),
 	DEF(SET_STR, dnpass),
+	DEF(SET_BOOL, auth_bind),
 	DEF(SET_STR, deref),
 	DEF(SET_STR, scope),
 	DEF(SET_STR, base),
@@ -51,6 +52,7 @@
 	MEMBER(uris) NULL,
 	MEMBER(dn) NULL,
 	MEMBER(dnpass) NULL,
+	MEMBER(auth_bind) FALSE,
 	MEMBER(deref) "never",
 	MEMBER(scope) "subtree",
 	MEMBER(base) NULL,
@@ -108,7 +110,8 @@
 	return ldap_err2string(err);
 }
 
-void db_ldap_search(struct ldap_connection *conn, struct ldap_request *request)
+void db_ldap_search(struct ldap_connection *conn, struct ldap_request *request,
+		    int scope)
 {
 	int msgid;
 
@@ -119,7 +122,7 @@
 		}
 	}
 
-	msgid = ldap_search(conn->ld, request->base, conn->set.ldap_scope,
+	msgid = ldap_search(conn->ld, request->base, scope,
 			    request->filter, request->attributes, 0);
 	if (msgid == -1) {
 		i_error("LDAP: ldap_search() failed (filter %s): %s",
@@ -150,7 +153,7 @@
 		struct ldap_request *request = value;
 
 		i_assert(conn->connected);
-		db_ldap_search(conn, request);
+		db_ldap_search(conn, request, conn->set.ldap_scope);
 	}
 	hash_iterate_deinit(iter);
 	hash_destroy(old_requests);
@@ -245,8 +248,7 @@
 		}
 	}
 
-	/* NOTE: we use blocking connect, we couldn't do anything anyway
-	   until it's done. */
+	/* FIXME: we shouldn't use blocking bind */
 	ret = ldap_simple_bind_s(conn->ld, conn->set.dn, conn->set.dnpass);
 	if (ret == LDAP_SERVER_DOWN) {
 		i_error("LDAP: Can't connect to server: %s", conn->set.hosts);

Index: db-ldap.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/db-ldap.h,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- db-ldap.h	6 Dec 2005 16:48:20 -0000	1.16
+++ db-ldap.h	30 Dec 2005 15:43:41 -0000	1.17
@@ -15,6 +15,7 @@
 	const char *uris;
 	const char *dn;
 	const char *dnpass;
+	int auth_bind;
 	const char *deref;
 	const char *scope;
 	const char *base;
@@ -62,7 +63,8 @@
 	char **attributes; /* points to pass_attr_names / user_attr_names */
 };
 
-void db_ldap_search(struct ldap_connection *conn, struct ldap_request *request);
+void db_ldap_search(struct ldap_connection *conn, struct ldap_request *request,
+		    int scope);
 
 void db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
 		       char ***attr_names_r, struct hash_table *attr_map,

Index: passdb-ldap.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/passdb-ldap.c,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -d -r1.37 -r1.38
--- passdb-ldap.c	6 Dec 2005 16:48:20 -0000	1.37
+++ passdb-ldap.c	30 Dec 2005 15:43:41 -0000	1.38
@@ -84,59 +84,78 @@
 	}
 }
 
-static void handle_request(struct ldap_connection *conn,
-			   struct ldap_request *request, LDAPMessage *res)
+static LDAPMessage *
+handle_request_get_entry(struct ldap_connection *conn,
+			 struct auth_request *auth_request,
+			 struct passdb_ldap_request *request, LDAPMessage *res)
 {
-	struct passdb_ldap_request *ldap_request =
-		(struct passdb_ldap_request *) request;
-        struct auth_request *auth_request = request->context;
 	enum passdb_result passdb_result;
 	LDAPMessage *entry;
-	const char *password, *scheme;
 	int ret;
 
 	passdb_result = PASSDB_RESULT_INTERNAL_FAILURE;
-	password = NULL;
 
-	if (res != NULL) {
+	if (!auth_request_unref(auth_request)) {
+		/* Auth request is already aborted */
+	} else if (res != NULL) {
+		/* LDAP query returned something */
 		ret = ldap_result2error(conn->ld, res, 0);
 		if (ret != LDAP_SUCCESS) {
 			auth_request_log_error(auth_request, "ldap",
 					       "ldap_search() failed: %s",
 					       ldap_err2string(ret));
-			res = NULL;
-		}
-	}
+		} else {
+			/* get the reply */
+			entry = ldap_first_entry(conn->ld, res);
+			if (entry != NULL) {
+				/* success */
+				return entry;
+			}
 
-	entry = res == NULL ? NULL : ldap_first_entry(conn->ld, res);
-	if (entry == NULL) {
-		if (res != NULL) {
+			/* no entries returned */
 			auth_request_log_info(auth_request, "ldap",
 					      "unknown user");
 			passdb_result = PASSDB_RESULT_USER_UNKNOWN;
 		}
-	} else {
-		ldap_query_save_result(conn, entry, auth_request);
-
-		if (auth_request->passdb_password == NULL) {
-			auth_request_log_error(auth_request, "ldap",
-					       "No password in reply");
-		} else if (ldap_next_entry(conn->ld, entry) != NULL) {
-			auth_request_log_error(auth_request, "ldap",
-					       "Multiple password replies");
-		} else {
-			password = auth_request->passdb_password;
-			if (password == NULL)
-				auth_request->no_password = TRUE;
-			passdb_result = PASSDB_RESULT_OK;
-		}
 	}
 
-	/* LDAP result is freed now. we can check if auth_request is
-	   even needed anymore */
-	if (!auth_request_unref(auth_request))
+	request->callback.verify_plain(passdb_result, auth_request);
+	return NULL;
+}
+
+static void handle_request(struct ldap_connection *conn,
+			   struct ldap_request *request, LDAPMessage *res)
+{
+	struct passdb_ldap_request *ldap_request =
+		(struct passdb_ldap_request *)request;
+        struct auth_request *auth_request = request->context;
+	enum passdb_result passdb_result;
+	LDAPMessage *entry;
+	const char *password, *scheme;
+	int ret;
+
+	entry = handle_request_get_entry(conn, auth_request, ldap_request, res);
+	if (entry == NULL)
 		return;
 
+	/* got first LDAP entry */
+	passdb_result = PASSDB_RESULT_INTERNAL_FAILURE;
+	password = NULL;
+
+	ldap_query_save_result(conn, entry, auth_request);
+	if (auth_request->passdb_password == NULL) {
+		auth_request_log_error(auth_request, "ldap",
+				       "No password in reply");
+	} else if (ldap_next_entry(conn->ld, entry) != NULL) {
+		auth_request_log_error(auth_request, "ldap",
+				       "Multiple password replies");
+	} else {
+		password = auth_request->passdb_password;
+		if (password == NULL)
+			auth_request->no_password = TRUE;
+		passdb_result = PASSDB_RESULT_OK;
+	}
+
 	scheme = password_get_scheme(&password);
 	/* auth_request_set_field() sets scheme */
 	i_assert(password == NULL || scheme != NULL);
@@ -170,6 +189,73 @@
 					    auth_request);
 }
 
+static void
+handle_request_authbind(struct ldap_connection *conn,
+			struct ldap_request *request, LDAPMessage *res)
+{
+	struct passdb_ldap_request *passdb_ldap_request =
+		(struct passdb_ldap_request *)request;
+	struct auth_request *auth_request = request->context;
+	enum passdb_result passdb_result;
+	int ret;
+
+	passdb_result = PASSDB_RESULT_INTERNAL_FAILURE;
+
+	if (!auth_request_unref(auth_request)) {
+		/* Auth request is already aborted */
+	} else if (res != NULL) {
+		ret = ldap_result2error(conn->ld, res, 0);
+		if (ret == LDAP_SUCCESS)
+			passdb_result = PASSDB_RESULT_OK;
+		else if (ret == LDAP_INVALID_CREDENTIALS)
+			passdb_result = PASSDB_RESULT_PASSWORD_MISMATCH;
+		else {
+			auth_request_log_error(request->context, "ldap",
+					       "ldap_bind() failed: %s",
+					       ldap_err2string(ret));
+		}
+	}
+
+	passdb_ldap_request->callback.verify_plain(passdb_result, auth_request);
+}
+
+static void
+handle_request_authbind_search(struct ldap_connection *conn,
+			       struct ldap_request *ldap_request,
+			       LDAPMessage *res)
+{
+	struct passdb_ldap_request *passdb_ldap_request =
+		(struct passdb_ldap_request *)ldap_request;
+	struct auth_request *auth_request = ldap_request->context;
+	LDAPMessage *entry;
+	const char *dn;
+	int msgid;
+
+	entry = handle_request_get_entry(conn, auth_request,
+					 passdb_ldap_request, res);
+	if (entry == NULL)
+		return;
+
+	dn = ldap_get_dn(conn->ld, entry);
+
+	/* switch the handler to the authenticated bind handler */
+	ldap_request->callback = handle_request_authbind;
+
+	msgid = ldap_bind(conn->ld, dn, auth_request->mech_password,
+			  LDAP_AUTH_SIMPLE);
+	if (msgid == -1) {
+		i_error("ldap_bind() failed: %s", ldap_get_error(conn));
+		passdb_ldap_request->callback.
+			verify_plain(PASSDB_RESULT_INTERNAL_FAILURE,
+				     auth_request);
+		return;
+	}
+
+	/* Bind started */
+	auth_request_ref(auth_request);
+	hash_insert(conn->requests, POINTER_CAST(msgid), ldap_request);
+}
+
 static void ldap_lookup_pass(struct auth_request *auth_request,
 			     struct ldap_request *ldap_request)
 {
@@ -202,7 +288,43 @@
 			       ldap_request->filter,
 			       t_strarray_join(attr_names, ","));
 
-	db_ldap_search(conn, ldap_request);
+	db_ldap_search(conn, ldap_request, conn->set.ldap_scope);
+}
+
+static void
+ldap_verify_plain_authbind(struct auth_request *auth_request,
+			   struct ldap_request *ldap_request)
+{
+	struct passdb_module *_module = auth_request->passdb->passdb;
+	struct ldap_passdb_module *module =
+		(struct ldap_passdb_module *)_module;
+	struct ldap_connection *conn = module->conn;
+	const struct var_expand_table *vars;
+	string_t *str;
+
+	vars = auth_request_get_var_expand_table(auth_request, ldap_escape);
+
+	str = t_str_new(512);
+	var_expand(str, conn->set.base, vars);
+	ldap_request->base = p_strdup(auth_request->pool, str_c(str));
+
+	str_truncate(str, 0);
+	var_expand(str, conn->set.pass_filter, vars);
+	ldap_request->filter = p_strdup(auth_request->pool, str_c(str));
+
+	/* we don't want any attributes in our search results;
+	   we only need the DN. */
+	ldap_request->attributes = p_new(auth_request->pool, char *, 1);
+
+	auth_request_ref(auth_request);
+	ldap_request->context = auth_request;
+	ldap_request->callback = handle_request_authbind_search;
+
+	auth_request_log_debug(auth_request, "ldap",
+			       "bind search: base=%s filter=%s",
+			       ldap_request->base, ldap_request->filter);
+
+        db_ldap_search(conn, ldap_request, LDAP_SCOPE_SUBTREE);
 }
 
 static void
@@ -210,12 +332,18 @@
 		  const char *password __attr_unused__,
 		  verify_plain_callback_t *callback)
 {
+	struct passdb_module *_module = request->passdb->passdb;
+	struct ldap_passdb_module *module =
+		(struct ldap_passdb_module *)_module;
+	struct ldap_connection *conn = module->conn;
 	struct passdb_ldap_request *ldap_request;
 
 	ldap_request = p_new(request->pool, struct passdb_ldap_request, 1);
 	ldap_request->callback.verify_plain = callback;
 
-        ldap_lookup_pass(request, &ldap_request->request);
+	conn->set.auth_bind ?
+		ldap_verify_plain_authbind(request, &ldap_request->request) :
+		ldap_lookup_pass(request, &ldap_request->request);
 }
 
 static void ldap_lookup_credentials(struct auth_request *request,
@@ -257,6 +385,11 @@
 		(struct ldap_passdb_module *)_module;
 
 	(void)db_ldap_connect(module->conn);
+
+	if (module->conn->set.auth_bind) {
+		/* Credential lookups can't be done with authentication binds */
+		_module->iface.lookup_credentials = NULL;
+	}
 }
 
 static void passdb_ldap_deinit(struct passdb_module *_module)

Index: passdb.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/passdb.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- passdb.c	14 Dec 2005 17:45:06 -0000	1.39
+++ passdb.c	30 Dec 2005 15:43:41 -0000	1.40
@@ -168,14 +168,14 @@
 		auth_passdb->passdb =
 			iface->preinit(auth_passdb, auth_passdb->args);
 	}
-	auth_passdb->passdb->iface = iface;
+	auth_passdb->passdb->iface = *iface;
 	return auth_passdb;
 }
 
 void passdb_init(struct auth_passdb *passdb)
 {
-	if (passdb->passdb->iface->init != NULL)
-		passdb->passdb->iface->init(passdb->passdb, passdb->args);
+	if (passdb->passdb->iface.init != NULL)
+		passdb->passdb->iface.init(passdb->passdb, passdb->args);
 
 	i_assert(passdb->passdb->default_pass_scheme != NULL ||
 		 passdb->passdb->cache_key == NULL);
@@ -188,8 +188,8 @@
 
 void passdb_deinit(struct auth_passdb *passdb)
 {
-	if (passdb->passdb->iface->deinit != NULL)
-		passdb->passdb->iface->deinit(passdb->passdb);
+	if (passdb->passdb->iface.deinit != NULL)
+		passdb->passdb->iface.deinit(passdb->passdb);
 #ifdef HAVE_MODULES
 	if (passdb->module != NULL)
                 auth_module_close(passdb->module);

Index: passdb.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/passdb.h,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- passdb.h	16 Oct 2005 14:06:59 -0000	1.29
+++ passdb.h	30 Dec 2005 15:43:41 -0000	1.30
@@ -34,19 +34,6 @@
 					   const char *password,
 					   struct auth_request *request);
 
-struct passdb_module {
-	/* The caching key for this module, or NULL if caching isn't wanted. */
-	const char *cache_key;
-	/* Default password scheme for this module.
-	   If cache_key is set, must not be NULL. */
-	const char *default_pass_scheme;
-	/* If blocking is set to TRUE, use child processes to access
-	   this passdb. */
-	int blocking;
-
-	const struct passdb_module_interface *iface;
-};
-
 struct passdb_module_interface {
 	const char *name;
 
@@ -65,6 +52,19 @@
 				   lookup_credentials_callback_t *callback);
 };
 
+struct passdb_module {
+	/* The caching key for this module, or NULL if caching isn't wanted. */
+	const char *cache_key;
+	/* Default password scheme for this module.
+	   If cache_key is set, must not be NULL. */
+	const char *default_pass_scheme;
+	/* If blocking is set to TRUE, use child processes to access
+	   this passdb. */
+	int blocking;
+
+	struct passdb_module_interface iface;
+};
+
 const char *
 passdb_get_credentials(struct auth_request *auth_request,
 		       const char *password, const char *scheme);

Index: userdb-ldap.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/userdb-ldap.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -d -r1.36 -r1.37
--- userdb-ldap.c	6 Dec 2005 16:48:20 -0000	1.36
+++ userdb-ldap.c	30 Dec 2005 15:43:41 -0000	1.37
@@ -201,7 +201,7 @@
 			       request->request.filter,
 			       t_strarray_join(attr_names, ","));
 
-	db_ldap_search(conn, &request->request);
+	db_ldap_search(conn, &request->request, conn->set.ldap_scope);
 }
 
 static struct userdb_module *



More information about the dovecot-cvs mailing list