dovecot-2.0: *-login: Fixes to SSL/login proxy connection counting.

dovecot at dovecot.org dovecot at dovecot.org
Fri Sep 11 20:43:42 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/d60fa42fbaac
changeset: 9929:d60fa42fbaac
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Sep 11 13:43:37 2009 -0400
description:
*-login: Fixes to SSL/login proxy connection counting.

diffstat:

11 files changed, 75 insertions(+), 60 deletions(-)
src/imap-login/client.c               |    2 -
src/login-common/client-common-auth.c |   10 +----
src/login-common/client-common.c      |   23 +++++++-----
src/login-common/client-common.h      |    3 -
src/login-common/login-proxy.c        |   60 +++++++++++++++++----------------
src/login-common/login-proxy.h        |    3 -
src/login-common/main.c               |    2 -
src/login-common/ssl-proxy-openssl.c  |   21 ++++++++---
src/login-common/ssl-proxy.c          |    5 ++
src/login-common/ssl-proxy.h          |    4 +-
src/pop3-login/client.c               |    2 -

diffs (truncated from 445 to 300 lines):

diff -r 4dd2430a7c62 -r d60fa42fbaac src/imap-login/client.c
--- a/src/imap-login/client.c	Fri Sep 11 12:47:23 2009 -0400
+++ b/src/imap-login/client.c	Fri Sep 11 13:43:37 2009 -0400
@@ -291,7 +291,7 @@ static void imap_client_input(struct cli
 		o_stream_uncork(imap_client->common.output);
 	}
 
-	client_unref(client);
+	client_unref(&client);
 }
 
 static struct client *imap_client_alloc(pool_t pool)
diff -r 4dd2430a7c62 -r d60fa42fbaac src/login-common/client-common-auth.c
--- a/src/login-common/client-common-auth.c	Fri Sep 11 12:47:23 2009 -0400
+++ b/src/login-common/client-common-auth.c	Fri Sep 11 13:43:37 2009 -0400
@@ -164,13 +164,7 @@ void client_proxy_finish_destroy_client(
 	if (client->proxy_master_user != NULL)
 		str_printfa(str, " (master %s)", client->proxy_master_user);
 
-	login_proxy_detach(client->login_proxy, client->input, client->output);
-
-	client->login_proxy = NULL;
-	client->input = NULL;
-	client->output = NULL;
-	client->fd = -1;
-	client->proxying = TRUE;
+	login_proxy_detach(client->login_proxy);
 	client_destroy_success(client, str_c(str));
 }
 
@@ -480,7 +474,7 @@ sasl_callback(struct client *client, enu
 		return;
 	}
 
-	client_unref(client);
+	client_unref(&client);
 }
 
 int client_auth_begin(struct client *client, const char *mech_name,
diff -r 4dd2430a7c62 -r d60fa42fbaac src/login-common/client-common.c
--- a/src/login-common/client-common.c	Fri Sep 11 12:47:23 2009 -0400
+++ b/src/login-common/client-common.c	Fri Sep 11 13:43:37 2009 -0400
@@ -160,7 +160,7 @@ void client_destroy(struct client *clien
 	if (client->ssl_proxy != NULL)
 		ssl_proxy_free(&client->ssl_proxy);
 	client->v.destroy(client);
-	client_unref(client);
+	client_unref(&client);
 }
 
 void client_destroy_success(struct client *client, const char *reason)
@@ -182,27 +182,30 @@ void client_ref(struct client *client)
 	client->refcount++;
 }
 
