From: Timo Sirainen Date: Wed, 19 May 2010 10:20:36 +0000 (+0200) Subject: login proxy: If passdb returns proxy_refresh=, send username to proxy-notify... X-Git-Tag: 2.0.beta6~206 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6303191abcb37164f435ccdc56e9dbddf1288851;p=thirdparty%2Fdovecot%2Fcore.git login proxy: If passdb returns proxy_refresh=, send username to proxy-notify fifo every n secs. --HG-- branch : HEAD --- diff --git a/src/login-common/client-common-auth.c b/src/login-common/client-common-auth.c index 450eb5bfa3..0ee06a8536 100644 --- a/src/login-common/client-common-auth.c +++ b/src/login-common/client-common-auth.c @@ -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) { diff --git a/src/login-common/client-common.c b/src/login-common/client-common.c index 82f7c3ecdb..1cdb63ef3c 100644 --- a/src/login-common/client-common.c +++ b/src/login-common/client-common.c @@ -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); diff --git a/src/login-common/client-common.h b/src/login-common/client-common.h index d58b9acd5d..6d12cae746 100644 --- a/src/login-common/client-common.h +++ b/src/login-common/client-common.h @@ -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; diff --git a/src/login-common/login-proxy-state.c b/src/login-common/login-proxy-state.c index 5166ce967d..3ae4fcbd46 100644 --- a/src/login-common/login-proxy-state.c +++ b/src/login-common/login-proxy-state.c @@ -3,11 +3,18 @@ #include "lib.h" #include "network.h" #include "hash.h" +#include "strescape.h" #include "login-proxy-state.h" +#include +#include + 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); + } + } +} diff --git a/src/login-common/login-proxy-state.h b/src/login-common/login-proxy-state.h index 26c50421e5..65e8fbbc71 100644 --- a/src/login-common/login-proxy-state.h +++ b/src/login-common/login-proxy-state.h @@ -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 diff --git a/src/login-common/login-proxy.c b/src/login-common/login-proxy.c index 85bfdb615a..7fdf5db8e2 100644 --- a/src/login-common/login-proxy.c +++ b/src/login-common/login-proxy.c @@ -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) diff --git a/src/login-common/login-proxy.h b/src/login-common/login-proxy.h index b389644a2a..c90658181c 100644 --- a/src/login-common/login-proxy.h +++ b/src/login-common/login-proxy.h @@ -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 diff --git a/src/login-common/main.c b/src/login-common/main.c index 9d0046d883..9b2783e8b1 100644 --- a/src/login-common/main.c +++ b/src/login-common/main.c @@ -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)