dovecot-2.0: imap-login now advertises only pre-login capabilities.

dovecot at dovecot.org dovecot at dovecot.org
Thu May 28 19:57:21 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/5f64f935e64b
changeset: 9402:5f64f935e64b
user:      Timo Sirainen <tss at iki.fi>
date:      Thu May 28 12:57:15 2009 -0400
description:
imap-login now advertises only pre-login capabilities.
If client had used CAPABILITY command before logging in, untagged CAPABILITY
is sent to client in the hope that client understands this. This change
could get reverted if it breaks too many clients.

diffstat:

8 files changed, 35 insertions(+), 67 deletions(-)
src/imap-login/client-authenticate.c |   11 +++++-
src/imap-login/client.c              |    9 ++---
src/imap-login/imap-proxy.c          |   54 +---------------------------------
src/imap/main.c                      |   16 ++++++++++
src/login-common/client-common.h     |    3 +
src/login-common/login-settings.c    |    2 -
src/login-common/login-settings.h    |    1 
src/login-common/sasl-server.c       |    6 +--

diffs (243 lines):

diff -r 82bb4c6a6d64 -r 5f64f935e64b src/imap-login/client-authenticate.c
--- a/src/imap-login/client-authenticate.c	Tue May 26 21:57:02 2009 -0400
+++ b/src/imap-login/client-authenticate.c	Thu May 28 12:57:15 2009 -0400
@@ -94,7 +94,7 @@ void client_auth_failed(struct imap_clie
 {
 	unsigned int delay_msecs;
 
-	client->common.auth_command_tag = NULL;
+	i_free_and_null(client->common.master_data_prefix);
 
 	if (client->auth_initializing)
 		return;
@@ -325,7 +325,14 @@ static int client_auth_begin(struct imap
 static int client_auth_begin(struct imap_client *client, const char *mech_name,
 			     const char *init_resp)
 {
-	client->common.auth_command_tag = client->cmd_tag;
+	char *prefix;
+
+	prefix = i_strdup_printf("%d%s", client->capability_command_used,
+				 client->cmd_tag);
+
+	i_free(client->common.master_data_prefix);
+	client->common.master_data_prefix = (void *)prefix;
+	client->common.master_data_prefix_len = strlen(prefix)+1;
 
 	client_ref(client);
 	client->auth_initializing = TRUE;
diff -r 82bb4c6a6d64 -r 5f64f935e64b src/imap-login/client.c
--- a/src/imap-login/client.c	Tue May 26 21:57:02 2009 -0400
+++ b/src/imap-login/client.c	Thu May 28 12:57:15 2009 -0400
@@ -96,13 +96,12 @@ bool client_skip_line(struct imap_client
 	return FALSE;
 }
 
-static const char *get_capability(struct imap_client *client, bool full)
+static const char *get_capability(struct imap_client *client)
 {
 	const char *auths;
 
 	auths = client_authenticate_get_capabilities(client);
-	return t_strconcat(full ? client->common.set->capability_string :
-			   CAPABILITY_BANNER_STRING,
+	return t_strconcat(CAPABILITY_BANNER_STRING,
 			   (ssl_initialized && !client->common.tls) ?
 			   " STARTTLS" : "",
 			   client->common.set->disable_plaintext_auth &&
@@ -114,7 +113,7 @@ static int cmd_capability(struct imap_cl
 {
 	client->capability_command_used = TRUE;
 	client_send_line(client, t_strconcat(
-		"* CAPABILITY ", get_capability(client, TRUE), NULL));
+		"* CAPABILITY ", get_capability(client), NULL));
 	client_send_tagline(client, "OK Capability completed.");
 	return 1;
 }
@@ -474,7 +473,7 @@ static void client_send_greeting(struct 
 
 	greet = t_str_new(128);
 	str_append(greet, "* OK ");
-	str_printfa(greet, "[CAPABILITY %s] ", get_capability(client, FALSE));
+	str_printfa(greet, "[CAPABILITY %s] ", get_capability(client));
 	str_append(greet, client->common.set->login_greeting);
 
 	client_send_line(client, str_c(greet));
diff -r 82bb4c6a6d64 -r 5f64f935e64b src/imap-login/imap-proxy.c
--- a/src/imap-login/imap-proxy.c	Tue May 26 21:57:02 2009 -0400
+++ b/src/imap-login/imap-proxy.c	Thu May 28 12:57:15 2009 -0400
@@ -20,32 +20,6 @@
 #define PROXY_FAILURE_MSG \
 	"NO ["IMAP_RESP_CODE_UNAVAILABLE"] "AUTH_TEMP_FAILED_MSG
 
-static const char *const *
-capabilities_strip_prelogin(const char *const *capabilities)
-{
-	ARRAY_TYPE(const_string) new_caps_arr;
-	const char **new_caps, *str;
-	unsigned int count;
-
-	t_array_init(&new_caps_arr, 64);
-	for (; *capabilities != NULL; capabilities++) {
-		if (strncasecmp(*capabilities, "AUTH=", 5) == 0 ||
-		    strcasecmp(*capabilities, "STARTTLS") == 0 ||
-		    strcasecmp(*capabilities, "SASL-IR") == 0 ||
-		    strcasecmp(*capabilities, "LOGINDISABLED") == 0 ||
-		    strcasecmp(*capabilities, "LOGIN-REFERRALS") == 0)
-			continue;
-
-		str = *capabilities;
-		array_append(&new_caps_arr, &str, 1);
-	}
-	new_caps = array_get_modifiable(&new_caps_arr, &count);
-	qsort(new_caps, count, sizeof(*new_caps), i_strcasecmp_p);
-
-	(void)array_append_space(&new_caps_arr);
-	return array_idx(&new_caps_arr, 0);
-}
-
 static void proxy_write_id(struct imap_client *client, string_t *str)
 {
 	str_printfa(str, "I ID ("
@@ -95,24 +69,10 @@ static void get_plain_auth(struct imap_c
 	base64_encode(str_data(str), str_len(str), dest);
 }
 
-static bool str_array_icmp(const char *const *arr1, const char *const *arr2)
-{
-	unsigned int i;
-
-	for (i = 0; arr1[i] != NULL; i++) {
-		if (arr2[i] == NULL || strcasecmp(arr1[i], arr2[i]) != 0)
-			return FALSE;
-	}
-	return TRUE;
-}
-
 static void
 client_send_capability_if_needed(struct imap_client *client, string_t *str,
 				 const char *capability)
 {
-	const char *const *backend_capabilities;
-	const char *const *proxy_capabilities;
-
 	if (!client->capability_command_used || capability == NULL)
 		return;
 
@@ -121,18 +81,8 @@ client_send_capability_if_needed(struct 
 	client->capability_command_used = FALSE;
 
 	/* client has used CAPABILITY command, so it didn't understand the
-	   capabilities in the banner. if backend server has different
-	   capabilities than we advertised already, there's a problem.
-	   to solve that we'll send the backend's untagged CAPABILITY reply
-	   and hope that the client understands it */
-	backend_capabilities =
-		capabilities_strip_prelogin(t_strsplit(capability, " "));
-	proxy_capabilities =
-		capabilities_strip_prelogin(t_strsplit(client->common.set->capability_string, " "));
-
-	if (str_array_icmp(backend_capabilities, proxy_capabilities))
-		return;
-
+	   capabilities in the banner. send the backend's untagged CAPABILITY
+	   reply and hope that the client understands it */
 	str_printfa(str, "* CAPABILITY %s\r\n", capability);
 }
 
diff -r 82bb4c6a6d64 -r 5f64f935e64b src/imap/main.c
--- a/src/imap/main.c	Tue May 26 21:57:02 2009 -0400
+++ b/src/imap/main.c	Thu May 28 12:57:15 2009 -0400
@@ -75,10 +75,20 @@ static void client_add_input(struct clie
 	buffer_t *buf;
 	const char *tag;
 	unsigned int data_pos;
+	bool send_untagged_capability = FALSE;
 
 	buf = input == NULL ? NULL : t_base64_decode_str(input);
 	if (buf != NULL && buf->used > 0) {
 		tag = t_strndup(buf->data, buf->used);
+		switch (*tag) {
+		case '0':
+			tag++;
+			break;
+		case '1':
+			send_untagged_capability = TRUE;
+			tag++;
+			break;
+		}
 		data_pos = strlen(tag) + 1;
 		if (data_pos > buf->used &&
 		    !i_stream_add_data(client->input,
@@ -95,6 +105,12 @@ static void client_add_input(struct clie
 			"* PREAUTH [CAPABILITY ",
 			str_c(client->capability_string), "] "
 			"Logged in as ", client->user->username, NULL));
+	} else if (send_untagged_capability) {
+		/* client doesn't seem to understand tagged capabilities. send
+		   untagged instead and hope that it works. */
+		client_send_line(client, t_strconcat("* CAPABILITY ",
+			str_c(client->capability_string), NULL));
+		client_send_line(client, t_strconcat(tag, " Logged in", NULL));
 	} else {
 		client_send_line(client, t_strconcat(
 			tag, " OK [CAPABILITY ",
diff -r 82bb4c6a6d64 -r 5f64f935e64b src/login-common/client-common.h
--- a/src/login-common/client-common.h	Tue May 26 21:57:02 2009 -0400
+++ b/src/login-common/client-common.h	Thu May 28 12:57:15 2009 -0400
@@ -24,7 +24,8 @@ struct client {
 
 	int fd;
 	struct istream *input;
-	const char *auth_command_tag;
+	unsigned char *master_data_prefix;
+	unsigned int master_data_prefix_len;
 
 	char *auth_mech_name;
 	struct auth_request *auth_request;
diff -r 82bb4c6a6d64 -r 5f64f935e64b src/login-common/login-settings.c
--- a/src/login-common/login-settings.c	Tue May 26 21:57:02 2009 -0400
+++ b/src/login-common/login-settings.c	Thu May 28 12:57:15 2009 -0400
@@ -22,7 +22,6 @@ static struct setting_define login_setti
 	DEF(SET_STR, login_log_format),
 
 	DEF(SET_BOOL, login_process_per_connection),
-	DEF(SET_STR, capability_string),
 
 	DEF(SET_ENUM, ssl),
 	DEF(SET_STR, ssl_ca_file),
@@ -56,7 +55,6 @@ static struct login_settings login_defau
 	MEMBER(login_log_format) "%$: %s",
 
 	MEMBER(login_process_per_connection) TRUE,
-	MEMBER(capability_string) NULL,
 
 	MEMBER(ssl) "yes:no:required",
 	MEMBER(ssl_ca_file) "",
diff -r 82bb4c6a6d64 -r 5f64f935e64b src/login-common/login-settings.h
--- a/src/login-common/login-settings.h	Tue May 26 21:57:02 2009 -0400
+++ b/src/login-common/login-settings.h	Thu May 28 12:57:15 2009 -0400
@@ -10,7 +10,6 @@ struct login_settings {
 	const char *login_log_format_elements, *login_log_format;
 
 	bool login_process_per_connection;
-	const char *capability_string;
 
 	const char *ssl;
 	const char *ssl_ca_file;
diff -r 82bb4c6a6d64 -r 5f64f935e64b src/login-common/sasl-server.c
--- a/src/login-common/sasl-server.c	Tue May 26 21:57:02 2009 -0400
+++ b/src/login-common/sasl-server.c	Thu May 28 12:57:15 2009 -0400
@@ -84,10 +84,8 @@ master_send_request(struct client *clien
 	req.remote_ip = client->ip;
 
 	buf = buffer_create_dynamic(pool_datastack_create(), 256);
-	if (client->auth_command_tag != NULL) {
-		buffer_append(buf, client->auth_command_tag,
-			      strlen(client->auth_command_tag)+1);
-	}
+	buffer_append(buf, client->master_data_prefix,
+		      client->master_data_prefix_len);
 
 	data = i_stream_get_data(client->input, &size);
 	buffer_append(buf, data, size);


More information about the dovecot-cvs mailing list