dovecot-2.0: doveadm: Added simple PLAIN authentication for remo...
dovecot at dovecot.org
dovecot at dovecot.org
Fri May 20 13:30:49 EEST 2011
details: http://hg.dovecot.org/dovecot-2.0/rev/6604f80abb02
changeset: 12814:6604f80abb02
user: Timo Sirainen <tss at iki.fi>
date: Fri May 20 13:30:40 2011 +0300
description:
doveadm: Added simple PLAIN authentication for remote connections.
Currently clients are required to use "doveadm" as the username and the
password must match doveadm_password setting. When using doveadm as a
client, it automatically uses these settings when connecting to remote
servers.
diffstat:
src/doveadm/client-connection.c | 63 +++++++++++++++++++++++++++++++++++-----
src/doveadm/doveadm-settings.c | 2 +
src/doveadm/doveadm-settings.h | 1 +
src/doveadm/server-connection.c | 47 ++++++++++++++++++++++++++---
4 files changed, 98 insertions(+), 15 deletions(-)
diffs (225 lines):
diff -r 9c9f81ad0111 -r 6604f80abb02 src/doveadm/client-connection.c
--- a/src/doveadm/client-connection.c Fri May 20 13:05:16 2011 +0300
+++ b/src/doveadm/client-connection.c Fri May 20 13:30:40 2011 +0300
@@ -1,6 +1,7 @@
/* Copyright (c) 2010-2011 Dovecot authors, see the included COPYING file */
#include "lib.h"
+#include "base64.h"
#include "ioloop.h"
#include "istream.h"
#include "ostream.h"
@@ -11,6 +12,7 @@
#include "doveadm-server.h"
#include "doveadm-mail.h"
#include "doveadm-print.h"
+#include "doveadm-settings.h"
#include "client-connection.h"
#include <unistd.h>
@@ -147,17 +149,56 @@
return TRUE;
}
-static bool
-client_connection_authenticate(struct client_connection *conn ATTR_UNUSED)
+static int
+client_connection_authenticate(struct client_connection *conn)
{
- i_fatal("Authentication not supported yet");
- return FALSE;
+ const char *line, *pass;
+ buffer_t *plain;
+ const unsigned char *data;
+ size_t size;
+
+ if ((line = i_stream_read_next_line(conn->input)) == NULL)
+ return 0;
+
+ if (*doveadm_settings->doveadm_password == '\0') {
+ i_error("doveadm_password not set, "
+ "remote authentication disabled");
+ return -1;
+ }
+
+ /* FIXME: some day we should probably let auth process do this and
+ support all kinds of authentication */
+ if (strncmp(line, "PLAIN\t", 6) != 0) {
+ i_error("doveadm client attempted non-PLAIN authentication");
+ return -1;
+ }
+
+ plain = buffer_create_dynamic(pool_datastack_create(), 128);
+ if (base64_decode(line + 6, strlen(line + 6), NULL, plain) < 0) {
+ i_error("doveadm client sent invalid base64 auth PLAIN data");
+ return -1;
+ }
+ data = plain->data;
+ size = plain->used;
+
+ if (size < 10 || data[0] != '\0' ||
+ memcmp(data+1, "doveadm", 7) != 0 || data[8] != '\0') {
+ i_error("doveadm client didn't authenticate as 'doveadm'");
+ return -1;
+ }
+ pass = t_strndup(data + 9, size - 9);
+ if (strcmp(pass, doveadm_settings->doveadm_password) != 0) {
+ i_error("doveadm client authenticated with wrong password");
+ return -1;
+ }
+ return 1;
}
static void client_connection_input(struct client_connection *conn)
{
const char *line;
- bool ret = TRUE;
+ bool ok = TRUE;
+ int ret;
if (!conn->handshaked) {
if ((line = i_stream_read_next_line(conn->input)) == NULL) {
@@ -176,19 +217,23 @@
conn->handshaked = TRUE;
}
if (!conn->authenticated) {
- if (!client_connection_authenticate(conn))
+ if ((ret = client_connection_authenticate(conn)) <= 0) {
+ if (ret < 0)
+ client_connection_destroy(&conn);
return;
+ }
+ conn->authenticated = TRUE;
}
- while (ret && (line = i_stream_read_next_line(conn->input)) != NULL) {
+ while (ok && (line = i_stream_read_next_line(conn->input)) != NULL) {
T_BEGIN {
char **args;
args = p_strsplit(pool_datastack_create(), line, "\t");
- ret = client_handle_command(conn, args);
+ ok = client_handle_command(conn, args);
} T_END;
}
- if (conn->input->eof || conn->input->stream_errno != 0 || !ret)
+ if (conn->input->eof || conn->input->stream_errno != 0 || !ok)
client_connection_destroy(&conn);
}
diff -r 9c9f81ad0111 -r 6604f80abb02 src/doveadm/doveadm-settings.c
--- a/src/doveadm/doveadm-settings.c Fri May 20 13:05:16 2011 +0300
+++ b/src/doveadm/doveadm-settings.c Fri May 20 13:30:40 2011 +0300
@@ -58,6 +58,7 @@
DEF(SET_STR, doveadm_socket_path),
DEF(SET_UINT, doveadm_worker_count),
DEF(SET_UINT, doveadm_proxy_port),
+ DEF(SET_STR, doveadm_password),
{ SET_STRLIST, "plugin", offsetof(struct doveadm_settings, plugin_envs), NULL },
@@ -71,6 +72,7 @@
.doveadm_socket_path = "doveadm-server",
.doveadm_worker_count = 0,
.doveadm_proxy_port = 0,
+ .doveadm_password = "",
.plugin_envs = ARRAY_INIT
};
diff -r 9c9f81ad0111 -r 6604f80abb02 src/doveadm/doveadm-settings.h
--- a/src/doveadm/doveadm-settings.h Fri May 20 13:05:16 2011 +0300
+++ b/src/doveadm/doveadm-settings.h Fri May 20 13:30:40 2011 +0300
@@ -8,6 +8,7 @@
const char *doveadm_socket_path;
unsigned int doveadm_worker_count;
unsigned int doveadm_proxy_port;
+ const char *doveadm_password;
ARRAY_DEFINE(plugin_envs, const char *);
};
diff -r 9c9f81ad0111 -r 6604f80abb02 src/doveadm/server-connection.c
--- a/src/doveadm/server-connection.c Fri May 20 13:05:16 2011 +0300
+++ b/src/doveadm/server-connection.c Fri May 20 13:30:40 2011 +0300
@@ -2,6 +2,7 @@
#include "lib.h"
#include "array.h"
+#include "base64.h"
#include "ioloop.h"
#include "network.h"
#include "istream.h"
@@ -11,6 +12,7 @@
#include "doveadm-print.h"
#include "doveadm-util.h"
#include "doveadm-server.h"
+#include "doveadm-settings.h"
#include "server-connection.h"
#include <unistd.h>
@@ -149,10 +151,28 @@
i_stream_skip(conn->input, size);
}
-static void
-server_connection_authenticate(struct server_connection *conn ATTR_UNUSED)
+static int
+server_connection_authenticate(struct server_connection *conn)
{
- i_fatal("Authentication not supported yet");
+ string_t *plain = t_str_new(128);
+ string_t *cmd = t_str_new(128);
+
+ if (*doveadm_settings->doveadm_password == '\0') {
+ i_error("doveadm_password not set, can't authenticate");
+ return -1;
+ }
+
+ str_append_c(plain, '\0');
+ str_append(plain, "doveadm");
+ str_append_c(plain, '\0');
+ str_append(plain, doveadm_settings->doveadm_password);
+
+ str_append(cmd, "PLAIN\t");
+ base64_encode(plain->data, plain->used, cmd);
+ str_append_c(cmd, '\n');
+
+ o_stream_send(conn->output, cmd->data, cmd->used);
+ return 0;
}
static void server_connection_input(struct server_connection *conn)
@@ -171,9 +191,12 @@
conn->handshaked = TRUE;
if (strcmp(line, "+") == 0)
conn->authenticated = TRUE;
- else if (strcmp(line, "-") == 0)
- server_connection_authenticate(conn);
- else {
+ else if (strcmp(line, "-") == 0) {
+ if (server_connection_authenticate(conn) < 0) {
+ server_connection_destroy(&conn);
+ return;
+ }
+ } else {
i_error("doveadm server sent invalid handshake: %s",
line);
server_connection_destroy(&conn);
@@ -190,6 +213,18 @@
if (size == 0)
return;
+ if (!conn->authenticated) {
+ if ((line = i_stream_next_line(conn->input)) != NULL)
+ return;
+ if (strcmp(line, "+") == 0)
+ conn->authenticated = TRUE;
+ else {
+ i_error("doveadm authentication failed (%s)", line+1);
+ server_connection_destroy(&conn);
+ return;
+ }
+ }
+
switch (conn->state) {
case SERVER_REPLY_STATE_DONE:
i_error("doveadm server sent unexpected input");
More information about the dovecot-cvs
mailing list