[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