db-ldap.c revision d1f0acc7fc722e13e8296228703adfe8a884d59e
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher/* Copyright (C) 2003 Timo Sirainen */
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher#include "config.h"
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher#undef HAVE_CONFIG_H
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher
c636315472e4f87313af7be30b7fbcad4b8ca8a4Stephen Gallagher#if defined(PASSDB_LDAP) || defined(USERDB_LDAP)
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher#include "common.h"
fd5a4eacd56700ffb08a73121aeacdc806cb0132Sumit Bose#include "network.h"
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher#include "ioloop.h"
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher#include "hash.h"
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher#include "str.h"
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher#include "settings.h"
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher#include "db-ldap.h"
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include <stddef.h>
df4cc3a83c5d6700b6a09ff96cb4a6b1949b1aa9Stephen Gallagher
df4cc3a83c5d6700b6a09ff96cb4a6b1949b1aa9Stephen Gallagher/* Older versions may require calling ldap_result() twice */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#if LDAP_VENDOR_VERSION <= 20112
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher# define OPENLDAP_ASYNC_WORKAROUND
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#endif
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#define DEF(type, name) \
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { type, #name, offsetof(struct ldap_settings, name) }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct setting_def setting_defs[] = {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF(SET_STR, hosts),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF(SET_STR, dn),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF(SET_STR, dnpass),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF(SET_STR, deref),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF(SET_STR, scope),
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose DEF(SET_STR, base),
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose DEF(SET_STR, user_attrs),
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose DEF(SET_STR, user_filter),
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke DEF(SET_STR, pass_attrs),
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke DEF(SET_STR, pass_filter),
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke DEF(SET_STR, user_global_uid),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DEF(SET_STR, user_global_gid)
2a552e43581c74f51205c7141ec9f6e9542509f8Stephen Gallagher};
2a552e43581c74f51205c7141ec9f6e9542509f8Stephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstruct ldap_settings default_ldap_settings = {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MEMBER(hosts) "localhost",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MEMBER(dn) NULL,
d921c1eba437662437847279f251a0a5d8f70127Maxim MEMBER(dnpass) NULL,
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek MEMBER(deref) "never",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MEMBER(scope) "subtree",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MEMBER(base) NULL,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MEMBER(user_attrs) NULL,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MEMBER(user_filter) NULL,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MEMBER(pass_attrs) NULL,
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce MEMBER(pass_filter) NULL,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MEMBER(user_global_uid) 0,
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek MEMBER(user_global_gid) 0
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher};
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagherstatic struct ldap_connection *ldap_connections = NULL;
4b6a0d0b3d42e5fdb457f47d9adfa5e66b160256Stephen Gallagher
e124844907ed6973915e4d56f5442ecd07535a12Jakub Hrozekstatic int ldap_conn_open(struct ldap_connection *conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void ldap_conn_close(struct ldap_connection *conn);
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagherstatic int deref2str(const char *str)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strcasecmp(str, "never") == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return LDAP_DEREF_NEVER;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strcasecmp(str, "searching") == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return LDAP_DEREF_SEARCHING;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strcasecmp(str, "finding") == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return LDAP_DEREF_FINDING;
be1ef1c62ad13612be5e1f879476c24452a5d6d0Stephen Gallagher if (strcasecmp(str, "always") == 0)
a3d176d116ceccd6a7547c128fab5df5cdd2c2b6Michal Zidek return LDAP_DEREF_ALWAYS;
a3d176d116ceccd6a7547c128fab5df5cdd2c2b6Michal Zidek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_fatal("LDAP: Unknown deref option '%s'", str);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagherstatic int scope2str(const char *str)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strcasecmp(str, "base") == 0)
558998ce664055a75595371118f818084d8f2b23Jan Cholasta return LDAP_SCOPE_BASE;
558998ce664055a75595371118f818084d8f2b23Jan Cholasta if (strcasecmp(str, "onelevel") == 0)
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta return LDAP_SCOPE_ONELEVEL;
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta if (strcasecmp(str, "subtree") == 0)
558998ce664055a75595371118f818084d8f2b23Jan Cholasta return LDAP_SCOPE_SUBTREE;
558998ce664055a75595371118f818084d8f2b23Jan Cholasta
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_fatal("LDAP: Unknown scope option '%s'", str);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic const char *get_ldap_error(struct ldap_connection *conn)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret, err;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, (void *) &err);
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny if (ret != LDAP_SUCCESS) {
f1828234a850dd28465425248a83a993f262918fPavel Březina i_error("LDAP: Can't get error number: %s",
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay ldap_err2string(ret));
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay return "??";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return ldap_err2string(err);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervoid db_ldap_search(struct ldap_connection *conn, const char *base, int scope,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *filter, char **attributes,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct ldap_request *request)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina{
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina int msgid;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (!conn->connected) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (!ldap_conn_open(conn)) {
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek request->callback(conn, request, NULL);
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta return;
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta }
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose msgid = ldap_search(conn->ld, base, scope, filter, attributes, 0);
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose if (msgid == -1) {
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose i_error("LDAP: ldap_search() failed (filter %s): %s",
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose filter, get_ldap_error(conn));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher request->callback(conn, request, NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher hash_insert(conn->requests, POINTER_CAST(msgid), request);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void ldap_input(void *context)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct ldap_connection *conn = context;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct ldap_request *request;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct timeval timeout;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher LDAPMessage *res;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret, msgid;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (;;) {
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek memset(&timeout, 0, sizeof(timeout));
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher ret = ldap_result(conn->ld, LDAP_RES_ANY, 1, &timeout, &res);
fe60346714a73ac3987f786731389320633dd245Pavel Březina#ifdef OPENLDAP_ASYNC_WORKAROUND
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose if (ret == 0) {
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose /* try again, there may be another in buffer */
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose ret = ldap_result(conn->ld, LDAP_RES_ANY, 1,
e5e8252ec48bfdd4e7529debc705c8e090264b9aSumit Bose &timeout, &res);
71e7918be3ca5d38794a16a17f6b4f19a24d51fcPavel Březina }
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher#endif
71e7918be3ca5d38794a16a17f6b4f19a24d51fcPavel Březina if (ret <= 0) {
71e7918be3ca5d38794a16a17f6b4f19a24d51fcPavel Březina if (ret < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_error("LDAP: ldap_result() failed: %s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher get_ldap_error(conn));
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek /* reconnect */
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek ldap_conn_close(conn);
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh }
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh return;
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose }
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek ret = ldap_result2error(conn->ld, res, 0);
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose if (ret != LDAP_SUCCESS) {
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose i_error("LDAP: ldap_result() failed: %s",
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek ldap_err2string(ret));
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl } else {
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek msgid = ldap_msgid(res);
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek request = hash_lookup(conn->requests,
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek POINTER_CAST(msgid));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (request != NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher request->callback(conn, request, res);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek hash_remove(conn->requests,
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek POINTER_CAST(msgid));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_free(request);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher i_error("LDAP: Reply with unknown msgid %d",
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher msgid);
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher }
fa551077410019fb34460dc730950e93b62b2963Jakub Hrozek }
fa551077410019fb34460dc730950e93b62b2963Jakub Hrozek
fa551077410019fb34460dc730950e93b62b2963Jakub Hrozek ldap_msgfree(res);
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher }
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagherstatic int ldap_conn_open(struct ldap_connection *conn)
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret, fd;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (conn->connected)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (conn->ld == NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->ld = ldap_init(conn->set.hosts, LDAP_PORT);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (conn->ld == NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_fatal("LDAP: ldap_init() failed with hosts: %s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->set.hosts);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = ldap_set_option(conn->ld, LDAP_OPT_DEREF,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (void *) &conn->set.ldap_deref);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret != LDAP_SUCCESS) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_fatal("LDAP: Can't set deref option: %s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ldap_err2string(ret));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose /* NOTE: we use blocking connect, we couldn't do anything anyway
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose until it's done. */
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose ret = ldap_simple_bind_s(conn->ld, conn->set.dn, conn->set.dnpass);
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose if (ret != LDAP_SUCCESS) {
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke if (ret == LDAP_SERVER_DOWN) {
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke i_error("LDAP: Can't connect to server: %s",
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke conn->set.hosts);
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke } else {
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke i_error("LDAP: ldap_simple_bind_s() failed: %s",
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher ldap_err2string(ret));
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher }
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher return FALSE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->connected = TRUE;
c7919a4fe41133cc466aa3d9431bfceee5784e7bJan Cholasta
b35f20cd8ecdc8308a3201e55752fb0443ec6ae4Jan Cholasta /* register LDAP input to ioloop */
c7919a4fe41133cc466aa3d9431bfceee5784e7bJan Cholasta ret = ldap_get_option(conn->ld, LDAP_OPT_DESC, (void *) &fd);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek if (ret != LDAP_SUCCESS) {
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek i_fatal("LDAP: Can't get connection fd: %s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ldap_err2string(ret));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
c7919a4fe41133cc466aa3d9431bfceee5784e7bJan Cholasta net_set_nonblock(fd, TRUE);
b35f20cd8ecdc8308a3201e55752fb0443ec6ae4Jan Cholasta conn->io = io_add(fd, IO_READ, ldap_input, conn);
c7919a4fe41133cc466aa3d9431bfceee5784e7bJan Cholasta return TRUE;
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void ldap_conn_close(struct ldap_connection *conn)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (conn->connected) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher io_remove(conn->io);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->io = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
3b1df539835367cb81cd5ff0f9959947d5642e55Stephen Gallagher conn->connected = FALSE;
3b1df539835367cb81cd5ff0f9959947d5642e55Stephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (conn->ld != NULL) {
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher ldap_unbind(conn->ld);
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher conn->ld = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
667db40da4db362d7ca0a1f7f1c4ba40fb71795aJakub Hrozekvoid db_ldap_set_attrs(struct ldap_connection *conn, const char *value,
60e51fd2764291df2332f36ff478777627d92b57Sumit Bose unsigned int **attrs, char ***attr_names)
c080a11e9e88f35e40aff4e476cabbd971833019Sumit Bose{
c080a11e9e88f35e40aff4e476cabbd971833019Sumit Bose const char *const *attr;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int i, dest, size;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher attr = t_strsplit(value, ",");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (*attr == NULL || **attr == '\0')
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_fatal("Missing uid field in attrs");
1467daed400d6c186bd0c99c057c42e764309ff3Stephen Gallagher
1467daed400d6c186bd0c99c057c42e764309ff3Stephen Gallagher for (size = 0; attr[size] != NULL; size++) ;
15b266d9f14dad26da8678a79019749d0f69532eStephen Gallagher
1467daed400d6c186bd0c99c057c42e764309ff3Stephen Gallagher /* +1 for terminating NULL */
b97595ae059c69b1960a6e7e56d74660388a683bJan Zeleny *attrs = p_new(conn->pool, unsigned int, size);
6a6a821866091e0f722808566c25b951aa346d7cStephen Gallagher *attr_names = p_new(conn->pool, char *, size + 1);
48d7840cae22c5ff4d786149b0d8ecee7efb8306Lukas Slebodnik for (i = 0, dest = 0; *attr != NULL; i++, attr++) {
60e51fd2764291df2332f36ff478777627d92b57Sumit Bose if (**attr != '\0') {
60e51fd2764291df2332f36ff478777627d92b57Sumit Bose (*attrs)[dest] = i;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (*attr_names)[dest] = p_strdup(conn->pool, *attr);
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher dest++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherconst char *ldap_escape(const char *str)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher string_t *s;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *p;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (p = str; *p != '\0'; p++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strchr("*()\\", *p) != NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (*p == '\0')
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return str;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher s = t_str_new(64);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str_append_n(s, str, (size_t) (p-str));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (; *p != '\0'; p++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strchr("*()\\", *p) != NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str_append_c(s, '\\');
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str_append_c(s, *p);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return str_c(s);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic const char *parse_setting(const char *key, const char *value,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher void *context)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct ldap_connection *conn = context;
bfbf5cb0f00c60c0f000f56c282377b13b9a89abSumit Bose
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher return parse_setting_from_defs(conn->pool, setting_defs,
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek &conn->set, key, value);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct ldap_connection *ldap_conn_find(const char *config_path)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct ldap_connection *conn;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce for (conn = ldap_connections; conn != NULL; conn = conn->next) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strcmp(conn->config_path, config_path) == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return conn;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
0ef783e186ef1c9f60e61a4e8e54c44cb366fdfePavel Březina return NULL;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek}
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstruct ldap_connection *db_ldap_init(const char *config_path)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct ldap_connection *conn;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher pool_t pool;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* see if it already exists */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn = ldap_conn_find(config_path);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (conn != NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->refcount++;
c0f9698cd951b7223f251ff2511c4b22a6e4ba60Jan Zeleny return conn;
c0f9698cd951b7223f251ff2511c4b22a6e4ba60Jan Zeleny }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher pool = pool_alloconly_create("ldap_connection", 1024);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn = p_new(pool, struct ldap_connection, 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->pool = pool;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->refcount = 1;
db78f4c750943fcd4b60bca5f3fdfd6cc5d3d4f8Ondrej Kos conn->requests = hash_create(default_pool, pool, 0, NULL, NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek conn->config_path = p_strdup(pool, config_path);
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek conn->set = default_ldap_settings;
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek settings_read(config_path, parse_setting, conn);
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek if (conn->set.base == NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_fatal("LDAP: No base given");
ca261795ce61c41d7e62217ccb2ee913923040ffPavel Březina
ca261795ce61c41d7e62217ccb2ee913923040ffPavel Březina conn->set.ldap_deref = deref2str(conn->set.deref);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->set.ldap_scope = scope2str(conn->set.scope);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (void)ldap_conn_open(conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->next = ldap_connections;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ldap_connections = conn;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return conn;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
77d165f0629966db65753a3aee84a8b4971673afPavel Březina
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervoid db_ldap_unref(struct ldap_connection *conn)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (--conn->refcount > 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ldap_conn_close(conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher hash_destroy(conn->requests);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher pool_unref(conn->pool);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#endif
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher