changeset 9929:d60fa42fbaac HEAD

*-login: Fixes to SSL/login proxy connection counting.
author Timo Sirainen <tss@iki.fi>
date Fri, 11 Sep 2009 13:43:37 -0400
parents 4dd2430a7c62
children 307a5f65f74d
files src/imap-login/client.c src/login-common/client-common-auth.c src/login-common/client-common.c src/login-common/client-common.h src/login-common/login-proxy.c src/login-common/login-proxy.h src/login-common/main.c src/login-common/ssl-proxy-openssl.c src/login-common/ssl-proxy.c src/login-common/ssl-proxy.h src/pop3-login/client.c
diffstat 11 files changed, 72 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- 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 @@
 		o_stream_uncork(imap_client->common.output);
 	}
 
-	client_unref(client);
+	client_unref(&client);
 }
 
 static struct client *imap_client_alloc(pool_t pool)
--- 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 @@
 	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 @@
 		return;
 	}
 
-	client_unref(client);
+	client_unref(&client);
 }
 
 int client_auth_begin(struct client *client, const char *mech_name,
--- 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 @@
 	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 @@
 	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 @@
 	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 @@
 			       "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);
--- 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 @@
 	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(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);
 
--- 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 *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 @@
 	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 @@
 	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 **_proxy)
 {
 	struct login_proxy *proxy = *_proxy;
+	struct client *client = proxy->client;
 	const char *ipstr;
 
 	*_proxy = NULL;
@@ -276,7 +276,7 @@
 		/* 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 @@
 		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 @@
 	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;
+	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);
+	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 @@
 	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 @@
 	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 @@
 		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);
--- 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 @@
 
 /* Detach proxy from client. This is done after the authentication is
    successful and all that is left is the dummy proxying. */
-void login_proxy_detach(struct login_proxy *proxy, struct istream *client_input,
-			struct ostream *client_output);
+void login_proxy_detach(struct login_proxy *proxy);
 
 /* STARTTLS command was issued. */
 int login_proxy_starttls(struct login_proxy *proxy);
--- a/src/login-common/main.c	Fri Sep 11 12:47:23 2009 -0400
+++ b/src/login-common/main.c	Fri Sep 11 13:43:37 2009 -0400
@@ -58,8 +58,8 @@
 
 		client = client_create(fd_ssl, TRUE, pool, set,
 				       &local_ip, &conn->remote_ip);
-		client->proxying = TRUE;
 		client->ssl_proxy = proxy;
+		ssl_proxy_set_client(proxy, client);
 	}
 
 	client->remote_port = conn->remote_port;
--- a/src/login-common/ssl-proxy-openssl.c	Fri Sep 11 12:47:23 2009 -0400
+++ b/src/login-common/ssl-proxy-openssl.c	Fri Sep 11 13:43:37 2009 -0400
@@ -10,6 +10,7 @@
 #include "llist.h"
 #include "master-service.h"
 #include "master-interface.h"
+#include "client-common.h"
 #include "ssl-proxy.h"
 
 #include <fcntl.h>
@@ -42,6 +43,7 @@
 	struct ssl_proxy *prev, *next;
 
 	SSL *ssl;
+	struct client *client;
 	struct ip_addr ip;
 	const struct login_settings *set;
 
@@ -62,7 +64,7 @@
 	unsigned int destroyed:1;
 	unsigned int cert_received:1;
 	unsigned int cert_broken:1;
-	unsigned int client:1;
+	unsigned int client_proxy:1;
 };
 
 struct ssl_parameters {
@@ -413,7 +415,7 @@
 {
 	int ret;
 
-	if (proxy->client) {
+	if (proxy->client_proxy) {
 		ret = SSL_connect(proxy->ssl);
 		if (ret != 1) {
 			ssl_handle_error(proxy, ret, "SSL_connect()");
@@ -596,11 +598,19 @@
 
 	(*proxy_r)->handshake_callback = callback;
 	(*proxy_r)->handshake_context = context;
-	(*proxy_r)->client = TRUE;
+	(*proxy_r)->client_proxy = TRUE;
 	ssl_step(*proxy_r);
 	return ret;
 }
 
+void ssl_proxy_set_client(struct ssl_proxy *proxy, struct client *client)
+{
+	i_assert(proxy->client == NULL);
+
+	client_ref(client);
+	proxy->client = client;
+}
+
 bool ssl_proxy_has_valid_client_cert(const struct ssl_proxy *proxy)
 {
 	return proxy->cert_received && !proxy->cert_broken;
@@ -685,6 +695,9 @@
 	i_assert(proxy->refcount == 0);
 
 	SSL_free(proxy->ssl);
+
+	if (proxy->client != NULL)
+		client_unref(&proxy->client);
 	i_free(proxy);
 }
 
@@ -712,8 +725,6 @@
 	(void)net_disconnect(proxy->fd_plain);
 
 	ssl_proxy_unref(proxy);
-
-        master_service_client_connection_destroyed(master_service);
 }
 
 static RSA *ssl_gen_rsa_key(SSL *ssl ATTR_UNUSED,
--- a/src/login-common/ssl-proxy.c	Fri Sep 11 12:47:23 2009 -0400
+++ b/src/login-common/ssl-proxy.c	Fri Sep 11 13:43:37 2009 -0400
@@ -27,6 +27,11 @@
 	return -1;
 }
 
+void ssl_proxy_set_client(struct ssl_proxy *proxy ATTR_UNUSED,
+			  struct client *client ATTR_UNUSED)
+{
+}
+
 bool ssl_proxy_has_valid_client_cert(const struct ssl_proxy *proxy ATTR_UNUSED)
 {
 	return FALSE;
--- a/src/login-common/ssl-proxy.h	Fri Sep 11 12:47:23 2009 -0400
+++ b/src/login-common/ssl-proxy.h	Fri Sep 11 13:43:37 2009 -0400
@@ -1,11 +1,10 @@
 #ifndef SSL_PROXY_H
 #define SSL_PROXY_H
 
-#include "ioloop.h"
-
 struct ip_addr;
 struct ssl_proxy;
 struct login_settings;
+struct client;
 
 extern bool ssl_initialized;
 
@@ -20,6 +19,7 @@
 			 const struct login_settings *set,
 			 ssl_handshake_callback_t *callback, void *context,
 			 struct ssl_proxy **proxy_r);
+void ssl_proxy_set_client(struct ssl_proxy *proxy, struct client *client);
 bool ssl_proxy_has_valid_client_cert(const struct ssl_proxy *proxy) ATTR_PURE;
 bool ssl_proxy_has_broken_client_cert(struct ssl_proxy *proxy);
 const char *ssl_proxy_get_peer_name(struct ssl_proxy *proxy);
--- a/src/pop3-login/client.c	Fri Sep 11 12:47:23 2009 -0400
+++ b/src/pop3-login/client.c	Fri Sep 11 13:43:37 2009 -0400
@@ -93,7 +93,7 @@
 		}
 	}
 
-	if (client_unref(client))
+	if (client_unref(&client))
 		o_stream_uncork(client->output);
 }