[dovecot-cvs] dovecot/src/auth Makefile.am, 1.24,
1.25 auth-client-connection.c, 1.5,
1.6 auth-client-interface.h, 1.4, 1.5 auth-master-connection.c,
1.6, 1.7 auth-master-connection.h, 1.2,
1.3 auth-master-interface.h, 1.3, 1.4 main.c, 1.23,
1.24 mech-anonymous.c, 1.3, 1.4 mech-cram-md5.c, 1.3,
1.4 mech-digest-md5.c, 1.19, 1.20 mech-plain.c, 1.16,
1.17 mech.c, 1.21, 1.22 mech.h, 1.15, 1.16 passdb.c, 1.14,
1.15 auth-mech-desc.h, 1.3, NONE
cras at procontrol.fi
cras at procontrol.fi
Sun May 30 00:40:33 EEST 2004
Update of /home/cvs/dovecot/src/auth
In directory talvi:/tmp/cvs-serv30244/auth
Modified Files:
Makefile.am auth-client-connection.c auth-client-interface.h
auth-master-connection.c auth-master-connection.h
auth-master-interface.h main.c mech-anonymous.c
mech-cram-md5.c mech-digest-md5.c mech-plain.c mech.c mech.h
passdb.c
Removed Files:
auth-mech-desc.h
Log Message:
Removed hardcoded mechanism lists. It's now possible to add them
dynamically. Added support for SASL initial response.
Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/auth/Makefile.am,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- a/Makefile.am 10 May 2004 01:47:09 -0000 1.24
+++ b/Makefile.am 29 May 2004 21:40:30 -0000 1.25
@@ -58,7 +58,6 @@
auth-client-interface.h \
auth-master-connection.h \
auth-master-interface.h \
- auth-mech-desc.h \
auth-module.h \
db-ldap.h \
db-mysql.h \
Index: auth-client-connection.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/auth-client-connection.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- a/auth-client-connection.c 3 Dec 2003 00:40:21 -0000 1.5
+++ b/auth-client-connection.c 29 May 2004 21:40:30 -0000 1.6
@@ -109,19 +109,26 @@
structures, as it may not be aligned properly. */
memcpy(&type, data, sizeof(type));
- if (type == AUTH_CLIENT_REQUEST_NEW) {
+ conn->refcount++;
+ switch (type) {
+ case AUTH_CLIENT_REQUEST_NEW: {
struct auth_client_request_new request;
if (size < sizeof(request))
return;
memcpy(&request, data, sizeof(request));
- i_stream_skip(conn->input, sizeof(request));
+ if (size < sizeof(request) + request.data_size)
+ return;
/* we have a full init request */
conn->refcount++;
- mech_request_new(conn, &request, request_callback);
- } else if (type == AUTH_CLIENT_REQUEST_CONTINUE) {
+ mech_request_new(conn, &request, data + sizeof(request),
+ request_callback);
+ i_stream_skip(conn->input, sizeof(request) + request.data_size);
+ break;
+ }
+ case AUTH_CLIENT_REQUEST_CONTINUE: {
struct auth_client_request_continue request;
if (size < sizeof(request))
@@ -131,8 +138,6 @@
if (size < sizeof(request) + request.data_size)
return;
- i_stream_skip(conn->input, sizeof(request) + request.data_size);
-
/* we have a full continued request */
conn->refcount++;
mech_request_continue(conn, &request, data + sizeof(request),
@@ -140,12 +145,16 @@
/* clear any sensitive data from memory */
safe_memset(data + sizeof(request), 0, request.data_size);
- } else {
+ i_stream_skip(conn->input, sizeof(request) + request.data_size);
+ break;
+ }
+ default:
/* unknown request */
- i_error("BUG: Auth client %u sent us unknown request %u",
+ i_error("BUG: Auth client %u sent us unknown request type %u",
conn->pid, type);
auth_client_connection_destroy(conn);
}
+ auth_client_connection_unref(conn);
}
static void auth_client_input(void *context)
@@ -198,8 +207,9 @@
conn->next = master->clients;
master->clients = conn;
- if (o_stream_send(conn->output, &master->handshake_reply,
- sizeof(master->handshake_reply)) < 0) {
+ if (o_stream_send(conn->output, master->handshake_reply,
+ sizeof(*master->handshake_reply) +
+ master->handshake_reply->data_size) < 0) {
auth_client_connection_destroy(conn);
conn = NULL;
}
@@ -298,9 +308,6 @@
void auth_client_connections_init(struct auth_master_connection *master)
{
- master->handshake_reply.server_pid = master->pid;
- master->handshake_reply.auth_mechanisms = auth_mechanisms;
-
master->to_clients = timeout_add(5000, request_timeout, master);
}
Index: auth-client-interface.h
===================================================================
RCS file: /home/cvs/dovecot/src/auth/auth-client-interface.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- a/auth-client-interface.h 29 May 2004 17:06:50 -0000 1.4
+++ b/auth-client-interface.h 29 May 2004 21:40:30 -0000 1.5
@@ -4,22 +4,10 @@
/* max. size for auth_client_request_continue.data[] */
#define AUTH_CLIENT_MAX_REQUEST_DATA_SIZE 4096
-/* sizeof(struct auth_client_request_new->protocol) */
-#define AUTH_CLIENT_PROTOCOL_BUF_SIZE 12
-
/* Client process must finish with single authentication requests in this time,
or the whole connection will be killed. */
#define AUTH_REQUEST_TIMEOUT 120
-enum auth_mech {
- AUTH_MECH_PLAIN = 0x01,
- AUTH_MECH_DIGEST_MD5 = 0x02,
- AUTH_MECH_ANONYMOUS = 0x04,
- AUTH_MECH_CRAM_MD5 = 0x08,
-
- AUTH_MECH_COUNT
-};
-
enum auth_client_request_new_flags {
AUTH_CLIENT_FLAG_SSL_VALID_CLIENT_CERT = 0x01
};
@@ -40,10 +28,19 @@
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 */
- enum auth_mech auth_mechanisms; /* valid authentication mechanisms */
+
+ uint32_t mech_count;
+ uint32_t data_size;
+ /* struct auth_client_handshake_mech_desc mech_desc[auth_mech_count]; */
};
/* New authentication request */
@@ -51,17 +48,24 @@
enum auth_client_request_type type; /* AUTH_CLIENT_REQUEST_NEW */
unsigned int id; /* unique ID for the request */
- enum auth_mech mech;
enum auth_client_request_new_flags flags;
- char protocol[AUTH_CLIENT_PROTOCOL_BUF_SIZE];
+
+ 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;
- size_t data_size;
+ uint32_t data_size;
/* unsigned char data[]; */
};
@@ -73,10 +77,10 @@
/* variable width data, indexes into data[].
Ignore if it points outside data_size. */
- size_t username_idx; /* NUL-terminated */
- size_t reply_idx; /* last, non-NUL terminated */
+ uint32_t username_idx; /* NUL-terminated */
+ uint32_t reply_idx; /* last, non-NUL terminated */
- size_t data_size;
+ uint32_t data_size;
/* unsigned char data[]; */
};
Index: auth-master-connection.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/auth-master-connection.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- a/auth-master-connection.c 29 May 2004 16:43:22 -0000 1.6
+++ b/auth-master-connection.c 29 May 2004 21:40:30 -0000 1.7
@@ -182,6 +182,48 @@
}
}
+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, (size_t)-1);
+
+ 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);
+ memcpy(buffer_get_space_unsafe(buf, 0, sizeof(reply)),
+ &reply, sizeof(reply));
+
+ master->handshake_reply = buffer_free_without_data(buf);
+}
+
struct auth_master_connection *
auth_master_connection_new(int fd, unsigned int pid)
{
@@ -198,6 +240,7 @@
MAX_OUTBUF_SIZE, FALSE);
conn->io = io_add(fd, IO_READ, master_input, conn);
}
+ master_get_handshake_reply(conn);
return conn;
}
@@ -241,6 +284,7 @@
i_free(l[i]);
}
buffer_free(conn->listeners_buf);
+ conn->listeners_buf = NULL;
auth_master_connection_unref(conn);
}
@@ -252,6 +296,7 @@
if (conn->output != NULL)
o_stream_unref(conn->output);
+ i_free(conn->handshake_reply);
i_free(conn);
return FALSE;
}
@@ -280,7 +325,7 @@
l->master = conn;
l->fd = fd;
l->path = i_strdup(path);
- l->io = io_add(fd, IO_READ, auth_accept, &l);
+ l->io = io_add(fd, IO_READ, auth_accept, l);
buffer_append(conn->listeners_buf, &l, sizeof(l));
}
Index: auth-master-connection.h
===================================================================
RCS file: /home/cvs/dovecot/src/auth/auth-master-connection.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- a/auth-master-connection.h 29 May 2004 16:43:22 -0000 1.2
+++ b/auth-master-connection.h 29 May 2004 21:40:30 -0000 1.3
@@ -15,7 +15,7 @@
unsigned int request_pos;
unsigned char request_buf[sizeof(struct auth_master_request)];
- struct auth_client_handshake_reply handshake_reply;
+ struct auth_client_handshake_reply *handshake_reply;
struct auth_client_connection *clients;
struct timeout *to_clients;
Index: auth-master-interface.h
===================================================================
RCS file: /home/cvs/dovecot/src/auth/auth-master-interface.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- a/auth-master-interface.h 22 Aug 2003 02:42:13 -0000 1.3
+++ b/auth-master-interface.h 29 May 2004 21:40:30 -0000 1.4
@@ -21,11 +21,11 @@
/* variable width fields are packed into data[]. These variables
contain indexes to the data, they're all NUL-terminated.
Ignore if it points outside data_size. */
- size_t system_user_idx;
- size_t virtual_user_idx;
- size_t home_idx, mail_idx, chroot_idx;
+ uint32_t system_user_idx;
+ uint32_t virtual_user_idx;
+ uint32_t home_idx, mail_idx, chroot_idx;
- size_t data_size;
+ uint32_t data_size;
/* unsigned char data[]; */
};
Index: main.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/main.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- a/main.c 29 May 2004 16:43:22 -0000 1.23
+++ b/main.c 29 May 2004 21:40:30 -0000 1.24
@@ -132,7 +132,7 @@
env = getenv("AUTH_SOCKETS");
}
- if (env != NULL) {
+ if (env != NULL && *env != '\0') {
master = auth_master_connection_new(-1, 0);
master_add_unix_listeners(master, env);
auth_client_connections_init(master);
Index: mech-anonymous.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech-anonymous.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- a/mech-anonymous.c 22 Aug 2003 04:57:49 -0000 1.3
+++ b/mech-anonymous.c 29 May 2004 21:40:30 -0000 1.4
@@ -5,15 +5,14 @@
static int
mech_anonymous_auth_continue(struct auth_request *auth_request,
- struct auth_client_request_continue *request,
- const unsigned char *data,
+ const unsigned char *data, size_t data_size,
mech_callback_t *callback)
{
i_assert(anonymous_username != NULL);
if (verbose) {
i_info("mech-anonymous: login by %s",
- t_strndup(data, request->data_size));
+ t_strndup(data, data_size));
}
auth_request->callback = callback;
@@ -22,37 +21,62 @@
return TRUE;
}
+static int
+mech_anonymous_auth_initial(struct auth_request *auth_request,
+ struct auth_client_request_new *request,
+ const unsigned char *data,
+ 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 = 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)
{
pool_unref(auth_request->pool);
}
-static struct auth_request *
-mech_anonymous_auth_new(struct auth_client_connection *conn, unsigned int id,
- mech_callback_t *callback)
+static struct auth_request *mech_anonymous_auth_new(void)
{
struct auth_request *auth_request;
- struct auth_client_request_reply reply;
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;
- /* initialize reply */
- memset(&reply, 0, sizeof(reply));
- reply.id = id;
- reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
- callback(&reply, NULL, conn);
return auth_request;
}
struct mech_module mech_anonymous = {
- AUTH_MECH_ANONYMOUS,
+ "ANONYMOUS",
+
+ MEMBER(plaintext) FALSE,
+ MEMBER(advertise) TRUE,
+
+ MEMBER(passdb_need_plain) FALSE,
+ MEMBER(passdb_need_credentials) FALSE,
+
mech_anonymous_auth_new
};
Index: mech-cram-md5.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech-cram-md5.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- a/mech-cram-md5.c 11 Nov 2003 09:59:27 -0000 1.3
+++ b/mech-cram-md5.c 29 May 2004 21:40:30 -0000 1.4
@@ -149,15 +149,14 @@
static int
mech_cram_md5_auth_continue(struct auth_request *auth_request,
- struct auth_client_request_continue *request __attr_unused__,
- const unsigned char *data,
- mech_callback_t *callback)
+ const unsigned char *data, size_t data_size,
+ mech_callback_t *callback)
{
struct cram_auth_request *auth =
(struct cram_auth_request *)auth_request;
const char *error;
- if (parse_cram_response(auth, data, request->data_size, &error)) {
+ if (parse_cram_response(auth, data, data_size, &error)) {
auth_request->callback = callback;
auth_request->user =
@@ -186,16 +185,43 @@
return FALSE;
}
+static int
+mech_cram_md5_auth_initial(struct auth_request *auth_request,
+ struct auth_client_request_new *request,
+ const unsigned char *data __attr_unused__,
+ mech_callback_t *callback)
+{
+ struct cram_auth_request *auth =
+ (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;
+}
+
static void mech_cram_md5_auth_free(struct auth_request *auth_request)
{
pool_unref(auth_request->pool);
}
-static struct auth_request *
-mech_cram_md5_auth_new(struct auth_client_connection *conn,
- unsigned int id, mech_callback_t *callback)
+static struct auth_request *mech_cram_md5_auth_new(void)
{
- struct auth_client_request_reply reply;
struct cram_auth_request *auth;
pool_t pool;
@@ -205,25 +231,21 @@
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;
- auth->challenge = p_strdup(auth->pool, get_cram_challenge());
-
- /* initialize reply */
- mech_init_auth_client_reply(&reply);
- reply.id = 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, conn);
-
return &auth->auth_request;
}
struct mech_module mech_cram_md5 = {
- AUTH_MECH_CRAM_MD5,
+ "CRAM-MD5",
+
+ MEMBER(plaintext) FALSE,
+ MEMBER(advertise) TRUE,
+
+ MEMBER(passdb_need_plain) FALSE,
+ MEMBER(passdb_need_credentials) TRUE,
+
mech_cram_md5_auth_new
};
Index: mech-digest-md5.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech-digest-md5.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- a/mech-digest-md5.c 6 Jan 2004 05:09:22 -0000 1.19
+++ b/mech-digest-md5.c 29 May 2004 21:40:30 -0000 1.20
@@ -525,8 +525,7 @@
static int
mech_digest_md5_auth_continue(struct auth_request *auth_request,
- struct auth_client_request_continue *request,
- const unsigned char *data,
+ const unsigned char *data, size_t data_size,
mech_callback_t *callback)
{
struct digest_auth_request *auth =
@@ -536,7 +535,7 @@
/* initialize reply */
mech_init_auth_client_reply(&reply);
- reply.id = request->id;
+ reply.id = auth_request->id;
if (auth->authenticated) {
/* authentication is done, we were just waiting the last
@@ -545,7 +544,7 @@
return TRUE;
}
- if (parse_digest_response(auth, data, request->data_size, &error)) {
+ if (parse_digest_response(auth, data, data_size, &error)) {
auth_request->callback = callback;
realm = auth->realm != NULL ? auth->realm : default_realm;
@@ -582,19 +581,50 @@
return FALSE;
}
+static int
+mech_digest_md5_auth_initial(struct auth_request *auth_request,
+ struct auth_client_request_new *request,
+ const unsigned char *data __attr_unused__,
+ mech_callback_t *callback)
+{
+ struct digest_auth_request *auth =
+ (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)) {
+ /* 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);
+ }
+
+ /* 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;
+}
+
static void mech_digest_md5_auth_free(struct auth_request *auth_request)
{
pool_unref(auth_request->pool);
}
static struct auth_request *
-mech_digest_md5_auth_new(struct auth_client_connection *conn,
- unsigned int id, mech_callback_t *callback)
+mech_digest_md5_auth_new(void)
{
- struct auth_client_request_reply reply;
struct digest_auth_request *auth;
pool_t pool;
- string_t *challenge;
pool = pool_alloconly_create("digest_md5_auth_request", 2048);
auth = p_new(pool, struct digest_auth_request, 1);
@@ -602,25 +632,21 @@
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;
-
- /* initialize reply */
- mech_init_auth_client_reply(&reply);
- reply.id = 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), conn);
-
return &auth->auth_request;
}
struct mech_module mech_digest_md5 = {
- AUTH_MECH_DIGEST_MD5,
+ "DIGEST-MD5",
+
+ MEMBER(plaintext) FALSE,
+ MEMBER(advertise) TRUE,
+
+ MEMBER(passdb_need_plain) FALSE,
+ MEMBER(passdb_need_credentials) TRUE,
+
mech_digest_md5_auth_new
};
Index: mech-plain.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech-plain.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- a/mech-plain.c 21 Sep 2003 16:21:36 -0000 1.16
+++ b/mech-plain.c 29 May 2004 21:40:30 -0000 1.17
@@ -13,8 +13,8 @@
static int
mech_plain_auth_continue(struct auth_request *auth_request,
- struct auth_client_request_continue *request,
- const unsigned char *data, mech_callback_t *callback)
+ const unsigned char *data, size_t data_size,
+ mech_callback_t *callback)
{
const char *authid, *authenid;
char *pass;
@@ -28,13 +28,13 @@
authenid = NULL; pass = "";
count = 0;
- for (i = 0; i < request->data_size; i++) {
+ for (i = 0; i < data_size; i++) {
if (data[i] == '\0') {
if (++count == 1)
authenid = (const char *) data + i+1;
else {
i++;
- len = request->data_size - i;
+ len = data_size - i;
pass = p_strndup(unsafe_data_stack_pool,
data+i, len);
break;
@@ -76,37 +76,61 @@
return TRUE;
}
+static int
+mech_plain_auth_initial(struct auth_request *auth_request,
+ struct auth_client_request_new *request,
+ const unsigned char *data,
+ 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;
+}
+
static void
mech_plain_auth_free(struct auth_request *auth_request)
{
pool_unref(auth_request->pool);
}
-static struct auth_request *
-mech_plain_auth_new(struct auth_client_connection *conn, unsigned int id,
- mech_callback_t *callback)
+static struct auth_request *mech_plain_auth_new(void)
{
struct auth_request *auth_request;
- struct auth_client_request_reply reply;
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;
-
- /* initialize reply */
- memset(&reply, 0, sizeof(reply));
- reply.id = id;
- reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
- callback(&reply, NULL, conn);
return auth_request;
}
struct mech_module mech_plain = {
- AUTH_MECH_PLAIN,
+ "PLAIN",
+
+ MEMBER(plaintext) TRUE,
+ MEMBER(advertise) FALSE,
+
+ MEMBER(passdb_need_plain) TRUE,
+ MEMBER(passdb_need_credentials) FALSE,
+
mech_plain_auth_new
};
Index: mech.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- a/mech.c 29 May 2004 17:06:50 -0000 1.21
+++ b/mech.c 29 May 2004 21:40:30 -0000 1.22
@@ -5,19 +5,14 @@
#include "buffer.h"
#include "hash.h"
#include "mech.h"
+#include "str.h"
#include "var-expand.h"
#include "auth-client-connection.h"
#include "auth-master-connection.h"
#include <stdlib.h>
-struct mech_module_list {
- struct mech_module_list *next;
-
- struct mech_module module;
-};
-
-enum auth_mech auth_mechanisms;
+struct mech_module_list *mech_modules;
const char *const *auth_realms;
const char *default_realm;
const char *anonymous_username;
@@ -25,17 +20,12 @@
static int set_use_cyrus_sasl;
static int ssl_require_client_cert;
-static struct mech_module_list *mech_modules;
static struct auth_client_request_reply failure_reply;
void mech_register_module(struct mech_module *module)
{
struct mech_module_list *list;
- i_assert((auth_mechanisms & module->mech) == 0);
-
- auth_mechanisms |= module->mech;
-
list = i_new(struct mech_module_list, 1);
list->module = *module;
@@ -47,13 +37,8 @@
{
struct mech_module_list **pos, *list;
- if ((auth_mechanisms & module->mech) == 0)
- return; /* not registered */
-
- auth_mechanisms &= ~module->mech;
-
for (pos = &mech_modules; *pos != NULL; pos = &(*pos)->next) {
- if ((*pos)->module.mech == module->mech) {
+ if (strcmp((*pos)->module.mech_name, module->mech_name) == 0) {
list = *pos;
*pos = (*pos)->next;
i_free(list);
@@ -62,17 +47,56 @@
}
}
+const string_t *auth_mechanisms_get_list(void)
+{
+ struct mech_module_list *list;
+ string_t *str;
+
+ str = t_str_new(128);
+ for (list = mech_modules; list != NULL; list = list->next)
+ str_append(str, list->module.mech_name);
+
+ return str;
+}
+
+static struct mech_module *mech_module_find(const char *name)
+{
+ struct mech_module_list *list;
+
+ for (list = mech_modules; list != NULL; list = list->next) {
+ if (strcmp(list->module.mech_name, name) == 0)
+ return &list->module;
+ }
+ 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_list *list;
+ struct mech_module *mech;
struct auth_request *auth_request;
- if ((auth_mechanisms & request->mech) == 0) {
+ /* make sure data is NUL-terminated */
+ if (request->data_size == 0 || 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 %d", conn->pid, request->mech);
+ "auth mechanism %s", conn->pid,
+ (const char *)data + request->mech_idx);
failure_reply.id = request->id;
callback(&failure_reply, NULL, conn);
return;
@@ -89,32 +113,26 @@
}
#ifdef USE_CYRUS_SASL2
- if (set_use_cyrus_sasl) {
+ if (set_use_cyrus_sasl)
auth_request = mech_cyrus_sasl_new(conn, request, callback);
- } else
+ else
#endif
- {
- auth_request = NULL;
-
- for (list = mech_modules; list != NULL; list = list->next) {
- if (list->module.mech == request->mech) {
- auth_request =
- list->module.auth_new(conn, request->id,
- callback);
- break;
- }
- }
- }
+ auth_request = mech->auth_new();
if (auth_request != NULL) {
auth_request->created = ioloop_time;
auth_request->conn = conn;
auth_request->id = request->id;
- strocpy(auth_request->protocol, request->protocol,
- sizeof(auth_request->protocol));
+ auth_request->protocol =
+ p_strdup(auth_request->pool,
+ (const char *)data + request->protocol_idx);
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);
}
}
@@ -133,7 +151,8 @@
callback(&failure_reply, NULL, conn);
} else {
if (!auth_request->auth_continue(auth_request,
- request, data, callback))
+ data, request->data_size,
+ callback))
mech_request_free(auth_request, request->id);
}
}
@@ -276,7 +295,6 @@
const char *env;
mech_modules = NULL;
- auth_mechanisms = 0;
memset(&failure_reply, 0, sizeof(failure_reply));
failure_reply.result = AUTH_CLIENT_RESULT_FAILURE;
@@ -312,7 +330,7 @@
mechanisms++;
}
- if (auth_mechanisms == 0)
+ if (mech_modules == NULL)
i_fatal("No authentication mechanisms configured");
/* get our realm - note that we allocate from data stack so
Index: mech.h
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- a/mech.h 29 May 2004 17:06:50 -0000 1.15
+++ b/mech.h 29 May 2004 21:40:30 -0000 1.16
@@ -19,26 +19,38 @@
unsigned int id;
time_t created;
- char protocol[AUTH_CLIENT_PROTOCOL_BUF_SIZE];
+ char *protocol;
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,
- struct auth_client_request_continue *request,
- const unsigned char *data,
+ const unsigned char *data, size_t data_size,
mech_callback_t *callback);
void (*auth_free)(struct auth_request *auth_request);
/* ... mechanism specific data ... */
};
struct mech_module {
- enum auth_mech mech;
+ const char *mech_name;
- struct auth_request *(*auth_new)(struct auth_client_connection *conn,
- unsigned int id,
- mech_callback_t *callback);
+ unsigned int plaintext:1;
+ unsigned int advertise:1;
+ unsigned int passdb_need_plain:1;
+ unsigned int passdb_need_credentials:1;
+
+ struct auth_request *(*auth_new)(void);
};
-extern enum auth_mech auth_mechanisms;
+struct mech_module_list {
+ struct mech_module_list *next;
+
+ struct mech_module module;
+};
+
+extern struct mech_module_list *mech_modules;
extern const char *const *auth_realms;
extern const char *default_realm;
extern const char *anonymous_username;
@@ -48,8 +60,11 @@
void mech_register_module(struct mech_module *module);
void mech_unregister_module(struct mech_module *module);
+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,
@@ -70,6 +85,7 @@
struct auth_request *
mech_cyrus_sasl_new(struct auth_client_connection *conn,
struct auth_client_request_new *request,
+ const unsigned char *data,
mech_callback_t *callback);
void auth_request_ref(struct auth_request *request);
Index: passdb.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/passdb.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- a/passdb.c 10 May 2004 01:47:09 -0000 1.14
+++ b/passdb.c 29 May 2004 21:40:30 -0000 1.15
@@ -71,6 +71,26 @@
callback(password, auth_request);
}
+static void
+mech_list_verify_passdb(struct passdb_module *passdb, const char *name)
+{
+ struct mech_module_list *list;
+
+ for (list = mech_modules; list != NULL; list = list->next) {
+ if (list->module.passdb_need_plain &&
+ passdb->verify_plain == NULL)
+ break;
+ if (list->module.passdb_need_credentials &&
+ passdb->lookup_credentials == NULL)
+ break;
+ }
+
+ if (list != NULL) {
+ i_fatal("Passdb %s doesn't support %s method",
+ name, list->module.mech_name);
+ }
+}
+
void passdb_init(void)
{
const char *name, *args;
@@ -135,17 +155,7 @@
if (passdb->init != NULL)
passdb->init(args != NULL ? args+1 : "");
- if ((auth_mechanisms & AUTH_MECH_PLAIN) &&
- passdb->verify_plain == NULL)
- i_fatal("Passdb %s doesn't support PLAIN method", name);
-
- if ((auth_mechanisms & AUTH_MECH_CRAM_MD5) &&
- passdb->lookup_credentials == NULL)
- i_fatal("Passdb %s doesn't support CRAM-MD5 method", name);
-
- if ((auth_mechanisms & AUTH_MECH_DIGEST_MD5) &&
- passdb->lookup_credentials == NULL)
- i_fatal("Passdb %s doesn't support DIGEST-MD5 method", name);
+ mech_list_verify_passdb(passdb, name);
}
void passdb_deinit(void)
--- auth-mech-desc.h DELETED ---
More information about the dovecot-cvs
mailing list