[dovecot-cvs] dovecot/src/auth Makefile.am, 1.34,
1.35 auth-client-connection.c, 1.12,
1.13 auth-client-connection.h, 1.2,
1.3 auth-client-interface.h, 1.8, 1.9 auth-master-connection.c,
1.11, 1.12 auth-master-connection.h, 1.4,
1.5 auth-master-interface.h, 1.5, NONE mech-anonymous.c, 1.5,
1.6 mech-apop.c, 1.5, 1.6 mech-cram-md5.c, 1.12,
1.13 mech-digest-md5.c, 1.25, 1.26 mech-login.c, 1.3,
1.4 mech-ntlm.c, 1.6, 1.7 mech-plain.c, 1.21, 1.22 mech-rpa.c,
1.5, 1.6 mech.c, 1.41, 1.42 mech.h, 1.22, 1.23 userdb.h, 1.10, 1.11
cras at dovecot.org
cras at dovecot.org
Wed Oct 13 19:38:35 EEST 2004
Update of /var/lib/cvs/dovecot/src/auth
In directory talvi:/tmp/cvs-serv8894/auth
Modified Files:
Makefile.am auth-client-connection.c auth-client-connection.h
auth-client-interface.h auth-master-connection.c
auth-master-connection.h mech-anonymous.c mech-apop.c
mech-cram-md5.c mech-digest-md5.c mech-login.c mech-ntlm.c
mech-plain.c mech-rpa.c mech.c mech.h userdb.h
Removed Files:
auth-master-interface.h
Log Message:
Changed dovecot-auth protocol to ASCII based. Should be easier now to write
replacement server if needed by someone. Also cleaned up/made more
consistent auth code. The new code could still use some cleaning though..
Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/Makefile.am,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- Makefile.am 10 Oct 2004 13:55:12 -0000 1.34
+++ Makefile.am 13 Oct 2004 16:38:32 -0000 1.35
@@ -71,7 +71,6 @@
auth-client-connection.h \
auth-client-interface.h \
auth-master-connection.h \
- auth-master-interface.h \
auth-module.h \
db-ldap.h \
db-mysql.h \
Index: auth-client-connection.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-client-connection.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- auth-client-connection.c 10 Oct 2004 14:21:07 -0000 1.12
+++ auth-client-connection.c 13 Oct 2004 16:38:32 -0000 1.13
@@ -5,48 +5,99 @@
#include "istream.h"
#include "ostream.h"
#include "network.h"
+#include "base64.h"
+#include "buffer.h"
#include "hash.h"
+#include "str.h"
+#include "str-sanitize.h"
#include "safe-memset.h"
#include "mech.h"
#include "auth-client-connection.h"
#include "auth-master-connection.h"
#include <stdlib.h>
-#include <syslog.h>
-#define MAX_INBUF_SIZE \
- (sizeof(struct auth_client_request_continue) + \
- AUTH_CLIENT_MAX_REQUEST_DATA_SIZE)
+/* Used only for string sanitization. */
+#define MAX_MECH_NAME_LEN 64
+
#define MAX_OUTBUF_SIZE (1024*50)
static void auth_client_connection_unref(struct auth_client_connection *conn);
-static void request_callback(struct auth_client_request_reply *reply,
- const void *data,
- struct auth_client_connection *conn)
+static void auth_client_send(struct auth_client_connection *conn,
+ const char *fmt, ...) __attr_format__(2, 3);
+static void auth_client_send(struct auth_client_connection *conn,
+ const char *fmt, ...)
{
- struct const_iovec iov[2];
+ va_list args;
+ string_t *str;
ssize_t ret;
- iov[0].iov_base = reply;
- iov[0].iov_len = sizeof(*reply);
- iov[1].iov_base = data;
- iov[1].iov_len = reply->data_size;
+ i_assert(conn->refcount > 1);
- ret = o_stream_sendv(conn->output, iov, 2);
- if (ret == (ssize_t)(iov[0].iov_len + iov[1].iov_len)) {
- /* all sent */
- auth_client_connection_unref(conn);
- return;
+ t_push();
+ va_start(args, fmt);
+ str = t_str_new(256);
+ str_vprintfa(str, fmt, args);
+ str_append_c(str, '\n');
+ ret = o_stream_send(conn->output, str_data(str), str_len(str));
+ if (ret != (ssize_t)str->used) {
+ i_warning("Authentication client %u: "
+ "Transmit buffer full, killing it", conn->pid);
+ auth_client_connection_destroy(conn);
}
+ va_end(args);
+ t_pop();
+}
- if (ret >= 0) {
- i_warning("Auth client %u: Transmit buffer full, killing it",
- conn->pid);
+static void auth_callback(struct auth_request *request,
+ enum auth_client_result result,
+ const void *reply, size_t reply_size)
+{
+ string_t *str = NULL;
+ ssize_t ret;
+
+ t_push();
+
+ switch (result) {
+ case AUTH_CLIENT_RESULT_CONTINUE:
+ str = t_str_new(32 + MAX_BASE64_ENCODED_SIZE(reply_size));
+ str_printfa(str, "CONT\t%u\t", request->id);
+ base64_encode(reply, reply_size, str);
+ request->accept_input = TRUE;
+ break;
+ case AUTH_CLIENT_RESULT_SUCCESS:
+ str = t_str_new(128 + MAX_BASE64_ENCODED_SIZE(reply_size));
+ str_printfa(str, "OK\t%u\t%s", request->id, request->user);
+ if (reply_size > 0) {
+ str_append(str, "\tresp=");
+ base64_encode(reply, reply_size, str);
+ }
+ break;
+ case AUTH_CLIENT_RESULT_FAILURE:
+ str = t_str_new(128);
+ str_printfa(str, "FAIL\t%u", request->id);
+ if (reply != NULL) {
+ str_append_c(str, '\t');
+ str_append(str, reply);
+ }
+ break;
}
- auth_client_connection_destroy(conn);
- auth_client_connection_unref(conn);
+ str_append_c(str, '\n');
+
+ ret = o_stream_send(request->conn->output, str->data, str->used);
+ if (ret < 0)
+ auth_client_connection_destroy(request->conn);
+ else if ((size_t)ret != str->used) {
+ i_warning("Authentication client %u: "
+ "Transmit buffer full, killing it",
+ request->conn->pid);
+ auth_client_connection_destroy(request->conn);
+ }
+ t_pop();
+
+ auth_client_connection_unref(request->conn);
}
struct auth_client_connection *
@@ -63,106 +114,229 @@
return NULL;
}
-static int auth_client_input_handshake(struct auth_client_connection *conn)
+static int
+auth_client_input_proto(struct auth_client_connection *conn, const char *args)
{
- struct auth_client_handshake_request rec;
- unsigned char *data;
- size_t size;
+ if (conn->default_protocol == NULL)
+ conn->default_protocol = p_strdup(conn->pool, args);
+ return TRUE;
+}
- data = i_stream_get_modifyable_data(conn->input, &size);
- if (size < sizeof(rec))
- return FALSE;
+static int
+auth_client_input_cpid(struct auth_client_connection *conn, const char *args)
+{
+ struct auth_client_connection *old;
+ unsigned int pid;
- /* Don't just cast because of alignment issues. */
- memcpy(&rec, data, sizeof(rec));
- i_stream_skip(conn->input, sizeof(rec));
+ if (conn->pid != 0) {
+ i_error("BUG: Authentication client re-handshaking");
+ return FALSE;
+ }
- if (rec.client_pid == 0) {
- i_error("BUG: Auth client said it's PID 0");
- auth_client_connection_destroy(conn);
+ pid = (unsigned int)strtoul(args, NULL, 10);
+ if (pid == 0) {
+ i_error("BUG: Authentication client said it's PID 0");
return FALSE;
}
- if (auth_client_connection_lookup(conn->master,
- rec.client_pid) != NULL) {
- /* well, it might have just reconnected very fast .. although
- there's not much reason for it. */
- i_error("BUG: Auth client gave a PID %u of existing connection",
- rec.client_pid);
- auth_client_connection_destroy(conn);
+ old = auth_client_connection_lookup(conn->master, pid);
+ if (old != NULL) {
+ /* already exists. it's possible that it just reconnected,
+ see if the old connection is still there. */
+ if (i_stream_read(old->input) == -1) {
+ auth_client_connection_destroy(old);
+ old = NULL;
+ }
+ }
+
+ if (old != NULL) {
+ i_error("BUG: Authentication client gave a PID "
+ "%u of existing connection", pid);
return FALSE;
}
- conn->pid = rec.client_pid;
+ conn->pid = pid;
return TRUE;
}
-static int auth_client_input_request(struct auth_client_connection *conn)
+static int
+auth_client_input_auth(struct auth_client_connection *conn, const char *args)
{
- enum auth_client_request_type type;
- unsigned char *data;
- size_t size;
+ struct mech_module *mech;
+ struct auth_request *request;
+ const char *const *list, *name, *arg, *initial_resp;
+ const void *initial_resp_data;
+ size_t initial_resp_len;
+ unsigned int id;
+ buffer_t *buf;
+ int valid_client_cert;
- data = i_stream_get_modifyable_data(conn->input, &size);
- if (size < sizeof(type))
+ if (conn->pid == 0) {
+ i_error("BUG: Authentication client %u didn't send handshake",
+ conn->pid);
return FALSE;
+ }
- /* note that we can't directly cast the received data pointer into
- structures, as it may not be aligned properly. */
- memcpy(&type, data, sizeof(type));
+ /* <id> <mechanism> [...] */
+ list = t_strsplit(args, "\t");
+ if (list[0] == NULL || list[1] == NULL) {
+ i_error("BUG: Authentication client %u "
+ "sent broken AUTH request", conn->pid);
+ return FALSE;
+ }
- conn->refcount++;
- switch (type) {
- case AUTH_CLIENT_REQUEST_NEW: {
- struct auth_client_request_new request;
+ id = (unsigned int)strtoul(list[0], NULL, 10);
- if (size < sizeof(request))
- return FALSE;
+ mech = mech_module_find(list[1]);
+ if (mech == NULL) {
+ /* unsupported mechanism */
+ i_error("BUG: Authentication client %u requested unsupported "
+ "authentication mechanism %s", conn->pid,
+ str_sanitize(list[1], MAX_MECH_NAME_LEN));
+ return FALSE;
+ }
- memcpy(&request, data, sizeof(request));
- if (size < sizeof(request) + request.data_size)
- return FALSE;
+ request = auth_request_new(mech);
+ if (request == NULL)
+ return TRUE;
- /* we have a full init request */
- conn->refcount++;
- mech_request_new(conn, &request, data + sizeof(request),
- request_callback);
- i_stream_skip(conn->input, sizeof(request) + request.data_size);
- break;
+ request->conn = conn;
+ request->id = id;
+
+ /* parse optional parameters */
+ initial_resp = NULL;
+ valid_client_cert = FALSE;
+ for (list += 2; *list != NULL; list++) {
+ arg = strchr(*list, '=');
+ if (arg == NULL) {
+ name = *list;
+ arg = "";
+ } else {
+ name = t_strdup_until(*list, arg);
+ arg++;
+ }
+
+ if (strcmp(name, "lip") == 0)
+ (void)net_addr2ip(arg, &request->local_ip);
+ else if (strcmp(name, "rip") == 0)
+ (void)net_addr2ip(arg, &request->remote_ip);
+ else if (strcmp(name, "proto") == 0)
+ request->protocol = p_strdup(request->pool, arg);
+ else if (strcmp(name, "resp") == 0)
+ initial_resp = arg;
+ else if (strcmp(name, "valid-client-cert") == 0)
+ valid_client_cert = TRUE;
}
- case AUTH_CLIENT_REQUEST_CONTINUE: {
- struct auth_client_request_continue request;
- if (size < sizeof(request))
- return FALSE;
+ if (request->protocol == NULL)
+ request->protocol = conn->default_protocol;
+ if (request->protocol == NULL) {
+ i_error("BUG: Authentication client %u "
+ "didn't specify protocol in request", conn->pid);
+ auth_request_destroy(request);
+ return FALSE;
+ }
- memcpy(&request, data, sizeof(request));
- if (size < sizeof(request) + request.data_size)
- return FALSE;
+ if (ssl_require_client_cert && !valid_client_cert) {
+ /* we fail without valid certificate */
+ if (verbose) {
+ i_info("ssl-cert-check(%s): "
+ "Client didn't present valid SSL certificate",
+ get_log_prefix(request));
+ }
+ auth_request_destroy(request);
+ auth_client_send(conn, "FAIL\t%u", id);
+ return TRUE;
+ }
- /* we have a full continued request */
- conn->refcount++;
- mech_request_continue(conn, &request, data + sizeof(request),
- request_callback);
+ if (initial_resp == NULL) {
+ initial_resp_data = NULL;
+ initial_resp_len = 0;
+ } else {
+ size_t len = strlen(initial_resp);
+ buf = buffer_create_dynamic(pool_datastack_create(),
+ MAX_BASE64_DECODED_SIZE(len));
+ if (base64_decode(initial_resp, len, NULL, buf) < 0) {
+ if (verbose) {
+ i_info("%s(%s): Invalid base64 data in "
+ "initial response", mech->mech_name,
+ get_log_prefix(request));
+ }
+ auth_request_destroy(request);
+ auth_client_send(conn, "FAIL\t%u\t"
+ "Invalid base64 data in initial response", id);
+ return TRUE;
+ }
+ initial_resp_data = buf->data;
+ initial_resp_len = buf->used;
+ }
+ hash_insert(conn->auth_requests, POINTER_CAST(id), request);
- /* clear any sensitive data from memory */
- safe_memset(data + sizeof(request), 0, request.data_size);
- i_stream_skip(conn->input, sizeof(request) + request.data_size);
- break;
+ /* connection is referenced only until auth_callback is called. */
+ conn->refcount++;
+ mech->auth_initial(request, initial_resp_data, initial_resp_len,
+ auth_callback);
+ return TRUE;
+}
+
+static int
+auth_client_input_cont(struct auth_client_connection *conn, const char *args)
+{
+ struct auth_request *request;
+ const char *data;
+ size_t data_len;
+ buffer_t *buf;
+ unsigned int id;
+
+ data = strchr(args, '\t');
+ if (data++ == NULL) {
+ i_error("BUG: Authentication client %u "
+ "sent broken CONT request", conn->pid);
+ return FALSE;
}
- default:
- /* unknown request */
- i_error("BUG: Auth client %u sent us unknown request type %u",
- conn->pid, type);
- auth_client_connection_destroy(conn);
+
+ id = (unsigned int)strtoul(args, NULL, 10);
+
+ request = hash_lookup(conn->auth_requests, POINTER_CAST(id));
+ if (request == NULL) {
+ /* timeouted */
+ auth_client_send(conn, "FAIL\t%u\tTimeouted", id);
+ return TRUE;
}
- auth_client_connection_unref(conn);
+
+ if (!request->accept_input) {
+ auth_client_send(conn, "FAIL\t%u\tUnexpected continuation", id);
+ auth_request_destroy(request);
+ return TRUE;
+ }
+ request->accept_input = FALSE;
+
+ data_len = strlen(data);
+ buf = buffer_create_dynamic(pool_datastack_create(),
+ MAX_BASE64_DECODED_SIZE(data_len));
+ if (base64_decode(data, data_len, NULL, buf) < 0) {
+ if (verbose) {
+ i_info("%s(%s): Invalid base64 data in "
+ "continued response", request->mech->mech_name,
+ get_log_prefix(request));
+ }
+ auth_client_send(conn, "FAIL\t%u\tInvalid base64 data in "
+ "continued response", id);
+ auth_request_destroy(request);
+ return TRUE;
+ }
+
+ conn->refcount++;
+ request->mech->auth_continue(request, buf->data, buf->used,
+ auth_callback);
return TRUE;
}
static void auth_client_input(void *context)
{
- struct auth_client_connection *conn = context;
+ struct auth_client_connection *conn = context;
+ char *line;
+ int ret;
switch (i_stream_read(conn->input)) {
case 0:
@@ -174,18 +348,35 @@
case -2:
/* buffer full */
i_error("BUG: Auth client %u sent us more than %d bytes",
- conn->pid, (int)MAX_INBUF_SIZE);
+ conn->pid, (int)AUTH_CLIENT_MAX_LINE_LENGTH);
auth_client_connection_destroy(conn);
return;
}
- if (conn->pid == 0) {
- if (!auth_client_input_handshake(conn))
- return;
- }
+ conn->refcount++;
+ while ((line = i_stream_next_line(conn->input)) != NULL) {
+ t_push();
+ if (strncmp(line, "AUTH\t", 5) == 0)
+ ret = auth_client_input_auth(conn, line + 5);
+ else if (strncmp(line, "CONT\t", 5) == 0)
+ ret = auth_client_input_cont(conn, line + 5);
+ else if (strncmp(line, "CPID\t", 5) == 0)
+ ret = auth_client_input_cpid(conn, line + 5);
+ else if (strncmp(line, "PROTO\t", 6) == 0)
+ ret = auth_client_input_proto(conn, line + 6);
+ else {
+ /* ignore unknown command */
+ ret = TRUE;
+ }
+ safe_memset(line, 0, strlen(line));
+ t_pop();
- while (auth_client_input_request(conn))
- ;
+ if (!ret) {
+ auth_client_connection_destroy(conn);
+ break;
+ }
+ }
+ auth_client_connection_unref(conn);
}
struct auth_client_connection *
@@ -193,8 +384,8 @@
{
static unsigned int connect_uid_counter = 0;
struct auth_client_connection *conn;
- struct auth_client_handshake_reply handshake_reply;
struct const_iovec iov[2];
+ string_t *str;
pool_t pool;
@@ -206,7 +397,8 @@
conn->connect_uid = ++connect_uid_counter;
conn->fd = fd;
- conn->input = i_stream_create_file(fd, default_pool, MAX_INBUF_SIZE,
+ conn->input = i_stream_create_file(fd, default_pool,
+ AUTH_CLIENT_MAX_LINE_LENGTH,
FALSE);
conn->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
FALSE);
@@ -218,13 +410,14 @@
conn->next = master->clients;
master->clients = conn;
- handshake_reply = *master->handshake_reply;
- handshake_reply.connect_uid = conn->connect_uid;
+ str = t_str_new(128);
+ str_printfa(str, "SPID\t%u\nCUID\t%u\nDONE\n",
+ master->pid, conn->connect_uid);
- iov[0].iov_base = &handshake_reply;
- iov[0].iov_len = sizeof(handshake_reply);
- iov[1].iov_base = master->handshake_reply + 1;
- iov[1].iov_len = handshake_reply.data_size;
+ iov[0].iov_base = str_data(mech_handshake);
+ iov[0].iov_len = str_len(mech_handshake);
+ iov[1].iov_base = str_data(str);
+ iov[1].iov_len = str_len(str);
if (o_stream_sendv(conn->output, iov, 2) < 0) {
auth_client_connection_destroy(conn);
Index: auth-client-connection.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-client-connection.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- auth-client-connection.h 2 Jul 2004 22:03:37 -0000 1.2
+++ auth-client-connection.h 13 Oct 2004 16:38:32 -0000 1.3
@@ -1,8 +1,6 @@
#ifndef __AUTH_CLIENT_CONNECTION_H
#define __AUTH_CLIENT_CONNECTION_H
-#include "auth-client-interface.h"
-
struct auth_client_connection {
struct auth_client_connection *next;
@@ -16,6 +14,7 @@
pool_t pool;
struct hash_table *auth_requests;
+ char *default_protocol;
unsigned int pid;
unsigned int connect_uid;
Index: auth-client-interface.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-client-interface.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- auth-client-interface.h 2 Sep 2004 19:18:14 -0000 1.8
+++ auth-client-interface.h 13 Oct 2004 16:38:32 -0000 1.9
@@ -1,91 +1,24 @@
#ifndef __AUTH_CLIENT_INTERFACE_H
#define __AUTH_CLIENT_INTERFACE_H
-/* max. size for auth_client_request_continue.data[] */
-#define AUTH_CLIENT_MAX_REQUEST_DATA_SIZE 4096
-
-/* Client process must finish with single authentication requests in this time,
- or the whole connection will be killed. */
+#define AUTH_CLIENT_MAX_LINE_LENGTH 8192
#define AUTH_REQUEST_TIMEOUT 120
-enum auth_client_request_new_flags {
- AUTH_CLIENT_FLAG_SSL_ENABLED = 0x01,
- AUTH_CLIENT_FLAG_SSL_VALID_CLIENT_CERT = 0x02
-};
-
-enum auth_client_request_type {
- AUTH_CLIENT_REQUEST_NEW = 1,
- AUTH_CLIENT_REQUEST_CONTINUE
-};
-
-enum auth_client_result {
- AUTH_CLIENT_RESULT_CONTINUE = 1,
- AUTH_CLIENT_RESULT_SUCCESS,
- AUTH_CLIENT_RESULT_FAILURE
-};
-
-/* Client -> Server */
-struct auth_client_handshake_request {
- unsigned int client_pid; /* unique identifier for client process */
-};
-
-struct auth_client_handshake_mech_desc {
- uint32_t name_idx;
- unsigned int plaintext:1;
- unsigned int advertise:1;
-};
-
-/* Server -> Client */
-struct auth_client_handshake_reply {
- unsigned int server_pid; /* unique auth process identifier */
- unsigned int connect_uid; /* unique connection identifier */
-
- uint32_t mech_count;
- uint32_t data_size;
- /* struct auth_client_handshake_mech_desc mech_desc[auth_mech_count]; */
-};
-
-/* New authentication request */
-struct auth_client_request_new {
- enum auth_client_request_type type; /* AUTH_CLIENT_REQUEST_NEW */
- unsigned int id; /* unique ID for the request */
-
- enum auth_client_request_new_flags flags;
-
- uint32_t ip_family; /* if non-zero, data begins with local/remote IPs */
-
- uint32_t protocol_idx;
- uint32_t mech_idx;
- uint32_t initial_resp_idx;
-
- uint32_t data_size;
- /* unsigned char data[]; */
-};
-#define AUTH_CLIENT_REQUEST_HAVE_INITIAL_RESPONSE(request) \
- ((request)->initial_resp_idx != (request)->data_size)
-
-/* Continue authentication request */
-struct auth_client_request_continue {
- enum auth_client_request_type type; /* AUTH_CLIENT_REQUEST_CONTINUE */
- unsigned int id;
-
- uint32_t data_size;
- /* unsigned char data[]; */
-};
-
-/* Reply to authentication */
-struct auth_client_request_reply {
- unsigned int id;
-
- enum auth_client_result result;
-
- /* variable width data, indexes into data[].
- Ignore if it points outside data_size. */
- uint32_t username_idx; /* NUL-terminated */
- uint32_t reply_idx; /* last, non-NUL terminated */
-
- uint32_t data_size;
- /* unsigned char data[]; */
+enum mech_security_flags {
+ /* Don't advertise this as available SASL mechanism (eg. APOP) */
+ MECH_SEC_PRIVATE = 0x0001,
+ /* Anonymous authentication */
+ MECH_SEC_ANONYMOUS = 0x0002,
+ /* Transfers plaintext passwords */
+ MECH_SEC_PLAINTEXT = 0x0004,
+ /* Subject to passive (dictionary) attack */
+ MECH_SEC_DICTIONARY = 0x0008,
+ /* Subject to active (non-dictionary) attack */
+ MECH_SEC_ACTIVE = 0x0010,
+ /* Provides forward secrecy between sessions */
+ MECH_SEC_FORWARD_SECRECY = 0x0020,
+ /* Provides mutual authentication */
+ MECH_SEC_MUTUAL_AUTH = 0x0040,
};
#endif
Index: auth-master-connection.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-master-connection.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- auth-master-connection.c 8 Oct 2004 17:51:47 -0000 1.11
+++ auth-master-connection.c 13 Oct 2004 16:38:32 -0000 1.12
@@ -3,7 +3,9 @@
#include "common.h"
#include "buffer.h"
#include "hash.h"
+#include "str.h"
#include "ioloop.h"
+#include "istream.h"
#include "ostream.h"
#include "network.h"
#include "mech.h"
@@ -12,12 +14,11 @@
#include "auth-master-connection.h"
#include <unistd.h>
+#include <stdlib.h>
+#define MAX_INBUF_SIZE 1024
#define MAX_OUTBUF_SIZE (1024*50)
-static struct auth_master_reply failure_reply =
-{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
struct auth_listener {
struct auth_master_connection *master;
int client_listener;
@@ -28,164 +29,162 @@
struct master_userdb_request {
struct auth_master_connection *conn;
- unsigned int tag;
+ unsigned int id;
};
static void master_output(void *context);
static void auth_master_connection_close(struct auth_master_connection *conn);
static int auth_master_connection_unref(struct auth_master_connection *conn);
-static size_t reply_add(buffer_t *buf, const char *str)
+static void master_send(struct auth_master_connection *conn,
+ const char *fmt, ...) __attr_format__(2, 3);
+static void master_send(struct auth_master_connection *conn,
+ const char *fmt, ...)
{
- size_t index;
-
- if (str == NULL || *str == '\0')
- return (size_t)-1;
+ va_list args;
+ string_t *str;
- index = buffer_get_used_size(buf) - sizeof(struct auth_master_reply);
- buffer_append(buf, str, strlen(str)+1);
- return index;
+ t_push();
+ va_start(args, fmt);
+ str = t_str_new(256);
+ str_vprintfa(str, fmt, args);
+ str_append_c(str, '\n');
+ (void)o_stream_send(conn->output, str_data(str), str_len(str));
+ va_end(args);
+ t_pop();
}
-static struct auth_master_reply *
-fill_reply(const struct user_data *user, size_t *reply_size)
+static void append_user_reply(string_t *str, const struct user_data *user)
{
- struct auth_master_reply reply, *reply_p;
- buffer_t *buf;
- char *p;
-
- buf = buffer_create_dynamic(pool_datastack_create(),
- sizeof(reply) + 256);
- memset(&reply, 0, sizeof(reply));
- buffer_append(buf, &reply, sizeof(reply));
-
- reply.success = TRUE;
+ const char *p;
- reply.uid = user->uid;
- reply.gid = user->gid;
+ str_append(str, user->virtual_user);
+ str_printfa(str, "%s\tuid=%s\tgid=%s", user->virtual_user,
+ dec2str(user->uid), dec2str(user->gid));
- reply.system_user_idx = reply_add(buf, user->system_user);
- reply.virtual_user_idx = reply_add(buf, user->virtual_user);
- reply.mail_idx = reply_add(buf, user->mail);
+ if (user->system_user != NULL)
+ str_printfa(str, "\tsystem_user=%s", user->system_user);
+ if (user->mail != NULL)
+ str_printfa(str, "\tmail=%s", user->mail);
p = user->home != NULL ? strstr(user->home, "/./") : NULL;
if (p == NULL) {
- reply.home_idx = reply_add(buf, user->home);
- reply.chroot_idx = reply_add(buf, NULL);
+ if (user->home != NULL)
+ str_printfa(str, "\thome=%s", user->home);
} else {
/* wu-ftpd like <chroot>/./<home> */
- reply.chroot_idx =
- reply_add(buf, t_strdup_until(user->home, p));
- reply.home_idx = reply_add(buf, p + 3);
- }
-
- *reply_size = buffer_get_used_size(buf);
- reply.data_size = *reply_size - sizeof(reply);
-
- reply_p = buffer_get_space_unsafe(buf, 0, sizeof(reply));
- *reply_p = reply;
-
- return reply_p;
-}
-
-static void master_send_reply(struct auth_master_connection *conn,
- struct auth_master_reply *reply,
- size_t reply_size, unsigned int tag)
-{
- ssize_t ret;
-
- reply->tag = tag;
-
- ret = o_stream_send(conn->output, reply, reply_size);
- if (ret < 0) {
- /* master died, kill ourself too */
- auth_master_connection_close(conn);
- return;
- }
- i_assert((size_t)ret == reply_size);
-
- if (o_stream_get_buffer_used_size(conn->output) >= MAX_OUTBUF_SIZE) {
- /* buffer full, stop accepting more input */
- if (conn->io != NULL) {
- io_remove(conn->io);
- conn->io = NULL;
- }
+ str_printfa(str, "\thome=%s\tchroot=%s",
+ p + 3, t_strdup_until(user->home, p));
}
}
-static void userdb_callback(struct user_data *user, void *context)
+static void userdb_callback(const struct user_data *user, void *context)
{
struct master_userdb_request *master_request = context;
- struct auth_master_reply *reply;
- size_t reply_size;
+ string_t *str;
if (auth_master_connection_unref(master_request->conn)) {
if (user == NULL) {
- master_send_reply(master_request->conn, &failure_reply,
- sizeof(failure_reply),
- master_request->tag);
+ master_send(master_request->conn, "NOTFOUND\t%u",
+ master_request->id);
} else {
- reply = fill_reply(user, &reply_size);
- master_send_reply(master_request->conn, reply,
- reply_size, master_request->tag);
+ str = t_str_new(256);
+ str_printfa(str, "USER\t%u\t", master_request->id);
+ append_user_reply(str, user);
+ master_send(master_request->conn, "%s", str_c(str));
}
}
i_free(master_request);
}
-static void master_handle_request(struct auth_master_connection *conn,
- struct auth_master_request *request)
+static int
+master_input_request(struct auth_master_connection *conn, const char *args)
{
struct auth_client_connection *client_conn;
- struct auth_request *auth_request;
struct master_userdb_request *master_request;
+ struct auth_request *request;
+ const char *const *list;
+ unsigned int id, client_pid, client_id;
- client_conn = auth_client_connection_lookup(conn, request->client_pid);
- auth_request = client_conn == NULL ? NULL :
+ /* <id> <client-pid> <client-id> */
+ list = t_strsplit(args, "\t");
+ if (list[0] == NULL || list[1] == NULL || list[2] == NULL) {
+ i_error("BUG: Master sent broken REQUEST");
+ return FALSE;
+ }
+
+ id = (unsigned int)strtoul(list[0], NULL, 10);
+ client_pid = (unsigned int)strtoul(list[1], NULL, 10);
+ client_id = (unsigned int)strtoul(list[2], NULL, 10);
+
+ client_conn = auth_client_connection_lookup(conn, client_pid);
+ request = client_conn == NULL ? NULL :
hash_lookup(client_conn->auth_requests,
- POINTER_CAST(request->id));
+ POINTER_CAST(client_id));
- if (auth_request == NULL) {
+ if (request == NULL) {
if (verbose) {
i_info("Master request %u.%u not found",
- request->client_pid, request->id);
+ client_pid, client_id);
}
- master_send_reply(conn, &failure_reply, sizeof(failure_reply),
- request->tag);
+ master_send(conn, "NOTFOUND\t%u", id);
} else {
master_request = i_new(struct master_userdb_request, 1);
master_request->conn = conn;
- master_request->tag = request->tag;
+ master_request->id = id;
conn->refcount++;
- userdb->lookup(auth_request, userdb_callback,
- master_request);
+ userdb->lookup(request, userdb_callback, master_request);
/* the auth request is finished, we don't need it anymore */
- mech_request_free(auth_request, request->id);
+ auth_request_destroy(request);
}
+ return TRUE;
+}
+
+static int
+master_input_die(struct auth_master_connection *conn)
+{
+ return TRUE;
}
static void master_input(void *context)
{
struct auth_master_connection *conn = context;
+ char *line;
int ret;
- ret = net_receive(conn->fd,
- conn->request_buf + conn->request_pos,
- sizeof(conn->request_buf) - conn->request_pos);
- if (ret < 0) {
- /* master died, kill ourself too */
+ switch (i_stream_read(conn->input)) {
+ case 0:
+ return;
+ case -1:
+ /* disconnected */
+ auth_master_connection_close(conn);
+ return;
+ case -2:
+ /* buffer full */
+ i_error("BUG: Master sent us more than %d bytes",
+ (int)MAX_INBUF_SIZE);
auth_master_connection_close(conn);
return;
}
- conn->request_pos += ret;
- if (conn->request_pos >= sizeof(conn->request_buf)) {
- /* reply is now read */
- master_handle_request(conn, (struct auth_master_request *)
- conn->request_buf);
- conn->request_pos = 0;
+ while ((line = i_stream_next_line(conn->input)) != NULL) {
+ t_push();
+ if (strncmp(line, "REQUEST\t", 8) == 0)
+ ret = master_input_request(conn, line + 8);
+ else if (strcmp(line, "DIE") == 0)
+ ret = master_input_die(conn);
+ else {
+ /* ignore unknown command */
+ ret = TRUE;
+ }
+ t_pop();
+
+ if (!ret) {
+ auth_master_connection_close(conn);
+ return;
+ }
}
}
@@ -206,56 +205,18 @@
}
}
-static void master_get_handshake_reply(struct auth_master_connection *master)
-{
- struct mech_module_list *list;
- buffer_t *buf;
- struct auth_client_handshake_reply reply;
- struct auth_client_handshake_mech_desc mech_desc;
- uint32_t mech_desc_offset;
-
- memset(&reply, 0, sizeof(reply));
- memset(&mech_desc, 0, sizeof(mech_desc));
-
- reply.server_pid = master->pid;
-
- buf = buffer_create_dynamic(default_pool, 128);
-
- for (list = mech_modules; list != NULL; list = list->next)
- reply.mech_count++;
- buffer_set_used_size(buf, sizeof(reply) +
- sizeof(mech_desc) * reply.mech_count);
-
- mech_desc_offset = sizeof(reply);
- for (list = mech_modules; list != NULL; list = list->next) {
- mech_desc.name_idx = buffer_get_used_size(buf) - sizeof(reply);
- mech_desc.plaintext = list->module.plaintext;
- mech_desc.advertise = list->module.advertise;
-
- memcpy(buffer_get_space_unsafe(buf, mech_desc_offset,
- sizeof(mech_desc)),
- &mech_desc, sizeof(mech_desc));
- buffer_append(buf, list->module.mech_name,
- strlen(list->module.mech_name) + 1);
-
- mech_desc_offset += sizeof(mech_desc);
- }
-
- reply.data_size = buffer_get_used_size(buf) - sizeof(reply);
- memcpy(buffer_get_space_unsafe(buf, 0, sizeof(reply)),
- &reply, sizeof(reply));
-
- master->handshake_reply = buffer_free_without_data(buf);
-}
-
static void
auth_master_connection_set_fd(struct auth_master_connection *conn, int fd)
{
+ if (conn->input != NULL)
+ i_stream_unref(conn->input);
if (conn->output != NULL)
o_stream_unref(conn->output);
if (conn->io != NULL)
io_remove(conn->io);
+ conn->input = i_stream_create_file(fd, default_pool,
+ MAX_INBUF_SIZE, FALSE);
conn->output = o_stream_create_file(fd, default_pool,
(size_t)-1, FALSE);
o_stream_set_flush_callback(conn->output, master_output, conn);
@@ -276,22 +237,15 @@
conn->listeners_buf = buffer_create_dynamic(default_pool, 64);
if (fd != -1)
auth_master_connection_set_fd(conn, fd);
- master_get_handshake_reply(conn);
return conn;
}
void auth_master_connection_send_handshake(struct auth_master_connection *conn)
{
- struct auth_master_handshake_reply reply;
-
/* just a note to master that we're ok. if we die before, it means
we're broken and a simple restart most likely won't help. */
- if (conn->output != NULL) {
- memset(&reply, 0, sizeof(reply));
- reply.server_pid = conn->pid;
- if (o_stream_send(conn->output, &reply, sizeof(reply)) < 0)
- auth_master_connection_close(conn);
- }
+ if (conn->output != NULL)
+ master_send(conn, "SPID\t%u", conn->pid);
}
static void auth_master_connection_close(struct auth_master_connection *conn)
@@ -350,7 +304,6 @@
if (conn->output != NULL)
o_stream_unref(conn->output);
- i_free(conn->handshake_reply);
i_free(conn);
return FALSE;
}
Index: auth-master-connection.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-master-connection.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- auth-master-connection.h 23 Jun 2004 17:50:44 -0000 1.4
+++ auth-master-connection.h 13 Oct 2004 16:38:32 -0000 1.5
@@ -1,21 +1,16 @@
#ifndef __AUTH_MASTER_CONNECTION_H
#define __AUTH_MASTER_CONNECTION_H
-#include "auth-master-interface.h"
-
struct auth_master_connection {
unsigned int pid;
int refcount;
int fd;
+ struct istream *input;
struct ostream *output;
struct io *io;
buffer_t *listeners_buf;
- unsigned int request_pos;
- unsigned char request_buf[sizeof(struct auth_master_request)];
-
- struct auth_client_handshake_reply *handshake_reply;
struct auth_client_connection *clients;
struct timeout *to_clients;
--- auth-master-interface.h DELETED ---
Index: mech-anonymous.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-anonymous.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- mech-anonymous.c 31 May 2004 18:57:25 -0000 1.5
+++ mech-anonymous.c 13 Oct 2004 16:38:32 -0000 1.6
@@ -1,85 +1,72 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2004 Timo Sirainen */
#include "common.h"
#include "mech.h"
-static int
-mech_anonymous_auth_continue(struct auth_request *auth_request,
+static void
+mech_anonymous_auth_continue(struct auth_request *request,
const unsigned char *data, size_t data_size,
mech_callback_t *callback)
{
i_assert(anonymous_username != NULL);
if (verbose) {
- auth_request->user =
+ /* temporarily set the user to the one that was given,
+ so that the log message goes right */
+ request->user =
p_strndup(pool_datastack_create(), data, data_size);
i_info("anonymous(%s): login",
- get_log_prefix(auth_request));
+ get_log_prefix(request));
}
- auth_request->callback = callback;
- auth_request->user = p_strdup(auth_request->pool, anonymous_username);
+ request->callback = callback;
+ request->user = p_strdup(request->pool, anonymous_username);
- mech_auth_finish(auth_request, NULL, 0, TRUE);
- return TRUE;
+ mech_auth_finish(request, NULL, 0, TRUE);
}
-static int
-mech_anonymous_auth_initial(struct auth_request *auth_request,
- struct auth_client_request_new *request,
- const unsigned char *data,
+static void
+mech_anonymous_auth_initial(struct auth_request *request,
+ const unsigned char *data, size_t data_size,
mech_callback_t *callback)
{
- struct auth_client_request_reply reply;
- size_t data_size;
-
- if (AUTH_CLIENT_REQUEST_HAVE_INITIAL_RESPONSE(request)) {
- data += request->initial_resp_idx;
- data_size = request->data_size - request->initial_resp_idx;
-
- return auth_request->auth_continue(auth_request, data,
- data_size, callback);
+ if (data_size == 0)
+ callback(request, AUTH_CLIENT_RESULT_CONTINUE, NULL, 0);
+ else {
+ mech_anonymous_auth_continue(request, data, data_size,
+ callback);
}
-
- /* initialize reply */
- memset(&reply, 0, sizeof(reply));
- reply.id = auth_request->id;
- reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
- callback(&reply, NULL, auth_request->conn);
- return TRUE;
}
static void
-mech_anonymous_auth_free(struct auth_request *auth_request)
+mech_anonymous_auth_free(struct auth_request *request)
{
- pool_unref(auth_request->pool);
+ pool_unref(request->pool);
}
static struct auth_request *mech_anonymous_auth_new(void)
{
- struct auth_request *auth_request;
+ struct auth_request *request;
pool_t pool;
pool = pool_alloconly_create("anonymous_auth_request", 256);
- auth_request = p_new(pool, struct auth_request, 1);
- auth_request->refcount = 1;
- auth_request->pool = pool;
- auth_request->auth_initial = mech_anonymous_auth_initial;
- auth_request->auth_continue = mech_anonymous_auth_continue;
- auth_request->auth_free = mech_anonymous_auth_free;
+ request = p_new(pool, struct auth_request, 1);
+ request->refcount = 1;
+ request->pool = pool;
- return auth_request;
+ return request;
}
struct mech_module mech_anonymous = {
"ANONYMOUS",
- MEMBER(plaintext) FALSE,
- MEMBER(advertise) TRUE,
+ MEMBER(flags) MECH_SEC_ANONYMOUS,
MEMBER(passdb_need_plain) FALSE,
MEMBER(passdb_need_credentials) FALSE,
- mech_anonymous_auth_new
+ mech_anonymous_auth_new,
+ mech_anonymous_auth_initial,
+ mech_anonymous_auth_continue,
+ mech_anonymous_auth_free
};
Index: mech-apop.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-apop.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- mech-apop.c 15 Sep 2004 13:20:16 -0000 1.5
+++ mech-apop.c 13 Oct 2004 16:38:32 -0000 1.6
@@ -35,7 +35,7 @@
apop_credentials_callback(const char *credentials,
struct auth_request *auth_request)
{
- struct apop_auth_request *auth =
+ struct apop_auth_request *request =
(struct apop_auth_request *)auth_request;
unsigned char digest[16];
struct md5_context ctx;
@@ -43,41 +43,41 @@
if (credentials != NULL) {
md5_init(&ctx);
- md5_update(&ctx, auth->challenge, strlen(auth->challenge));
+ md5_update(&ctx, request->challenge,
+ strlen(request->challenge));
md5_update(&ctx, credentials, strlen(credentials));
md5_final(&ctx, digest);
- ret = memcmp(digest, auth->digest, 16) == 0;
+ ret = memcmp(digest, request->digest, 16) == 0;
}
mech_auth_finish(auth_request, NULL, 0, ret);
}
-static int
+static void
mech_apop_auth_initial(struct auth_request *auth_request,
- struct auth_client_request_new *request,
- const unsigned char *data,
+ const unsigned char *data, size_t data_size,
mech_callback_t *callback)
{
- struct apop_auth_request *auth =
+ struct apop_auth_request *request =
(struct apop_auth_request *)auth_request;
const unsigned char *tmp, *end, *username = NULL;
const char *str, *error;
auth_request->callback = callback;
- if (!AUTH_CLIENT_REQUEST_HAVE_INITIAL_RESPONSE(request)) {
+ if (data_size == 0) {
/* Should never happen */
if (verbose) {
i_info("apop(%s): no initial respone",
get_log_prefix(auth_request));
}
mech_auth_finish(auth_request, NULL, 0, FALSE);
- return TRUE;
+ return;
}
- tmp = data = data + request->initial_resp_idx;
- end = data + request->data_size - request->initial_resp_idx;
+ tmp = data;
+ end = data + data_size;
while (tmp != end && *tmp != '\0')
tmp++;
@@ -93,9 +93,9 @@
get_log_prefix(auth_request));
}
mech_auth_finish(auth_request, NULL, 0, FALSE);
- return TRUE;
+ return;
}
- auth->challenge = p_strdup(auth->pool, (const char *)data);
+ request->challenge = p_strdup(request->pool, (const char *)data);
if (tmp != end) {
username = ++tmp;
@@ -110,58 +110,55 @@
get_log_prefix(auth_request));
}
mech_auth_finish(auth_request, NULL, 0, FALSE);
- return TRUE;
+ return;
}
tmp++;
- auth_request->user = p_strdup(auth->pool, (const char *)username);
+ auth_request->user = p_strdup(request->pool, (const char *)username);
if (!mech_fix_username(auth_request->user, &error)) {
if (verbose) {
i_info("apop(%s): %s",
get_log_prefix(auth_request), error);
}
mech_auth_finish(auth_request, NULL, 0, FALSE);
- return TRUE;
+ return;
}
- memcpy(auth->digest, tmp, sizeof(auth->digest));
+ memcpy(request->digest, tmp, sizeof(request->digest));
passdb->lookup_credentials(auth_request, PASSDB_CREDENTIALS_PLAINTEXT,
apop_credentials_callback);
- return TRUE;
}
-static void mech_apop_auth_free(struct auth_request *auth_request)
+static void mech_apop_auth_free(struct auth_request *request)
{
- pool_unref(auth_request->pool);
+ pool_unref(request->pool);
}
static struct auth_request *mech_apop_auth_new(void)
{
- struct apop_auth_request *auth;
+ struct apop_auth_request *request;
pool_t pool;
pool = pool_alloconly_create("apop_auth_request", 256);
- auth = p_new(pool, struct apop_auth_request, 1);
- auth->pool = pool;
-
- auth->auth_request.refcount = 1;
- auth->auth_request.pool = pool;
- auth->auth_request.auth_initial = mech_apop_auth_initial;
- auth->auth_request.auth_continue = NULL;
- auth->auth_request.auth_free = mech_apop_auth_free;
+ request = p_new(pool, struct apop_auth_request, 1);
+ request->pool = pool;
- return &auth->auth_request;
+ request->auth_request.refcount = 1;
+ request->auth_request.pool = pool;
+ return &request->auth_request;
}
const struct mech_module mech_apop = {
"APOP",
- MEMBER(plaintext) FALSE,
- MEMBER(advertise) FALSE,
+ MEMBER(flags) MECH_SEC_PRIVATE | MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE,
MEMBER(passdb_need_plain) FALSE,
MEMBER(passdb_need_credentials) TRUE,
mech_apop_auth_new,
+ mech_apop_auth_initial,
+ NULL,
+ mech_apop_auth_free
};
Index: mech-cram-md5.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-cram-md5.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- mech-cram-md5.c 8 Oct 2004 17:51:47 -0000 1.12
+++ mech-cram-md5.c 13 Oct 2004 16:38:32 -0000 1.13
@@ -42,11 +42,11 @@
buf[i] = (buf[i] % 10) + '0';
buf[sizeof(buf)-1] = '\0';
- return t_strdup_printf("<%s.%s@%s>", (const char *) buf,
+ return t_strdup_printf("<%s.%s@%s>", (const char *)buf,
dec2str(ioloop_time), my_hostname);
}
-static int verify_credentials(struct cram_auth_request *auth,
+static int verify_credentials(struct cram_auth_request *request,
const char *credentials)
{
@@ -66,15 +66,15 @@
return FALSE;
hmac_md5_set_cram_context(&ctx, context_digest);
- hmac_md5_update(&ctx, auth->challenge, strlen(auth->challenge));
+ hmac_md5_update(&ctx, request->challenge, strlen(request->challenge));
hmac_md5_final(&ctx, digest);
response_hex = binary_to_hex(digest, 16);
- if (memcmp(response_hex, auth->response, 32) != 0) {
+ if (memcmp(response_hex, request->response, 32) != 0) {
if (verbose) {
i_info("cram-md5(%s): password mismatch",
- get_log_prefix(&auth->auth_request));
+ get_log_prefix(&request->auth_request));
}
return FALSE;
}
@@ -82,7 +82,7 @@
return TRUE;
}
-static int parse_cram_response(struct cram_auth_request *auth,
+static int parse_cram_response(struct cram_auth_request *request,
const unsigned char *data, size_t size,
const char **error_r)
{
@@ -102,126 +102,106 @@
return FALSE;
}
- auth->username = p_strndup(auth->pool, data, space);
+ request->username = p_strndup(request->pool, data, space);
space++;
- auth->response = p_strndup(auth->pool, data + space, size - space);
+ request->response =
+ p_strndup(request->pool, data + space, size - space);
return TRUE;
}
static void credentials_callback(const char *result,
- struct auth_request *request)
+ struct auth_request *auth_request)
{
- struct cram_auth_request *auth =
- (struct cram_auth_request *) request;
+ struct cram_auth_request *request =
+ (struct cram_auth_request *)auth_request;
- if (verify_credentials(auth, result))
- mech_auth_finish(request, NULL, 0, TRUE);
+ if (verify_credentials(request, result))
+ mech_auth_finish(auth_request, NULL, 0, TRUE);
else {
if (verbose) {
i_info("cram-md5(%s): authentication failed",
- get_log_prefix(&auth->auth_request));
+ get_log_prefix(auth_request));
}
- mech_auth_finish(request, NULL, 0, FALSE);
+ mech_auth_finish(auth_request, NULL, 0, FALSE);
}
}
-static int
+static void
mech_cram_md5_auth_continue(struct auth_request *auth_request,
const unsigned char *data, size_t data_size,
mech_callback_t *callback)
{
- struct cram_auth_request *auth =
+ struct cram_auth_request *request =
(struct cram_auth_request *)auth_request;
const char *error;
- if (parse_cram_response(auth, data, data_size, &error)) {
+ if (parse_cram_response(request, data, data_size, &error)) {
auth_request->callback = callback;
auth_request->user =
- p_strdup(auth_request->pool, auth->username);
+ p_strdup(auth_request->pool, request->username);
if (mech_fix_username(auth_request->user, &error)) {
- passdb->lookup_credentials(&auth->auth_request,
+ passdb->lookup_credentials(auth_request,
PASSDB_CREDENTIALS_CRAM_MD5,
credentials_callback);
- return TRUE;
+ return;
}
}
if (error == NULL)
error = "authentication failed";
- if (verbose) {
- i_info("cram-md5(%s): %s",
- get_log_prefix(&auth->auth_request), error);
- }
+ if (verbose)
+ i_info("cram-md5(%s): %s", get_log_prefix(auth_request), error);
/* failed */
mech_auth_finish(auth_request, NULL, 0, FALSE);
- return FALSE;
}
-static int
+static void
mech_cram_md5_auth_initial(struct auth_request *auth_request,
- struct auth_client_request_new *request,
const unsigned char *data __attr_unused__,
+ size_t data_size __attr_unused__,
mech_callback_t *callback)
{
- struct cram_auth_request *auth =
+ struct cram_auth_request *request =
(struct cram_auth_request *)auth_request;
- struct auth_client_request_reply reply;
-
- if (AUTH_CLIENT_REQUEST_HAVE_INITIAL_RESPONSE(request)) {
- /* No initial response in CRAM-MD5 */
- return FALSE;
- }
-
- auth->challenge = p_strdup(auth->pool, get_cram_challenge());
-
- /* initialize reply */
- mech_init_auth_client_reply(&reply);
- reply.id = request->id;
- reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
- /* send the initial challenge */
- reply.reply_idx = 0;
- reply.data_size = strlen(auth->challenge);
- callback(&reply, auth->challenge, auth_request->conn);
- return TRUE;
+ request->challenge = p_strdup(request->pool, get_cram_challenge());
+ callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE,
+ request->challenge, strlen(request->challenge));
}
-static void mech_cram_md5_auth_free(struct auth_request *auth_request)
+static void mech_cram_md5_auth_free(struct auth_request *request)
{
- pool_unref(auth_request->pool);
+ pool_unref(request->pool);
}
static struct auth_request *mech_cram_md5_auth_new(void)
{
- struct cram_auth_request *auth;
+ struct cram_auth_request *request;
pool_t pool;
pool = pool_alloconly_create("cram_md5_auth_request", 2048);
- auth = p_new(pool, struct cram_auth_request, 1);
- auth->pool = pool;
-
- auth->auth_request.refcount = 1;
- auth->auth_request.pool = pool;
- auth->auth_request.auth_initial = mech_cram_md5_auth_initial;
- auth->auth_request.auth_continue = mech_cram_md5_auth_continue;
- auth->auth_request.auth_free = mech_cram_md5_auth_free;
+ request = p_new(pool, struct cram_auth_request, 1);
+ request->pool = pool;
- return &auth->auth_request;
+ request->auth_request.refcount = 1;
+ request->auth_request.pool = pool;
+ return &request->auth_request;
}
struct mech_module mech_cram_md5 = {
"CRAM-MD5",
- MEMBER(plaintext) FALSE,
- MEMBER(advertise) TRUE,
+ MEMBER(flags) MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE,
MEMBER(passdb_need_plain) FALSE,
MEMBER(passdb_need_credentials) TRUE,
- mech_cram_md5_auth_new
+ mech_cram_md5_auth_new,
+ mech_cram_md5_auth_initial,
+ mech_cram_md5_auth_continue,
+ mech_cram_md5_auth_free
};
Index: mech-digest-md5.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-digest-md5.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- mech-digest-md5.c 8 Oct 2004 17:51:47 -0000 1.25
+++ mech-digest-md5.c 13 Oct 2004 16:38:32 -0000 1.26
@@ -52,7 +52,7 @@
char *rspauth;
};
-static string_t *get_digest_challenge(struct digest_auth_request *auth)
+static string_t *get_digest_challenge(struct digest_auth_request *request)
{
buffer_t *buf;
string_t *str;
@@ -79,7 +79,7 @@
base64_encode(nonce, sizeof(nonce), buf);
buffer_append_c(buf, '\0');
- auth->nonce = p_strdup(auth->pool, buffer_get_data(buf, NULL));
+ request->nonce = p_strdup(request->pool, buffer_get_data(buf, NULL));
t_pop();
str = t_str_new(256);
@@ -89,11 +89,11 @@
str_append_c(str, ',');
}
- str_printfa(str, "nonce=\"%s\",", auth->nonce);
+ str_printfa(str, "nonce=\"%s\",", request->nonce);
str_append(str, "qop=\""); first_qop = TRUE;
for (i = 0; i < QOP_COUNT; i++) {
- if (auth->qop & (1 << i)) {
+ if (request->qop & (1 << i)) {
if (first_qop)
first_qop = FALSE;
else
@@ -108,7 +108,7 @@
return str;
}
-static int verify_credentials(struct digest_auth_request *auth,
+static int verify_credentials(struct digest_auth_request *request,
const char *credentials)
{
struct md5_context ctx;
@@ -151,9 +151,9 @@
md5_init(&ctx);
md5_update(&ctx, digest, 16);
md5_update(&ctx, ":", 1);
- md5_update(&ctx, auth->nonce, strlen(auth->nonce));
+ md5_update(&ctx, request->nonce, strlen(request->nonce));
md5_update(&ctx, ":", 1);
- md5_update(&ctx, auth->cnonce, strlen(auth->cnonce));
+ md5_update(&ctx, request->cnonce, strlen(request->cnonce));
md5_final(&ctx, digest);
a1_hex = binary_to_hex(digest, 16);
@@ -167,11 +167,12 @@
else
md5_update(&ctx, ":", 1);
- if (auth->digest_uri != NULL) {
- md5_update(&ctx, auth->digest_uri,
- strlen(auth->digest_uri));
+ if (request->digest_uri != NULL) {
+ md5_update(&ctx, request->digest_uri,
+ strlen(request->digest_uri));
}
- if (auth->qop == QOP_AUTH_INT || auth->qop == QOP_AUTH_CONF) {
+ if (request->qop == QOP_AUTH_INT ||
+ request->qop == QOP_AUTH_CONF) {
md5_update(&ctx, ":00000000000000000000000000000000",
33);
}
@@ -182,13 +183,15 @@
md5_init(&ctx);
md5_update(&ctx, a1_hex, 32);
md5_update(&ctx, ":", 1);
- md5_update(&ctx, auth->nonce, strlen(auth->nonce));
+ md5_update(&ctx, request->nonce, strlen(request->nonce));
md5_update(&ctx, ":", 1);
- md5_update(&ctx, auth->nonce_count, strlen(auth->nonce_count));
+ md5_update(&ctx, request->nonce_count,
+ strlen(request->nonce_count));
md5_update(&ctx, ":", 1);
- md5_update(&ctx, auth->cnonce, strlen(auth->cnonce));
+ md5_update(&ctx, request->cnonce, strlen(request->cnonce));
md5_update(&ctx, ":", 1);
- md5_update(&ctx, auth->qop_value, strlen(auth->qop_value));
+ md5_update(&ctx, request->qop_value,
+ strlen(request->qop_value));
md5_update(&ctx, ":", 1);
md5_update(&ctx, a2_hex, 32);
md5_final(&ctx, digest);
@@ -196,10 +199,10 @@
if (i == 0) {
/* verify response */
- if (memcmp(response_hex, auth->response, 32) != 0) {
+ if (memcmp(response_hex, request->response, 32) != 0) {
if (verbose) {
struct auth_request *auth_request =
- &auth->auth_request;
+ &request->auth_request;
i_info("digest-md5(%s): "
"password mismatch",
get_log_prefix(auth_request));
@@ -207,8 +210,9 @@
return FALSE;
}
} else {
- auth->rspauth = p_strconcat(auth->pool, "rspauth=",
- response_hex, NULL);
+ request->rspauth =
+ p_strconcat(request->pool, "rspauth=",
+ response_hex, NULL);
}
}
@@ -283,7 +287,7 @@
return TRUE;
}
-static int auth_handle_response(struct digest_auth_request *auth,
+static int auth_handle_response(struct digest_auth_request *request,
char *key, char *value, const char **error)
{
int i;
@@ -295,13 +299,13 @@
*error = "Invalid realm";
return FALSE;
}
- if (auth->realm == NULL && *value != '\0')
- auth->realm = p_strdup(auth->pool, value);
+ if (request->realm == NULL && *value != '\0')
+ request->realm = p_strdup(request->pool, value);
return TRUE;
}
if (strcmp(key, "username") == 0) {
- if (auth->username != NULL) {
+ if (request->username != NULL) {
*error = "username must not exist more than once";
return FALSE;
}
@@ -311,23 +315,23 @@
return FALSE;
}
- auth->username = p_strdup(auth->pool, value);
+ request->username = p_strdup(request->pool, value);
return TRUE;
}
if (strcmp(key, "nonce") == 0) {
/* nonce must be same */
- if (strcmp(value, auth->nonce) != 0) {
+ if (strcmp(value, request->nonce) != 0) {
*error = "Invalid nonce";
return FALSE;
}
- auth->nonce_found = TRUE;
+ request->nonce_found = TRUE;
return TRUE;
}
if (strcmp(key, "cnonce") == 0) {
- if (auth->cnonce != NULL) {
+ if (request->cnonce != NULL) {
*error = "cnonce must not exist more than once";
return FALSE;
}
@@ -337,12 +341,12 @@
return FALSE;
}
- auth->cnonce = p_strdup(auth->pool, value);
+ request->cnonce = p_strdup(request->pool, value);
return TRUE;
}
if (strcmp(key, "nonce-count") == 0) {
- if (auth->nonce_count != NULL) {
+ if (request->nonce_count != NULL) {
*error = "nonce-count must not exist more than once";
return FALSE;
}
@@ -352,7 +356,7 @@
return FALSE;
}
- auth->nonce_count = p_strdup(auth->pool, value);
+ request->nonce_count = p_strdup(request->pool, value);
return TRUE;
}
@@ -367,13 +371,13 @@
return FALSE;
}
- auth->qop &= (1 << i);
- if (auth->qop == 0) {
+ request->qop &= (1 << i);
+ if (request->qop == 0) {
*error = "Nonallowed QoP requested";
return FALSE;
}
- auth->qop_value = p_strdup(auth->pool, value);
+ request->qop_value = p_strdup(request->pool, value);
return TRUE;
}
@@ -390,18 +394,18 @@
But isn't the realm enough already? That'd be just extra
configuration.. Maybe optionally list valid hosts in
config file? */
- auth->digest_uri = p_strdup(auth->pool, value);
+ request->digest_uri = p_strdup(request->pool, value);
return TRUE;
}
if (strcmp(key, "maxbuf") == 0) {
- if (auth->maxbuf != 0) {
+ if (request->maxbuf != 0) {
*error = "maxbuf must not exist more than once";
return FALSE;
}
- auth->maxbuf = strtoul(value, NULL, 10);
- if (auth->maxbuf == 0) {
+ request->maxbuf = strtoul(value, NULL, 10);
+ if (request->maxbuf == 0) {
*error = "Invalid maxbuf value";
return FALSE;
}
@@ -423,7 +427,7 @@
return FALSE;
}
- memcpy(auth->response, value, 32);
+ memcpy(request->response, value, 32);
return TRUE;
}
@@ -441,7 +445,7 @@
return TRUE;
}
-static int parse_digest_response(struct digest_auth_request *auth,
+static int parse_digest_response(struct digest_auth_request *request,
const unsigned char *data, size_t size,
const char **error)
{
@@ -471,7 +475,7 @@
copy = t_strdup_noconst(t_strndup(data, size));
while (*copy != '\0') {
if (parse_next(©, &key, &value)) {
- if (!auth_handle_response(auth, key, value, error)) {
+ if (!auth_handle_response(request, key, value, error)) {
failed = TRUE;
break;
}
@@ -482,22 +486,22 @@
}
if (!failed) {
- if (!auth->nonce_found) {
+ if (!request->nonce_found) {
*error = "Missing nonce parameter";
failed = TRUE;
- } else if (auth->cnonce == NULL) {
+ } else if (request->cnonce == NULL) {
*error = "Missing cnonce parameter";
failed = TRUE;
- } else if (auth->username == NULL) {
+ } else if (request->username == NULL) {
*error = "Missing username parameter";
failed = TRUE;
}
}
- if (auth->nonce_count == NULL)
- auth->nonce_count = p_strdup(auth->pool, "00000001");
- if (auth->qop_value == NULL)
- auth->qop_value = p_strdup(auth->pool, "auth");
+ if (request->nonce_count == NULL)
+ request->nonce_count = p_strdup(request->pool, "00000001");
+ if (request->qop_value == NULL)
+ request->qop_value = p_strdup(request->pool, "auth");
t_pop();
@@ -505,148 +509,118 @@
}
static void credentials_callback(const char *result,
- struct auth_request *request)
+ struct auth_request *auth_request)
{
- struct digest_auth_request *auth =
- (struct digest_auth_request *) request;
- struct auth_client_request_reply reply;
+ struct digest_auth_request *request =
+ (struct digest_auth_request *)auth_request;
- if (!verify_credentials(auth, result)) {
- mech_auth_finish(request, NULL, 0, FALSE);
+ if (!verify_credentials(request, result)) {
+ mech_auth_finish(auth_request, NULL, 0, FALSE);
return;
}
- mech_init_auth_client_reply(&reply);
- reply.id = request->id;
- reply.result = AUTH_CLIENT_RESULT_CONTINUE;
- reply.data_size = strlen(auth->rspauth);
- auth->authenticated = TRUE;
-
- request->callback(&reply, auth->rspauth, request->conn);
+ auth_request->callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE,
+ request->rspauth, strlen(request->rspauth));
}
-static int
+static void
mech_digest_md5_auth_continue(struct auth_request *auth_request,
const unsigned char *data, size_t data_size,
mech_callback_t *callback)
{
- struct digest_auth_request *auth =
+ struct digest_auth_request *request =
(struct digest_auth_request *)auth_request;
- struct auth_client_request_reply reply;
const char *error, *realm;
- /* initialize reply */
- mech_init_auth_client_reply(&reply);
- reply.id = auth_request->id;
-
- if (auth->authenticated) {
+ if (request->authenticated) {
/* authentication is done, we were just waiting the last
word from client */
mech_auth_finish(auth_request, NULL, 0, TRUE);
- return TRUE;
+ return;
}
- if (parse_digest_response(auth, data, data_size, &error)) {
+ if (parse_digest_response(request, data, data_size, &error)) {
auth_request->callback = callback;
- realm = auth->realm != NULL ? auth->realm : default_realm;
+ realm = request->realm != NULL ? request->realm : default_realm;
if (realm == NULL) {
auth_request->user = p_strdup(auth_request->pool,
- auth->username);
+ request->username);
} else {
auth_request->user = p_strconcat(auth_request->pool,
- auth->username, "@",
+ request->username, "@",
realm, NULL);
}
if (mech_fix_username(auth_request->user, &error)) {
- passdb->lookup_credentials(&auth->auth_request,
+ passdb->lookup_credentials(auth_request,
PASSDB_CREDENTIALS_DIGEST_MD5,
credentials_callback);
- return TRUE;
+ return;
}
}
- if (error == NULL)
- error = "Authentication failed";
- else if (verbose) {
+ if (verbose && error != NULL) {
i_info("digest-md5(%s): %s",
get_log_prefix(auth_request), error);
}
- /* failed */
- reply.result = AUTH_CLIENT_RESULT_FAILURE;
- reply.data_size = strlen(error)+1;
- callback(&reply, error, auth_request->conn);
- return FALSE;
+ mech_auth_finish(auth_request, NULL, 0, FALSE);
}
-static int
+static void
mech_digest_md5_auth_initial(struct auth_request *auth_request,
- struct auth_client_request_new *request,
- const unsigned char *data __attr_unused__,
+ const unsigned char *data, size_t data_size,
mech_callback_t *callback)
{
- struct digest_auth_request *auth =
+ struct digest_auth_request *request =
(struct digest_auth_request *)auth_request;
- struct auth_client_request_reply reply;
string_t *challenge;
- size_t data_size;
- if (AUTH_CLIENT_REQUEST_HAVE_INITIAL_RESPONSE(request)) {
+ if (data_size > 0) {
/* FIXME: support subsequent authentication? */
- data += request->initial_resp_idx;
- data_size = request->data_size - request->initial_resp_idx;
-
- return auth_request->auth_continue(auth_request, data,
- data_size, callback);
+ mech_digest_md5_auth_continue(auth_request, data, data_size,
+ callback);
+ return;
}
- /* initialize reply */
- mech_init_auth_client_reply(&reply);
- reply.id = request->id;
- reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
- /* send the initial challenge */
- reply.reply_idx = 0;
- challenge = get_digest_challenge(auth);
- reply.data_size = str_len(challenge);
- callback(&reply, str_data(challenge), auth_request->conn);
- return TRUE;
+ challenge = get_digest_challenge(request);
+ callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE,
+ str_data(challenge), str_len(challenge));
}
-static void mech_digest_md5_auth_free(struct auth_request *auth_request)
+static void mech_digest_md5_auth_free(struct auth_request *request)
{
- pool_unref(auth_request->pool);
+ pool_unref(request->pool);
}
static struct auth_request *
mech_digest_md5_auth_new(void)
{
- struct digest_auth_request *auth;
+ struct digest_auth_request *request;
pool_t pool;
pool = pool_alloconly_create("digest_md5_auth_request", 2048);
- auth = p_new(pool, struct digest_auth_request, 1);
- auth->pool = pool;
+ request = p_new(pool, struct digest_auth_request, 1);
+ request->pool = pool;
- auth->auth_request.refcount = 1;
- auth->auth_request.pool = pool;
- auth->auth_request.auth_initial = mech_digest_md5_auth_initial;
- auth->auth_request.auth_continue = mech_digest_md5_auth_continue;
- auth->auth_request.auth_free = mech_digest_md5_auth_free;
- auth->qop = QOP_AUTH;
- return &auth->auth_request;
+ request->auth_request.refcount = 1;
+ request->auth_request.pool = pool;
+ request->qop = QOP_AUTH;
+ return &request->auth_request;
}
struct mech_module mech_digest_md5 = {
"DIGEST-MD5",
- MEMBER(plaintext) FALSE,
- MEMBER(advertise) TRUE,
+ MEMBER(flags) MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE |
+ MECH_SEC_MUTUAL_AUTH,
MEMBER(passdb_need_plain) FALSE,
MEMBER(passdb_need_credentials) TRUE,
- mech_digest_md5_auth_new
+ mech_digest_md5_auth_new,
+ mech_digest_md5_auth_initial,
+ mech_digest_md5_auth_continue,
+ mech_digest_md5_auth_free
};
Index: mech-login.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-login.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- mech-login.c 31 Aug 2004 09:31:18 -0000 1.3
+++ mech-login.c 13 Oct 2004 16:38:32 -0000 1.4
@@ -20,98 +20,77 @@
mech_auth_finish(request, NULL, 0, result == PASSDB_RESULT_OK);
}
-static int
-mech_login_auth_continue(struct auth_request *auth_request,
+static void
+mech_login_auth_continue(struct auth_request *request,
const unsigned char *data, size_t data_size,
mech_callback_t *callback)
{
- struct auth_client_request_reply reply;
static const char prompt2[] = "Password:";
const char *error;
- auth_request->callback = callback;
+ request->callback = callback;
- if (!auth_request->user) {
- auth_request->user =
- p_strndup(auth_request->pool, data, data_size);
+ if (request->user == NULL) {
+ request->user = p_strndup(request->pool, data, data_size);
- if (!mech_fix_username(auth_request->user, &error)) {
+ if (!mech_fix_username(request->user, &error)) {
if (verbose) {
i_info("login(%s): %s",
- get_log_prefix(auth_request), error);
+ get_log_prefix(request), error);
}
- mech_auth_finish(auth_request, NULL, 0, FALSE);
- return TRUE;
+ mech_auth_finish(request, NULL, 0, FALSE);
+ return;
}
- mech_init_auth_client_reply(&reply);
- reply.id = auth_request->id;
- reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
- reply.reply_idx = 0;
- reply.data_size = strlen(prompt2);
- callback(&reply, prompt2, auth_request->conn);
+ callback(request, AUTH_CLIENT_RESULT_CONTINUE,
+ prompt2, strlen(prompt2));
} else {
char *pass = p_strndup(unsafe_data_stack_pool, data, data_size);
-
- passdb->verify_plain(auth_request, pass, verify_callback);
-
+ passdb->verify_plain(request, pass, verify_callback);
safe_memset(pass, 0, strlen(pass));
}
-
- return TRUE;
}
-static int
-mech_login_auth_initial(struct auth_request *auth_request,
- struct auth_client_request_new *request,
- const unsigned char *data __attr_unused__,
- mech_callback_t *callback)
+static void
+mech_login_auth_initial(struct auth_request *request,
+ const unsigned char *data __attr_unused__,
+ size_t data_size __attr_unused__,
+ mech_callback_t *callback)
{
- struct auth_client_request_reply reply;
static const char prompt1[] = "Username:";
- mech_init_auth_client_reply(&reply);
- reply.id = request->id;
- reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
- reply.reply_idx = 0;
- reply.data_size = strlen(prompt1);
- callback(&reply, prompt1, auth_request->conn);
-
- return TRUE;
+ callback(request, AUTH_CLIENT_RESULT_CONTINUE,
+ prompt1, strlen(prompt1));
}
-static void mech_login_auth_free(struct auth_request *auth_request)
+static void mech_login_auth_free(struct auth_request *request)
{
- pool_unref(auth_request->pool);
+ pool_unref(request->pool);
}
static struct auth_request *mech_login_auth_new(void)
{
- struct auth_request *auth;
+ struct auth_request *request;
pool_t pool;
pool = pool_alloconly_create("login_auth_request", 256);
- auth = p_new(pool, struct auth_request, 1);
-
- auth->refcount = 1;
- auth->pool = pool;
- auth->auth_initial = mech_login_auth_initial;
- auth->auth_continue = mech_login_auth_continue;
- auth->auth_free = mech_login_auth_free;
+ request = p_new(pool, struct auth_request, 1);
- return auth;
+ request->refcount = 1;
+ request->pool = pool;
+ return request;
}
const struct mech_module mech_login = {
"LOGIN",
- MEMBER(plaintext) TRUE,
- MEMBER(advertise) TRUE,
+ MEMBER(flags) MECH_SEC_PLAINTEXT,
MEMBER(passdb_need_plain) TRUE,
MEMBER(passdb_need_credentials) FALSE,
mech_login_auth_new,
+ mech_login_auth_initial,
+ mech_login_auth_continue,
+ mech_login_auth_free
};
Index: mech-ntlm.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-ntlm.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- mech-ntlm.c 7 Oct 2004 19:37:27 -0000 1.6
+++ mech-ntlm.c 13 Oct 2004 16:38:32 -0000 1.7
@@ -36,7 +36,7 @@
lm_credentials_callback(const char *credentials,
struct auth_request *auth_request)
{
- struct ntlm_auth_request *auth =
+ struct ntlm_auth_request *request =
(struct ntlm_auth_request *)auth_request;
const unsigned char *client_response;
unsigned char lm_response[LM_RESPONSE_SIZE];
@@ -53,9 +53,9 @@
hash, sizeof(hash));
hex_to_binary(credentials, hash_buffer);
- client_response = ntlmssp_buffer_data(auth->response, lm_response);
+ client_response = ntlmssp_buffer_data(request->response, lm_response);
- ntlmssp_v1_response(hash, auth->challenge, lm_response);
+ ntlmssp_v1_response(hash, request->challenge, lm_response);
ret = memcmp(lm_response, client_response, LM_RESPONSE_SIZE) == 0;
@@ -66,7 +66,7 @@
ntlm_credentials_callback(const char *credentials,
struct auth_request *auth_request)
{
- struct ntlm_auth_request *auth =
+ struct ntlm_auth_request *request =
(struct ntlm_auth_request *)auth_request;
const unsigned char *client_response;
unsigned char hash[NTLMSSP_HASH_SIZE];
@@ -74,7 +74,7 @@
buffer_t *hash_buffer;
int ret;
- if (credentials == NULL && !auth->ntlm2_negotiated) {
+ if (credentials == NULL && !request->ntlm2_negotiated) {
passdb->lookup_credentials(auth_request,
PASSDB_CREDENTIALS_LANMAN,
lm_credentials_callback);
@@ -85,8 +85,9 @@
hash, sizeof(hash));
hex_to_binary(credentials, hash_buffer);
- response_length = ntlmssp_buffer_length(auth->response, ntlm_response);
- client_response = ntlmssp_buffer_data(auth->response, ntlm_response);
+ response_length =
+ ntlmssp_buffer_length(request->response, ntlm_response);
+ client_response = ntlmssp_buffer_data(request->response, ntlm_response);
if (response_length > NTLMSSP_RESPONSE_SIZE) {
unsigned char ntlm_v2_response[NTLMSSP_V2_RESPONSE_SIZE];
@@ -98,7 +99,7 @@
* as a standalone server, not as NT domain member.
*/
ntlmssp_v2_response(auth_request->user, NULL,
- hash, auth->challenge, blob,
+ hash, request->challenge, blob,
response_length - NTLMSSP_V2_RESPONSE_SIZE,
ntlm_v2_response);
@@ -107,14 +108,14 @@
} else {
unsigned char ntlm_response[NTLMSSP_RESPONSE_SIZE];
const unsigned char *client_lm_response =
- ntlmssp_buffer_data(auth->response, lm_response);
+ ntlmssp_buffer_data(request->response, lm_response);
- if (auth->ntlm2_negotiated)
- ntlmssp2_response(hash, auth->challenge,
+ if (request->ntlm2_negotiated)
+ ntlmssp2_response(hash, request->challenge,
client_lm_response,
ntlm_response);
else
- ntlmssp_v1_response(hash, auth->challenge,
+ ntlmssp_v1_response(hash, request->challenge,
ntlm_response);
ret = memcmp(ntlm_response, client_response,
@@ -124,47 +125,42 @@
mech_auth_finish(auth_request, NULL, 0, ret);
}
-static int
+static void
mech_ntlm_auth_continue(struct auth_request *auth_request,
const unsigned char *data, size_t data_size,
mech_callback_t *callback)
{
- struct ntlm_auth_request *auth =
+ struct ntlm_auth_request *request =
(struct ntlm_auth_request *)auth_request;
- struct auth_client_request_reply reply;
const char *error;
auth_request->callback = callback;
- if (!auth->challenge) {
- const struct ntlmssp_request *request =
+ if (!request->challenge) {
+ const struct ntlmssp_request *ntlm_request =
(struct ntlmssp_request *)data;
const struct ntlmssp_challenge *message;
size_t message_size;
- if (!ntlmssp_check_request(request, data_size, &error)) {
+ if (!ntlmssp_check_request(ntlm_request, data_size, &error)) {
if (verbose) {
i_info("ntlm(%s): invalid NTLM request, %s",
get_log_prefix(auth_request),
error);
}
mech_auth_finish(auth_request, NULL, 0, FALSE);
- return TRUE;
+ return;
}
- message = ntlmssp_create_challenge(auth->pool, request,
+ message = ntlmssp_create_challenge(request->pool, ntlm_request,
&message_size);
- auth->ntlm2_negotiated =
+ request->ntlm2_negotiated =
read_le32(&message->flags) & NTLMSSP_NEGOTIATE_NTLM2;
- auth->challenge = message->challenge;
-
- mech_init_auth_client_reply(&reply);
- reply.id = auth_request->id;
- reply.result = AUTH_CLIENT_RESULT_CONTINUE;
+ request->challenge = message->challenge;
- reply.reply_idx = 0;
- reply.data_size = message_size;
- callback(&reply, message, auth_request->conn);
+ auth_request->callback(auth_request,
+ AUTH_CLIENT_RESULT_CONTINUE,
+ message, message_size);
} else {
const struct ntlmssp_response *response =
(struct ntlmssp_response *)data;
@@ -177,14 +173,14 @@
error);
}
mech_auth_finish(auth_request, NULL, 0, FALSE);
- return TRUE;
+ return;
}
- auth->response = p_malloc(auth->pool, data_size);
- memcpy(auth->response, response, data_size);
+ request->response = p_malloc(request->pool, data_size);
+ memcpy(request->response, response, data_size);
username = p_strdup(auth_request->pool,
- ntlmssp_t_str(auth->response, user));
+ ntlmssp_t_str(request->response, user));
if (!mech_fix_username(username, &error)) {
if (verbose) {
@@ -192,70 +188,55 @@
get_log_prefix(auth_request), error);
}
mech_auth_finish(auth_request, NULL, 0, FALSE);
- return TRUE;
+ return;
}
auth_request->user = username;
-
passdb->lookup_credentials(auth_request,
PASSDB_CREDENTIALS_NTLM,
ntlm_credentials_callback);
}
-
- return TRUE;
}
-static int
+static void
mech_ntlm_auth_initial(struct auth_request *auth_request,
- struct auth_client_request_new *request,
const unsigned char *data __attr_unused__,
+ size_t data_size __attr_unused__,
mech_callback_t *callback)
{
- struct auth_client_request_reply reply;
-
- mech_init_auth_client_reply(&reply);
- reply.id = request->id;
- reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
- reply.reply_idx = 0;
- reply.data_size = 0;
- callback(&reply, "", auth_request->conn);
-
- return TRUE;
+ callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE, NULL, 0);
}
static void
-mech_ntlm_auth_free(struct auth_request *auth_request)
+mech_ntlm_auth_free(struct auth_request *request)
{
- pool_unref(auth_request->pool);
+ pool_unref(request->pool);
}
static struct auth_request *mech_ntlm_auth_new(void)
{
- struct ntlm_auth_request *auth;
+ struct ntlm_auth_request *request;
pool_t pool;
pool = pool_alloconly_create("ntlm_auth_request", 256);
- auth = p_new(pool, struct ntlm_auth_request, 1);
- auth->pool = pool;
-
- auth->auth_request.refcount = 1;
- auth->auth_request.pool = pool;
- auth->auth_request.auth_initial = mech_ntlm_auth_initial;
- auth->auth_request.auth_continue = mech_ntlm_auth_continue;
- auth->auth_request.auth_free = mech_ntlm_auth_free;
+ request = p_new(pool, struct ntlm_auth_request, 1);
+ request->pool = pool;
- return &auth->auth_request;
+ request->auth_request.refcount = 1;
+ request->auth_request.pool = pool;
+ return &request->auth_request;
}
const struct mech_module mech_ntlm = {
"NTLM",
- MEMBER(plaintext) FALSE,
- MEMBER(advertise) TRUE,
+ MEMBER(flags) MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE,
MEMBER(passdb_need_plain) FALSE,
MEMBER(passdb_need_credentials) TRUE,
mech_ntlm_auth_new,
+ mech_ntlm_auth_initial,
+ mech_ntlm_auth_continue,
+ mech_ntlm_auth_free
};
Index: mech-plain.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-plain.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- mech-plain.c 31 Aug 2004 09:31:18 -0000 1.21
+++ mech-plain.c 13 Oct 2004 16:38:32 -0000 1.22
@@ -11,8 +11,8 @@
mech_auth_finish(request, NULL, 0, result == PASSDB_RESULT_OK);
}
-static int
-mech_plain_auth_continue(struct auth_request *auth_request,
+static void
+mech_plain_auth_continue(struct auth_request *request,
const unsigned char *data, size_t data_size,
mech_callback_t *callback)
{
@@ -20,7 +20,7 @@
char *pass;
size_t i, count, len;
- auth_request->callback = callback;
+ request->callback = callback;
/* authorization ID \0 authentication ID \0 pass.
we'll ignore authorization ID for now. */
@@ -46,93 +46,74 @@
/* invalid input */
if (verbose) {
i_info("plain(%s): invalid input",
- get_log_prefix(auth_request));
+ get_log_prefix(request));
}
- mech_auth_finish(auth_request, NULL, 0, FALSE);
+ mech_auth_finish(request, NULL, 0, FALSE);
} else {
/* split and save user/realm */
if (strchr(authenid, '@') == NULL && default_realm != NULL) {
- auth_request->user = p_strconcat(auth_request->pool,
- authenid, "@",
- default_realm, NULL);
+ request->user = p_strconcat(request->pool,
+ authenid, "@",
+ default_realm, NULL);
} else {
- auth_request->user = p_strdup(auth_request->pool,
- authenid);
+ request->user = p_strdup(request->pool, authenid);
}
- if (!mech_fix_username(auth_request->user, &error)) {
+ if (!mech_fix_username(request->user, &error)) {
/* invalid username */
if (verbose) {
i_info("plain(%s): %s",
- get_log_prefix(auth_request), error);
+ get_log_prefix(request), error);
}
- mech_auth_finish(auth_request, NULL, 0, FALSE);
+ mech_auth_finish(request, NULL, 0, FALSE);
} else {
- passdb->verify_plain(auth_request, pass,
- verify_callback);
+ passdb->verify_plain(request, pass, verify_callback);
}
/* make sure it's cleared */
safe_memset(pass, 0, strlen(pass));
}
- return TRUE;
}
-static int
-mech_plain_auth_initial(struct auth_request *auth_request,
- struct auth_client_request_new *request,
- const unsigned char *data,
+static void
+mech_plain_auth_initial(struct auth_request *request,
+ const unsigned char *data, size_t data_size,
mech_callback_t *callback)
{
- struct auth_client_request_reply reply;
- size_t data_size;
-
- if (AUTH_CLIENT_REQUEST_HAVE_INITIAL_RESPONSE(request)) {
- data += request->initial_resp_idx;
- data_size = request->data_size - request->initial_resp_idx;
-
- return auth_request->auth_continue(auth_request, data,
- data_size, callback);
- }
-
- /* initialize reply */
- memset(&reply, 0, sizeof(reply));
- reply.id = request->id;
- reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
- callback(&reply, NULL, auth_request->conn);
- return TRUE;
+ if (data_size == 0)
+ callback(request, AUTH_CLIENT_RESULT_CONTINUE, NULL, 0);
+ else
+ mech_plain_auth_continue(request, data, data_size, callback);
}
static void
-mech_plain_auth_free(struct auth_request *auth_request)
+mech_plain_auth_free(struct auth_request *request)
{
- pool_unref(auth_request->pool);
+ pool_unref(request->pool);
}
static struct auth_request *mech_plain_auth_new(void)
{
- struct auth_request *auth_request;
+ struct auth_request *request;
pool_t pool;
pool = pool_alloconly_create("plain_auth_request", 256);
- auth_request = p_new(pool, struct auth_request, 1);
- auth_request->refcount = 1;
- auth_request->pool = pool;
- auth_request->auth_initial = mech_plain_auth_initial;
- auth_request->auth_continue = mech_plain_auth_continue;
- auth_request->auth_free = mech_plain_auth_free;
- return auth_request;
+ request = p_new(pool, struct auth_request, 1);
+ request->refcount = 1;
+ request->pool = pool;
+ return request;
}
struct mech_module mech_plain = {
"PLAIN",
- MEMBER(plaintext) TRUE,
- MEMBER(advertise) FALSE,
+ MEMBER(flags) MECH_SEC_PLAINTEXT,
MEMBER(passdb_need_plain) TRUE,
MEMBER(passdb_need_credentials) FALSE,
- mech_plain_auth_new
+ mech_plain_auth_new,
+ mech_plain_auth_initial,
+ mech_plain_auth_continue,
+ mech_plain_auth_free
};
Index: mech-rpa.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-rpa.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- mech-rpa.c 8 Oct 2004 17:51:47 -0000 1.5
+++ mech-rpa.c 13 Oct 2004 16:38:32 -0000 1.6
@@ -64,7 +64,7 @@
/*
* Compute client -> server authentication response.
*/
-static void rpa_user_response(struct rpa_auth_request *auth,
+static void rpa_user_response(struct rpa_auth_request *request,
unsigned char *digest)
{
struct md5_context ctx;
@@ -73,22 +73,22 @@
memset(z, 0, sizeof(z));
md5_init(&ctx);
- md5_update(&ctx, auth->pwd_md5, 16);
+ md5_update(&ctx, request->pwd_md5, 16);
md5_update(&ctx, z, sizeof(z));
- md5_update(&ctx, auth->username_ucs2be, auth->username_len);
- md5_update(&ctx, auth->service_ucs2be, auth->service_len);
- md5_update(&ctx, auth->realm_ucs2be, auth->realm_len);
- md5_update(&ctx, auth->user_challenge, auth->user_challenge_len);
- md5_update(&ctx, auth->service_challenge, RPA_SCHALLENGE_LEN);
- md5_update(&ctx, auth->service_timestamp, RPA_TIMESTAMP_LEN);
- md5_update(&ctx, auth->pwd_md5, 16);
+ md5_update(&ctx, request->username_ucs2be, request->username_len);
+ md5_update(&ctx, request->service_ucs2be, request->service_len);
+ md5_update(&ctx, request->realm_ucs2be, request->realm_len);
+ md5_update(&ctx, request->user_challenge, request->user_challenge_len);
+ md5_update(&ctx, request->service_challenge, RPA_SCHALLENGE_LEN);
+ md5_update(&ctx, request->service_timestamp, RPA_TIMESTAMP_LEN);
+ md5_update(&ctx, request->pwd_md5, 16);
md5_final(&ctx, digest);
}
/*
* Compute server -> client authentication response.
*/
-static void rpa_server_response(struct rpa_auth_request *auth,
+static void rpa_server_response(struct rpa_auth_request *request,
unsigned char *digest)
{
struct md5_context ctx;
@@ -99,32 +99,32 @@
memset(z, 0, sizeof(z));
md5_init(&ctx);
- md5_update(&ctx, auth->pwd_md5, 16);
+ md5_update(&ctx, request->pwd_md5, 16);
md5_update(&ctx, z, sizeof(z));
- md5_update(&ctx, auth->service_ucs2be, auth->service_len);
- md5_update(&ctx, auth->username_ucs2be, auth->username_len);
- md5_update(&ctx, auth->realm_ucs2be, auth->realm_len);
- md5_update(&ctx, auth->service_challenge, RPA_SCHALLENGE_LEN);
- md5_update(&ctx, auth->user_challenge, auth->user_challenge_len);
- md5_update(&ctx, auth->service_timestamp, RPA_TIMESTAMP_LEN);
- md5_update(&ctx, auth->pwd_md5, 16);
+ md5_update(&ctx, request->service_ucs2be, request->service_len);
+ md5_update(&ctx, request->username_ucs2be, request->username_len);
+ md5_update(&ctx, request->realm_ucs2be, request->realm_len);
+ md5_update(&ctx, request->service_challenge, RPA_SCHALLENGE_LEN);
+ md5_update(&ctx, request->user_challenge, request->user_challenge_len);
+ md5_update(&ctx, request->service_timestamp, RPA_TIMESTAMP_LEN);
+ md5_update(&ctx, request->pwd_md5, 16);
md5_final(&ctx, tmp);
for (i = 0; i < 16; i++)
- tmp[i] = auth->session_key[i] ^ tmp[i];
+ tmp[i] = request->session_key[i] ^ tmp[i];
md5_init(&ctx);
- md5_update(&ctx, auth->pwd_md5, 16);
+ md5_update(&ctx, request->pwd_md5, 16);
md5_update(&ctx, z, sizeof(z));
- md5_update(&ctx, auth->service_ucs2be, auth->service_len);
- md5_update(&ctx, auth->username_ucs2be, auth->username_len);
- md5_update(&ctx, auth->realm_ucs2be, auth->realm_len);
- md5_update(&ctx, auth->session_key, 16);
- md5_update(&ctx, auth->service_challenge, RPA_SCHALLENGE_LEN);
- md5_update(&ctx, auth->user_challenge, auth->user_challenge_len);
- md5_update(&ctx, auth->service_timestamp, RPA_TIMESTAMP_LEN);
+ md5_update(&ctx, request->service_ucs2be, request->service_len);
+ md5_update(&ctx, request->username_ucs2be, request->username_len);
+ md5_update(&ctx, request->realm_ucs2be, request->realm_len);
+ md5_update(&ctx, request->session_key, 16);
+ md5_update(&ctx, request->service_challenge, RPA_SCHALLENGE_LEN);
+ md5_update(&ctx, request->user_challenge, request->user_challenge_len);
+ md5_update(&ctx, request->service_timestamp, RPA_TIMESTAMP_LEN);
md5_update(&ctx, tmp, 16);
- md5_update(&ctx, auth->pwd_md5, 16);
+ md5_update(&ctx, request->pwd_md5, 16);
md5_final(&ctx, digest);
}
@@ -248,10 +248,10 @@
}
static int
-rpa_parse_token3(struct rpa_auth_request *auth, const void *data,
+rpa_parse_token3(struct rpa_auth_request *request, const void *data,
size_t data_size, const char **error)
{
- struct auth_request *auth_request = (struct auth_request *)auth;
+ struct auth_request *auth_request = &request->auth_request;
const unsigned char *end = ((unsigned char *)data) + data_size;
const unsigned char *p;
unsigned int len;
@@ -277,21 +277,21 @@
user = t_strndup(p, len);
p += len;
- auth_request->user = rpa_parse_username(auth->pool, user);
+ auth_request->user = rpa_parse_username(request->pool, user);
- auth->username_ucs2be = ucs2be_str(auth->pool, auth_request->user,
- &auth->username_len);
+ request->username_ucs2be = ucs2be_str(request->pool, auth_request->user,
+ &request->username_len);
/* Read user challenge */
- auth->user_challenge_len = rpa_read_buffer(auth->pool, &p, end,
- &auth->user_challenge);
- if (auth->user_challenge_len == 0) {
+ request->user_challenge_len = rpa_read_buffer(request->pool, &p, end,
+ &request->user_challenge);
+ if (request->user_challenge_len == 0) {
*error = "invalid user challenge";
return FALSE;
}
/* Read user response */
- len = rpa_read_buffer(auth->pool, &p, end, &auth->user_response);
+ len = rpa_read_buffer(request->pool, &p, end, &request->user_response);
if (len != RPA_UCHALLENGE_LEN) {
*error = "invalid user response";
return FALSE;
@@ -321,7 +321,7 @@
}
static const unsigned char *
-mech_rpa_build_token2(struct rpa_auth_request *auth,
+mech_rpa_build_token2(struct rpa_auth_request *request,
const char *realms, size_t *size)
{
unsigned int realms_len;
@@ -333,7 +333,7 @@
length = sizeof(rpa_oid) + 3 + RPA_SCHALLENGE_LEN +
RPA_TIMESTAMP_LEN + 2 + realms_len;
- buf = buffer_create_dynamic(auth->pool, length + 4);
+ buf = buffer_create_dynamic(request->pool, length + 4);
buffer_append_c(buf, ASN1_APPLICATION);
buffer_append_asn1_length(buf, length);
@@ -344,18 +344,19 @@
buffer_append_c(buf, 0);
/* Service challenge */
- auth->service_challenge = p_malloc(auth->pool, RPA_SCHALLENGE_LEN);
- random_fill(auth->service_challenge, RPA_SCHALLENGE_LEN);
+ request->service_challenge =
+ p_malloc(request->pool, RPA_SCHALLENGE_LEN);
+ random_fill(request->service_challenge, RPA_SCHALLENGE_LEN);
buffer_append_c(buf, RPA_SCHALLENGE_LEN);
- buffer_append(buf, auth->service_challenge, RPA_SCHALLENGE_LEN);
+ buffer_append(buf, request->service_challenge, RPA_SCHALLENGE_LEN);
/* Timestamp, looks like clients accept anything we send */
random_fill(timestamp, sizeof(timestamp));
- auth->service_timestamp = p_malloc(auth->pool, RPA_TIMESTAMP_LEN);
- memcpy(auth->service_timestamp,
+ request->service_timestamp = p_malloc(request->pool, RPA_TIMESTAMP_LEN);
+ memcpy(request->service_timestamp,
binary_to_hex(timestamp, sizeof(timestamp)),
RPA_TIMESTAMP_LEN);
- buffer_append(buf, auth->service_timestamp, RPA_TIMESTAMP_LEN);
+ buffer_append(buf, request->service_timestamp, RPA_TIMESTAMP_LEN);
/* Realm list */
buffer_append_c(buf, realms_len >> 8);
@@ -367,29 +368,29 @@
}
static const unsigned char *
-mech_rpa_build_token4(struct rpa_auth_request *auth, size_t *size)
+mech_rpa_build_token4(struct rpa_auth_request *request, size_t *size)
{
unsigned int length = sizeof(rpa_oid) + 17 + 17 + 1;
buffer_t *buf;
unsigned char server_response[16];
- buf = buffer_create_dynamic(auth->pool, length + 4);
+ buf = buffer_create_dynamic(request->pool, length + 4);
buffer_append_c(buf, ASN1_APPLICATION);
buffer_append_asn1_length(buf, length);
buffer_append(buf, rpa_oid, sizeof(rpa_oid));
/* Generate random session key */
- auth->session_key = p_malloc(auth->pool, 16);
- random_fill(auth->session_key, 16);
+ request->session_key = p_malloc(request->pool, 16);
+ random_fill(request->session_key, 16);
/* Server authentication response */
- rpa_server_response(auth, server_response);
+ rpa_server_response(request, server_response);
buffer_append_c(buf, 16);
buffer_append(buf, server_response, 16);
buffer_append_c(buf, 16);
- buffer_append(buf, auth->session_key, 16);
+ buffer_append(buf, request->session_key, 16);
/* Status, 0 - success */
buffer_append_c(buf, 0);
@@ -402,28 +403,24 @@
rpa_credentials_callback(const char *credentials,
struct auth_request *auth_request)
{
- struct rpa_auth_request *auth =
+ struct rpa_auth_request *request =
(struct rpa_auth_request *)auth_request;
buffer_t *hash_buffer;
if (credentials == NULL)
return;
- auth->pwd_md5 = p_malloc(auth->pool, 16);
-
- hash_buffer = buffer_create_data(auth->pool, auth->pwd_md5, 16);
-
+ request->pwd_md5 = p_malloc(request->pool, 16);
+ hash_buffer = buffer_create_data(request->pool, request->pwd_md5, 16);
hex_to_binary(credentials, hash_buffer);
}
-static int
+static void
mech_rpa_auth_phase1(struct auth_request *auth_request,
- const unsigned char *data, size_t data_size,
- mech_callback_t *callback)
+ const unsigned char *data, size_t data_size)
{
- struct rpa_auth_request *auth =
+ struct rpa_auth_request *request =
(struct rpa_auth_request *)auth_request;
- struct auth_client_request_reply reply;
const unsigned char *token2;
size_t token2_size;
const char *service, *error;
@@ -434,52 +431,42 @@
get_log_prefix(auth_request), error);
}
mech_auth_finish(auth_request, NULL, 0, FALSE);
- return TRUE;
+ return;
}
service = t_str_lcase(auth_request->protocol);
- token2 = mech_rpa_build_token2(auth, t_strconcat(service, "@",
+ token2 = mech_rpa_build_token2(request, t_strconcat(service, "@",
my_hostname, NULL), &token2_size);
- auth->service_ucs2be = ucs2be_str(auth->pool, service,
- &auth->service_len);
- auth->realm_ucs2be = ucs2be_str(auth->pool, my_hostname,
- &auth->realm_len);
-
- mech_init_auth_client_reply(&reply);
- reply.id = auth_request->id;
- reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
- reply.reply_idx = 0;
- reply.data_size = token2_size;
- callback(&reply, token2, auth_request->conn);
-
- auth->phase = 1;
+ request->service_ucs2be = ucs2be_str(request->pool, service,
+ &request->service_len);
+ request->realm_ucs2be = ucs2be_str(request->pool, my_hostname,
+ &request->realm_len);
- return TRUE;
+ auth_request->callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE,
+ token2, token2_size);
+ request->phase = 1;
}
-static int
+static void
mech_rpa_auth_phase2(struct auth_request *auth_request,
- const unsigned char *data, size_t data_size,
- mech_callback_t *callback)
+ const unsigned char *data, size_t data_size)
{
- struct rpa_auth_request *auth =
+ struct rpa_auth_request *request =
(struct rpa_auth_request *)auth_request;
- struct auth_client_request_reply reply;
unsigned char response[16];
const unsigned char *token4;
const char *error;
size_t token4_size;
- if (!rpa_parse_token3(auth, data, data_size, &error)) {
+ if (!rpa_parse_token3(request, data, data_size, &error)) {
if (verbose) {
i_info("rpa(%s): invalid token 3, %s",
get_log_prefix(auth_request), error);
}
mech_auth_finish(auth_request, NULL, 0, FALSE);
- return TRUE;
+ return;
}
if (!mech_fix_username(auth_request->user, &error)) {
@@ -488,41 +475,31 @@
get_log_prefix(auth_request), error);
}
mech_auth_finish(auth_request, NULL, 0, FALSE);
- return TRUE;
+ return;
}
passdb->lookup_credentials(auth_request, PASSDB_CREDENTIALS_RPA,
rpa_credentials_callback);
- if (auth->pwd_md5 == NULL) {
+ if (request->pwd_md5 == NULL) {
mech_auth_finish(auth_request, NULL, 0, FALSE);
- return TRUE;
+ return;
}
- rpa_user_response(auth, response);
- if (memcmp(response, auth->user_response, 16) != 0) {
+ rpa_user_response(request, response);
+ if (memcmp(response, request->user_response, 16) != 0) {
mech_auth_finish(auth_request, NULL, 0, FALSE);
- return TRUE;
+ return;
}
- token4 = mech_rpa_build_token4(auth, &token4_size);
-
- mech_init_auth_client_reply(&reply);
- reply.id = auth_request->id;
- reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
- reply.reply_idx = 0;
- reply.data_size = token4_size;
- callback(&reply, token4, auth_request->conn);
-
- auth->phase = 2;
-
- return TRUE;
+ token4 = mech_rpa_build_token4(request, &token4_size);
+ auth_request->callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE,
+ token4, token4_size);
+ request->phase = 2;
}
-static int
+static void
mech_rpa_auth_phase3(struct auth_request *auth_request,
- const unsigned char *data, size_t data_size,
- mech_callback_t *callback __attr_unused__)
+ const unsigned char *data, size_t data_size)
{
static const unsigned char client_ack[3] = { 0x60, 0x01, 0x00 };
int ret = TRUE;
@@ -537,90 +514,80 @@
}
mech_auth_finish(auth_request, NULL, 0, ret);
- return TRUE;
}
-static int
+static void
mech_rpa_auth_continue(struct auth_request *auth_request,
- const unsigned char *data, size_t data_size,
- mech_callback_t *callback)
+ const unsigned char *data, size_t data_size,
+ mech_callback_t *callback)
{
- struct rpa_auth_request *auth =
+ struct rpa_auth_request *request =
(struct rpa_auth_request *)auth_request;
auth_request->callback = callback;
- switch (auth->phase) {
- case 0: return mech_rpa_auth_phase1(auth_request, data,
- data_size, callback);
- case 1: return mech_rpa_auth_phase2(auth_request, data,
- data_size, callback);
- case 2: return mech_rpa_auth_phase3(auth_request, data,
- data_size, callback);
+ switch (request->phase) {
+ case 0:
+ mech_rpa_auth_phase1(auth_request, data, data_size);
+ break;
+ case 1:
+ mech_rpa_auth_phase2(auth_request, data, data_size);
+ break;
+ case 2:
+ mech_rpa_auth_phase3(auth_request, data, data_size);
+ break;
+ default:
+ mech_auth_finish(auth_request, NULL, 0, FALSE);
+ break;
}
-
- mech_auth_finish(auth_request, NULL, 0, FALSE);
- return TRUE;
}
-static int
+static void
mech_rpa_auth_initial(struct auth_request *auth_request,
- struct auth_client_request_new *request,
const unsigned char *data __attr_unused__,
+ size_t data_size __attr_unused__,
mech_callback_t *callback)
{
- struct auth_client_request_reply reply;
-
- mech_init_auth_client_reply(&reply);
- reply.id = request->id;
- reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
- reply.reply_idx = 0;
- reply.data_size = 0;
- callback(&reply, "", auth_request->conn);
-
- return TRUE;
+ callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE, NULL, 0);
}
static void
mech_rpa_auth_free(struct auth_request *auth_request)
{
- struct rpa_auth_request *auth =
+ struct rpa_auth_request *request =
(struct rpa_auth_request *)auth_request;
- if (auth->pwd_md5 != NULL)
- safe_memset(auth->pwd_md5, 0, 16);
+ if (request->pwd_md5 != NULL)
+ safe_memset(request->pwd_md5, 0, 16);
pool_unref(auth_request->pool);
}
static struct auth_request *mech_rpa_auth_new(void)
{
- struct rpa_auth_request *auth;
+ struct rpa_auth_request *request;
pool_t pool;
pool = pool_alloconly_create("rpa_auth_request", 256);
- auth = p_new(pool, struct rpa_auth_request, 1);
- auth->pool = pool;
- auth->phase = 0;
-
- auth->auth_request.refcount = 1;
- auth->auth_request.pool = pool;
- auth->auth_request.auth_initial = mech_rpa_auth_initial;
- auth->auth_request.auth_continue = mech_rpa_auth_continue;
- auth->auth_request.auth_free = mech_rpa_auth_free;
+ request = p_new(pool, struct rpa_auth_request, 1);
+ request->pool = pool;
+ request->phase = 0;
- return &auth->auth_request;
+ request->auth_request.refcount = 1;
+ request->auth_request.pool = pool;
+ return &request->auth_request;
}
const struct mech_module mech_rpa = {
"RPA",
- MEMBER(plaintext) FALSE,
- MEMBER(advertise) TRUE,
+ MEMBER(flags) MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE,
MEMBER(passdb_need_plain) FALSE,
MEMBER(passdb_need_credentials) TRUE,
mech_rpa_auth_new,
+ mech_rpa_auth_initial,
+ mech_rpa_auth_continue,
+ mech_rpa_auth_free
};
Index: mech.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -d -r1.41 -r1.42
--- mech.c 10 Oct 2004 14:32:32 -0000 1.41
+++ mech.c 13 Oct 2004 16:38:32 -0000 1.42
@@ -14,14 +14,14 @@
#include <stdlib.h>
struct mech_module_list *mech_modules;
+buffer_t *mech_handshake;
+
const char *const *auth_realms;
const char *default_realm;
const char *anonymous_username;
char username_chars[256], username_translation[256];
int ssl_require_client_cert;
-static struct auth_client_request_reply failure_reply;
-
static buffer_t *auth_failures_buf;
static struct timeout *to_auth_failures;
@@ -32,6 +32,23 @@
list = i_new(struct mech_module_list, 1);
list->module = *module;
+ str_printfa(mech_handshake, "MECH\t%s", module->mech_name);
+ if ((module->flags & MECH_SEC_PRIVATE) != 0)
+ str_append(mech_handshake, "\tprivate");
+ if ((module->flags & MECH_SEC_ANONYMOUS) != 0)
+ str_append(mech_handshake, "\tanonymous");
+ if ((module->flags & MECH_SEC_PLAINTEXT) != 0)
+ str_append(mech_handshake, "\tplaintext");
+ if ((module->flags & MECH_SEC_DICTIONARY) != 0)
+ str_append(mech_handshake, "\tdictionary");
+ if ((module->flags & MECH_SEC_ACTIVE) != 0)
+ str_append(mech_handshake, "\tactive");
+ if ((module->flags & MECH_SEC_FORWARD_SECRECY) != 0)
+ str_append(mech_handshake, "\tforward-secrecy");
+ if ((module->flags & MECH_SEC_MUTUAL_AUTH) != 0)
+ str_append(mech_handshake, "\tmutual-auth");
+ str_append_c(mech_handshake, '\n');
+
list->next = mech_modules;
mech_modules = list;
}
@@ -62,7 +79,7 @@
return str;
}
-static struct mech_module *mech_module_find(const char *name)
+struct mech_module *mech_module_find(const char *name)
{
struct mech_module_list *list;
@@ -73,183 +90,48 @@
return NULL;
}
-void mech_request_new(struct auth_client_connection *conn,
- struct auth_client_request_new *request,
- const unsigned char *data,
- mech_callback_t *callback)
-{
- struct mech_module *mech;
- struct auth_request *auth_request;
- size_t ip_size = 1;
-
- if (request->ip_family == AF_INET)
- ip_size = 4;
- else if (request->ip_family != 0)
- ip_size = sizeof(auth_request->local_ip.ip);
- else
- ip_size = 0;
-
- /* make sure data is NUL-terminated */
- if (request->data_size <= ip_size*2 || request->initial_resp_idx == 0 ||
- request->mech_idx >= request->data_size ||
- request->protocol_idx >= request->data_size ||
- request->initial_resp_idx > request->data_size ||
- data[request->initial_resp_idx-1] != '\0') {
- i_error("BUG: Auth client %u sent corrupted request",
- conn->pid);
- failure_reply.id = request->id;
- callback(&failure_reply, NULL, conn);
- return;
- }
-
- mech = mech_module_find((const char *)data + request->mech_idx);
- if (mech == NULL) {
- /* unsupported mechanism */
- i_error("BUG: Auth client %u requested unsupported "
- "auth mechanism %s", conn->pid,
- (const char *)data + request->mech_idx);
- failure_reply.id = request->id;
- callback(&failure_reply, NULL, conn);
- return;
- }
-
- auth_request = mech->auth_new();
- if (auth_request == NULL)
- return;
-
- auth_request->created = ioloop_time;
- auth_request->conn = conn;
- auth_request->id = request->id;
- auth_request->protocol =
- p_strdup(auth_request->pool,
- (const char *)data + request->protocol_idx);
-
- if (request->ip_family != 0) {
- auth_request->local_ip.family = request->ip_family;
- auth_request->remote_ip.family = request->ip_family;
-
- memcpy(&auth_request->local_ip.ip, data, ip_size);
- memcpy(&auth_request->remote_ip.ip, data + ip_size, ip_size);
- }
-
- if (ssl_require_client_cert &&
- (request->flags & AUTH_CLIENT_FLAG_SSL_VALID_CLIENT_CERT) == 0) {
- /* we fail without valid certificate */
- if (verbose) {
- i_info("ssl-cert-check(%s): "
- "Client didn't present valid SSL certificate",
- get_log_prefix(auth_request));
- }
- auth_request_unref(auth_request);
-
- failure_reply.id = request->id;
- callback(&failure_reply, NULL, conn);
- return;
- }
-
- hash_insert(conn->auth_requests, POINTER_CAST(request->id),
- auth_request);
-
- if (!auth_request->auth_initial(auth_request, request, data, callback))
- mech_request_free(auth_request, request->id);
-}
-
-void mech_request_continue(struct auth_client_connection *conn,
- struct auth_client_request_continue *request,
- const unsigned char *data,
- mech_callback_t *callback)
-{
- struct auth_request *auth_request;
-
- auth_request = hash_lookup(conn->auth_requests,
- POINTER_CAST(request->id));
- if (auth_request == NULL) {
- /* timeouted */
- failure_reply.id = request->id;
- callback(&failure_reply, NULL, conn);
- } else {
- if (!auth_request->auth_continue(auth_request,
- data, request->data_size,
- callback))
- mech_request_free(auth_request, request->id);
- }
-}
-
-void mech_request_free(struct auth_request *auth_request, unsigned int id)
+struct auth_request *auth_request_new(struct mech_module *mech)
{
- if (auth_request->conn != NULL) {
- hash_remove(auth_request->conn->auth_requests,
- POINTER_CAST(id));
- }
- auth_request_unref(auth_request);
-}
+ struct auth_request *request;
-void mech_init_auth_client_reply(struct auth_client_request_reply *reply)
-{
- memset(reply, 0, sizeof(*reply));
+ request = mech->auth_new();
+ if (request == NULL)
+ return NULL;
- reply->username_idx = (uint32_t)-1;
- reply->reply_idx = (uint32_t)-1;
+ request->mech = mech;
+ request->created = ioloop_time;
+ return request;
}
-void *mech_auth_success(struct auth_client_request_reply *reply,
- struct auth_request *auth_request,
- const void *data, size_t data_size)
+void auth_request_destroy(struct auth_request *request)
{
- buffer_t *buf;
-
- buf = buffer_create_dynamic(pool_datastack_create(), 256);
-
- reply->username_idx = 0;
- buffer_append(buf, auth_request->user, strlen(auth_request->user)+1);
-
- if (data_size == 0)
- reply->reply_idx = (uint32_t)-1;
- else {
- reply->reply_idx = buffer_get_used_size(buf);
- buffer_append(buf, data, data_size);
+ if (request->conn != NULL) {
+ hash_remove(request->conn->auth_requests,
+ POINTER_CAST(request->id));
}
-
- reply->result = AUTH_CLIENT_RESULT_SUCCESS;
- reply->data_size = buffer_get_used_size(buf);
- return buffer_get_modifyable_data(buf, NULL);
+ auth_request_unref(request);
}
-void mech_auth_finish(struct auth_request *auth_request,
+void mech_auth_finish(struct auth_request *request,
const void *data, size_t data_size, int success)
{
- struct auth_client_request_reply reply;
- void *reply_data;
- int free_request;
-
if (!success) {
/* failure. don't announce it immediately to avoid
a) timing attacks, b) flooding */
- buffer_append(auth_failures_buf,
- &auth_request, sizeof(auth_request));
+ buffer_append(auth_failures_buf, &request, sizeof(request));
return;
}
- memset(&reply, 0, sizeof(reply));
- reply.id = auth_request->id;
- reply.result = AUTH_CLIENT_RESULT_SUCCESS;
-
- if (auth_request->conn == NULL) {
- /* client is already gone */
- free_request = TRUE;
- } else {
- /* get this before callback because it can destroy connection */
- free_request = AUTH_MASTER_IS_DUMMY(auth_request->conn->master);
-
- reply_data = mech_auth_success(&reply, auth_request,
- data, data_size);
- auth_request->callback(&reply, reply_data, auth_request->conn);
+ if (request->conn != NULL) {
+ request->callback(request, AUTH_CLIENT_RESULT_SUCCESS,
+ data, data_size);
}
- if (free_request) {
+ if (request->conn == NULL ||
+ AUTH_MASTER_IS_DUMMY(request->conn->master)) {
/* we don't have master process, the request is no longer
needed */
- mech_request_free(auth_request, auth_request->id);
+ auth_request_destroy(request);
}
}
@@ -285,7 +167,7 @@
if (--request->refcount > 0)
return TRUE;
- request->auth_free(request);
+ request->mech->auth_free(request);
return FALSE;
}
@@ -358,22 +240,18 @@
void auth_failure_buf_flush(void)
{
struct auth_request **auth_request;
- struct auth_client_request_reply reply;
size_t i, size;
auth_request = buffer_get_modifyable_data(auth_failures_buf, &size);
size /= sizeof(*auth_request);
- memset(&reply, 0, sizeof(reply));
- reply.result = AUTH_CLIENT_RESULT_FAILURE;
-
for (i = 0; i < size; i++) {
- reply.id = auth_request[i]->id;
if (auth_request[i]->conn != NULL) {
- auth_request[i]->callback(&reply, NULL,
- auth_request[i]->conn);
+ auth_request[i]->callback(auth_request[i],
+ AUTH_CLIENT_RESULT_FAILURE,
+ NULL, 0);
}
- mech_request_free(auth_request[i], reply.id);
+ auth_request_destroy(auth_request[i]);
}
buffer_set_used_size(auth_failures_buf, 0);
}
@@ -397,10 +275,8 @@
const char *const *mechanisms;
const char *env;
- mech_modules = NULL;
-
- memset(&failure_reply, 0, sizeof(failure_reply));
- failure_reply.result = AUTH_CLIENT_RESULT_FAILURE;
+ mech_modules = NULL;
+ mech_handshake = str_new(default_pool, 512);
anonymous_username = getenv("ANONYMOUS_USERNAME");
if (anonymous_username != NULL && *anonymous_username == '\0')
@@ -493,4 +369,6 @@
mech_unregister_module(&mech_ntlm);
mech_unregister_module(&mech_rpa);
mech_unregister_module(&mech_anonymous);
+
+ str_free(mech_handshake);
}
Index: mech.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech.h,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- mech.h 10 Oct 2004 13:55:12 -0000 1.22
+++ mech.h 13 Oct 2004 16:38:32 -0000 1.23
@@ -4,11 +4,18 @@
#include "network.h"
#include "auth-client-interface.h"
+enum auth_client_result {
+ AUTH_CLIENT_RESULT_CONTINUE = 1,
+ AUTH_CLIENT_RESULT_SUCCESS,
+ AUTH_CLIENT_RESULT_FAILURE
+};
+
+struct auth_request;
struct auth_client_connection;
-typedef void mech_callback_t(struct auth_client_request_reply *reply,
- const void *data,
- struct auth_client_connection *conn);
+typedef void mech_callback_t(struct auth_request *request,
+ enum auth_client_result result,
+ const void *reply, size_t reply_size);
struct auth_request {
int refcount;
@@ -16,34 +23,35 @@
pool_t pool;
char *user;
+ struct mech_module *mech;
struct auth_client_connection *conn;
+
unsigned int id;
time_t created;
- char *protocol;
+ const char *protocol;
struct ip_addr local_ip, remote_ip;
mech_callback_t *callback;
- int (*auth_initial)(struct auth_request *auth_request,
- struct auth_client_request_new *request,
- const unsigned char *data,
- mech_callback_t *callback);
- int (*auth_continue)(struct auth_request *auth_request,
- const unsigned char *data, size_t data_size,
- mech_callback_t *callback);
- void (*auth_free)(struct auth_request *auth_request);
+ unsigned int accept_input:1;
/* ... mechanism specific data ... */
};
struct mech_module {
const char *mech_name;
- unsigned int plaintext:1;
- unsigned int advertise:1;
+ enum mech_security_flags flags;
unsigned int passdb_need_plain:1;
unsigned int passdb_need_credentials:1;
struct auth_request *(*auth_new)(void);
+ void (*auth_initial)(struct auth_request *request,
+ const unsigned char *data, size_t data_size,
+ mech_callback_t *callback);
+ void (*auth_continue)(struct auth_request *request,
+ const unsigned char *data, size_t data_size,
+ mech_callback_t *callback);
+ void (*auth_free)(struct auth_request *request);
};
struct mech_module_list {
@@ -53,6 +61,8 @@
};
extern struct mech_module_list *mech_modules;
+extern buffer_t *mech_handshake;
+
extern const char *const *auth_realms;
extern const char *default_realm;
extern const char *anonymous_username;
@@ -61,28 +71,17 @@
void mech_register_module(struct mech_module *module);
void mech_unregister_module(struct mech_module *module);
+struct mech_module *mech_module_find(const char *name);
const string_t *auth_mechanisms_get_list(void);
-void mech_request_new(struct auth_client_connection *conn,
- struct auth_client_request_new *request,
- const unsigned char *data,
- mech_callback_t *callback);
-void mech_request_continue(struct auth_client_connection *conn,
- struct auth_client_request_continue *request,
- const unsigned char *data,
- mech_callback_t *callback);
-void mech_request_free(struct auth_request *auth_request, unsigned int id);
-
-void mech_init_auth_client_reply(struct auth_client_request_reply *reply);
-void *mech_auth_success(struct auth_client_request_reply *reply,
- struct auth_request *auth_request,
- const void *data, size_t data_size);
-void mech_auth_finish(struct auth_request *auth_request,
+void mech_auth_finish(struct auth_request *request,
const void *data, size_t data_size, int success);
int mech_fix_username(char *username, const char **error_r);
+struct auth_request *auth_request_new(struct mech_module *mech);
+void auth_request_destroy(struct auth_request *request);
void auth_request_ref(struct auth_request *request);
int auth_request_unref(struct auth_request *request);
Index: userdb.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/userdb.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- userdb.h 20 Sep 2004 21:47:31 -0000 1.10
+++ userdb.h 13 Oct 2004 16:38:32 -0000 1.11
@@ -13,7 +13,7 @@
gid_t gid;
};
-typedef void userdb_callback_t(struct user_data *user, void *context);
+typedef void userdb_callback_t(const struct user_data *user, void *context);
struct userdb_module {
void (*preinit)(const char *args);
More information about the dovecot-cvs
mailing list