userdb-ldap.c revision 3b94ff5951db4d4eddb7a80ed4e3f61207202635
5952N/A/* Copyright (C) 2003 Timo Sirainen */
5952N/A
5952N/A#include "config.h"
5952N/A#undef HAVE_CONFIG_H
5952N/A
5952N/A#ifdef USERDB_LDAP
5952N/A
5952N/A#include "common.h"
5952N/A#include "str.h"
5952N/A#include "var-expand.h"
5952N/A#include "db-ldap.h"
5952N/A#include "userdb.h"
5952N/A
5952N/A#include <ldap.h>
5952N/A#include <stdlib.h>
5952N/A
5952N/A/* using posixAccount */
5952N/A#define DEFAULT_ATTRIBUTES "uid,homeDirectory,,,uidNumber,gidNumber"
5952N/A
5952N/Aenum ldap_user_attr {
5952N/A ATTR_VIRTUAL_USER = 0,
5952N/A ATTR_HOME,
5952N/A ATTR_MAIL,
5952N/A ATTR_SYSTEM_USER,
5952N/A ATTR_UID_NUMBER,
5952N/A ATTR_GID_NUMBER,
5952N/A
5952N/A ATTR_COUNT
6815N/A};
5952N/A
5952N/Astruct userdb_ldap_connection {
5952N/A struct ldap_connection *conn;
6815N/A
6815N/A unsigned int *attrs;
5952N/A char **attr_names;
5952N/A};
5952N/A
6815N/Astruct userdb_ldap_request {
5952N/A struct ldap_request request;
5952N/A userdb_callback_t *userdb_callback;
5952N/A};
5952N/A
5952N/Astatic struct userdb_ldap_connection *userdb_ldap_conn;
5952N/A
5952N/Astatic void parse_attr(struct userdb_ldap_connection *conn,
5952N/A struct user_data *user,
5952N/A const char *attr, const char *value)
5952N/A{
5952N/A enum ldap_user_attr i;
5952N/A
5952N/A for (i = 0; i < ATTR_COUNT; i++) {
5952N/A if (strcasecmp(conn->attr_names[i], attr) == 0)
5952N/A break;
}
if (i == ATTR_COUNT) {
i_error("LDAP: Unknown attribute '%s'", attr);
return;
}
switch (conn->attrs[i]) {
case ATTR_VIRTUAL_USER:
user->virtual_user = t_strdup(value);
break;
case ATTR_HOME:
user->home = t_strdup(value);
break;
case ATTR_MAIL:
user->mail = t_strdup(value);
break;
case ATTR_SYSTEM_USER:
user->system_user = t_strdup(value);
break;
case ATTR_UID_NUMBER:
user->uid = atoi(value);
break;
case ATTR_GID_NUMBER:
user->gid = atoi(value);
break;
case ATTR_COUNT:
break;
}
}
static void handle_request(struct ldap_connection *conn,
struct ldap_request *request, LDAPMessage *res)
{
struct userdb_ldap_request *urequest =
(struct userdb_ldap_request *) request;
struct user_data user;
LDAPMessage *entry;
BerElement *ber;
char *attr, **vals;
int ret;
ret = ldap_result2error(conn->ld, res, 0);
if (ret != LDAP_SUCCESS) {
i_error("LDAP: ldap_search() failed: %s",
ldap_err2string(ret));
urequest->userdb_callback(NULL, request->context);
return;
}
entry = res == NULL ? NULL : ldap_first_entry(conn->ld, res);
if (entry == NULL) {
if (res != NULL)
i_error("LDAP: Authenticated user not found");
urequest->userdb_callback(NULL, request->context);
return;
}
t_push();
memset(&user, 0, sizeof(user));
user.uid = conn->set.user_global_uid;
user.gid = conn->set.user_global_gid;
attr = ldap_first_attribute(conn->ld, entry, &ber);
while (attr != NULL) {
vals = ldap_get_values(conn->ld, entry, attr);
if (vals != NULL && vals[0] != NULL && vals[1] == NULL)
parse_attr(userdb_ldap_conn, &user, attr, vals[0]);
ldap_value_free(vals);
ldap_memfree(attr);
attr = ldap_next_attribute(conn->ld, entry, ber);
}
if (user.virtual_user == NULL)
i_error("LDAP: No username in reply");
else if (user.uid == (uid_t)-1) {
i_error("ldap(%s): uidNumber not set and no default given in "
"user_global_uid", user.virtual_user);
} else if (user.gid == (gid_t)-1) {
i_error("ldap(%s): gidNumber not set and no default given in "
"user_global_gid", user.virtual_user);
} else if (ldap_next_entry(conn->ld, entry) != NULL) {
i_error("ldap(%s): Multiple replies found for user",
user.virtual_user);
} else {
urequest->userdb_callback(&user, request->context);
t_pop();
return;
}
/* error */
urequest->userdb_callback(NULL, request->context);
t_pop();
}
static void userdb_ldap_lookup(struct auth_request *auth_request,
userdb_callback_t *callback, void *context)
{
struct ldap_connection *conn = userdb_ldap_conn->conn;
struct userdb_ldap_request *request;
const char *filter;
string_t *str;
if (conn->set.user_filter == NULL) {
filter = t_strdup_printf("(&(objectClass=posixAccount)(%s=%s))",
userdb_ldap_conn->attr_names[ATTR_VIRTUAL_USER],
ldap_escape(auth_request->user));
} else {
str = t_str_new(512);
var_expand(str, conn->set.user_filter,
auth_request_get_var_expand_table(auth_request,
ldap_escape));
filter = str_c(str);
}
request = i_new(struct userdb_ldap_request, 1);
request->request.callback = handle_request;
request->request.context = context;
request->userdb_callback = callback;
db_ldap_search(conn, conn->set.base, conn->set.ldap_scope,
filter, userdb_ldap_conn->attr_names,
&request->request);
}
static void userdb_ldap_init(const char *args)
{
struct ldap_connection *conn;
userdb_ldap_conn = i_new(struct userdb_ldap_connection, 1);
userdb_ldap_conn->conn = conn = db_ldap_init(args);
db_ldap_set_attrs(conn, conn->set.user_attrs ?
conn->set.user_attrs : DEFAULT_ATTRIBUTES,
&userdb_ldap_conn->attrs,
&userdb_ldap_conn->attr_names);
}
static void userdb_ldap_deinit(void)
{
db_ldap_unref(userdb_ldap_conn->conn);
i_free(userdb_ldap_conn);
}
struct userdb_module userdb_ldap = {
userdb_ldap_init,
userdb_ldap_deinit,
userdb_ldap_lookup
};
#endif