]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
login proxy: Added client_proxy passdb extra field to specify proxy's connect timeout.
authorTimo Sirainen <tss@iki.fi>
Wed, 12 Aug 2009 22:02:20 +0000 (18:02 -0400)
committerTimo Sirainen <tss@iki.fi>
Wed, 12 Aug 2009 22:02:20 +0000 (18:02 -0400)
--HG--
branch : HEAD

src/login-common/client-common-auth.c
src/login-common/client-common.h
src/login-common/login-proxy.c
src/login-common/login-proxy.h

index 965ef8827c3d8b29012954279bd50b8bf6891638..acfe6028a2be477eb8db9add20f5cb18a6764f02 100644 (file)
@@ -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);
index 58803f3742fef43cd9b8ec918c4d6c37ba6fe4bd..ccece2a4c65ba77af09f278832f6e499bd9b7b01 100644 (file)
@@ -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;
index 37ecada92acdaaedd9712ad5c607534ac9c974e7..6b224c1d2e10788f4ba051bf8bd758b22b35a898 100644 (file)
@@ -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)
index 87a6702e68dfa0439247fe932dd56007999be057..7d09fff8cdb1fcf7088fe4dffca0dee93d7a1ea2 100644 (file)
@@ -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);