db-ldap.c revision d1f0acc7fc722e13e8296228703adfe8a884d59e
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher/* Copyright (C) 2003 Timo Sirainen */
c636315472e4f87313af7be30b7fbcad4b8ca8a4Stephen Gallagher#if defined(PASSDB_LDAP) || defined(USERDB_LDAP)
df4cc3a83c5d6700b6a09ff96cb4a6b1949b1aa9Stephen Gallagher/* Older versions may require calling ldap_result() twice */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { type, #name, offsetof(struct ldap_settings, name) }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct setting_def setting_defs[] = {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstruct ldap_settings default_ldap_settings = {
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagherstatic struct ldap_connection *ldap_connections = NULL;
e124844907ed6973915e4d56f5442ecd07535a12Jakub Hrozekstatic int ldap_conn_open(struct ldap_connection *conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void ldap_conn_close(struct ldap_connection *conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_fatal("LDAP: Unknown deref option '%s'", str);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_fatal("LDAP: Unknown scope option '%s'", str);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic const char *get_ldap_error(struct ldap_connection *conn)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, (void *) &err);
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay return "??";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervoid db_ldap_search(struct ldap_connection *conn, const char *base, int scope,
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose msgid = ldap_search(conn->ld, base, scope, filter, attributes, 0);
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose i_error("LDAP: ldap_search() failed (filter %s): %s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher hash_insert(conn->requests, POINTER_CAST(msgid), request);
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher ret = ldap_result(conn->ld, LDAP_RES_ANY, 1, &timeout, &res);
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose /* try again, there may be another in buffer */
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek /* reconnect */
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher i_error("LDAP: Reply with unknown msgid %d",
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagherstatic int ldap_conn_open(struct ldap_connection *conn)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->ld = ldap_init(conn->set.hosts, LDAP_PORT);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_fatal("LDAP: ldap_init() failed with hosts: %s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = ldap_set_option(conn->ld, LDAP_OPT_DEREF,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_fatal("LDAP: Can't set deref option: %s",
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);
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke i_error("LDAP: Can't connect to server: %s",
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke i_error("LDAP: ldap_simple_bind_s() failed: %s",
b35f20cd8ecdc8308a3201e55752fb0443ec6ae4Jan Cholasta /* register LDAP input to ioloop */
c7919a4fe41133cc466aa3d9431bfceee5784e7bJan Cholasta ret = ldap_get_option(conn->ld, LDAP_OPT_DESC, (void *) &fd);
b35f20cd8ecdc8308a3201e55752fb0443ec6ae4Jan Cholasta conn->io = io_add(fd, IO_READ, ldap_input, conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void ldap_conn_close(struct ldap_connection *conn)
667db40da4db362d7ca0a1f7f1c4ba40fb71795aJakub Hrozekvoid db_ldap_set_attrs(struct ldap_connection *conn, const char *value,
c080a11e9e88f35e40aff4e476cabbd971833019Sumit Bose const char *const *attr;
1467daed400d6c186bd0c99c057c42e764309ff3Stephen Gallagher for (size = 0; attr[size] != NULL; size++) ;
1467daed400d6c186bd0c99c057c42e764309ff3Stephen Gallagher /* +1 for terminating NULL */
6a6a821866091e0f722808566c25b951aa346d7cStephen Gallagher *attr_names = p_new(conn->pool, char *, size + 1);
48d7840cae22c5ff4d786149b0d8ecee7efb8306Lukas Slebodnik for (i = 0, dest = 0; *attr != NULL; i++, attr++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (*attr_names)[dest] = p_strdup(conn->pool, *attr);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *p;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (*p == '\0')
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (; *p != '\0'; p++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic const char *parse_setting(const char *key, const char *value,
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher return parse_setting_from_defs(conn->pool, setting_defs,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct ldap_connection *ldap_conn_find(const char *config_path)
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce for (conn = ldap_connections; conn != NULL; conn = conn->next) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strcmp(conn->config_path, config_path) == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstruct ldap_connection *db_ldap_init(const char *config_path)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* see if it already exists */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher pool = pool_alloconly_create("ldap_connection", 1024);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn = p_new(pool, struct ldap_connection, 1);
db78f4c750943fcd4b60bca5f3fdfd6cc5d3d4f8Ondrej Kos conn->requests = hash_create(default_pool, pool, 0, NULL, NULL);
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek conn->config_path = p_strdup(pool, config_path);
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek settings_read(config_path, parse_setting, conn);
ca261795ce61c41d7e62217ccb2ee913923040ffPavel Březina conn->set.ldap_deref = deref2str(conn->set.deref);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->set.ldap_scope = scope2str(conn->set.scope);