Mercurial > dovecot > original-hg > dovecot-1.2
changeset 7122:fb03422c0760 HEAD
Added "proxy_maybe" field. If it's used instead of "proxy" and the
proxy destination matches the current connection, the user is logged in
normally instead of the login failing with "Proxying loops".
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 06 Jan 2008 03:13:20 +0200 |
parents | 05bc8679c886 |
children | 25e7c37c7c10 |
files | src/auth/auth-request-handler.c src/auth/auth-request.c src/auth/auth-request.h src/auth/auth-stream.c src/auth/auth-stream.h |
diffstat | 5 files changed, 114 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/src/auth/auth-request-handler.c Sun Jan 06 03:11:02 2008 +0200 +++ b/src/auth/auth-request-handler.c Sun Jan 06 03:13:20 2008 +0200 @@ -209,6 +209,8 @@ handler->callback(str_c(str), handler->context); break; case AUTH_CLIENT_RESULT_SUCCESS: + auth_request_proxy_finish(request); + str_printfa(str, "OK\t%u\tuser=%s", request->id, request->user); if (reply_size > 0) { str_append(str, "\tresp=");
--- a/src/auth/auth-request.c Sun Jan 06 03:11:02 2008 +0200 +++ b/src/auth/auth-request.c Sun Jan 06 03:13:20 2008 +0200 @@ -967,6 +967,33 @@ } } +static void auth_request_set_reply_field(struct auth_request *request, + const char *name, const char *value) +{ + if (strcmp(name, "nologin") == 0) { + /* user can't actually login - don't keep this + reply for master */ + request->no_login = TRUE; + value = NULL; + } else if (strcmp(name, "proxy") == 0) { + /* we're proxying authentication for this user. send + password back if using plaintext authentication. */ + request->proxy = TRUE; + value = NULL; + } else if (strcmp(name, "proxy_maybe") == 0) { + /* like "proxy", but log in normally if we're proxying to + ourself */ + request->proxy = TRUE; + request->proxy_maybe = TRUE; + name = "proxy"; + value = NULL; + } + + if (request->extra_fields == NULL) + request->extra_fields = auth_stream_reply_init(request); + auth_stream_reply_add(request->extra_fields, name, value); +} + void auth_request_set_field(struct auth_request *request, const char *name, const char *value, const char *default_scheme) @@ -1046,22 +1073,8 @@ auth_request_init_userdb_reply(request); auth_request_set_userdb_field(request, name + 7, value); } else { - if (strcmp(name, "nologin") == 0) { - /* user can't actually login - don't keep this - reply for master */ - request->no_login = TRUE; - value = NULL; - } else if (strcmp(name, "proxy") == 0) { - /* we're proxying authentication for this user. send - password back if using plaintext authentication. */ - request->proxy = TRUE; - request->no_login = TRUE; - value = NULL; - } - - if (request->extra_fields == NULL) - request->extra_fields = auth_stream_reply_init(request); - auth_stream_reply_add(request->extra_fields, name, value); + /* these fields are returned to client */ + auth_request_set_reply_field(request, name, value); return; } @@ -1213,6 +1226,52 @@ } } +static bool auth_request_proxy_is_self(struct auth_request *request) +{ + const char *const *tmp, *host = NULL, *port = NULL, *destuser = NULL; + struct ip_addr ip; + + tmp = auth_stream_split(request->extra_fields); + for (; *tmp != NULL; tmp++) { + if (strncmp(*tmp, "host=", 5) == 0) + host = *tmp + 5; + else if (strncmp(*tmp, "port=", 5) == 0) + port = *tmp + 5; + if (strncmp(*tmp, "destuser=", 9) == 0) + destuser = *tmp + 9; + } + + if (host == NULL || net_addr2ip(host, &ip) < 0) { + /* broken setup */ + return FALSE; + } + if (!net_ip_compare(&ip, &request->local_ip)) + return FALSE; + + if (port != NULL && (unsigned int)atoi(port) != request->local_port) + return FALSE; + return destuser == NULL || + strcmp(destuser, request->original_username) == 0; +} + +void auth_request_proxy_finish(struct auth_request *request) +{ + if (!request->proxy_maybe || request->no_login) + return; + + if (!auth_request_proxy_is_self(request)) { + request->no_login = TRUE; + return; + } + + /* proxying to ourself - log in without proxying by dropping all the + proxying fields. */ + auth_stream_reply_remove(request->extra_fields, "proxy"); + auth_stream_reply_remove(request->extra_fields, "host"); + auth_stream_reply_remove(request->extra_fields, "port"); + auth_stream_reply_remove(request->extra_fields, "destuser"); +} + int auth_request_password_verify(struct auth_request *request, const char *plain_password, const char *crypted_password,
--- a/src/auth/auth-request.h Sun Jan 06 03:11:02 2008 +0200 +++ b/src/auth/auth-request.h Sun Jan 06 03:13:20 2008 +0200 @@ -90,6 +90,7 @@ unsigned int no_password:1; unsigned int skip_password_check:1; unsigned int proxy:1; + unsigned int proxy_maybe:1; unsigned int cert_username:1; unsigned int userdb_lookup:1; unsigned int userdb_lookup_failed:1; @@ -147,6 +148,7 @@ void auth_request_set_userdb_field_values(struct auth_request *request, const char *name, const char *const *values); +void auth_request_proxy_finish(struct auth_request *request); int auth_request_password_verify(struct auth_request *request, const char *plain_password,
--- a/src/auth/auth-stream.c Sun Jan 06 03:11:02 2008 +0200 +++ b/src/auth/auth-stream.c Sun Jan 06 03:13:20 2008 +0200 @@ -57,6 +57,33 @@ } } +void auth_stream_reply_remove(struct auth_stream_reply *reply, const char *key) +{ + const char *str = str_c(reply->str); + unsigned int i, start, key_len = strlen(key); + + i = 0; + while (str[i] != '\0') { + start = i; + for (; str[i] != '\0'; i++) { + if (str[i] == '\t') { + i++; + break; + } + } + + if (strncmp(str+start, key, key_len) == 0 && + (str[start+key_len] == '=' || + str[start+key_len] == '\t' || + str[start+key_len] == '\0')) { + str_delete(reply->str, start, i-start); + if (str_len(reply->str) == start && start > 0) + str_delete(reply->str, start - 1, 1); + break; + } + } +} + void auth_stream_reply_reset(struct auth_stream_reply *reply) { str_truncate(reply->str, 0); @@ -78,3 +105,8 @@ { return reply == NULL || str_len(reply->str) == 0; } + +const char *const *auth_stream_split(struct auth_stream_reply *reply) +{ + return t_strsplit(str_c(reply->str), "\t"); +}
--- a/src/auth/auth-stream.h Sun Jan 06 03:11:02 2008 +0200 +++ b/src/auth/auth-stream.h Sun Jan 06 03:13:20 2008 +0200 @@ -7,9 +7,12 @@ void auth_stream_reply_add(struct auth_stream_reply *reply, const char *key, const char *value); void auth_stream_reply_reset(struct auth_stream_reply *reply); +void auth_stream_reply_remove(struct auth_stream_reply *reply, const char *key); void auth_stream_reply_import(struct auth_stream_reply *reply, const char *str); const char *auth_stream_reply_export(struct auth_stream_reply *reply); bool auth_stream_is_empty(struct auth_stream_reply *reply); +const char *const *auth_stream_split(struct auth_stream_reply *reply); + #endif