[dovecot-cvs] dovecot/src/imap-login client-authenticate.c, 1.28,
1.29 client.c, 1.29, 1.30 client.h, 1.10, 1.11
cras at dovecot.org
cras at dovecot.org
Mon Oct 11 20:14:28 EEST 2004
- Previous message: [dovecot-cvs]
dovecot/src/lib-storage/index/mbox mbox-sync.c, 1.102, 1.103
- Next message: [dovecot-cvs] dovecot/src/login-common Makefile.am, 1.5,
1.6 auth-common.c, 1.5, NONE auth-common.h, 1.2,
NONE client-common.h, 1.6, 1.7 sasl-server.c, NONE,
1.1 sasl-server.h, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /var/lib/cvs/dovecot/src/imap-login
In directory talvi:/tmp/cvs-serv12396/imap-login
Modified Files:
client-authenticate.c client.c client.h
Log Message:
Login process cleanups. Share more authentication code between pop3/imap.
Index: client-authenticate.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap-login/client-authenticate.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- client-authenticate.c 8 Oct 2004 17:51:47 -0000 1.28
+++ client-authenticate.c 11 Oct 2004 17:14:26 -0000 1.29
@@ -11,14 +11,8 @@
#include "str-sanitize.h"
#include "imap-parser.h"
#include "auth-client.h"
-#include "ssl-proxy.h"
#include "client.h"
#include "client-authenticate.h"
-#include "auth-common.h"
-#include "master.h"
-
-/* Used only for string sanitization while verbose_auth is set. */
-#define MAX_MECH_NAME 64
const char *client_authenticate_get_capabilities(int secured)
{
@@ -45,214 +39,6 @@
return str_c(str);
}
-static void client_auth_abort(struct imap_client *client, const char *msg)
-{
- client->authenticating = FALSE;
-
- if (client->common.auth_request != NULL) {
- auth_client_request_abort(client->common.auth_request);
- client->common.auth_request = NULL;
- }
-
- if (msg != NULL && verbose_auth)
- client_syslog(client, "Authentication failed: %s", msg);
-
- client_send_tagline(client, msg != NULL ?
- t_strconcat("NO ", msg, NULL) :
- "NO Authentication failed.");
-
- /* get back to normal client input */
- if (client->common.io != NULL)
- io_remove(client->common.io);
- client->common.io = client->common.fd == -1 ? NULL :
- io_add(client->common.fd, IO_READ, client_input, client);
-
- client_unref(client);
-}
-
-static void master_callback(struct client *_client, int success)
-{
- struct imap_client *client = (struct imap_client *) _client;
- const char *reason = NULL;
-
- if (success) {
- reason = t_strconcat("Login: ", client->common.virtual_user,
- NULL);
- } else {
- reason = t_strconcat("Internal login failure: ",
- client->common.virtual_user, NULL);
- client_send_line(client, "* BYE Internal login failure. "
- "Error report written to server log.");
- }
-
- client_destroy(client, reason);
-}
-
-static void client_send_auth_data(struct imap_client *client,
- const unsigned char *data, size_t size)
-{
- buffer_t *buf;
- const void *buf_data;
- size_t buf_size;
- ssize_t ret;
-
- t_push();
-
- buf = buffer_create_dynamic(pool_datastack_create(), size*2);
- buffer_append(buf, "+ ", 2);
- base64_encode(data, size, buf);
- buffer_append(buf, "\r\n", 2);
-
- buf_data = buffer_get_data(buf, &buf_size);
- if ((ret = o_stream_send(client->output, buf_data, buf_size)) < 0)
- client_destroy(client, "Disconnected");
- else if ((size_t)ret != buf_size)
- client_destroy(client, "Transmit buffer full");
-
- t_pop();
-}
-
-static void login_callback(struct auth_request *request,
- struct auth_client_request_reply *reply,
- const unsigned char *data, void *context)
-{
- struct imap_client *client = context;
- const char *error;
-
- switch (auth_callback(request, reply, data, &client->common,
- master_callback, &error)) {
- case -1:
- case 0:
- /* login failed */
- client_auth_abort(client, error);
- break;
-
- default:
- /* success, we should be able to log in. if we fail, just
- disconnect the client. */
- client->authenticating = FALSE;
- client_send_tagline(client, "OK Logged in.");
- client_unref(client);
- }
-}
-
-static enum auth_client_request_new_flags
-client_get_auth_flags(struct imap_client *client)
-{
- enum auth_client_request_new_flags auth_flags = 0;
-
- if (client->common.proxy != NULL &&
- ssl_proxy_has_valid_client_cert(client->common.proxy))
- auth_flags |= AUTH_CLIENT_FLAG_SSL_VALID_CLIENT_CERT;
- if (client->tls)
- auth_flags |= AUTH_CLIENT_FLAG_SSL_ENABLED;
- return auth_flags;
-}
-
-int cmd_login(struct imap_client *client, struct imap_arg *args)
-{
- const char *user, *pass, *error;
- struct auth_request_info info;
- string_t *plain_login;
-
- /* two arguments: username and password */
- if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
- return FALSE;
- if (args[1].type != IMAP_ARG_ATOM && args[1].type != IMAP_ARG_STRING)
- return FALSE;
- if (args[2].type != IMAP_ARG_EOL)
- return FALSE;
-
- user = IMAP_ARG_STR(&args[0]);
- pass = IMAP_ARG_STR(&args[1]);
-
- if (!client->secured && disable_plaintext_auth) {
- if (verbose_auth) {
- client_syslog(client, "Login failed: "
- "Plaintext authentication disabled");
- }
- client_send_line(client,
- "* BAD [ALERT] Plaintext authentication is disabled, "
- "but your client sent password in plaintext anyway. "
- "If anyone was listening, the password was exposed.");
- client_send_tagline(client,
- "NO Plaintext authentication disabled.");
- return TRUE;
- }
-
- /* authorization ID \0 authentication ID \0 pass */
- plain_login = t_str_new(64);
- str_append_c(plain_login, '\0');
- str_append(plain_login, user);
- str_append_c(plain_login, '\0');
- str_append(plain_login, pass);
-
- memset(&info, 0, sizeof(info));
- info.mech = "PLAIN";
- info.protocol = "IMAP";
- info.flags = client_get_auth_flags(client);
- info.local_ip = client->common.local_ip;
- info.remote_ip = client->common.ip;
- info.initial_resp_data = str_data(plain_login);
- info.initial_resp_size = str_len(plain_login);
-
- client_ref(client);
-
- client->common.auth_request =
- auth_client_request_new(auth_client, NULL, &info,
- login_callback, client, &error);
- if (client->common.auth_request == NULL) {
- if (verbose_auth)
- client_syslog(client, "Login failed: %s", error);
- client_send_tagline(client, t_strconcat(
- "NO Login failed: ", error, NULL));
- client_unref(client);
- return TRUE;
- }
-
- /* don't read any input from client until login is finished */
- if (client->common.io != NULL) {
- io_remove(client->common.io);
- client->common.io = NULL;
- }
-
- client->authenticating = TRUE;
- return TRUE;
-}
-
-static void authenticate_callback(struct auth_request *request,
- struct auth_client_request_reply *reply,
- const unsigned char *data, void *context)
-{
- struct imap_client *client = context;
- const char *error;
-
- if (!client->authenticating) {
- /* client aborted */
- i_assert(reply == NULL);
- return;
- }
-
- switch (auth_callback(request, reply, data, &client->common,
- master_callback, &error)) {
- case -1:
- /* login failed */
- client_auth_abort(client, error);
- break;
-
- case 0:
- /* continue */
- client_send_auth_data(client, data, reply->data_size);
- break;
- default:
- /* success, we should be able to log in. if we fail, just
- disconnect the client. */
- client->authenticating = FALSE;
- client_send_tagline(client, "OK Logged in.");
- client_unref(client);
- }
-}
-
static void client_auth_input(void *context)
{
struct imap_client *client = context;
@@ -276,7 +62,8 @@
return;
if (strcmp(line, "*") == 0) {
- client_auth_abort(client, "Authentication aborted");
+ sasl_server_auth_cancel(&client->common,
+ "Authentication aborted");
return;
}
@@ -285,13 +72,13 @@
if (base64_decode(line, linelen, NULL, buf) < 0) {
/* failed */
- client_auth_abort(client, "Invalid base64 data");
+ sasl_server_auth_cancel(&client->common, "Invalid base64 data");
} else if (client->common.auth_request == NULL) {
- client_auth_abort(client, "Don't send unrequested data");
+ sasl_server_auth_cancel(&client->common,
+ "Don't send unrequested data");
} else {
auth_client_request_continue(client->common.auth_request,
- buffer_get_data(buf, NULL),
- buffer_get_used_size(buf));
+ buf->data, buf->used);
}
/* clear sensitive data */
@@ -301,75 +88,142 @@
safe_memset(buffer_free_without_data(buf), 0, bufsize);
}
+static void sasl_callback(struct client *_client, enum sasl_server_reply reply,
+ const char *data)
+{
+ struct imap_client *client = (struct imap_client *)_client;
+ struct const_iovec iov[3];
+ size_t data_len;
+ ssize_t ret;
+
+ switch (reply) {
+ case SASL_SERVER_REPLY_SUCCESS:
+ 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 (data == NULL)
+ client_send_tagline(client, "Authentication failed");
+ else {
+ client_send_tagline(client, t_strconcat(
+ "NO Authentication failed: ", data, NULL));
+ }
+
+ /* 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);
+ break;
+ case SASL_SERVER_REPLY_MASTER_FAILED:
+ client_send_line(client, "* BYE Internal login failure. "
+ "Error report written to server log.");
+ client_destroy(client, t_strconcat("Internal login failure: ",
+ client->common.virtual_user,
+ NULL));
+ break;
+ case SASL_SERVER_REPLY_CONTINUE:
+ data_len = strlen(data);
+ iov[0].iov_base = "+ ";
+ iov[0].iov_len = 2;
+ iov[1].iov_base = data;
+ iov[1].iov_len = data_len;
+ iov[2].iov_base = "\r\n";
+ iov[2].iov_len = 2;
+
+ ret = o_stream_sendv(client->output, iov, 3);
+ if (ret < 0)
+ client_destroy(client, "Disconnected");
+ else if ((size_t)ret != 2 + data_len + 2)
+ client_destroy(client, "Transmit buffer full");
+ else {
+ /* continue */
+ return;
+ }
+ break;
+ }
+
+ client_unref(client);
+}
+
int cmd_authenticate(struct imap_client *client, struct imap_arg *args)
{
- const struct auth_mech_desc *mech;
- const char *mech_name, *error;
- struct auth_request_info info;
+ const char *mech_name;
/* we want only one argument: authentication mechanism name */
if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
- return FALSE;
+ return -1;
if (args[1].type != IMAP_ARG_EOL)
- return FALSE;
+ return -1;
mech_name = IMAP_ARG_STR(&args[0]);
if (*mech_name == '\0')
return FALSE;
- mech = auth_client_find_mech(auth_client, mech_name);
- if (mech == NULL) {
- if (verbose_auth) {
- client_syslog(client, "Authenticate %s failed: "
- "Unsupported mechanism",
- str_sanitize(mech_name, MAX_MECH_NAME));
- }
- client_send_tagline(client,
- "NO Unsupported authentication mechanism.");
- return TRUE;
- }
+ client_ref(client);
+ sasl_server_auth_begin(&client->common, "IMAP", mech_name, NULL, 0,
+ sasl_callback);
+ if (!client->common.authenticating)
+ return 1;
- if (!client->secured && mech->plaintext && disable_plaintext_auth) {
+ /* following input data will go to authentication */
+ if (client->io != NULL)
+ io_remove(client->io);
+ client->io = io_add(client->common.fd, IO_READ,
+ client_auth_input, client);
+ return 0;
+}
+
+int cmd_login(struct imap_client *client, struct imap_arg *args)
+{
+ const char *user, *pass;
+ string_t *plain_login;
+
+ /* two arguments: username and password */
+ if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
+ return -1;
+ if (args[1].type != IMAP_ARG_ATOM && args[1].type != IMAP_ARG_STRING)
+ return -1;
+ if (args[2].type != IMAP_ARG_EOL)
+ return -1;
+
+ user = IMAP_ARG_STR(&args[0]);
+ pass = IMAP_ARG_STR(&args[1]);
+
+ if (!client->common.secured && disable_plaintext_auth) {
if (verbose_auth) {
- client_syslog(client, "Authenticate %s failed: "
- "Plaintext authentication disabled",
- str_sanitize(mech_name, MAX_MECH_NAME));
+ client_syslog(&client->common, "Login failed: "
+ "Plaintext authentication disabled");
}
+ client_send_line(client,
+ "* BAD [ALERT] Plaintext authentication is disabled, "
+ "but your client sent password in plaintext anyway. "
+ "If anyone was listening, the password was exposed.");
client_send_tagline(client,
"NO Plaintext authentication disabled.");
- return TRUE;
+ return 1;
}
- memset(&info, 0, sizeof(info));
- info.mech = mech->name;
- info.protocol = "IMAP";
- info.flags = client_get_auth_flags(client);
- info.local_ip = client->common.local_ip;
- info.remote_ip = client->common.ip;
+ /* authorization ID \0 authentication ID \0 pass */
+ plain_login = buffer_create_dynamic(pool_datastack_create(), 64);
+ buffer_append_c(plain_login, '\0');
+ buffer_append(plain_login, user, strlen(user));
+ buffer_append_c(plain_login, '\0');
+ buffer_append(plain_login, pass, strlen(pass));
client_ref(client);
- o_stream_uncork(client->output);
+ sasl_server_auth_begin(&client->common, "IMAP", "PLAIN",
+ plain_login->data, plain_login->used,
+ sasl_callback);
+ if (!client->common.authenticating)
+ return 1;
- client->common.auth_request =
- auth_client_request_new(auth_client, NULL, &info,
- authenticate_callback, client, &error);
- if (client->common.auth_request != NULL) {
- /* following input data will go to authentication */
- if (client->common.io != NULL)
- io_remove(client->common.io);
- client->common.io = io_add(client->common.fd, IO_READ,
- client_auth_input, client);
- client->authenticating = TRUE;
- } else {
- if (verbose_auth) {
- client_syslog(client, "Authenticate %s failed: %s",
- str_sanitize(mech_name, MAX_MECH_NAME),
- error);
- }
- client_send_tagline(client, t_strconcat(
- "NO Authentication failed: ", error, NULL));
- client_unref(client);
+ /* don't read any input from client until login is finished */
+ if (client->io != NULL) {
+ io_remove(client->io);
+ client->io = NULL;
}
- return TRUE;
+ return 0;
}
Index: client.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap-login/client.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- client.c 5 Oct 2004 16:00:18 -0000 1.29
+++ client.c 11 Oct 2004 17:14:26 -0000 1.30
@@ -56,8 +56,8 @@
if (addr == NULL)
addr = "??";
- process_title_set(t_strdup_printf(client->tls ? "[%s TLS]" : "[%s]",
- addr));
+ process_title_set(t_strdup_printf(client->common.tls ?
+ "[%s TLS]" : "[%s]", addr));
}
static void client_open_streams(struct imap_client *client, int fd)
@@ -93,10 +93,11 @@
{
const char *auths;
- auths = client_authenticate_get_capabilities(client->secured);
+ auths = client_authenticate_get_capabilities(client->common.secured);
return t_strconcat(CAPABILITY_STRING,
- (ssl_initialized && !client->tls) ? " STARTTLS" : "",
- disable_plaintext_auth && !client->secured ?
+ (ssl_initialized && !client->common.tls) ?
+ " STARTTLS" : "",
+ disable_plaintext_auth && !client->common.secured ?
" LOGINDISABLED" : "", auths, NULL);
}
@@ -120,8 +121,8 @@
return;
}
- client->tls = TRUE;
- client->secured = TRUE;
+ client->common.tls = TRUE;
+ client->common.secured = TRUE;
client_set_title(client);
client->common.fd = fd_ssl;
@@ -133,8 +134,7 @@
client->skip_line = FALSE;
client_open_streams(client, fd_ssl);
- client->common.io = io_add(client->common.fd, IO_READ,
- client_input, client);
+ client->io = io_add(client->common.fd, IO_READ, client_input, client);
}
static void client_output_starttls(void *context)
@@ -153,7 +153,7 @@
static int cmd_starttls(struct imap_client *client)
{
- if (client->tls) {
+ if (client->common.tls) {
client_send_tagline(client, "BAD TLS is already active.");
return TRUE;
}
@@ -165,9 +165,9 @@
/* remove input handler, SSL proxy gives us a new fd. we also have to
remove it in case we have to wait for buffer to be flushed */
- if (client->common.io != NULL) {
- io_remove(client->common.io);
- client->common.io = NULL;
+ if (client->io != NULL) {
+ io_remove(client->io);
+ client->io = NULL;
}
client_send_tagline(client, "OK Begin TLS negotiation now.");
@@ -212,17 +212,16 @@
if (strcmp(cmd, "LOGOUT") == 0)
return cmd_logout(client);
- return FALSE;
+ return -1;
}
static int client_handle_input(struct imap_client *client)
{
struct imap_arg *args;
const char *msg;
- int fatal;
+ int ret, fatal;
- if (client->authenticating)
- return FALSE; /* wait until authentication is finished */
+ i_assert(!client->common.authenticating);
if (client->cmd_finished) {
/* clear the previous command from memory. don't do this
@@ -276,8 +275,13 @@
}
client->skip_line = TRUE;
- if (*client->cmd_tag == '\0' ||
- !client_command_execute(client, client->cmd_name, args)) {
+ if (*client->cmd_tag == '\0')
+ ret = -1;
+ else
+ ret = client_command_execute(client, client->cmd_name, args);
+
+ client->cmd_finished = TRUE;
+ if (ret < 0) {
if (*client->cmd_tag == '\0')
client->cmd_tag = "*";
if (++client->bad_counter >= CLIENT_MAX_BAD_COMMANDS) {
@@ -286,13 +290,12 @@
client_destroy(client, "Disconnected: "
"Too many invalid commands");
return FALSE;
- }
+ }
client_send_tagline(client,
"BAD Error in IMAP command received by server.");
}
- client->cmd_finished = TRUE;
- return TRUE;
+ return ret != 0;
}
int client_read(struct imap_client *client)
@@ -397,10 +400,10 @@
client = i_new(struct imap_client, 1);
client->created = ioloop_time;
client->refcount = 1;
- client->tls = ssl;
+ client->common.tls = ssl;
addr = net_ip2addr(ip);
- client->secured = ssl ||
+ client->common.secured = ssl ||
(IPADDR_IS_V4(ip) && strncmp(addr, "127.", 4) == 0) ||
(IPADDR_IS_V6(ip) && strcmp(addr, "::1") == 0);
@@ -409,7 +412,7 @@
client->common.fd = fd;
client_open_streams(client, fd);
- client->common.io = io_add(fd, IO_READ, client_input, client);
+ client->io = io_add(fd, IO_READ, client_input, client);
client->last_input = ioloop_time;
hash_insert(clients, client, client);
@@ -434,7 +437,7 @@
client->destroyed = TRUE;
if (reason != NULL)
- client_syslog(client, "%s", reason);
+ client_syslog(&client->common, "%s", reason);
hash_remove(clients, client);
@@ -449,9 +452,9 @@
if (client->common.master_tag != 0)
master_request_abort(&client->common);
- if (client->common.io != NULL) {
- io_remove(client->common.io);
- client->common.io = NULL;
+ if (client->io != NULL) {
+ io_remove(client->io);
+ client->io = NULL;
}
if (client->common.fd != -1) {
@@ -507,22 +510,6 @@
client_send_line(client, t_strconcat(client->cmd_tag, " ", line, NULL));
}
-void client_syslog(struct imap_client *client, const char *format, ...)
-{
- const char *addr;
- va_list args;
-
- addr = net_ip2addr(&client->common.ip);
- if (addr == NULL)
- addr = "??";
-
- t_push();
- va_start(args, format);
- i_info("%s [%s]", t_strdup_vprintf(format, args), addr);
- va_end(args);
- t_pop();
-}
-
static void client_check_idle(struct imap_client *client)
{
if (ioloop_time - client->last_input >= CLIENT_LOGIN_IDLE_TIMEOUT) {
Index: client.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap-login/client.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- client.h 5 Oct 2004 16:00:18 -0000 1.10
+++ client.h 11 Oct 2004 17:14:26 -0000 1.11
@@ -11,6 +11,7 @@
time_t created;
int refcount;
+ struct io *io;
struct istream *input;
struct ostream *output;
struct imap_parser *parser;
@@ -20,12 +21,9 @@
const char *cmd_tag, *cmd_name;
- unsigned int tls:1;
- unsigned int secured:1;
unsigned int cmd_finished:1;
unsigned int skip_line:1;
unsigned int input_blocked:1;
- unsigned int authenticating:1;
unsigned int destroyed:1;
};
@@ -33,8 +31,6 @@
void client_send_line(struct imap_client *client, const char *line);
void client_send_tagline(struct imap_client *client, const char *line);
-void client_syslog(struct imap_client *client, const char *format, ...)
- __attr_format__(2, 3);
int client_read(struct imap_client *client);
void client_input(void *context);
- Previous message: [dovecot-cvs]
dovecot/src/lib-storage/index/mbox mbox-sync.c, 1.102, 1.103
- Next message: [dovecot-cvs] dovecot/src/login-common Makefile.am, 1.5,
1.6 auth-common.c, 1.5, NONE auth-common.h, 1.2,
NONE client-common.h, 1.6, 1.7 sasl-server.c, NONE,
1.1 sasl-server.h, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the dovecot-cvs
mailing list