]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imapc: Added imapc_sasl_mechanisms setting
authorTimo Sirainen <tss@iki.fi>
Thu, 8 Jan 2015 20:52:11 +0000 (22:52 +0200)
committerTimo Sirainen <tss@iki.fi>
Thu, 8 Jan 2015 20:52:11 +0000 (22:52 +0200)
The first supported SASL mechanism is used, otherwise the login fails
entirely.

src/lib-imap-client/imapc-client.c
src/lib-imap-client/imapc-client.h
src/lib-imap-client/imapc-connection.c
src/lib-storage/Makefile.am
src/lib-storage/index/imapc/imapc-settings.c
src/lib-storage/index/imapc/imapc-settings.h
src/lib-storage/index/imapc/imapc-storage.c
src/lib-storage/mail-storage.c

index 50354964fd206c0b162148840fb0a1daa5c727fa..6de4de0e57356b6cb56fb3e1788bceaab08a276a 100644 (file)
@@ -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 =
index 191db2ea623e3de0383a7063d33725239238589c..b6765f33ac9d024ecc793db058c4626ab9ef0e75 100644 (file)
@@ -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;
index cf766b86616369a4cf4c8c8bfb30a78419a46ab0..e90124909b1dd8d228b45765e25c318ebe664d9c 100644 (file)
@@ -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);
index b6273460aecf03e8ec4bedf7c40a12d2c88d88e0..41509a34325b9f8bbab45469803d30f38e422b50 100644 (file)
@@ -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 \
index ede10d1b7af727cefb705e60b704539145cd476d..f9cf437a5775d861e1857d587b239ca4588e1752 100644 (file)
@@ -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,
index 05f2b7476fb608f8e16451fc69e2aae3502b7883..624715f3fc5f74b37452ab43c8a80b8ebcbc18b5 100644 (file)
@@ -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;
index 08c61e8569a8fb7ad48112610e6806f0f103484f..a632a5eb59da49706b42eeac4dae2ac6474dcaed 100644 (file)
@@ -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, "/",
index 6023fec7da3efbee65e95e97c9b70ccca54afbd9..6c640e0bd4fc75d3cbd03016bc3794a1464bff23 100644 (file)
@@ -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)