[dovecot-cvs] dovecot/src/auth passdb-ldap.c,NONE,1.1 Makefile.am,1.10,1.11 db-ldap.c,1.3,1.4 db-ldap.h,1.2,1.3 passdb.c,1.2,1.3 passdb.h,1.3,1.4 userdb-ldap.c,1.3,1.4

cras at procontrol.fi cras at procontrol.fi
Tue Feb 11 11:56:00 EET 2003


Update of /home/cvs/dovecot/src/auth
In directory danu:/tmp/cvs-serv6445

Modified Files:
	Makefile.am db-ldap.c db-ldap.h passdb.c passdb.h 
	userdb-ldap.c 
Added Files:
	passdb-ldap.c 
Log Message:
passdb ldap added. fixes to userdb ldap.



--- NEW FILE: passdb-ldap.c ---
/* Copyright (C) 2003 Timo Sirainen */

#include "config.h"
#undef HAVE_CONFIG_H

#ifdef PASSDB_LDAP

#include "common.h"
#include "str.h"
#include "var-expand.h"
#include "mycrypt.h"
#include "db-ldap.h"
#include "passdb.h"

#include <ldap.h>
#include <stdlib.h>

/* using posixAccount */
#define DEFAULT_ATTRIBUTES "uid,userPassword"

enum ldap_user_attr {
	ATTR_VIRTUAL_USER = 0,
	ATTR_PASSWORD,

	ATTR_COUNT
};

struct passdb_ldap_connection {
	struct ldap_connection *conn;

        unsigned int *attrs;
	char **attr_names;
};

struct passdb_ldap_request {
	struct ldap_request request;

	enum passdb_credentials credentials;
	union {
		verify_plain_callback_t *verify_plain;
                lookup_credentials_callback_t *lookup_credentials;
	} callback;

	char password[1]; /* variable width */
};

static struct passdb_ldap_connection *passdb_ldap_conn;

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;
	LDAPMessage *entry;
	BerElement *ber;
	char *attr, **vals;
	const char *user, *password;

	if (auth_request->realm == NULL)
		user = auth_request->user;
	else {
		user = t_strconcat(auth_request->user, "@",
				   auth_request->realm, NULL);
	}

	password = NULL;

	entry = ldap_first_entry(conn->ld, res);
	if (entry == NULL)
		i_error("ldap(%s): unknown user", user);
	else {
		attr = ldap_first_attribute(conn->ld, entry, &ber);
		while (attr != NULL) {
			vals = ldap_get_values(conn->ld, entry, attr);
			if (vals != NULL && vals[0] != NULL &&
			    vals[1] == NULL) {
				if (strcasecmp(attr, passdb_ldap_conn->
					       attr_names[ATTR_PASSWORD]) == 0)
					password = t_strdup(vals[0]);
			}
			ldap_value_free(vals);
			ldap_memfree(attr);

			attr = ldap_next_attribute(conn->ld, entry, ber);
		}

		if (password == NULL)
			i_error("ldap(%s): No password in reply", user);
		else if (ldap_next_entry(conn->ld, entry) != NULL) {
			i_error("ldap(%s): Multiple password replies", user);
			password = NULL;
		}
	}

	switch (ldap_request->credentials) {
	case -1:
		/* verify_plain */
		if (password == NULL) {
			ldap_request->callback.
				verify_plain(PASSDB_RESULT_USER_UNKNOWN,
					     auth_request);
			break;
		}

		if (strncasecmp(password, "{crypt}", 7) == 0)
			password += 7;

		if (strcmp(mycrypt(password, ldap_request->password),
			   ldap_request->password) != 0) {
			if (verbose)
				i_info("ldap(%s): password mismatch", user);
			ldap_request->callback.
				verify_plain(PASSDB_RESULT_PASSWORD_MISMATCH,
					     auth_request);
		} else {
			ldap_request->callback.verify_plain(PASSDB_RESULT_OK,
							    auth_request);
		}
		break;
	case PASSDB_CREDENTIALS_PLAINTEXT:
		if (password != NULL &&
		    strncasecmp(password, "{plain}", 7) == 0)
			password += 7;
		else
			password = NULL;

		ldap_request->callback.lookup_credentials(password,
							  auth_request);
		break;
	case PASSDB_CREDENTIALS_CRYPT:
		ldap_request->callback.lookup_credentials(password,
							  auth_request);
		break;
	case PASSDB_CREDENTIALS_DIGEST_MD5:
		if (password != NULL &&
		    strncasecmp(password, "{digest-md5}", 12) == 0)
			password += 12;
		else
			password = NULL;

		ldap_request->callback.lookup_credentials(password,
							  auth_request);
		break;
	}
}

static void ldap_lookup_pass(struct auth_request *auth_request,
			     struct ldap_request *ldap_request)
{
	struct ldap_connection *conn = passdb_ldap_conn->conn;
	const char *user, *filter;
	string_t *str;

	if (auth_request->realm == NULL)
		user = auth_request->user;
	else {
		user = t_strconcat(auth_request->user, "@",
				   auth_request->realm, NULL);
	}

