Mercurial > dovecot > core-2.2
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);