db-ldap.c revision 0d7d27765267594a5870892268ab345148306d49
c636315472e4f87313af7be30b7fbcad4b8ca8a4Stephen Gallagher/* Copyright (C) 2003 Timo Sirainen */
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher#if defined(PASSDB_LDAP) || defined(USERDB_LDAP)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher/* Older versions may require calling ldap_result() twice */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher/* Solaris LDAP library doesn't have LDAP_OPT_SUCCESS */
2a552e43581c74f51205c7141ec9f6e9542509f8Stephen Gallagher { type, #name, offsetof(struct ldap_settings, name) }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct setting_def setting_defs[] = {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstruct ldap_settings default_ldap_settings = {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MEMBER(user_attrs) "uid,homeDirectory,,,uidNumber,gidNumber",
be1ef1c62ad13612be5e1f879476c24452a5d6d0Stephen Gallagher MEMBER(user_filter) "(&(objectClass=posixAccount)(uid=%u))",
a3d176d116ceccd6a7547c128fab5df5cdd2c2b6Michal Zidek MEMBER(pass_filter) "(&(objectClass=posixAccount)(uid=%u))",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct ldap_connection *ldap_connections = NULL;
558998ce664055a75595371118f818084d8f2b23Jan Cholastastatic void ldap_conn_close(struct ldap_connection *conn);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina i_fatal("LDAP: Unknown scope option '%s'", str);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozekconst char *ldap_get_error(struct ldap_connection *conn)
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta ret = ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, (void *) &err);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_error("LDAP: Can't get error number: %s",
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose return "??";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervoid db_ldap_search(struct ldap_connection *conn, const char *base, int scope,
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher msgid = ldap_search(conn->ld, base, scope, filter, attributes, 0);
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose i_error("LDAP: ldap_search() failed (filter %s): %s",
e5e8252ec48bfdd4e7529debc705c8e090264b9aSumit Bose hash_insert(conn->requests, POINTER_CAST(msgid), request);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = ldap_result(conn->ld, LDAP_RES_ANY, 1, &timeout, &res);
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek /* try again, there may be another in buffer */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = ldap_result(conn->ld, LDAP_RES_ANY, 1,
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher /* reconnect */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher request = hash_lookup(conn->requests, POINTER_CAST(msgid));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_error("LDAP: Reply with unknown msgid %d",
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher hash_remove(conn->requests, POINTER_CAST(msgid));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherint db_ldap_connect(struct ldap_connection *conn)
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher if (ldap_initialize(&conn->ld, conn->set.uris) != LDAP_SUCCESS)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_fatal("LDAP: Your LDAP library doesn't support "
c7919a4fe41133cc466aa3d9431bfceee5784e7bJan Cholasta "'uris' setting, use 'hosts' instead.");
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek conn->ld = ldap_init(conn->set.hosts, LDAP_PORT);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_fatal("LDAP: ldap_init() failed with hosts: %s",
b35f20cd8ecdc8308a3201e55752fb0443ec6ae4Jan Cholasta ret = ldap_set_option(conn->ld, LDAP_OPT_DEREF,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_fatal("LDAP: Can't set deref option: %s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = ldap_set_option(conn->ld, LDAP_OPT_PROTOCOL_VERSION,
3b1df539835367cb81cd5ff0f9959947d5642e55Stephen Gallagher i_fatal("LDAP: Can't set protocol version %u: %s",
3b1df539835367cb81cd5ff0f9959947d5642e55Stephen Gallagher conn->set.ldap_version, ldap_err2string(ret));
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher /* NOTE: we use blocking connect, we couldn't do anything anyway
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher until it's done. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = ldap_simple_bind_s(conn->ld, conn->set.dn, conn->set.dnpass);
667db40da4db362d7ca0a1f7f1c4ba40fb71795aJakub Hrozek i_error("LDAP: Can't connect to server: %s", conn->set.hosts);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_error("LDAP: ldap_simple_bind_s() failed (dn %s): %s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->set.dn == NULL ? "(none)" : conn->set.dn,
b97595ae059c69b1960a6e7e56d74660388a683bJan Zeleny /* register LDAP input to ioloop */
6a6a821866091e0f722808566c25b951aa346d7cStephen Gallagher ret = ldap_get_option(conn->ld, LDAP_OPT_DESC, (void *) &fd);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->io = io_add(fd, IO_READ, ldap_input, conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void ldap_conn_close(struct ldap_connection *conn)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher while (hash_iterate(iter, &key, &value)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervoid db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher char ***attr_names_r, struct hash_table *attr_map,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *const default_attr_map[])
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *const *attr;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce unsigned int i, size;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (size = 0; attr[size] != NULL; size++) ;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *attr_names_r = p_new(conn->pool, char *, size + 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i = 0; i < size; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher value = *default_attr_map == NULL ? name :
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher name = p_strdup_until(conn->pool, attr[i], p);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ((c) == '*' || (c) == '(' || (c) == ')' || (c) == '\\')
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *p;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (*p == '\0')
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str_append_n(ret, str, (size_t) (p - str));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (; *p != '\0'; p++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic const char *parse_setting(const char *key, const char *value,
2e6087c6cc903d5164b9a1d5e3d791fd046001d9Jakub Hrozek return parse_setting_from_defs(conn->pool, setting_defs,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct ldap_connection *ldap_conn_find(const char *config_path)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (conn = ldap_connections; conn != NULL; conn = conn->next) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strcmp(conn->config_path, config_path) == 0)
fe2091327ff44f80d6681c261494e4432404e9baStephen 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);
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce conn->requests = hash_create(default_pool, pool, 0, NULL, NULL);
72e60fd4eabcfbcdbfe01e8c38b94052bc6c2067Jakub Hrozek if (!settings_read(config_path, NULL, parse_setting, NULL, conn))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->set.ldap_deref = deref2str(conn->set.deref);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->set.ldap_scope = scope2str(conn->set.scope);