	if (conn->set.filter == NULL) {
		filter = t_strdup_printf("(&(objectClass=posixAccount)(%s=%s))",
			passdb_ldap_conn->attr_names[ATTR_VIRTUAL_USER], user);
	} else {
		str = t_str_new(512);
		var_expand(str, conn->set.filter, user, NULL);
		filter = str_c(str);
	}

	ldap_request->callback = handle_request;
	ldap_request->context = auth_request;

	db_ldap_search(conn, conn->set.base, conn->set.ldap_scope,
		       filter, passdb_ldap_conn->attr_names,
		       ldap_request);
}

static void
ldap_verify_plain(struct auth_request *request, const char *password,
		  verify_plain_callback_t *callback)
{
	struct passdb_ldap_request *ldap_request;

	ldap_request = i_malloc(sizeof(struct passdb_ldap_request) +
				strlen(password));
	ldap_request->credentials = -1;
	ldap_request->callback.verify_plain = callback;
	strcpy(ldap_request->password, password);

        ldap_lookup_pass(request, &ldap_request->request);
}

static void ldap_lookup_credentials(struct auth_request *request,
				    enum passdb_credentials credentials,
				    lookup_credentials_callback_t *callback)
{
	struct passdb_ldap_request *ldap_request;

	ldap_request = i_new(struct passdb_ldap_request, 1);
	ldap_request->credentials = credentials;
	ldap_request->callback.lookup_credentials = callback;

        ldap_lookup_pass(request, &ldap_request->request);
}

static void passdb_ldap_init(const char *args)
{
	struct ldap_connection *conn;

	passdb_ldap_conn = i_new(struct passdb_ldap_connection, 1);
	passdb_ldap_conn->conn = conn = db_ldap_init(args);

	db_ldap_set_attrs(conn, conn->set.attrs ?
			  conn->set.attrs : DEFAULT_ATTRIBUTES,
			  &passdb_ldap_conn->attrs,
			  &passdb_ldap_conn->attr_names);
}

static void passdb_ldap_deinit(void)
{
	db_ldap_unref(passdb_ldap_conn->conn);
	i_free(passdb_ldap_conn);
}

struct passdb_module passdb_ldap = {
	passdb_ldap_init,
	passdb_ldap_deinit,

	ldap_verify_plain,
	ldap_lookup_credentials
};

#endif

Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/auth/Makefile.am,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- Makefile.am	4 Feb 2003 03:24:47 -0000	1.10
+++ Makefile.am	11 Feb 2003 09:55:58 -0000	1.11
@@ -26,6 +26,7 @@
 	mech-digest-md5.c \
 	mycrypt.c \
 	passdb.c \
+	passdb-ldap.c \
 	passdb-passwd.c \
 	passdb-passwd-file.c \
 	passdb-pam.c \

Index: db-ldap.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/db-ldap.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- db-ldap.c	2 Feb 2003 10:59:58 -0000	1.3
+++ db-ldap.c	11 Feb 2003 09:55:58 -0000	1.4
@@ -27,6 +27,7 @@
 	DEF(SET_STR, dn),
 	DEF(SET_STR, dnpass),
 	DEF(SET_STR, deref),
+	DEF(SET_STR, scope),
 	DEF(SET_STR, base),
 	DEF(SET_STR, attrs),
 	DEF(SET_STR, filter)
@@ -37,6 +38,7 @@
 	MEMBER(dn) NULL,
 	MEMBER(dnpass) NULL,
 	MEMBER(deref) "never",
+	MEMBER(scope) "subtree",
 	MEMBER(base) NULL,
 	MEMBER(attrs) NULL,
 	MEMBER(filter) NULL
@@ -58,6 +60,18 @@
 	i_fatal("LDAP: Unknown deref option '%s'", str);
 }
 
