Mercurial > dovecot > original-hg > dovecot-1.2
view src/auth/passdb-ldap.c @ 2942:c7d426f8cb58 HEAD
Added name variable for userdb_module and passdb_module and changed their
initialization a bit.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 06 Dec 2004 18:39:02 +0200 |
parents | b66dd3188e6a |
children | 1ed01cfed3a9 |
line wrap: on
line source
/* 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 "password-scheme.h" #include "db-ldap.h" #include "passdb.h" #include "passdb-cache.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 char *passdb_ldap_cache_key; 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, *scheme; int ret; user = auth_request->user; password = NULL; if (res != NULL) { ret = ldap_result2error(conn->ld, res, 0); if (ret != LDAP_SUCCESS) { i_error("ldap(%s): ldap_search() failed: %s", get_log_prefix(auth_request), ldap_err2string(ret)); res = NULL; } } entry = res == NULL ? NULL : ldap_first_entry(conn->ld, res); if (entry == NULL) { if (res != NULL && verbose) { i_info("ldap(%s): unknown user", get_log_prefix(auth_request)); } } 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", get_log_prefix(auth_request)); } else if (ldap_next_entry(conn->ld, entry) != NULL) { i_error("ldap(%s): Multiple password replies", get_log_prefix(auth_request)); password = NULL; } } /* LDAP result is free'd now. we can check if auth_request is even needed anymore */ if (!auth_request_unref(auth_request)) return; scheme = password_get_scheme(&password); if (scheme == NULL) { scheme = conn->set.default_pass_scheme; i_assert(scheme != NULL); } if (ldap_request->credentials != -1) { passdb_handle_credentials(ldap_request->credentials, password, scheme, ldap_request->callback.lookup_credentials, auth_request); i_free(request); return; } /* verify plain */ if (password == NULL) { ldap_request->callback.verify_plain(PASSDB_RESULT_USER_UNKNOWN, auth_request); i_free(request); return; } ret = password_verify(ldap_request->password, password, scheme, user); if (ret < 0) { i_error("ldap(%s): Unknown password scheme %s", get_log_prefix(auth_request), scheme); } else if (ret == 0) { if (verbose) { i_info("ldap(%s): password mismatch", get_log_prefix(auth_request)); } } ldap_request->callback.verify_plain(ret > 0 ? PASSDB_RESULT_OK : PASSDB_RESULT_PASSWORD_MISMATCH, auth_request); i_free(request); } 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 *filter; string_t *str; if (conn->set.pass_filter == NULL) { filter = t_strdup_printf("(&(objectClass=posixAccount)(%s=%s))", passdb_ldap_conn->attr_names[ATTR_VIRTUAL_USER], ldap_escape(auth_request->user)); } else { str = t_str_new(512); var_expand(str, conn->set.pass_filter, auth_request_get_var_expand_table(auth_request, ldap_escape)); filter = str_c(str); } auth_request_ref(auth_request); 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 ldap_connection *conn = passdb_ldap_conn->conn; struct passdb_ldap_request *ldap_request; enum passdb_result result; if (passdb_cache_verify_plain(request, passdb_ldap_cache_key, password, conn->set.default_pass_scheme, &result)) { callback(result, request); return; } 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; const char *result, *scheme; if (passdb_cache_lookup_credentials(request, passdb_ldap_cache_key, &result, &scheme)) { if (scheme == NULL) { scheme = passdb_ldap_conn->conn->set. default_pass_scheme; } passdb_handle_credentials(credentials, result, scheme, callback, request); return; } 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_preinit(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.pass_attrs ? conn->set.pass_attrs : DEFAULT_ATTRIBUTES, &passdb_ldap_conn->attrs, &passdb_ldap_conn->attr_names); passdb_ldap_cache_key = auth_cache_parse_key(conn->set.pass_filter); } static void passdb_ldap_init(const char *args __attr_unused__) { (void)db_ldap_connect(passdb_ldap_conn->conn); } static void passdb_ldap_deinit(void) { db_ldap_unref(passdb_ldap_conn->conn); i_free(passdb_ldap_cache_key); i_free(passdb_ldap_conn); } struct passdb_module passdb_ldap = { "ldap", passdb_ldap_preinit, passdb_ldap_init, passdb_ldap_deinit, ldap_verify_plain, ldap_lookup_credentials }; #endif