-bool client_unref(struct client *client)
-{
+bool client_unref(struct client **_client)
+{
+	struct client *client = *_client;
+
 	i_assert(client->refcount > 0);
 	if (--client->refcount > 0)
 		return TRUE;
 
+	*_client = NULL;
+
 	i_assert(client->destroyed);
+	i_assert(client->ssl_proxy == NULL);
+	i_assert(client->login_proxy == NULL);
 
 	if (client->input != NULL)
 		i_stream_unref(&client->input);
 	if (client->output != NULL)
 		o_stream_unref(&client->output);
 
-	if (!client->proxying) {
-		i_assert(client->ssl_proxy == NULL);
-		master_service_client_connection_destroyed(master_service);
-	}
-
 	i_free(client->virtual_user);
 	i_free(client->auth_mech_name);
 	pool_unref(&client->pool);
+
+	master_service_client_connection_destroyed(master_service);
 	return FALSE;
 }
 
@@ -243,7 +246,7 @@ static void client_start_tls(struct clie
 	int fd_ssl;
 
 	client_ref(client);
-	if (!client_unref(client) || client->destroyed)
+	if (!client_unref(&client) || client->destroyed)
 		return;
 
 	fd_ssl = ssl_proxy_new(client->fd, &client->ip,
@@ -255,9 +258,9 @@ static void client_start_tls(struct clie
 			       "Disconnected: TLS initialization failed.");
 		return;
 	}
+	ssl_proxy_set_client(client->ssl_proxy, client);
 
 	client->starttls = TRUE;
-	client->proxying = TRUE;
 	client->tls = TRUE;
 	client->secured = TRUE;
 	client_set_title(client);
diff -r 4dd2430a7c62 -r d60fa42fbaac src/login-common/client-common.h
--- a/src/login-common/client-common.h	Fri Sep 11 12:47:23 2009 -0400
+++ b/src/login-common/client-common.h	Fri Sep 11 13:43:37 2009 -0400
@@ -115,7 +115,6 @@ struct client {
 	unsigned int tls:1;
 	unsigned int secured:1;
 	unsigned int trusted:1;
-	unsigned int proxying:1;
 	unsigned int authenticating:1;
 	unsigned int auth_tried_disabled_plaintext:1;
 	unsigned int auth_initializing:1;
@@ -134,7 +133,7 @@ void client_destroy_internal_failure(str
 void client_destroy_internal_failure(struct client *client);
 
 void client_ref(struct client *client);
-bool client_unref(struct client *client);
+bool client_unref(struct client **client);
 
 void client_cmd_starttls(struct client *client);
 
diff -r 4dd2430a7c62 -r d60fa42fbaac src/login-common/login-proxy.c
--- a/src/login-common/login-proxy.c	Fri Sep 11 12:47:23 2009 -0400
+++ b/src/login-common/login-proxy.c	Fri Sep 11 13:43:37 2009 -0400
@@ -19,13 +19,12 @@ struct login_proxy {
 struct login_proxy {
 	struct login_proxy *prev, *next;
 
-	struct client *prelogin_client;
+	struct client *client;
 	int client_fd, server_fd;
 	struct io *client_io, *server_io;
 	struct istream *server_input;
 	struct ostream *client_output, *server_output;
-	struct ip_addr ip;
-	struct ssl_proxy *ssl_proxy;
+	struct ssl_proxy *ssl_server_proxy;
 
 	struct timeval created;
 	struct timeout *to;
@@ -226,7 +225,8 @@ login_proxy_new(struct client *client, c
 	proxy->user = i_strdup(client->virtual_user);
 	proxy->port = set->port;
 	proxy->ssl_flags = set->ssl_flags;
-	proxy->prelogin_client = client;
+	proxy->client = client;
+	client_ref(client);
 
 	proxy->server_fd = fd;
 	proxy->server_io = io_add(fd, IO_WRITE, proxy_wait_connect, proxy);
@@ -238,7 +238,6 @@ login_proxy_new(struct client *client, c
 	proxy->callback = callback;
 	proxy->context = context;
 
-	proxy->ip = client->ip;
 	proxy->client_fd = -1;
 
 	proxy->state_rec = rec;
@@ -249,6 +248,7 @@ void login_proxy_free(struct login_proxy
 void login_proxy_free(struct login_proxy **_proxy)
 {
 	struct login_proxy *proxy = *_proxy;
+	struct client *client = proxy->client;
 	const char *ipstr;
 
 	*_proxy = NULL;
@@ -276,7 +276,7 @@ void login_proxy_free(struct login_proxy
 		/* detached proxy */
 		DLLIST_REMOVE(&login_proxies, proxy);
 
-		ipstr = net_ip2addr(&proxy->ip);
+		ipstr = net_ip2addr(&proxy->client->ip);
 		i_info("proxy(%s): disconnecting %s",
 		       str_sanitize(proxy->user, 80),
 		       ipstr != NULL ? ipstr : "");
@@ -293,15 +293,16 @@ void login_proxy_free(struct login_proxy
 		proxy->callback(proxy->context);
 	}
 
-	if (proxy->ssl_proxy != NULL)
-		ssl_proxy_free(&proxy->ssl_proxy);
 	net_disconnect(proxy->server_fd);
 
+	if (proxy->ssl_server_proxy != NULL)
+		ssl_proxy_free(&proxy->ssl_server_proxy);
 	i_free(proxy->host);
 	i_free(proxy->user);
 	i_free(proxy);
 
-	master_service_client_connection_destroyed(master_service);
+	client->login_proxy = NULL;
+	client_unref(&client);
 }
 
 bool login_proxy_is_ourself(const struct client *client, const char *host,
@@ -346,27 +347,26 @@ login_proxy_get_ssl_flags(const struct l
 	return proxy->ssl_flags;
 }
 
-void login_proxy_detach(struct login_proxy *proxy, struct istream *client_input,
-			struct ostream *client_output)
-{
+void login_proxy_detach(struct login_proxy *proxy)
+{
+	struct client *client = proxy->client;
 	const unsigned char *data;
 	size_t size;
 
 	i_assert(proxy->client_fd == -1);
 	i_assert(proxy->server_output != NULL);
 
-	proxy->prelogin_client = NULL;
-	proxy->client_fd = i_stream_get_fd(client_input);
-	proxy->client_output = client_output;
-
-	o_stream_set_max_buffer_size(client_output, (size_t)-1);
-	o_stream_set_flush_callback(client_output, proxy_client_output, proxy);
+	proxy->client_fd = i_stream_get_fd(client->input);
+	proxy->client_output = client->output;
+
+	o_stream_set_max_buffer_size(client->output, (size_t)-1);
+	o_stream_set_flush_callback(client->output, proxy_client_output, proxy);
+	client->output = NULL;
 
 	/* send all pending client input to proxy and get rid of the stream */
-	data = i_stream_get_data(client_input, &size);
+	data = i_stream_get_data(client->input, &size);
 	if (size != 0)
 		(void)o_stream_send(proxy->server_output, data, size);
-	i_stream_unref(&client_input);
 
 	/* from now on, just do dummy proxying */
 	io_remove(&proxy->server_io);
@@ -381,6 +381,9 @@ void login_proxy_detach(struct login_pro
 	proxy->context = NULL;
 
 	DLLIST_PREPEND(&login_proxies, proxy);
+
+	client->fd = -1;
+	client->login_proxy = NULL;
 }
 
 static int login_proxy_ssl_handshaked(void *context)
@@ -388,15 +391,15 @@ static int login_proxy_ssl_handshaked(vo
 	struct login_proxy *proxy = context;
 
 	if ((proxy->ssl_flags & PROXY_SSL_FLAG_ANY_CERT) != 0 ||
-	    ssl_proxy_has_valid_client_cert(proxy->ssl_proxy))
+	    ssl_proxy_has_valid_client_cert(proxy->ssl_server_proxy))
 		return 0;
 
-	if (!ssl_proxy_has_broken_client_cert(proxy->ssl_proxy)) {
-		client_log_err(proxy->prelogin_client, t_strdup_printf(
+	if (!ssl_proxy_has_broken_client_cert(proxy->ssl_server_proxy)) {
+		client_log_err(proxy->client, t_strdup_printf(
 			"proxy: SSL certificate not received from %s:%u",
 			proxy->host, proxy->port));
 	} else {
-		client_log_err(proxy->prelogin_client, t_strdup_printf(
+		client_log_err(proxy->client, t_strdup_printf(
 			"proxy: Received invalid SSL certificate from %s:%u",
 			proxy->host, proxy->port));
 	}
@@ -414,16 +417,17 @@ int login_proxy_starttls(struct login_pr
 		o_stream_destroy(&proxy->server_output);
 	io_remove(&proxy->server_io);
 
-	fd = ssl_proxy_client_new(proxy->server_fd, &proxy->ip,
-				  proxy->prelogin_client->set,
+	fd = ssl_proxy_client_new(proxy->server_fd, &proxy->client->ip,
+				  proxy->client->set,
 				  login_proxy_ssl_handshaked, proxy,
-				  &proxy->ssl_proxy);
+				  &proxy->ssl_server_proxy);
 	if (fd < 0) {
-		client_log_err(proxy->prelogin_client, t_strdup_printf(
+		client_log_err(proxy->client, t_strdup_printf(
 			"proxy: SSL handshake failed to %s:%u",
 			proxy->host, proxy->port));
 		return -1;
 	}
+	ssl_proxy_set_client(proxy->ssl_server_proxy, proxy->client);
 
 	proxy->server_fd = fd;
 	proxy_plain_connected(proxy);
diff -r 4dd2430a7c62 -r d60fa42fbaac src/login-common/login-proxy.h
--- a/src/login-common/login-proxy.h	Fri Sep 11 12:47:23 2009 -0400
+++ b/src/login-common/login-proxy.h	Fri Sep 11 13:43:37 2009 -0400
@@ -47,8 +47,7 @@ bool login_proxy_is_ourself(const struct
 
 /* Detach proxy from client. This is done after the authentication is
    successful and all that is left is the dummy proxying. */


More information about the dovecot-cvs mailing list