From: Timo Sirainen Date: Wed, 12 Aug 2009 22:02:20 +0000 (-0400) Subject: login proxy: Added client_proxy passdb extra field to specify proxy's connect timeout. X-Git-Tag: 2.0.alpha1~279 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2598b2f36365b52d9754b9348a5be29569293e46;p=thirdparty%2Fdovecot%2Fcore.git login proxy: Added client_proxy passdb extra field to specify proxy's connect timeout. --HG-- branch : HEAD --- diff --git a/src/login-common/client-common-auth.c b/src/login-common/client-common-auth.c index 965ef8827c..acfe6028a2 100644 --- a/src/login-common/client-common-auth.c +++ b/src/login-common/client-common-auth.c @@ -112,6 +112,8 @@ static void client_auth_parse_args(struct client *client, reply_r->destuser = value; else if (strcmp(key, "pass") == 0) reply_r->password = value; + else if (strcmp(key, "proxy_timeout") == 0) + reply_r->proxy_timeout_msecs = 1000*atoi(value); else if (strcmp(key, "master") == 0) reply_r->master_user = value; else if (strcmp(key, "ssl") == 0) { @@ -248,6 +250,8 @@ static void proxy_input(struct client *client) static int proxy_start(struct client *client, const struct client_auth_reply *reply) { + struct login_proxy_settings proxy_set; + i_assert(reply->destuser != NULL); i_assert(!client->destroyed); @@ -275,9 +279,14 @@ static int proxy_start(struct client *client, return -1; } + memset(&proxy_set, 0, sizeof(proxy_set)); + proxy_set.host = reply->host; + proxy_set.port = reply->port; + proxy_set.connect_timeout_msecs = reply->proxy_timeout_msecs; + proxy_set.ssl_flags = reply->ssl_flags; + client->login_proxy = - login_proxy_new(client, reply->host, reply->port, - reply->ssl_flags, proxy_input, client); + login_proxy_new(client, &proxy_set, proxy_input, client); if (client->login_proxy == NULL) { client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP, AUTH_TEMP_FAILED_MSG); diff --git a/src/login-common/client-common.h b/src/login-common/client-common.h index 58803f3742..ccece2a4c6 100644 --- a/src/login-common/client-common.h +++ b/src/login-common/client-common.h @@ -42,6 +42,7 @@ struct client_auth_reply { /* for proxying */ const char *host, *destuser, *password; unsigned int port; + unsigned int proxy_timeout_msecs; enum login_proxy_ssl_flags ssl_flags; unsigned int proxy:1; diff --git a/src/login-common/login-proxy.c b/src/login-common/login-proxy.c index 37ecada92a..6b224c1d2e 100644 --- a/src/login-common/login-proxy.c +++ b/src/login-common/login-proxy.c @@ -25,6 +25,8 @@ struct login_proxy { struct ip_addr ip; struct ssl_proxy *ssl_proxy; + struct timeout *to; + char *host, *user; unsigned int port; enum login_proxy_ssl_flags ssl_flags; @@ -139,6 +141,9 @@ static void proxy_wait_connect(struct login_proxy *proxy) return; } + if (proxy->to != NULL) + timeout_remove(&proxy->to); + if ((proxy->ssl_flags & PROXY_SSL_FLAG_YES) != 0 && (proxy->ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0) { if (login_proxy_starttls(proxy) < 0) { @@ -151,43 +156,52 @@ static void proxy_wait_connect(struct login_proxy *proxy) } } +static void proxy_connect_timeout(struct login_proxy *proxy) +{ + i_error("proxy: connect(%s, %u) timed out", proxy->host, proxy->port); + login_proxy_free(&proxy); +} + #undef login_proxy_new struct login_proxy * -login_proxy_new(struct client *client, const char *host, unsigned int port, - enum login_proxy_ssl_flags ssl_flags, +login_proxy_new(struct client *client, const struct login_proxy_settings *set, proxy_callback_t *callback, void *context) { struct login_proxy *proxy; struct ip_addr ip; int fd; - if (host == NULL) { + if (set->host == NULL) { i_error("proxy(%s): host not given", client->virtual_user); return NULL; } - if (net_addr2ip(host, &ip) < 0) { + if (net_addr2ip(set->host, &ip) < 0) { i_error("proxy(%s): %s is not a valid IP", - client->virtual_user, host); + client->virtual_user, set->host); return NULL; } - fd = net_connect_ip(&ip, port, NULL); + fd = net_connect_ip(&ip, set->port, NULL); if (fd < 0) { i_error("proxy(%s): connect(%s, %u) failed: %m", - client->virtual_user, host, port); + client->virtual_user, set->host, set->port); return NULL; } proxy = i_new(struct login_proxy, 1); - proxy->host = i_strdup(host); + proxy->host = i_strdup(set->host); proxy->user = i_strdup(client->virtual_user); - proxy->port = port; - proxy->ssl_flags = ssl_flags; + proxy->port = set->port; + proxy->ssl_flags = set->ssl_flags; proxy->prelogin_client = client; proxy->server_fd = fd; proxy->server_io = io_add(fd, IO_WRITE, proxy_wait_connect, proxy); + if (set->connect_timeout_msecs != 0) { + proxy->to = timeout_add(set->connect_timeout_msecs, + proxy_connect_timeout, proxy); + } proxy->callback = callback; proxy->context = context; @@ -208,6 +222,9 @@ void login_proxy_free(struct login_proxy **_proxy) return; proxy->destroying = TRUE; + if (proxy->to != NULL) + timeout_remove(&proxy->to); + if (proxy->server_io != NULL) io_remove(&proxy->server_io); if (proxy->server_input != NULL) diff --git a/src/login-common/login-proxy.h b/src/login-common/login-proxy.h index 87a6702e68..7d09fff8cd 100644 --- a/src/login-common/login-proxy.h +++ b/src/login-common/login-proxy.h @@ -13,24 +13,29 @@ enum login_proxy_ssl_flags { PROXY_SSL_FLAG_ANY_CERT = 0x04 }; +struct login_proxy_settings { + const char *host; + unsigned int port; + unsigned int connect_timeout_msecs; + enum login_proxy_ssl_flags ssl_flags; +}; + /* Called when new input comes from proxy. */ typedef void proxy_callback_t(void *context); /* Create a proxy to given host. Returns NULL if failed. Given callback is called when new input is available from proxy. */ struct login_proxy * -login_proxy_new(struct client *client, const char *host, unsigned int port, - enum login_proxy_ssl_flags ssl_flags, +login_proxy_new(struct client *client, const struct login_proxy_settings *set, proxy_callback_t *callback, void *context); #ifdef CONTEXT_TYPE_SAFETY -# define login_proxy_new(client, host, port, ssl_flags, callback, context) \ +# define login_proxy_new(client, set, callback, context) \ ({(void)(1 ? 0 : callback(context)); \ - login_proxy_new(client, host, port, ssl_flags, \ + login_proxy_new(client, set, \ (proxy_callback_t *)callback, context); }) #else -# define login_proxy_new(client, host, port, ssl_flags, callback, context) \ - login_proxy_new(client, host, port, ssl_flags, \ - (proxy_callback_t *)callback, context) +# define login_proxy_new(client, set, callback, context) \ + login_proxy_new(client, set, (proxy_callback_t *)callback, context) #endif /* Free the proxy. This should be called if authentication fails. */ void login_proxy_free(struct login_proxy **proxy);