dovecot-2.2: imap/pop3-login: Use libsasl for authenticating to ...
dovecot at dovecot.org
dovecot at dovecot.org
Sun Jun 9 06:03:51 EEST 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/266101990d63
changeset: 16487:266101990d63
user: Timo Sirainen <tss at iki.fi>
date: Sun Jun 09 06:03:34 2013 +0300
description:
imap/pop3-login: Use libsasl for authenticating to remote IMAP/POP3 server.
Also passdb lookup can return "proxy_mech" extra field to specify which SASL
mechanism to use.
diffstat:
src/imap-login/Makefile.am | 1 +
src/imap-login/client.h | 1 -
src/imap-login/imap-proxy.c | 101 +++++++++++++++++-------
src/login-common/Makefile.am | 1 +
src/login-common/client-common-auth.c | 23 +++++
src/login-common/client-common.c | 3 +
src/login-common/client-common.h | 4 +-
src/login-common/main.c | 3 +
src/pop3-login/Makefile.am | 1 +
src/pop3-login/pop3-proxy.c | 137 ++++++++++++++++++++++++---------
10 files changed, 205 insertions(+), 70 deletions(-)
diffs (truncated from 560 to 300 lines):
diff -r 1cbff0a8a849 -r 266101990d63 src/imap-login/Makefile.am
--- a/src/imap-login/Makefile.am Sun Jun 09 06:02:14 2013 +0300
+++ b/src/imap-login/Makefile.am Sun Jun 09 06:03:34 2013 +0300
@@ -6,6 +6,7 @@
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib-settings \
-I$(top_srcdir)/src/lib-auth \
+ -I$(top_srcdir)/src/lib-sasl \
-I$(top_srcdir)/src/lib-imap \
-I$(top_srcdir)/src/lib-master \
-I$(top_srcdir)/src/login-common
diff -r 1cbff0a8a849 -r 266101990d63 src/imap-login/client.h
--- a/src/imap-login/client.h Sun Jun 09 06:02:14 2013 +0300
+++ b/src/imap-login/client.h Sun Jun 09 06:03:34 2013 +0300
@@ -19,7 +19,6 @@
unsigned int cmd_finished:1;
unsigned int proxy_sasl_ir:1;
unsigned int proxy_seen_banner:1;
- unsigned int proxy_wait_auth_continue:1;
unsigned int skip_line:1;
unsigned int id_logged:1;
unsigned int client_ignores_capability_resp_code:1;
diff -r 1cbff0a8a849 -r 266101990d63 src/imap-login/imap-proxy.c
--- a/src/imap-login/imap-proxy.c Sun Jun 09 06:02:14 2013 +0300
+++ b/src/imap-login/imap-proxy.c Sun Jun 09 06:03:34 2013 +0300
@@ -9,6 +9,7 @@
#include "str.h"
#include "str-sanitize.h"
#include "safe-memset.h"
+#include "sasl-client.h"
#include "client.h"
#include "client-authenticate.h"
#include "imap-resp-code.h"
@@ -55,42 +56,55 @@
i_free_and_null(client->proxy_password);
}
-static void get_plain_auth(struct client *client, string_t *dest)
+static int proxy_write_login(struct imap_client *client, string_t *str)
{
- string_t *str;
+ struct sasl_client_settings sasl_set;
+ const unsigned char *output;
+ unsigned int len;
+ const char *mech_name, *error;
- str = t_str_new(128);
- str_append(str, client->proxy_user);
- str_append_c(str, '\0');
- str_append(str, client->proxy_master_user);
- str_append_c(str, '\0');
- str_append(str, client->proxy_password);
- base64_encode(str_data(str), str_len(str), dest);
-}
-
-static void proxy_write_login(struct imap_client *client, string_t *str)
-{
str_append(str, "C CAPABILITY\r\n");
- if (client->common.proxy_master_user == NULL) {
+ if (client->common.proxy_mech == NULL) {
/* logging in normally - use LOGIN command */
str_append(str, "L LOGIN ");
imap_append_string(str, client->common.proxy_user);
str_append_c(str, ' ');
imap_append_string(str, client->common.proxy_password);
+ str_append(str, "\r\n");
proxy_free_password(&client->common);
- } else if (client->proxy_sasl_ir) {
- /* master user login with SASL initial response support */
- str_append(str, "L AUTHENTICATE PLAIN ");
- get_plain_auth(&client->common, str);
- proxy_free_password(&client->common);
- } else {
- /* master user login without SASL initial response */
- str_append(str, "L AUTHENTICATE PLAIN");
- client->proxy_wait_auth_continue = TRUE;
+ return 0;
+ }
+
+ i_assert(client->common.proxy_sasl_client == NULL);
+ memset(&sasl_set, 0, sizeof(sasl_set));
+ sasl_set.authid = client->common.proxy_user;
+ sasl_set.authzid = client->common.proxy_master_user;
+ sasl_set.password = client->common.proxy_password;
+ client->common.proxy_sasl_client =
+ sasl_client_new(client->common.proxy_mech, &sasl_set);
+ mech_name = sasl_client_mech_get_name(client->common.proxy_mech);
+
+ str_append(str, "L AUTHENTICATE ");
+ str_append(str, mech_name);
+ if (client->proxy_sasl_ir) {
+ if (sasl_client_output(client->common.proxy_sasl_client,
+ &output, &len, &error) < 0) {
+ client_log_err(&client->common, t_strdup_printf(
+ "proxy: SASL mechanism %s init failed: %s",
+ mech_name, error));
+ return -1;
+ }
+ str_append_c(str, ' ');
+ if (len == 0)
+ str_append_c(str, '=');
+ else
+ base64_encode(output, len, str);
}
str_append(str, "\r\n");
+ proxy_free_password(&client->common);
+ return 0;
}
static int proxy_input_banner(struct imap_client *client,
@@ -126,7 +140,8 @@
}
str_append(str, "S STARTTLS\r\n");
} else {
- proxy_write_login(client, str);
+ if (proxy_write_login(client, str) < 0)
+ return -1;
}
o_stream_nsend(output, str_data(str), str_len(str));
@@ -173,6 +188,10 @@
struct imap_client *imap_client = (struct imap_client *)client;
struct ostream *output;
string_t *str;
+ const unsigned char *data;
+ unsigned int data_len;
+ const char *error;
+ int ret;
i_assert(!client->destroyed);
@@ -188,17 +207,37 @@
return 0;
} else if (*line == '+') {
/* AUTHENTICATE started. finish it. */
- if (!imap_client->proxy_wait_auth_continue) {
+ if (client->proxy_sasl_client == NULL) {
/* used literals with LOGIN command, just ignore. */
return 0;
}
client->proxy_state = IMAP_PROXY_STATE_AUTH_CONTINUE;
- imap_client->proxy_wait_auth_continue = FALSE;
str = t_str_new(128);
- get_plain_auth(client, str);
+ if (line[1] != ' ' ||
+ base64_decode(line+2, strlen(line+2), NULL, str) < 0) {
+ client_log_err(client,
+ "proxy: Server sent invalid base64 data in AUTHENTICATE response");
+ client_proxy_failed(client, TRUE);
+ return -1;
+ }
+ ret = sasl_client_input(client->proxy_sasl_client,
+ str_data(str), str_len(str), &error);
+ if (ret == 0) {
+ ret = sasl_client_output(client->proxy_sasl_client,
+ &data, &data_len, &error);
+ }
+ if (ret < 0) {
+ client_log_err(client, t_strdup_printf(
+ "proxy: Server sent invalid authentication data: %s",
+ error));
+ client_proxy_failed(client, TRUE);
+ return -1;
+ }
+
+ str_truncate(str, 0);
+ base64_encode(data, data_len, str);
str_append(str, "\r\n");
- proxy_free_password(client);
o_stream_nsend(output, str_data(str), str_len(str));
return 0;
@@ -220,7 +259,10 @@
/* i/ostreams changed. */
output = login_proxy_get_ostream(client->login_proxy);
str = t_str_new(128);
- proxy_write_login(imap_client, str);
+ if (proxy_write_login(imap_client, str) < 0) {
+ client_proxy_failed(client, TRUE);
+ return -1;
+ }
o_stream_nsend(output, str_data(str), str_len(str));
return 1;
} else if (strncmp(line, "L OK ", 5) == 0) {
@@ -305,7 +347,6 @@
imap_client->proxy_sasl_ir = FALSE;
imap_client->proxy_seen_banner = FALSE;
- imap_client->proxy_wait_auth_continue = FALSE;
client->proxy_state = IMAP_PROXY_STATE_NONE;
}
diff -r 1cbff0a8a849 -r 266101990d63 src/login-common/Makefile.am
--- a/src/login-common/Makefile.am Sun Jun 09 06:02:14 2013 +0300
+++ b/src/login-common/Makefile.am Sun Jun 09 06:03:34 2013 +0300
@@ -4,6 +4,7 @@
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib-settings \
-I$(top_srcdir)/src/lib-auth \
+ -I$(top_srcdir)/src/lib-sasl \
-I$(top_srcdir)/src/lib-master \
-I$(top_srcdir)/src/lib-ssl-iostream \
-I$(top_srcdir)/src/lib-mail \
diff -r 1cbff0a8a849 -r 266101990d63 src/login-common/client-common-auth.c
--- a/src/login-common/client-common-auth.c Sun Jun 09 06:02:14 2013 +0300
+++ b/src/login-common/client-common-auth.c Sun Jun 09 06:03:34 2013 +0300
@@ -9,6 +9,7 @@
#include "time-util.h"
#include "login-proxy.h"
#include "auth-client.h"
+#include "sasl-client.h"
#include "master-service-ssl-settings.h"
#include "client-common.h"
@@ -104,6 +105,8 @@
reply_r->proxy_timeout_msecs = 1000*atoi(value);
else if (strcmp(key, "proxy_refresh") == 0)
reply_r->proxy_refresh_secs = atoi(value);
+ else if (strcmp(key, "proxy_mech") == 0)
+ reply_r->proxy_mech = value;
else if (strcmp(key, "master") == 0)
reply_r->master_user = value;
else if (strcmp(key, "ssl") == 0) {
@@ -198,6 +201,8 @@
client_proxy_error(client, PROXY_FAILURE_MSG);
}
+ if (client->proxy_sasl_client != NULL)
+ sasl_client_free(&client->proxy_sasl_client);
login_proxy_free(&client->login_proxy);
proxy_free_password(client);
i_free_and_null(client->proxy_user);
@@ -270,10 +275,13 @@
const struct client_auth_reply *reply)
{
struct login_proxy_settings proxy_set;
+ const struct sasl_client_mech *sasl_mech = NULL;
i_assert(reply->destuser != NULL);
i_assert(!client->destroyed);
+ i_assert(client->proxy_sasl_client == NULL);
+ client->proxy_mech = NULL;
client->v.proxy_reset(client);
if (reply->password == NULL) {
@@ -287,6 +295,20 @@
return -1;
}
+ if (reply->proxy_mech != NULL) {
+ sasl_mech = sasl_client_mech_find(reply->proxy_mech);
+ if (sasl_mech == NULL) {
+ client_log_err(client, t_strdup_printf(
+ "proxy: Unsupported SASL mechanism %s",
+ reply->proxy_mech));
+ client_proxy_error(client, PROXY_FAILURE_MSG);
+ return -1;
+ }
+ } else if (reply->master_user != NULL) {
+ /* have to use PLAIN authentication with master user logins */
+ sasl_mech = &sasl_client_mech_plain;
+ }
+
i_assert(client->refcount > 1);
if (client->destroyed) {
@@ -318,6 +340,7 @@
return -1;
}
+ client->proxy_mech = sasl_mech;
client->proxy_user = i_strdup(reply->destuser);
client->proxy_master_user = i_strdup(reply->master_user);
client->proxy_password = i_strdup(reply->password);
diff -r 1cbff0a8a849 -r 266101990d63 src/login-common/client-common.c
--- a/src/login-common/client-common.c Sun Jun 09 06:02:14 2013 +0300
+++ b/src/login-common/client-common.c Sun Jun 09 06:03:34 2013 +0300
@@ -18,6 +18,7 @@
#include "master-service-ssl-settings.h"
#include "master-auth.h"
#include "auth-client.h"
+#include "sasl-client.h"
#include "login-proxy.h"
#include "ssl-proxy.h"
#include "client-common.h"
@@ -209,6 +210,8 @@
i_free_and_null(client->proxy_password);
}
+ if (client->proxy_sasl_client != NULL)
+ sasl_client_free(&client->proxy_sasl_client);
if (client->login_proxy != NULL)
login_proxy_free(&client->login_proxy);
if (client->v.destroy != NULL)
diff -r 1cbff0a8a849 -r 266101990d63 src/login-common/client-common.h
--- a/src/login-common/client-common.h Sun Jun 09 06:02:14 2013 +0300
More information about the dovecot-cvs
mailing list