db-ldap.c revision 76b43e4417bab52e913da39b5f5bc2a130d3f149
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2003-2008 Dovecot authors, see the included COPYING file */
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"
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen#include "array.h"
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#include "hash.h"
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen#include "aqueue.h"
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen#include "str.h"
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen#include "var-expand.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
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen#define HAVE_LDAP_SASL
d8c2d988a913d1aae9abf2dd50c611c87d81d72aTimo Sirainen#ifdef HAVE_SASL_SASL_H
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen# include <sasl/sasl.h>
d8c2d988a913d1aae9abf2dd50c611c87d81d72aTimo Sirainen#elif defined (HAVE_SASL_H)
d8c2d988a913d1aae9abf2dd50c611c87d81d72aTimo Sirainen# include <sasl.h>
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen#else
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen# undef HAVE_LDAP_SASL
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen#endif
d8c2d988a913d1aae9abf2dd50c611c87d81d72aTimo Sirainen#if SASL_VERSION_MAJOR < 2
d8c2d988a913d1aae9abf2dd50c611c87d81d72aTimo Sirainen# undef HAVE_LDAP_SASL
d8c2d988a913d1aae9abf2dd50c611c87d81d72aTimo Sirainen#endif
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen
594d203bdcbd160688bce5d5a6d65783b919ad49Timo Sirainen#ifndef LDAP_SASL_QUIET
594d203bdcbd160688bce5d5a6d65783b919ad49Timo Sirainen# define LDAP_SASL_QUIET 0 /* Doesn't exist in Solaris LDAP */
594d203bdcbd160688bce5d5a6d65783b919ad49Timo Sirainen#endif
594d203bdcbd160688bce5d5a6d65783b919ad49Timo 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
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainenstruct db_ldap_result_iterate_context {
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen struct ldap_connection *conn;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen LDAPMessage *entry;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen struct auth_request *auth_request;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen struct hash_table *attr_map;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen struct var_expand_table *var_table;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen char *attr, **vals;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen const char *name, *value, *template, *val_1_arr[2];
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen const char *const *static_attrs;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen BerElement *ber;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen string_t *var, *debug;
fb5abffb7097b3c5f167deff6ae293d2f828695bTimo Sirainen unsigned int value_idx;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen};
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstruct db_ldap_sasl_bind_context {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen const char *authcid;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen const char *passwd;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen const char *realm;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen const char *authzid;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen};
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen#define DEF_STR(name) DEF_STRUCT_STR(name, ldap_settings)
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen#define DEF_INT(name) DEF_STRUCT_INT(name, ldap_settings)
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, ldap_settings)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstatic struct setting_def setting_defs[] = {
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(hosts),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(uris),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(dn),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(dnpass),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_BOOL(auth_bind),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(auth_bind_userdn),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_BOOL(tls),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_BOOL(sasl_bind),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(sasl_mech),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(sasl_realm),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(sasl_authz_id),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(deref),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(scope),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(base),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_INT(ldap_version),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(user_attrs),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(user_filter),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(pass_attrs),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(pass_filter),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(default_pass_scheme),
e25885d4c7c4b392c66bbf26a9b892362d90f001Timo Sirainen
e25885d4c7c4b392c66bbf26a9b892362d90f001Timo Sirainen { 0, NULL, 0 }
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,
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen MEMBER(tls) FALSE,
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen MEMBER(sasl_bind) FALSE,
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen MEMBER(sasl_mech) NULL,
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen MEMBER(sasl_realm) NULL,
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen MEMBER(sasl_authz_id) NULL,
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen MEMBER(deref) "never",
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen MEMBER(scope) "subtree",
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen MEMBER(base) NULL,
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen MEMBER(ldap_version) 2,
e53ca064060239939bd554a562ba007367dac8edTimo Sirainen MEMBER(user_attrs) "homeDirectory=home,uidNumber=uid,gidNumber=gid",
5a8b0ce25f7838652b4a0cb9dab0ad19ec0fab25Timo Sirainen MEMBER(user_filter) "(&(objectClass=posixAccount)(uid=%u))",
e53ca064060239939bd554a562ba007367dac8edTimo Sirainen MEMBER(pass_attrs) "uid=user,userPassword=password",
5a8b0ce25f7838652b4a0cb9dab0ad19ec0fab25Timo Sirainen MEMBER(pass_filter) "(&(objectClass=posixAccount)(uid=%u))",
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen MEMBER(default_pass_scheme) "crypt"
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen};
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
c4457e497e01b57565d24da624968699b166e02aTimo Sirainenstatic struct ldap_connection *ldap_connections = NULL;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainenstatic int db_ldap_bind(struct ldap_connection *conn);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic void db_ldap_conn_close(struct ldap_connection *conn);
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
78361883c67c58e339697c167ca285731f50287bTimo Sirainenstatic int ldap_get_errno(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));
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen return LDAP_UNAVAILABLE;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
78361883c67c58e339697c167ca285731f50287bTimo Sirainen return err;
78361883c67c58e339697c167ca285731f50287bTimo Sirainen}
78361883c67c58e339697c167ca285731f50287bTimo Sirainen
78361883c67c58e339697c167ca285731f50287bTimo Sirainenconst char *ldap_get_error(struct ldap_connection *conn)
78361883c67c58e339697c167ca285731f50287bTimo Sirainen{
78361883c67c58e339697c167ca285731f50287bTimo Sirainen return ldap_err2string(ldap_get_errno(conn));
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainenstatic void ldap_conn_reconnect(struct ldap_connection *conn)
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_conn_close(conn);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (db_ldap_connect(conn) < 0)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_conn_close(conn);
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen}
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic int ldap_handle_error(struct ldap_connection *conn)
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen{
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen int err = ldap_get_errno(conn);
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen switch (err) {
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_SUCCESS:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen i_unreached();
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_SIZELIMIT_EXCEEDED:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_TIMELIMIT_EXCEEDED:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_NO_SUCH_ATTRIBUTE:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_UNDEFINED_TYPE:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_INAPPROPRIATE_MATCHING:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_CONSTRAINT_VIOLATION:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_TYPE_OR_VALUE_EXISTS:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_INVALID_SYNTAX:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_NO_SUCH_OBJECT:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_ALIAS_PROBLEM:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_INVALID_DN_SYNTAX:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_IS_LEAF:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_ALIAS_DEREF_PROBLEM:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_FILTER_ERROR:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen /* invalid input */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return -1;
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_SERVER_DOWN:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_TIMEOUT:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_UNAVAILABLE:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_BUSY:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen#ifdef LDAP_CONNECT_ERROR
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_CONNECT_ERROR:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen#endif
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_LOCAL_ERROR:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_INVALID_CREDENTIALS:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen default:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen /* connection problems */
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen ldap_conn_reconnect(conn);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return 0;
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen }
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen}
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic int db_ldap_request_bind(struct ldap_connection *conn,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request *request)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request_bind *brequest =
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen (struct ldap_request_bind *)request;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(request->type == LDAP_REQUEST_TYPE_BIND);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(request->msgid == -1);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->conn_state == LDAP_CONN_STATE_BOUND_AUTH ||
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state == LDAP_CONN_STATE_BOUND_DEFAULT);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count == 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->msgid = ldap_bind(conn->ld, brequest->dn,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->auth_request->mech_password,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen LDAP_AUTH_SIMPLE);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (request->msgid == -1) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen auth_request_log_error(request->auth_request, "ldap",
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen "ldap_bind(%s) failed: %s",
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen brequest->dn, ldap_get_error(conn));
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (ldap_handle_error(conn) < 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* broken request, remove it */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return 0;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return -1;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state = LDAP_CONN_STATE_BINDING;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return 1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen}
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic int db_ldap_request_search(struct ldap_connection *conn,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request *request)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request_search *srequest =
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen (struct ldap_request_search *)request;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->conn_state == LDAP_CONN_STATE_BOUND_DEFAULT);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(request->msgid == -1);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->msgid =
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ldap_search(conn->ld, srequest->base, conn->set.ldap_scope,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen srequest->filter, srequest->attributes, 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (request->msgid == -1) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen auth_request_log_error(request->auth_request, "ldap",
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen "ldap_search() failed (filter %s): %s",
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen srequest->filter, ldap_get_error(conn));
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (ldap_handle_error(conn) < 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* broken request, remove it */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return 0;
1a59321a1116f9819e7b2899379a44de339ce802Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return -1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return 1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen}
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic bool db_ldap_request_queue_next(struct ldap_connection *conn)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request *const *requestp, *request;
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen unsigned int queue_size = aqueue_count(conn->request_queue);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen int ret = -1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (conn->pending_count == queue_size) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* no non-pending requests */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return FALSE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (queue_size > DB_LDAP_MAX_PENDING_REQUESTS) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* wait until server has replied to some requests */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return FALSE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
1a59321a1116f9819e7b2899379a44de339ce802Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (db_ldap_connect(conn) < 0)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return FALSE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen requestp = array_idx(&conn->request_array,
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen aqueue_idx(conn->request_queue,
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen conn->pending_count));
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request = *requestp;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (conn->pending_count > 0 &&
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->type == LDAP_REQUEST_TYPE_BIND) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* we can't do binds until all existing requests are finished */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return FALSE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen switch (conn->conn_state) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen case LDAP_CONN_STATE_DISCONNECTED:
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen case LDAP_CONN_STATE_BINDING:
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* wait until we're in bound state */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return FALSE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen case LDAP_CONN_STATE_BOUND_AUTH:
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (request->type == LDAP_REQUEST_TYPE_BIND)
0c822051bb9a910ee588fd97f7ec6f9df3d1b3c6Timo Sirainen break;
0c822051bb9a910ee588fd97f7ec6f9df3d1b3c6Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* bind to default dn first */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count == 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen (void)db_ldap_bind(conn);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return FALSE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen case LDAP_CONN_STATE_BOUND_DEFAULT:
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* we can do anything in this state */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen break;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen switch (request->type) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen case LDAP_REQUEST_TYPE_BIND:
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ret = db_ldap_request_bind(conn, request);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen break;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen case LDAP_REQUEST_TYPE_SEARCH:
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ret = db_ldap_request_search(conn, request);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen break;
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen }
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (ret > 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* success */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(request->msgid != -1);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->pending_count++;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return TRUE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen } else if (ret < 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* disconnected */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return FALSE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen } else {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* broken request, remove from queue */
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen aqueue_delete_tail(conn->request_queue);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->callback(conn, request, NULL);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return TRUE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenvoid db_ldap_request(struct ldap_connection *conn,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request *request)
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->msgid = -1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->create_time = ioloop_time;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (conn->request_queue->full &&
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen aqueue_count(conn->request_queue) >= DB_LDAP_MAX_QUEUE_SIZE) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* Queue is full already, fail this request */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen auth_request_log_error(request->auth_request, "ldap",
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen "Request queue is full");
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->callback(conn, request, NULL);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen aqueue_append(conn->request_queue, &request);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen (void)db_ldap_request_queue_next(conn);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen}
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic int db_ldap_connect_finish(struct ldap_connection *conn, int ret)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (ret == LDAP_SERVER_DOWN) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_error("LDAP: Can't connect to server: %s",
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->set.uris != NULL ?
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->set.uris : conn->set.hosts);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return -1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (ret != LDAP_SUCCESS) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_error("LDAP: binding failed (dn %s): %s",
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->set.dn == NULL ? "(none)" : conn->set.dn,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ldap_get_error(conn));
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return -1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state = LDAP_CONN_STATE_BOUND_DEFAULT;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen while (db_ldap_request_queue_next(conn))
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return 0;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen}
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic void db_ldap_default_bind_finished(struct ldap_connection *conn,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen LDAPMessage *res)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen int ret;
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count == 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->default_bind_msgid = -1;
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ret = ldap_result2error(conn->ld, res, FALSE);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (db_ldap_connect_finish(conn, ret) < 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* lost connection, close it */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_conn_close(conn);
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen}
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic void db_ldap_abort_requests(struct ldap_connection *conn,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen unsigned int max_count,
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen unsigned int timeout_secs,
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen bool error, const char *reason)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request *const *requestp, *request;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen time_t diff;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen while (aqueue_count(conn->request_queue) > 0 && max_count > 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen requestp = array_idx(&conn->request_array,
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen aqueue_idx(conn->request_queue, 0));
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request = *requestp;
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen diff = ioloop_time - request->create_time;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (diff < (time_t)timeout_secs)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen break;
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* timed out, abort */
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen aqueue_delete_tail(conn->request_queue);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (request->msgid != -1) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count > 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->pending_count--;
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen }
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen if (error) {
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen auth_request_log_error(request->auth_request, "ldap",
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen "%s", reason);
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen } else {
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen auth_request_log_info(request->auth_request, "ldap",
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen "%s", reason);
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->callback(conn, request, NULL);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen max_count--;
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen}
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic void
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainendb_ldap_handle_result(struct ldap_connection *conn, LDAPMessage *res)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request *const *requests, *request = NULL;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen unsigned int i, count;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen int msgid, ret;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen msgid = ldap_msgid(res);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (msgid == conn->default_bind_msgid) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_default_bind_finished(conn, res);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen }
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen count = aqueue_count(conn->request_queue);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen requests = count == 0 ? NULL : array_idx(&conn->request_array, 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen for (i = 0; i < count; i++) {
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen request = requests[aqueue_idx(conn->request_queue, i)];
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (request->msgid == msgid)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen break;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (request->msgid == -1) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request = NULL;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen break;
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen }
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (request == NULL) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_error("LDAP: Reply with unknown msgid %d", msgid);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (request->type == LDAP_REQUEST_TYPE_BIND) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->conn_state == LDAP_CONN_STATE_BINDING);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count == 1);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state = LDAP_CONN_STATE_BOUND_AUTH;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count > 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->pending_count--;
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen aqueue_delete(conn->request_queue, i);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ret = ldap_result2error(conn->ld, res, 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (ret != LDAP_SUCCESS && request->type == LDAP_REQUEST_TYPE_SEARCH) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* handle search failures here */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request_search *srequest =
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen (struct ldap_request_search *)request;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen auth_request_log_error(request->auth_request, "ldap",
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen "ldap_search(%s) failed: %s",
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen srequest->filter, ldap_err2string(ret));
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen res = NULL;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen T_FRAME(
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->callback(conn, request, res);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen );
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (i > 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* see if there are timed out requests */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_abort_requests(conn, i,
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen DB_LDAP_REQUEST_LOST_TIMEOUT_SECS,
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen TRUE, "Request lost");
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen}
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenstatic void ldap_input(struct ldap_connection *conn)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct timeval timeout;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen LDAPMessage *res;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen int ret;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen for (;;) {
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen if (conn->ld == NULL)
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen return;
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen
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
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen if (ret <= 0)
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen break;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_handle_result(conn, res);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen ldap_msgfree(res);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->last_reply_stamp = ioloop_time;
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen
d39e77e1f7f58e1e21042a673b718541fa3f63c7Timo Sirainen if (ret == 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* send more requests */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen while (db_ldap_request_queue_next(conn))
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ;
d39e77e1f7f58e1e21042a673b718541fa3f63c7Timo Sirainen } else if (ldap_get_errno(conn) != LDAP_SERVER_DOWN) {
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen i_error("LDAP: ldap_result() failed: %s", ldap_get_error(conn));
0d68d1da0825e01be3f207042b9132ae8dfc9c06Timo Sirainen ldap_conn_reconnect(conn);
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen } else if (aqueue_count(conn->request_queue) > 0 ||
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ioloop_time - conn->last_reply_stamp <
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen DB_LDAP_IDLE_RECONNECT_SECS) {
d39e77e1f7f58e1e21042a673b718541fa3f63c7Timo Sirainen i_error("LDAP: Connection lost to LDAP server, reconnecting");
d39e77e1f7f58e1e21042a673b718541fa3f63c7Timo Sirainen ldap_conn_reconnect(conn);
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen } else {
d39e77e1f7f58e1e21042a673b718541fa3f63c7Timo Sirainen /* server probably disconnected an idle connection. don't
d39e77e1f7f58e1e21042a673b718541fa3f63c7Timo Sirainen reconnect until the next request comes. */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_conn_close(conn);
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen#ifdef HAVE_LDAP_SASL
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainenstatic int
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainensasl_interact(LDAP *ld ATTR_UNUSED, unsigned flags ATTR_UNUSED,
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen void *defaults, void *interact)
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct db_ldap_sasl_bind_context *context = defaults;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen sasl_interact_t *in;
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen const char *str;
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen for (in = interact; in->id != SASL_CB_LIST_END; in++) {
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen switch (in->id) {
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen case SASL_CB_GETREALM:
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen str = context->realm;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen break;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen case SASL_CB_AUTHNAME:
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen str = context->authcid;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen break;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen case SASL_CB_USER:
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen str = context->authzid;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen break;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen case SASL_CB_PASS:
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen str = context->passwd;
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen break;
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen default:
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen str = NULL;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen break;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen }
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen if (str != NULL) {
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen in->len = strlen(str);
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen in->result = str;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen }
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen }
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen return LDAP_SUCCESS;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen}
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen#endif
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainenstatic int db_ldap_bind(struct ldap_connection *conn)
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen{
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen int msgid;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->conn_state != LDAP_CONN_STATE_BINDING);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->default_bind_msgid == -1);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count == 0);
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
763fd2ac217023c0940415379abcd5eb7a0f7ba7Timo Sirainen msgid = ldap_bind(conn->ld, conn->set.dn, conn->set.dnpass,
763fd2ac217023c0940415379abcd5eb7a0f7ba7Timo Sirainen LDAP_AUTH_SIMPLE);
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen if (msgid == -1) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(ldap_get_errno(conn) != LDAP_SUCCESS);
7cf0a6613fca9983b8a3443f9f6ef15df5a22162Timo Sirainen if (db_ldap_connect_finish(conn, ldap_get_errno(conn)) < 0) {
7cf0a6613fca9983b8a3443f9f6ef15df5a22162Timo Sirainen /* lost connection, close it */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_conn_close(conn);
7cf0a6613fca9983b8a3443f9f6ef15df5a22162Timo Sirainen }
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return -1;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen }
1a59321a1116f9819e7b2899379a44de339ce802Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state = LDAP_CONN_STATE_BINDING;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->default_bind_msgid = msgid;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return 0;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen}
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainenstatic void db_ldap_get_fd(struct ldap_connection *conn)
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen{
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen int ret;
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen /* get the connection's fd */
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen ret = ldap_get_option(conn->ld, LDAP_OPT_DESC, (void *)&conn->fd);
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen if (ret != LDAP_SUCCESS) {
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen i_fatal("LDAP: Can't get connection fd: %s",
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen ldap_err2string(ret));
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen }
d2ded6e1da2d07ac070888873ddc10999a6d87baTimo Sirainen if (conn->fd <= CLIENT_LISTEN_FD) {
d2ded6e1da2d07ac070888873ddc10999a6d87baTimo Sirainen /* Solaris LDAP library seems to be broken */
d2ded6e1da2d07ac070888873ddc10999a6d87baTimo Sirainen i_fatal("LDAP: Buggy LDAP library returned wrong fd: %d",
d2ded6e1da2d07ac070888873ddc10999a6d87baTimo Sirainen conn->fd);
d2ded6e1da2d07ac070888873ddc10999a6d87baTimo Sirainen }
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen i_assert(conn->fd != -1);
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen net_set_nonblock(conn->fd, TRUE);
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen}
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainenint db_ldap_connect(struct ldap_connection *conn)
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen{
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen unsigned int ldap_version;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen int ret;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (conn->conn_state != LDAP_CONN_STATE_DISCONNECTED)
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return 0;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count == 0);
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,
16133a719ce8b6a5b8cedd721340cc1607c43433Timo 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
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen /* If SASL binds are used, the protocol version needs to be
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen at least 3 */
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen ldap_version = conn->set.sasl_bind &&
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen conn->set.ldap_version < 3 ? 3 :
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen conn->set.ldap_version;
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen ret = ldap_set_option(conn->ld, LDAP_OPT_PROTOCOL_VERSION,
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen (void *)&ldap_version);
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen if (ret != LDAP_OPT_SUCCESS) {
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen i_fatal("LDAP: Can't set protocol version %u: %s",
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen ldap_version, ldap_err2string(ret));
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen if (conn->set.tls) {
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen#ifdef LDAP_HAVE_START_TLS_S
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen ret = ldap_start_tls_s(conn->ld, NULL, NULL);
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen if (ret != LDAP_SUCCESS) {
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen i_error("LDAP: ldap_start_tls_s() failed: %s",
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen ldap_err2string(ret));
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return -1;
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen }
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen#else
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen i_error("LDAP: Your LDAP library doesn't support TLS");
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return -1;
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen#endif
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen }
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen if (conn->set.sasl_bind) {
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen#ifdef HAVE_LDAP_SASL
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct db_ldap_sasl_bind_context context;
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen memset(&context, 0, sizeof(context));
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen context.authcid = conn->set.dn;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen context.passwd = conn->set.dnpass;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen context.realm = conn->set.sasl_realm;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen context.authzid = conn->set.sasl_authz_id;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen
efb7a523ea2f7670ca07acaaa5aeb30692ad6cd3Timo Sirainen /* There doesn't seem to be a way to do SASL binding
efb7a523ea2f7670ca07acaaa5aeb30692ad6cd3Timo Sirainen asynchronously.. */
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen ret = ldap_sasl_interactive_bind_s(conn->ld, NULL,
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen conn->set.sasl_mech,
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen NULL, NULL, LDAP_SASL_QUIET,
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen sasl_interact, &context);
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen if (db_ldap_connect_finish(conn, ret) < 0)
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return -1;
efb7a523ea2f7670ca07acaaa5aeb30692ad6cd3Timo Sirainen#else
efb7a523ea2f7670ca07acaaa5aeb30692ad6cd3Timo Sirainen i_fatal("LDAP: sasl_bind=yes but no SASL support compiled in");
efb7a523ea2f7670ca07acaaa5aeb30692ad6cd3Timo Sirainen#endif
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state = LDAP_CONN_STATE_BOUND_DEFAULT;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen } else {
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen if (db_ldap_bind(conn) < 0)
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return -1;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_get_fd(conn);
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen conn->io = io_add(conn->fd, IO_READ, ldap_input, conn);
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return 0;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic void db_ldap_disconnect_timeout(struct ldap_connection *conn)
095034a7699bfc464a07883f633551b5c313c4e7Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_abort_requests(conn, -1U,
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS,
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen FALSE, "LDAP server not connected");
095034a7699bfc464a07883f633551b5c313c4e7Timo Sirainen
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen if (aqueue_count(conn->request_queue) == 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* no requests left, remove this timeout handler */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen timeout_remove(&conn->to);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen}
095034a7699bfc464a07883f633551b5c313c4e7Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic void db_ldap_conn_close(struct ldap_connection *conn)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request *const *requests, *request;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen unsigned int i;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state = LDAP_CONN_STATE_DISCONNECTED;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->default_bind_msgid = -1;
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (conn->pending_count != 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen requests = array_idx(&conn->request_array, 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen for (i = 0; i < conn->pending_count; i++) {
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen request = requests[aqueue_idx(conn->request_queue, i)];
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(request->msgid != -1);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->msgid = -1;
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->pending_count = 0;
9e7182d6fa1940ec14cc2938699820b68ee1dc0dTimo Sirainen }
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (conn->io != NULL)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen io_remove(&conn->io);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (conn->ld != NULL) {
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen ldap_unbind(conn->ld);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->ld = NULL;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen conn->fd = -1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen if (aqueue_count(conn->request_queue) == 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (conn->to != NULL)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen timeout_remove(&conn->to);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen } else if (conn->to == NULL) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->to = timeout_add(DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS *
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen 1000/2, db_ldap_disconnect_timeout, conn);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo 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,
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen const char *skip_attr)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen const char *const *attr, *attr_data, *p;
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen string_t *static_data;
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen char *name, *value;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen unsigned int i, j, size;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen if (*attrlist == '\0')
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen return;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen attr = t_strsplit(attrlist, ",");
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen static_data = t_str_new(128);
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
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen for (i = j = 0; i < size; i++) {
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen /* allow spaces here so "foo=1, bar=2" works */
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen attr_data = attr[i];
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen while (*attr_data == ' ') attr_data++;
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen p = strchr(attr_data, '=');
acbf19bc103b663fbc311a3b2b88d586ea60c20dTimo Sirainen if (p == NULL)
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen name = value = p_strdup(conn->pool, attr_data);
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen else if (p != attr_data) {
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen name = p_strdup_until(conn->pool, attr_data, p);
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen value = p_strdup(conn->pool, p + 1);
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen } else {
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen /* =<static key>=<static value> */
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen if (str_len(static_data) > 0)
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen str_append_c(static_data, ',');
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen str_append(static_data, p + 1);
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen continue;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen
73583cff4f0ca9ee87204256ca1994adf17cb94cTimo Sirainen if (*name != '\0' &&
73583cff4f0ca9ee87204256ca1994adf17cb94cTimo Sirainen (skip_attr == NULL || strcmp(skip_attr, value) != 0)) {
0d7d27765267594a5870892268ab345148306d49Timo Sirainen hash_insert(attr_map, name, value);
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen (*attr_names_r)[j++] = name;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen if (str_len(static_data) > 0) {
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen hash_insert(attr_map, "",
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen p_strdup(conn->pool, str_c(static_data)));
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainenstruct var_expand_table *
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainendb_ldap_value_get_var_expand_table(struct auth_request *auth_request)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen{
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen const struct var_expand_table *auth_table;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen struct var_expand_table *table;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen unsigned int count;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen auth_table = auth_request_get_var_expand_table(auth_request, NULL);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen for (count = 0; auth_table[count].key != '\0'; count++) ;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen count++;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen table = t_new(struct var_expand_table, count + 1);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen table[0].key = '$';
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen memcpy(table + 1, auth_table, sizeof(*table) * count);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen return table;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen#define IS_LDAP_ESCAPED_CHAR(c) \
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen ((c) == '*' || (c) == '(' || (c) == ')' || (c) == '\\')
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainenconst char *ldap_escape(const char *str,
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen const struct auth_request *auth_request ATTR_UNUSED)
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
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainenstruct db_ldap_result_iterate_context *
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainendb_ldap_result_iterate_init(struct ldap_connection *conn, LDAPMessage *entry,
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen struct auth_request *auth_request,
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen struct hash_table *attr_map)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen{
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen struct db_ldap_result_iterate_context *ctx;
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen const char *static_data;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx = t_new(struct db_ldap_result_iterate_context, 1);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->conn = conn;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->entry = entry;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->auth_request = auth_request;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->attr_map = attr_map;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen static_data = hash_lookup(attr_map, "");
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen if (static_data != NULL)
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen ctx->static_attrs = t_strsplit(static_data, ",");
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (auth_request->auth->verbose_debug)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->debug = t_str_new(256);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->attr = ldap_first_attribute(conn->ld, entry, &ctx->ber);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen return ctx;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainenstatic void
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainendb_ldap_result_iterate_finish(struct db_ldap_result_iterate_context *ctx)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen{
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (ctx->debug != NULL && str_len(ctx->debug) > 0) {
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen auth_request_log_debug(ctx->auth_request, "ldap",
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen "result: %s", str_c(ctx->debug) + 1);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen }
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ber_free(ctx->ber, 0);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainenstatic void
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainendb_ldap_result_change_attr(struct db_ldap_result_iterate_context *ctx)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen{
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->name = hash_lookup(ctx->attr_map, ctx->attr);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (ctx->debug != NULL) {
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen str_printfa(ctx->debug, " %s(%s)=", ctx->attr,
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->name != NULL ? ctx->name : "?unknown?");
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen }
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (ctx->name == NULL || *ctx->name == '\0') {
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->value = NULL;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen return;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen }
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (strchr(ctx->name, '%') != NULL &&
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen (ctx->template = strchr(ctx->name, '=')) != NULL) {
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen /* we want to use variables */
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->name = t_strdup_until(ctx->name, ctx->template);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->template++;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (ctx->var_table == NULL) {
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->var_table = db_ldap_value_get_var_expand_table(
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->auth_request);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->var = t_str_new(256);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen }
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen }
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->vals = ldap_get_values(ctx->conn->ld, ctx->entry,
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->attr);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->value = ctx->vals[0];
fb5abffb7097b3c5f167deff6ae293d2f828695bTimo Sirainen ctx->value_idx = 0;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainenstatic void
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainendb_ldap_result_return_value(struct db_ldap_result_iterate_context *ctx)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen{
fb5abffb7097b3c5f167deff6ae293d2f828695bTimo Sirainen bool first = ctx->value_idx == 0;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (ctx->template != NULL) {
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->var_table[0].value = ctx->value;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen str_truncate(ctx->var, 0);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen var_expand(ctx->var, ctx->template, ctx->var_table);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->value = str_c(ctx->var);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen }
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (ctx->debug != NULL) {
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (!first)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen str_append_c(ctx->debug, '/');
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (ctx->auth_request->auth->verbose_debug_passwords ||
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen strcmp(ctx->name, "password") != 0)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen str_append(ctx->debug, ctx->value);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen else
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen str_append(ctx->debug, PASSWORD_HIDDEN_STR);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen }
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainenstatic bool db_ldap_result_int_next(struct db_ldap_result_iterate_context *ctx)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen{
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen const char *p;
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen while (ctx->attr != NULL) {
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (ctx->vals == NULL) {
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen /* a new attribute */
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen db_ldap_result_change_attr(ctx);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen } else {
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen /* continuing existing attribute */
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (ctx->value != NULL)
fb5abffb7097b3c5f167deff6ae293d2f828695bTimo Sirainen ctx->value = ctx->vals[++ctx->value_idx];
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen }
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (ctx->value != NULL) {
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen db_ldap_result_return_value(ctx);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen return TRUE;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen }
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ldap_value_free(ctx->vals); ctx->vals = NULL;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ldap_memfree(ctx->attr);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->attr = ldap_next_attribute(ctx->conn->ld, ctx->entry,
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->ber);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen }
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen if (ctx->static_attrs != NULL && *ctx->static_attrs != NULL) {
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen p = strchr(*ctx->static_attrs, '=');
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen if (p == NULL) {
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen ctx->name = *ctx->static_attrs;
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen ctx->value = "";
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen } else {
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen ctx->name = t_strdup_until(*ctx->static_attrs, p);
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen ctx->value = p + 1;
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen }
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen ctx->static_attrs++;
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen return TRUE;
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen }
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen db_ldap_result_iterate_finish(ctx);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen return FALSE;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainenbool db_ldap_result_iterate_next(struct db_ldap_result_iterate_context *ctx,
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen const char **name_r, const char **value_r)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen{
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (!db_ldap_result_int_next(ctx))
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen return FALSE;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen *name_r = ctx->name;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen *value_r = ctx->value;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen return TRUE;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainenbool db_ldap_result_iterate_next_all(struct db_ldap_result_iterate_context *ctx,
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen const char **name_r,
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen const char *const **values_r)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen{
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (!db_ldap_result_int_next(ctx))
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen return FALSE;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (ctx->template != NULL) {
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen /* we can use only one value with templates */
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->val_1_arr[0] = ctx->value;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen *values_r = ctx->val_1_arr;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen } else {
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen *values_r = (const char *const *)ctx->vals;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen }
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->value = NULL;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen *name_r = ctx->name;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen return TRUE;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstatic const char *parse_setting(const char *key, const char *value,
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen struct ldap_connection *conn)
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
2e1e493b248dec0127b1eabeea5a8bc330378fcdTimo Sirainen if (*config_path == '\0')
2e1e493b248dec0127b1eabeea5a8bc330378fcdTimo Sirainen i_fatal("LDAP: Configuration file path not given");
2e1e493b248dec0127b1eabeea5a8bc330378fcdTimo 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 conn->refcount = 1;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state = LDAP_CONN_STATE_DISCONNECTED;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->default_bind_msgid = -1;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen conn->fd = -1;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen conn->config_path = p_strdup(pool, config_path);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->set = default_ldap_settings;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen if (!settings_read(config_path, NULL, parse_setting,
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen null_settings_section_callback, 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
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen if (conn->set.uris == NULL && conn->set.hosts == NULL)
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen i_fatal("LDAP: No uris or hosts set");
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen#ifndef LDAP_HAVE_INITIALIZE
3c9e09fa412f62259e3a10bfe9ac6afb1becc2f0Timo Sirainen if (conn->set.uris != NULL) {
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen i_fatal("LDAP: Dovecot compiled without support for LDAP uris "
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen "(ldap_initialize not found)");
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen }
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen#endif
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->set.ldap_deref = deref2str(conn->set.deref);
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen conn->set.ldap_scope = scope2str(conn->set.scope);
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_array_init(&conn->request_array, DB_LDAP_MAX_QUEUE_SIZE);
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen conn->request_queue = aqueue_init(&conn->request_array.arr);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen conn->next = ldap_connections;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen ldap_connections = conn;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return conn;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid db_ldap_unref(struct ldap_connection **_conn)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct ldap_connection *conn = *_conn;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct ldap_connection **p;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *_conn = NULL;
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
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen db_ldap_abort_requests(conn, -1U, 0, FALSE, "Shutting down");
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count == 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_conn_close(conn);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->to == NULL);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen array_free(&conn->request_array);
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen aqueue_deinit(&conn->request_queue);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
0d7d27765267594a5870892268ab345148306d49Timo Sirainen if (conn->pass_attr_map != NULL)
ba00293b85c7fb4e7a2d100991c716e17b9daaaeTimo Sirainen hash_destroy(&conn->pass_attr_map);
0d7d27765267594a5870892268ab345148306d49Timo Sirainen if (conn->user_attr_map != NULL)
ba00293b85c7fb4e7a2d100991c716e17b9daaaeTimo Sirainen hash_destroy(&conn->user_attr_map);
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen pool_unref(&conn->pool);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen#ifndef BUILTIN_LDAP
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen/* Building a plugin */
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainenextern struct passdb_module_interface passdb_ldap;
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainenextern struct userdb_module_interface userdb_ldap;
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainenvoid authdb_ldap_init(void);
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainenvoid authdb_ldap_deinit(void);
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainenvoid authdb_ldap_init(void)
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen{
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen passdb_register_module(&passdb_ldap);
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen userdb_register_module(&userdb_ldap);
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen}
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainenvoid authdb_ldap_deinit(void)
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen{
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen passdb_unregister_module(&passdb_ldap);
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen userdb_unregister_module(&userdb_ldap);
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen}
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen#endif
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#endif