dovecot-2.0: Added support for userdb lookup to fail with a reas...
dovecot at dovecot.org
dovecot at dovecot.org
Wed Mar 31 19:22:29 EEST 2010
details: http://hg.dovecot.org/dovecot-2.0/rev/2e08ce368bc0
changeset: 11018:2e08ce368bc0
user: Timo Sirainen <tss at iki.fi>
date: Wed Mar 31 19:21:09 2010 +0300
description:
Added support for userdb lookup to fail with a reason (many API changes).
diffstat:
doc/auth-protocol.txt | 7 +-
src/doveadm/doveadm-auth.c | 11 ++-
src/doveadm/doveadm-mail.c | 9 +-
src/dsync/dsync.c | 8 +-
src/imap/main.c | 82 +++++++++++++++++++--------
src/lib-auth/auth-master.c | 48 +++++++++++----
src/lib-auth/auth-master.h | 4 +-
src/lib-master/master-auth.c | 8 +--
src/lib-master/master-auth.h | 4 +
src/lib-master/master-login-auth.c | 39 ++++++++----
src/lib-master/master-login-auth.h | 2 +-
src/lib-master/master-login.c | 17 ++++-
src/lib-master/master-login.h | 6 +-
src/lib-storage/mail-storage-service.c | 66 ++++++++++++++--------
src/lib-storage/mail-storage-service.h | 11 +--
src/lmtp/commands.c | 22 ++++---
src/login-common/client-common-auth.c | 5 +
src/login-common/sasl-server.c | 15 +++--
src/login-common/sasl-server.h | 1 +
src/pop3/main.c | 12 +++-
20 files changed, 253 insertions(+), 124 deletions(-)
diffs (truncated from 925 to 300 lines):
diff -r ce7ed594d99e -r 2e08ce368bc0 doc/auth-protocol.txt
--- a/doc/auth-protocol.txt Wed Mar 31 19:18:01 2010 +0300
+++ b/doc/auth-protocol.txt Wed Mar 31 19:21:09 2010 +0300
@@ -164,7 +164,7 @@
M: "USER" TAB <id> TAB <userid> TAB service=<service> [TAB <parameters>]
S: "NOTFOUND" TAB <id>
- S: "FAIL" TAB <id> TAB <error message>
+ S: "FAIL" TAB <id> [TAB <parameters>]
S: "USER" TAB <id> TAB <userid> [TAB <parameters>]
Master commands can request information about existing authentication
@@ -180,7 +180,10 @@
FAIL reply means an internal error occurred. Usually either a configuration
mistake or temporary error caused by lost resource (eg. database down).
-Also unknown request IDs are reported as FAILs.
+Also unknown request IDs are reported as FAILs. Currently the only
+specified parameter is "reason", which is used when user is wanted to be
+put into "temporarily disabled" state and the reason string will be shown
+to user on login or to LMTP RCPT TO reply.
USER reply is sent if request succeeded. It can return parameters:
diff -r ce7ed594d99e -r 2e08ce368bc0 src/doveadm/doveadm-auth.c
--- a/src/doveadm/doveadm-auth.c Wed Mar 31 19:18:01 2010 +0300
+++ b/src/doveadm/doveadm-auth.c Wed Mar 31 19:21:09 2010 +0300
@@ -37,9 +37,14 @@
conn = auth_master_init(auth_socket_path, 0);
ret = auth_master_user_lookup(conn, input->username, &input->info,
pool, &username, &fields);
- if (ret < 0)
- i_fatal("userdb lookup failed");
- else if (ret == 0) {
+ if (ret < 0) {
+ if (fields[0] == NULL)
+ i_fatal("userdb lookup failed for %s", input->username);
+ else {
+ i_fatal("userdb lookup failed for %s: %s",
+ input->username, fields[0]);
+ }
+ } else if (ret == 0) {
printf("userdb lookup: user %s doesn't exist\n",
input->username);
} else {
diff -r ce7ed594d99e -r 2e08ce368bc0 src/doveadm/doveadm-mail.c
--- a/src/doveadm/doveadm-mail.c Wed Mar 31 19:18:01 2010 +0300
+++ b/src/doveadm/doveadm-mail.c Wed Mar 31 19:21:09 2010 +0300
@@ -99,11 +99,12 @@
return ret;
}
- if (mail_storage_service_next(storage_service, service_user,
- &mail_user, &error) < 0) {
- *error_r = t_strdup_printf("User init failed: %s", error);
+ ret = mail_storage_service_next(storage_service, service_user,
+ &mail_user);
+ if (ret < 0) {
+ *error_r = "User init failed";
mail_storage_service_user_free(&service_user);
- return -2;
+ return ret;
}
cmd(mail_user, args);
diff -r ce7ed594d99e -r 2e08ce368bc0 src/dsync/dsync.c
--- a/src/dsync/dsync.c Wed Mar 31 19:18:01 2010 +0300
+++ b/src/dsync/dsync.c Wed Mar 31 19:21:09 2010 +0300
@@ -147,8 +147,8 @@
&service_user, &error) <= 0)
i_fatal("User lookup failed: %s", error);
if (mail_storage_service_next(storage_service, service_user,
- &mail_user, &error) < 0)
- i_fatal("User init failed: %s", error);
+ &mail_user) < 0)
+ i_fatal("User init failed");
if (mirror_cmd != NULL) {
/* user initialization may exec doveconf, so do our forking
@@ -170,8 +170,8 @@
if (settings_parse_line(set_parser, set_line) < 0)
i_unreached();
if (mail_storage_service_next(storage_service, service_user,
- &mail_user2, &error) < 0)
- i_fatal("User init failed: %s", error);
+ &mail_user2) < 0)
+ i_fatal("User init failed");
worker2 = dsync_worker_init_local(mail_user2, alt_char);
diff -r ce7ed594d99e -r 2e08ce368bc0 src/imap/main.c
--- a/src/imap/main.c Wed Mar 31 19:18:01 2010 +0300
+++ b/src/imap/main.c Wed Mar 31 19:21:09 2010 +0300
@@ -15,6 +15,7 @@
#include "master-login.h"
#include "mail-user.h"
#include "mail-storage-service.h"
+#include "imap-resp-code.h"
#include "imap-commands.h"
#include "imap-fetch.h"
@@ -104,52 +105,72 @@
}
}
+struct client_input {
+ const char *tag;
+
+ const unsigned char *input;
+ unsigned int input_size;
+ bool send_untagged_capability;
+};
+
+static void
+client_parse_input(const unsigned char *data, unsigned int len,
+ struct client_input *input_r)
+{
+ unsigned int taglen;
+
+ i_assert(len > 0);
+
+ memset(input_r, 0, sizeof(*input_r));
+
+ if (data[0] == '1')
+ input_r->send_untagged_capability = TRUE;
+ data++; len--;
+
+ input_r->tag = t_strndup(data, len);
+ taglen = strlen(input_r->tag) + 1;
+
+ if (len > taglen) {
+ input_r->input = data + taglen;
+ input_r->input_size = len - taglen;
+ }
+}
+
static void client_add_input(struct client *client, const buffer_t *buf)
{
struct ostream *output;
- const char *tag;
- unsigned int data_pos;
- bool send_untagged_capability = FALSE;
+ struct client_input input;
if (buf != NULL && buf->used > 0) {
- tag = t_strndup(buf->data, buf->used);
- switch (*tag) {
- case '0':
- tag++;
- break;
- case '1':
- send_untagged_capability = TRUE;
- tag++;
- break;
- }
- data_pos = strlen(tag) + 1;
- if (data_pos > buf->used &&
- !i_stream_add_data(client->input,
- CONST_PTR_OFFSET(buf->data, data_pos),
- buf->used - data_pos))
+ client_parse_input(buf->data, buf->used, &input);
+ if (input.input_size > 0 &&
+ !i_stream_add_data(client->input, input.input,
+ input.input_size))
i_panic("Couldn't add client input to stream");
} else {
/* IMAPLOGINTAG environment is compatible with mailfront */
- tag = getenv("IMAPLOGINTAG");
+ memset(&input, 0, sizeof(input));
+ input.tag = getenv("IMAPLOGINTAG");
}
output = client->output;
o_stream_ref(output);
o_stream_cork(output);
- if (tag == NULL) {
+ if (input.tag == NULL) {
client_send_line(client, t_strconcat(
"* PREAUTH [CAPABILITY ",
str_c(client->capability_string), "] "
"Logged in as ", client->user->username, NULL));
- } else if (send_untagged_capability) {
+ } else if (input.send_untagged_capability) {
/* client doesn't seem to understand tagged capabilities. send
untagged instead and hope that it works. */
client_send_line(client, t_strconcat("* CAPABILITY ",
str_c(client->capability_string), NULL));
- client_send_line(client, t_strconcat(tag, " OK Logged in", NULL));
+ client_send_line(client,
+ t_strconcat(input.tag, " OK Logged in", NULL));
} else {
client_send_line(client, t_strconcat(
- tag, " OK [CAPABILITY ",
+ input.tag, " OK [CAPABILITY ",
str_c(client->capability_string), "] Logged in", NULL));
}
(void)client_handle_input(client);
@@ -241,6 +262,18 @@
}
}
+static void login_client_failed(const struct master_login_client *client,
+ const char *errormsg)
+{
+ struct client_input input;
+ const char *msg;
+
+ client_parse_input(client->data, client->auth_req.data_size, &input);
+ msg = t_strdup_printf("%s NO ["IMAP_RESP_CODE_UNAVAILABLE"] %s\r\n",
+ input.tag, errormsg);
+ (void)write(client->fd, msg, strlen(msg));
+}
+
static void client_connected(const struct master_service_connection *conn)
{
if (master_login == NULL) {
@@ -315,7 +348,8 @@
} else {
master_login = master_login_init(master_service, "auth-master",
postlogin_socket_path,
- login_client_connected);
+ login_client_connected,
+ login_client_failed);
io_loop_set_running(current_ioloop);
}
diff -r ce7ed594d99e -r 2e08ce368bc0 src/lib-auth/auth-master.c
--- a/src/lib-auth/auth-master.c Wed Mar 31 19:18:01 2010 +0300
+++ b/src/lib-auth/auth-master.c Wed Mar 31 19:21:09 2010 +0300
@@ -50,6 +50,7 @@
struct auth_master_lookup_ctx {
struct auth_master_connection *conn;
+ const char *user;
const char *expected_reply;
int return_value;
@@ -135,19 +136,21 @@
return 0;
}
-static int parse_reply(struct auth_master_connection *conn,
- const char *cmd, const char *const *args,
- const char *expected_reply)
+static int parse_reply(const char *cmd, const char *const *args,
+ const char *expected_reply, const char *user, bool debug)
{
- io_loop_stop(conn->ioloop);
-
if (strcmp(cmd, expected_reply) == 0)
return 1;
if (strcmp(cmd, "NOTFOUND") == 0)
return 0;
if (strcmp(cmd, "FAIL") == 0) {
- i_error("Lookup failed: %s",
- *args != NULL ? *args : "Internal failure");
+ if (*args == NULL) {
+ i_error("user %s: Auth %s lookup failed",
+ user, expected_reply);
+ } else if (debug) {
+ i_debug("user %s: Auth %s lookup returned temporary failure: %s",
+ user, expected_reply, *args);
+ }
return -1;
}
i_error("Unknown reply: %s", cmd);
@@ -159,17 +162,31 @@
{
struct auth_master_lookup_ctx *ctx = context;
unsigned int i, len;
+ bool debug = (ctx->conn->flags & AUTH_MASTER_FLAG_DEBUG) != 0;
+
+ io_loop_stop(ctx->conn->ioloop);
ctx->return_value =
- parse_reply(ctx->conn, cmd, args, ctx->expected_reply);
- if (ctx->return_value > 0) {
- len = str_array_length(args);
+ parse_reply(cmd, args, ctx->expected_reply, ctx->user, debug);
+
+ len = str_array_length(args);
+ if (ctx->return_value >= 0) {
ctx->fields = p_new(ctx->pool, const char *, len + 1);
for (i = 0; i < len; i++)
ctx->fields[i] = p_strdup(ctx->pool, args[i]);
- if ((ctx->conn->flags & AUTH_MASTER_FLAG_DEBUG) != 0)
- i_debug("auth input: %s", t_strarray_join(args, " "));
+ } else {
+ /* put the reason string into first field */
+ ctx->fields = p_new(ctx->pool, const char *, 2);
+ for (i = 0; i < len; i++) {
+ if (strncmp(args[i], "reason=", 7) == 0) {
+ ctx->fields[0] =
+ p_strdup(ctx->pool, args[i] + 7);
+ break;
+ }
+ }
}
+ if (debug)
+ i_debug("auth input: %s", t_strarray_join(args, " "));
More information about the dovecot-cvs
mailing list