From: Timo Sirainen Date: Thu, 8 Jan 2015 20:52:11 +0000 (+0200) Subject: imapc: Added imapc_sasl_mechanisms setting X-Git-Tag: 2.2.16.rc1~164 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c6033074ada5c7441ff7bb12c4b433cae737fea2;p=thirdparty%2Fdovecot%2Fcore.git imapc: Added imapc_sasl_mechanisms setting The first supported SASL mechanism is used, otherwise the login fails entirely. --- diff --git a/src/lib-imap-client/imapc-client.c b/src/lib-imap-client/imapc-client.c index 50354964fd..6de4de0e57 100644 --- a/src/lib-imap-client/imapc-client.c +++ b/src/lib-imap-client/imapc-client.c @@ -54,6 +54,7 @@ imapc_client_init(const struct imapc_client_settings *set) client->set.master_user = p_strdup_empty(pool, set->master_user); client->set.username = p_strdup(pool, set->username); client->set.password = p_strdup(pool, set->password); + client->set.sasl_mechanisms = p_strdup(pool, set->sasl_mechanisms); client->set.dns_client_socket_path = p_strdup(pool, set->dns_client_socket_path); client->set.temp_path_prefix = diff --git a/src/lib-imap-client/imapc-client.h b/src/lib-imap-client/imapc-client.h index 191db2ea62..b6765f33ac 100644 --- a/src/lib-imap-client/imapc-client.h +++ b/src/lib-imap-client/imapc-client.h @@ -60,6 +60,9 @@ struct imapc_client_settings { const char *master_user; const char *username; const char *password; + /* Space-separated list of SASL mechanisms to try (in the specified + order). The default is to use only LOGIN command or SASL PLAIN. */ + const char *sasl_mechanisms; unsigned int max_idle_time; const char *dns_client_socket_path; diff --git a/src/lib-imap-client/imapc-connection.c b/src/lib-imap-client/imapc-connection.c index cf766b8661..e90124909b 100644 --- a/src/lib-imap-client/imapc-connection.c +++ b/src/lib-imap-client/imapc-connection.c @@ -760,12 +760,52 @@ imapc_connection_authenticate_cb(const struct imapc_command_reply *reply, imapc_connection_disconnect(conn); } +static bool imapc_connection_have_auth(struct imapc_connection *conn, + const char *mech_name) +{ + char *const *capa; + + for (capa = conn->capabilities_list; *capa != NULL; capa++) { + if (strncasecmp(*capa, "AUTH=", 5) == 0 && + strcasecmp((*capa)+5, mech_name) == 0) + return TRUE; + } + return FALSE; +} + +static int +imapc_connection_get_sasl_mech(struct imapc_connection *conn, + const struct dsasl_client_mech **mech_r, + const char **error_r) +{ + const struct imapc_client_settings *set = &conn->client->set; + const char *const *mechanisms = + t_strsplit_spaces(set->sasl_mechanisms, ", "); + + /* find one of the specified SASL mechanisms */ + for (; *mechanisms != NULL; mechanisms++) { + if (imapc_connection_have_auth(conn, *mechanisms)) { + *mech_r = dsasl_client_mech_find(*mechanisms); + if (*mech_r != NULL) + return 0; + + *error_r = t_strdup_printf( + "Support for SASL method '%s' is missing", *mechanisms); + return -1; + } + } + *error_r = t_strdup_printf("IMAP server doesn't support any of the requested SASL mechanisms: %s", + set->sasl_mechanisms); + return -1; +} + static void imapc_connection_authenticate(struct imapc_connection *conn) { const struct imapc_client_settings *set = &conn->client->set; struct imapc_command *cmd; struct dsasl_client_settings sasl_set; - const struct dsasl_client_mech *sasl_mech; + const struct dsasl_client_mech *sasl_mech = NULL; + const char *error; if (conn->client->set.debug) { if (set->master_user == NULL) { @@ -777,9 +817,19 @@ static void imapc_connection_authenticate(struct imapc_connection *conn) } } - if ((set->master_user == NULL && - !need_literal(set->username) && !need_literal(set->password)) || - (conn->capabilities & IMAPC_CAPABILITY_AUTH_PLAIN) == 0) { + if (set->sasl_mechanisms != NULL && set->sasl_mechanisms[0] != '\0') { + if (imapc_connection_get_sasl_mech(conn, &sasl_mech, &error) < 0) { + i_error("imapc(%s): Authentication failed: %s", + conn->name, error); + imapc_connection_disconnect(conn); + return; + } + } + + if (sasl_mech == NULL && + ((set->master_user == NULL && + !need_literal(set->username) && !need_literal(set->password)) || + (conn->capabilities & IMAPC_CAPABILITY_AUTH_PLAIN) == 0)) { /* We can use LOGIN command */ cmd = imapc_connection_cmd(conn, imapc_connection_login_cb, conn); @@ -798,7 +848,8 @@ static void imapc_connection_authenticate(struct imapc_connection *conn) } sasl_set.password = set->password; - sasl_mech = &dsasl_client_mech_plain; + if (sasl_mech == NULL) + sasl_mech = &dsasl_client_mech_plain; conn->sasl_client = dsasl_client_new(sasl_mech, &sasl_set); cmd = imapc_connection_cmd(conn, imapc_connection_authenticate_cb, conn); diff --git a/src/lib-storage/Makefile.am b/src/lib-storage/Makefile.am index b6273460ae..41509a3432 100644 --- a/src/lib-storage/Makefile.am +++ b/src/lib-storage/Makefile.am @@ -7,6 +7,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib-test \ -I$(top_srcdir)/src/lib-auth \ -I$(top_srcdir)/src/lib-dict \ + -I$(top_srcdir)/src/lib-sasl \ -I$(top_srcdir)/src/lib-ssl-iostream \ -I$(top_srcdir)/src/lib-fs \ -I$(top_srcdir)/src/lib-master \ diff --git a/src/lib-storage/index/imapc/imapc-settings.c b/src/lib-storage/index/imapc/imapc-settings.c index ede10d1b7a..f9cf437a57 100644 --- a/src/lib-storage/index/imapc/imapc-settings.c +++ b/src/lib-storage/index/imapc/imapc-settings.c @@ -20,6 +20,7 @@ static const struct setting_define imapc_setting_defines[] = { DEF(SET_STR_VARS, imapc_user), DEF(SET_STR_VARS, imapc_master_user), DEF(SET_STR, imapc_password), + DEF(SET_STR, imapc_sasl_mechanisms), DEF(SET_ENUM, imapc_ssl), DEF(SET_BOOL, imapc_ssl_verify), @@ -39,6 +40,7 @@ static const struct imapc_settings imapc_default_settings = { .imapc_user = "", .imapc_master_user = "", .imapc_password = "", + .imapc_sasl_mechanisms = "", .imapc_ssl = "no:imaps:starttls", .imapc_ssl_verify = TRUE, diff --git a/src/lib-storage/index/imapc/imapc-settings.h b/src/lib-storage/index/imapc/imapc-settings.h index 05f2b7476f..624715f3fc 100644 --- a/src/lib-storage/index/imapc/imapc-settings.h +++ b/src/lib-storage/index/imapc/imapc-settings.h @@ -16,6 +16,7 @@ struct imapc_settings { const char *imapc_user; const char *imapc_master_user; const char *imapc_password; + const char *imapc_sasl_mechanisms; const char *imapc_ssl; bool imapc_ssl_verify; diff --git a/src/lib-storage/index/imapc/imapc-storage.c b/src/lib-storage/index/imapc/imapc-storage.c index 08c61e8569..a632a5eb59 100644 --- a/src/lib-storage/index/imapc/imapc-storage.c +++ b/src/lib-storage/index/imapc/imapc-storage.c @@ -221,6 +221,7 @@ int imapc_storage_client_create(struct mail_namespace *ns, *error_r = "missing imapc_password"; return -1; } + set.sasl_mechanisms = imapc_set->imapc_sasl_mechanisms; set.max_idle_time = imapc_set->imapc_max_idle_time; set.dns_client_socket_path = *ns->user->set->base_dir == '\0' ? "" : t_strconcat(ns->user->set->base_dir, "/", diff --git a/src/lib-storage/mail-storage.c b/src/lib-storage/mail-storage.c index 6023fec7da..6c640e0bd4 100644 --- a/src/lib-storage/mail-storage.c +++ b/src/lib-storage/mail-storage.c @@ -11,6 +11,7 @@ #include "mkdir-parents.h" #include "time-util.h" #include "var-expand.h" +#include "dsasl-client.h" #include "mail-index-private.h" #include "mail-index-alloc-cache.h" #include "mailbox-tree.h" @@ -40,6 +41,7 @@ ARRAY_TYPE(mail_storage) mail_storage_classes; void mail_storage_init(void) { + dsasl_clients_init(); mailbox_lists_init(); mail_storage_hooks_init(); i_array_init(&mail_storage_classes, 8); @@ -55,6 +57,7 @@ void mail_storage_deinit(void) array_free(&mail_storage_classes); mail_storage_hooks_deinit(); mailbox_lists_deinit(); + dsasl_clients_deinit(); } void mail_storage_class_register(struct mail_storage *storage_class)