dovecot: Added "proxy_maybe" field. If it's used instead of "pro...
dovecot at dovecot.org
dovecot at dovecot.org
Sun Jan 6 03:13:23 EET 2008
details: http://hg.dovecot.org/dovecot/rev/fb03422c0760
changeset: 7122:fb03422c0760
user: Timo Sirainen <tss at iki.fi>
date: Sun Jan 06 03:13:20 2008 +0200
description:
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".
diffstat:
5 files changed, 114 insertions(+), 16 deletions(-)
src/auth/auth-request-handler.c | 2
src/auth/auth-request.c | 91 ++++++++++++++++++++++++++++++++-------
src/auth/auth-request.h | 2
src/auth/auth-stream.c | 32 +++++++++++++
src/auth/auth-stream.h | 3 +
diffs (208 lines):
diff -r 05bc8679c886 -r fb03422c0760 src/auth/auth-request-handler.c
--- 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 @@ static void auth_callback(struct auth_re
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=");
diff -r 05bc8679c886 -r fb03422c0760 src/auth/auth-request.c
--- 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 @@ auth_request_set_password(struct auth_re
}
}
+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 @@ void auth_request_set_field(struct auth_
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;
}
@@ -1211,6 +1224,52 @@ void auth_request_set_userdb_field_value
/* add only one */
auth_request_set_userdb_field(request, name, *values);
}
+}
+
+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,
diff -r 05bc8679c886 -r fb03422c0760 src/auth/auth-request.h
--- 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 @@ struct auth_request {
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_value
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,
diff -r 05bc8679c886 -r fb03422c0760 src/auth/auth-stream.c
--- 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_add(struct auth_s
}
}
+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 @@ bool auth_stream_is_empty(struct auth_st
{
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");
+}
diff -r 05bc8679c886 -r fb03422c0760 src/auth/auth-stream.h
--- 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_s
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
More information about the dovecot-cvs
mailing list