+static int scope2str(const char *str)
+{
+	if (strcasecmp(str, "base") == 0)
+		return LDAP_SCOPE_BASE;
+	if (strcasecmp(str, "onelevel") == 0)
+		return LDAP_SCOPE_ONELEVEL;
+	if (strcasecmp(str, "subtree") == 0)
+		return LDAP_SCOPE_SUBTREE;
+
+	i_fatal("LDAP: Unknown scope option '%s'", str);
+}
+
 static const char *get_ldap_error(struct ldap_connection *conn)
 {
 	int ret, err;
@@ -251,14 +265,11 @@
 	conn->set = default_ldap_settings;
 	settings_read(config_path, parse_setting, conn);
 
-	/*if (conn->set.dnuser == NULL)
-		i_fatal("LDAP: No user given");
-	if (conn->set.dnpass == NULL)
-		i_fatal("LDAP: No password given");*/
 	if (conn->set.base == NULL)
 		i_fatal("LDAP: No base given");
 
         conn->set.ldap_deref = deref2str(conn->set.deref);
+        conn->set.ldap_scope = scope2str(conn->set.scope);
 
 	(void)ldap_conn_open(conn);
 	return conn;

Index: db-ldap.h
===================================================================
RCS file: /home/cvs/dovecot/src/auth/db-ldap.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- db-ldap.h	2 Feb 2003 00:08:28 -0000	1.2
+++ db-ldap.h	11 Feb 2003 09:55:58 -0000	1.3
@@ -15,11 +15,12 @@
 	const char *dn;
 	const char *dnpass;
 	const char *deref;
+	const char *scope;
 	const char *base;
 	const char *attrs;
 	const char *filter;
 
-	int ldap_deref;
+	int ldap_deref, ldap_scope;
 };
 
 struct ldap_connection {

Index: passdb.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/passdb.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- passdb.c	31 Jan 2003 06:56:58 -0000	1.2
+++ passdb.c	11 Feb 2003 09:55:58 -0000	1.3
@@ -11,8 +11,12 @@
 const char *passdb_credentials_to_str(enum passdb_credentials credentials)
 {
 	switch (credentials) {
+	case _PASSDB_CREDENTIALS_INTERNAL:
+		break;
 	case PASSDB_CREDENTIALS_PLAINTEXT:
 		return "plaintext";
+	case PASSDB_CREDENTIALS_CRYPT:
+		return "crypt";
 	case PASSDB_CREDENTIALS_DIGEST_MD5:
 		return "digest-md5";
 	}
@@ -52,6 +56,10 @@
 #ifdef PASSDB_VPOPMAIL
 	if (strcasecmp(name, "vpopmail") == 0)
 		passdb = &passdb_vpopmail;
+#endif
+#ifdef USERDB_LDAP
+	if (strcasecmp(name, "ldap") == 0)
+		passdb = &passdb_ldap;
 #endif
 
 	if (passdb == NULL)

Index: passdb.h
===================================================================
RCS file: /home/cvs/dovecot/src/auth/passdb.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- passdb.h	2 Feb 2003 00:08:28 -0000	1.3
+++ passdb.h	11 Feb 2003 09:55:58 -0000	1.4
@@ -7,7 +7,10 @@
 	((pass)[0] != '\0' && (pass)[0] != '*' && (pass)[0] != '!')
 
 enum passdb_credentials {
+	_PASSDB_CREDENTIALS_INTERNAL = -1,
+
 	PASSDB_CREDENTIALS_PLAINTEXT,
+	PASSDB_CREDENTIALS_CRYPT,
 	PASSDB_CREDENTIALS_DIGEST_MD5
 };
 
@@ -49,6 +52,7 @@
 extern struct passdb_module passdb_passwd_file;
 extern struct passdb_module passdb_pam;
 extern struct passdb_module passdb_vpopmail;
+extern struct passdb_module passdb_ldap;
 
 void passdb_init(void);
 void passdb_deinit(void);

Index: userdb-ldap.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/userdb-ldap.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- userdb-ldap.c	4 Feb 2003 03:24:38 -0000	1.3
+++ userdb-ldap.c	11 Feb 2003 09:55:58 -0000	1.4
@@ -6,6 +6,8 @@
 #ifdef USERDB_LDAP
 
 #include "common.h"
+#include "str.h"
+#include "var-expand.h"
 #include "db-ldap.h"
 #include "userdb.h"
 
@@ -98,6 +100,7 @@
 	entry = ldap_first_entry(conn->ld, res);
 	if (entry == NULL) {
 		i_error("LDAP: ldap_first_entry failed()");
+		urequest->userdb_callback(NULL, request->context);
 		return;
 	}
 
@@ -115,9 +118,10 @@
 		attr = ldap_next_attribute(conn->ld, entry, ber);
 	}
 
-	if (user.virtual_user == NULL)
+	if (user.virtual_user == NULL) {
 		i_error("LDAP: No username in reply");
-	else {
+		urequest->userdb_callback(NULL, request->context);
+	} else {
 		if (ldap_next_entry(conn->ld, entry) != NULL) {
 			i_error("LDAP: Multiple replies found for user %s",
 				user.virtual_user);
@@ -135,6 +139,7 @@
 	struct ldap_connection *conn = userdb_ldap_conn->conn;
 	struct userdb_ldap_request *request;
 	const char *filter;
+	string_t *str;
 
 	if (realm != NULL)
 		user = t_strconcat(user, "@", realm, NULL);
@@ -143,8 +148,9 @@
 		filter = t_strdup_printf("(&(objectClass=posixAccount)(%s=%s))",
 			userdb_ldap_conn->attr_names[ATTR_VIRTUAL_USER], user);
 	} else {
-		filter = t_strdup_printf("(&%s(%s=%s))", conn->set.filter,
-			userdb_ldap_conn->attr_names[ATTR_VIRTUAL_USER], user);
+		str = t_str_new(512);
+		var_expand(str, conn->set.filter, user, NULL);
+		filter = str_c(str);
 	}
 
 	request = i_new(struct userdb_ldap_request, 1);
@@ -152,7 +158,7 @@
 	request->request.context = context;
 	request->userdb_callback = callback;
 
-	db_ldap_search(conn, conn->set.base, LDAP_SCOPE_SUBTREE,
+	db_ldap_search(conn, conn->set.base, conn->set.ldap_scope,
 		       filter, userdb_ldap_conn->attr_names,
 		       &request->request);
 }




More information about the dovecot-cvs mailing list