Mercurial > dovecot > core-2.2
changeset 4880:4ec6a4def05b HEAD
We treated internal userdb lookup errors as "user unknown" errors. In such
situations this caused deliver to think the user didn't exist and the mail
get bounced.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 09 Dec 2006 17:11:48 +0200 |
parents | b0ada6e57b07 |
children | 53ac6f2c1242 |
files | src/auth/auth-master-connection.c src/auth/auth-request-handler.c src/auth/auth-request.c src/auth/auth-request.h src/auth/auth-worker-client.c src/auth/userdb-blocking.c src/auth/userdb-ldap.c src/auth/userdb-passwd-file.c src/auth/userdb-passwd.c src/auth/userdb-prefetch.c src/auth/userdb-sql.c src/auth/userdb-static.c src/auth/userdb-vpopmail.c src/auth/userdb.h |
diffstat | 14 files changed, 105 insertions(+), 42 deletions(-) [+] |
line wrap: on
line diff
--- a/src/auth/auth-master-connection.c Thu Dec 07 01:43:15 2006 +0200 +++ b/src/auth/auth-master-connection.c Sat Dec 09 17:11:48 2006 +0200 @@ -78,18 +78,25 @@ } static void -user_callback(struct auth_stream_reply *reply, +user_callback(enum userdb_result result, + struct auth_stream_reply *reply, struct auth_request *auth_request) { struct auth_master_connection *conn = auth_request->context; string_t *str; str = t_str_new(128); - if (reply == NULL) + switch (result) { + case USERDB_RESULT_INTERNAL_FAILURE: + str_printfa(str, "FAIL\t%u", auth_request->id); + break; + case USERDB_RESULT_USER_UNKNOWN: str_printfa(str, "NOTFOUND\t%u", auth_request->id); - else { + break; + case USERDB_RESULT_OK: str_printfa(str, "USER\t%u\t", auth_request->id); str_append(str, auth_stream_reply_export(reply)); + break; } if (conn->listener->auth->verbose_debug)
--- a/src/auth/auth-request-handler.c Thu Dec 07 01:43:15 2006 +0200 +++ b/src/auth/auth-request-handler.c Sat Dec 09 17:11:48 2006 +0200 @@ -396,7 +396,8 @@ return TRUE; } -static void userdb_callback(struct auth_stream_reply *reply, +static void userdb_callback(enum userdb_result result, + struct auth_stream_reply *reply, struct auth_request *request) { struct auth_request_handler *handler = request->context; @@ -407,15 +408,21 @@ request->state = AUTH_REQUEST_STATE_FINISHED; str = t_str_new(256); - if (reply == NULL) + switch (result) { + case USERDB_RESULT_INTERNAL_FAILURE: + str_printfa(str, "FAIL\t%u", request->id); + break; + case USERDB_RESULT_USER_UNKNOWN: str_printfa(str, "NOTFOUND\t%u", request->id); - else { + break; + case USERDB_RESULT_OK: if (request->master_user != NULL) { auth_stream_reply_add(reply, "master_user", request->master_user); } str_printfa(str, "USER\t%u\t", request->id); str_append(str, auth_stream_reply_export(reply)); + break; } handler->master_callback(str_c(str), request->master);
--- a/src/auth/auth-request.c Thu Dec 07 01:43:15 2006 +0200 +++ b/src/auth/auth-request.c Sat Dec 09 17:11:48 2006 +0200 @@ -564,24 +564,34 @@ } } -void auth_request_userdb_callback(struct auth_stream_reply *reply, +void auth_request_userdb_callback(enum userdb_result result, + struct auth_stream_reply *reply, struct auth_request *request) { - if (reply == NULL && request->userdb->next != NULL) { + if (result != USERDB_RESULT_OK && request->userdb->next != NULL) { /* try next userdb. */ + if (result == USERDB_RESULT_INTERNAL_FAILURE) + request->userdb_internal_failure = TRUE; + request->userdb = request->userdb->next; auth_request_lookup_user(request, request->private_callback.userdb); return; } - if (reply == NULL && request->client_pid != 0) { - /* this was actual login attempt */ + if (request->userdb_internal_failure && result != USERDB_RESULT_OK) { + /* one of the userdb lookups failed. the user might have been + in there, so this is an internal failure */ + result = USERDB_RESULT_INTERNAL_FAILURE; + } else if (result == USERDB_RESULT_USER_UNKNOWN && + request->client_pid != 0) { + /* this was an actual login attempt, the user should + have been found. */ auth_request_log_error(request, "userdb", "user not found from userdb"); } - request->private_callback.userdb(reply, request); + request->private_callback.userdb(result, reply, request); } void auth_request_lookup_user(struct auth_request *request,
--- a/src/auth/auth-request.h Thu Dec 07 01:43:15 2006 +0200 +++ b/src/auth/auth-request.h Sat Dec 09 17:11:48 2006 +0200 @@ -72,6 +72,7 @@ unsigned int passdb_failure:1; unsigned int internal_failure:1; unsigned int passdb_internal_failure:1; + unsigned int userdb_internal_failure:1; unsigned int delayed_failure:1; unsigned int accept_input:1; unsigned int no_failure_delay:1; @@ -154,7 +155,8 @@ enum passdb_credentials credentials, const char *data, set_credentials_callback_t *callback); -void auth_request_userdb_callback(struct auth_stream_reply *reply, +void auth_request_userdb_callback(enum userdb_result result, + struct auth_stream_reply *reply, struct auth_request *request); #endif
--- a/src/auth/auth-worker-client.c Thu Dec 07 01:43:15 2006 +0200 +++ b/src/auth/auth-worker-client.c Sat Dec 09 17:11:48 2006 +0200 @@ -298,16 +298,27 @@ } static void -lookup_user_callback(struct auth_stream_reply *reply, +lookup_user_callback(enum userdb_result result, + struct auth_stream_reply *reply, struct auth_request *auth_request) { struct auth_worker_client *client = auth_request->context; string_t *str; - str = t_str_new(64); + str = t_str_new(128); str_printfa(str, "%u\t", auth_request->id); - if (reply != NULL) + switch (result) { + case USERDB_RESULT_INTERNAL_FAILURE: + str_append(str, "FAIL\t"); + break; + case USERDB_RESULT_USER_UNKNOWN: + str_append(str, "NOTFOUND\t"); + break; + case USERDB_RESULT_OK: + str_append(str, "OK\t"); str_append(str, auth_stream_reply_export(reply)); + break; + } str_append_c(str, '\n'); o_stream_send(client->output, str_data(str), str_len(str));
--- a/src/auth/userdb-blocking.c Thu Dec 07 01:43:15 2006 +0200 +++ b/src/auth/userdb-blocking.c Sat Dec 09 17:11:48 2006 +0200 @@ -10,16 +10,23 @@ static void user_callback(struct auth_request *request, const char *reply) { - struct auth_stream_reply *stream_reply; + struct auth_stream_reply *stream_reply = NULL; + enum userdb_result result; - if (*reply == '\0') - stream_reply = NULL; - else { + if (strncmp(reply, "FAIL\t", 5) == 0) + result = USERDB_RESULT_INTERNAL_FAILURE; + else if (strncmp(reply, "NOTFOUND\t", 9) == 0) + result = USERDB_RESULT_USER_UNKNOWN; + else if (strncmp(reply, "OK\t", 3) == 0) { + result = USERDB_RESULT_OK; stream_reply = auth_stream_reply_init(request); auth_stream_reply_import(stream_reply, reply); + } else { + result = USERDB_RESULT_INTERNAL_FAILURE; + i_error("BUG: auth-worker sent invalid user reply"); } - auth_request_userdb_callback(stream_reply, request); + auth_request_userdb_callback(result, stream_reply, request); } void userdb_blocking_lookup(struct auth_request *request)
--- a/src/auth/userdb-ldap.c Thu Dec 07 01:43:15 2006 +0200 +++ b/src/auth/userdb-ldap.c Sat Dec 09 17:11:48 2006 +0200 @@ -138,32 +138,36 @@ struct auth_request *auth_request = urequest->auth_request; LDAPMessage *entry; struct auth_stream_reply *reply = NULL; + enum userdb_result result = USERDB_RESULT_INTERNAL_FAILURE; int ret; ret = ldap_result2error(conn->ld, res, 0); if (ret != LDAP_SUCCESS) { auth_request_log_error(auth_request, "ldap", "ldap_search() failed: %s", ldap_err2string(ret)); - urequest->userdb_callback(NULL, auth_request); + urequest->userdb_callback(result, NULL, auth_request); return; } entry = res == NULL ? NULL : ldap_first_entry(conn->ld, res); if (entry == NULL) { if (res != NULL) { + result = USERDB_RESULT_USER_UNKNOWN; auth_request_log_error(auth_request, "ldap", "Authenticated user not found"); } } else { reply = ldap_query_get_result(conn, entry, auth_request); - if (ldap_next_entry(conn->ld, entry) != NULL) { + if (ldap_next_entry(conn->ld, entry) == NULL) + result = USERDB_RESULT_OK; + else { auth_request_log_error(auth_request, "ldap", "Multiple replies found for user"); reply = NULL; } } - urequest->userdb_callback(reply, auth_request); + urequest->userdb_callback(result, reply, auth_request); auth_request_unref(&auth_request); }
--- a/src/auth/userdb-passwd-file.c Thu Dec 07 01:43:15 2006 +0200 +++ b/src/auth/userdb-passwd-file.c Sat Dec 09 17:11:48 2006 +0200 @@ -31,7 +31,7 @@ pu = db_passwd_file_lookup(module->pwf, auth_request); if (pu == NULL) { - callback(NULL, auth_request); + callback(USERDB_RESULT_USER_UNKNOWN, NULL, auth_request); return; } @@ -65,7 +65,7 @@ t_pop(); } - callback(reply, auth_request); + callback(USERDB_RESULT_OK, reply, auth_request); } static struct userdb_module *
--- a/src/auth/userdb-passwd.c Thu Dec 07 01:43:15 2006 +0200 +++ b/src/auth/userdb-passwd.c Sat Dec 09 17:11:48 2006 +0200 @@ -17,7 +17,7 @@ pw = getpwnam(auth_request->user); if (pw == NULL) { auth_request_log_info(auth_request, "passwd", "unknown user"); - callback(NULL, auth_request); + callback(USERDB_RESULT_USER_UNKNOWN, NULL, auth_request); return; } @@ -36,7 +36,7 @@ auth_stream_reply_add(reply, "gid", dec2str(pw->pw_gid)); auth_stream_reply_add(reply, "home", pw->pw_dir); - callback(reply, auth_request); + callback(USERDB_RESULT_OK, reply, auth_request); } struct userdb_module_interface userdb_passwd = {
--- a/src/auth/userdb-prefetch.c Thu Dec 07 01:43:15 2006 +0200 +++ b/src/auth/userdb-prefetch.c Sat Dec 09 17:11:48 2006 +0200 @@ -29,7 +29,7 @@ auth_request_log_info(auth_request, "prefetch", "passdb didn't return userdb entries"); } - callback(NULL, auth_request); + callback(USERDB_RESULT_USER_UNKNOWN, NULL, auth_request); return; } @@ -84,7 +84,7 @@ } if (uid == (uid_t)-1 || gid == (gid_t)-1) - callback(NULL, auth_request); + callback(USERDB_RESULT_USER_UNKNOWN, NULL, auth_request); else { struct auth_stream_reply *reply; @@ -92,7 +92,7 @@ exported they are already in escaped form in the string. */ reply = auth_stream_reply_init(auth_request); auth_stream_reply_import(reply, str_c(str)); - callback(reply, auth_request); + callback(USERDB_RESULT_OK, reply, auth_request); } t_pop(); }
--- a/src/auth/userdb-sql.c Thu Dec 07 01:43:15 2006 +0200 +++ b/src/auth/userdb-sql.c Sat Dec 09 17:11:48 2006 +0200 @@ -78,24 +78,29 @@ return reply; } -static void sql_query_callback(struct sql_result *result, void *context) +static void sql_query_callback(struct sql_result *sql_result, void *context) { struct userdb_sql_request *sql_request = context; struct auth_request *auth_request = sql_request->auth_request; struct auth_stream_reply *reply = NULL; + enum userdb_result result = USERDB_RESULT_INTERNAL_FAILURE; int ret; - ret = sql_result_next_row(result); + ret = sql_result_next_row(sql_result); if (ret < 0) { auth_request_log_error(auth_request, "sql", - "User query failed: %s", sql_result_get_error(result)); + "User query failed: %s", + sql_result_get_error(sql_result)); } else if (ret == 0) { + result = USERDB_RESULT_USER_UNKNOWN; auth_request_log_info(auth_request, "sql", "User not found"); } else { - reply = sql_query_get_result(result, auth_request); + reply = sql_query_get_result(sql_result, auth_request); + if (reply != NULL) + result = USERDB_RESULT_OK; } - sql_request->callback(reply, auth_request); + sql_request->callback(result, reply, auth_request); auth_request_unref(&auth_request); i_free(sql_request); }
--- a/src/auth/userdb-static.c Thu Dec 07 01:43:15 2006 +0200 +++ b/src/auth/userdb-static.c Sat Dec 09 17:11:48 2006 +0200 @@ -49,7 +49,7 @@ auth_stream_reply_add(reply, args[i], value); } - callback(reply, auth_request); + callback(USERDB_RESULT_OK, reply, auth_request); t_pop(); }
--- a/src/auth/userdb-vpopmail.c Thu Dec 07 01:43:15 2006 +0200 +++ b/src/auth/userdb-vpopmail.c Sat Dec 09 17:11:48 2006 +0200 @@ -50,7 +50,7 @@ vpw = vpopmail_lookup_vqp(auth_request, vpop_user, vpop_domain); if (vpw == NULL) { - callback(NULL, auth_request); + callback(USERDB_RESULT_USER_UNKNOWN, NULL, auth_request); return; } @@ -59,7 +59,7 @@ if (vget_assign(vpop_domain, NULL, 0, &uid, &gid) == NULL) { auth_request_log_info(auth_request, "vpopmail", "vget_assign(%s) failed", vpop_domain); - callback(NULL, auth_request); + callback(USERDB_RESULT_INTERNAL_FAILURE, NULL, auth_request); return; } @@ -72,14 +72,16 @@ auth_request_log_error(auth_request, "vpopmail", "make_user_dir(%s, %s) failed", vpop_user, vpop_domain); - callback(NULL, auth_request); + callback(USERDB_RESULT_INTERNAL_FAILURE, + NULL, auth_request); return; } /* get the user again so pw_dir is visible */ vpw = vauth_getpw(vpop_user, vpop_domain); if (vpw == NULL) { - callback(NULL, auth_request); + callback(USERDB_RESULT_INTERNAL_FAILURE, + NULL, auth_request); return; } } @@ -90,7 +92,7 @@ auth_stream_reply_add(reply, "gid", dec2str(gid)); auth_stream_reply_add(reply, "home", vpw->pw_dir); - callback(reply, auth_request); + callback(USERDB_RESULT_OK, reply, auth_request); } struct userdb_module_interface userdb_vpopmail = {
--- a/src/auth/userdb.h Thu Dec 07 01:43:15 2006 +0200 +++ b/src/auth/userdb.h Sat Dec 09 17:11:48 2006 +0200 @@ -5,7 +5,15 @@ struct auth_request; -typedef void userdb_callback_t(struct auth_stream_reply *reply, +enum userdb_result { + USERDB_RESULT_INTERNAL_FAILURE = -1, + USERDB_RESULT_USER_UNKNOWN = -2, + + USERDB_RESULT_OK = 1 +}; + +typedef void userdb_callback_t(enum userdb_result result, + struct auth_stream_reply *reply, struct auth_request *request); struct userdb_module {