Mercurial > dovecot > original-hg > dovecot-1.2
changeset 3158:8849f2e380d1 HEAD
userdb can now return extra parameters to master. Removed special handling
of home/mail wherever possible, they're just regular extra parameters now.
LDAP passdb and static userdb can return extra parameters now.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 12 Feb 2005 15:47:20 +0200 |
parents | 7eb1995f5a27 |
children | 852d010a4563 |
files | src/auth/auth-client-connection.c src/auth/auth-master-connection.c src/auth/auth-request-handler-default.c src/auth/auth-request.c src/auth/auth-request.h src/auth/db-ldap.c src/auth/db-ldap.h src/auth/passdb-cache.c src/auth/passdb-ldap.c src/auth/passdb-sql.c src/auth/userdb-ldap.c src/auth/userdb-passdb.c src/auth/userdb-passwd-file.c src/auth/userdb-passwd.c src/auth/userdb-sql.c src/auth/userdb-static.c src/auth/userdb-vpopmail.c src/auth/userdb.h src/master/mail-process.c |
diffstat | 19 files changed, 392 insertions(+), 357 deletions(-) [+] |
line wrap: on
line diff
--- a/src/auth/auth-client-connection.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/auth-client-connection.c Sat Feb 12 15:47:20 2005 +0200 @@ -34,6 +34,10 @@ va_start(args, fmt); str = t_str_new(256); str_vprintfa(str, fmt, args); + + if (conn->auth->verbose_debug) + i_info("client out: %s", str_c(str)); + str_append_c(str, '\n'); (void)o_stream_send(conn->output, str_data(str), str_len(str)); @@ -133,6 +137,9 @@ static int auth_client_handle_line(struct auth_client_connection *conn, const char *line) { + if (conn->auth->verbose_debug) + i_info("client in: %s", line); + if (strncmp(line, "AUTH\t", 5) == 0) { return auth_request_handler_auth_begin(conn->request_handler, line + 5);
--- a/src/auth/auth-master-connection.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/auth-master-connection.c Sat Feb 12 15:47:20 2005 +0200 @@ -45,6 +45,9 @@ struct auth_master_connection *conn = context; struct const_iovec iov[2]; + if (conn->auth->verbose_debug) + i_info("master out: %s", reply); + iov[0].iov_base = reply; iov[0].iov_len = strlen(reply); iov[1].iov_base = "\n"; @@ -129,6 +132,9 @@ } while ((line = i_stream_next_line(conn->input)) != NULL) { + if (conn->auth->verbose_debug) + i_info("master in: %s", line); + t_push(); if (strncmp(line, "REQUEST\t", 8) == 0) ret = master_input_request(conn, line + 8);
--- a/src/auth/auth-request-handler-default.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/auth-request-handler-default.c Sat Feb 12 15:47:20 2005 +0200 @@ -376,51 +376,20 @@ return TRUE; } -static void append_user_reply(string_t *str, const struct user_data *user) -{ - const char *p; - - str_printfa(str, "%s\tuid=%s\tgid=%s", user->virtual_user, - dec2str(user->uid), dec2str(user->gid)); - - if (user->system_user != NULL) - str_printfa(str, "\tsystem_user=%s", user->system_user); - if (user->mail != NULL) - str_printfa(str, "\tmail=%s", user->mail); - - p = user->home != NULL ? strstr(user->home, "/./") : NULL; - if (p == NULL) { - if (user->home != NULL) - str_printfa(str, "\thome=%s", user->home); - } else { - /* wu-ftpd like <chroot>/./<home> */ - str_printfa(str, "\thome=%s\tchroot=%s", - p + 3, t_strdup_until(user->home, p)); - } -} - -static void userdb_callback(const struct user_data *user, void *context) +static void userdb_callback(const char *result, void *context) { struct auth_request *request = context; struct auth_request_handler *handler = request->context; string_t *reply; - if (user != NULL) { - auth_request_log_debug(request, "userdb", - "uid=%s gid=%s home=%s mail=%s", - dec2str(user->uid), dec2str(user->gid), - user->home != NULL ? user->home : "", - user->mail != NULL ? user->mail : ""); - } - reply = t_str_new(256); if (handler->prepend_connect_uid) str_printfa(reply, "%u\t", request->connect_uid); - if (user == NULL) + if (result == NULL) str_printfa(reply, "NOTFOUND\t%u", request->id); else { str_printfa(reply, "USER\t%u\t", request->id); - append_user_reply(reply, user); + str_append(reply, result); } handler->master_callback(str_c(reply), handler->master_context);
--- a/src/auth/auth-request.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/auth-request.c Sat Feb 12 15:47:20 2005 +0200 @@ -143,14 +143,12 @@ } struct auth_request_extra * -auth_request_extra_begin(struct auth_request *request, - const char *user_password) +auth_request_extra_begin(struct auth_request *request) { struct auth_request_extra *extra; extra = i_new(struct auth_request_extra, 1); extra->request = request; - extra->user_password = i_strdup(user_password); return extra; } @@ -199,7 +197,7 @@ } void auth_request_extra_finish(struct auth_request_extra *extra, - const char *cache_key) + const char *user_password, const char *cache_key) { string_t *str; @@ -219,16 +217,12 @@ str_c(str), NULL)); } - if (extra->user_password != NULL) { + if (user_password != NULL) { if (extra->request->proxy) { /* we're proxying - send back the password that was sent by user (not the password in passdb). */ - str_printfa(extra->str, "\tpass=%s", - extra->user_password); + str_printfa(extra->str, "\tpass=%s", user_password); } - safe_memset(extra->user_password, 0, - strlen(extra->user_password)); - i_free(extra->user_password); } if (extra->str != NULL) @@ -353,7 +347,7 @@ va_start(va, format); t_push(); - i_info("%s", get_log_str(auth_request, subsystem, format, va)); + i_error("%s", get_log_str(auth_request, subsystem, format, va)); t_pop(); va_end(va); }
--- a/src/auth/auth-request.h Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/auth-request.h Sat Feb 12 15:47:20 2005 +0200 @@ -69,10 +69,11 @@ const char *username, const char **error_r); struct auth_request_extra * -auth_request_extra_begin(struct auth_request *request, const char *password); +auth_request_extra_begin(struct auth_request *request); void auth_request_extra_next(struct auth_request_extra *extra, const char *name, const char *value); void auth_request_extra_finish(struct auth_request_extra *extra, + const char *user_password, const char *cache_key); const struct var_expand_table *
--- a/src/auth/db-ldap.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/db-ldap.c Sat Feb 12 15:47:20 2005 +0200 @@ -272,28 +272,41 @@ } } -void db_ldap_set_attrs(struct ldap_connection *conn, const char *value, - unsigned int **attrs, char ***attr_names) +void db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist, + const char *const default_attr_map[]) { const char *const *attr; - unsigned int i, dest, size; + char *name, *value, *p; + unsigned int i, size; - attr = t_strsplit(value, ","); - if (*attr == NULL || **attr == '\0') - i_fatal("Missing uid field in attrs"); + if (*attrlist == '\0') + return; + + t_push(); + attr = t_strsplit(attrlist, ","); for (size = 0; attr[size] != NULL; size++) ; + conn->attr_names = p_new(conn->pool, char *, size); - /* +1 for terminating NULL */ - *attrs = p_new(conn->pool, unsigned int, size); - *attr_names = p_new(conn->pool, char *, size + 1); - for (i = 0, dest = 0; *attr != NULL; i++, attr++) { - if (**attr != '\0') { - (*attrs)[dest] = i; - (*attr_names)[dest] = p_strdup(conn->pool, *attr); - dest++; + for (i = 0; i < size; i++) { + p = strchr(attr[i], '='); + if (p == NULL) { + name = p_strdup(conn->pool, attr[i]); + value = *default_attr_map == NULL ? name : + p_strdup(conn->pool, *default_attr_map); + } else { + name = p_strdup_until(conn->pool, attr[i], p); + value = p_strdup(conn->pool, p + 1); } + + conn->attr_names[i] = name; + if (*name != '\0') + hash_insert(conn->attr_map, name, value); + + if (*default_attr_map != NULL) + default_attr_map++; } + t_pop(); } #define IS_LDAP_ESCAPED_CHAR(c) \ @@ -362,6 +375,8 @@ conn->refcount = 1; conn->requests = hash_create(default_pool, pool, 0, NULL, NULL); + conn->attr_map = hash_create(default_pool, pool, 0, str_hash, + (hash_cmp_callback_t *)strcmp); conn->config_path = p_strdup(pool, config_path); conn->set = default_ldap_settings; @@ -387,6 +402,7 @@ ldap_conn_close(conn); hash_destroy(conn->requests); + hash_destroy(conn->attr_map); pool_unref(conn->pool); }
--- a/src/auth/db-ldap.h Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/db-ldap.h Sat Feb 12 15:47:20 2005 +0200 @@ -45,6 +45,9 @@ struct io *io; struct hash_table *requests; + char **attr_names; + struct hash_table *attr_map; + unsigned int connected:1; }; @@ -57,8 +60,8 @@ const char *filter, char **attributes, struct ldap_request *request); -void db_ldap_set_attrs(struct ldap_connection *conn, const char *value, - unsigned int **attrs, char ***attr_names); +void db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist, + const char *const default_attr_map[]); struct ldap_connection *db_ldap_init(const char *config_path); void db_ldap_unref(struct ldap_connection *conn);
--- a/src/auth/passdb-cache.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/passdb-cache.c Sat Feb 12 15:47:20 2005 +0200 @@ -18,7 +18,7 @@ if (*list == NULL) return; - extra = auth_request_extra_begin(request, password); + extra = auth_request_extra_begin(request); for (; *list != NULL; list++) { t_push(); value = strchr(*list, '='); @@ -33,7 +33,7 @@ auth_request_extra_next(extra, name, value); t_pop(); } - auth_request_extra_finish(extra, NULL); + auth_request_extra_finish(extra, password, NULL); } int passdb_cache_verify_plain(struct auth_request *request, const char *key,
--- a/src/auth/passdb-ldap.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/passdb-ldap.c Sat Feb 12 15:47:20 2005 +0200 @@ -6,6 +6,7 @@ #ifdef PASSDB_LDAP #include "common.h" +#include "hash.h" #include "str.h" #include "var-expand.h" #include "password-scheme.h" @@ -16,18 +17,8 @@ #include <ldap.h> #include <stdlib.h> -enum ldap_user_attr { - ATTR_VIRTUAL_USER = 0, - ATTR_PASSWORD, - - ATTR_COUNT -}; - -struct passdb_ldap_connection { - struct ldap_connection *conn; - - unsigned int *attrs; - char **attr_names; +static const char *default_attr_map[] = { + "user", "password", NULL }; struct passdb_ldap_request { @@ -42,9 +33,45 @@ char password[1]; /* variable width */ }; -static struct passdb_ldap_connection *passdb_ldap_conn; +static struct ldap_connection *passdb_ldap_conn; static char *passdb_ldap_cache_key; +static const char * +ldap_query_save_result(struct ldap_connection *conn, LDAPMessage *entry, + struct passdb_ldap_request *ldap_request, + struct auth_request *auth_request) +{ + struct auth_request_extra *extra; + BerElement *ber; + const char *name, *password; + char *attr, **vals; + unsigned int i; + + extra = auth_request_extra_begin(auth_request); + + password = NULL; + attr = ldap_first_attribute(conn->ld, entry, &ber); + while (attr != NULL) { + name = hash_lookup(passdb_ldap_conn->attr_map, attr); + vals = ldap_get_values(conn->ld, entry, attr); + + if (name != NULL && vals != NULL && vals[0] != NULL) { + if (strcmp(name, "password") == 0 && vals[1] == NULL) + password = t_strdup(vals[0]); + for (i = 0; vals[i] != NULL; i++) + auth_request_extra_next(extra, name, vals[i]); + } + + ldap_value_free(vals); + ldap_memfree(attr); + + attr = ldap_next_attribute(conn->ld, entry, ber); + } + + auth_request_extra_finish(extra, ldap_request->password, NULL); + return password; +} + static void handle_request(struct ldap_connection *conn, struct ldap_request *request, LDAPMessage *res) { @@ -53,13 +80,10 @@ struct auth_request *auth_request = request->context; enum passdb_result result; LDAPMessage *entry; - BerElement *ber; - char *attr, **vals; - const char *user, *password, *scheme; + const char *password, *scheme; int ret; result = PASSDB_RESULT_USER_UNKNOWN; - user = auth_request->user; password = NULL; if (res != NULL) { @@ -81,20 +105,8 @@ "unknown user"); } } else { - 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) { - if (strcasecmp(attr, passdb_ldap_conn-> - attr_names[ATTR_PASSWORD]) == 0) - password = t_strdup(vals[0]); - } - ldap_value_free(vals); - ldap_memfree(attr); - - attr = ldap_next_attribute(conn->ld, entry, ber); - } + password = ldap_query_save_result(conn, entry, ldap_request, + auth_request); if (password == NULL) { auth_request_log_error(auth_request, "ldap", @@ -131,7 +143,8 @@ return; } - ret = password_verify(ldap_request->password, password, scheme, user); + ret = password_verify(ldap_request->password, password, scheme, + auth_request->user); if (ret < 0) { auth_request_log_error(auth_request, "ldap", "Unknown password scheme %s", scheme); @@ -148,9 +161,9 @@ static void ldap_lookup_pass(struct auth_request *auth_request, struct ldap_request *ldap_request) { - struct ldap_connection *conn = passdb_ldap_conn->conn; + struct ldap_connection *conn = passdb_ldap_conn; const struct var_expand_table *vars; - const char **attr_names = (const char **)passdb_ldap_conn->attr_names; + const char **attr_names = (const char **)conn->attr_names; const char *filter, *base; string_t *str; @@ -182,12 +195,12 @@ ldap_verify_plain(struct auth_request *request, const char *password, verify_plain_callback_t *callback) { - struct ldap_connection *conn = passdb_ldap_conn->conn; struct passdb_ldap_request *ldap_request; enum passdb_result result; if (passdb_cache_verify_plain(request, passdb_ldap_cache_key, password, - conn->set.default_pass_scheme, &result)) { + passdb_ldap_conn->set.default_pass_scheme, + &result)) { callback(result, request); return; } @@ -210,10 +223,8 @@ if (passdb_cache_lookup_credentials(request, passdb_ldap_cache_key, &result, &scheme)) { - if (scheme == NULL) { - scheme = passdb_ldap_conn->conn->set. - default_pass_scheme; - } + if (scheme == NULL) + scheme = passdb_ldap_conn->set.default_pass_scheme; passdb_handle_credentials(result != NULL ? PASSDB_RESULT_OK : PASSDB_RESULT_USER_UNKNOWN, credentials, result, scheme, @@ -230,24 +241,22 @@ static void passdb_ldap_preinit(const char *args) { - struct ldap_connection *conn; + passdb_ldap_conn = db_ldap_init(args); - passdb_ldap_conn = i_new(struct passdb_ldap_connection, 1); - passdb_ldap_conn->conn = conn = db_ldap_init(args); - - db_ldap_set_attrs(conn, conn->set.pass_attrs, &passdb_ldap_conn->attrs, - &passdb_ldap_conn->attr_names); - passdb_ldap_cache_key = auth_cache_parse_key(conn->set.pass_filter); + db_ldap_set_attrs(passdb_ldap_conn, passdb_ldap_conn->set.pass_attrs, + default_attr_map); + passdb_ldap_cache_key = + auth_cache_parse_key(passdb_ldap_conn->set.pass_filter); } static void passdb_ldap_init(const char *args __attr_unused__) { - (void)db_ldap_connect(passdb_ldap_conn->conn); + (void)db_ldap_connect(passdb_ldap_conn); } static void passdb_ldap_deinit(void) { - db_ldap_unref(passdb_ldap_conn->conn); + db_ldap_unref(passdb_ldap_conn); i_free(passdb_ldap_cache_key); i_free(passdb_ldap_conn); }
--- a/src/auth/passdb-sql.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/passdb-sql.c Sat Feb 12 15:47:20 2005 +0200 @@ -32,17 +32,21 @@ static char *passdb_sql_cache_key; static void result_save_extra_fields(struct sql_result *result, - struct passdb_sql_request *sql_request, - struct auth_request *auth_request) + unsigned int skip_idx, + struct passdb_sql_request *sql_request) { + struct auth_request *auth_request = sql_request->auth_request; struct auth_request_extra *extra; unsigned int i, fields_count; const char *name, *value; - extra = auth_request_extra_begin(auth_request, sql_request->password); + extra = auth_request_extra_begin(auth_request); fields_count = sql_result_get_fields_count(result); for (i = 0; i < fields_count; i++) { + if (i == skip_idx) + continue; + name = sql_result_get_field_name(result, i); value = sql_result_get_field_value(result, i); @@ -50,7 +54,8 @@ auth_request_extra_next(extra, name, value); } - auth_request_extra_finish(extra, passdb_sql_cache_key); + auth_request_extra_finish(extra, sql_request->password, + passdb_sql_cache_key); } static void sql_query_callback(struct sql_result *result, void *context) @@ -82,7 +87,7 @@ "Password query must return a field named 'password'"); } else { password = t_strdup(sql_result_get_field_value(result, idx)); - result_save_extra_fields(result, sql_request, auth_request); + result_save_extra_fields(result, idx, sql_request); passdb_result = PASSDB_RESULT_OK; }
--- a/src/auth/userdb-ldap.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/userdb-ldap.c Sat Feb 12 15:47:20 2005 +0200 @@ -6,6 +6,7 @@ #ifdef USERDB_LDAP #include "common.h" +#include "hash.h" #include "str.h" #include "var-expand.h" #include "db-ldap.h" @@ -14,22 +15,8 @@ #include <ldap.h> #include <stdlib.h> -enum ldap_user_attr { - ATTR_VIRTUAL_USER = 0, - ATTR_HOME, - ATTR_MAIL, - ATTR_SYSTEM_USER, - ATTR_UID_NUMBER, - ATTR_GID_NUMBER, - - ATTR_COUNT -}; - -struct userdb_ldap_connection { - struct ldap_connection *conn; - - unsigned int *attrs; - char **attr_names; +static const char *default_attr_map[] = { + "", "home", "mail", "system_user", "uid", "gid", NULL }; struct userdb_ldap_request { @@ -38,49 +25,103 @@ userdb_callback_t *userdb_callback; }; -static struct userdb_ldap_connection *userdb_ldap_conn; +static struct ldap_connection *userdb_ldap_conn; + +static int append_uid_list(struct auth_request *auth_request, string_t *str, + const char *name, char **vals) +{ + uid_t uid; -static void parse_attr(struct auth_request *auth_request, - struct userdb_ldap_connection *conn, - struct user_data *user, - const char *attr, const char *value) -{ - enum ldap_user_attr i; + for (; *vals != NULL; vals++) { + str_append_c(str, '\t'); + str_append(str, name); + str_append_c(str, '='); - for (i = 0; i < ATTR_COUNT; i++) { - if (strcasecmp(conn->attr_names[i], attr) == 0) - break; + uid = userdb_parse_uid(auth_request, *vals); + if (uid == (uid_t)-1) + return FALSE; + str_append(str, dec2str(uid)); } - if (i == ATTR_COUNT) { - auth_request_log_error(auth_request, "ldap", - "Unknown attribute '%s'", attr); - return; + return TRUE; +} + +static int append_gid_list(struct auth_request *auth_request, string_t *str, + const char *name, char **vals) +{ + gid_t gid; + + for (; *vals != NULL; vals++) { + str_append_c(str, '\t'); + str_append(str, name); + str_append_c(str, '='); + + gid = userdb_parse_gid(auth_request, *vals); + if (gid == (gid_t)-1) + return FALSE; + str_append(str, dec2str(gid)); } - 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 = userdb_parse_uid(auth_request, value); - break; - case ATTR_GID_NUMBER: - user->gid = userdb_parse_gid(auth_request, value); - break; + return TRUE; +} + +static const char * +ldap_query_get_result(struct ldap_connection *conn, LDAPMessage *entry, + struct auth_request *auth_request) +{ + string_t *str; + BerElement *ber; + const char *name; + char *attr, **vals; + unsigned int i; + int seen_uid = FALSE, seen_gid = FALSE; + + str = t_str_new(256); + str_append(str, auth_request->user); + + attr = ldap_first_attribute(conn->ld, entry, &ber); + while (attr != NULL) { + name = hash_lookup(userdb_ldap_conn->attr_map, attr); + vals = ldap_get_values(conn->ld, entry, attr); - case ATTR_COUNT: - break; + if (name != NULL && vals != NULL && vals[0] != NULL) { + if (strcmp(name, "uid") == 0) { + if (!append_uid_list(auth_request, str, + name, vals)) + return NULL; + seen_uid = TRUE; + } else if (strcmp(name, "gid") == 0) { + if (!append_gid_list(auth_request, str, + name, vals)) + return NULL; + seen_gid = TRUE; + } else { + for (i = 0; vals[i] != NULL; i++) { + str_append_c(str, '\t'); + str_append(str, name); + str_append_c(str, '='); + str_append(str, vals[i]); + } + } + } + ldap_value_free(vals); + ldap_memfree(attr); + + attr = ldap_next_attribute(conn->ld, entry, ber); } + + if (!seen_uid) { + auth_request_log_error(auth_request, "ldap", + "uid not in user_attrs and no default given in " + "user_global_uid"); + } + if (!seen_gid) { + auth_request_log_error(auth_request, "ldap", + "gid not in user_attrs and no default given in " + "user_global_gid"); + } + + return str_c(str); } static void handle_request(struct ldap_connection *conn, @@ -89,10 +130,8 @@ struct userdb_ldap_request *urequest = (struct userdb_ldap_request *) request; struct auth_request *auth_request = urequest->auth_request; - struct user_data user; LDAPMessage *entry; - BerElement *ber; - char *attr, **vals; + const char *result; int ret; ret = ldap_result2error(conn->ld, res, 0); @@ -109,58 +148,23 @@ auth_request_log_error(auth_request, "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(auth_request, userdb_ldap_conn, - &user, attr, vals[0]); + result = NULL; + } else { + result = ldap_query_get_result(conn, entry, auth_request); + if (ldap_next_entry(conn->ld, entry) != NULL) { + auth_request_log_error(auth_request, "ldap", + "Multiple replies found for user"); + result = NULL; } - ldap_value_free(vals); - ldap_memfree(attr); - - attr = ldap_next_attribute(conn->ld, entry, ber); } - if (user.virtual_user == NULL) - auth_request_log_error(auth_request, "ldap", - "No username in reply"); - else if (user.uid == (uid_t)-1) { - auth_request_log_error(auth_request, "ldap", - "uidNumber not set and no default given in " - "user_global_uid"); - } else if (user.gid == (gid_t)-1) { - auth_request_log_error(auth_request, "ldap", - "gidNumber not set and no default given in " - "user_global_gid"); - } else if (ldap_next_entry(conn->ld, entry) != NULL) { - auth_request_log_error(auth_request, "ldap", - "Multiple replies found for user"); - } else { - urequest->userdb_callback(&user, request->context); - t_pop(); - return; - } - - /* error */ - urequest->userdb_callback(NULL, request->context); - t_pop(); + urequest->userdb_callback(result, request->context); } 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 ldap_connection *conn = userdb_ldap_conn; const struct var_expand_table *vars; const char **attr_names = (const char **)userdb_ldap_conn->attr_names; struct userdb_ldap_request *request; @@ -195,23 +199,19 @@ static void userdb_ldap_preinit(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, &userdb_ldap_conn->attrs, - &userdb_ldap_conn->attr_names); + userdb_ldap_conn = db_ldap_init(args); + db_ldap_set_attrs(userdb_ldap_conn, userdb_ldap_conn->set.user_attrs, + default_attr_map); } static void userdb_ldap_init(const char *args __attr_unused__) { - (void)db_ldap_connect(userdb_ldap_conn->conn); + (void)db_ldap_connect(userdb_ldap_conn); } static void userdb_ldap_deinit(void) { - db_ldap_unref(userdb_ldap_conn->conn); + db_ldap_unref(userdb_ldap_conn); i_free(userdb_ldap_conn); }
--- a/src/auth/userdb-passdb.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/userdb-passdb.c Sat Feb 12 15:47:20 2005 +0200 @@ -15,18 +15,27 @@ static void passdb_lookup(struct auth_request *auth_request, userdb_callback_t *callback, void *context) { - struct user_data data; const char *const *args; + string_t *str; + uid_t uid; + gid_t gid; int uid_seen, gid_seen; - memset(&data, 0, sizeof(data)); - data.virtual_user = auth_request->user; - - uid_seen = gid_seen = FALSE; - data.uid = (uid_t)-1; - data.gid = (gid_t)-1; + if (auth_request->extra_fields == NULL) { + auth_request_log_error(auth_request, "passdb", + "passdb didn't return userdb entries"); + callback(NULL, context); + return; + } t_push(); + + uid = (uid_t)-1; gid = (gid_t)-1; + uid_seen = gid_seen = FALSE; + + str = t_str_new(256); + str_append(str, auth_request->user); + args = t_strsplit(auth_request->extra_fields, "\t"); for (; *args != NULL; args++) { const char *arg = *args; @@ -35,16 +44,26 @@ continue; arg += 7; + str_append_c(str, '\t'); if (strncmp(arg, "uid=", 4) == 0) { uid_seen = TRUE; - data.uid = userdb_parse_uid(auth_request, arg+4); + uid = userdb_parse_uid(auth_request, arg+4); + if (uid == (uid_t)-1) + break; + + str_append(str, "uid="); + str_append(str, dec2str(uid)); } else if (strncmp(arg, "gid=", 4) == 0) { gid_seen = TRUE; - data.gid = userdb_parse_gid(auth_request, arg+4); - } else if (strncmp(arg, "home=", 5) == 0) - data.home = arg + 5; - else if (strncmp(arg, "mail=", 5) == 0) - data.mail = arg + 5; + gid = userdb_parse_gid(auth_request, arg+4); + if (gid == (gid_t)-1) + break; + + str_append(str, "gid="); + str_append(str, dec2str(gid)); + } else { + str_append(str, arg); + } } if (!uid_seen) { @@ -56,10 +75,10 @@ "userdb_gid not returned"); } - if (data.uid == (uid_t)-1 || data.gid == (gid_t)-1) + if (uid == (uid_t)-1 || gid == (gid_t)-1) callback(NULL, context); else - callback(&data, context); + callback(str_c(str), context); t_pop(); }
--- a/src/auth/userdb-passwd-file.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/userdb-passwd-file.c Sat Feb 12 15:47:20 2005 +0200 @@ -6,6 +6,7 @@ #ifdef USERDB_PASSWD_FILE #include "common.h" +#include "str.h" #include "userdb.h" #include "db-passwd-file.h" @@ -14,8 +15,8 @@ static void passwd_file_lookup(struct auth_request *auth_request, userdb_callback_t *callback, void *context) { - struct user_data data; struct passwd_user *pu; + string_t *str; pu = db_passwd_file_lookup(userdb_pwf, auth_request); if (pu == NULL) { @@ -23,15 +24,16 @@ return; } - memset(&data, 0, sizeof(data)); - data.uid = pu->uid; - data.gid = pu->gid; + str = t_str_new(128); + str_printfa(str, "%s\tuid=%s\tgid=%s", + auth_request->user, dec2str(pu->uid), dec2str(pu->gid)); - data.virtual_user = auth_request->user; - data.home = pu->home; - data.mail = pu->mail; + if (pu->home != NULL) + str_printfa(str, "\thome=%s", pu->home); + if (pu->mail != NULL) + str_printfa(str, "\tmail=%s", pu->mail); - callback(&data, context); + callback(str_c(str), context); } static void passwd_file_init(const char *args)
--- a/src/auth/userdb-passwd.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/userdb-passwd.c Sat Feb 12 15:47:20 2005 +0200 @@ -13,8 +13,8 @@ static void passwd_lookup(struct auth_request *auth_request, userdb_callback_t *callback, void *context) { - struct user_data data; struct passwd *pw; + const char *result; pw = getpwnam(auth_request->user); if (pw == NULL) { @@ -23,14 +23,11 @@ return; } - memset(&data, 0, sizeof(data)); - data.uid = pw->pw_uid; - data.gid = pw->pw_gid; - - data.virtual_user = data.system_user = pw->pw_name; - data.home = pw->pw_dir; - - callback(&data, context); + result = t_strdup_printf("%s\tsystem_user=%s\tuid=%s\tgid=%s\t" + "home=%s", pw->pw_name, pw->pw_name, + dec2str(pw->pw_uid), dec2str(pw->pw_gid), + pw->pw_dir); + callback(result, context); } struct userdb_module userdb_passwd = {
--- a/src/auth/userdb-sql.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/userdb-sql.c Sat Feb 12 15:47:20 2005 +0200 @@ -23,15 +23,67 @@ static struct sql_connection *userdb_sql_conn; +static const char *sql_query_get_result(struct sql_result *result, + struct auth_request *auth_request) +{ + string_t *str; + uid_t uid, gid; + const char *name, *value; + unsigned int i, fields_count; + + uid = (uid_t)-1; + gid = (gid_t)-1; + + str = t_str_new(256); + str_append(str, auth_request->user); + + fields_count = sql_result_get_fields_count(result); + for (i = 0; i < fields_count; i++) { + name = sql_result_get_field_name(result, i); + value = sql_result_get_field_value(result, i); + + if (value == NULL) + continue; + + str_append_c(str, '\t'); + str_append(str, name); + str_append_c(str, '='); + + /* some special handling for UID and GID. */ + if (strcmp(name, "uid") == 0) { + uid = userdb_parse_uid(auth_request, value); + if (uid == (uid_t)-1) + return NULL; + value = dec2str(uid); + } else if (strcmp(name, "gid") == 0) { + gid = userdb_parse_gid(auth_request, value); + if (gid == (gid_t)-1) + return NULL; + value = dec2str(gid); + } + + str_append(str, value); + } + + if (uid == (uid_t)-1) { + auth_request_log_error(auth_request, "sql", + "Password query didn't return uid, or it was NULL"); + } + if (gid == (gid_t)-1) { + auth_request_log_error(auth_request, "sql", + "Password query didn't return gid, or it was NULL"); + } + + return str_c(str); +} + static void sql_query_callback(struct sql_result *result, void *context) { struct userdb_sql_request *sql_request = context; struct auth_request *auth_request = sql_request->auth_request; - struct user_data user; - const char *uid, *gid; + const char *user_result = NULL; int ret; - uid = gid = NULL; ret = sql_result_next_row(result); if (ret < 0) { auth_request_log_error(auth_request, "sql", @@ -39,37 +91,10 @@ } else if (ret == 0) { auth_request_log_info(auth_request, "sql", "User not found"); } else { - uid = sql_result_find_field_value(result, "uid"); - if (uid == NULL) { - auth_request_log_error(auth_request, "sql", - "Password query didn't return uid, " - "or it was NULL"); - } - gid = sql_result_find_field_value(result, "gid"); - if (gid == NULL) { - auth_request_log_error(auth_request, "sql", - "Password query didn't return gid, " - "or it was NULL"); - } + user_result = sql_query_get_result(result, auth_request); } - if (uid == NULL || gid == NULL) - sql_request->callback(NULL, sql_request->context); - else { - memset(&user, 0, sizeof(user)); - user.virtual_user = auth_request->user; - user.system_user = - sql_result_find_field_value(result, "system_user"); - user.home = sql_result_find_field_value(result, "home"); - user.mail = sql_result_find_field_value(result, "mail"); - - user.uid = userdb_parse_uid(auth_request, uid); - user.gid = userdb_parse_gid(auth_request, uid); - if (user.uid == (uid_t)-1 || user.gid == (gid_t)-1) - sql_request->callback(NULL, sql_request->context); - else - sql_request->callback(&user, sql_request->context); - } + sql_request->callback(user_result, sql_request->context); i_free(sql_request); }
--- a/src/auth/userdb-static.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/userdb-static.c Sat Feb 12 15:47:20 2005 +0200 @@ -12,83 +12,68 @@ #include <stdlib.h> -static uid_t static_uid; -static gid_t static_gid; -static char *static_home_template, *static_mail_template; +static char *static_template; static void static_lookup(struct auth_request *auth_request, userdb_callback_t *callback, void *context) { - struct user_data data; string_t *str; - memset(&data, 0, sizeof(data)); - data.uid = static_uid; - data.gid = static_gid; - - data.virtual_user = data.system_user = auth_request->user; - - if (static_home_template != NULL) { - str = t_str_new(256); - var_expand(str, static_home_template, - auth_request_get_var_expand_table(auth_request, - NULL)); - data.home = str_c(str); - } - if (static_mail_template != NULL) { - str = t_str_new(256); - var_expand(str, static_mail_template, - auth_request_get_var_expand_table(auth_request, - NULL)); - data.mail = str_c(str); - } - - callback(&data, context); + str = t_str_new(128); + str_append(str, auth_request->user); + var_expand(str, static_template, + auth_request_get_var_expand_table(auth_request, NULL)); + callback(str_c(str), context); } static void static_init(const char *args) { const char *const *tmp; + uid_t uid; + gid_t gid; + string_t *str; - static_uid = 0; - static_gid = 0; - static_home_template = NULL; - static_mail_template = NULL; + uid = (uid_t)-1; + gid = (gid_t)-1; + + t_push(); + str = t_str_new(128); for (tmp = t_strsplit_spaces(args, " "); *tmp != NULL; tmp++) { + str_append_c(str, '\t'); if (strncasecmp(*tmp, "uid=", 4) == 0) { - static_uid = userdb_parse_uid(NULL, *tmp + 4); - if (static_uid == (uid_t)-1) { + uid = userdb_parse_uid(NULL, *tmp + 4); + if (uid == (uid_t)-1) { i_fatal("static userdb: Invalid uid: %s", *tmp + 4); } + str_append(str, "uid="); + str_append(str, dec2str(uid)); } else if (strncasecmp(*tmp, "gid=", 4) == 0) { - static_gid = userdb_parse_gid(NULL, *tmp + 4); - if (static_gid == (gid_t)-1) { + gid = userdb_parse_gid(NULL, *tmp + 4); + if (gid == (gid_t)-1) { i_fatal("static userdb: Invalid gid: %s", *tmp + 4); } - } else if (strncasecmp(*tmp, "home=", 5) == 0) { - i_free(static_home_template); - static_home_template = i_strdup(*tmp + 5); - } else if (strncasecmp(*tmp, "mail=", 5) == 0) { - i_free(static_mail_template); - static_mail_template = i_strdup(*tmp + 5); + str_append(str, "gid="); + str_append(str, dec2str(gid)); } else { - i_fatal("static userdb: Invalid option: '%s'", *tmp); + str_append(str, *tmp); } } - if (static_uid == 0) + if (uid == (uid_t)-1) i_fatal("static userdb: uid missing"); - if (static_gid == 0) + if (gid == (gid_t)-1) i_fatal("static userdb: gid missing"); + + static_template = i_strdup(str_c(str)); + t_pop(); } static void static_deinit(void) { - i_free(static_home_template); - i_free(static_mail_template); + i_free(static_template); } struct userdb_module userdb_static = {
--- a/src/auth/userdb-vpopmail.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/userdb-vpopmail.c Sat Feb 12 15:47:20 2005 +0200 @@ -46,10 +46,9 @@ { char vpop_user[VPOPMAIL_LIMIT], vpop_domain[VPOPMAIL_LIMIT]; struct vqpasswd *vpw; - struct user_data data; + const char *result; uid_t uid; gid_t gid; - pool_t pool; vpw = vpopmail_lookup_vqp(auth_request, vpop_user, vpop_domain); if (vpw == NULL) { @@ -87,14 +86,11 @@ } } - memset(&data, 0, sizeof(data)); - data.uid = uid; - data.gid = gid; + result = t_strdup_printf("%s\tuid=%s\tgid=%s\thome=%s", + vpw->pw_name, dec2str(uid), dec2str(gid), + vpw->pw_dir); - data.virtual_user = vpw->pw_name; - data.home = vpw->pw_dir; - - callback(&data, context); + callback(result, context); } struct userdb_module userdb_vpopmail = {
--- a/src/auth/userdb.h Sat Feb 12 11:36:23 2005 +0200 +++ b/src/auth/userdb.h Sat Feb 12 15:47:20 2005 +0200 @@ -3,17 +3,7 @@ struct auth_request; -struct user_data { - const char *virtual_user; - const char *home; - const char *mail; - - const char *system_user; - uid_t uid; - gid_t gid; -}; - -typedef void userdb_callback_t(const struct user_data *user, void *context); +typedef void userdb_callback_t(const char *result, void *context); struct userdb_module { const char *name;
--- a/src/master/mail-process.c Sat Feb 12 11:36:23 2005 +0200 +++ b/src/master/mail-process.c Sat Feb 12 15:47:20 2005 +0200 @@ -298,7 +298,7 @@ { struct settings *set = group->set; const struct var_expand_table *var_expand_table; - const char *addr, *mail, *chroot_dir, *home_dir, *full_home_dir; + const char *p, *addr, *mail, *chroot_dir, *home_dir, *full_home_dir; const char *system_user; char title[1024]; struct log_io *log; @@ -325,12 +325,23 @@ chroot_dir = *args + 7; else if (strncmp(*args, "system_user=", 12) == 0) system_user = *args + 12; - else if (strncmp(*args, "uid=", 4) == 0) + else if (strncmp(*args, "uid=", 4) == 0) { + if (uid != 0) { + i_error("uid specified multiple times for %s", + user); + return FALSE; + } uid = (uid_t)strtoul(*args + 4, NULL, 10); - else if (strncmp(*args, "gid=", 4) == 0) + } else if (strncmp(*args, "gid=", 4) == 0) gid = (gid_t)strtoul(*args + 4, NULL, 10); } + if (*chroot_dir == '\0' && (p = strstr(home_dir, "/./")) != NULL) { + /* wu-ftpd like <chroot>/./<home> */ + chroot_dir = t_strdup_until(home_dir, p); + home_dir = p + 3; + } + if (!validate_uid_gid(set, uid, gid, user)) return FALSE;