[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