db-ldap.c revision 6ef7e31619edfaa17ed044b45861d106a86191ef
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen/* Copyright (C) 2003 Timo Sirainen */
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
2fbc2a7c65d30e46803195ebb4547176b85c22c7Timo Sirainen#include "common.h"
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#if defined(PASSDB_LDAP) || defined(USERDB_LDAP)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen#include "network.h"
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#include "ioloop.h"
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#include "hash.h"
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen#include "str.h"
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#include "settings.h"
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen#include "userdb.h"
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#include "db-ldap.h"
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#include <stddef.h>
0cb57ee35d4cab9c03434d7abf312c081ed554d4Timo Sirainen#include <stdlib.h>
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
a8fc29f19ea6e2d472ba779b2dd5ca4e1f3dac79Timo Sirainen/* Older versions may require calling ldap_result() twice */
a8fc29f19ea6e2d472ba779b2dd5ca4e1f3dac79Timo Sirainen#if LDAP_VENDOR_VERSION <= 20112
3e1ded79bbc9166aa221bcf62d8eb2bee179c557Timo Sirainen# define OPENLDAP_ASYNC_WORKAROUND
3e1ded79bbc9166aa221bcf62d8eb2bee179c557Timo Sirainen#endif
3e1ded79bbc9166aa221bcf62d8eb2bee179c557Timo Sirainen
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen/* Solaris LDAP library doesn't have LDAP_OPT_SUCCESS */
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen#ifndef LDAP_OPT_SUCCESS
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen# define LDAP_OPT_SUCCESS LDAP_SUCCESS
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen#endif
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#define DEF(type, name) \
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen { type, #name, offsetof(struct ldap_settings, name) }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstatic struct setting_def setting_defs[] = {
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen DEF(SET_STR, hosts),
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen DEF(SET_STR, uris),
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen DEF(SET_STR, dn),
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen DEF(SET_STR, dnpass),
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen DEF(SET_BOOL, auth_bind),
f1ddb98e6b639394ae205b305be1ddcfab102578Timo Sirainen DEF(SET_STR, auth_bind_userdn),
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen DEF(SET_STR, deref),
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen DEF(SET_STR, scope),
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen DEF(SET_STR, base),
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen DEF(SET_INT, ldap_version),
10c5fd417af4ee30b68c967f5e7d5a49f4f149b5Timo Sirainen DEF(SET_STR, user_attrs),
10c5fd417af4ee30b68c967f5e7d5a49f4f149b5Timo Sirainen DEF(SET_STR, user_filter),
10c5fd417af4ee30b68c967f5e7d5a49f4f149b5Timo Sirainen DEF(SET_STR, pass_attrs),
1f18053d463f0294387b5e4dd11f9010bda9a24eTimo Sirainen DEF(SET_STR, pass_filter),
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen DEF(SET_STR, default_pass_scheme),
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen DEF(SET_STR, user_global_uid),
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen DEF(SET_STR, user_global_gid)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen};
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstruct ldap_settings default_ldap_settings = {
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen MEMBER(hosts) NULL,
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen MEMBER(uris) NULL,
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen MEMBER(dn) NULL,
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen MEMBER(dnpass) NULL,
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen MEMBER(auth_bind) FALSE,
f1ddb98e6b639394ae205b305be1ddcfab102578Timo Sirainen MEMBER(auth_bind_userdn) NULL,
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen MEMBER(deref) "never",
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen MEMBER(scope) "subtree",
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen MEMBER(base) NULL,
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen MEMBER(ldap_version) 2,
5a8b0ce25f7838652b4a0cb9dab0ad19ec0fab25Timo Sirainen MEMBER(user_attrs) "uid,homeDirectory,,,uidNumber,gidNumber",
5a8b0ce25f7838652b4a0cb9dab0ad19ec0fab25Timo Sirainen MEMBER(user_filter) "(&(objectClass=posixAccount)(uid=%u))",
5a8b0ce25f7838652b4a0cb9dab0ad19ec0fab25Timo Sirainen MEMBER(pass_attrs) "uid,userPassword",
5a8b0ce25f7838652b4a0cb9dab0ad19ec0fab25Timo Sirainen MEMBER(pass_filter) "(&(objectClass=posixAccount)(uid=%u))",
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen MEMBER(default_pass_scheme) "crypt",
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen MEMBER(user_global_uid) "",
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen MEMBER(user_global_gid) ""
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen};
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
c4457e497e01b57565d24da624968699b166e02aTimo Sirainenstatic struct ldap_connection *ldap_connections = NULL;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic void ldap_conn_close(struct ldap_connection *conn, bool flush_requests);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstatic int deref2str(const char *str)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (strcasecmp(str, "never") == 0)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return LDAP_DEREF_NEVER;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (strcasecmp(str, "searching") == 0)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return LDAP_DEREF_SEARCHING;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (strcasecmp(str, "finding") == 0)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return LDAP_DEREF_FINDING;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (strcasecmp(str, "always") == 0)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return LDAP_DEREF_ALWAYS;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen i_fatal("LDAP: Unknown deref option '%s'", str);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainenstatic int scope2str(const char *str)
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen{
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen if (strcasecmp(str, "base") == 0)
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen return LDAP_SCOPE_BASE;
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen if (strcasecmp(str, "onelevel") == 0)
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen return LDAP_SCOPE_ONELEVEL;
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen if (strcasecmp(str, "subtree") == 0)
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen return LDAP_SCOPE_SUBTREE;
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen i_fatal("LDAP: Unknown scope option '%s'", str);
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen}
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainenconst char *ldap_get_error(struct ldap_connection *conn)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen int ret, err;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen ret = ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, (void *) &err);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (ret != LDAP_SUCCESS) {
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen i_error("LDAP: Can't get error number: %s",
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen ldap_err2string(ret));
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return "??";
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return ldap_err2string(err);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainenvoid db_ldap_search(struct ldap_connection *conn, struct ldap_request *request,
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen int scope)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen int msgid;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (!conn->connected) {
08aea01ef9a9d20703e0fcf8618e6195c0037a44Timo Sirainen if (!db_ldap_connect(conn)) {
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen request->callback(conn, request, NULL);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen msgid = ldap_search(conn->ld, request->base, scope,
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen request->filter, request->attributes, 0);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (msgid == -1) {
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen i_error("LDAP: ldap_search() failed (filter %s): %s",
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen request->filter, ldap_get_error(conn));
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen request->callback(conn, request, NULL);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen hash_insert(conn->requests, POINTER_CAST(msgid), request);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainenstatic void ldap_conn_retry_requests(struct ldap_connection *conn)
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen{
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen struct hash_table *old_requests;
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen struct hash_iterate_context *iter;
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen void *key, *value;
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen i_assert(conn->connected);
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen if (hash_size(conn->requests) == 0)
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen return;
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen old_requests = conn->requests;
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen conn->requests = hash_create(default_pool, conn->pool, 0, NULL, NULL);
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen iter = hash_iterate_init(old_requests);
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen while (hash_iterate(iter, &key, &value)) {
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen struct ldap_request *request = value;
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen i_assert(conn->connected);
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen db_ldap_search(conn, request, conn->set.ldap_scope);
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen }
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen hash_iterate_deinit(iter);
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen hash_destroy(old_requests);
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen}
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainenstatic void ldap_conn_reconnect(struct ldap_connection *conn)
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen{
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen ldap_conn_close(conn, FALSE);
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen if (!db_ldap_connect(conn)) {
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen /* failed to reconnect. fail all requests. */
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen ldap_conn_close(conn, TRUE);
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen }
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen}
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstatic void ldap_input(void *context)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct ldap_connection *conn = context;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct ldap_request *request;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct timeval timeout;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen LDAPMessage *res;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen int ret, msgid;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen while (conn->ld != NULL) {
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen memset(&timeout, 0, sizeof(timeout));
a8fc29f19ea6e2d472ba779b2dd5ca4e1f3dac79Timo Sirainen ret = ldap_result(conn->ld, LDAP_RES_ANY, 1, &timeout, &res);
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen#ifdef OPENLDAP_ASYNC_WORKAROUND
a8fc29f19ea6e2d472ba779b2dd5ca4e1f3dac79Timo Sirainen if (ret == 0) {
a8fc29f19ea6e2d472ba779b2dd5ca4e1f3dac79Timo Sirainen /* try again, there may be another in buffer */
a8fc29f19ea6e2d472ba779b2dd5ca4e1f3dac79Timo Sirainen ret = ldap_result(conn->ld, LDAP_RES_ANY, 1,
a8fc29f19ea6e2d472ba779b2dd5ca4e1f3dac79Timo Sirainen &timeout, &res);
a8fc29f19ea6e2d472ba779b2dd5ca4e1f3dac79Timo Sirainen }
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen#endif
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (ret <= 0) {
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (ret < 0) {
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen i_error("LDAP: ldap_result() failed: %s",
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen ldap_get_error(conn));
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen ldap_conn_reconnect(conn);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen msgid = ldap_msgid(res);
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen request = hash_lookup(conn->requests, POINTER_CAST(msgid));
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen if (request == NULL) {
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen i_error("LDAP: Reply with unknown msgid %d",
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen msgid);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen } else {
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen hash_remove(conn->requests, POINTER_CAST(msgid));
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen request->callback(conn, request, res);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen ldap_msgfree(res);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenbool db_ldap_connect(struct ldap_connection *conn)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen int ret, fd;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (conn->connected)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return TRUE;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (conn->ld == NULL) {
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen if (conn->set.uris != NULL) {
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen#ifdef LDAP_HAVE_INITIALIZE
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen if (ldap_initialize(&conn->ld, conn->set.uris) != LDAP_SUCCESS)
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen conn->ld = NULL;
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen#else
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen i_fatal("LDAP: Your LDAP library doesn't support "
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen "'uris' setting, use 'hosts' instead.");
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen#endif
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen } else
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen conn->ld = ldap_init(conn->set.hosts, LDAP_PORT);
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (conn->ld == NULL)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen i_fatal("LDAP: ldap_init() failed with hosts: %s",
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->set.hosts);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen ret = ldap_set_option(conn->ld, LDAP_OPT_DEREF,
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen (void *) &conn->set.ldap_deref);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (ret != LDAP_SUCCESS) {
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen i_fatal("LDAP: Can't set deref option: %s",
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen ldap_err2string(ret));
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen ret = ldap_set_option(conn->ld, LDAP_OPT_PROTOCOL_VERSION,
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen (void *) &conn->set.ldap_version);
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen if (ret != LDAP_OPT_SUCCESS) {
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen i_fatal("LDAP: Can't set protocol version %u: %s",
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen conn->set.ldap_version, ldap_err2string(ret));
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen /* FIXME: we shouldn't use blocking bind */
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen ret = ldap_simple_bind_s(conn->ld, conn->set.dn, conn->set.dnpass);
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen if (ret == LDAP_SERVER_DOWN) {
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen i_error("LDAP: Can't connect to server: %s", conn->set.hosts);
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen return FALSE;
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (ret != LDAP_SUCCESS) {
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen i_error("LDAP: ldap_simple_bind_s() failed (dn %s): %s",
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen conn->set.dn == NULL ? "(none)" : conn->set.dn,
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen ldap_get_error(conn));
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return FALSE;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->connected = TRUE;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen /* register LDAP input to ioloop */
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen ret = ldap_get_option(conn->ld, LDAP_OPT_DESC, (void *) &fd);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (ret != LDAP_SUCCESS) {
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen i_fatal("LDAP: Can't get connection fd: %s",
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen ldap_err2string(ret));
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen net_set_nonblock(fd, TRUE);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->io = io_add(fd, IO_READ, ldap_input, conn);
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen /* in case there are requests waiting, retry them */
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen ldap_conn_retry_requests(conn);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return TRUE;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic void ldap_conn_close(struct ldap_connection *conn, bool flush_requests)
095034a7699bfc464a07883f633551b5c313c4e7Timo Sirainen{
9e7182d6fa1940ec14cc2938699820b68ee1dc0dTimo Sirainen struct hash_iterate_context *iter;
9e7182d6fa1940ec14cc2938699820b68ee1dc0dTimo Sirainen void *key, *value;
095034a7699bfc464a07883f633551b5c313c4e7Timo Sirainen
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen if (flush_requests) {
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen iter = hash_iterate_init(conn->requests);
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen while (hash_iterate(iter, &key, &value)) {
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen struct ldap_request *request = value;
095034a7699bfc464a07883f633551b5c313c4e7Timo Sirainen
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen request->callback(conn, request, NULL);
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen }
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen hash_iterate_deinit(iter);
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen hash_clear(conn->requests, FALSE);
9e7182d6fa1940ec14cc2938699820b68ee1dc0dTimo Sirainen }
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen conn->connected = FALSE;
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen if (conn->io != NULL) {
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen io_remove(conn->io);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->io = NULL;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (conn->ld != NULL) {
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen ldap_unbind(conn->ld);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->ld = NULL;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainenvoid db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
0d7d27765267594a5870892268ab345148306d49Timo Sirainen char ***attr_names_r, struct hash_table *attr_map,
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen const char *const default_attr_map[])
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen const char *const *attr;
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen char *name, *value, *p;
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen unsigned int i, size;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen if (*attrlist == '\0')
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen return;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen t_push();
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen attr = t_strsplit(attrlist, ",");
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
0e90e1b11b699166a4a4c5e01d132a28c3e26affTimo Sirainen /* @UNSAFE */
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen for (size = 0; attr[size] != NULL; size++) ;
0d7d27765267594a5870892268ab345148306d49Timo Sirainen *attr_names_r = p_new(conn->pool, char *, size + 1);
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen for (i = 0; i < size; i++) {
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen p = strchr(attr[i], '=');
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen if (p == NULL) {
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen name = p_strdup(conn->pool, attr[i]);
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen value = *default_attr_map == NULL ? name :
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen p_strdup(conn->pool, *default_attr_map);
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen } else {
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen name = p_strdup_until(conn->pool, attr[i], p);
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen value = p_strdup(conn->pool, p + 1);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen
0d7d27765267594a5870892268ab345148306d49Timo Sirainen (*attr_names_r)[i] = name;
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen if (*name != '\0')
0d7d27765267594a5870892268ab345148306d49Timo Sirainen hash_insert(attr_map, name, value);
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen if (*default_attr_map != NULL)
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen default_attr_map++;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen t_pop();
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen#define IS_LDAP_ESCAPED_CHAR(c) \
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen ((c) == '*' || (c) == '(' || (c) == ')' || (c) == '\\')
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainenconst char *ldap_escape(const char *str)
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen{
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen const char *p;
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen string_t *ret;
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen for (p = str; *p != '\0'; p++) {
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen if (IS_LDAP_ESCAPED_CHAR(*p))
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen break;
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen }
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen if (*p == '\0')
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen return str;
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen ret = t_str_new((size_t) (p - str) + 64);
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen str_append_n(ret, str, (size_t) (p - str));
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen for (; *p != '\0'; p++) {
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen if (IS_LDAP_ESCAPED_CHAR(*p))
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen str_append_c(ret, '\\');
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen str_append_c(ret, *p);
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen }
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen return str_c(ret);
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen}
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstatic const char *parse_setting(const char *key, const char *value,
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen void *context)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct ldap_connection *conn = context;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return parse_setting_from_defs(conn->pool, setting_defs,
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen &conn->set, key, value);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
c4457e497e01b57565d24da624968699b166e02aTimo Sirainenstatic struct ldap_connection *ldap_conn_find(const char *config_path)
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen{
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen struct ldap_connection *conn;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen for (conn = ldap_connections; conn != NULL; conn = conn->next) {
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen if (strcmp(conn->config_path, config_path) == 0)
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen return conn;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen }
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen return NULL;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen}
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstruct ldap_connection *db_ldap_init(const char *config_path)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct ldap_connection *conn;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen pool_t pool;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen /* see if it already exists */
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen conn = ldap_conn_find(config_path);
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen if (conn != NULL) {
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen conn->refcount++;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen return conn;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen }
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen pool = pool_alloconly_create("ldap_connection", 1024);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn = p_new(pool, struct ldap_connection, 1);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->pool = pool;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->refcount = 1;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->requests = hash_create(default_pool, pool, 0, NULL, NULL);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen conn->config_path = p_strdup(pool, config_path);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->set = default_ldap_settings;
0cb57ee35d4cab9c03434d7abf312c081ed554d4Timo Sirainen if (!settings_read(config_path, NULL, parse_setting, NULL, conn))
0cb57ee35d4cab9c03434d7abf312c081ed554d4Timo Sirainen exit(FATAL_DEFAULT);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (conn->set.base == NULL)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen i_fatal("LDAP: No base given");
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->set.ldap_deref = deref2str(conn->set.deref);
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen conn->set.ldap_scope = scope2str(conn->set.scope);
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen if (*conn->set.user_global_uid == '\0')
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen conn->set.uid = (uid_t)-1;
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen else {
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen conn->set.uid =
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen userdb_parse_uid(NULL, conn->set.user_global_uid);
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen if (conn->set.uid == (uid_t)-1) {
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen i_fatal("LDAP: Invalid user_global_uid: %s",
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen conn->set.user_global_uid);
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen }
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen }
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen if (*conn->set.user_global_gid == '\0')
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen conn->set.gid = (gid_t)-1;
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen else {
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen conn->set.gid =
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen userdb_parse_gid(NULL, conn->set.user_global_gid);
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen if (conn->set.gid == (gid_t)-1) {
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen i_fatal("LDAP: Invalid user_global_gid: %s",
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen conn->set.user_global_gid);
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen }
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen conn->next = ldap_connections;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen ldap_connections = conn;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return conn;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenvoid db_ldap_unref(struct ldap_connection *conn)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct ldap_connection **p;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen i_assert(conn->refcount >= 0);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (--conn->refcount > 0)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen for (p = &ldap_connections; *p != NULL; p = &(*p)->next) {
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen if (*p == conn) {
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen *p = conn->next;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen break;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen }
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen ldap_conn_close(conn, TRUE);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen hash_destroy(conn->requests);
0d7d27765267594a5870892268ab345148306d49Timo Sirainen if (conn->pass_attr_map != NULL)
0d7d27765267594a5870892268ab345148306d49Timo Sirainen hash_destroy(conn->pass_attr_map);
0d7d27765267594a5870892268ab345148306d49Timo Sirainen if (conn->user_attr_map != NULL)
0d7d27765267594a5870892268ab345148306d49Timo Sirainen hash_destroy(conn->user_attr_map);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen pool_unref(conn->pool);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#endif