From: Timo Sirainen Date: Thu, 14 May 2009 23:01:28 +0000 (-0400) Subject: login processes: Added initial support for per-connection configuration. X-Git-Tag: 2.0.alpha1~769 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=97db4761382024093f441e4bc78ba8b6a056504d;p=thirdparty%2Fdovecot%2Fcore.git login processes: Added initial support for per-connection configuration. --HG-- branch : HEAD --- diff --git a/src/imap-login/client-authenticate.c b/src/imap-login/client-authenticate.c index 9df8b001b1..5d7d44797d 100644 --- a/src/imap-login/client-authenticate.c +++ b/src/imap-login/client-authenticate.c @@ -22,7 +22,7 @@ #define IMAP_SERVICE_NAME "imap" -const char *client_authenticate_get_capabilities(bool secured) +const char *client_authenticate_get_capabilities(struct imap_client *client) { const struct auth_mech_desc *mech; unsigned int i, count; @@ -36,7 +36,8 @@ const char *client_authenticate_get_capabilities(bool secured) c) we allow insecure authentication */ if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 && - (secured || !login_settings->disable_plaintext_auth || + (client->common.secured || + !client->common.set->disable_plaintext_auth || (mech[i].flags & MECH_SEC_PLAINTEXT) == 0)) { str_append_c(str, ' '); str_append(str, "AUTH="); @@ -165,7 +166,7 @@ static bool client_handle_args(struct imap_client *client, master_user = value; else if (strcmp(key, "user") == 0) { /* already handled in login-common */ - } else if (login_settings->auth_debug) + } else if (client->common.set->auth_debug) i_info("Ignoring unknown passdb extra field: %s", key); } @@ -353,8 +354,8 @@ int cmd_authenticate(struct imap_client *client, const struct imap_arg *args) } if (!client->common.secured && - strcmp(login_settings->ssl, "required") == 0) { - if (login_settings->verbose_auth) { + strcmp(client->common.set->ssl, "required") == 0) { + if (client->common.set->verbose_auth) { client_syslog(&client->common, "Login failed: " "SSL required for authentication"); } @@ -387,8 +388,9 @@ int cmd_login(struct imap_client *client, const struct imap_arg *args) user = IMAP_ARG_STR(&args[0]); pass = IMAP_ARG_STR(&args[1]); - if (!client->common.secured && login_settings->disable_plaintext_auth) { - if (login_settings->verbose_auth) { + if (!client->common.secured && + client->common.set->disable_plaintext_auth) { + if (client->common.set->verbose_auth) { client_syslog(&client->common, "Login failed: " "Plaintext authentication disabled"); } diff --git a/src/imap-login/client-authenticate.h b/src/imap-login/client-authenticate.h index 9932aefa92..b5e2d393d2 100644 --- a/src/imap-login/client-authenticate.h +++ b/src/imap-login/client-authenticate.h @@ -8,7 +8,7 @@ struct imap_arg; #define IMAP_AUTHZ_FAILED_MSG \ "["IMAP_RESP_CODE_AUTHZFAILED"] Authorization failed" -const char *client_authenticate_get_capabilities(bool secured); +const char *client_authenticate_get_capabilities(struct imap_client *client); int cmd_login(struct imap_client *client, const struct imap_arg *args); int cmd_authenticate(struct imap_client *client, const struct imap_arg *args); diff --git a/src/imap-login/client.c b/src/imap-login/client.c index c38a8ce562..79c7e780ee 100644 --- a/src/imap-login/client.c +++ b/src/imap-login/client.c @@ -56,8 +56,8 @@ static void client_set_title(struct imap_client *client) { const char *addr; - if (!login_settings->verbose_proctitle || - !login_settings->login_process_per_connection) + if (!client->common.set->verbose_proctitle || + !client->common.set->login_process_per_connection) return; addr = net_ip2addr(&client->common.ip); @@ -100,12 +100,12 @@ static const char *get_capability(struct imap_client *client, bool full) { const char *auths; - auths = client_authenticate_get_capabilities(client->common.secured); - return t_strconcat(full ? login_settings->capability_string : + auths = client_authenticate_get_capabilities(client); + return t_strconcat(full ? client->common.set->capability_string : CAPABILITY_BANNER_STRING, (ssl_initialized && !client->common.tls) ? " STARTTLS" : "", - login_settings->disable_plaintext_auth && + client->common.set->disable_plaintext_auth && !client->common.secured ? " LOGINDISABLED" : "", auths, NULL); } @@ -128,7 +128,7 @@ static void client_start_tls(struct imap_client *client) return; fd_ssl = ssl_proxy_new(client->common.fd, &client->common.ip, - &client->common.proxy); + client->common.set, &client->common.proxy); if (fd_ssl == -1) { client_send_line(client, "* BYE TLS initialization failed."); client_destroy(client, @@ -431,7 +431,8 @@ void client_input(struct imap_client *client) void client_destroy_oldest(void) { - unsigned int max_connections = login_settings->login_max_connections; + unsigned int max_connections = + global_login_settings->login_max_connections; struct client *client; struct imap_client *destroy_buf[CLIENT_DESTROY_OLDEST_COUNT]; unsigned int i, destroy_count; @@ -474,7 +475,7 @@ static void client_send_greeting(struct imap_client *client) greet = t_str_new(128); str_append(greet, "* OK "); str_printfa(greet, "[CAPABILITY %s] ", get_capability(client, FALSE)); - str_append(greet, login_settings->login_greeting); + str_append(greet, client->common.set->login_greeting); client_send_line(client, str_c(greet)); client->greeting_sent = TRUE; @@ -501,14 +502,16 @@ void client_set_auth_waiting(struct imap_client *client) client_auth_waiting_timeout, client); } -struct client *client_create(int fd, bool ssl, const struct ip_addr *local_ip, - const struct ip_addr *ip) +struct client *client_create(int fd, bool ssl, pool_t pool, + const struct login_settings *set, + const struct ip_addr *local_ip, + const struct ip_addr *remote_ip) { struct imap_client *client; i_assert(fd != -1); - if (clients_get_count() >= login_settings->login_max_connections) { + if (clients_get_count() >= set->login_max_connections) { /* reached max. users count, kill few of the oldest connections */ client_destroy_oldest(); @@ -517,17 +520,19 @@ struct client *client_create(int fd, bool ssl, const struct ip_addr *local_ip, /* always use nonblocking I/O */ net_set_nonblock(fd, TRUE); - client = i_new(struct imap_client, 1); + client = p_new(pool, struct imap_client, 1); client->created = ioloop_time; client->refcount = 1; + client->common.pool = pool; + client->common.set = set; client->common.local_ip = *local_ip; - client->common.ip = *ip; + client->common.ip = *remote_ip; client->common.fd = fd; client->common.tls = ssl; client->common.trusted = client_is_trusted(&client->common); client->common.secured = ssl || client->common.trusted || - net_ip_compare(ip, local_ip); + net_ip_compare(remote_ip, local_ip); client_open_streams(client, fd); client->io = io_add(fd, IO_READ, client_input, client); diff --git a/src/imap-login/imap-proxy.c b/src/imap-login/imap-proxy.c index fcd7737bcc..a0c5d9dbde 100644 --- a/src/imap-login/imap-proxy.c +++ b/src/imap-login/imap-proxy.c @@ -128,7 +128,7 @@ client_send_capability_if_needed(struct imap_client *client, string_t *str, backend_capabilities = capabilities_strip_prelogin(t_strsplit(capability, " ")); proxy_capabilities = - capabilities_strip_prelogin(t_strsplit(login_settings->capability_string, " ")); + capabilities_strip_prelogin(t_strsplit(client->common.set->capability_string, " ")); if (str_array_icmp(backend_capabilities, proxy_capabilities)) return; @@ -290,7 +290,7 @@ static int proxy_input_line(struct imap_client *client, const char *line) return 1; } else if (strncmp(line, "L ", 2) == 0) { line += 2; - if (login_settings->verbose_auth) { + if (client->common.set->verbose_auth) { str = t_str_new(128); str_printfa(str, "proxy(%s): Login failed to %s:%u", client->common.virtual_user, diff --git a/src/login-common/client-common.c b/src/login-common/client-common.c index 32adfbe738..80836475d6 100644 --- a/src/login-common/client-common.c +++ b/src/login-common/client-common.c @@ -90,7 +90,6 @@ get_var_expand_table(struct client *client) tab[12].value = ssl_proxy_get_security_string(client->proxy); } tab[13].value = dec2str(client->mail_pid); - return tab; } @@ -119,7 +118,8 @@ client_get_log_str(struct client *client, const char *msg) }; const struct var_expand_table *var_expand_table; struct var_expand_table *tab; - const char *p, *const *e; + const char *p; + char *const *e; string_t *str; var_expand_table = get_var_expand_table(client); @@ -128,7 +128,7 @@ client_get_log_str(struct client *client, const char *msg) memcpy(tab, static_tab, sizeof(static_tab)); str = t_str_new(256); - for (e = login_settings->log_format_elements_split; *e != NULL; e++) { + for (e = client->set->log_format_elements_split; *e != NULL; e++) { for (p = *e; *p != '\0'; p++) { if (*p != '%' || p[1] == '\0') continue; @@ -147,7 +147,7 @@ client_get_log_str(struct client *client, const char *msg) tab[1].value = msg; str_truncate(str, 0); - var_expand(str, login_settings->login_log_format, tab); + var_expand(str, client->set->login_log_format, tab); return str_c(str); } @@ -171,10 +171,10 @@ bool client_is_trusted(struct client *client) struct ip_addr net_ip; unsigned int bits; - if (login_settings->login_trusted_networks == NULL) + if (client->set->login_trusted_networks == NULL) return FALSE; - net = t_strsplit_spaces(login_settings->login_trusted_networks, ", "); + net = t_strsplit_spaces(client->set->login_trusted_networks, ", "); for (; *net != NULL; net++) { if (net_parse_range(*net, &net_ip, &bits) < 0) { i_error("login_trusted_networks: " @@ -190,7 +190,7 @@ bool client_is_trusted(struct client *client) const char *client_get_extra_disconnect_reason(struct client *client) { - if (login_settings->ssl_require_client_cert && client->proxy != NULL) { + if (client->set->ssl_require_client_cert && client->proxy != NULL) { if (ssl_proxy_has_broken_client_cert(client->proxy)) return "(client sent an invalid cert)"; if (!ssl_proxy_has_valid_client_cert(client->proxy)) @@ -203,7 +203,7 @@ const char *client_get_extra_disconnect_reason(struct client *client) /* some auth attempts without SSL/TLS */ if (client->auth_tried_disabled_plaintext) return "(tried to use disabled plaintext auth)"; - if (login_settings->ssl_require_client_cert) + if (client->set->ssl_require_client_cert) return "(cert required, client didn't start TLS)"; return t_strdup_printf("(auth failed, %u attempts)", diff --git a/src/login-common/client-common.h b/src/login-common/client-common.h index 02337c2926..4216ad89e2 100644 --- a/src/login-common/client-common.h +++ b/src/login-common/client-common.h @@ -14,11 +14,13 @@ struct client { struct client *prev, *next; + pool_t pool; struct ip_addr local_ip; struct ip_addr ip; unsigned int local_port, remote_port; struct ssl_proxy *proxy; + const struct login_settings *set; int fd; struct istream *input; @@ -45,8 +47,10 @@ struct client { extern struct client *clients; -struct client *client_create(int fd, bool ssl, const struct ip_addr *local_ip, - const struct ip_addr *ip); +struct client *client_create(int fd, bool ssl, pool_t pool, + const struct login_settings *set, + const struct ip_addr *local_ip, + const struct ip_addr *remote_ip); void client_link(struct client *client); void client_unlink(struct client *client); diff --git a/src/login-common/common.h b/src/login-common/common.h index 0ae8a36acf..899c1be0c3 100644 --- a/src/login-common/common.h +++ b/src/login-common/common.h @@ -19,6 +19,6 @@ extern bool closing_down; extern int anvil_fd; extern struct master_service *service; -extern struct login_settings *login_settings; +extern const struct login_settings *global_login_settings; #endif diff --git a/src/login-common/login-proxy.c b/src/login-common/login-proxy.c index c8017fa421..e9fe56d4e4 100644 --- a/src/login-common/login-proxy.c +++ b/src/login-common/login-proxy.c @@ -358,6 +358,7 @@ int login_proxy_starttls(struct login_proxy *proxy) io_remove(&proxy->server_io); fd = ssl_proxy_client_new(proxy->server_fd, &proxy->ip, + proxy->prelogin_client->set, login_proxy_ssl_handshaked, proxy, &proxy->ssl_proxy); if (fd < 0) { diff --git a/src/login-common/login-settings.c b/src/login-common/login-settings.c index d5ce7c35a9..4547e56ed6 100644 --- a/src/login-common/login-settings.c +++ b/src/login-common/login-settings.c @@ -51,7 +51,7 @@ static struct setting_define login_setting_defines[] = { static struct login_settings login_default_settings = { MEMBER(login_chroot) TRUE, MEMBER(login_trusted_networks) "", - MEMBER(login_greeting) PACKAGE" ready.", + MEMBER(login_greeting) PACKAGE_NAME" ready.", MEMBER(login_log_format_elements) "user=<%u> method=%m rip=%r lip=%l %c", MEMBER(login_log_format) "%$: %s", @@ -127,13 +127,12 @@ static int ssl_settings_check(void *_set ATTR_UNUSED, const char **error_r) #endif } -static bool login_settings_check(void *_set, pool_t pool ATTR_UNUSED, - const char **error_r) +static bool login_settings_check(void *_set, pool_t pool, const char **error_r) { struct login_settings *set = _set; set->log_format_elements_split = - t_strsplit(set->login_log_format_elements, " "); + p_strsplit(pool, set->login_log_format_elements, " "); if (set->ssl_require_client_cert || set->ssl_username_from_cert) { /* if we require valid cert, make sure we also ask for it */ @@ -162,7 +161,10 @@ static bool login_settings_check(void *_set, pool_t pool ATTR_UNUSED, } /* */ -struct login_settings *login_settings_read(struct master_service *service) +struct login_settings * +login_settings_read(struct master_service *service, pool_t pool, + const struct ip_addr *local_ip, + const struct ip_addr *remote_ip) { static const struct setting_parser_info *set_roots[] = { &login_setting_parser_info, @@ -171,15 +173,27 @@ struct login_settings *login_settings_read(struct master_service *service) struct master_service_settings_input input; const char *error; void **sets; + struct login_settings *set; memset(&input, 0, sizeof(input)); input.roots = set_roots; input.module = "login"; input.service = login_protocol; + if (local_ip != NULL) + input.local_ip = *local_ip; + if (remote_ip != NULL) + input.remote_ip = *remote_ip; + + /* this function always clears the previous settings pool. since we're + doing per-connection lookups, we always need to duplicate the + settings using another pool. */ if (master_service_settings_read(service, &input, &error) < 0) i_fatal("Error reading configuration: %s", error); sets = master_service_settings_get_others(service); - return sets[0]; + set = settings_dup(&login_setting_parser_info, sets[0], pool); + if (!login_settings_check(set, pool, &error)) + i_fatal("login_settings_check() failed: %s", error); + return set; } diff --git a/src/login-common/login-settings.h b/src/login-common/login-settings.h index aa721b2f6d..bb8ca59300 100644 --- a/src/login-common/login-settings.h +++ b/src/login-common/login-settings.h @@ -34,9 +34,12 @@ struct login_settings { unsigned int mail_max_userip_connections; /* generated: */ - const char *const *log_format_elements_split; + char *const *log_format_elements_split; }; -struct login_settings *login_settings_read(struct master_service *service); +struct login_settings * +login_settings_read(struct master_service *service, pool_t pool, + const struct ip_addr *local_ip, + const struct ip_addr *remote_ip); #endif diff --git a/src/login-common/main.c b/src/login-common/main.c index 886fde7064..921a8049d5 100644 --- a/src/login-common/main.c +++ b/src/login-common/main.c @@ -23,7 +23,7 @@ bool closing_down; int anvil_fd = -1; struct master_service *service; -struct login_settings *login_settings; +const struct login_settings *global_login_settings; static bool ssl_connections = FALSE; @@ -32,7 +32,9 @@ static void client_connected(const struct master_service_connection *conn) struct client *client; struct ssl_proxy *proxy; struct ip_addr local_ip; + const struct login_settings *set; unsigned int local_port; + pool_t pool; int fd_ssl; if (net_getsockname(conn->fd, &local_ip, &local_port) < 0) { @@ -40,21 +42,26 @@ static void client_connected(const struct master_service_connection *conn) local_port = 0; } + pool = pool_alloconly_create("login client", 1024); + set = login_settings_read(service, pool, &local_ip, &conn->remote_ip); + if (!ssl_connections && !conn->ssl) { - client = client_create(conn->fd, FALSE, &local_ip, + client = client_create(conn->fd, FALSE, pool, set, &local_ip, &conn->remote_ip); } else { - fd_ssl = ssl_proxy_new(conn->fd, &conn->remote_ip, &proxy); + fd_ssl = ssl_proxy_new(conn->fd, &conn->remote_ip, set, &proxy); if (fd_ssl == -1) { net_disconnect(conn->fd); + pool_unref(&pool); return; } - client = client_create(fd_ssl, TRUE, + client = client_create(fd_ssl, TRUE, pool, set, &local_ip, &conn->remote_ip); client->proxying = TRUE; client->proxy = proxy; } + client->remote_port = conn->remote_port; client->local_port = local_port; } @@ -95,13 +102,14 @@ static void main_preinit(void) normal connections each use one fd, but SSL connections use two */ max_fds = MASTER_LISTEN_FD_FIRST + 16 + master_service_get_socket_count(service) + - login_settings->login_max_connections*2; + global_login_settings->login_max_connections*2; restrict_fd_limit(max_fds); io_loop_set_max_fd_count(current_ioloop, max_fds); - i_assert(strcmp(login_settings->ssl, "no") == 0 || ssl_initialized); + i_assert(strcmp(global_login_settings->ssl, "no") == 0 || + ssl_initialized); - if (login_settings->mail_max_userip_connections > 0) + if (global_login_settings->mail_max_userip_connections > 0) anvil_fd = anvil_connect(); restrict_access_by_env(NULL, TRUE); @@ -143,11 +151,14 @@ static void main_deinit(void) int main(int argc, char *argv[], char *envp[]) { const char *getopt_str; + pool_t set_pool; int c; //FIXME:is_inetd = getenv("DOVECOT_MASTER") == NULL; - service = master_service_init(login_process_name, 0, argc, argv); + service = master_service_init(login_process_name, + MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN, + argc, argv); master_service_init_log(service, t_strconcat(login_process_name, ": ", NULL), 0); @@ -176,7 +187,9 @@ int main(int argc, char *argv[], char *envp[]) #endif process_title_init(argv, envp); - login_settings = login_settings_read(service); + set_pool = pool_alloconly_create("global login settings", 1024); + global_login_settings = + login_settings_read(service, set_pool, NULL, NULL); main_preinit(); master_service_init_finish(service); @@ -184,6 +197,7 @@ int main(int argc, char *argv[], char *envp[]) master_service_run(service, client_connected); main_deinit(); + pool_unref(&set_pool); master_service_deinit(&service); return 0; } diff --git a/src/login-common/sasl-server.c b/src/login-common/sasl-server.c index 70808fe162..95b722bed6 100644 --- a/src/login-common/sasl-server.c +++ b/src/login-common/sasl-server.c @@ -105,7 +105,7 @@ static bool anvil_has_too_many_connections(struct client *client) if (client->virtual_user == NULL) return FALSE; - if (login_settings->mail_max_userip_connections == 0) + if (client->set->mail_max_userip_connections == 0) return FALSE; ident = t_strconcat("LOOKUP\t", net_ip2addr(&client->ip), "/", @@ -123,7 +123,7 @@ static bool anvil_has_too_many_connections(struct client *client) buf[ret-1] = '\0'; return strtoul(buf, NULL, 10) >= - login_settings->mail_max_userip_connections; + client->set->mail_max_userip_connections; } static void authenticate_callback(struct auth_request *request, int status, @@ -219,7 +219,7 @@ void sasl_server_auth_begin(struct client *client, return; } - if (!client->secured && login_settings->disable_plaintext_auth && + if (!client->secured && client->set->disable_plaintext_auth && (mech->flags & MECH_SEC_PLAINTEXT) != 0) { sasl_server_auth_failed(client, "Plaintext authentication disabled."); @@ -252,7 +252,7 @@ static void sasl_server_auth_cancel(struct client *client, const char *reason, { i_assert(client->authenticating); - if (login_settings->verbose_auth && reason != NULL) { + if (client->set->verbose_auth && reason != NULL) { const char *auth_name = str_sanitize(client->auth_mech_name, MAX_MECH_NAME); client_syslog(client, diff --git a/src/login-common/ssl-proxy-openssl.c b/src/login-common/ssl-proxy-openssl.c index d4f7ea3117..ddc6987022 100644 --- a/src/login-common/ssl-proxy-openssl.c +++ b/src/login-common/ssl-proxy-openssl.c @@ -42,6 +42,7 @@ struct ssl_proxy { SSL *ssl; struct ip_addr ip; + const struct login_settings *set; int fd_ssl, fd_plain; struct io *io_ssl_read, *io_ssl_write, *io_plain_read, *io_plain_write; @@ -496,6 +497,7 @@ static void ssl_step(struct ssl_proxy *proxy) static int ssl_proxy_new_common(SSL_CTX *ssl_ctx, int fd, const struct ip_addr *ip, + const struct login_settings *set, struct ssl_proxy **proxy_r) { struct ssl_proxy *proxy; @@ -538,6 +540,7 @@ ssl_proxy_new_common(SSL_CTX *ssl_ctx, int fd, const struct ip_addr *ip, proxy = i_new(struct ssl_proxy, 1); proxy->refcount = 2; proxy->ssl = ssl; + proxy->set = set; proxy->fd_ssl = fd; proxy->fd_plain = sfd[0]; proxy->ip = *ip; @@ -550,11 +553,13 @@ ssl_proxy_new_common(SSL_CTX *ssl_ctx, int fd, const struct ip_addr *ip, return sfd[1]; } -int ssl_proxy_new(int fd, const struct ip_addr *ip, struct ssl_proxy **proxy_r) +int ssl_proxy_new(int fd, const struct ip_addr *ip, + const struct login_settings *set, struct ssl_proxy **proxy_r) { int ret; - if ((ret = ssl_proxy_new_common(ssl_server_ctx, fd, ip, proxy_r)) < 0) + ret = ssl_proxy_new_common(ssl_server_ctx, fd, ip, set, proxy_r); + if (ret < 0) return -1; ssl_step(*proxy_r); @@ -562,12 +567,14 @@ int ssl_proxy_new(int fd, const struct ip_addr *ip, struct ssl_proxy **proxy_r) } int ssl_proxy_client_new(int fd, struct ip_addr *ip, + const struct login_settings *set, ssl_handshake_callback_t *callback, void *context, struct ssl_proxy **proxy_r) { int ret; - if ((ret = ssl_proxy_new_common(ssl_client_ctx, fd, ip, proxy_r)) < 0) + ret = ssl_proxy_new_common(ssl_client_ctx, fd, ip, set, proxy_r); + if (ret < 0) return -1; (*proxy_r)->handshake_callback = callback; @@ -724,8 +731,8 @@ static int ssl_verify_client_cert(int preverify_ok, X509_STORE_CTX *ctx) proxy = SSL_get_ex_data(ssl, extdata_index); proxy->cert_received = TRUE; - if (login_settings->verbose_ssl || - (login_settings->verbose_auth && !preverify_ok)) { + if (proxy->set->verbose_ssl || + (proxy->set->verbose_auth && !preverify_ok)) { char buf[1024]; X509_NAME *subject; @@ -927,7 +934,7 @@ static void ssl_proxy_init_client(const struct login_settings *set) void ssl_proxy_init(void) { - const struct login_settings *set = login_settings; + const struct login_settings *set = global_login_settings; static char dovecot[] = "dovecot"; unsigned char buf; diff --git a/src/login-common/ssl-proxy.h b/src/login-common/ssl-proxy.h index e1b66ccd75..a2ee532473 100644 --- a/src/login-common/ssl-proxy.h +++ b/src/login-common/ssl-proxy.h @@ -5,6 +5,7 @@ struct ip_addr; struct ssl_proxy; +struct login_settings; extern bool ssl_initialized; @@ -13,8 +14,10 @@ typedef int ssl_handshake_callback_t(void *context); /* establish SSL connection with the given fd, returns a new fd which you must use from now on, or -1 if error occurred. Unless -1 is returned, the given fd must be simply forgotten. */ -int ssl_proxy_new(int fd, const struct ip_addr *ip, struct ssl_proxy **proxy_r); +int ssl_proxy_new(int fd, const struct ip_addr *ip, + const struct login_settings *set, struct ssl_proxy **proxy_r); int ssl_proxy_client_new(int fd, struct ip_addr *ip, + const struct login_settings *set, ssl_handshake_callback_t *callback, void *context, struct ssl_proxy **proxy_r); bool ssl_proxy_has_valid_client_cert(const struct ssl_proxy *proxy) ATTR_PURE; diff --git a/src/pop3-login/client-authenticate.c b/src/pop3-login/client-authenticate.c index 13d2e32762..b6a4fe7e5d 100644 --- a/src/pop3-login/client-authenticate.c +++ b/src/pop3-login/client-authenticate.c @@ -36,7 +36,8 @@ bool cmd_capa(struct pop3_client *client, const char *args ATTR_UNUSED) if (ssl_initialized && !client->common.tls) str_append(str, "STLS\r\n"); - if (!login_settings->disable_plaintext_auth || client->common.secured) + if (!client->common.set->disable_plaintext_auth || + client->common.secured) str_append(str, "USER\r\n"); str_append(str, "SASL"); @@ -48,7 +49,7 @@ bool cmd_capa(struct pop3_client *client, const char *args ATTR_UNUSED) */ if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 && (client->common.secured || - !login_settings->disable_plaintext_auth || + !client->common.set->disable_plaintext_auth || (mech[i].flags & MECH_SEC_PLAINTEXT) == 0)) { str_append_c(str, ' '); str_append(str, mech[i].name); @@ -166,7 +167,7 @@ static bool client_handle_args(struct pop3_client *client, master_user = value; else if (strcmp(key, "user") == 0) { /* already handled in login-common */ - } else if (login_settings->auth_debug) + } else if (client->common.set->auth_debug) i_info("Ignoring unknown passdb extra field: %s", key); } @@ -280,8 +281,8 @@ bool cmd_auth(struct pop3_client *client, const char *args) const char *mech_name, *p; if (!client->common.secured && - strcmp(login_settings->ssl, "required") == 0) { - if (login_settings->verbose_auth) { + strcmp(client->common.set->ssl, "required") == 0) { + if (client->common.set->verbose_auth) { client_syslog(&client->common, "Login failed: " "SSL required for authentication"); } @@ -300,7 +301,7 @@ bool cmd_auth(struct pop3_client *client, const char *args) for (i = 0; i < count; i++) { if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 && (client->common.secured || - login_settings->disable_plaintext_auth || + client->common.set->disable_plaintext_auth || (mech[i].flags & MECH_SEC_PLAINTEXT) == 0)) client_send_line(client, mech[i].name); } @@ -333,10 +334,10 @@ bool cmd_auth(struct pop3_client *client, const char *args) static bool check_plaintext_auth(struct pop3_client *client) { if (client->common.secured || - !login_settings->disable_plaintext_auth) + !client->common.set->disable_plaintext_auth) return TRUE; - if (login_settings->verbose_auth) { + if (client->common.set->verbose_auth) { client_syslog(&client->common, "Login failed: " "Plaintext authentication disabled"); } @@ -406,7 +407,7 @@ bool cmd_apop(struct pop3_client *client, const char *args) const char *p; if (client->apop_challenge == NULL) { - if (login_settings->verbose_auth) { + if (client->common.set->verbose_auth) { client_syslog(&client->common, "APOP failed: APOP not enabled"); } @@ -417,7 +418,7 @@ bool cmd_apop(struct pop3_client *client, const char *args) /* */ p = strchr(args, ' '); if (p == NULL || strlen(p+1) != 32) { - if (login_settings->verbose_auth) { + if (client->common.set->verbose_auth) { client_syslog(&client->common, "APOP failed: Invalid parameters"); } @@ -433,7 +434,7 @@ bool cmd_apop(struct pop3_client *client, const char *args) buffer_append_c(apop_data, '\0'); if (hex_to_binary(p+1, apop_data) < 0) { - if (login_settings->verbose_auth) { + if (client->common.set->verbose_auth) { client_syslog(&client->common, "APOP failed: " "Invalid characters in MD5 response"); } diff --git a/src/pop3-login/client.c b/src/pop3-login/client.c index 082af0a3c9..176a07249c 100644 --- a/src/pop3-login/client.c +++ b/src/pop3-login/client.c @@ -42,8 +42,8 @@ static void client_set_title(struct pop3_client *client) { const char *addr; - if (!login_settings->verbose_proctitle || - !login_settings->login_process_per_connection) + if (!client->common.set->verbose_proctitle || + !client->common.set->login_process_per_connection) return; addr = net_ip2addr(&client->common.ip); @@ -70,7 +70,7 @@ static void client_start_tls(struct pop3_client *client) return; fd_ssl = ssl_proxy_new(client->common.fd, &client->common.ip, - &client->common.proxy); + client->common.set, &client->common.proxy); if (fd_ssl == -1) { client_send_line(client, "-ERR TLS initialization failed."); client_destroy(client, @@ -229,7 +229,8 @@ void client_input(struct pop3_client *client) void client_destroy_oldest(void) { - unsigned int max_connections = login_settings->login_max_connections; + unsigned int max_connections = + global_login_settings->login_max_connections; struct client *client; struct pop3_client *destroy_buf[CLIENT_DESTROY_OLDEST_COUNT]; unsigned int i, destroy_count; @@ -292,7 +293,7 @@ static void client_auth_ready(struct pop3_client *client) client->apop_challenge = get_apop_challenge(client); client_send_line(client, t_strconcat("+OK ", - login_settings->login_greeting, + client->common.set->login_greeting, client->apop_challenge != NULL ? " " : NULL, client->apop_challenge, NULL)); @@ -303,14 +304,16 @@ static void client_idle_disconnect_timeout(struct pop3_client *client) client_destroy(client, "Disconnected: Inactivity"); } -struct client *client_create(int fd, bool ssl, const struct ip_addr *local_ip, - const struct ip_addr *ip) +struct client *client_create(int fd, bool ssl, pool_t pool, + const struct login_settings *set, + const struct ip_addr *local_ip, + const struct ip_addr *remote_ip) { struct pop3_client *client; i_assert(fd != -1); - if (clients_get_count() >= login_settings->login_max_connections) { + if (clients_get_count() >= set->login_max_connections) { /* reached max. users count, kill few of the oldest connections */ client_destroy_oldest(); @@ -319,17 +322,19 @@ struct client *client_create(int fd, bool ssl, const struct ip_addr *local_ip, /* always use nonblocking I/O */ net_set_nonblock(fd, TRUE); - client = i_new(struct pop3_client, 1); + client = p_new(pool, struct pop3_client, 1); client->created = ioloop_time; client->refcount = 1; + client->common.pool = pool; + client->common.set = set; client->common.local_ip = *local_ip; - client->common.ip = *ip; + client->common.ip = *remote_ip; client->common.fd = fd; client->common.tls = ssl; client->common.trusted = client_is_trusted(&client->common); client->common.secured = ssl || client->common.trusted || - net_ip_compare(ip, local_ip); + net_ip_compare(remote_ip, local_ip); client_open_streams(client, fd); client_link(&client->common); diff --git a/src/pop3-login/pop3-proxy.c b/src/pop3-login/pop3-proxy.c index 1cd1a5d145..7081ac7d94 100644 --- a/src/pop3-login/pop3-proxy.c +++ b/src/pop3-login/pop3-proxy.c @@ -188,7 +188,7 @@ static int proxy_input_line(struct pop3_client *client, const char *line) else client_send_line(client, line); - if (login_settings->verbose_auth) { + if (client->common.set->verbose_auth) { str = t_str_new(128); str_printfa(str, "proxy(%s): Login failed to %s:%u", client->common.virtual_user,