db-ldap.c revision 73583cff4f0ca9ee87204256ca1994adf17cb94c
/* Copyright (C) 2003-2006 Timo Sirainen */
#include "common.h"
#if defined(PASSDB_LDAP) || defined(USERDB_LDAP)
#include "network.h"
#include "ioloop.h"
#include "hash.h"
#include "str.h"
#include "settings.h"
#include "userdb.h"
#include "db-ldap.h"
#include <stddef.h>
#include <stdlib.h>
#define HAVE_LDAP_SASL
#ifdef HAVE_SASL_SASL_H
#elif defined (HAVE_SASL_H)
# include <sasl.h>
#else
#endif
#if SASL_VERSION_MAJOR < 2
#endif
#ifndef LDAP_SASL_QUIET
# define LDAP_SASL_QUIET 0 /* Doesn't exist in Solaris LDAP */
#endif
/* Older versions may require calling ldap_result() twice */
#if LDAP_VENDOR_VERSION <= 20112
# define OPENLDAP_ASYNC_WORKAROUND
#endif
/* Solaris LDAP library doesn't have LDAP_OPT_SUCCESS */
#ifndef LDAP_OPT_SUCCESS
# define LDAP_OPT_SUCCESS LDAP_SUCCESS
#endif
static struct setting_def setting_defs[] = {
{ 0, NULL, 0 }
};
struct ldap_settings default_ldap_settings = {
};
{
return LDAP_DEREF_NEVER;
return LDAP_DEREF_SEARCHING;
return LDAP_DEREF_FINDING;
return LDAP_DEREF_ALWAYS;
}
{
return LDAP_SCOPE_BASE;
return LDAP_SCOPE_ONELEVEL;
return LDAP_SCOPE_SUBTREE;
}
{
if (ret != LDAP_SUCCESS) {
i_error("LDAP: Can't get error number: %s",
return "??";
}
return ldap_err2string(err);
}
struct ldap_request *request)
{
else
}
int scope)
{
int msgid;
if (db_ldap_connect(conn) < 0) {
return;
}
if (conn->last_auth_bind) {
/* switch back to the default dn before doing the
search request. */
if (db_ldap_bind(conn) < 0) {
return;
}
}
if (msgid == -1) {
i_error("LDAP: ldap_search() failed (filter %s): %s",
return;
}
} else {
}
}
{
struct hash_table *old_requests;
struct hash_iterate_context *iter;
bool have_hash_binds = FALSE;
return;
/* first retry all the search requests */
/* bind request */
} else {
}
}
/* then delayed search requests */
p = &conn->delayed_requests_head;
while (*p != NULL) {
request = *p;
} else {
p = &(*p)->next;
}
}
/* next retry all the bind requests. without auth binds the
only bind request can be the initial connection binding,
which we don't care to retry. */
}
}
}
}
}
{
if (db_ldap_connect(conn) < 0) {
/* failed to reconnect. fail all requests. */
}
}
static void ldap_input(void *context)
{
struct ldap_request *request;
#ifdef OPENLDAP_ASYNC_WORKAROUND
if (ret == 0) {
/* try again, there may be another in buffer */
}
#endif
if (ret <= 0) {
if (ret < 0) {
i_error("LDAP: ldap_result() failed: %s",
}
return;
}
i_error("LDAP: Reply with unknown msgid %d",
msgid);
} else {
}
}
}
#ifdef HAVE_LDAP_SASL
static int
{
const char *str;
case SASL_CB_GETREALM:
break;
case SASL_CB_AUTHNAME:
break;
case SASL_CB_USER:
break;
case SASL_CB_PASS:
break;
default:
break;
}
}
}
return LDAP_SUCCESS;
}
#endif
{
if (ret == LDAP_SERVER_DOWN) {
i_error("LDAP: Can't connect to server: %s",
return -1;
}
if (ret != LDAP_SUCCESS) {
i_error("LDAP: binding failed (dn %s): %s",
return -1;
}
/* in case there are requests waiting, retry them */
}
return 0;
}
struct ldap_request *ldap_request,
{
int ret;
/* aborted */
return;
}
/* lost connection, close it */
}
}
{
struct ldap_request *ldap_request;
int msgid;
if (msgid == -1) {
i_error("ldap_bind(%s) failed: %s",
return -1;
}
/* we're binding back to the original DN, not doing an
authentication bind */
return 0;
}
{
int ret;
/* get the connection's fd */
if (ret != LDAP_SUCCESS) {
i_fatal("LDAP: Can't get connection fd: %s",
}
}
{
unsigned int ldap_version;
int ret;
return 0;
#ifdef LDAP_HAVE_INITIALIZE
#else
i_fatal("LDAP: Your LDAP library doesn't support "
"'uris' setting, use 'hosts' instead.");
#endif
} else
i_fatal("LDAP: ldap_init() failed with hosts: %s",
if (ret != LDAP_SUCCESS) {
i_fatal("LDAP: Can't set deref option: %s",
}
/* If SASL binds are used, the protocol version needs to be
at least 3 */
(void *)&ldap_version);
if (ret != LDAP_OPT_SUCCESS) {
i_fatal("LDAP: Can't set protocol version %u: %s",
}
}
#ifdef LDAP_HAVE_START_TLS_S
if (ret != LDAP_SUCCESS) {
i_error("LDAP: ldap_start_tls_s() failed: %s",
return -1;
}
#else
i_error("LDAP: Your LDAP library doesn't support TLS");
return -1;
#endif
}
#ifdef HAVE_LDAP_SASL
struct ldap_sasl_bind_context context;
/* There doesn't seem to be a way to do SASL binding
asynchronously.. */
sasl_interact, &context);
return -1;
#else
i_fatal("LDAP: sasl_bind=yes but no SASL support compiled in");
#endif
} else {
if (db_ldap_bind(conn) < 0)
return -1;
}
return 0;
}
{
struct hash_iterate_context *iter;
if (flush_requests) {
}
}
}
}
}
const char *const default_attr_map[],
const char *skip_attr)
{
const char *const *attr;
unsigned int i, j, size;
if (*attrlist == '\0')
return;
t_push();
/* @UNSAFE */
for (i = j = 0; i < size; i++) {
if (p == NULL) {
} else {
}
if (*name != '\0' &&
(*attr_names_r)[j++] = name;
}
if (*default_attr_map != NULL)
}
t_pop();
}
#define IS_LDAP_ESCAPED_CHAR(c) \
((c) == '*' || (c) == '(' || (c) == ')' || (c) == '\\')
const char *ldap_escape(const char *str,
{
const char *p;
for (p = str; *p != '\0'; p++) {
if (IS_LDAP_ESCAPED_CHAR(*p))
break;
}
if (*p == '\0')
return str;
for (; *p != '\0'; p++) {
if (IS_LDAP_ESCAPED_CHAR(*p))
str_append_c(ret, *p);
}
}
void *context)
{
}
{
struct ldap_connection *conn;
return conn;
}
return NULL;
}
{
struct ldap_connection *conn;
/* see if it already exists */
return conn;
}
if (*config_path == '\0')
i_fatal("LDAP: Configuration file path not given");
i_fatal("LDAP: No base given");
i_fatal("LDAP: No uris or hosts set");
#ifndef LDAP_HAVE_INITIALIZE
i_fatal("LDAP: Dovecot compiled without support for LDAP uris "
"(ldap_initialize not found)");
}
#endif
else {
i_fatal("LDAP: Invalid user_global_uid: %s",
}
}
else {
i_fatal("LDAP: Invalid user_global_gid: %s",
}
}
return conn;
}
{
struct ldap_connection **p;
return;
if (*p == conn) {
break;
}
}
}
#endif