db-ldap.c revision 964c86de7158ccafdfe665853579d71232e2634e
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher/* Copyright (c) 2003-2011 Dovecot authors, see the included COPYING file */
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher#include "auth-common.h"
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher#if defined(BUILTIN_LDAP) || defined(PLUGIN_BUILD)
c252d148fa8ab50aaaa8bbae7beb4d208025171dNikolai Kondrashov
9542512d7be40f2000298c86d3d2b728f4f0f65aStephen Gallagher#include "network.h"
9542512d7be40f2000298c86d3d2b728f4f0f65aStephen Gallagher#include "ioloop.h"
9542512d7be40f2000298c86d3d2b728f4f0f65aStephen Gallagher#include "array.h"
c6e39e15178675d0779e0ae855245774a09b4eb5Nikolai Kondrashov#include "hash.h"
c6e39e15178675d0779e0ae855245774a09b4eb5Nikolai Kondrashov#include "aqueue.h"
c6e39e15178675d0779e0ae855245774a09b4eb5Nikolai Kondrashov#include "str.h"
c6e39e15178675d0779e0ae855245774a09b4eb5Nikolai Kondrashov#include "env-util.h"
c6e39e15178675d0779e0ae855245774a09b4eb5Nikolai Kondrashov#include "var-expand.h"
fd5a4eacd56700ffb08a73121aeacdc806cb0132Sumit Bose#include "settings.h"
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher#include "userdb.h"
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher#include "db-ldap.h"
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher#include <stddef.h>
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher#include <stdlib.h>
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher#include <unistd.h>
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov
428db8a58c0c149d5efccc6d788f70916c1d34d7Jakub Hrozek#define HAVE_LDAP_SASL
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#ifdef HAVE_SASL_SASL_H
df4cc3a83c5d6700b6a09ff96cb4a6b1949b1aa9Stephen Gallagher# include <sasl/sasl.h>
df4cc3a83c5d6700b6a09ff96cb4a6b1949b1aa9Stephen Gallagher#elif defined (HAVE_SASL_H)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher# include <sasl.h>
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#else
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher# undef HAVE_LDAP_SASL
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#endif
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#ifdef LDAP_OPT_X_TLS
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher# define OPENLDAP_TLS_OPTIONS
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#endif
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#if SASL_VERSION_MAJOR < 2
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher# undef HAVE_LDAP_SASL
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#endif
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#ifndef LDAP_SASL_QUIET
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher# define LDAP_SASL_QUIET 0 /* Doesn't exist in Solaris LDAP */
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose#endif
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose/* Older versions may require calling ldap_result() twice */
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose#if LDAP_VENDOR_VERSION <= 20112
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose# define OPENLDAP_ASYNC_WORKAROUND
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose#endif
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke/* Solaris LDAP library doesn't have LDAP_OPT_SUCCESS */
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke#ifndef LDAP_OPT_SUCCESS
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose# define LDAP_OPT_SUCCESS LDAP_SUCCESS
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose#endif
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstruct db_ldap_result_iterate_context {
2a552e43581c74f51205c7141ec9f6e9542509f8Stephen Gallagher struct ldap_connection *conn;
2a552e43581c74f51205c7141ec9f6e9542509f8Stephen Gallagher LDAPMessage *entry;
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek struct auth_request *auth_request;
1a59af8245f183f22d87d067a90197d8e2ea958dJakub Hrozek
a5bb518446d5ce565d7ba819590a009cabb0b0b4Jakub Hrozek struct hash_table *attr_map;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct var_expand_table *var_table;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
d921c1eba437662437847279f251a0a5d8f70127Maxim char *attr, **vals;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek const char *name, *template, *val_1_arr[2];
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer const char *const *static_attrs;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher BerElement *ber;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher string_t *var, *debug;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher};
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorcestruct db_ldap_sasl_bind_context {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *authcid;
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek const char *passwd;
5377441d7a846461c2d9a7a870cea711360a529aNikolai Kondrashov const char *realm;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *authzid;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher};
32381402a4a9afc003782c9e2301fc59c9bda2a9Yassir Elley
dbfc407eef1d9ba2469687c3ffbe7fd8bb111d94Jakub Hrozek#define DEF_STR(name) DEF_STRUCT_STR(name, ldap_settings)
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher#define DEF_INT(name) DEF_STRUCT_INT(name, ldap_settings)
4b6a0d0b3d42e5fdb457f47d9adfa5e66b160256Stephen Gallagher#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, ldap_settings)
e124844907ed6973915e4d56f5442ecd07535a12Jakub Hrozek
5484044ea7bb632b915f706685fce509f6eacc48Jakub Hrozekstatic struct setting_def setting_defs[] = {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF_STR(hosts),
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher DEF_STR(uris),
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher DEF_STR(dn),
87d3b47abba6a40fcf809c85a2b138bc1013d9c5Jakub Hrozek DEF_STR(dnpass),
bc13c352ba9c2877f1e9bc62e55ad60fc000a55dJakub Hrozek DEF_BOOL(auth_bind),
bc13c352ba9c2877f1e9bc62e55ad60fc000a55dJakub Hrozek DEF_STR(auth_bind_userdn),
bc13c352ba9c2877f1e9bc62e55ad60fc000a55dJakub Hrozek DEF_BOOL(tls),
bc13c352ba9c2877f1e9bc62e55ad60fc000a55dJakub Hrozek DEF_BOOL(sasl_bind),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF_STR(sasl_mech),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF_STR(sasl_realm),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF_STR(sasl_authz_id),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF_STR(tls_ca_cert_file),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF_STR(tls_ca_cert_dir),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF_STR(tls_cert_file),
054b5d4bb98973698f74d66b14ccd14394b53f10Lukas Slebodnik DEF_STR(tls_key_file),
054b5d4bb98973698f74d66b14ccd14394b53f10Lukas Slebodnik DEF_STR(tls_cipher_suite),
a3d176d116ceccd6a7547c128fab5df5cdd2c2b6Michal Zidek DEF_STR(tls_require_cert),
a3d176d116ceccd6a7547c128fab5df5cdd2c2b6Michal Zidek DEF_STR(deref),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF_STR(scope),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF_STR(base),
4f6931e854c698dcb1c09f99eb330ce2fb97e7c6Lukas Slebodnik DEF_INT(ldap_version),
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher DEF_STR(debug_level),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF_STR(ldaprc_path),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF_STR(user_attrs),
558998ce664055a75595371118f818084d8f2b23Jan Cholasta DEF_STR(user_filter),
558998ce664055a75595371118f818084d8f2b23Jan Cholasta DEF_STR(pass_attrs),
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta DEF_STR(pass_filter),
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta DEF_STR(iterate_attrs),
558998ce664055a75595371118f818084d8f2b23Jan Cholasta DEF_STR(iterate_filter),
558998ce664055a75595371118f818084d8f2b23Jan Cholasta DEF_STR(default_pass_scheme),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF_BOOL(userdb_warning_disable),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { 0, NULL, 0 }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher};
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct ldap_settings default_ldap_settings = {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher .hosts = NULL,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher .uris = NULL,
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny .dn = NULL,
f1828234a850dd28465425248a83a993f262918fPavel Březina .dnpass = NULL,
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay .auth_bind = FALSE,
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina .auth_bind_userdn = NULL,
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina .tls = FALSE,
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina .sasl_bind = FALSE,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher .sasl_mech = NULL,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher .sasl_realm = NULL,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher .sasl_authz_id = NULL,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher .tls_ca_cert_file = NULL,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher .tls_ca_cert_dir = NULL,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher .tls_cert_file = NULL,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher .tls_key_file = NULL,
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek .tls_cipher_suite = NULL,
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek .tls_require_cert = NULL,
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek .deref = "never",
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina .scope = "subtree",
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina .base = NULL,
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina .ldap_version = 3,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek .debug_level = "0",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek .ldaprc_path = "",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek .user_attrs = "homeDirectory=home,uidNumber=uid,gidNumber=gid",
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta .user_filter = "(&(objectClass=posixAccount)(uid=%u))",
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta .pass_attrs = "uid=user,userPassword=password",
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta .pass_filter = "(&(objectClass=posixAccount)(uid=%u))",
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek .iterate_attrs = "uid=user",
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek .iterate_filter = "(objectClass=posixAccount)",
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek .default_pass_scheme = "crypt",
19d3aba12c70528708be9440aca66038a291f29eYassir Elley .userdb_warning_disable = FALSE
19d3aba12c70528708be9440aca66038a291f29eYassir Elley};
19d3aba12c70528708be9440aca66038a291f29eYassir Elley
f3a25949de81f80c136bb073e4a8f504b080c20cJakub Hrozekstatic struct ldap_connection *ldap_connections = NULL;
f3a25949de81f80c136bb073e4a8f504b080c20cJakub Hrozek
f3a25949de81f80c136bb073e4a8f504b080c20cJakub Hrozekstatic int db_ldap_bind(struct ldap_connection *conn);
45726939a48e605b0166521f94300ae04981a3a7Sumit Bosestatic void db_ldap_conn_close(struct ldap_connection *conn);
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose
3be9e26dcd169d44ae105f1b8a0674464c700b77Sumit Bosestatic int deref2str(const char *str)
5484044ea7bb632b915f706685fce509f6eacc48Jakub Hrozek{
5484044ea7bb632b915f706685fce509f6eacc48Jakub Hrozek if (strcasecmp(str, "never") == 0)
3be9e26dcd169d44ae105f1b8a0674464c700b77Sumit Bose return LDAP_DEREF_NEVER;
3be9e26dcd169d44ae105f1b8a0674464c700b77Sumit Bose if (strcasecmp(str, "searching") == 0)
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose return LDAP_DEREF_SEARCHING;
5484044ea7bb632b915f706685fce509f6eacc48Jakub Hrozek if (strcasecmp(str, "finding") == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return LDAP_DEREF_FINDING;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose if (strcasecmp(str, "always") == 0)
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose return LDAP_DEREF_ALWAYS;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose i_fatal("LDAP: Unknown deref option '%s'", str);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorcestatic int scope2str(const char *str)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strcasecmp(str, "base") == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return LDAP_SCOPE_BASE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strcasecmp(str, "onelevel") == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return LDAP_SCOPE_ONELEVEL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strcasecmp(str, "subtree") == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return LDAP_SCOPE_SUBTREE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_fatal("LDAP: Unknown scope option '%s'", str);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher#ifdef OPENLDAP_TLS_OPTIONS
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int tls_require_cert2str(const char *str)
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek{
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher if (strcasecmp(str, "never") == 0)
fe60346714a73ac3987f786731389320633dd245Pavel Březina return LDAP_OPT_X_TLS_NEVER;
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose if (strcasecmp(str, "hard") == 0)
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose return LDAP_OPT_X_TLS_HARD;
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter if (strcasecmp(str, "demand") == 0)
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek return LDAP_OPT_X_TLS_DEMAND;
e5e8252ec48bfdd4e7529debc705c8e090264b9aSumit Bose if (strcasecmp(str, "allow") == 0)
71e7918be3ca5d38794a16a17f6b4f19a24d51fcPavel Březina return LDAP_OPT_X_TLS_ALLOW;
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher if (strcasecmp(str, "try") == 0)
71e7918be3ca5d38794a16a17f6b4f19a24d51fcPavel Březina return LDAP_OPT_X_TLS_TRY;
71e7918be3ca5d38794a16a17f6b4f19a24d51fcPavel Březina
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina i_fatal("LDAP: Unknown tls_require_cert value '%s'", str);
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina}
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina#endif
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březinastatic int ldap_get_errno(struct ldap_connection *conn)
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina{
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek int ret, err;
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek ret = ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, (void *) &err);
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek if (ret != LDAP_SUCCESS) {
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek i_error("LDAP: Can't get error number: %s",
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek ldap_err2string(ret));
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek return LDAP_UNAVAILABLE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek return err;
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh}
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Boseconst char *ldap_get_error(struct ldap_connection *conn)
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha{
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha const char *ret;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek char *str = NULL;
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose ret = ldap_err2string(ldap_get_errno(conn));
e046ae03d0f55b1c8b0ec2fa6139bf86a3449adfPavel Březina
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose ldap_get_option(conn->ld, LDAP_OPT_ERROR_STRING, (void *)&str);
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose if (str != NULL) {
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek ret = t_strconcat(ret, ", ", str, NULL);
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek ldap_memfree(str);
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek }
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek ldap_set_option(conn->ld, LDAP_OPT_ERROR_STRING, NULL);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek return ret;
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina}
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichlstatic void ldap_conn_reconnect(struct ldap_connection *conn)
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl{
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek db_ldap_conn_close(conn);
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose if (db_ldap_connect(conn) < 0)
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek db_ldap_conn_close(conn);
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose}
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bosestatic int ldap_handle_error(struct ldap_connection *conn)
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose{
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek int err = ldap_get_errno(conn);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina switch (err) {
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek case LDAP_SUCCESS:
ea422c7061072c125eb53b40d7f3ca444d886913Sumit Bose i_unreached();
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek case LDAP_SIZELIMIT_EXCEEDED:
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek case LDAP_TIMELIMIT_EXCEEDED:
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek case LDAP_NO_SUCH_ATTRIBUTE:
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose case LDAP_UNDEFINED_TYPE:
6cb5bad3c8e2f35ca9dce1800a506d626f90c079Lukas Slebodnik case LDAP_INAPPROPRIATE_MATCHING:
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek case LDAP_CONSTRAINT_VIOLATION:
b407fe0474a674bb42f0f42ab47c7f530a07a367Pavel Březina case LDAP_TYPE_OR_VALUE_EXISTS:
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek case LDAP_INVALID_SYNTAX:
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek case LDAP_NO_SUCH_OBJECT:
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek case LDAP_ALIAS_PROBLEM:
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek case LDAP_INVALID_DN_SYNTAX:
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek case LDAP_IS_LEAF:
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek case LDAP_ALIAS_DEREF_PROBLEM:
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek case LDAP_FILTER_ERROR:
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek /* invalid input */
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek return -1;
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek case LDAP_SERVER_DOWN:
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik case LDAP_TIMEOUT:
99f8be128274eba264ea1434a7eb2800bced5902Lukas Slebodnik case LDAP_UNAVAILABLE:
99f8be128274eba264ea1434a7eb2800bced5902Lukas Slebodnik case LDAP_BUSY:
99f8be128274eba264ea1434a7eb2800bced5902Lukas Slebodnik#ifdef LDAP_CONNECT_ERROR
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik case LDAP_CONNECT_ERROR:
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik#endif
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek case LDAP_LOCAL_ERROR:
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek case LDAP_INVALID_CREDENTIALS:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher default:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* connection problems */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek ldap_conn_reconnect(conn);
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
9f521c61c17cecd9625ebc1b33c666fa3488622cJakub Hrozek
fb3c5cdfcda069a5fbeb7b9d200c0881911364b8Jakub Hrozekstatic int db_ldap_request_bind(struct ldap_connection *conn,
9f521c61c17cecd9625ebc1b33c666fa3488622cJakub Hrozek struct ldap_request *request)
9f521c61c17cecd9625ebc1b33c666fa3488622cJakub Hrozek{
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher struct ldap_request_bind *brequest =
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher (struct ldap_request_bind *)request;
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik i_assert(request->type == LDAP_REQUEST_TYPE_BIND);
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik i_assert(request->msgid == -1);
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik i_assert(conn->conn_state == LDAP_CONN_STATE_BOUND_AUTH ||
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik conn->conn_state == LDAP_CONN_STATE_BOUND_DEFAULT);
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik i_assert(conn->pending_count == 0);
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik request->msgid = ldap_bind(conn->ld, brequest->dn,
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik request->auth_request->mech_password,
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik LDAP_AUTH_SIMPLE);
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik if (request->msgid == -1) {
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher auth_request_log_error(request->auth_request, "ldap",
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher "ldap_bind(%s) failed: %s",
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik brequest->dn, ldap_get_error(conn));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ldap_handle_error(conn) < 0) {
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher /* broken request, remove it */
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek return 0;
cbff3fcdce5b0377a62fbe74f32e476efbf7ca9cNikolai Kondrashov }
cbff3fcdce5b0377a62fbe74f32e476efbf7ca9cNikolai Kondrashov return -1;
cbff3fcdce5b0377a62fbe74f32e476efbf7ca9cNikolai Kondrashov }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->conn_state = LDAP_CONN_STATE_BINDING;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int db_ldap_request_search(struct ldap_connection *conn,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct ldap_request *request)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik struct ldap_request_search *srequest =
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik (struct ldap_request_search *)request;
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik i_assert(conn->conn_state == LDAP_CONN_STATE_BOUND_DEFAULT);
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik i_assert(request->msgid == -1);
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher request->msgid =
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ldap_search(conn->ld, srequest->base, conn->set.ldap_scope,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher srequest->filter, srequest->attributes, 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (request->msgid == -1) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher auth_request_log_error(request->auth_request, "ldap",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "ldap_search(%s) parsing failed: %s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher srequest->filter, ldap_get_error(conn));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ldap_handle_error(conn) < 0) {
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose /* broken request, remove it */
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose return 0;
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose }
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose return -1;
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose }
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose return 1;
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose}
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bosestatic bool db_ldap_request_queue_next(struct ldap_connection *conn)
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose{
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke struct ldap_request *const *requestp, *request;
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke int ret = -1;
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke /* connecting may call db_ldap_connect_finish(), which gets us back
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke here. so do the connection before checking the request queue. */
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher if (db_ldap_connect(conn) < 0)
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher return FALSE;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (conn->pending_count == aqueue_count(conn->request_queue)) {
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik /* no non-pending requests */
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return FALSE;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik }
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik if (conn->pending_count > DB_LDAP_MAX_PENDING_REQUESTS) {
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik /* wait until server has replied to some requests */
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return FALSE;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik }
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik requestp = array_idx(&conn->request_array,
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik aqueue_idx(conn->request_queue,
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik conn->pending_count));
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik request = *requestp;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik if (conn->pending_count > 0 &&
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik request->type == LDAP_REQUEST_TYPE_BIND) {
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik /* we can't do binds until all existing requests are finished */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return FALSE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher switch (conn->conn_state) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher case LDAP_CONN_STATE_DISCONNECTED:
1467daed400d6c186bd0c99c057c42e764309ff3Stephen Gallagher case LDAP_CONN_STATE_BINDING:
1467daed400d6c186bd0c99c057c42e764309ff3Stephen Gallagher /* wait until we're in bound state */
15b266d9f14dad26da8678a79019749d0f69532eStephen Gallagher return FALSE;
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik case LDAP_CONN_STATE_BOUND_AUTH:
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik if (request->type == LDAP_REQUEST_TYPE_BIND)
1467daed400d6c186bd0c99c057c42e764309ff3Stephen Gallagher break;
b97595ae059c69b1960a6e7e56d74660388a683bJan Zeleny
6a6a821866091e0f722808566c25b951aa346d7cStephen Gallagher /* bind to default dn first */
48d7840cae22c5ff4d786149b0d8ecee7efb8306Lukas Slebodnik i_assert(conn->pending_count == 0);
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov (void)db_ldap_bind(conn);
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov return FALSE;
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov case LDAP_CONN_STATE_BOUND_DEFAULT:
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov /* we can do anything in this state */
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov break;
60e51fd2764291df2332f36ff478777627d92b57Sumit Bose }
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik switch (request->type) {
51d65c4ad15c2cc23f38fa09dd6efeb15e4f3e86Jakub Hrozek case LDAP_REQUEST_TYPE_BIND:
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik ret = db_ldap_request_bind(conn, request);
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik break;
51d65c4ad15c2cc23f38fa09dd6efeb15e4f3e86Jakub Hrozek case LDAP_REQUEST_TYPE_SEARCH:
cbff3fcdce5b0377a62fbe74f32e476efbf7ca9cNikolai Kondrashov ret = db_ldap_request_search(conn, request);
7bb9ba8688ec1ca930d693eea05e936bc38f6d1bSumit Bose break;
51d65c4ad15c2cc23f38fa09dd6efeb15e4f3e86Jakub Hrozek }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher if (ret > 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* success */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(request->msgid != -1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->pending_count++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else if (ret < 0) {
17f08cbd0f909181536b93d6c12c7cd69995f09eSumit Bose /* disconnected */
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov return FALSE;
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov } else {
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov /* broken request, remove from queue */
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov aqueue_delete_tail(conn->request_queue);
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov request->callback(conn, request, NULL);
6398f22526303343193a18e514602f1af6fb29cbNikolai Kondrashov return TRUE;
6398f22526303343193a18e514602f1af6fb29cbNikolai Kondrashov }
a8d887323f83984679a7d9b827a70146656bb7b2Sumit Bose}
a8d887323f83984679a7d9b827a70146656bb7b2Sumit Bose
6398f22526303343193a18e514602f1af6fb29cbNikolai Kondrashovstatic bool
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherdb_ldap_check_limits(struct ldap_connection *conn, struct ldap_request *request)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct ldap_request *const *first_requestp;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int count;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher time_t secs_diff;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher count = aqueue_count(conn->request_queue);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (count == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher first_requestp = array_idx(&conn->request_array,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher aqueue_idx(conn->request_queue, 0));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher secs_diff = ioloop_time - (*first_requestp)->create_time;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (secs_diff > DB_LDAP_REQUEST_LOST_TIMEOUT_SECS) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher auth_request_log_error(request->auth_request, "ldap",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "Connection appears to be hanging, reconnecting");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ldap_conn_reconnect(conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervoid db_ldap_request(struct ldap_connection *conn,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct ldap_request *request)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
bfbf5cb0f00c60c0f000f56c282377b13b9a89abSumit Bose i_assert(request->auth_request != NULL);
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek request->msgid = -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher request->create_time = ioloop_time;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
a5bb518446d5ce565d7ba819590a009cabb0b0b4Jakub Hrozek if (!db_ldap_check_limits(conn, request)) {
eaaeaa7e00c3d4bfa792cc4d3c6770dc1e28ef0cSumit Bose request->callback(conn, request, NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce aqueue_append(conn->request_queue, &request);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (void)db_ldap_request_queue_next(conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int db_ldap_connect_finish(struct ldap_connection *conn, int ret)
0ef783e186ef1c9f60e61a4e8e54c44cb366fdfePavel Březina{
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek if (ret == LDAP_SERVER_DOWN) {
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta i_error("LDAP: Can't connect to server: %s",
50c9d542e8bf641412debaa82a4dcf67ddb72258Lukas Slebodnik conn->set.uris != NULL ?
50c9d542e8bf641412debaa82a4dcf67ddb72258Lukas Slebodnik conn->set.uris : conn->set.hosts);
50c9d542e8bf641412debaa82a4dcf67ddb72258Lukas Slebodnik return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
b3b6189850d50c656d62efbd498789124c033b00Lukas Slebodnik if (ret != LDAP_SUCCESS) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_error("LDAP: binding failed (dn %s): %s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->set.dn == NULL ? "(none)" : conn->set.dn,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ldap_get_error(conn));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
c0f9698cd951b7223f251ff2511c4b22a6e4ba60Jan Zeleny if (conn->to != NULL)
769347ad4d35d43488eb98f980143495b0db415dStef Walter timeout_remove(&conn->to);
115de6d50f0d0bdd5745a5d8eb0d067be9128528Sumit Bose conn->conn_state = LDAP_CONN_STATE_BOUND_DEFAULT;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina while (db_ldap_request_queue_next(conn))
769347ad4d35d43488eb98f980143495b0db415dStef Walter ;
769347ad4d35d43488eb98f980143495b0db415dStef Walter return 0;
376eaf187c13c2a1eaea0ffbdd970b6b563ab74cPetr Cech}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void db_ldap_default_bind_finished(struct ldap_connection *conn,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher LDAPMessage *res)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
284937e6b5b0c9d7a1d3382d0d2820d1168842fbPavel Březina i_assert(conn->pending_count == 0);
284937e6b5b0c9d7a1d3382d0d2820d1168842fbPavel Březina conn->default_bind_msgid = -1;
284937e6b5b0c9d7a1d3382d0d2820d1168842fbPavel Březina
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = ldap_result2error(conn->ld, res, FALSE);
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek if (db_ldap_connect_finish(conn, ret) < 0) {
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek /* lost connection, close it */
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek db_ldap_conn_close(conn);
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek }
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
ca261795ce61c41d7e62217ccb2ee913923040ffPavel Březinastatic void db_ldap_abort_requests(struct ldap_connection *conn,
ca261795ce61c41d7e62217ccb2ee913923040ffPavel Březina unsigned int max_count,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int timeout_secs,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool error, const char *reason)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
77d165f0629966db65753a3aee84a8b4971673afPavel Březina struct ldap_request *const *requestp, *request;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher time_t diff;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher while (aqueue_count(conn->request_queue) > 0 && max_count > 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher requestp = array_idx(&conn->request_array,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher aqueue_idx(conn->request_queue, 0));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher request = *requestp;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher diff = ioloop_time - request->create_time;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (diff < (time_t)timeout_secs)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* timed out, abort */
126c9338cf12a3e4404c36bbe4ec14b18f23537cMaxim aqueue_delete_tail(conn->request_queue);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (request->msgid != -1) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(conn->pending_count > 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->pending_count--;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (error) {
4e0404ca1b19830dc0f729e59efd5bbd0a9d6103Lukas Slebodnik auth_request_log_error(request->auth_request, "ldap",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "%s", reason);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
eaa723b4d06b4c1e588df67bef44a84bbfaebf1aLukas Slebodnik auth_request_log_info(request->auth_request, "ldap",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "%s", reason);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher request->callback(conn, request, NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher max_count--;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct ldap_request *
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherdb_ldap_find_request(struct ldap_connection *conn, int msgid,
bfbf5cb0f00c60c0f000f56c282377b13b9a89abSumit Bose unsigned int *idx_r)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct ldap_request *const *requests, *request = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int i, count;
2e6087c6cc903d5164b9a1d5e3d791fd046001d9Jakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher count = aqueue_count(conn->request_queue);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (count == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher requests = array_idx(&conn->request_array, 0);
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek for (i = 0; i < count; i++) {
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose request = requests[aqueue_idx(conn->request_queue, i)];
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (request->msgid == msgid) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *idx_r = i;
3a4186ae40d0c3b7be46a4c973166f6048fcfe38Lukas Slebodnik return request;
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce }
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter if (request->msgid == -1)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
46e36286953de4e5af5e4289b90a529929bdd17cPetr Cech }
1658c567191c35beaddffafdb079abe33248037bLukas Slebodnik return NULL;
29be7d76c949b82350c7603cfd362a1fcb47eb1bJan Zeleny}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
72e60fd4eabcfbcdbfe01e8c38b94052bc6c2067Jakub Hrozekstatic void
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherdb_ldap_handle_result(struct ldap_connection *conn, LDAPMessage *res)
823a5b3f4375f12b6edae4dd5169ee01771baebeJan Zeleny{
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher struct ldap_request *request;
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta unsigned int idx;
7de6e3534fd61c7619ed34a6b1afe7230b5e6504Ondrej Kos int msgid, ret;
701f13b5c8e27bcbfc79e77ce7c76d9f768a448cLukas Slebodnik
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina msgid = ldap_msgid(res);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (msgid == conn->default_bind_msgid) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher db_ldap_default_bind_finished(conn, res);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
5a70b84cb66fb8c7a3fce0e3f2e4b61e0b2ea9d4Simo Sorce }
5f90993426fa2bdc3b3d994c9e85e0805bb92bbcSimo Sorce
9959c512ac3ba36f7a0db7614f0357ce0bae748fJakub Hrozek request = db_ldap_find_request(conn, msgid, &idx);
7452f1b637276ce582b120f8f5482ae7f3b6bd47Jakub Hrozek if (request == NULL) {
918b2a5a91f1c551d48f4bffed2a28c36fdb4be1Simo Sorce i_error("LDAP: Reply with unknown msgid %d", msgid);
bc052ea17d858c19f9cb9c9e2bc602e754f68831Sumit Bose return;
2fa8d6655ac37f9bdeb34420000052d921f4a543Michal Zidek }
a473fb88e6015cf0ccbd2e9005c7e6acca18f452Pavel Březina
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(conn->pending_count > 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (request->type == LDAP_REQUEST_TYPE_BIND) {
7ac503a73a26abe49f9f7d175c74df705380898dPavel Březina i_assert(conn->conn_state == LDAP_CONN_STATE_BINDING);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(conn->pending_count == 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->conn_state = LDAP_CONN_STATE_BOUND_AUTH;
e850be1ff2e13bba9812c94c3d102c0a0b570820Jakub Hrozek } else {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina switch (ldap_msgtype(res)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher case LDAP_RES_SEARCH_ENTRY:
d844aab866ae237844360cea70e2dccdc90c783dStephen Gallagher case LDAP_RES_SEARCH_RESULT:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
ef39c0adcb61b16f9edc7beb4cdc8f3b0d5a8f15Stephen Gallagher case LDAP_RES_SEARCH_REFERENCE:
ef39c0adcb61b16f9edc7beb4cdc8f3b0d5a8f15Stephen Gallagher /* we're going to ignore this */
8c3a4809b3420657289b42f028a1c9019b112991Stephen Gallagher return;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce default:
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose i_error("LDAP: Reply with unexpected type %d",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ldap_msgtype(res));
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina return;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta }
7ac503a73a26abe49f9f7d175c74df705380898dPavel Březina if (ldap_msgtype(res) == LDAP_RES_SEARCH_ENTRY)
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek ret = LDAP_SUCCESS;
590582be38cdbfde387fcc57df92903d48c5a083Jakub Hrozek else {
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina conn->pending_count--;
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina aqueue_delete(conn->request_queue, idx);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina ret = ldap_result2error(conn->ld, res, 0);
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret != LDAP_SUCCESS && request->type == LDAP_REQUEST_TYPE_SEARCH) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* handle search failures here */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter struct ldap_request_search *srequest =
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (struct ldap_request_search *)request;
df4e1db5d41c903ae57fd880acc76a0ad84aa7b2Pavel Březina
364b3572bab5a9649e8f2d4da835d05d3c8ca7a9Pavel Březina auth_request_log_error(request->auth_request, "ldap",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "ldap_search(%s) failed: %s",
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek srequest->filter, ldap_err2string(ret));
1f1e6cbc59868f06dee3ab4b3df660fcb77ce1c8Jakub Hrozek res = NULL;
4c11f752e1f10cf5740d53a3206bb795e9e34fe8Jan Zeleny }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher T_BEGIN {
1a7d1977037864e52858058777af8ff8401547ddJan Cholasta request->callback(conn, request, res);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } T_END;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (idx > 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* see if there are timed out requests */
376eaf187c13c2a1eaea0ffbdd970b6b563ab74cPetr Cech db_ldap_abort_requests(conn, idx,
7ac503a73a26abe49f9f7d175c74df705380898dPavel Březina DB_LDAP_REQUEST_LOST_TIMEOUT_SECS,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher TRUE, "Request lost");
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek }
fa70db6004a099afb7cb55031cd7bacb9e78202ePavel Březina}
ac47e8854f3bc404f2a35c6682faf621673d6b32Pavel Březina
b79e0e50a935d108173ca3062f2afe16103fcb1dPavel Březinastatic void ldap_input(struct ldap_connection *conn)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
f9961e5f82e0ef474d6492371bfdf9e74e208a99Pavel Březina struct timeval timeout;
87c07559af5cfcd2752295ef7c425bd3205f426fStephen Gallagher LDAPMessage *res;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher time_t prev_reply_diff;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher do {
3441d0c2d11aea0c39b009751a1898333c009674Stephen Gallagher if (conn->ld == NULL)
65e8f538ad35ba7d86cd9e60a3d86aec34537027Stephen Gallagher return;
45aeb924ec3ac448bb8d174a5cc061ed98b147c7Jakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher memset(&timeout, 0, sizeof(timeout));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = ldap_result(conn->ld, LDAP_RES_ANY, 0, &timeout, &res);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#ifdef OPENLDAP_ASYNC_WORKAROUND
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret == 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* try again, there may be another in buffer */
e9eeb4302e0e426c6cc1a4e65b95a6f7066e80b9Pavel Březina ret = ldap_result(conn->ld, LDAP_RES_ANY, 0,
85feb8d77a2c832787880944e02104846c4d5376Pavel Březina &timeout, &res);
cc84fd46f356c4a36a721ab135a33ec77c93e34dJakub Hrozek }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#endif
65e8f538ad35ba7d86cd9e60a3d86aec34537027Stephen Gallagher if (ret <= 0)
cdaa29d2c5724a4c72bfa0f42284ccfac3d5a464Pavel Reichl break;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher
fae99bfe4bfc8b4a12e9c2a0ad01b3684c22f934Simo Sorce db_ldap_handle_result(conn, res);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek ldap_msgfree(res);
8ca73915a3bf60331468fed6b3b38652c979f95dJakub Hrozek } while (conn->io != NULL);
d0599eaa9369fd867953e3c58b8d7bb445525ff5Pavel Březina
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher prev_reply_diff = ioloop_time - conn->last_reply_stamp;
213ce2a78b1abe3921d8dc13c949a28130d00aecJan Zeleny conn->last_reply_stamp = ioloop_time;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
38e2ec1c757955ab557fd95807afa58042d09482Jan Zeleny if (ret > 0) {
ad07ed37b6b51ef134d4524edaf2259e19ac984fJan Zeleny /* input disabled, continue once it's enabled */
1a853121ca2ba8ede6df429ee76942131ffb0f65Jan Zeleny i_assert(conn->io == NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else if (ret == 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* send more requests */
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose while (db_ldap_request_queue_next(conn))
3a62a99faf8e12965100d0b26fc9e07752bd3e2dStephen Gallagher ;
1a7d1977037864e52858058777af8ff8401547ddJan Cholasta } else if (ldap_get_errno(conn) != LDAP_SERVER_DOWN) {
65e8f538ad35ba7d86cd9e60a3d86aec34537027Stephen Gallagher i_error("LDAP: ldap_result() failed: %s", ldap_get_error(conn));
88275cccddf39892e01682b39b02292eb74729bdPavel Březina ldap_conn_reconnect(conn);
b407fe0474a674bb42f0f42ab47c7f530a07a367Pavel Březina } else if (aqueue_count(conn->request_queue) > 0 ||
4ddd5591c50e27dffa55f03fbce0dcc85cd50a8bPavel Březina prev_reply_diff < DB_LDAP_IDLE_RECONNECT_SECS) {
a679f0167b646cffdae86546ed77e105576991b0Pavel Březina i_error("LDAP: Connection lost to LDAP server, reconnecting");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ldap_conn_reconnect(conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* server probably disconnected an idle connection. don't
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher reconnect until the next request comes. */
347f7c4d1e8e83fc7ffcaf9524a67e8b3ad5d7c5Jan Cholasta db_ldap_conn_close(conn);
4139a7a731f2831963a42b26aac111422be28792Jakub Hrozek }
50fe3d79ab12b795a687b676761bef265701626aStephen Gallagher}
50fe3d79ab12b795a687b676761bef265701626aStephen Gallagher
3f32406640d89face5e79244b4d8dab34adb6c7cPavel Březina#ifdef HAVE_LDAP_SASL
17d37aecdf397fcb7a1d0c75adebdb25d7be112ePavel Březinastatic int
b1a822a16e3ef97e31d167f9e97efec06fc121dcJakub Hrozeksasl_interact(LDAP *ld ATTR_UNUSED, unsigned flags ATTR_UNUSED,
d43c9d18fb263b1ea4071b20e93ce4994583f62fJakub Hrozek void *defaults, void *interact)
077f8c9ca849ec895da3f0a25d15484ead08e99eLukas Slebodnik{
7ac503a73a26abe49f9f7d175c74df705380898dPavel Březina struct db_ldap_sasl_bind_context *context = defaults;
bf6c3f07d653d474da9e43b2b7cced57fc4ea069Sumit Bose sasl_interact_t *in;
b6dfbf81c61d4431aaa81687ec53e892f8b71edbSumit Bose const char *str;
e293fba4f5459f3c2dad254dcc966407d8fc3312Jakub Hrozek
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose for (in = interact; in->id != SASL_CB_LIST_END; in++) {
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose switch (in->id) {
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose case SASL_CB_GETREALM:
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose str = context->realm;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer break;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina case SASL_CB_AUTHNAME:
462db32918a05097652f8232cd6c8d78a826e63cLukas Slebodnik str = context->authcid;
462db32918a05097652f8232cd6c8d78a826e63cLukas Slebodnik break;
284937e6b5b0c9d7a1d3382d0d2820d1168842fbPavel Březina case SASL_CB_USER:
23fb01bf67a6058fb508da6d81515e8b18634bebPavel Březina str = context->authzid;
462db32918a05097652f8232cd6c8d78a826e63cLukas Slebodnik break;
347f7c4d1e8e83fc7ffcaf9524a67e8b3ad5d7c5Jan Cholasta case SASL_CB_PASS:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str = context->passwd;
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek break;
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek default:
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek str = NULL;
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek break;
374bf54785365273b20690bd3792c25a44738041Pavel Březina }
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher if (str != NULL) {
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher in->len = strlen(str);
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose in->result = str;
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose }
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina }
2d5d7761ef2b0d43c39dadf877b87aae19231036Lukas Slebodnik return LDAP_SUCCESS;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina}
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina#endif
eaa723b4d06b4c1e588df67bef44a84bbfaebf1aLukas Slebodnik
eaa723b4d06b4c1e588df67bef44a84bbfaebf1aLukas Slebodnikstatic void ldap_connection_timeout(struct ldap_connection *conn)
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek{
eaa723b4d06b4c1e588df67bef44a84bbfaebf1aLukas Slebodnik i_assert(conn->conn_state == LDAP_CONN_STATE_BINDING);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek i_error("LDAP: Initial binding to LDAP server timed out");
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek db_ldap_conn_close(conn);
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek}
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozekstatic int db_ldap_bind(struct ldap_connection *conn)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher{
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher int msgid;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher i_assert(conn->conn_state != LDAP_CONN_STATE_BINDING);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher i_assert(conn->default_bind_msgid == -1);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher i_assert(conn->pending_count == 0);
11e8f3ecdddf8edd8b1bbe9f41b49ce8b709b92aPetr Cech
11e8f3ecdddf8edd8b1bbe9f41b49ce8b709b92aPetr Cech msgid = ldap_bind(conn->ld, conn->set.dn, conn->set.dnpass,
11e8f3ecdddf8edd8b1bbe9f41b49ce8b709b92aPetr Cech LDAP_AUTH_SIMPLE);
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt if (msgid == -1) {
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt i_assert(ldap_get_errno(conn) != LDAP_SUCCESS);
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher if (db_ldap_connect_finish(conn, ldap_get_errno(conn)) < 0) {
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher /* lost connection, close it */
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher db_ldap_conn_close(conn);
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher }
87c07559af5cfcd2752295ef7c425bd3205f426fStephen Gallagher return -1;
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik }
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik conn->conn_state = LDAP_CONN_STATE_BINDING;
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik conn->default_bind_msgid = msgid;
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik if (conn->to != NULL)
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher timeout_remove(&conn->to);
87c07559af5cfcd2752295ef7c425bd3205f426fStephen Gallagher conn->to = timeout_add(DB_LDAP_REQUEST_LOST_TIMEOUT_SECS*1000,
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik ldap_connection_timeout, conn);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik return 0;
69b46c32357ccf1aab9c0bd6d1afa33a8724ad77Lukas Slebodnik}
69b46c32357ccf1aab9c0bd6d1afa33a8724ad77Lukas Slebodnik
69b46c32357ccf1aab9c0bd6d1afa33a8724ad77Lukas Slebodnikstatic void db_ldap_get_fd(struct ldap_connection *conn)
69b46c32357ccf1aab9c0bd6d1afa33a8724ad77Lukas Slebodnik{
69b46c32357ccf1aab9c0bd6d1afa33a8724ad77Lukas Slebodnik int ret;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik /* get the connection's fd */
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik ret = ldap_get_option(conn->ld, LDAP_OPT_DESC, (void *)&conn->fd);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik if (ret != LDAP_SUCCESS) {
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik i_fatal("LDAP: Can't get connection fd: %s",
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik ldap_err2string(ret));
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik }
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik if (conn->fd <= STDERR_FILENO) {
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose /* Solaris LDAP library seems to be broken */
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose i_fatal("LDAP: Buggy LDAP library returned wrong fd: %d",
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose conn->fd);
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose }
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose i_assert(conn->fd != -1);
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose net_set_nonblock(conn->fd, TRUE);
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose}
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bosestatic void
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bosedb_ldap_set_opt(struct ldap_connection *conn, int opt, const void *value,
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose const char *optname, const char *value_str)
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik{
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik int ret;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik ret = ldap_set_option(conn == NULL ? NULL : conn->ld, opt, value);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik if (ret != LDAP_SUCCESS) {
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik i_fatal("LDAP: Can't set option %s to %s: %s",
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik optname, value_str, ldap_err2string(ret));
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose }
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose}
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bosestatic void
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bosedb_ldap_set_opt_str(struct ldap_connection *conn, int opt, const char *value,
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose const char *optname)
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose{
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose if (value != NULL)
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose db_ldap_set_opt(conn, opt, value, optname, value);
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose}
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnikstatic void db_ldap_set_tls_options(struct ldap_connection *conn)
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik{
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik if (!conn->set.tls)
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik return;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik
3b1aa479b377e570c6dff359a1f8099289a2af75Michal Židek#ifdef OPENLDAP_TLS_OPTIONS
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik db_ldap_set_opt_str(NULL, LDAP_OPT_X_TLS_CACERTFILE,
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik conn->set.tls_ca_cert_file, "tls_ca_cert_file");
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik db_ldap_set_opt_str(NULL, LDAP_OPT_X_TLS_CACERTDIR,
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik conn->set.tls_ca_cert_dir, "tls_ca_cert_dir");
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik db_ldap_set_opt_str(NULL, LDAP_OPT_X_TLS_CERTFILE,
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik conn->set.tls_cert_file, "tls_cert_file");
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik db_ldap_set_opt_str(NULL, LDAP_OPT_X_TLS_KEYFILE,
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik conn->set.tls_key_file, "tls_key_file");
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik db_ldap_set_opt_str(NULL, LDAP_OPT_X_TLS_CIPHER_SUITE,
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik conn->set.tls_cipher_suite, "tls_cipher_suite");
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik if (conn->set.tls_require_cert != NULL) {
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose int value = tls_require_cert2str(conn->set.tls_require_cert);
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose db_ldap_set_opt(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &value,
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose "tls_require_cert", conn->set.tls_require_cert);
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose }
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose#else
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose if (conn->set.tls_ca_cert_file != NULL ||
3b1aa479b377e570c6dff359a1f8099289a2af75Michal Židek conn->set.tls_ca_cert_dir != NULL ||
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose conn->set.tls_cert_file != NULL ||
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose conn->set.tls_key_file != NULL ||
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose conn->set.tls_cipher_suite != NULL)
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose i_warning("LDAP: tls_* settings ignored, "
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose "your LDAP library doesn't seem to support them");
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose#endif
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose}
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose
bf01e8179cbb2be476805340636098deda7e1366Sumit Bosestatic void db_ldap_set_options(struct ldap_connection *conn)
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose{
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose unsigned int ldap_version;
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose int value;
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher db_ldap_set_opt(conn, LDAP_OPT_DEREF, &conn->set.ldap_deref,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher "deref", conn->set.deref);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher#ifdef LDAP_OPT_DEBUG_LEVEL
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher value = atoi(conn->set.debug_level);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (value != 0) {
4c11f752e1f10cf5740d53a3206bb795e9e34fe8Jan Zeleny db_ldap_set_opt(NULL, LDAP_OPT_DEBUG_LEVEL, &value,
c2352a73f52f600d95966ebe0b0819649ba923faStephen Gallagher "debug_level", conn->set.debug_level);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
1f1e6cbc59868f06dee3ab4b3df660fcb77ce1c8Jakub Hrozek#endif
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose if (conn->set.ldap_version < 3) {
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose if (conn->set.sasl_bind)
817b1bcafff27cc67630dd0cbd36df708c05fcccStephen Gallagher i_fatal("LDAP: sasl_bind=yes requires ldap_version=3");
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley if (conn->set.tls)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher i_fatal("LDAP: tls=yes requires ldap_version=3");
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher }
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher ldap_version = conn->set.ldap_version;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher db_ldap_set_opt(conn, LDAP_OPT_PROTOCOL_VERSION, &ldap_version,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher "protocol_version", dec2str(ldap_version));
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher db_ldap_set_tls_options(conn);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
d87e960c17d7598781cf032d06ba03a3ecadbfa2Pavel Březina
42c28b9424b6ef8a0021b124773e171dd5defaddJakub Hrozekint db_ldap_connect(struct ldap_connection *conn)
df4e1db5d41c903ae57fd880acc76a0ad84aa7b2Pavel Březina{
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter int ret;
d9577dbd92555b0755881e37724019ef9c578404Stef Walter
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (conn->conn_state != LDAP_CONN_STATE_DISCONNECTED)
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return 0;
d4aa049726ce8c6feeaf6995d4abb4cb5155b9a1Pavel Březina
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher i_assert(conn->pending_count == 0);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (conn->ld == NULL) {
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter if (conn->set.uris != NULL) {
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher#ifdef LDAP_HAVE_INITIALIZE
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (ldap_initialize(&conn->ld, conn->set.uris) != LDAP_SUCCESS)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher conn->ld = NULL;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher#else
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher i_fatal("LDAP: Your LDAP library doesn't support "
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher "'uris' setting, use 'hosts' instead.");
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher#endif
29be7d76c949b82350c7603cfd362a1fcb47eb1bJan Zeleny } else
dbea04f585a30d001b574317c068cd03a4fa332bJakub Hrozek conn->ld = ldap_init(conn->set.hosts, LDAP_PORT);
5a70b84cb66fb8c7a3fce0e3f2e4b61e0b2ea9d4Simo Sorce
823a5b3f4375f12b6edae4dd5169ee01771baebeJan Zeleny if (conn->ld == NULL)
9959c512ac3ba36f7a0db7614f0357ce0bae748fJakub Hrozek i_fatal("LDAP: ldap_init() failed with hosts: %s",
918b2a5a91f1c551d48f4bffed2a28c36fdb4be1Simo Sorce conn->set.hosts);
bc052ea17d858c19f9cb9c9e2bc602e754f68831Sumit Bose
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny db_ldap_set_options(conn);
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek }
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce
22d381367c27910fe82f476a76b9f4ede555e35aLukas Slebodnik if (conn->set.tls) {
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik#ifdef LDAP_HAVE_START_TLS_S
7de6e3534fd61c7619ed34a6b1afe7230b5e6504Ondrej Kos ret = ldap_start_tls_s(conn->ld, NULL, NULL);
a473fb88e6015cf0ccbd2e9005c7e6acca18f452Pavel Březina if (ret != LDAP_SUCCESS) {
de38d860e39585486e3ccbb42555196e319c7efdSumit Bose if (ret == LDAP_OPERATIONS_ERROR &&
022c6b90bb37851c0e8704c0e5388ebc113c6470Lukas Slebodnik strncmp(conn->set.uris, "ldaps:", 6) == 0) {
022c6b90bb37851c0e8704c0e5388ebc113c6470Lukas Slebodnik i_fatal("LDAP: Don't use both tls=yes "
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek "and ldaps URI");
022c6b90bb37851c0e8704c0e5388ebc113c6470Lukas Slebodnik }
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik i_error("LDAP: ldap_start_tls_s() failed: %s",
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik ldap_err2string(ret));
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek return -1;
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek }
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher#else
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher i_error("LDAP: Your LDAP library doesn't support TLS");
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik return -1;
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek#endif
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik }
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik if (conn->set.sasl_bind) {
7d8b7d82f0a91ed656320577fc781f24a66db9f8Sumit Bose#ifdef HAVE_LDAP_SASL
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek struct db_ldap_sasl_bind_context context;
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek memset(&context, 0, sizeof(context));
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek context.authcid = conn->set.dn;
1a7d1977037864e52858058777af8ff8401547ddJan Cholasta context.passwd = conn->set.dnpass;
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta context.realm = conn->set.sasl_realm;
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta context.authzid = conn->set.sasl_authz_id;
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta
1a7d1977037864e52858058777af8ff8401547ddJan Cholasta /* There doesn't seem to be a way to do SASL binding
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher asynchronously.. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = ldap_sasl_interactive_bind_s(conn->ld, NULL,
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek conn->set.sasl_mech,
1e0fa55fb377db788e065de917ba8e149eb56161Jakub Hrozek NULL, NULL, LDAP_SASL_QUIET,
1e0fa55fb377db788e065de917ba8e149eb56161Jakub Hrozek sasl_interact, &context);
1e0fa55fb377db788e065de917ba8e149eb56161Jakub Hrozek if (db_ldap_connect_finish(conn, ret) < 0)
1e0fa55fb377db788e065de917ba8e149eb56161Jakub Hrozek return -1;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek#else
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek i_fatal("LDAP: sasl_bind=yes but no SASL support compiled in");
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek#endif
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek conn->conn_state = LDAP_CONN_STATE_BOUND_DEFAULT;
1e0fa55fb377db788e065de917ba8e149eb56161Jakub Hrozek } else {
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek if (db_ldap_bind(conn) < 0)
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek return -1;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek }
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek db_ldap_get_fd(conn);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek conn->io = io_add(conn->fd, IO_READ, ldap_input, conn);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek return 0;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek}
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnikvoid db_ldap_enable_input(struct ldap_connection *conn, bool enable)
fd98a28d6e94080e52bbedc789b06606a6019b10Lukas Slebodnik{
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if (!enable) {
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if (conn->io != NULL)
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek io_remove(&conn->io);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek } else {
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if (conn->io == NULL && conn->fd != -1) {
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina conn->io = io_add(conn->fd, IO_READ, ldap_input, conn);
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina ldap_input(conn);
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina }
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina }
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina}
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březinastatic void db_ldap_disconnect_timeout(struct ldap_connection *conn)
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina{
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina db_ldap_abort_requests(conn, -1U,
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS, FALSE,
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina "Aborting (timeout), we're not connected to LDAP server");
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina if (aqueue_count(conn->request_queue) == 0) {
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina /* no requests left, remove this timeout handler */
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina timeout_remove(&conn->to);
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina }
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina}
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bosestatic void db_ldap_conn_close(struct ldap_connection *conn)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose{
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose struct ldap_request *const *requests, *request;
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose unsigned int i;
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose
4f6931e854c698dcb1c09f99eb330ce2fb97e7c6Lukas Slebodnik conn->conn_state = LDAP_CONN_STATE_DISCONNECTED;
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik conn->default_bind_msgid = -1;
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher if (conn->to != NULL)
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher timeout_remove(&conn->to);
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher if (conn->pending_count != 0) {
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt requests = array_idx(&conn->request_array, 0);
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik for (i = 0; i < conn->pending_count; i++) {
65ce66c43141f7e5c8482a8f8e7e217a23791588Petr Cech request = requests[aqueue_idx(conn->request_queue, i)];
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik i_assert(request->msgid != -1);
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik request->msgid = -1;
4f6931e854c698dcb1c09f99eb330ce2fb97e7c6Lukas Slebodnik }
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik conn->pending_count = 0;
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose }
b6dfbf81c61d4431aaa81687ec53e892f8b71edbSumit Bose
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek if (conn->ld != NULL) {
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek ldap_unbind(conn->ld);
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose conn->ld = NULL;
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik }
8babbeee01e67893af4828ddfc922ecac0be4197Pavel Reichl conn->fd = -1;
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik if (conn->io != NULL) {
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik /* the fd may have already been closed before ldap_unbind(),
4f6931e854c698dcb1c09f99eb330ce2fb97e7c6Lukas Slebodnik so we'll have to use io_remove_closed(). */
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik io_remove_closed(&conn->io);
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose }
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose if (aqueue_count(conn->request_queue) > 0) {
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose conn->to = timeout_add(DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS *
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt 1000/2, db_ldap_disconnect_timeout, conn);
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt }
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose}
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik
0d01e4f6cc21d8ca0e4fafe59c7cbfa1459fa47eSumit Bosevoid db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose char ***attr_names_r, struct hash_table *attr_map,
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik const char *skip_attr)
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik{
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose const char *const *attr, *attr_data, *p;
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose string_t *static_data;
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose char *name, *value;
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose unsigned int i, j, size;
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose if (*attrlist == '\0')
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose return;
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose attr = t_strsplit(attrlist, ",");
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose static_data = t_str_new(128);
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose /* @UNSAFE */
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose for (size = 0; attr[size] != NULL; size++) ;
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose *attr_names_r = p_new(conn->pool, char *, size + 1);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose for (i = j = 0; i < size; i++) {
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose /* allow spaces here so "foo=1, bar=2" works */
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose attr_data = attr[i];
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose while (*attr_data == ' ') attr_data++;
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose p = strchr(attr_data, '=');
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose if (p == NULL)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose name = value = p_strdup(conn->pool, attr_data);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose else if (p != attr_data) {
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose name = p_strdup_until(conn->pool, attr_data, p);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose value = p_strdup(conn->pool, p + 1);
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose } else {
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose /* =<static key>=<static value> */
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose if (str_len(static_data) > 0)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose str_append_c(static_data, ',');
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose str_append(static_data, p + 1);
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose continue;
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose }
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose if (*name != '\0' &&
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose (skip_attr == NULL || strcmp(skip_attr, value) != 0)) {
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose if (hash_table_lookup(attr_map, name) != NULL) {
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose i_fatal("ldap: LDAP attribute '%s' used multiple times. This is currently unsupported.",
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose name);
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose }
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose hash_table_insert(attr_map, name, value);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose (*attr_names_r)[j++] = name;
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose }
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose }
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher if (str_len(static_data) > 0) {
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina hash_table_insert(attr_map, "",
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina p_strdup(conn->pool, str_c(static_data)));
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina }
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina}
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březinastruct var_expand_table *
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březinadb_ldap_value_get_var_expand_table(struct auth_request *auth_request)
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina{
0bb98b7700b1b61f5b0a20b93279d5c2c391007fPavel Březina const struct var_expand_table *auth_table = NULL;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina struct var_expand_table *table;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina unsigned int count;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina auth_table = auth_request_get_var_expand_table(auth_request, NULL);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina for (count = 0; auth_table[count].key != '\0'; count++) ;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina count++;
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina table = t_new(struct var_expand_table, count + 1);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina table[0].key = '$';
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina memcpy(table + 1, auth_table, sizeof(*table) * count);
706d211b5d6e32d11a1c6ffc8065ca8be4d4d8c5Pavel Březina return table;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina}
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina#define IS_LDAP_ESCAPED_CHAR(c) \
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina ((c) == '*' || (c) == '(' || (c) == ')' || (c) == '\\')
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březinaconst char *ldap_escape(const char *str,
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina const struct auth_request *auth_request ATTR_UNUSED)
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *p;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter string_t *ret;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter for (p = str; *p != '\0'; p++) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (IS_LDAP_ESCAPED_CHAR(*p))
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
769347ad4d35d43488eb98f980143495b0db415dStef Walter
769347ad4d35d43488eb98f980143495b0db415dStef Walter if (*p == '\0')
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek return str;
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ret = t_str_new((size_t) (p - str) + 64);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append_n(ret, str, (size_t) (p - str));
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter for (; *p != '\0'; p++) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (IS_LDAP_ESCAPED_CHAR(*p))
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append_c(ret, '\\');
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append_c(ret, *p);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return str_c(ret);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstruct db_ldap_result_iterate_context *
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walterdb_ldap_result_iterate_init(struct ldap_connection *conn, LDAPMessage *entry,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter struct auth_request *auth_request,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter struct hash_table *attr_map)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter struct db_ldap_result_iterate_context *ctx;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *static_data;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx = t_new(struct db_ldap_result_iterate_context, 1);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->conn = conn;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->entry = entry;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->auth_request = auth_request;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->attr_map = attr_map;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher static_data = hash_table_lookup(attr_map, "");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (static_data != NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const struct var_expand_table *table;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher string_t *str;
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos
769347ad4d35d43488eb98f980143495b0db415dStef Walter table = auth_request_get_var_expand_table(auth_request, NULL);
769347ad4d35d43488eb98f980143495b0db415dStef Walter str = t_str_new(256);
7ac503a73a26abe49f9f7d175c74df705380898dPavel Březina var_expand(str, static_data, table);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->static_attrs = t_strsplit(str_c(str), ",");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
9917c138d9a270deb5820915384fbde751190c2aLukas Slebodnik
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (auth_request->set->debug)
e369fc08906383e6d5c39832f31bb6600a33f887Simo Sorce ctx->debug = t_str_new(256);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->attr = ldap_first_attribute(conn->ld, entry, &ctx->ber);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return ctx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
ef39c0adcb61b16f9edc7beb4cdc8f3b0d5a8f15Stephen Gallagherstatic void
8c3a4809b3420657289b42f028a1c9019b112991Stephen Gallagherdb_ldap_result_iterate_finish(struct db_ldap_result_iterate_context *ctx)
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ctx->debug != NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (str_len(ctx->debug) > 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher auth_request_log_debug(ctx->auth_request, "ldap",
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher "result: %s", str_c(ctx->debug) + 1);
f427b36b0cecc426856ab3f77a9c684ac355659dSumit Bose } else {
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik auth_request_log_debug(ctx->auth_request, "ldap",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "no fields returned by the server");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ber_free(ctx->ber, 0);
a8d887323f83984679a7d9b827a70146656bb7b2Sumit Bose}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
d844aab866ae237844360cea70e2dccdc90c783dStephen Gallagherstatic void
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherdb_ldap_result_change_attr(struct db_ldap_result_iterate_context *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(ctx->vals == NULL);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
300c772767c1b12077cac1d148ac89738b058f97Jan Zeleny ctx->name = hash_table_lookup(ctx->attr_map, ctx->attr);
bdc2aced1185c4ee36921fa01b8dc01789a63900Jakub Hrozek ctx->template = NULL;
bdc2aced1185c4ee36921fa01b8dc01789a63900Jakub Hrozek
bdc2aced1185c4ee36921fa01b8dc01789a63900Jakub Hrozek if (ctx->debug != NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str_printfa(ctx->debug, " %s(%s)=", ctx->attr,
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina ctx->name != NULL ? ctx->name : "?unknown?");
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina }
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina if (ctx->name == NULL || *ctx->name == '\0')
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina return;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina if (strchr(ctx->name, '%') != NULL &&
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina (ctx->template = strchr(ctx->name, '=')) != NULL) {
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina /* we want to use variables */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina ctx->name = t_strdup_until(ctx->name, ctx->template);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik ctx->template++;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina if (ctx->var_table == NULL) {
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina ctx->var_table = db_ldap_value_get_var_expand_table(
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ctx->auth_request);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ctx->var = t_str_new(256);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ctx->vals = ldap_get_values(ctx->conn->ld, ctx->entry,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek ctx->attr);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek}
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekstatic void
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekdb_ldap_result_return_value(struct db_ldap_result_iterate_context *ctx)
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta{
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta unsigned int i;
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta
b42b5d5aaf4da165582e73ad985fdff6e34e61e4Jakub Hrozek if (ctx->template != NULL) {
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta if (ctx->vals[1] != NULL) {
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose auth_request_log_warning(ctx->auth_request, "ldap",
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose "Multiple values found for '%s', "
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta "using value '%s'", ctx->name, ctx->vals[0]);
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta }
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose ctx->var_table[0].value = ctx->vals[0];
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose str_truncate(ctx->var, 0);
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose var_expand(ctx->var, ctx->template, ctx->var_table);
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta ctx->val_1_arr[0] = str_c(ctx->var);
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta }
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose if (ctx->debug == NULL) {
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose /* no debugging */
e3f0014bb64b7e93979948936cf93cf869d3dc44Jan Zeleny } else if (ctx->auth_request->set->debug_passwords ||
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose (strcmp(ctx->name, "password") != 0 &&
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose strcmp(ctx->name, "password_noscheme") != 0)) {
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose str_append(ctx->debug, ctx->vals[0]);
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose for (i = 1; ctx->vals[i] != NULL; i++)
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose str_printfa(ctx->debug, ", %s", ctx->vals[i]);
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose } else {
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose str_append(ctx->debug, PASSWORD_HIDDEN_STR);
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose }
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose}
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bosestatic bool db_ldap_result_int_next(struct db_ldap_result_iterate_context *ctx)
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek{
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek const char *p;
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek while (ctx->attr != NULL) {
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek if (ctx->vals == NULL) {
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina db_ldap_result_change_attr(ctx);
2b7ef850846029641cc59560c2d8d4ab7254dda5Pavel Březina if (ctx->vals != NULL) {
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek db_ldap_result_return_value(ctx);
590582be38cdbfde387fcc57df92903d48c5a083Jakub Hrozek return TRUE;
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina }
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina }
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina ldap_value_free(ctx->vals); ctx->vals = NULL;
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek ldap_memfree(ctx->attr);
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek ctx->attr = ldap_next_attribute(ctx->conn->ld, ctx->entry,
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek ctx->ber);
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek }
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose if (ctx->static_attrs != NULL && *ctx->static_attrs != NULL) {
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose p = strchr(*ctx->static_attrs, '=');
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose if (p == NULL) {
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek ctx->name = *ctx->static_attrs;
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek ctx->val_1_arr[0] = "";
1a59af8245f183f22d87d067a90197d8e2ea958dJakub Hrozek } else {
1a59af8245f183f22d87d067a90197d8e2ea958dJakub Hrozek ctx->name = t_strdup_until(*ctx->static_attrs, p);
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina ctx->val_1_arr[0] = p + 1;
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina }
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina /* make _next() return correct values */
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina ctx->template = "";
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina ctx->static_attrs++;
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek return TRUE;
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher db_ldap_result_iterate_finish(ctx);
376eaf187c13c2a1eaea0ffbdd970b6b563ab74cPetr Cech return FALSE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherbool db_ldap_result_iterate_next(struct db_ldap_result_iterate_context *ctx,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek const char **name_r,
ac47e8854f3bc404f2a35c6682faf621673d6b32Pavel Březina const char *const **values_r)
b79e0e50a935d108173ca3062f2afe16103fcb1dPavel Březina{
769347ad4d35d43488eb98f980143495b0db415dStef Walter if (!db_ldap_result_int_next(ctx))
769347ad4d35d43488eb98f980143495b0db415dStef Walter return FALSE;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (ctx->template != NULL) {
ccf340e56364851f2e5b75e52d3d63701b662954Lukas Slebodnik /* we can use only one value with templates */
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher *values_r = ctx->val_1_arr;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher } else {
2db6afe70eee2bbc22aa657a6b6609a9f3eb5d4cSimo Sorce *values_r = (const char *const *)ctx->vals;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *name_r = ctx->name;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return TRUE;
2db6afe70eee2bbc22aa657a6b6609a9f3eb5d4cSimo Sorce}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozekstatic const char *parse_setting(const char *key, const char *value,
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek struct ldap_connection *conn)
52e0894fd65bff4715c88330eb62b28e1635228fStephen Gallagher{
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher return parse_setting_from_defs(conn->pool, setting_defs,
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek &conn->set, key, value);
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek}
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozekstatic struct ldap_connection *ldap_conn_find(const char *config_path)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
8a07521b413a3b5879f824e1872c5770c92ee5c0Stephen Gallagher struct ldap_connection *conn;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (conn = ldap_connections; conn != NULL; conn = conn->next) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strcmp(conn->config_path, config_path) == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return conn;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstruct ldap_connection *db_ldap_init(const char *config_path, bool userdb)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct ldap_connection *conn;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *str;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher pool_t pool;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik /* see if it already exists */
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek conn = ldap_conn_find(config_path);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek if (conn != NULL) {
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek if (userdb)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->userdb_used = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->refcount++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return conn;
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if (*config_path == '\0')
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt i_fatal("LDAP: Configuration file path not given");
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek pool = pool_alloconly_create("ldap_connection", 1024);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek conn = p_new(pool, struct ldap_connection, 1);
b49a7d90708e816120ff88ce5a88fa62b35ff795Simo Sorce conn->pool = pool;
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik conn->refcount = 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->userdb_used = userdb;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->conn_state = LDAP_CONN_STATE_DISCONNECTED;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->default_bind_msgid = -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->fd = -1;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik conn->config_path = p_strdup(pool, config_path);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik conn->set = default_ldap_settings;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!settings_read(config_path, NULL, parse_setting,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher null_settings_section_callback, conn))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher exit(FATAL_DEFAULT);
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (conn->set.base == NULL)
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik i_fatal("LDAP: No base given");
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
a9eff330a7fbd231e8cc28a6828a1e5014ddb0d2Michal Zidek if (conn->set.uris == NULL && conn->set.hosts == NULL)
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt i_fatal("LDAP: No uris or hosts set");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#ifndef LDAP_HAVE_INITIALIZE
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (conn->set.uris != NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_fatal("LDAP: Dovecot compiled without support for LDAP uris "
2c0a971010596c122d7a0c0d76c8eb85f16f6d06Jakub Hrozek "(ldap_initialize not found)");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik#endif
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek if (*conn->set.ldaprc_path != '\0') {
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek str = getenv("LDAPRC");
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek if (str != NULL && strcmp(str, conn->set.ldaprc_path) != 0) {
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt i_fatal("LDAP: Multiple different ldaprc_path "
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "settings not allowed (%s and %s)",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str, conn->set.ldaprc_path);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
2c0a971010596c122d7a0c0d76c8eb85f16f6d06Jakub Hrozek env_put(t_strconcat("LDAPRC=", conn->set.ldaprc_path, NULL));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt conn->set.ldap_deref = deref2str(conn->set.deref);
2c0a971010596c122d7a0c0d76c8eb85f16f6d06Jakub Hrozek conn->set.ldap_scope = scope2str(conn->set.scope);
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_array_init(&conn->request_array, 512);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->request_queue = aqueue_init(&conn->request_array.arr);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->next = ldap_connections;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ldap_connections = conn;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik return conn;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zelenyvoid db_ldap_unref(struct ldap_connection **_conn)
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny{
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek struct ldap_connection *conn = *_conn;
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny struct ldap_connection **p;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt *_conn = NULL;
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek i_assert(conn->refcount >= 0);
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt if (--conn->refcount > 0)
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny return;
f1828234a850dd28465425248a83a993f262918fPavel Březina
f1828234a850dd28465425248a83a993f262918fPavel Březina for (p = &ldap_connections; *p != NULL; p = &(*p)->next) {
f1828234a850dd28465425248a83a993f262918fPavel Březina if (*p == conn) {
f1828234a850dd28465425248a83a993f262918fPavel Březina *p = conn->next;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik break;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik }
f1828234a850dd28465425248a83a993f262918fPavel Březina }
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay db_ldap_abort_requests(conn, -1U, 0, FALSE, "Shutting down");
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay i_assert(conn->pending_count == 0);
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay db_ldap_conn_close(conn);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik i_assert(conn->to == NULL);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay array_free(&conn->request_array);
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek aqueue_deinit(&conn->request_queue);
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek if (conn->pass_attr_map != NULL)
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek hash_table_destroy(&conn->pass_attr_map);
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek if (conn->user_attr_map != NULL)
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek hash_table_destroy(&conn->user_attr_map);
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek pool_unref(&conn->pool);
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek}
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březinavoid db_ldap_check_userdb_warning(struct ldap_connection *conn)
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina{
23fb01bf67a6058fb508da6d81515e8b18634bebPavel Březina const struct ldap_settings *def = &default_ldap_settings;
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina const char *set_name;
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina if (worker || conn->userdb_used || conn->set.userdb_warning_disable)
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina return;
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina if (strcmp(conn->set.user_attrs, def->user_attrs) != 0)
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina set_name = "user_attrs";
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina else if (strcmp(conn->set.user_filter, def->user_filter) != 0)
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina set_name = "user_filter";
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina else if (strcmp(conn->set.iterate_attrs, def->iterate_attrs) != 0)
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina set_name = "iterate_attrs";
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina else if (strcmp(conn->set.iterate_filter, def->iterate_filter) != 0)
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina set_name = "iterate_filter";
42870c7ac3608ffc58f2c9524ad3dfc1401bc1aaPavel Březina else
42870c7ac3608ffc58f2c9524ad3dfc1401bc1aaPavel Březina set_name = NULL;
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina if (set_name != NULL) {
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt i_warning("ldap: Ignoring changed %s in %s, "
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina "because userdb ldap not used. "
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina "(If this is intentional, set userdb_warning_disable=yes)",
558998ce664055a75595371118f818084d8f2b23Jan Cholasta set_name, conn->config_path);
558998ce664055a75595371118f818084d8f2b23Jan Cholasta }
558998ce664055a75595371118f818084d8f2b23Jan Cholasta}
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta
558998ce664055a75595371118f818084d8f2b23Jan Cholasta#ifndef BUILTIN_LDAP
558998ce664055a75595371118f818084d8f2b23Jan Cholasta/* Building a plugin */
558998ce664055a75595371118f818084d8f2b23Jan Cholastaextern struct passdb_module_interface passdb_ldap_plugin;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardtextern struct userdb_module_interface userdb_ldap_plugin;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholastavoid authdb_ldap_init(void);
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholastavoid authdb_ldap_deinit(void);
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta
748ba184db97b7534254f97018fa04e8aa458faeJan Cholastavoid authdb_ldap_init(void)
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta{
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta passdb_register_module(&passdb_ldap_plugin);
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta userdb_register_module(&userdb_ldap_plugin);
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt}
558998ce664055a75595371118f818084d8f2b23Jan Cholastavoid authdb_ldap_deinit(void)
558998ce664055a75595371118f818084d8f2b23Jan Cholasta{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher passdb_unregister_module(&passdb_ldap_plugin);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher userdb_unregister_module(&userdb_ldap_plugin);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
6e973aa578a692b2e7597811dfdfdb1a442c85f8Nikolai Kondrashov#endif
62b20154899f847e760d6dfbae6a32fb45b448deLukas Slebodnik
cbff3fcdce5b0377a62fbe74f32e476efbf7ca9cNikolai Kondrashov#endif
6e973aa578a692b2e7597811dfdfdb1a442c85f8Nikolai Kondrashov