Mercurial > dovecot > core-2.2
changeset 10266:e99c02873d8c HEAD
*-login: Use new anvil library to do async anvil lookups.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 06 Nov 2009 13:57:43 -0500 |
parents | 8ebf82849077 |
children | 2e00f9da27ad |
files | src/login-common/common.h src/login-common/main.c src/login-common/sasl-server.c |
diffstat | 3 files changed, 58 insertions(+), 59 deletions(-) [+] |
line wrap: on
line diff
--- a/src/login-common/common.h Fri Nov 06 13:57:04 2009 -0500 +++ b/src/login-common/common.h Fri Nov 06 13:57:43 2009 -0500 @@ -18,7 +18,7 @@ extern struct auth_client *auth_client; extern struct master_auth *master_auth; extern bool closing_down; -extern int anvil_fd; +extern struct anvil_client *anvil; extern const struct login_settings *global_login_settings; extern void **global_other_settings;
--- a/src/login-common/main.c Fri Nov 06 13:57:04 2009 -0500 +++ b/src/login-common/main.c Fri Nov 06 13:57:43 2009 -0500 @@ -10,6 +10,7 @@ #include "master-service.h" #include "master-interface.h" #include "client-common.h" +#include "anvil-client.h" #include "auth-client.h" #include "ssl-proxy.h" #include "login-proxy.h" @@ -21,7 +22,7 @@ struct auth_client *auth_client; struct master_auth *master_auth; bool closing_down; -int anvil_fd = -1; +struct anvil_client *anvil; const struct login_settings *global_login_settings; void **global_other_settings; @@ -104,19 +105,10 @@ clients_notify_auth_connected(); } -static int anvil_connect(void) +static bool anvil_reconnect_callback(void) { -#define ANVIL_HANDSHAKE "VERSION\tanvil\t1\t0\n" - int fd; - - fd = net_connect_unix_with_retries("anvil", 5000); - if (fd == -1) - i_fatal("net_connect_unix(anvil) failed: %m"); - net_set_nonblock(fd, FALSE); - - if (write(fd, ANVIL_HANDSHAKE, strlen(ANVIL_HANDSHAKE)) < 0) - i_fatal("write(anvil) failed: %m"); - return fd; + master_service_stop_new_connections(master_service); + return FALSE; } static void main_preinit(bool allow_core_dumps) @@ -147,8 +139,11 @@ i_assert(strcmp(global_login_settings->ssl, "no") == 0 || ssl_initialized); - if (global_login_settings->mail_max_userip_connections > 0) - anvil_fd = anvil_connect(); + if (global_login_settings->mail_max_userip_connections > 0) { + anvil = anvil_client_init("anvil", anvil_reconnect_callback); + if (anvil_client_connect(anvil, TRUE) < 0) + i_fatal("Couldn't connect to anvil"); + } restrict_access_by_env(NULL, TRUE); if (allow_core_dumps) @@ -187,10 +182,8 @@ clients_deinit(); master_auth_deinit(&master_auth); - if (anvil_fd != -1) { - if (close(anvil_fd) < 0) - i_error("close(anvil) failed: %m"); - } + if (anvil != NULL) + anvil_client_deinit(&anvil); } int main(int argc, char *argv[])
--- a/src/login-common/sasl-server.c Fri Nov 06 13:57:04 2009 -0500 +++ b/src/login-common/sasl-server.c Fri Nov 06 13:57:43 2009 -0500 @@ -8,6 +8,7 @@ #include "write-full.h" #include "strescape.h" #include "str-sanitize.h" +#include "anvil-client.h" #include "auth-client.h" #include "ssl-proxy.h" #include "master-service.h" @@ -22,6 +23,11 @@ "Maximum number of connections from user+IP exceeded " \ "(mail_max_userip_connections)" +struct anvil_request { + struct client *client; + unsigned int auth_pid, auth_id; +}; + const struct auth_mech_desc * sasl_server_get_advertised_mechs(struct client *client, unsigned int *count_r) { @@ -98,9 +104,9 @@ call_client_callback(client, sasl_reply, data, NULL); } -static void -master_send_request(struct client *client, struct auth_client_request *request) +static void master_send_request(struct anvil_request *anvil_request) { + struct client *client = anvil_request->client; struct master_auth_request req; const unsigned char *data; const char *cookie; @@ -110,8 +116,8 @@ buf = buffer_create_dynamic(pool_datastack_create(), 256); memset(&req, 0, sizeof(req)); - req.auth_pid = auth_client_request_get_server_pid(request); - req.auth_id = auth_client_request_get_id(request); + req.auth_pid = anvil_request->auth_pid; + req.auth_id = anvil_request->auth_id; req.local_ip = client->local_ip; req.remote_ip = client->ip; req.client_pid = getpid(); @@ -132,39 +138,44 @@ master_auth_callback, client, &client->master_tag); } -static bool anvil_has_too_many_connections(struct client *client) +static void anvil_lookup_callback(const char *reply, void *context) { - const char *ident; - char buf[64]; - ssize_t ret; + struct anvil_request *req = context; + struct client *client = req->client; + + if (reply == NULL || + strtoul(reply, NULL, 10) < client->set->mail_max_userip_connections) + master_send_request(req); + else { + client->authenticating = FALSE; + call_client_callback(client, SASL_SERVER_REPLY_MASTER_FAILED, + ERR_TOO_MANY_USERIP_CONNECTIONS, NULL); + } + i_free(req); +} - if (client->virtual_user == NULL) - return FALSE; - if (client->set->mail_max_userip_connections == 0) - return FALSE; +static void +anvil_check_too_many_connections(struct client *client, + struct auth_client_request *request) +{ + struct anvil_request *req; + const char *query; - ident = t_strconcat("LOOKUP\t", login_protocol, "/", + req = i_new(struct anvil_request, 1); + req->client = client; + req->auth_pid = auth_client_request_get_server_pid(request); + req->auth_id = auth_client_request_get_id(request); + + if (client->virtual_user == NULL || + client->set->mail_max_userip_connections == 0) { + anvil_lookup_callback(NULL, req); + return; + } + + query = t_strconcat("LOOKUP\t", login_protocol, "/", net_ip2addr(&client->ip), "/", - str_tabescape(client->virtual_user), "\n", NULL); - if (write_full(anvil_fd, ident, strlen(ident)) < 0) { - if (errno == EPIPE) { - /* anvil process was probably recreated, don't bother - logging an error about losing connection to it */ - return FALSE; - } - i_fatal("write(anvil) failed: %m"); - } - ret = read(anvil_fd, buf, sizeof(buf)-1); - if (ret < 0) - i_fatal("read(anvil) failed: %m"); - else if (ret == 0) - i_fatal("read(anvil) failed: EOF"); - if (buf[ret-1] != '\n') - i_fatal("anvil lookup failed: Invalid input in reply"); - buf[ret-1] = '\0'; - - return strtoul(buf, NULL, 10) >= - client->set->mail_max_userip_connections; + str_tabescape(client->virtual_user), NULL); + anvil_client_query(anvil, query, anvil_lookup_callback, req); } static void @@ -209,13 +220,8 @@ client->authenticating = FALSE; call_client_callback(client, SASL_SERVER_REPLY_SUCCESS, NULL, args); - } else if (anvil_has_too_many_connections(client)) { - client->authenticating = FALSE; - call_client_callback(client, - SASL_SERVER_REPLY_MASTER_FAILED, - ERR_TOO_MANY_USERIP_CONNECTIONS, NULL); } else { - master_send_request(client, request); + anvil_check_too_many_connections(client, request); } break; case AUTH_REQUEST_STATUS_FAIL: