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) {
}
}
- 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);
}
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);
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),
.imapc_user = "",
.imapc_master_user = "",
.imapc_password = "",
+ .imapc_sasl_mechanisms = "",
.imapc_ssl = "no:imaps:starttls",
.imapc_ssl_verify = TRUE,
#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"
void mail_storage_init(void)
{
+ dsasl_clients_init();
mailbox_lists_init();
mail_storage_hooks_init();
i_array_init(&mail_storage_classes, 8);
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)