[dovecot-cvs] dovecot/src/lib-auth auth-client.c, 1.2, 1.3 auth-client.h, 1.3, 1.4 auth-server-connection.c, 1.3, 1.4 auth-server-connection.h, 1.2, 1.3 auth-server-request.c, 1.8, 1.9

cras at procontrol.fi cras at procontrol.fi
Sun May 30 00:40:33 EEST 2004


Update of /home/cvs/dovecot/src/lib-auth
In directory talvi:/tmp/cvs-serv30244/lib-auth

Modified Files:
	auth-client.c auth-client.h auth-server-connection.c 
	auth-server-connection.h auth-server-request.c 
Log Message:
Removed hardcoded mechanism lists. It's now possible to add them
dynamically. Added support for SASL initial response.



Index: auth-client.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-auth/auth-client.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- a/auth-client.c	22 Aug 2003 03:34:04 -0000	1.2
+++ b/auth-client.c	29 May 2004 21:40:30 -0000	1.3
@@ -1,6 +1,7 @@
 /* Copyright (C) 2003 Timo Sirainen */
 
 #include "lib.h"
+#include "buffer.h"
 #include "ioloop.h"
 #include "hash.h"
 #include "auth-client.h"
@@ -15,6 +16,8 @@
 
 	client = i_new(struct auth_client, 1);
 	client->pid = client_pid;
+	client->available_auth_mechs =
+		buffer_create_dynamic(default_pool, 128, (size_t)-1);
 
 	auth_client_connect_missing_servers(client);
 	return client;
