Mercurial > dovecot > original-hg > dovecot-1.2
changeset 2766:26a091f3add6 HEAD
Implemented support for LOGIN-REFERRALS using "referral" and "reason"
parameters from auth server.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 18 Oct 2004 04:13:25 +0300 |
parents | 428bba43a387 |
children | 54dfccbe7f11 |
files | configure.in src/imap-login/client-authenticate.c src/imap-login/client.c src/lib-auth/auth-server-request.c src/login-common/sasl-server.c src/login-common/sasl-server.h src/pop3-login/client-authenticate.c src/pop3-login/client.c |
diffstat | 8 files changed, 150 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/configure.in Mon Oct 18 04:00:42 2004 +0300 +++ b/configure.in Mon Oct 18 04:13:25 2004 +0300 @@ -1,7 +1,7 @@ AC_INIT(src) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(dovecot, 1.0-test48) +AM_INIT_AUTOMAKE(dovecot, 1.0-test49) AM_MAINTAINER_MODE @@ -1326,7 +1326,7 @@ dnl ** capabilities dnl ** -capability="IMAP4rev1 SORT THREAD=REFERENCES MULTIAPPEND UNSELECT LITERAL+ IDLE CHILDREN LISTEXT NAMESPACE" +capability="IMAP4rev1 SORT THREAD=REFERENCES MULTIAPPEND UNSELECT LITERAL+ IDLE CHILDREN LISTEXT NAMESPACE LOGIN-REFERRALS" AC_DEFINE_UNQUOTED(CAPABILITY_STRING, "$capability", IMAP capabilities) CFLAGS="$CFLAGS $EXTRA_CFLAGS"
--- a/src/imap-login/client-authenticate.c Mon Oct 18 04:00:42 2004 +0300 +++ b/src/imap-login/client-authenticate.c Mon Oct 18 04:13:25 2004 +0300 @@ -76,8 +76,54 @@ safe_memset(line, 0, strlen(line)); } +static int client_handle_success_args(struct imap_client *client, + const char *const *args, int nologin) +{ + const char *reason = NULL, *referral = NULL; + string_t *reply; + + for (; *args != NULL; args++) { + if (strcmp(*args, "nologin") == 0) + nologin = TRUE; + else if (strncmp(*args, "reason=", 7) == 0) + reason = *args + 7; + else if (strncmp(*args, "referral=", 9) == 0) + referral = *args + 9; + } + + if (!nologin && referral == NULL) + return FALSE; + + reply = t_str_new(128); + str_append(reply, nologin ? "NO " : "OK "); + if (referral != NULL) + str_printfa(reply, "[REFERRAL %s] ", referral); + + if (reason != NULL) + str_append(reply, reason); + else if (!nologin) + str_append(reply, "Logged in."); + else if (referral != NULL) + str_append(reply, "Try this server instead."); + else + str_append(reply, "Login disabled."); + + client_send_tagline(client, str_c(reply)); + if (!nologin) { + client_destroy(client, t_strconcat( + "Login: ", client->common.virtual_user, NULL)); + } else { + /* get back to normal client input. */ + if (client->io != NULL) + io_remove(client->io); + client->io = io_add(client->common.fd, IO_READ, + client_input, client); + } + return TRUE; +} + static void sasl_callback(struct client *_client, enum sasl_server_reply reply, - const char *data) + const char *data, const char *const *args) { struct imap_client *client = (struct imap_client *)_client; struct const_iovec iov[3]; @@ -86,11 +132,21 @@ switch (reply) { case SASL_SERVER_REPLY_SUCCESS: + if (args != NULL) { + if (client_handle_success_args(client, args, FALSE)) + break; + } + client_send_tagline(client, "OK Logged in."); client_destroy(client, t_strconcat( "Login: ", client->common.virtual_user, NULL)); break; case SASL_SERVER_REPLY_AUTH_FAILED: + if (args != NULL) { + if (client_handle_success_args(client, args, TRUE)) + break; + } + if (data == NULL) client_send_tagline(client, "Authentication failed"); else {
--- a/src/imap-login/client.c Mon Oct 18 04:00:42 2004 +0300 +++ b/src/imap-login/client.c Mon Oct 18 04:13:25 2004 +0300 @@ -483,6 +483,7 @@ o_stream_unref(client->output); i_free(client->common.virtual_user); + i_free(client->common.auth_mech_name); i_free(client); main_unref();
--- a/src/lib-auth/auth-server-request.c Mon Oct 18 04:00:42 2004 +0300 +++ b/src/lib-auth/auth-server-request.c Mon Oct 18 04:13:25 2004 +0300 @@ -201,14 +201,16 @@ { struct auth_request *request; struct auth_server_connection *next; - const char *error; + const char *error, *const *list; unsigned int id; - error = strchr(args, '\t'); - if (error != NULL) - error++; + list = t_strsplit(args, "\t"); + if (list[0] == NULL) { + i_error("BUG: Authentication server sent broken OK line"); + return FALSE; + } - id = (unsigned int)strtoul(args, NULL, 10); + id = (unsigned int)strtoul(list[0], NULL, 10); request = hash_lookup(conn->requests, POINTER_CAST(id)); if (request == NULL) { @@ -216,6 +218,14 @@ return TRUE; } + if (list[1] == NULL) { + error = NULL; + list++; + } else { + error = *list[1] == '\0' ? NULL : list[1]; + list += 2; + } + hash_remove(conn->requests, POINTER_CAST(request->id)); if (request->retrying) { next = request->next_conn == NULL ? NULL : @@ -241,7 +251,7 @@ } } - request->callback(request, -1, error, NULL, request->context); + request->callback(request, -1, error, list, request->context); auth_client_request_free(request); return TRUE; }
--- a/src/login-common/sasl-server.c Mon Oct 18 04:00:42 2004 +0300 +++ b/src/login-common/sasl-server.c Mon Oct 18 04:13:25 2004 +0300 @@ -28,11 +28,8 @@ static void master_callback(struct client *client, int success) { client->authenticating = FALSE; - i_free(client->auth_mech_name); - client->auth_mech_name = NULL; - client->sasl_callback(client, success ? SASL_SERVER_REPLY_SUCCESS : - SASL_SERVER_REPLY_MASTER_FAILED, NULL); + SASL_SERVER_REPLY_MASTER_FAILED, NULL, NULL); } static void authenticate_callback(struct auth_request *request, int status, @@ -40,7 +37,8 @@ const char *const *args, void *context) { struct client *client = context; - const char *error; + unsigned int i; + int nologin; if (!client->authenticating) { /* client aborted */ @@ -60,33 +58,47 @@ } client->sasl_callback(client, SASL_SERVER_REPLY_CONTINUE, - data_base64); + data_base64, NULL); break; case 1: client->auth_request = NULL; - for (; *args != NULL; args++) { - if (strncmp(*args, "user=", 5) == 0) { + nologin = FALSE; + for (i = 0; args[i] != NULL; i++) { + if (strncmp(args[i], "user=", 5) == 0) { i_free(client->virtual_user); - client->virtual_user = i_strdup(*args + 5); + client->virtual_user = i_strdup(args[i] + 5); + } + if (strcmp(args[i], "nologin") == 0) { + /* user can't login */ + nologin = TRUE; } } - master_request_login(client, master_callback, + if (nologin) { + client->authenticating = FALSE; + client->sasl_callback(client, SASL_SERVER_REPLY_SUCCESS, + NULL, args); + } else { + master_request_login(client, master_callback, auth_client_request_get_server_pid(request), auth_client_request_get_id(request)); + } break; case -1: client->auth_request = NULL; - /* see if we have error message */ - if (data_base64 != NULL) { - error = t_strconcat("Authentication failed: ", - (const char *)data_base64, NULL); - } else { - error = NULL; + /* base64 contains error message, if there is one */ + if (verbose_auth && data_base64 != NULL) { + client_syslog(client, "Authenticate %s failed: %s", + str_sanitize(client->auth_mech_name, + MAX_MECH_NAME), + (const char *)data_base64); } - sasl_server_auth_cancel(client, error); + + client->authenticating = FALSE; + client->sasl_callback(client, SASL_SERVER_REPLY_AUTH_FAILED, + (const char *)data_base64, args); break; } } @@ -101,6 +113,7 @@ const char *error; client->authenticating = TRUE; + i_free(client->auth_mech_name); client->auth_mech_name = i_strdup(mech_name); client->sasl_callback = callback; @@ -144,13 +157,12 @@ } client->authenticating = FALSE; - i_free(client->auth_mech_name); - client->auth_mech_name = NULL; if (client->auth_request != NULL) { auth_client_request_abort(client->auth_request); client->auth_request = NULL; } - client->sasl_callback(client, SASL_SERVER_REPLY_AUTH_FAILED, reason); + client->sasl_callback(client, SASL_SERVER_REPLY_AUTH_FAILED, + reason, NULL); }
--- a/src/login-common/sasl-server.h Mon Oct 18 04:00:42 2004 +0300 +++ b/src/login-common/sasl-server.h Mon Oct 18 04:13:25 2004 +0300 @@ -10,7 +10,7 @@ typedef void sasl_server_callback_t(struct client *client, enum sasl_server_reply reply, - const char *data); + const char *data, const char *const *args); void sasl_server_auth_begin(struct client *client, const char *protocol, const char *mech_name,
--- a/src/pop3-login/client-authenticate.c Mon Oct 18 04:00:42 2004 +0300 +++ b/src/pop3-login/client-authenticate.c Mon Oct 18 04:13:25 2004 +0300 @@ -77,8 +77,42 @@ safe_memset(line, 0, strlen(line)); } +static int client_handle_success_args(struct pop3_client *client, + const char *const *args) +{ + const char *reason = NULL; + string_t *reply; + int nologin = FALSE; + + for (; *args != NULL; args++) { + if (strcmp(*args, "nologin") == 0) + nologin = TRUE; + else if (strncmp(*args, "reason=", 7) == 0) + reason = *args + 7; + } + + if (!nologin) + return FALSE; + + reply = t_str_new(128); + str_append(reply, "-ERR "); + if (reason != NULL) + str_append(reply, reason); + else + str_append(reply, "Login disabled."); + + client_send_line(client, str_c(reply)); + + /* get back to normal client input. */ + if (client->io != NULL) + io_remove(client->io); + client->io = io_add(client->common.fd, IO_READ, + client_input, client); + return TRUE; +} + static void sasl_callback(struct client *_client, enum sasl_server_reply reply, - const char *data) + const char *data, const char *const *args) { struct pop3_client *client = (struct pop3_client *)_client; struct const_iovec iov[3]; @@ -87,6 +121,11 @@ switch (reply) { case SASL_SERVER_REPLY_SUCCESS: + if (args != NULL) { + if (client_handle_success_args(client, args)) + break; + } + client_send_line(client, "+OK Logged in."); client_destroy(client, t_strconcat( "Login: ", client->common.virtual_user, NULL));