]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
login proxy: If passdb returns proxy_refresh=<secs>, send username to proxy-notify...
authorTimo Sirainen <tss@iki.fi>
Wed, 19 May 2010 10:20:36 +0000 (12:20 +0200)
committerTimo Sirainen <tss@iki.fi>
Wed, 19 May 2010 10:20:36 +0000 (12:20 +0200)
--HG--
branch : HEAD

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

index 450eb5bfa319a86aa511e25c65a4ed7d642fc54f..0ee06a8536d10432b82d835df2c4043a97f990b0 100644 (file)
@@ -87,6 +87,8 @@ static void client_auth_parse_args(struct client *client,
                        reply_r->password = value;
                else if (strcmp(key, "proxy_timeout") == 0)
                        reply_r->proxy_timeout_msecs = 1000*atoi(value);
+               else if (strcmp(key, "proxy_refresh") == 0)
+                       reply_r->proxy_refresh_secs = atoi(value);
                else if (strcmp(key, "master") == 0)
                        reply_r->master_user = value;
                else if (strcmp(key, "ssl") == 0) {
@@ -261,6 +263,7 @@ static int proxy_start(struct client *client,
        proxy_set.port = reply->port;
        proxy_set.dns_client_socket_path = LOGIN_DNS_CLIENT_SOCKET_PATH;
        proxy_set.connect_timeout_msecs = reply->proxy_timeout_msecs;
+       proxy_set.notify_refresh_secs = reply->proxy_refresh_secs;
        proxy_set.ssl_flags = reply->ssl_flags;
 
        if (login_proxy_new(client, &proxy_set, proxy_input) < 0) {
index 82f7c3ecdbb17c93d281ad6b2aa741e859fbf811..1cdb63ef3c1a2a950fa647fb5207e52a33bba65c 100644 (file)
@@ -144,9 +144,6 @@ void client_destroy(struct client *client, const char *reason)
                i_free_and_null(client->proxy_password);
        }
 
-       i_free_and_null(client->proxy_user);
-       i_free_and_null(client->proxy_master_user);
-
        if (client->login_proxy != NULL)
                login_proxy_free(&client->login_proxy);
        if (client->ssl_proxy != NULL)
@@ -201,6 +198,8 @@ bool client_unref(struct client **_client)
        if (client->output != NULL)
                o_stream_unref(&client->output);
 
+       i_free(client->proxy_user);
+       i_free(client->proxy_master_user);
        i_free(client->virtual_user);
        i_free(client->auth_mech_name);
        pool_unref(&client->pool);
index d58b9acd5d553b4ccdab76829d7066f3e252a281..6d12cae746f2a68e164e32d62feef1a008452562 100644 (file)
@@ -43,6 +43,7 @@ struct client_auth_reply {
        const char *host, *destuser, *password;
        unsigned int port;
        unsigned int proxy_timeout_msecs;
+       unsigned int proxy_refresh_secs;
        enum login_proxy_ssl_flags ssl_flags;
 
        unsigned int proxy:1;
index 5166ce967d7f633eb00234b1086e980ec6cc725f..3ae4fcbd467880fe250cb086663071c102fb530d 100644 (file)
@@ -3,11 +3,18 @@
 #include "lib.h"
 #include "network.h"
 #include "hash.h"
+#include "strescape.h"
 #include "login-proxy-state.h"
 
+#include <unistd.h>
+#include <fcntl.h>
+
 struct login_proxy_state {
        struct hash_table *hash;
        pool_t pool;
+
+       const char *notify_path;
+       int notify_fd;
 };
 
 static unsigned int login_proxy_record_hash(const void *p)
@@ -27,15 +34,23 @@ static int login_proxy_record_cmp(const void *p1, const void *p2)
        return (int)rec1->port - (int)rec2->port;
 }
 
-struct login_proxy_state *login_proxy_state_init(void)
+struct login_proxy_state *login_proxy_state_init(const char *notify_path)
 {
        struct login_proxy_state *state;
 
        state = i_new(struct login_proxy_state, 1);
        state->pool = pool_alloconly_create("login proxy state", 1024);
+       state->notify_path = p_strdup(state->pool, notify_path);
        state->hash = hash_table_create(default_pool, state->pool, 0,
                                        login_proxy_record_hash,
                                        login_proxy_record_cmp);
+       if (state->notify_path == NULL)
+               state->notify_fd = -1;
+       else {
+               state->notify_fd = open(state->notify_path, O_WRONLY);
+               if (state->notify_fd == -1)
+                       i_error("open(%s) failed: %m", state->notify_path);
+       }
        return state;
 }
 
@@ -44,6 +59,11 @@ void login_proxy_state_deinit(struct login_proxy_state **_state)
        struct login_proxy_state *state = *_state;
 
        *_state = NULL;
+
+       if (state->notify_fd != -1) {
+               if (close(state->notify_fd) < 0)
+                       i_error("close(%s) failed: %m", state->notify_path);
+       }
        hash_table_destroy(&state->hash);
        pool_unref(&state->pool);
        i_free(state);
@@ -68,3 +88,30 @@ login_proxy_state_get(struct login_proxy_state *state,
        }
        return rec;
 }
+
+void login_proxy_state_notify(struct login_proxy_state *state,
+                             const char *user)
+{
+       unsigned int len;
+       ssize_t ret;
+
+       if (state->notify_fd == -1)
+               return;
+
+       T_BEGIN {
+               const char *cmd;
+
+               cmd = t_strconcat(str_tabescape(user), "\n", NULL);
+               len = strlen(cmd);
+               ret = write(state->notify_fd, cmd, len);
+       } T_END;
+
+       if (ret != len) {
+               if (ret < 0)
+                       i_error("write(%s) failed: %m", state->notify_path);
+               else {
+                       i_error("write(%s) wrote partial update",
+                               state->notify_path);
+               }
+       }
+}
index 26c50421e5ef8747a5049a82beeaa5d2c221a4ad..65e8fbbc71ca2ad699a9633ed54f7871f3a6e470 100644 (file)
@@ -12,11 +12,14 @@ struct login_proxy_record {
        struct timeval last_success;
 };
 
-struct login_proxy_state *login_proxy_state_init(void);
+struct login_proxy_state *login_proxy_state_init(const char *notify_path);
 void login_proxy_state_deinit(struct login_proxy_state **state);
 
 struct login_proxy_record *
 login_proxy_state_get(struct login_proxy_state *state,
                      const struct ip_addr *ip, unsigned int port);
 
+void login_proxy_state_notify(struct login_proxy_state *state,
+                             const char *user);
+
 #endif
index 85bfdb615a803bc6481290d40b9bf660c71b4c77..7fdf5db8e278ec9d32061aa944371772f3e51a51 100644 (file)
@@ -31,13 +31,14 @@ struct login_proxy {
        time_t last_io;
 
        struct timeval created;
-       struct timeout *to;
+       struct timeout *to, *to_notify;
        struct login_proxy_record *state_rec;
 
        struct ip_addr ip;
        char *host;
        unsigned int port;
        unsigned int connect_timeout_msecs;
+       unsigned int notify_refresh_secs;
        enum login_proxy_ssl_flags ssl_flags;
 
        proxy_callback_t *callback;
@@ -266,6 +267,7 @@ int login_proxy_new(struct client *client,
        proxy->host = i_strdup(set->host);
        proxy->port = set->port;
        proxy->connect_timeout_msecs = set->connect_timeout_msecs;
+       proxy->notify_refresh_secs = set->notify_refresh_secs;
        proxy->ssl_flags = set->ssl_flags;
        client_ref(client);
 
@@ -301,6 +303,8 @@ void login_proxy_free(struct login_proxy **_proxy)
 
        if (proxy->to != NULL)
                timeout_remove(&proxy->to);
+       if (proxy->to_notify != NULL)
+               timeout_remove(&proxy->to_notify);
 
        if (proxy->state_rec != NULL)
                proxy->state_rec->num_waiting_connections--;
@@ -390,6 +394,11 @@ login_proxy_get_ssl_flags(const struct login_proxy *proxy)
        return proxy->ssl_flags;
 }
 
+static void login_proxy_notify(struct login_proxy *proxy)
+{
+       login_proxy_state_notify(proxy_state, proxy->client->proxy_user);
+}
+
 void login_proxy_detach(struct login_proxy *proxy)
 {
        struct client *client = proxy->client;
@@ -420,6 +429,12 @@ void login_proxy_detach(struct login_proxy *proxy)
        o_stream_set_flush_callback(proxy->server_output, server_output, proxy);
        i_stream_destroy(&proxy->server_input);
 
+       if (proxy->notify_refresh_secs != 0) {
+               proxy->to_notify =
+                       timeout_add(proxy->notify_refresh_secs * 1000,
+                                   login_proxy_notify, proxy);
+       }
+
        proxy->callback = NULL;
 
        DLLIST_PREPEND(&login_proxies, proxy);
@@ -503,9 +518,9 @@ void login_proxy_kill_idle(void)
        }
 }
 
-void login_proxy_init(void)
+void login_proxy_init(const char *proxy_notify_pipe_path)
 {
-       proxy_state = login_proxy_state_init();
+       proxy_state = login_proxy_state_init(proxy_notify_pipe_path);
 }
 
 void login_proxy_deinit(void)
index b389644a2ad30f1a9c0084ac0222bd516b3b8e7d..c90658181ca7c7f41e89b796d614e824bdf849b1 100644 (file)
@@ -18,6 +18,9 @@ struct login_proxy_settings {
        const char *dns_client_socket_path;
        unsigned int port;
        unsigned int connect_timeout_msecs;
+       /* send a notification about proxy connection to proxy-notify pipe
+          every n seconds */
+       unsigned int notify_refresh_secs;
        enum login_proxy_ssl_flags ssl_flags;
 };
 
@@ -54,7 +57,7 @@ login_proxy_get_ssl_flags(const struct login_proxy *proxy) ATTR_PURE;
 
 void login_proxy_kill_idle(void);
 
-void login_proxy_init(void);
+void login_proxy_init(const char *proxy_notify_pipe_path);
 void login_proxy_deinit(void);
 
 #endif
index 9d0046d883f3189fd16651fa814e741169925d79..9b2783e8b169d42d2ec2b93d93682684a31dc99a 100644 (file)
@@ -304,7 +304,7 @@ static void main_init(const char *login_socket)
        master_auth = master_auth_init(master_service, login_binary.protocol);
 
        clients_init();
-       login_proxy_init();
+       login_proxy_init("proxy-notify");
 }
 
 static void main_deinit(void)