@@ -23,6 +26,14 @@
 void auth_client_free(struct auth_client *client)
 {
 	struct auth_server_connection *next;
+	struct auth_mech_desc *mech;
+	size_t i, size;
+
+	mech = buffer_get_modifyable_data(client->available_auth_mechs, &size);
+	size /= sizeof(*mech);
+	for (i = 0; i < size; i++)
+		i_free(mech[i].name);
+	buffer_free(client->available_auth_mechs);
 
 	while (client->connections != NULL) {
 		next = client->connections->next;
@@ -35,9 +46,32 @@
 	i_free(client);
 }
 
-enum auth_mech auth_client_get_available_mechs(struct auth_client *client)
+const struct auth_mech_desc *
+auth_client_get_available_mechs(struct auth_client *client,
+				unsigned int *mech_count)
 {
-	return client->available_auth_mechs;
+	const struct auth_mech_desc *mechs;
+	size_t size;
+
+	mechs = buffer_get_data(client->available_auth_mechs, &size);
+	*mech_count = size / sizeof(*mechs);
+	return mechs;
+}
+
+const struct auth_mech_desc *
+auth_client_find_mech(struct auth_client *client, const char *name)
+{
+	const struct auth_mech_desc *mech;
+	size_t i, size;
+
+	mech = buffer_get_data(client->available_auth_mechs, &size);
+	size /= sizeof(*mech);
+	for (i = 0; i < size; i++) {
+		if (strcasecmp(mech[i].name, name) == 0)
+			return &mech[i];
+	}
+
+	return NULL;
 }
 
 int auth_client_is_connected(struct auth_client *client)

Index: auth-client.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-auth/auth-client.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- a/auth-client.h	29 May 2004 17:06:49 -0000	1.3
+++ b/auth-client.h	29 May 2004 21:40:30 -0000	1.4
@@ -6,6 +6,12 @@
 struct auth_client;
 struct auth_request;
 
+struct auth_mech_desc {
+	char *name;
+	unsigned int plaintext:1;
+	unsigned int advertise:1;
+};
+
 /* reply is NULL if auth connection died */
 typedef void auth_request_callback_t(struct auth_request *request,
 				     struct auth_client_request_reply *reply,
@@ -22,7 +28,11 @@
 void auth_client_set_connect_notify(struct auth_client *client,
 				    auth_connect_notify_callback_t *callback,
 				    void *context);
-enum auth_mech auth_client_get_available_mechs(struct auth_client *client);
+const struct auth_mech_desc *
+auth_client_get_available_mechs(struct auth_client *client,
+				unsigned int *mech_count);
+const struct auth_mech_desc *
+auth_client_find_mech(struct auth_client *client, const char *name);
 
 void auth_client_connect_missing_servers(struct auth_client *client);
 
@@ -30,8 +40,10 @@
    happens for the request. */
 struct auth_request *
 auth_client_request_new(struct auth_client *client,
-			enum auth_mech mech, const char *protocol,
+			const char *mech, const char *protocol,
 			enum auth_client_request_new_flags flags,
+			const unsigned char *initial_resp_data,
+			size_t initial_resp_size,
 			auth_request_callback_t *callback, void *context,
 			const char **error_r);
 

Index: auth-server-connection.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-auth/auth-server-connection.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- a/auth-server-connection.c	22 Aug 2003 06:37:57 -0000	1.3
+++ b/auth-server-connection.c	29 May 2004 21:40:30 -0000	1.4
@@ -1,6 +1,7 @@
 /* Copyright (C) 2003 Timo Sirainen */
 
 #include "lib.h"
+#include "buffer.h"
 #include "hash.h"
 #include "ioloop.h"
 #include "istream.h"
@@ -21,30 +22,78 @@
 
 static void auth_server_connection_unref(struct auth_server_connection *conn);
 
-static void update_available_auth_mechs(struct auth_client *client)
+static void update_available_auth_mechs(struct auth_server_connection *conn)
 {
-	struct auth_server_connection *conn;
+	struct auth_client *client = conn->client;
+	const struct auth_mech_desc *mech;
+	struct auth_mech_desc *new_mech;
+	unsigned int i;
 
-        client->available_auth_mechs = 0;
-	for (conn = client->connections; conn != NULL; conn = conn->next)
-                client->available_auth_mechs |= conn->available_auth_mechs;
+	mech = conn->available_auth_mechs;
+	for (i = 0; i < conn->available_auth_mechs_count; i++) {
+		if (auth_client_find_mech(client, mech[i].name) == NULL) {
+			new_mech = buffer_append_space_unsafe(
+				client->available_auth_mechs, sizeof(*mech));
+			*new_mech = mech[i];
+			new_mech->name = i_strdup(mech[i].name);
+		}
+	}
 }
 
 static void auth_handle_handshake(struct auth_server_connection *conn,
-				  struct auth_client_handshake_reply *handshake)
+				  struct auth_client_handshake_reply *handshake,
+				  const unsigned char *data)
 {
+	struct auth_client_handshake_mech_desc handshake_mech_desc;
+	struct auth_mech_desc mech_desc;
+	buffer_t *buf;
+	unsigned int i;
+
 	if (handshake->server_pid == 0) {
 		i_error("BUG: Auth server said it's PID 0");
 		auth_server_connection_destroy(conn, FALSE);
 		return;
 	}
 
+	if (handshake->data_size == 0 || data[handshake->data_size-1] != '\0' ||
+	    handshake->mech_count * sizeof(handshake_mech_desc) >=
+	    handshake->data_size)  {
+		i_error("BUG: Auth server sent corrupted handshake");
+		auth_server_connection_destroy(conn, FALSE);
+		return;
+	}
+
+	buf = buffer_create_dynamic(conn->pool, sizeof(mech_desc) *
+				    handshake->mech_count, (size_t)-1);
+	for (i = 0; i < handshake->mech_count; i++) {
+		memcpy(&handshake_mech_desc,
+		       data + sizeof(handshake_mech_desc) * i,
+		       sizeof(handshake_mech_desc));
+
+		if (handshake_mech_desc.name_idx >= handshake->data_size) {
+			i_error("BUG: Auth server sent corrupted handshake");
+			auth_server_connection_destroy(conn, FALSE);
+			return;
+		}
+
+		mech_desc.name = p_strdup(conn->pool, (const char *)data +
+					  handshake_mech_desc.name_idx);
+		mech_desc.plaintext = handshake_mech_desc.plaintext;
+		mech_desc.advertise = handshake_mech_desc.advertise;
+		buffer_append(buf, &mech_desc, sizeof(mech_desc));
+
+		if (strcmp(mech_desc.name, "PLAIN") == 0)
+			conn->has_plain_mech = TRUE;
+	}
+
 	conn->pid = handshake->server_pid;
-	conn->available_auth_mechs = handshake->auth_mechanisms;
+	conn->available_auth_mechs_count =
+		buffer_get_used_size(buf) / sizeof(mech_desc);
+	conn->available_auth_mechs = buffer_free_without_data(buf);
 	conn->handshake_received = TRUE;
 
         conn->client->conn_waiting_handshake_count--;
-	update_available_auth_mechs(conn->client);
+	update_available_auth_mechs(conn);
 
 	if (conn->client->connect_notify_callback != NULL &&
 	    auth_client_is_connected(conn->client)) {
@@ -77,17 +126,19 @@
 
 	if (!conn->handshake_received) {
 		data = i_stream_get_data(conn->input, &size);
-		if (size == sizeof(handshake)) {
-			memcpy(&handshake, data, sizeof(handshake));
-			i_stream_skip(conn->input, sizeof(handshake));
+		if (size < sizeof(handshake))
+			return;
 
-			auth_handle_handshake(conn, &handshake);
-		} else if (size > sizeof(handshake)) {
-			i_error("BUG: Auth server sent us too large handshake "
-				"(%"PRIuSIZE_T " vs %"PRIuSIZE_T")", size,
-				sizeof(handshake));
-			auth_server_connection_destroy(conn, FALSE);
-		}
+		memcpy(&handshake, data, sizeof(handshake));
+		if (size < sizeof(handshake) + handshake.data_size)
+			return;
+
+		conn->refcount++;
+		auth_handle_handshake(conn, &handshake,
+				      data + sizeof(handshake));
+		i_stream_skip(conn->input, sizeof(handshake) +
+			      handshake.data_size);
+		auth_server_connection_unref(conn);
 		return;
 	}
 
@@ -210,6 +261,7 @@
 {
 	if (--conn->refcount > 0)
 		return;
+	i_assert(conn->refcount == 0);
 
 	hash_destroy(conn->requests);
 
@@ -233,16 +285,21 @@
 
 struct auth_server_connection *
 auth_server_connection_find_mech(struct auth_client *client,
-				 enum auth_mech mech, const char **error_r)
+				 const char *name, const char **error_r)
 {
 	struct auth_server_connection *conn;
+	const struct auth_mech_desc *mech;
+	unsigned int i;
 
 	for (conn = client->connections; conn != NULL; conn = conn->next) {
-		if ((conn->available_auth_mechs & mech))
-			return conn;
+		mech = conn->available_auth_mechs;
+		for (i = 0; i < conn->available_auth_mechs_count; i++) {
+			if (strcmp(mech[i].name, name) == 0)
+				return conn;
+		}
 	}
 
-	if ((client->available_auth_mechs & mech) == 0)
+	if (auth_client_find_mech(client, name) == NULL)
 		*error_r = "Unsupported authentication mechanism";
 	else {
 		*error_r = "Authentication server isn't connected, "

Index: auth-server-connection.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-auth/auth-server-connection.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- a/auth-server-connection.h	22 Aug 2003 06:37:57 -0000	1.2
+++ b/auth-server-connection.h	29 May 2004 21:40:30 -0000	1.3
@@ -9,7 +9,7 @@
 
 	unsigned int conn_waiting_handshake_count;
 
-	enum auth_mech available_auth_mechs;
+	buffer_t *available_auth_mechs;
 	unsigned int request_id_counter;
 
 	auth_connect_notify_callback_t *connect_notify_callback;
@@ -31,13 +31,15 @@
 	struct ostream *output;
 
 	unsigned int pid;
-	enum auth_mech available_auth_mechs;
+	const struct auth_mech_desc *available_auth_mechs;
+	unsigned int available_auth_mechs_count;
         struct auth_client_request_reply reply;
 
         struct hash_table *requests;
 
 	unsigned int handshake_received:1;
 	unsigned int reply_received:1;
+	unsigned int has_plain_mech:1;
 };
 
 struct auth_server_connection *
@@ -50,6 +52,6 @@
 
 struct auth_server_connection *
 auth_server_connection_find_mech(struct auth_client *client,
-				 enum auth_mech mech, const char **error_r);
+				 const char *name, const char **error_r);
 
 #endif

Index: auth-server-request.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-auth/auth-server-request.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- a/auth-server-request.c	29 May 2004 17:06:49 -0000	1.8
+++ b/auth-server-request.c	29 May 2004 21:40:30 -0000	1.9
@@ -1,6 +1,7 @@
 /* Copyright (C) 2003 Timo Sirainen */
 
 #include "lib.h"
+#include "buffer.h"
 #include "hash.h"
 #include "ostream.h"
 #include "auth-client.h"
@@ -10,12 +11,14 @@
 struct auth_request {
         struct auth_server_connection *conn;
 
-	enum auth_mech mech;
-	char protocol[AUTH_CLIENT_PROTOCOL_BUF_SIZE];
+	char *mech, *protocol;
 	enum auth_client_request_new_flags flags;
 
 	unsigned int id;
 
+	unsigned char *initial_resp_data;
+	size_t initial_resp_size;
+
 	auth_request_callback_t *callback;
 	void *context;
 
@@ -31,16 +34,42 @@
 					struct auth_request *request)
 {
 	struct auth_client_request_new auth_request;
+	buffer_t *buf;
+	int ret;
 
+	memset(&auth_request, 0, sizeof(auth_request));
 	auth_request.type = AUTH_CLIENT_REQUEST_NEW;
 	auth_request.id = request->id;
-	strocpy(auth_request.protocol, request->protocol,
-		sizeof(auth_request.protocol));
-	auth_request.mech = request->mech;
 	auth_request.flags = request->flags;
 
-	if (o_stream_send(conn->output, &auth_request,
-			  sizeof(auth_request)) < 0) {
+	t_push();
+	buf = buffer_create_dynamic(pool_datastack_create(), 256, (size_t)-1);
+	buffer_set_used_size(buf, sizeof(auth_request));
+
+	auth_request.mech_idx =
+		buffer_get_used_size(buf) - sizeof(auth_request);
+	buffer_append(buf, request->mech, strlen(request->mech)+1);
+
+	auth_request.protocol_idx =
+		buffer_get_used_size(buf) - sizeof(auth_request);
+	buffer_append(buf, request->protocol, strlen(request->protocol)+1);
+
+	auth_request.initial_resp_idx =
+		buffer_get_used_size(buf) - sizeof(auth_request);
+	buffer_append(buf, request->initial_resp_data,
+		      request->initial_resp_size);
+
+	auth_request.data_size =
+		buffer_get_used_size(buf) - sizeof(auth_request);
+
+	memcpy(buffer_get_space_unsafe(buf, 0, sizeof(auth_request)),
+	       &auth_request, sizeof(auth_request));
+
+	ret = o_stream_send(conn->output, buffer_get_data(buf, NULL),
+			    buffer_get_used_size(buf));
+	t_pop();
+
+	if (ret < 0) {
 		errno = conn->output->stream_errno;
 		i_warning("Error sending request to auth server: %m");
 		auth_server_connection_destroy(conn, TRUE);
@@ -75,7 +104,7 @@
 {
 	conn = conn->next;
 	while (conn != NULL) {
-		if ((conn->available_auth_mechs & AUTH_MECH_PLAIN) != 0)
+		if (conn->has_plain_mech)
 			return conn;
 		conn = conn->next;
 	}
@@ -179,8 +208,10 @@
 
 struct auth_request *
 auth_client_request_new(struct auth_client *client,
-			enum auth_mech mech, const char *protocol,
+			const char *mech, const char *protocol,
 			enum auth_client_request_new_flags flags,
+			const unsigned char *initial_resp_data,
+			size_t initial_resp_size,
 			auth_request_callback_t *callback, void *context,
 			const char **error_r)
 {
@@ -193,10 +224,18 @@
 
 	request = i_new(struct auth_request, 1);
 	request->conn = conn;
-	request->mech = mech;
-	strocpy(request->protocol, protocol, sizeof(request->protocol));
+	request->mech = i_strdup(mech);
+	request->protocol = i_strdup(protocol);
 	request->flags = flags;
 	request->id = ++client->request_id_counter;
+
+	if (initial_resp_size != 0) {
+		request->initial_resp_size = initial_resp_size;
+		request->initial_resp_data = i_malloc(initial_resp_size);
+		memcpy(request->initial_resp_data, initial_resp_data,
+		       initial_resp_size);
+	}
+	
 	if (request->id == 0) {
 		/* wrapped - ID 0 not allowed */
 		request->id = ++client->request_id_counter;
@@ -216,8 +255,8 @@
 {
 	auth_server_send_continue(request->conn, request, data, data_size);
 
-	if (request->mech == AUTH_MECH_PLAIN &&
-	    request->plaintext_data == NULL) {
+	if (strcmp(request->mech, "PLAIN") == 0 &&
+	    request->plaintext_data == NULL && request->conn != NULL) {
 		request->next_conn = get_next_plain_server(request->conn);
 		if (request->next_conn != NULL) {
 			/* plaintext authentication - save the data so we can
@@ -245,7 +284,10 @@
 
 	request->callback(request, NULL, NULL, request->context);
 
+	i_free(request->initial_resp_data);
 	i_free(request->plaintext_data);
+	i_free(request->mech);
+	i_free(request->protocol);
 	i_free(request);
 }
 



More information about the dovecot-cvs mailing list