]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Moved client side code for auth process handling to lib-auth. Some other login proces...
authorTimo Sirainen <tss@iki.fi>
Fri, 22 Aug 2003 02:42:12 +0000 (05:42 +0300)
committerTimo Sirainen <tss@iki.fi>
Fri, 22 Aug 2003 02:42:12 +0000 (05:42 +0300)
--HG--
branch : HEAD

48 files changed:
configure.in
src/Makefile.am
src/auth/Makefile.am
src/auth/auth-client-connection.c [new file with mode: 0644]
src/auth/auth-client-connection.h [new file with mode: 0644]
src/auth/auth-client-interface.h [new file with mode: 0644]
src/auth/auth-login-interface.h [deleted file]
src/auth/auth-master-connection.c [new file with mode: 0644]
src/auth/auth-master-connection.h [new file with mode: 0644]
src/auth/auth-master-interface.h
src/auth/login-connection.c [deleted file]
src/auth/login-connection.h [deleted file]
src/auth/main.c
src/auth/master-connection.c [deleted file]
src/auth/master-connection.h [deleted file]
src/auth/mech-anonymous.c
src/auth/mech-digest-md5.c
src/auth/mech-plain.c
src/auth/mech.c
src/auth/mech.h
src/imap-login/Makefile.am
src/imap-login/client-authenticate.c
src/imap-login/client.c
src/imap-login/client.h
src/imap-login/common.h [deleted file]
src/lib-auth/.cvsignore [new file with mode: 0644]
src/lib-auth/Makefile.am [new file with mode: 0644]
src/lib-auth/auth-client.c [new file with mode: 0644]
src/lib-auth/auth-client.h [new file with mode: 0644]
src/lib-auth/auth-server-connection.c [new file with mode: 0644]
src/lib-auth/auth-server-connection.h [new file with mode: 0644]
src/lib-auth/auth-server-request.c [new file with mode: 0644]
src/lib-auth/auth-server-request.h [new file with mode: 0644]
src/login-common/Makefile.am
src/login-common/auth-common.c
src/login-common/auth-common.h
src/login-common/auth-connection.c [deleted file]
src/login-common/auth-connection.h [deleted file]
src/login-common/client-common.h
src/login-common/common.h
src/login-common/main.c
src/login-common/master.c
src/login-common/master.h
src/pop3-login/Makefile.am
src/pop3-login/client-authenticate.c
src/pop3-login/client.c
src/pop3-login/client.h
src/pop3-login/common.h [deleted file]

index 66dbb6c62a74ee60be62346d23256c3abcc9c9f5..f4c61e5b91bf4a7ffd994e04a56de7d152640b72 100644 (file)
@@ -1096,6 +1096,7 @@ Makefile
 doc/Makefile
 src/Makefile
 src/lib/Makefile
+src/lib-auth/Makefile
 src/lib-charset/Makefile
 src/lib-imap/Makefile
 src/lib-index/Makefile
index d76ee8bb46d01a8d0ec9de21626e5cfb5a344718..f5059b15efc9cef70f6fa3e3d9f31dc95f31b1c4 100644 (file)
@@ -2,4 +2,4 @@ if BUILD_POP3D
 POP3D = pop3-login pop3
 endif
 
-SUBDIRS = lib lib-settings lib-charset lib-mail lib-imap lib-index lib-storage auth master login-common imap-login imap $(POP3D) util
+SUBDIRS = lib lib-settings lib-charset lib-mail lib-imap lib-index lib-storage lib-auth auth master login-common imap-login imap $(POP3D) util
index 951c99a4929f897547ea0e5f4aadd72158875d8a..1cc13d8208792f30bcd9f7388ab759b3eeee4071 100644 (file)
@@ -16,13 +16,13 @@ dovecot_auth_LDADD = \
        $(MODULE_LIBS)
 
 dovecot_auth_SOURCES = \
+       auth-client-connection.c \
+       auth-master-connection.c \
        auth-module.c \
        db-ldap.c \
        db-pgsql.c \
        db-passwd-file.c \
-       login-connection.c \
        main.c \
-       master-connection.c \
        md5crypt.c \
        mech.c \
        mech-anonymous.c \
@@ -48,7 +48,9 @@ dovecot_auth_SOURCES = \
        userdb-pgsql.c
 
 noinst_HEADERS = \
-       auth-login-interface.h \
+       auth-client-connection.h \
+       auth-client-interface.h \
+       auth-master-connection.h \
        auth-master-interface.h \
        auth-mech-desc.h \
        auth-module.h \
@@ -56,8 +58,6 @@ noinst_HEADERS = \
        db-pgsql.h \
        db-passwd-file.h \
        common.h \
-       login-connection.h \
-       master-connection.h \
        md5crypt.h \
        mech.h \
        mycrypt.h \
diff --git a/src/auth/auth-client-connection.c b/src/auth/auth-client-connection.c
new file mode 100644 (file)
index 0000000..1d01046
--- /dev/null
@@ -0,0 +1,308 @@
+/* Copyright (C) 2002-2003 Timo Sirainen */
+
+#include "common.h"
+#include "ioloop.h"
+#include "istream.h"
+#include "ostream.h"
+#include "network.h"
+#include "hash.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)
+#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)
+{
+       ssize_t ret;
+
+       ret = o_stream_send(conn->output, reply, sizeof(*reply));
+       if ((size_t)ret == sizeof(*reply)) {
+               if (reply->data_size == 0) {
+                       /* all sent */
+                       auth_client_connection_unref(conn);
+                       return;
+               }
+
+               ret = o_stream_send(conn->output, data, reply->data_size);
+               if ((size_t)ret == reply->data_size) {
+                       /* all sent */
+                       auth_client_connection_unref(conn);
+                       return;
+               }
+       }
+
+       if (ret >= 0) {
+               i_warning("Auth client %u: Transmit buffer full, killing it",
+                         conn->pid);
+       }
+
+       auth_client_connection_destroy(conn);
+       auth_client_connection_unref(conn);
+}
+
+struct auth_client_connection *
+auth_client_connection_lookup(struct auth_master_connection *master,
+                             unsigned int pid)
+{
+       struct auth_client_connection *conn;
+
+       for (conn = master->clients; conn != NULL; conn = conn->next) {
+               if (conn->pid == pid)
+                       return conn;
+       }
+
+       return NULL;
+}
+
+static void auth_client_input_handshake(struct auth_client_connection *conn)
+{
+        struct auth_client_handshake_request rec;
+        unsigned char *data;
+       size_t size;
+
+       data = i_stream_get_modifyable_data(conn->input, &size);
+       if (size < sizeof(rec))
+               return;
+
+       /* Don't just cast because of alignment issues. */
+       memcpy(&rec, data, sizeof(rec));
+       i_stream_skip(conn->input, sizeof(rec));
+
+       if (rec.client_pid == 0) {
+               i_error("BUG: Auth client said it's PID 0");
+               auth_client_connection_destroy(conn);
+       } else 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);
+       } else {
+               conn->pid = rec.client_pid;
+       }
+}
+
+static void auth_client_input_request(struct auth_client_connection *conn)
+{
+        enum auth_client_request_type type;
+        unsigned char *data;
+       size_t size;
+
+       data = i_stream_get_modifyable_data(conn->input, &size);
+       if (size < sizeof(type))
+               return;
+
+       /* 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));
+
+       if (type == 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));
+
+               /* we have a full init request */
+               conn->refcount++;
+               mech_request_new(conn, &request, request_callback);
+       } else if (type == AUTH_CLIENT_REQUEST_CONTINUE) {
+                struct auth_client_request_continue request;
+
+               if (size < sizeof(request))
+                       return;
+
+               memcpy(&request, data, sizeof(request));
+               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),
+                                     request_callback);
+
+               /* clear any sensitive data from memory */
+               safe_memset(data + sizeof(request), 0, request.data_size);
+       } else {
+               /* unknown request */
+               i_error("BUG: Auth client %u sent us unknown request %u",
+                       conn->pid, type);
+               auth_client_connection_destroy(conn);
+       }
+}
+
+static void auth_client_input(void *context)
+{
+       struct auth_client_connection *conn  = context;
+
+       switch (i_stream_read(conn->input)) {
+       case 0:
+               return;
+       case -1:
+               /* disconnected */
+               auth_client_connection_destroy(conn);
+               return;
+       case -2:
+               /* buffer full */
+               i_error("BUG: Auth client %u sent us more than %d bytes",
+                       conn->pid, (int)MAX_INBUF_SIZE);
+               auth_client_connection_destroy(conn);
+               return;
+       }
+
+       if (conn->pid == 0)
+               auth_client_input_handshake(conn);
+       else
+               auth_client_input_request(conn);
+}
+
+struct auth_client_connection *
+auth_client_connection_create(struct auth_master_connection *master, int fd)
+{
+       struct auth_client_connection *conn;
+       pool_t pool;
+
+       pool = pool_alloconly_create("Auth client", 4096);
+       conn = p_new(pool, struct auth_client_connection, 1);
+       conn->pool = pool;
+       conn->master = master;
+       conn->refcount = 1;
+
+       conn->fd = fd;
+       conn->input = i_stream_create_file(fd, default_pool, MAX_INBUF_SIZE,
+                                          FALSE);
+       conn->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
+                                           FALSE);
+       conn->io = io_add(fd, IO_READ, auth_client_input, conn);
+
+       conn->auth_requests = hash_create(default_pool, conn->pool,
+                                         0, NULL, NULL);
+
+       conn->next = master->clients;
+       master->clients = conn;
+
+       if (o_stream_send(conn->output, &master->handshake_reply,
+                         sizeof(master->handshake_reply)) < 0) {
+               auth_client_connection_destroy(conn);
+               conn = NULL;
+       }
+
+       return conn;
+}
+
+static void auth_request_hash_destroy(void *key __attr_unused__, void *value,
+                                     void *context __attr_unused__)
+{
+       struct auth_request *auth_request = value;
+
+       auth_request->auth_free(auth_request);
+}
+
+void auth_client_connection_destroy(struct auth_client_connection *conn)
+{
+       struct auth_client_connection **pos;
+
+       if (conn->fd == -1)
+               return;
+
+       for (pos = &conn->master->clients; *pos != NULL; pos = &(*pos)->next) {
+               if (*pos == conn) {
+                       *pos = conn->next;
+                       break;
+               }
+       }
+
+       i_stream_close(conn->input);
+       o_stream_close(conn->output);
+
+       io_remove(conn->io);
+       conn->io = 0;
+
+       net_disconnect(conn->fd);
+       conn->fd = -1;
+
+       conn->master = NULL;
+        auth_client_connection_unref(conn);
+}
+
+static void auth_client_connection_unref(struct auth_client_connection *conn)
+{
+       if (--conn->refcount > 0)
+               return;
+
+       hash_foreach(conn->auth_requests, auth_request_hash_destroy, NULL);
+       hash_destroy(conn->auth_requests);
+
+       i_stream_unref(conn->input);
+       o_stream_unref(conn->output);
+
+       pool_unref(conn->pool);
+}
+
+static void auth_request_hash_timeout_check(void *key __attr_unused__,
+                                           void *value, void *context)
+{
+       struct auth_client_connection *conn = context;
+       struct auth_request *auth_request = value;
+
+       if (auth_request->created + AUTH_REQUEST_TIMEOUT < ioloop_time) {
+               i_warning("Login process has too old (%us) requests, "
+                         "killing it.",
+                         (unsigned int)(ioloop_time - auth_request->created));
+
+               auth_client_connection_destroy(conn);
+               hash_foreach_stop();
+       }
+}
+
+static void request_timeout(void *context __attr_unused__)
+{
+        struct auth_master_connection *master = context;
+       struct auth_client_connection *conn;
+
+       for (conn = master->clients; conn != NULL; conn = conn->next) {
+               conn->refcount++;
+               hash_foreach(conn->auth_requests,
+                            auth_request_hash_timeout_check, conn);
+               auth_client_connection_unref(conn);
+       }
+}
+
+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);
+}
+
+void auth_client_connections_deinit(struct auth_master_connection *master)
+{
+       struct auth_client_connection *next;
+
+       while (master->clients != NULL) {
+               next = master->clients->next;
+               auth_client_connection_destroy(master->clients);
+               master->clients = next;
+       }
+
+       timeout_remove(master->to_clients);
+       master->to_clients = NULL;
+}
diff --git a/src/auth/auth-client-connection.h b/src/auth/auth-client-connection.h
new file mode 100644 (file)
index 0000000..4ca0534
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __AUTH_CLIENT_CONNECTION_H
+#define __AUTH_CLIENT_CONNECTION_H
+
+#include "auth-client-interface.h"
+
+struct auth_client_connection {
+       struct auth_client_connection *next;
+
+       struct auth_master_connection *master;
+       int refcount;
+
+       int fd;
+       struct io *io;
+       struct istream *input;
+       struct ostream *output;
+
+       pool_t pool;
+       struct hash_table *auth_requests;
+
+       unsigned int pid;
+};
+
+struct auth_client_connection *
+auth_client_connection_create(struct auth_master_connection *master, int fd);
+void auth_client_connection_destroy(struct auth_client_connection *conn);
+
+struct auth_client_connection *
+auth_client_connection_lookup(struct auth_master_connection *master,
+                             unsigned int pid);
+
+void auth_client_connections_init(struct auth_master_connection *master);
+void auth_client_connections_deinit(struct auth_master_connection *master);
+
+#endif
diff --git a/src/auth/auth-client-interface.h b/src/auth/auth-client-interface.h
new file mode 100644 (file)
index 0000000..3ccdcef
--- /dev/null
@@ -0,0 +1,79 @@
+#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_REQUEST_TIMEOUT 120
+
+enum auth_mech {
+       AUTH_MECH_PLAIN         = 0x01,
+       AUTH_MECH_DIGEST_MD5    = 0x02,
+       AUTH_MECH_ANONYMOUS     = 0x04,
+
+       AUTH_MECH_COUNT
+};
+
+enum auth_protocol {
+       AUTH_PROTOCOL_IMAP      = 0x01,
+       AUTH_PROTOCOL_POP3      = 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 */
+};
+
+/* Server -> Client */
+struct auth_client_handshake_reply {
+       unsigned int server_pid; /* unique auth process identifier */
+       enum auth_mech auth_mechanisms; /* valid authentication mechanisms */
+};
+
+/* 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_mech mech;
+       enum auth_protocol protocol;
+};
+
+/* 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;
+       /* 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. */
+       size_t username_idx; /* NUL-terminated */
+       size_t reply_idx; /* last, non-NUL terminated */
+
+       size_t data_size;
+       /* unsigned char data[]; */
+};
+
+#endif
diff --git a/src/auth/auth-login-interface.h b/src/auth/auth-login-interface.h
deleted file mode 100644 (file)
index cb8e386..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef __AUTH_LOGIN_INTERFACE_H
-#define __AUTH_LOGIN_INTERFACE_H
-
-/* max. size for auth_login_request_continue.data[] */
-#define AUTH_LOGIN_MAX_REQUEST_DATA_SIZE 4096
-
-/* Login 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_COUNT
-};
-
-enum auth_protocol {
-       AUTH_PROTOCOL_IMAP      = 0x01,
-       AUTH_PROTOCOL_POP3      = 0x02
-};
-
-enum auth_login_request_type {
-       AUTH_LOGIN_REQUEST_NEW = 1,
-        AUTH_LOGIN_REQUEST_CONTINUE
-};
-
-enum auth_login_result {
-       AUTH_LOGIN_RESULT_CONTINUE = 1,
-       AUTH_LOGIN_RESULT_SUCCESS,
-       AUTH_LOGIN_RESULT_FAILURE
-};
-
-/* Incoming handshake */
-struct auth_login_handshake_input {
-       unsigned int pid; /* unique identifier for client process */
-};
-
-/* Outgoing handshake */
-struct auth_login_handshake_output {
-       unsigned int pid; /* unique auth process identifier */
-       enum auth_mech auth_mechanisms; /* valid authentication mechanisms */
-};
-
-/* New authentication request */
-struct auth_login_request_new {
-       enum auth_login_request_type type; /* AUTH_LOGIN_REQUEST_NEW */
-       unsigned int id; /* unique ID for the request */
-
-       enum auth_mech mech;
-       enum auth_protocol protocol;
-};
-
-/* Continue authentication request */
-struct auth_login_request_continue {
-       enum auth_login_request_type type; /* AUTH_LOGIN_REQUEST_CONTINUE */
-       unsigned int id;
-
-       size_t data_size;
-       /* unsigned char data[]; */
-};
-
-/* Reply to authentication */
-struct auth_login_reply {
-       unsigned int id;
-
-       enum auth_login_result result;
-
-       /* 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 */
-
-       size_t data_size;
-       /* unsigned char data[]; */
-};
-
-#endif
diff --git a/src/auth/auth-master-connection.c b/src/auth/auth-master-connection.c
new file mode 100644 (file)
index 0000000..b14f1d5
--- /dev/null
@@ -0,0 +1,224 @@
+/* Copyright (C) 2002 Timo Sirainen */
+
+#include "common.h"
+#include "buffer.h"
+#include "hash.h"
+#include "ioloop.h"
+#include "ostream.h"
+#include "network.h"
+#include "mech.h"
+#include "userdb.h"
+#include "auth-client-connection.h"
+#include "auth-master-connection.h"
+
+#define MAX_OUTBUF_SIZE (1024*50)
+
+static struct auth_master_reply failure_reply =
+{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+struct master_userdb_request {
+       struct auth_master_connection *conn;
+       unsigned int tag;
+};
+
+static int auth_master_connection_unref(struct auth_master_connection *conn);
+
+static size_t reply_add(buffer_t *buf, const char *str)
+{
+       size_t index;
+
+       if (str == NULL || *str == '\0')
+               return (size_t)-1;
+
+       index = buffer_get_used_size(buf) - sizeof(struct auth_master_reply);
+       buffer_append(buf, str, strlen(str)+1);
+       return index;
+}
+
+static struct auth_master_reply *
+fill_reply(const struct user_data *user, size_t *reply_size)
+{
+       struct auth_master_reply reply, *reply_p;
+       buffer_t *buf;
+       char *p;
+
+       buf = buffer_create_dynamic(data_stack_pool,
+                                   sizeof(reply) + 256, (size_t)-1);
+       memset(&reply, 0, sizeof(reply));
+       buffer_append(buf, &reply, sizeof(reply));
+
+       reply.success = TRUE;
+
+       reply.uid = user->uid;
+       reply.gid = 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);
+
+       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);
+       } 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;
+       for (;;) {
+               ret = o_stream_send(conn->output, reply, reply_size);
+               if (ret < 0) {
+                       /* master died, kill ourself too */
+                       io_loop_stop(ioloop);
+                       break;
+               }
+
+               if ((size_t)ret == reply_size)
+                       break;
+
+               /* buffer full, we have to block */
+               i_warning("Master transmit buffer full, blocking..");
+               if (o_stream_flush(conn->output) < 0) {
+                       /* transmit error, probably master died */
+                       io_loop_stop(ioloop);
+                       break;
+               }
+       }
+}
+
+static void userdb_callback(struct user_data *user, void *context)
+{
+       struct master_userdb_request *master_request = context;
+       struct auth_master_reply *reply;
+       size_t reply_size;
+
+       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);
+               } else {
+                       reply = fill_reply(user, &reply_size);
+                       master_send_reply(master_request->conn, reply,
+                                         reply_size, master_request->tag);
+               }
+       }
+       i_free(master_request);
+}
+
+static void master_handle_request(struct auth_master_connection *conn,
+                                 struct auth_master_request *request)
+{
+       struct auth_client_connection *client_conn;
+       struct auth_request *auth_request;
+       struct master_userdb_request *master_request;
+
+       client_conn = auth_client_connection_lookup(conn, request->client_pid);
+       auth_request = client_conn == NULL ? NULL :
+               hash_lookup(client_conn->auth_requests,
+                           POINTER_CAST(request->id));
+
+       if (auth_request == NULL) {
+               if (verbose) {
+                       i_info("Master request %u.%u not found",
+                              request->client_pid, request->id);
+               }
+               master_send_reply(conn, &failure_reply, sizeof(failure_reply),
+                                 request->tag);
+       } else {
+               /* the auth request is finished, we don't need it anymore */
+               mech_request_free(client_conn, auth_request, request->id);
+
+               master_request = i_new(struct master_userdb_request, 1);
+               master_request->conn = conn;
+               master_request->tag = request->tag;
+
+               conn->refcount++;
+               userdb->lookup(auth_request->user, userdb_callback,
+                              master_request);
+       }
+}
+
+static void master_input(void *context)
+{
+       struct auth_master_connection *conn = context;
+       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 */
+               io_loop_stop(ioloop);
+               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;
+       }
+}
+
+struct auth_master_connection *
+auth_master_connection_new(int fd, unsigned int pid)
+{
+       struct auth_master_connection *conn;
+
+       conn = i_new(struct auth_master_connection, 1);
+       conn->refcount = 1;
+       conn->pid = pid;
+       conn->fd = fd;
+       conn->output = o_stream_create_file(MASTER_SOCKET_FD, default_pool,
+                                           MAX_OUTBUF_SIZE, FALSE);
+       conn->io = io_add(MASTER_SOCKET_FD, IO_READ, master_input, conn);
+
+       /* just a note to master that we're ok. if we die before,
+          master should shutdown itself. */
+       o_stream_send(conn->output, "O", 1);
+       return conn;
+}
+
+void auth_master_connection_free(struct auth_master_connection *conn)
+{
+       if (conn->fd == -1)
+               return;
+
+       conn->fd = -1;
+       o_stream_close(conn->output);
+
+       io_remove(conn->io);
+       conn->io = NULL;
+
+       auth_master_connection_unref(conn);
+}
+
+static int auth_master_connection_unref(struct auth_master_connection *conn)
+{
+       if (--conn->refcount > 0)
+               return TRUE;
+
+       o_stream_unref(conn->output);
+       i_free(conn);
+       return FALSE;
+}
diff --git a/src/auth/auth-master-connection.h b/src/auth/auth-master-connection.h
new file mode 100644 (file)
index 0000000..6eb0bc4
--- /dev/null
@@ -0,0 +1,26 @@
+#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 ostream *output;
+       struct io *io;
+
+       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;
+};
+
+struct auth_master_connection *
+auth_master_connection_new(int fd, unsigned int pid);
+void auth_master_connection_free(struct auth_master_connection *conn);
+
+#endif
index 1494bb737391c92da92b51bac9fe805164d9bcc5..00e1db803ce8df5fc3bd55d3f18d4ec0c79be49b 100644 (file)
@@ -7,7 +7,7 @@ struct auth_master_request {
        unsigned int tag;
 
        unsigned int id;
-       unsigned int login_pid;
+       unsigned int client_pid;
 };
 
 struct auth_master_reply {
diff --git a/src/auth/login-connection.c b/src/auth/login-connection.c
deleted file mode 100644 (file)
index 65bd1f4..0000000
+++ /dev/null
@@ -1,318 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "common.h"
-#include "ioloop.h"
-#include "istream.h"
-#include "ostream.h"
-#include "network.h"
-#include "hash.h"
-#include "safe-memset.h"
-#include "mech.h"
-#include "login-connection.h"
-
-#include <stdlib.h>
-#include <syslog.h>
-
-#define MAX_INBUF_SIZE \
-       (sizeof(struct auth_login_request_continue) + \
-        AUTH_LOGIN_MAX_REQUEST_DATA_SIZE)
-#define MAX_OUTBUF_SIZE (1024*50)
-
-static struct timeout *to;
-static struct auth_login_handshake_output handshake_output;
-static struct login_connection *connections;
-
-static void login_connection_unref(struct login_connection *conn);
-
-static void request_callback(struct auth_login_reply *reply,
-                            const void *data, struct login_connection *conn)
-{
-       ssize_t ret;
-
-       ret = o_stream_send(conn->output, reply, sizeof(*reply));
-       if ((size_t)ret == sizeof(*reply)) {
-               if (reply->data_size == 0) {
-                       /* all sent */
-                       login_connection_unref(conn);
-                       return;
-               }
-
-               ret = o_stream_send(conn->output, data, reply->data_size);
-               if ((size_t)ret == reply->data_size) {
-                       /* all sent */
-                       login_connection_unref(conn);
-                       return;
-               }
-       }
-
-       if (ret >= 0)
-               i_warning("Transmit buffer full for login process, killing it");
-
-       login_connection_destroy(conn);
-       login_connection_unref(conn);
-}
-
-struct login_connection *login_connection_lookup(unsigned int pid)
-{
-       struct login_connection *conn;
-
-       for (conn = connections; conn != NULL; conn = conn->next) {
-               if (conn->pid == pid)
-                       return conn;
-       }
-
-       return NULL;
-}
-
-static void login_input_handshake(struct login_connection *conn)
-{
-        struct auth_login_handshake_input rec;
-        unsigned char *data;
-       size_t size;
-
-       data = i_stream_get_modifyable_data(conn->input, &size);
-       if (size < sizeof(struct auth_login_handshake_input))
-               return;
-
-       /* Don't just cast because of alignment issues. */
-       memcpy(&rec, data, sizeof(rec));
-       i_stream_skip(conn->input, sizeof(rec));
-
-       if (rec.pid == 0) {
-               i_error("BUG: login said it's PID 0");
-               login_connection_destroy(conn);
-       } else if (login_connection_lookup(rec.pid) != NULL) {
-               /* well, it might have just reconnected very fast .. although
-                  there's not much reason for it. */
-               i_error("BUG: login gave a PID of existing connection");
-               login_connection_destroy(conn);
-       } else {
-               conn->pid = rec.pid;
-               if (verbose_debug) {
-                       i_info("Login process %d sent handshake: PID %s",
-                              conn->fd, dec2str(conn->pid));
-               }
-       }
-}
-
-static void login_input_request(struct login_connection *conn)
-{
-        enum auth_login_request_type type;
-        unsigned char *data;
-       size_t size;
-
-       data = i_stream_get_modifyable_data(conn->input, &size);
-       if (size < sizeof(type))
-               return;
-
-       /* 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));
-
-       if (type == AUTH_LOGIN_REQUEST_NEW) {
-               struct auth_login_request_new request;
-
-               if (size < sizeof(request))
-                       return;
-
-               memcpy(&request, data, sizeof(request));
-               i_stream_skip(conn->input, sizeof(request));
-
-               /* we have a full init request */
-               conn->refcount++;
-               mech_request_new(conn, &request, request_callback);
-       } else if (type == AUTH_LOGIN_REQUEST_CONTINUE) {
-                struct auth_login_request_continue request;
-
-               if (size < sizeof(request))
-                       return;
-
-               memcpy(&request, data, sizeof(request));
-               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),
-                                     request_callback);
-
-               /* clear any sensitive data from memory */
-               safe_memset(data + sizeof(request), 0, request.data_size);
-       } else {
-               /* unknown request */
-               i_error("BUG: login sent us unknown request %u", type);
-               login_connection_destroy(conn);
-       }
-}
-
-static void login_input(void *context)
-{
-       struct login_connection *conn  = context;
-
-       switch (i_stream_read(conn->input)) {
-       case 0:
-               return;
-       case -1:
-               /* disconnected */
-               login_connection_destroy(conn);
-               return;
-       case -2:
-               /* buffer full */
-               i_error("BUG: login sent us more than %d bytes of data",
-                       (int)MAX_INBUF_SIZE);
-               login_connection_destroy(conn);
-               return;
-       }
-
-       if (conn->pid == 0)
-               login_input_handshake(conn);
-       else
-               login_input_request(conn);
-}
-
-struct login_connection *login_connection_create(int fd)
-{
-       struct login_connection *conn;
-
-       if (verbose_debug)
-               i_info("Login process %d connected", fd);
-
-       conn = i_new(struct login_connection, 1);
-       conn->refcount = 1;
-
-       conn->fd = fd;
-       conn->input = i_stream_create_file(fd, default_pool, MAX_INBUF_SIZE,
-                                          FALSE);
-       conn->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
-                                           FALSE);
-       conn->io = io_add(fd, IO_READ, login_input, conn);
-
-       conn->pool = pool_alloconly_create("auth_request hash", 10240);
-       conn->auth_requests = hash_create(default_pool, conn->pool,
-                                         0, NULL, NULL);
-
-       conn->next = connections;
-       connections = conn;
-
-       if (o_stream_send(conn->output, &handshake_output,
-                         sizeof(handshake_output)) < 0) {
-               login_connection_destroy(conn);
-               conn = NULL;
-       }
-
-       return conn;
-}
-
-static void auth_request_hash_destroy(void *key __attr_unused__, void *value,
-                                     void *context __attr_unused__)
-{
-       struct auth_request *auth_request = value;
-
-       auth_request->auth_free(auth_request);
-}
-
-void login_connection_destroy(struct login_connection *conn)
-{
-       struct login_connection **pos;
-
-       if (conn->fd == -1)
-               return;
-
-       if (verbose_debug)
-               i_info("Login process %d disconnected", conn->fd);
-
-       for (pos = &connections; *pos != NULL; pos = &(*pos)->next) {
-               if (*pos == conn) {
-                       *pos = conn->next;
-                       break;
-               }
-       }
-
-       i_stream_close(conn->input);
-       o_stream_close(conn->output);
-
-       io_remove(conn->io);
-       net_disconnect(conn->fd);
-       conn->fd = -1;
-
-        login_connection_unref(conn);
-}
-
-static void login_connection_unref(struct login_connection *conn)
-{
-       if (--conn->refcount > 0)
-               return;
-
-       hash_foreach(conn->auth_requests, auth_request_hash_destroy, NULL);
-       hash_destroy(conn->auth_requests);
-
-       i_stream_unref(conn->input);
-       o_stream_unref(conn->output);
-
-       pool_unref(conn->pool);
-       i_free(conn);
-}
-
-static void auth_request_hash_timeout_check(void *key __attr_unused__,
-                                           void *value, void *context)
-{
-       struct login_connection *conn = context;
-       struct auth_request *auth_request = value;
-
-       if (auth_request->created + AUTH_REQUEST_TIMEOUT < ioloop_time) {
-               i_warning("Login process has too old (%us) requests, "
-                         "killing it.",
-                         (unsigned int)(ioloop_time - auth_request->created));
-
-               login_connection_destroy(conn);
-               hash_foreach_stop();
-       }
-}
-
-static void request_timeout(void *context __attr_unused__)
-{
-       struct login_connection *conn;
-
-       for (conn = connections; conn != NULL; conn = conn->next) {
-               conn->refcount++;
-               hash_foreach(conn->auth_requests,
-                            auth_request_hash_timeout_check, conn);
-               login_connection_unref(conn);
-       }
-}
-
-void login_connections_init(void)
-{
-       const char *env;
-       unsigned int pid;
-
-       env = getenv("AUTH_PROCESS");
-       if (env == NULL)
-               i_fatal("AUTH_PROCESS environment is unset");
-
-       pid = atoi(env);
-       if (pid == 0)
-               i_fatal("AUTH_PROCESS can't be 0");
-
-       memset(&handshake_output, 0, sizeof(handshake_output));
-       handshake_output.pid = pid;
-       handshake_output.auth_mechanisms = auth_mechanisms;
-
-       connections = NULL;
-       to = timeout_add(5000, request_timeout, NULL);
-}
-
-void login_connections_deinit(void)
-{
-       struct login_connection *next;
-
-       while (connections != NULL) {
-               next = connections->next;
-               login_connection_destroy(connections);
-               connections = next;
-       }
-
-       timeout_remove(to);
-}
diff --git a/src/auth/login-connection.h b/src/auth/login-connection.h
deleted file mode 100644 (file)
index 89bdd4a..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __LOGIN_CONNECTION_H
-#define __LOGIN_CONNECTION_H
-
-#include "auth-login-interface.h"
-
-struct login_connection {
-       struct login_connection *next;
-       int refcount;
-
-       int fd;
-       struct io *io;
-       struct istream *input;
-       struct ostream *output;
-
-       pool_t pool;
-       struct hash_table *auth_requests;
-
-       unsigned int pid;
-};
-
-struct login_connection *login_connection_create(int fd);
-void login_connection_destroy(struct login_connection *conn);
-
-struct login_connection *login_connection_lookup(unsigned int pid);
-
-void login_connections_init(void);
-void login_connections_deinit(void);
-
-#endif
index 4252c838b18de279b4ddfc480771e42556acb05c..69c0eb8a82e4f0a439a567ed7fb966bc8ab46389 100644 (file)
@@ -10,8 +10,8 @@
 #include "mech.h"
 #include "userdb.h"
 #include "passdb.h"
-#include "master-connection.h"
-#include "login-connection.h"
+#include "auth-master-connection.h"
+#include "auth-client-connection.h"
 
 #include <stdlib.h>
 #include <syslog.h>
@@ -19,6 +19,7 @@
 struct ioloop *ioloop;
 int verbose = FALSE, verbose_debug = FALSE;
 
+static struct auth_master_connection *master;
 static struct io *io_listen;
 
 static void sig_quit(int signo __attr_unused__)
@@ -36,7 +37,7 @@ static void auth_accept(void *context __attr_unused__)
                        i_fatal("accept() failed: %m");
        } else {
                net_set_nonblock(fd, TRUE);
-               (void)login_connection_create(fd);
+               (void)auth_client_connection_create(master, fd);
        }
 }
 
@@ -69,21 +70,31 @@ static void drop_privileges(void)
 
 static void main_init(void)
 {
+       const char *env;
+       unsigned int pid;
+
        lib_init_signals(sig_quit);
 
        verbose = getenv("VERBOSE") != NULL;
        verbose_debug = getenv("VERBOSE_DEBUG") != NULL;
 
+       env = getenv("AUTH_PROCESS");
+       if (env == NULL)
+               i_fatal("AUTH_PROCESS environment is unset");
+
+       pid = atoi(env);
+       if (pid == 0)
+               i_fatal("AUTH_PROCESS can't be 0");
+
        mech_init();
        userdb_init();
        passdb_init();
 
-       login_connections_init();
-
        io_listen = io_add(LOGIN_LISTEN_FD, IO_READ, auth_accept, NULL);
 
        /* initialize master last - it sends the "we're ok" notification */
-       master_connection_init();
+       master = auth_master_connection_new(MASTER_SOCKET_FD, pid);
+       auth_client_connections_init(master);
 }
 
 static void main_deinit(void)
@@ -93,13 +104,13 @@ static void main_deinit(void)
 
        io_remove(io_listen);
 
-       login_connections_deinit();
+       auth_client_connections_deinit(master);
 
        passdb_deinit();
        userdb_deinit();
        mech_deinit();
 
-       master_connection_deinit();
+       auth_master_connection_free(master);
        random_deinit();
 
        closelog();
diff --git a/src/auth/master-connection.c b/src/auth/master-connection.c
deleted file mode 100644 (file)
index 6e3df8f..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "common.h"
-#include "buffer.h"
-#include "hash.h"
-#include "ioloop.h"
-#include "ostream.h"
-#include "network.h"
-#include "mech.h"
-#include "userdb.h"
-#include "login-connection.h"
-#include "master-connection.h"
-#include "auth-master-interface.h"
-
-#define MAX_OUTBUF_SIZE (1024*50)
-
-static struct auth_master_reply failure_reply;
-
-static struct ostream *output;
-static struct io *io_master;
-
-static unsigned int master_pos;
-static char master_buf[sizeof(struct auth_master_request)];
-
-static size_t reply_add(buffer_t *buf, const char *str)
-{
-       size_t index;
-
-       if (str == NULL || *str == '\0')
-               return (size_t)-1;
-
-       index = buffer_get_used_size(buf) - sizeof(struct auth_master_reply);
-       buffer_append(buf, str, strlen(str)+1);
-       return index;
-}
-
-static struct auth_master_reply *
-fill_reply(const struct user_data *user, size_t *reply_size)
-{
-       struct auth_master_reply reply, *reply_p;
-       buffer_t *buf;
-       char *p;
-
-       buf = buffer_create_dynamic(data_stack_pool,
-                                   sizeof(reply) + 256, (size_t)-1);
-       memset(&reply, 0, sizeof(reply));
-       buffer_append(buf, &reply, sizeof(reply));
-
-       reply.success = TRUE;
-
-       reply.uid = user->uid;
-       reply.gid = 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);
-
-       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);
-       } 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 send_reply(struct auth_master_reply *reply, size_t reply_size,
-                      unsigned int tag)
-{
-       ssize_t ret;
-
-       reply->tag = tag;
-       for (;;) {
-               ret = o_stream_send(output, reply, reply_size);
-               if (ret < 0) {
-                       /* master died, kill ourself too */
-                       io_loop_stop(ioloop);
-                       break;
-               }
-
-               if ((size_t)ret == reply_size)
-                       break;
-
-               /* buffer full, we have to block */
-               i_warning("Master transmit buffer full, blocking..");
-               if (o_stream_flush(output) < 0) {
-                       /* transmit error, probably master died */
-                       io_loop_stop(ioloop);
-                       break;
-               }
-       }
-}
-
-static void userdb_callback(struct user_data *user, void *context)
-{
-       unsigned int tag = POINTER_CAST_TO(context, unsigned int);
-       struct auth_master_reply *reply;
-       size_t reply_size;
-
-       if (user == NULL)
-               send_reply(&failure_reply, sizeof(failure_reply), tag);
-       else {
-               reply = fill_reply(user, &reply_size);
-               send_reply(reply, reply_size, tag);
-       }
-}
-
-static void master_handle_request(struct auth_master_request *request)
-{
-       struct login_connection *login_conn;
-       struct auth_request *auth_request;
-
-       login_conn = login_connection_lookup(request->login_pid);
-       auth_request = login_conn == NULL ? NULL :
-               hash_lookup(login_conn->auth_requests,
-                           POINTER_CAST(request->id));
-
-       if (auth_request == NULL) {
-               if (verbose) {
-                       i_info("Master request %u.%u not found",
-                              request->login_pid, request->id);
-               }
-               send_reply(&failure_reply, sizeof(failure_reply), request->tag);
-       } else {
-               userdb->lookup(auth_request->user, userdb_callback,
-                              POINTER_CAST(request->tag));
-               mech_request_free(login_conn, auth_request, request->id);
-       }
-}
-
-static void master_input(void *context __attr_unused__)
-{
-       int ret;
-
-       ret = net_receive(MASTER_SOCKET_FD, master_buf + master_pos,
-                         sizeof(master_buf) - master_pos);
-       if (ret < 0) {
-               /* master died, kill ourself too */
-               io_loop_stop(ioloop);
-               return;
-       }
-
-       master_pos += ret;
-       if (master_pos < sizeof(master_buf))
-               return;
-
-       /* reply is now read */
-       master_handle_request((struct auth_master_request *) master_buf);
-       master_pos = 0;
-}
-
-void master_connection_init(void)
-{
-       memset(&failure_reply, 0, sizeof(failure_reply));
-
-       master_pos = 0;
-       output = o_stream_create_file(MASTER_SOCKET_FD, default_pool,
-                                     MAX_OUTBUF_SIZE, FALSE);
-       io_master = io_add(MASTER_SOCKET_FD, IO_READ, master_input, NULL);
-
-       /* just a note to master that we're ok. if we die before,
-          master should shutdown itself. */
-       o_stream_send(output, "O", 1);
-}
-
-void master_connection_deinit(void)
-{
-       o_stream_unref(output);
-       io_remove(io_master);
-}
diff --git a/src/auth/master-connection.h b/src/auth/master-connection.h
deleted file mode 100644 (file)
index d2c1ae6..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __MASTER_CONNECTION_H
-#define __MASTER_CONNECTION_H
-
-void master_connection_init(void);
-void master_connection_deinit(void);
-
-#endif
index b48e85a93e133008c719e44cda170808b2ff37ec..272ab23facb66e2605db46c70daf38fde69bf391 100644 (file)
@@ -5,7 +5,7 @@
 
 static int
 mech_anonymous_auth_continue(struct auth_request *auth_request,
-                            struct auth_login_request_continue *request,
+                            struct auth_client_request_continue *request,
                             const unsigned char *data,
                             mech_callback_t *callback)
 {
@@ -29,11 +29,11 @@ mech_anonymous_auth_free(struct auth_request *auth_request)
 }
 
 static struct auth_request *
-mech_anonymous_auth_new(struct login_connection *conn, unsigned int id,
+mech_anonymous_auth_new(struct auth_client_connection *conn, unsigned int id,
                        mech_callback_t *callback)
 {
         struct auth_request *auth_request;
-       struct auth_login_reply reply;
+       struct auth_client_request_reply reply;
        pool_t pool;
 
        pool = pool_alloconly_create("anonymous_auth_request", 256);
@@ -45,7 +45,7 @@ mech_anonymous_auth_new(struct login_connection *conn, unsigned int id,
        /* initialize reply */
        memset(&reply, 0, sizeof(reply));
        reply.id = id;
-       reply.result = AUTH_LOGIN_RESULT_CONTINUE;
+       reply.result = AUTH_CLIENT_RESULT_CONTINUE;
 
        callback(&reply, NULL, conn);
        return auth_request;
index 133e7912e8e306ec866cf48df14d9c97d940bf1f..a5bd4faf9a7300ac376262d83f6f1b4e88a5d2e4 100644 (file)
@@ -526,15 +526,15 @@ static void credentials_callback(const char *result,
 {
        struct digest_auth_request *auth =
                (struct digest_auth_request *) request;
-       struct auth_login_reply reply;
+       struct auth_client_request_reply reply;
 
-       mech_init_login_reply(&reply);
+       mech_init_auth_client_reply(&reply);
        reply.id = request->id;
 
        if (!verify_credentials(auth, result))
-               reply.result = AUTH_LOGIN_RESULT_FAILURE;
+               reply.result = AUTH_CLIENT_RESULT_FAILURE;
        else {
-               reply.result = AUTH_LOGIN_RESULT_CONTINUE;
+               reply.result = AUTH_CLIENT_RESULT_CONTINUE;
                reply.data_size = strlen(auth->rspauth);
                auth->authenticated = TRUE;
        }
@@ -544,17 +544,17 @@ static void credentials_callback(const char *result,
 
 static int
 mech_digest_md5_auth_continue(struct auth_request *auth_request,
-                             struct auth_login_request_continue *request,
+                             struct auth_client_request_continue *request,
                              const unsigned char *data,
                              mech_callback_t *callback)
 {
        struct digest_auth_request *auth =
                (struct digest_auth_request *)auth_request;
-       struct auth_login_reply reply;
+       struct auth_client_request_reply reply;
        const char *error, *realm;
 
        /* initialize reply */
-       mech_init_login_reply(&reply);
+       mech_init_auth_client_reply(&reply);
        reply.id = request->id;
 
        if (auth->authenticated) {
@@ -596,7 +596,7 @@ mech_digest_md5_auth_continue(struct auth_request *auth_request,
        }
 
        /* failed */
-       reply.result = AUTH_LOGIN_RESULT_FAILURE;
+       reply.result = AUTH_CLIENT_RESULT_FAILURE;
        reply.data_size = strlen(error)+1;
        callback(&reply, error, auth_request->conn);
        return FALSE;
@@ -608,10 +608,10 @@ static void mech_digest_md5_auth_free(struct auth_request *auth_request)
 }
 
 static struct auth_request *
-mech_digest_md5_auth_new(struct login_connection *conn,
+mech_digest_md5_auth_new(struct auth_client_connection *conn,
                         unsigned int id, mech_callback_t *callback)
 {
-       struct auth_login_reply reply;
+       struct auth_client_request_reply reply;
        struct digest_auth_request *auth;
        pool_t pool;
        string_t *challenge;
@@ -626,9 +626,9 @@ mech_digest_md5_auth_new(struct login_connection *conn,
        auth->qop = QOP_AUTH;
 
        /* initialize reply */
-       mech_init_login_reply(&reply);
+       mech_init_auth_client_reply(&reply);
        reply.id = id;
-       reply.result = AUTH_LOGIN_RESULT_CONTINUE;
+       reply.result = AUTH_CLIENT_RESULT_CONTINUE;
 
        /* send the initial challenge */
        reply.reply_idx = 0;
index 8195cb9735cef4137458e39d8d4e3acb7622277b..d82c0220431af612fce854c107b11e6ed97b0a7b 100644 (file)
@@ -13,7 +13,7 @@ static void verify_callback(enum passdb_result result,
 
 static int
 mech_plain_auth_continue(struct auth_request *auth_request,
-                        struct auth_login_request_continue *request,
+                        struct auth_client_request_continue *request,
                         const unsigned char *data, mech_callback_t *callback)
 {
        const char *authid, *authenid;
@@ -82,11 +82,11 @@ mech_plain_auth_free(struct auth_request *auth_request)
 }
 
 static struct auth_request *
-mech_plain_auth_new(struct login_connection *conn, unsigned int id,
+mech_plain_auth_new(struct auth_client_connection *conn, unsigned int id,
                    mech_callback_t *callback)
 {
         struct auth_request *auth_request;
-       struct auth_login_reply reply;
+       struct auth_client_request_reply reply;
        pool_t pool;
 
        pool = pool_alloconly_create("plain_auth_request", 256);
@@ -98,7 +98,7 @@ mech_plain_auth_new(struct login_connection *conn, unsigned int id,
        /* initialize reply */
        memset(&reply, 0, sizeof(reply));
        reply.id = id;
-       reply.result = AUTH_LOGIN_RESULT_CONTINUE;
+       reply.result = AUTH_CLIENT_RESULT_CONTINUE;
 
        callback(&reply, NULL, conn);
        return auth_request;
index 145c5e0d7d4bc00a629a236c91ce0b55876ff70a..1d67309de0a38560b8fd0e48b3da4de95d4757e7 100644 (file)
@@ -5,7 +5,7 @@
 #include "buffer.h"
 #include "hash.h"
 #include "mech.h"
-#include "login-connection.h"
+#include "auth-client-connection.h"
 
 #include <stdlib.h>
 
@@ -23,7 +23,7 @@ char username_chars[256];
 
 static int set_use_cyrus_sasl;
 static struct mech_module_list *mech_modules;
-static struct auth_login_reply failure_reply;
+static struct auth_client_request_reply failure_reply;
 
 void mech_register_module(struct mech_module *module)
 {
@@ -59,8 +59,8 @@ void mech_unregister_module(struct mech_module *module)
        }
 }
 
-void mech_request_new(struct login_connection *conn,
-                     struct auth_login_request_new *request,
+void mech_request_new(struct auth_client_connection *conn,
+                     struct auth_client_request_new *request,
                      mech_callback_t *callback)
 {
        struct mech_module_list *list;
@@ -68,8 +68,8 @@ void mech_request_new(struct login_connection *conn,
 
        if ((auth_mechanisms & request->mech) == 0) {
                /* unsupported mechanism */
-               i_error("BUG: login requested unsupported "
-                       "auth mechanism %d", request->mech);
+               i_error("BUG: Auth client %u requested unsupported "
+                       "auth mechanism %d", conn->pid, request->mech);
                failure_reply.id = request->id;
                callback(&failure_reply, NULL, conn);
                return;
@@ -104,8 +104,8 @@ void mech_request_new(struct login_connection *conn,
        }
 }
 
-void mech_request_continue(struct login_connection *conn,
-                          struct auth_login_request_continue *request,
+void mech_request_continue(struct auth_client_connection *conn,
+                          struct auth_client_request_continue *request,
                           const unsigned char *data,
                           mech_callback_t *callback)
 {
@@ -124,22 +124,22 @@ void mech_request_continue(struct login_connection *conn,
        }
 }
 
-void mech_request_free(struct login_connection *conn,
+void mech_request_free(struct auth_client_connection *conn,
                       struct auth_request *auth_request, unsigned int id)
 {
        auth_request->auth_free(auth_request);
        hash_remove(conn->auth_requests, POINTER_CAST(id));
 }
 
-void mech_init_login_reply(struct auth_login_reply *reply)
+void mech_init_auth_client_reply(struct auth_client_request_reply *reply)
 {
        memset(reply, 0, sizeof(*reply));
 
-       reply->username_idx = (unsigned int)-1;
-       reply->reply_idx = (unsigned int)-1;
+       reply->username_idx = (size_t)-1;
+       reply->reply_idx = (size_t)-1;
 }
 
-void *mech_auth_success(struct auth_login_reply *reply,
+void *mech_auth_success(struct auth_client_request_reply *reply,
                        struct auth_request *auth_request,
                        const void *data, size_t data_size)
 {
@@ -157,7 +157,7 @@ void *mech_auth_success(struct auth_login_reply *reply,
                buffer_append(buf, data, data_size);
        }
 
-       reply->result = AUTH_LOGIN_RESULT_SUCCESS;
+       reply->result = AUTH_CLIENT_RESULT_SUCCESS;
        reply->data_size = buffer_get_used_size(buf);
        return buffer_get_modifyable_data(buf, NULL);
 }
@@ -165,7 +165,7 @@ void *mech_auth_success(struct auth_login_reply *reply,
 void mech_auth_finish(struct auth_request *auth_request,
                      const void *data, size_t data_size, int success)
 {
-       struct auth_login_reply reply;
+       struct auth_client_request_reply reply;
        void *reply_data;
 
        memset(&reply, 0, sizeof(reply));
@@ -174,10 +174,10 @@ void mech_auth_finish(struct auth_request *auth_request,
        if (success) {
                reply_data = mech_auth_success(&reply, auth_request,
                                               data, data_size);
-               reply.result = AUTH_LOGIN_RESULT_SUCCESS;
+               reply.result = AUTH_CLIENT_RESULT_SUCCESS;
        } else {
                reply_data = NULL;
-               reply.result = AUTH_LOGIN_RESULT_FAILURE;
+               reply.result = AUTH_CLIENT_RESULT_FAILURE;
        }
 
        auth_request->callback(&reply, reply_data, auth_request->conn);
@@ -213,7 +213,7 @@ void mech_init(void)
        auth_mechanisms = 0;
 
        memset(&failure_reply, 0, sizeof(failure_reply));
-       failure_reply.result = AUTH_LOGIN_RESULT_FAILURE;
+       failure_reply.result = AUTH_CLIENT_RESULT_FAILURE;
 
        anonymous_username = getenv("ANONYMOUS_USERNAME");
        if (anonymous_username != NULL && *anonymous_username == '\0')
index 2c071b6b10895db4161bbc7b23e59090ccbeb7bc..13cbfaa34352110b7c4ec5970100f5081025a3b1 100644 (file)
@@ -1,18 +1,19 @@
 #ifndef __MECH_H
 #define __MECH_H
 
-#include "auth-login-interface.h"
+#include "auth-client-interface.h"
 
-struct login_connection;
+struct auth_client_connection;
 
-typedef void mech_callback_t(struct auth_login_reply *reply,
-                            const void *data, struct login_connection *conn);
+typedef void mech_callback_t(struct auth_client_request_reply *reply,
+                            const void *data,
+                            struct auth_client_connection *conn);
 
 struct auth_request {
        pool_t pool;
        char *user;
 
-       struct login_connection *conn;
+       struct auth_client_connection *conn;
        unsigned int id;
        time_t created;
 
@@ -20,7 +21,7 @@ struct auth_request {
        mech_callback_t *callback;
 
        int (*auth_continue)(struct auth_request *auth_request,
-                            struct auth_login_request_continue *request,
+                            struct auth_client_request_continue *request,
                             const unsigned char *data,
                             mech_callback_t *callback);
        void (*auth_free)(struct auth_request *auth_request);
@@ -30,7 +31,7 @@ struct auth_request {
 struct mech_module {
        enum auth_mech mech;
 
-       struct auth_request *(*auth_new)(struct login_connection *conn,
+       struct auth_request *(*auth_new)(struct auth_client_connection *conn,
                                         unsigned int id,
                                         mech_callback_t *callback);
 };
@@ -44,18 +45,18 @@ extern char username_chars[256];
 void mech_register_module(struct mech_module *module);
 void mech_unregister_module(struct mech_module *module);
 
-void mech_request_new(struct login_connection *conn,
-                     struct auth_login_request_new *request,
+void mech_request_new(struct auth_client_connection *conn,
+                     struct auth_client_request_new *request,
                      mech_callback_t *callback);
-void mech_request_continue(struct login_connection *conn,
-                          struct auth_login_request_continue *request,
+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 login_connection *conn,
+void mech_request_free(struct auth_client_connection *conn,
                       struct auth_request *auth_request, unsigned int id);
 
-void mech_init_login_reply(struct auth_login_reply *reply);
-void *mech_auth_success(struct auth_login_reply *reply,
+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,
@@ -64,9 +65,10 @@ void mech_auth_finish(struct auth_request *auth_request,
 int mech_is_valid_username(const char *username);
 
 void mech_cyrus_sasl_init_lib(void);
-struct auth_request *mech_cyrus_sasl_new(struct login_connection *conn,
-                                        struct auth_login_request_new *request,
-                                        mech_callback_t *callback);
+struct auth_request *
+mech_cyrus_sasl_new(struct auth_client_connection *conn,
+                   struct auth_client_request_new *request,
+                   mech_callback_t *callback);
 
 void mech_init(void);
 void mech_deinit(void);
index e973b3c6c002d5f3611b89790ad5feefee283096..69c3db3ed49cc5da69bc301a51ad848cd87fb965 100644 (file)
@@ -4,12 +4,14 @@ pkglibexec_PROGRAMS = imap-login
 
 INCLUDES = \
        -I$(top_srcdir)/src/lib \
+       -I$(top_srcdir)/src/lib-auth \
        -I$(top_srcdir)/src/lib-imap \
        -I$(top_srcdir)/src/login-common
 
 imap_login_LDADD = \
        ../login-common/liblogin-common.a \
        ../lib-imap/imap-parser.o \
+       ../lib-auth/libauth.a \
        ../lib/liblib.a \
        $(SSL_LIBS)
 
@@ -18,6 +20,5 @@ imap_login_SOURCES = \
        client-authenticate.c
 
 noinst_HEADERS = \
-       common.h \
        client.h \
        client-authenticate.h
index 664aaf7f6bccd5c4f2640a81c5f5a8cb801be224..0452c2807a23285c0f7282c286a30cbf2ff07a7f 100644 (file)
@@ -9,26 +9,27 @@
 #include "safe-memset.h"
 #include "str.h"
 #include "imap-parser.h"
-#include "auth-connection.h"
+#include "auth-client.h"
 #include "../auth/auth-mech-desc.h"
 #include "client.h"
 #include "client-authenticate.h"
 #include "auth-common.h"
 #include "master.h"
 
-static enum auth_mech auth_mechs = 0;
-static char *auth_mechs_capability = NULL;
-
 const char *client_authenticate_get_capabilities(int tls)
 {
+       static enum auth_mech cached_auth_mechs = 0;
+       static char *cached_capability = NULL;
+        enum auth_mech auth_mechs;
        string_t *str;
        int i;
 
-       if (auth_mechs == available_auth_mechs)
-               return auth_mechs_capability;
+       auth_mechs = auth_client_get_available_mechs(auth_client);
+       if (auth_mechs == cached_auth_mechs)
+               return cached_capability;
 
-       auth_mechs = available_auth_mechs;
-       i_free(auth_mechs_capability);
+       cached_auth_mechs = auth_mechs;
+       i_free(cached_capability);
 
        str = t_str_new(128);
 
@@ -43,8 +44,8 @@ const char *client_authenticate_get_capabilities(int tls)
                }
        }
 
-       auth_mechs_capability = i_strdup_empty(str_c(str));
-       return auth_mechs_capability;
+       cached_capability = i_strdup_empty(str_c(str));
+       return cached_capability;
 }
 
 static struct auth_mech_desc *auth_mech_find(const char *name)
@@ -65,8 +66,7 @@ static void client_auth_abort(struct imap_client *client, const char *msg)
        client->authenticating = FALSE;
 
        if (client->common.auth_request != NULL) {
-               auth_abort_request(client->common.auth_request);
-                auth_request_unref(client->common.auth_request);
+               auth_client_request_abort(client->common.auth_request);
                client->common.auth_request = NULL;
        }
 
@@ -80,8 +80,6 @@ static void client_auth_abort(struct imap_client *client, const char *msg)
                io_remove(client->common.io);
        client->common.io = client->common.fd == -1 ? NULL :
                io_add(client->common.fd, IO_READ, client_input, client);
-
-       client_unref(client);
 }
 
 static void master_callback(struct client *_client, int success)
@@ -99,7 +97,6 @@ static void master_callback(struct client *_client, int success)
        }
 
        client_destroy(client, reason);
-       client_unref(client);
 }
 
 static void client_send_auth_data(struct imap_client *client,
@@ -122,15 +119,15 @@ static void client_send_auth_data(struct imap_client *client,
 }
 
 static void login_callback(struct auth_request *request,
-                          struct auth_login_reply *reply,
-                          const unsigned char *data, struct client *_client)
+                          struct auth_client_request_reply *reply,
+                          const unsigned char *data, void *context)
 {
-       struct imap_client *client = (struct imap_client *) _client;
+       struct imap_client *client = context;
        const char *error;
        const void *ptr;
        size_t size;
 
-       switch (auth_callback(request, reply, data, _client,
+       switch (auth_callback(request, reply, data, &client->common,
                              master_callback, &error)) {
        case -1:
                /* login failed */
@@ -140,7 +137,7 @@ static void login_callback(struct auth_request *request,
        case 0:
                /* continue */
                ptr = buffer_get_data(client->plain_login, &size);
-               auth_continue_request(request, ptr, size);
+               auth_client_request_continue(request, ptr, size);
 
                buffer_set_used_size(client->plain_login, 0);
                break;
@@ -184,33 +181,34 @@ int cmd_login(struct imap_client *client, struct imap_arg *args)
        buffer_append_c(client->plain_login, '\0');
        buffer_append(client->plain_login, pass, strlen(pass));
 
-       client_ref(client);
-       if (auth_init_request(AUTH_MECH_PLAIN, AUTH_PROTOCOL_IMAP,
-                             login_callback, &client->common, &error)) {
-               /* don't read any input from client until login is finished */
-               if (client->common.io != NULL) {
-                       io_remove(client->common.io);
-                       client->common.io = NULL;
-               }
-                client->authenticating = TRUE;
-               return TRUE;
-       } else {
+       client->common.auth_request =
+               auth_client_request_new(auth_client, AUTH_MECH_PLAIN,
+                                       AUTH_PROTOCOL_IMAP, login_callback,
+                                       client, &error);
+       if (client->common.auth_request == NULL) {
                client_send_tagline(client, t_strconcat(
                        "NO Login failed: ", error, NULL));
-               client_unref(client);
                return TRUE;
        }
+
+       /* don't read any input from client until login is finished */
+       if (client->common.io != NULL) {
+               io_remove(client->common.io);
+               client->common.io = NULL;
+       }
+
+       client->authenticating = TRUE;
+       return TRUE;
 }
 
 static void authenticate_callback(struct auth_request *request,
-                                 struct auth_login_reply *reply,
-                                 const unsigned char *data,
-                                 struct client *_client)
+                                 struct auth_client_request_reply *reply,
+                                 const unsigned char *data, void *context)
 {
-       struct imap_client *client = (struct imap_client *) _client;
+       struct imap_client *client = context;
        const char *error;
 
-       switch (auth_callback(request, reply, data, _client,
+       switch (auth_callback(request, reply, data, &client->common,
                              master_callback, &error)) {
        case -1:
                /* login failed */
@@ -266,9 +264,9 @@ static void client_auth_input(void *context)
        } else if (client->common.auth_request == NULL) {
                client_auth_abort(client, "Don't send unrequested data");
        } else {
-               auth_continue_request(client->common.auth_request,
-                                     buffer_get_data(buf, NULL),
-                                     buffer_get_used_size(buf));
+               auth_client_request_continue(client->common.auth_request,
+                                            buffer_get_data(buf, NULL),
+                                            buffer_get_used_size(buf));
        }
 
        /* clear sensitive data */
@@ -306,9 +304,12 @@ int cmd_authenticate(struct imap_client *client, struct imap_arg *args)
                return TRUE;
        }
 
-       client_ref(client);
-       if (auth_init_request(mech->mech, AUTH_PROTOCOL_IMAP,
-                             authenticate_callback, &client->common, &error)) {
+       client->common.auth_request =
+               auth_client_request_new(auth_client, mech->mech,
+                                       AUTH_PROTOCOL_IMAP,
+                                       authenticate_callback,
+                                       client, &error);
+       if (client->common.auth_request != NULL) {
                /* following input data will go to authentication */
                if (client->common.io != NULL)
                        io_remove(client->common.io);
@@ -318,7 +319,6 @@ int cmd_authenticate(struct imap_client *client, struct imap_arg *args)
        } else {
                client_send_tagline(client, t_strconcat(
                        "NO Authentication failed: ", error, NULL));
-               client_unref(client);
        }
 
        return TRUE;
index 2455ee0cb33fda4334e17912218282f9012c1558..a844c71b30534655e825c2a1cbdc95b8c316de28 100644 (file)
@@ -12,7 +12,7 @@
 #include "imap-parser.h"
 #include "client.h"
 #include "client-authenticate.h"
-#include "auth-connection.h"
+#include "auth-client.h"
 #include "ssl-proxy.h"
 
 /* max. size of one parameter in line */
@@ -41,6 +41,8 @@
 static struct hash_table *clients;
 static struct timeout *to_idle;
 
+static int client_unref(struct imap_client *client);
+
 static void client_set_title(struct imap_client *client)
 {
        const char *addr;
@@ -275,7 +277,7 @@ void client_input(void *context)
        if (!client_read(client))
                return;
 
-       if (!auth_is_connected()) {
+       if (!auth_client_is_connected(auth_client)) {
                /* we're not yet connected to auth process -
                   don't allow any commands */
                client_send_line(client,
@@ -284,7 +286,7 @@ void client_input(void *context)
                return;
        }
 
-       client_ref(client);
+       client->refcount++;
 
        o_stream_cork(client->output);
        while (client_handle_input(client)) ;
@@ -386,6 +388,14 @@ void client_destroy(struct imap_client *client, const char *reason)
        i_stream_close(client->input);
        o_stream_close(client->output);
 
+       if (client->common.auth_request != NULL) {
+               auth_client_request_abort(client->common.auth_request);
+                client->common.auth_request = NULL;
+       }
+
+       if (client->common.master_tag != 0)
+               master_request_abort(&client->common);
+
        if (client->common.io != NULL) {
                io_remove(client->common.io);
                client->common.io = NULL;
@@ -399,12 +409,7 @@ void client_destroy(struct imap_client *client, const char *reason)
        client_unref(client);
 }
 
-void client_ref(struct imap_client *client)
-{
-       client->refcount++;
-}
-
-int client_unref(struct imap_client *client)
+static int client_unref(struct imap_client *client)
 {
        if (--client->refcount > 0)
                return TRUE;
@@ -476,7 +481,7 @@ static void client_hash_check_io(void *key, void *value __attr_unused__,
        }
 }
 
-void clients_notify_auth_process(void)
+void clients_notify_auth_connected(void)
 {
        hash_foreach(clients, client_hash_check_io, NULL);
 }
index 358e7acd504149b75dcd849414ded27df9c85f5c..e963bc494da1cbcc5a690f157d9ca611c4e0225a 100644 (file)
@@ -33,9 +33,6 @@ struct imap_client {
 struct client *client_create(int fd, struct ip_addr *ip, int ssl);
 void client_destroy(struct imap_client *client, const char *reason);
 
-void client_ref(struct imap_client *client);
-int client_unref(struct imap_client *client);
-
 void client_send_line(struct imap_client *client, const char *line);
 void client_send_tagline(struct imap_client *client, const char *line);
 void client_syslog(struct imap_client *client, const char *text);
diff --git a/src/imap-login/common.h b/src/imap-login/common.h
deleted file mode 100644 (file)
index 5a2a04d..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __COMMON_H
-#define __COMMON_H
-
-#include "lib.h"
-#include "../auth/auth-login-interface.h"
-
-extern int disable_plaintext_auth, process_per_connection, verbose_proctitle;
-extern unsigned int max_logging_users;
-extern unsigned int login_process_uid;
-
-void main_ref(void);
-void main_unref(void);
-
-void main_close_listen(void);
-
-#endif
diff --git a/src/lib-auth/.cvsignore b/src/lib-auth/.cvsignore
new file mode 100644 (file)
index 0000000..8553e9e
--- /dev/null
@@ -0,0 +1,8 @@
+*.la
+*.lo
+*.o
+.deps
+.libs
+Makefile
+Makefile.in
+so_locations
diff --git a/src/lib-auth/Makefile.am b/src/lib-auth/Makefile.am
new file mode 100644 (file)
index 0000000..3d24965
--- /dev/null
@@ -0,0 +1,12 @@
+noinst_LIBRARIES = libauth.a
+
+INCLUDES = \
+       -I$(top_srcdir)/src/lib
+
+libauth_a_SOURCES = \
+       auth-client.c \
+       auth-server-connection.c \
+       auth-server-request.c
+
+noinst_HEADERS = \
+       auth-client.h
diff --git a/src/lib-auth/auth-client.c b/src/lib-auth/auth-client.c
new file mode 100644 (file)
index 0000000..e68c248
--- /dev/null
@@ -0,0 +1,111 @@
+/* Copyright (C) 2003 Timo Sirainen */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "hash.h"
+#include "auth-client.h"
+#include "auth-server-connection.h"
+
+#include <dirent.h>
+#include <sys/stat.h>
+
+struct auth_client *auth_client_new(unsigned int client_pid)
+{
+       struct auth_client *client;
+
+       client = i_new(struct auth_client, 1);
+       client->pid = client_pid;
+
+       auth_client_connect_missing_servers(client);
+       return client;
+}
+
+void auth_client_free(struct auth_client *client)
+{
+       struct auth_server_connection *next;
+
+       while (client->connections != NULL) {
+               next = client->connections->next;
+               auth_server_connection_destroy(client->connections, FALSE);
+               client->connections = next;
+       }
+
+       if (client->to_reconnect != NULL)
+               timeout_remove(client->to_reconnect);
+       i_free(client);
+}
+
+enum auth_mech auth_client_get_available_mechs(struct auth_client *client)
+{
+       return client->available_auth_mechs;
+}
+
+int auth_client_is_connected(struct auth_client *client)
+{
+       return client->to_reconnect == NULL &&
+               client->conn_waiting_handshake_count == 0;
+}
+
+void auth_client_set_connect_notify(struct auth_client *client,
+                                   auth_connect_notify_callback_t *callback,
+                                   void *context)
+{
+       client->connect_notify_callback = callback;
+       client->connect_notify_context = context;
+}
+
+static void reconnect_timeout(void *context)
+{
+       struct auth_client *client = context;
+
+       auth_client_connect_missing_servers(client);
+}
+
+void auth_client_connect_missing_servers(struct auth_client *client)
+{
+       DIR *dirp;
+       struct dirent *dp;
+       struct stat st;
+       int reconnect;
+
+       /* we're chrooted into */
+       dirp = opendir(".");
+       if (dirp == NULL) {
+               i_fatal("opendir(.) failed when trying to get list of "
+                       "authentication servers: %m");
+       }
+
+       reconnect = FALSE;
+       while ((dp = readdir(dirp)) != NULL) {
+               if (dp->d_name[0] == '.')
+                       continue;
+
+               if (auth_server_connection_find_path(client, dp->d_name) != NULL) {
+                       /* already connected */
+                       continue;
+               }
+
+               if (stat(dp->d_name, &st) == 0 && S_ISSOCK(st.st_mode)) {
+                       if (auth_server_connection_new(client,
+                                                      dp->d_name) == NULL)
+                               reconnect = TRUE;
+               }
+       }
+
+       if (closedir(dirp) < 0)
+               i_error("closedir() failed: %m");
+
+       if (reconnect || client->connections == NULL) {
+               if (client->to_reconnect == NULL) {
+                       client->to_reconnect =
+                               timeout_add(5000, reconnect_timeout, client);
+               }
+       } else if (client->to_reconnect != NULL) {
+               timeout_remove(client->to_reconnect);
+               client->to_reconnect = NULL;
+       }
+
+       client->connect_notify_callback(client,
+                                       auth_client_is_connected(client),
+                                       client->connect_notify_context);
+}
diff --git a/src/lib-auth/auth-client.h b/src/lib-auth/auth-client.h
new file mode 100644 (file)
index 0000000..1883206
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef __AUTH_CLIENT_H
+#define __AUTH_CLIENT_H
+
+#include "../auth/auth-client-interface.h"
+
+struct auth_client;
+struct auth_request;
+
+/* reply is NULL if auth connection died */
+typedef void auth_request_callback_t(struct auth_request *request,
+                                    struct auth_client_request_reply *reply,
+                                    const unsigned char *data, void *context);
+
+typedef void auth_connect_notify_callback_t(struct auth_client *client,
+                                           int connected, void *context);
+
+/* Create new authentication client. */
+struct auth_client *auth_client_new(unsigned int client_pid);
+void auth_client_free(struct auth_client *client);
+
+int auth_client_is_connected(struct auth_client *client);
+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);
+
+void auth_client_connect_missing_servers(struct auth_client *client);
+
+/* Create a new authentication request. callback is called whenever something
+   happens for the request. */
+struct auth_request *
+auth_client_request_new(struct auth_client *client,
+                       enum auth_mech mech, enum auth_protocol protocol,
+                       auth_request_callback_t *callback, void *context,
+                       const char **error_r);
+
+/* Continue authentication. Call when
+   reply->result == AUTH_CLIENT_REQUEST_CONTINUE */
+void auth_client_request_continue(struct auth_request *request,
+                                 const unsigned char *data, size_t data_size);
+
+/* Abort ongoing authentication request. */
+void auth_client_request_abort(struct auth_request *request);
+
+/* Return ID of this request. */
+unsigned int auth_client_request_get_id(struct auth_request *request);
+
+/* Return the PID of the server that handled this request. */
+unsigned int auth_client_request_get_server_pid(struct auth_request *request);
+
+#endif
diff --git a/src/lib-auth/auth-server-connection.c b/src/lib-auth/auth-server-connection.c
new file mode 100644 (file)
index 0000000..063d171
--- /dev/null
@@ -0,0 +1,229 @@
+/* Copyright (C) 2003 Timo Sirainen */
+
+#include "lib.h"
+#include "hash.h"
+#include "ioloop.h"
+#include "istream.h"
+#include "ostream.h"
+#include "network.h"
+#include "auth-client.h"
+#include "auth-server-connection.h"
+#include "auth-server-request.h"
+
+#include <unistd.h>
+
+/* Maximum size for an auth reply. 50kB should be more than enough. */
+#define MAX_INBUF_SIZE (1024*50)
+
+#define MAX_OUTBUF_SIZE \
+       (sizeof(struct auth_client_request_continue) + \
+        AUTH_CLIENT_MAX_REQUEST_DATA_SIZE)
+
+static void update_available_auth_mechs(struct auth_client *client)
+{
+       struct auth_server_connection *conn;
+
+        client->available_auth_mechs = 0;
+       for (conn = client->connections; conn != NULL; conn = conn->next)
+                client->available_auth_mechs |= conn->available_auth_mechs;
+}
+
+static void auth_handle_handshake(struct auth_server_connection *conn,
+                                 struct auth_client_handshake_reply *handshake)
+{
+       if (handshake->server_pid == 0) {
+               i_error("BUG: Auth server said it's PID 0");
+               auth_server_connection_destroy(conn, FALSE);
+               return;
+       }
+
+       conn->pid = handshake->server_pid;
+       conn->available_auth_mechs = handshake->auth_mechanisms;
+       conn->handshake_received = TRUE;
+
+        conn->client->conn_waiting_handshake_count--;
+       update_available_auth_mechs(conn->client);
+
+       if (auth_client_is_connected(conn->client)) {
+               conn->client->connect_notify_callback(conn->client, TRUE,
+                               conn->client->connect_notify_context);
+       }
+}
+
+static void auth_client_input(void *context)
+{
+       struct auth_server_connection *conn = context;
+       struct auth_client_handshake_reply handshake;
+       const unsigned char *data;
+       size_t size;
+
+       switch (i_stream_read(conn->input)) {
+       case 0:
+               return;
+       case -1:
+               /* disconnected */
+               auth_server_connection_destroy(conn, TRUE);
+               return;
+       case -2:
+               /* buffer full - can't happen unless auth is buggy */
+               i_error("BUG: Auth server sent us more than %d bytes of data",
+                       MAX_INBUF_SIZE);
+               auth_server_connection_destroy(conn, FALSE);
+               return;
+       }
+
+       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));
+
+                       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);
+               }
+               return;
+       }
+
+       if (!conn->reply_received) {
+               data = i_stream_get_data(conn->input, &size);
+               if (size < sizeof(conn->reply))
+                       return;
+
+               memcpy(&conn->reply, data, sizeof(conn->reply));
+               i_stream_skip(conn->input, sizeof(conn->reply));
+               conn->reply_received = TRUE;
+       }
+
+       data = i_stream_get_data(conn->input, &size);
+       if (size < conn->reply.data_size)
+               return;
+
+       /* we've got a full reply */
+       conn->reply_received = FALSE;
+       auth_server_request_handle_reply(conn, &conn->reply, data);
+       i_stream_skip(conn->input, conn->reply.data_size);
+}
+
+struct auth_server_connection *
+auth_server_connection_new(struct auth_client *client, const char *path)
+{
+       struct auth_server_connection *conn;
+       struct auth_client_handshake_request handshake;
+       pool_t pool;
+       int fd;
+
+       fd = net_connect_unix(path);
+       if (fd == -1) {
+               i_error("Can't connect to auth server at %s: %m", path);
+               return NULL;
+       }
+
+       /* use blocking connection since we depend on auth server -
+          if it's slow, just wait */
+
+       pool = pool_alloconly_create("Auth connection", 1024);
+       conn = p_new(pool, struct auth_server_connection, 1);
+       conn->pool = pool;
+
+       conn->client = client;
+       conn->path = p_strdup(pool, path);
+       conn->fd = fd;
+       conn->io = io_add(fd, IO_READ, auth_client_input, conn);
+       conn->input = i_stream_create_file(fd, default_pool, MAX_INBUF_SIZE,
+                                          FALSE);
+       conn->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
+                                           FALSE);
+       conn->requests = hash_create(default_pool, pool, 100, NULL, NULL);
+
+       conn->next = client->connections;
+       client->connections = conn;
+
+       /* send our handshake */
+       memset(&handshake, 0, sizeof(handshake));
+       handshake.client_pid = client->pid;
+
+        client->conn_waiting_handshake_count++;
+       if (o_stream_send(conn->output, &handshake, sizeof(handshake)) < 0) {
+               errno = conn->output->stream_errno;
+               i_warning("Error sending handshake to auth server: %m");
+               auth_server_connection_destroy(conn, TRUE);
+               return NULL;
+       }
+       return conn;
+}
+
+void auth_server_connection_destroy(struct auth_server_connection *conn,
+                                   int reconnect)
+{
+       struct auth_client *client = conn->client;
+       struct auth_server_connection **pos;
+
+        pos = &conn->client->connections;
+       for (; *pos != NULL; pos = &(*pos)->next) {
+               if (*pos == conn) {
+                       *pos = conn->next;
+                       break;
+               }
+       }
+
+       if (!conn->handshake_received)
+               client->conn_waiting_handshake_count--;
+
+       io_remove(conn->io);
+       if (close(conn->fd) < 0)
+               i_error("close(auth) failed: %m");
+       conn->fd = -1;
+
+       auth_server_requests_remove_all(conn);
+       hash_destroy(conn->requests);
+
+       i_stream_unref(conn->input);
+       o_stream_unref(conn->output);
+       pool_unref(conn->pool);
+
+       if (reconnect)
+               auth_client_connect_missing_servers(client);
+       else {
+               client->connect_notify_callback(client,
+                               auth_client_is_connected(client),
+                               client->connect_notify_context);
+       }
+}
+
+struct auth_server_connection *
+auth_server_connection_find_path(struct auth_client *client, const char *path)
+{
+       struct auth_server_connection *conn;
+
+       for (conn = client->connections; conn != NULL; conn = conn->next) {
+               if (strcmp(conn->path, path) == 0)
+                       return conn;
+       }
+
+       return NULL;
+}
+
+struct auth_server_connection *
+auth_server_connection_find_mech(struct auth_client *client,
+                                enum auth_mech mech, const char **error_r)
+{
+       struct auth_server_connection *conn;
+
+       for (conn = client->connections; conn != NULL; conn = conn->next) {
+               if ((conn->available_auth_mechs & mech))
+                       return conn;
+       }
+
+       if ((client->available_auth_mechs & mech) == 0)
+               *error_r = "Unsupported authentication mechanism";
+       else {
+               *error_r = "Authentication server isn't connected, "
+                       "try again later..";
+       }
+
+       return NULL;
+}
diff --git a/src/lib-auth/auth-server-connection.h b/src/lib-auth/auth-server-connection.h
new file mode 100644 (file)
index 0000000..bf3dc89
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef __AUTH_SERVER_CONNECTION_H
+#define __AUTH_SERVER_CONNECTION_H
+
+struct auth_client {
+       unsigned int pid;
+
+       struct auth_server_connection *connections;
+       struct timeout *to_reconnect;
+
+       unsigned int conn_waiting_handshake_count;
+
+       enum auth_mech available_auth_mechs;
+       unsigned int request_id_counter;
+
+       auth_connect_notify_callback_t *connect_notify_callback;
+       void *connect_notify_context;
+};
+
+struct auth_server_connection {
+       struct auth_server_connection *next;
+
+       pool_t pool;
+       struct auth_client *client;
+       const char *path;
+       int fd;
+
+       struct io *io;
+       struct istream *input;
+       struct ostream *output;
+
+       unsigned int pid;
+       enum auth_mech available_auth_mechs;
+        struct auth_client_request_reply reply;
+
+        struct hash_table *requests;
+
+       unsigned int handshake_received:1;
+       unsigned int reply_received:1;
+};
+
+struct auth_server_connection *
+auth_server_connection_new(struct auth_client *client, const char *path);
+void auth_server_connection_destroy(struct auth_server_connection *conn,
+                                   int reconnect);
+
+struct auth_server_connection *
+auth_server_connection_find_path(struct auth_client *client, const char *path);
+
+struct auth_server_connection *
+auth_server_connection_find_mech(struct auth_client *client,
+                                enum auth_mech mech, const char **error_r);
+
+#endif
diff --git a/src/lib-auth/auth-server-request.c b/src/lib-auth/auth-server-request.c
new file mode 100644 (file)
index 0000000..04193da
--- /dev/null
@@ -0,0 +1,134 @@
+/* Copyright (C) 2003 Timo Sirainen */
+
+#include "lib.h"
+#include "hash.h"
+#include "ostream.h"
+#include "auth-client.h"
+#include "auth-server-connection.h"
+#include "auth-server-request.h"
+
+struct auth_request {
+        enum auth_mech mech;
+        struct auth_server_connection *conn;
+
+       unsigned int id;
+
+       auth_request_callback_t *callback;
+       void *context;
+
+       unsigned int init_sent:1;
+};
+
+void auth_server_request_handle_reply(struct auth_server_connection *conn,
+                                     struct auth_client_request_reply *reply,
+                                     const unsigned char *data)
+{
+       struct auth_request *request;
+
+       request = hash_lookup(conn->requests, POINTER_CAST(reply->id));
+       if (request == NULL) {
+               i_error("BUG: Auth server sent us reply with unknown ID %u",
+                       reply->id);
+               return;
+       }
+
+       request->callback(request, reply, data, request->context);
+
+       if (reply->result != AUTH_CLIENT_RESULT_CONTINUE) {
+               hash_remove(conn->requests, POINTER_CAST(request->id));
+               i_free(request);
+       }
+}
+
+static void request_hash_remove(void *key __attr_unused__, void *value,
+                               void *context __attr_unused__)
+{
+       struct auth_request *request = value;
+
+       request->callback(request, NULL, NULL, request->context);
+       request->conn = NULL;
+}
+
+void auth_server_requests_remove_all(struct auth_server_connection *conn)
+{
+       hash_foreach(conn->requests, request_hash_remove, NULL);
+}
+
+struct auth_request *
+auth_client_request_new(struct auth_client *client,
+                       enum auth_mech mech, enum auth_protocol protocol,
+                       auth_request_callback_t *callback, void *context,
+                       const char **error_r)
+{
+       struct auth_server_connection *conn;
+       struct auth_request *request;
+       struct auth_client_request_new auth_request;
+
+       conn = auth_server_connection_find_mech(client, mech, error_r);
+       if (conn == NULL)
+               return NULL;
+
+       request = i_new(struct auth_request, 1);
+       request->mech = mech;
+       request->conn = conn;
+       request->id = ++client->request_id_counter;
+       if (request->id == 0) {
+               /* wrapped - ID 0 not allowed */
+               request->id = ++client->request_id_counter;
+       }
+       request->callback = callback;
+       request->context = context;
+
+       hash_insert(conn->requests, POINTER_CAST(request->id), request);
+
+       /* send request to auth */
+       auth_request.type = AUTH_CLIENT_REQUEST_NEW;
+       auth_request.id = request->id;
+       auth_request.protocol = protocol;
+       auth_request.mech = request->mech;
+       if (o_stream_send(request->conn->output, &auth_request,
+                         sizeof(auth_request)) < 0) {
+               errno = request->conn->output->stream_errno;
+               i_warning("Error sending request to auth process: %m");
+               auth_server_connection_destroy(request->conn, TRUE);
+       }
+       return request;
+}
+
+void auth_client_request_continue(struct auth_request *request,
+                                 const unsigned char *data, size_t data_size)
+{
+       struct auth_client_request_continue auth_request;
+
+       /* send continued request to auth */
+       auth_request.type = AUTH_CLIENT_REQUEST_CONTINUE;
+       auth_request.id = request->id;
+       auth_request.data_size = data_size;
+
+       if (o_stream_send(request->conn->output, &auth_request,
+                         sizeof(auth_request)) < 0 ||
+           o_stream_send(request->conn->output, data, data_size) < 0) {
+               errno = request->conn->output->stream_errno;
+               i_warning("Error sending continue request to auth process: %m");
+               auth_server_connection_destroy(request->conn, TRUE);
+       }
+}
+
+void auth_client_request_abort(struct auth_request *request)
+{
+       void *id = POINTER_CAST(request->id);
+
+       if (hash_lookup(request->conn->requests, id) != NULL)
+               hash_remove(request->conn->requests, id);
+       i_free(request);
+}
+
+unsigned int auth_client_request_get_id(struct auth_request *request)
+{
+       return request->id;
+}
+
+unsigned int auth_client_request_get_server_pid(struct auth_request *request)
+{
+       return request->conn->pid;
+}
diff --git a/src/lib-auth/auth-server-request.h b/src/lib-auth/auth-server-request.h
new file mode 100644 (file)
index 0000000..8ed99de
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __AUTH_SERVER_REQUEST_H
+#define __AUTH_SERVER_REQUEST_H
+
+void auth_server_request_handle_reply(struct auth_server_connection *conn,
+                                     struct auth_client_request_reply *reply,
+                                     const unsigned char *data);
+
+void auth_server_requests_remove_all(struct auth_server_connection *conn);
+
+#endif
index 7013d3111872b711e76d30adb85fa4033d8e4ae6..b3aabccf8017f08a6ced66b48a72c1e7ee8f9086 100644 (file)
@@ -2,12 +2,12 @@ noinst_LIBRARIES = liblogin-common.a
 
 INCLUDES = \
        -I$(top_srcdir)/src/lib \
+       -I$(top_srcdir)/src/lib-auth \
        -DPKG_RUNDIR=\""$(localstatedir)/run/$(PACKAGE)"\" \
        -DSBINDIR=\""$(sbindir)"\"
 
 liblogin_common_a_SOURCES = \
        auth-common.c \
-       auth-connection.c \
        main.c \
        master.c \
        ssl-proxy.c \
@@ -16,7 +16,6 @@ liblogin_common_a_SOURCES = \
 
 noinst_HEADERS = \
        auth-common.h \
-       auth-connection.h \
        client-common.h \
        common.h \
        master.h \
index 1e4ee29b361e228e3ac10894fbe56d591484e7a3..83c932d72c58f52aed57a41d73ab0b2be5152d40 100644 (file)
@@ -3,11 +3,11 @@
 #include "common.h"
 #include "ioloop.h"
 #include "client-common.h"
-#include "auth-connection.h"
+#include "auth-client.h"
 #include "auth-common.h"
 
-static const char *auth_login_get_str(struct auth_login_reply *reply,
-                                     const unsigned char *data, size_t idx)
+static const char *auth_client_get_str(struct auth_client_request_reply *reply,
+                                      const unsigned char *data, size_t idx)
 {
        size_t stop;
 
@@ -20,47 +20,44 @@ static const char *auth_login_get_str(struct auth_login_reply *reply,
        return t_strndup(data + idx, stop);
 }
 
-int auth_callback(struct auth_request *request, struct auth_login_reply *reply,
+int auth_callback(struct auth_request *request,
+                 struct auth_client_request_reply *reply,
                  const unsigned char *data, struct client *client,
-                 master_callback_t *master_callback, const char **error)
+                 master_callback_t *master_callback, const char **error_r)
 {
        const char *user;
 
-       *error = NULL;
+       *error_r = NULL;
 
        if (reply == NULL) {
                /* failed */
-               if (client->auth_request != NULL) {
-                       auth_request_unref(client->auth_request);
-                       client->auth_request = NULL;
-               }
-               *error = "Authentication process died.";
+               client->auth_request = NULL;
+               *error_r = "Authentication process died.";
                return -1;
        }
 
        switch (reply->result) {
-       case AUTH_LOGIN_RESULT_CONTINUE:
+       case AUTH_CLIENT_RESULT_CONTINUE:
                if (client->auth_request != NULL) {
                        i_assert(client->auth_request == request);
                } else {
                        i_assert(client->auth_request == NULL);
 
                        client->auth_request = request;
-                       auth_request_ref(client->auth_request);
                }
                return 0;
 
-       case AUTH_LOGIN_RESULT_SUCCESS:
-                auth_request_unref(client->auth_request);
+       case AUTH_CLIENT_RESULT_SUCCESS:
                client->auth_request = NULL;
 
-               user = auth_login_get_str(reply, data, reply->username_idx);
+               user = auth_client_get_str(reply, data, reply->username_idx);
 
                i_free(client->virtual_user);
                client->virtual_user = i_strdup(user);
 
-               master_request_imap(client, master_callback,
-                                   request->conn->pid, request->id);
+               master_request_login(client, master_callback,
+                       auth_client_request_get_server_pid(request),
+                       auth_client_request_get_id(request));
 
                /* disable IO until we're back from master */
                if (client->io != NULL) {
@@ -69,14 +66,13 @@ int auth_callback(struct auth_request *request, struct auth_login_reply *reply,
                }
                return 1;
 
-       case AUTH_LOGIN_RESULT_FAILURE:
+       case AUTH_CLIENT_RESULT_FAILURE:
                /* see if we have error message */
-                auth_request_unref(client->auth_request);
                client->auth_request = NULL;
 
                if (reply->data_size > 0 && data[reply->data_size-1] == '\0') {
-                       *error = t_strconcat("Authentication failed: ",
-                                            (const char *) data, NULL);
+                       *error_r = t_strconcat("Authentication failed: ",
+                                              (const char *) data, NULL);
                }
                return -1;
        }
index c7ba088cc672f45ce9a11c03b49f9e54e9af1ee0..794588e44a064a82e734c54ca345cb89ce67feb2 100644 (file)
@@ -1,9 +1,10 @@
 #ifndef __AUTH_COMMON_H
 #define __AUTH_COMMON_H
 
-int auth_callback(struct auth_request *request, struct auth_login_reply *reply,
+int auth_callback(struct auth_request *request,
+                 struct auth_client_request_reply *reply,
                  const unsigned char *data, struct client *client,
-                 master_callback_t *master_callback, const char **error);
+                 master_callback_t *master_callback, const char **error_r);
 
 #endif
 
diff --git a/src/login-common/auth-connection.c b/src/login-common/auth-connection.c
deleted file mode 100644 (file)
index 77e1efa..0000000
+++ /dev/null
@@ -1,443 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "common.h"
-#include "hash.h"
-#include "ioloop.h"
-#include "network.h"
-#include "istream.h"
-#include "ostream.h"
-#include "client-common.h"
-#include "auth-connection.h"
-
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/stat.h>
-
-/* Maximum size for an auth reply. 50kB should be more than enough. */
-#define MAX_INBUF_SIZE (1024*50)
-
-#define MAX_OUTBUF_SIZE \
-       (sizeof(struct auth_login_request_continue) + \
-        AUTH_LOGIN_MAX_REQUEST_DATA_SIZE)
-
-enum auth_mech available_auth_mechs;
-
-static int auth_reconnect;
-static unsigned int request_id_counter;
-static struct auth_connection *auth_connections;
-static struct timeout *to;
-static unsigned int auth_waiting_handshake_count;
-
-static void auth_connection_destroy(struct auth_connection *conn);
-static void auth_connection_unref(struct auth_connection *conn);
-
-static void auth_input(void *context);
-static void auth_connect_missing(void);
-
-static struct auth_connection *auth_connection_find(const char *path)
-{
-       struct auth_connection *conn;
-
-       for (conn = auth_connections; conn != NULL; conn = conn->next) {
-               if (strcmp(conn->path, path) == 0)
-                       return conn;
-       }
-
-       return NULL;
-}
-
-static struct auth_connection *auth_connection_new(const char *path)
-{
-       struct auth_connection *conn;
-        struct auth_login_handshake_input handshake;
-       int fd;
-
-       fd = net_connect_unix(path);
-       if (fd == -1) {
-               i_error("Can't connect to auth process at %s: %m", path);
-                auth_reconnect = TRUE;
-               return NULL;
-       }
-
-       /* use blocking connection since we depend on auth process -
-          if it's slow, just wait */
-
-       conn = i_new(struct auth_connection, 1);
-       conn->refcount = 1;
-       conn->path = i_strdup(path);
-       conn->fd = fd;
-       conn->io = io_add(fd, IO_READ, auth_input, conn);
-       conn->input = i_stream_create_file(fd, default_pool, MAX_INBUF_SIZE,
-                                          FALSE);
-       conn->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
-                                           FALSE);
-       conn->requests = hash_create(default_pool, default_pool, 100,
-                                    NULL, NULL);
-
-       conn->next = auth_connections;
-       auth_connections = conn;
-
-       /* send our handshake */
-        auth_waiting_handshake_count++;
-       memset(&handshake, 0, sizeof(handshake));
-       handshake.pid = login_process_uid;
-       if (o_stream_send(conn->output, &handshake, sizeof(handshake)) < 0) {
-               errno = conn->output->stream_errno;
-               i_warning("Error sending handshake to auth process: %m");
-               auth_connection_destroy(conn);
-               return NULL;
-       }
-       return conn;
-}
-
-static void request_hash_remove(void *key __attr_unused__, void *value,
-                               void *context __attr_unused__)
-{
-       struct auth_request *request = value;
-
-       request->callback(request, NULL, NULL, request->context);
-}
-
-static void request_hash_destroy(void *key __attr_unused__, void *value,
-                                void *context __attr_unused__)
-{
-       struct auth_request *request = value;
-
-       i_free(request);
-}
-
-static void auth_connection_destroy(struct auth_connection *conn)
-{
-       struct auth_connection **pos;
-
-       if (conn->fd == -1)
-               return;
-
-       for (pos = &auth_connections; *pos != NULL; pos = &(*pos)->next) {
-               if (*pos == conn) {
-                       *pos = conn->next;
-                       break;
-               }
-       }
-
-       if (!conn->handshake_received)
-               auth_waiting_handshake_count--;
-
-       if (close(conn->fd) < 0)
-               i_error("close(auth) failed: %m");
-       io_remove(conn->io);
-       conn->fd = -1;
-
-       hash_foreach(conn->requests, request_hash_remove, NULL);
-
-        auth_connection_unref(conn);
-
-       if (auth_is_connected())
-               clients_notify_auth_process();
-}
-
-static void auth_connection_unref(struct auth_connection *conn)
-{
-       if (--conn->refcount > 0)
-               return;
-
-       hash_foreach(conn->requests, request_hash_destroy, NULL);
-       hash_destroy(conn->requests);
-
-       i_stream_unref(conn->input);
-       o_stream_unref(conn->output);
-       i_free(conn->path);
-       i_free(conn);
-}
-
-static struct auth_connection *
-auth_connection_get(enum auth_mech mech, size_t size, const char **error)
-{
-       struct auth_connection *conn;
-       int found;
-
-       found = FALSE;
-       for (conn = auth_connections; conn != NULL; conn = conn->next) {
-               if ((conn->available_auth_mechs & mech)) {
-                       if (o_stream_have_space(conn->output, size) > 0)
-                               return conn;
-
-                       found = TRUE;
-               }
-       }
-
-       if (!found) {
-               if ((available_auth_mechs & mech) == 0)
-                       *error = "Unsupported authentication mechanism";
-               else {
-                       *error = "Authentication server isn't connected, "
-                               "try again later..";
-                       auth_reconnect = TRUE;
-               }
-       } else {
-               *error = "Authentication servers are busy, wait..";
-               i_warning("Authentication servers are busy");
-       }
-
-       return NULL;
-}
-
-static void update_available_auth_mechs(void)
-{
-       struct auth_connection *conn;
-
-        available_auth_mechs = 0;
-       for (conn = auth_connections; conn != NULL; conn = conn->next)
-                available_auth_mechs |= conn->available_auth_mechs;
-}
-
-static void auth_handle_handshake(struct auth_connection *conn,
-                                 struct auth_login_handshake_output *handshake)
-{
-       if (handshake->pid == 0) {
-               i_error("BUG: Auth process said it's PID 0");
-               auth_connection_destroy(conn);
-               return;
-       }
-
-       conn->pid = handshake->pid;
-       conn->available_auth_mechs = handshake->auth_mechanisms;
-       conn->handshake_received = TRUE;
-
-        auth_waiting_handshake_count--;
-       update_available_auth_mechs();
-
-       if (auth_is_connected())
-               clients_notify_auth_process();
-}
-
-static void auth_handle_reply(struct auth_connection *conn,
-                             struct auth_login_reply *reply,
-                             const unsigned char *data)
-{
-       struct auth_request *request;
-
-       request = hash_lookup(conn->requests, POINTER_CAST(reply->id));
-       if (request == NULL) {
-               i_error("BUG: Auth process sent us reply with unknown ID %u",
-                       reply->id);
-               return;
-       }
-
-       request->callback(request, reply, data, request->context);
-
-       if (reply->result != AUTH_LOGIN_RESULT_CONTINUE) {
-               hash_remove(conn->requests, POINTER_CAST(request->id));
-               i_free(request);
-       }
-}
-
-static void auth_input(void *context)
-{
-       struct auth_connection *conn = context;
-        struct auth_login_handshake_output handshake;
-       const unsigned char *data;
-       size_t size;
-
-       switch (i_stream_read(conn->input)) {
-       case 0:
-               return;
-       case -1:
-               /* disconnected */
-                auth_reconnect = TRUE;
-               auth_connection_destroy(conn);
-               return;
-       case -2:
-               /* buffer full - can't happen unless auth is buggy */
-               i_error("BUG: Auth process sent us more than %d bytes of data",
-                       MAX_INBUF_SIZE);
-               auth_connection_destroy(conn);
-               return;
-       }
-
-       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));
-
-                       auth_handle_handshake(conn, &handshake);
-               } else if (size > sizeof(handshake)) {
-                       i_error("BUG: Auth process sent us too large handshake "
-                               "(%"PRIuSIZE_T " vs %"PRIuSIZE_T")", size,
-                               sizeof(handshake));
-                       auth_connection_destroy(conn);
-               }
-               return;
-       }
-
-       if (!conn->reply_received) {
-               data = i_stream_get_data(conn->input, &size);
-               if (size < sizeof(conn->reply))
-                       return;
-
-               memcpy(&conn->reply, data, sizeof(conn->reply));
-               i_stream_skip(conn->input, sizeof(conn->reply));
-               conn->reply_received = TRUE;
-       }
-
-       data = i_stream_get_data(conn->input, &size);
-       if (size < conn->reply.data_size)
-               return;
-
-       /* we've got a full reply */
-       conn->reply_received = FALSE;
-       auth_handle_reply(conn, &conn->reply, data);
-       i_stream_skip(conn->input, conn->reply.data_size);
-}
-
-int auth_init_request(enum auth_mech mech, enum auth_protocol protocol,
-                     auth_callback_t callback, void *context,
-                     const char **error)
-{
-       struct auth_connection *conn;
-       struct auth_request *request;
-       struct auth_login_request_new auth_request;
-
-       if (auth_reconnect)
-               auth_connect_missing();
-
-       conn = auth_connection_get(mech, sizeof(auth_request), error);
-       if (conn == NULL)
-               return FALSE;
-
-       /* create internal request structure */
-       request = i_new(struct auth_request, 1);
-       request->mech = mech;
-       request->conn = conn;
-       request->id = ++request_id_counter;
-       if (request->id == 0) {
-               /* wrapped - ID 0 not allowed */
-               request->id = ++request_id_counter;
-       }
-       request->callback = callback;
-       request->context = context;
-
-       hash_insert(conn->requests, POINTER_CAST(request->id), request);
-
-       /* send request to auth */
-       auth_request.type = AUTH_LOGIN_REQUEST_NEW;
-       auth_request.protocol = protocol;
-       auth_request.mech = request->mech;
-       auth_request.id = request->id;
-       if (o_stream_send(request->conn->output, &auth_request,
-                         sizeof(auth_request)) < 0) {
-               errno = request->conn->output->stream_errno;
-               i_warning("Error sending request to auth process: %m");
-               auth_connection_destroy(request->conn);
-       }
-       return TRUE;
-}
-
-void auth_continue_request(struct auth_request *request,
-                          const unsigned char *data, size_t data_size)
-{
-       struct auth_login_request_continue auth_request;
-
-       /* send continued request to auth */
-       auth_request.type = AUTH_LOGIN_REQUEST_CONTINUE;
-       auth_request.id = request->id;
-       auth_request.data_size = data_size;
-
-       if (o_stream_send(request->conn->output, &auth_request,
-                         sizeof(auth_request)) < 0 ||
-           o_stream_send(request->conn->output, data, data_size) < 0) {
-               errno = request->conn->output->stream_errno;
-               i_warning("Error sending continue request to auth process: %m");
-               auth_connection_destroy(request->conn);
-       }
-}
-
-void auth_abort_request(struct auth_request *request)
-{
-       void *id = POINTER_CAST(request->id);
-
-       if (hash_lookup(request->conn->requests, id) != NULL)
-               hash_remove(request->conn->requests, id);
-       i_free(request);
-}
-
-void auth_request_ref(struct auth_request *request)
-{
-       request->conn->refcount++;
-}
-
-void auth_request_unref(struct auth_request *request)
-{
-       auth_connection_unref(request->conn);
-}
-
-int auth_is_connected(void)
-{
-       return !auth_reconnect && auth_waiting_handshake_count == 0;
-}
-
-static void auth_connect_missing(void)
-{
-       DIR *dirp;
-       struct dirent *dp;
-       struct stat st;
-
-       auth_reconnect = TRUE;
-
-       /* we're chrooted into */
-       dirp = opendir(".");
-       if (dirp == NULL) {
-               i_error("opendir(\".\") failed when trying to get list of "
-                       "authentication servers: %m");
-               return;
-       }
-
-       while ((dp = readdir(dirp)) != NULL) {
-               if (dp->d_name[0] == '.')
-                       continue;
-
-               if (auth_connection_find(dp->d_name) != NULL) {
-                       /* already connected */
-                       continue;
-               }
-
-               if (stat(dp->d_name, &st) == 0 && S_ISSOCK(st.st_mode)) {
-                       if (auth_connection_new(dp->d_name) != NULL)
-                               auth_reconnect = FALSE;
-               }
-       }
-
-       (void)closedir(dirp);
-}
-
-static void
-auth_connect_missing_timeout(void *context __attr_unused__)
-{
-       if (auth_reconnect)
-                auth_connect_missing();
-}
-
-void auth_connection_init(void)
-{
-       auth_connections = NULL;
-       request_id_counter = 0;
-       auth_reconnect = FALSE;
-        auth_waiting_handshake_count = 0;
-
-       auth_connect_missing();
-       to = timeout_add(1000, auth_connect_missing_timeout, NULL);
-}
-
-void auth_connection_deinit(void)
-{
-       struct auth_connection *next;
-
-       while (auth_connections != NULL) {
-               next = auth_connections->next;
-               auth_connection_destroy(auth_connections);
-               auth_connections = next;
-       }
-
-       timeout_remove(to);
-}
diff --git a/src/login-common/auth-connection.h b/src/login-common/auth-connection.h
deleted file mode 100644 (file)
index 5e5cf7d..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef __AUTH_CONNECTION_H
-#define __AUTH_CONNECTION_H
-
-struct client;
-struct auth_request;
-
-/* reply is NULL if auth connection died */
-typedef void auth_callback_t(struct auth_request *request,
-                            struct auth_login_reply *reply,
-                            const unsigned char *data, struct client *client);
-
-struct auth_connection {
-       struct auth_connection *next;
-       int refcount;
-
-       char *path;
-       int fd;
-       struct io *io;
-       struct istream *input;
-       struct ostream *output;
-
-       unsigned int pid;
-       enum auth_mech available_auth_mechs;
-        struct auth_login_reply reply;
-
-        struct hash_table *requests;
-
-       unsigned int handshake_received:1;
-       unsigned int reply_received:1;
-};
-
-struct auth_request {
-        enum auth_mech mech;
-        struct auth_connection *conn;
-
-       unsigned int id;
-
-       auth_callback_t *callback;
-       void *context;
-
-       unsigned int init_sent:1;
-};
-
-extern enum auth_mech available_auth_mechs;
-
-int auth_init_request(enum auth_mech mech, enum auth_protocol protocol,
-                     auth_callback_t callback, void *context,
-                     const char **error);
-
-void auth_continue_request(struct auth_request *request,
-                          const unsigned char *data, size_t data_size);
-
-void auth_abort_request(struct auth_request *request);
-
-void auth_request_ref(struct auth_request *request);
-void auth_request_unref(struct auth_request *request);
-
-int auth_is_connected(void);
-
-void auth_connection_init(void);
-void auth_connection_deinit(void);
-
-#endif
index d45c5177a63915b893eb41d2f82f075a4cc5b79f..1d52e7e57fa4dcb040c032f55a2c6827e39e31dc 100644 (file)
@@ -10,7 +10,8 @@ struct client {
        int fd;
        struct io *io;
 
-        struct auth_request *auth_request;
+       struct auth_request *auth_request;
+       unsigned int master_tag;
        master_callback_t *master_callback;
 
        char *virtual_user;
@@ -20,7 +21,7 @@ struct client {
 struct client *client_create(int fd, struct ip_addr *ip, int ssl);
 
 unsigned int clients_get_count(void);
-void clients_notify_auth_process(void);
+void clients_notify_auth_connected(void);
 void clients_destroy_all(void);
 
 void clients_init(void);
index 153855d100d3aa1ef730f62e3216a46182d6906a..77dc2a368b15775d5ba5f72c42f227caf46c6cb8 100644 (file)
@@ -2,12 +2,12 @@
 #define __COMMON_H
 
 #include "lib.h"
-#include "../auth/auth-login-interface.h"
 
 extern int disable_plaintext_auth, process_per_connection, verbose_proctitle;
 extern int verbose_ssl;
 extern unsigned int max_logging_users;
 extern unsigned int login_process_uid;
+extern struct auth_client *auth_client;
 
 void main_ref(void);
 void main_unref(void);
index ec129d65dbd86f69ca369686c2dc2b24ffeeda33..e0f640a38a15d1f4580a868e739e9e8f874362c2 100644 (file)
@@ -7,9 +7,9 @@
 #include "restrict-process-size.h"
 #include "process-title.h"
 #include "fd-close-on-exec.h"
-#include "auth-connection.h"
 #include "master.h"
 #include "client-common.h"
+#include "auth-client.h"
 #include "ssl-proxy.h"
 
 #include <stdlib.h>
@@ -20,6 +20,7 @@ int disable_plaintext_auth, process_per_connection, verbose_proctitle;
 int verbose_ssl;
 unsigned int max_logging_users;
 unsigned int login_process_uid;
+struct auth_client *auth_client;
 
 static struct ioloop *ioloop;
 static struct io *io_listen, *io_ssl_listen;
@@ -113,6 +114,13 @@ static void login_accept_ssl(void *context __attr_unused__)
                (void)client_create(fd_ssl, &ip, TRUE);
 }
 
+static void auth_connect_notify(struct auth_client *client __attr_unused__,
+                               int connected, void *context __attr_unused__)
+{
+       if (connected)
+                clients_notify_auth_connected();
+}
+
 static void open_logfile(const char *name)
 {
        if (getenv("USE_SYSLOG") != NULL)
@@ -140,6 +148,7 @@ static void drop_privileges(const char *name)
        /* Refuse to run as root - we should never need it and it's
           dangerous with SSL. */
        restrict_access_by_env(TRUE);
+       sleep(5);
 
        /* make sure we can't fork() */
        restrict_process_size((unsigned int)-1, 1);
@@ -169,7 +178,8 @@ static void main_init(void)
         closing_down = FALSE;
        main_refcount = 0;
 
-       auth_connection_init();
+       auth_client = auth_client_new((unsigned int)getpid());
+        auth_client_set_connect_notify(auth_client, auth_connect_notify, NULL);
        clients_init();
 
        io_listen = io_ssl_listen = NULL;
@@ -209,7 +219,7 @@ static void main_deinit(void)
 
        ssl_proxy_deinit();
 
-       auth_connection_deinit();
+       auth_client_free(auth_client);
        clients_deinit();
        master_deinit();
 
index 3e2779ea85a1a9f810831fb4ca46b13543301a42..1b3b87c14f78932701f71c5cef6db4bda2326f2e 100644 (file)
@@ -16,6 +16,7 @@
 static int master_fd;
 static struct io *io_master;
 static struct hash_table *master_requests;
+static unsigned int master_tag_counter;
 
 static unsigned int master_pos;
 static char master_buf[sizeof(struct master_login_reply)];
@@ -33,15 +34,17 @@ static void request_handle(struct master_login_reply *reply)
        hash_remove(master_requests, POINTER_CAST(reply->tag));
 }
 
-void master_request_imap(struct client *client, master_callback_t *callback,
-                        unsigned int auth_pid, unsigned int auth_id)
+void master_request_login(struct client *client, master_callback_t *callback,
+                         unsigned int auth_pid, unsigned int auth_id)
 {
        struct master_login_request req;
 
        i_assert(auth_pid != 0);
 
        memset(&req, 0, sizeof(req));
-       req.tag = client->fd;
+       req.tag = ++master_tag_counter;
+       if (req.tag == 0)
+               req.tag = ++master_tag_counter;
        req.auth_pid = auth_pid;
        req.auth_id = auth_id;
        req.ip = client->ip;
@@ -49,10 +52,20 @@ void master_request_imap(struct client *client, master_callback_t *callback,
        if (fd_send(master_fd, client->fd, &req, sizeof(req)) != sizeof(req))
                i_fatal("fd_send(%d) failed: %m", client->fd);
 
+       client->master_tag = req.tag;
        client->master_callback = callback;
+
        hash_insert(master_requests, POINTER_CAST(req.tag), client);
 }
 
+void master_request_abort(struct client *client)
+{
+       client->master_tag = 0;
+       client->master_callback = NULL;
+
+       hash_remove(master_requests, POINTER_CAST(client->master_tag));
+}
+
 void master_notify_finished(void)
 {
        struct master_login_request req;
index df5f0cc2e04f5758d3796606d830a013c50bd86b..4988caf0d809f917f35524459f5a5bacef3019a1 100644 (file)
@@ -7,8 +7,9 @@ struct client;
 
 typedef void master_callback_t(struct client *client, int success);
 
-void master_request_imap(struct client *client, master_callback_t *callback,
-                        unsigned int auth_pid, unsigned int auth_id);
+void master_request_login(struct client *client, master_callback_t *callback,
+                         unsigned int auth_pid, unsigned int auth_id);
+void master_request_abort(struct client *client);
 
 /* Notify master that we're not listening for new connections anymore. */
 void master_notify_finished(void);
index d69aebc424a1cff5282ae46d21b54fd95705ef0d..1d4d03661e1c5bf5bb9c96a69cef7c0b430bc4cb 100644 (file)
@@ -4,10 +4,12 @@ pkglibexec_PROGRAMS = pop3-login
 
 INCLUDES = \
        -I$(top_srcdir)/src/lib \
+       -I$(top_srcdir)/src/lib-auth \
        -I$(top_srcdir)/src/login-common
 
 pop3_login_LDADD = \
        ../login-common/liblogin-common.a \
+       ../lib-auth/libauth.a \
        ../lib/liblib.a \
        $(SSL_LIBS)
 
@@ -16,6 +18,5 @@ pop3_login_SOURCES = \
        client-authenticate.c
 
 noinst_HEADERS = \
-       common.h \
        client.h \
        client-authenticate.h
index 9690f8181339f19ae16211b3e874f8e1fcb5fe6d..1cb028031e7021b6cb17c2d6cfbc4b503b17391c 100644 (file)
@@ -8,7 +8,7 @@
 #include "ostream.h"
 #include "safe-memset.h"
 #include "str.h"
-#include "auth-connection.h"
+#include "auth-client.h"
 #include "../auth/auth-mech-desc.h"
 #include "../pop3/capability.h"
 #include "master.h"
 #include "client-authenticate.h"
 #include "ssl-proxy.h"
 
-static enum auth_mech auth_mechs = 0;
-static char *auth_mechs_capability = NULL;
-
 int cmd_capa(struct pop3_client *client, const char *args __attr_unused__)
 {
+       static enum auth_mech cached_auth_mechs = 0;
+       static char *cached_capability = NULL;
+        enum auth_mech auth_mechs;
        string_t *str;
        int i;
 
-       if (auth_mechs != available_auth_mechs) {
-               auth_mechs = available_auth_mechs;
-               i_free(auth_mechs_capability);
+       auth_mechs = auth_client_get_available_mechs(auth_client);
+       if (cached_auth_mechs != auth_mechs) {
+               cached_auth_mechs = auth_mechs;
+               i_free(cached_capability);
 
                str = t_str_new(128);
 
@@ -42,13 +43,13 @@ int cmd_capa(struct pop3_client *client, const char *args __attr_unused__)
                        }
                }
 
-               auth_mechs_capability = i_strdup(str_c(str));
+               cached_capability = i_strdup(str_c(str));
        }
 
        client_send_line(client, t_strconcat("+OK\r\n" POP3_CAPABILITY_REPLY,
                                             (ssl_initialized && !client->tls) ?
                                             "STLS\r\n" : "",
-                                            auth_mechs_capability,
+                                            cached_capability,
                                             "\r\n.", NULL));
        return TRUE;
 }
@@ -69,7 +70,7 @@ static struct auth_mech_desc *auth_mech_find(const char *name)
 static void client_auth_abort(struct pop3_client *client, const char *msg)
 {
        if (client->common.auth_request != NULL) {
-               auth_abort_request(client->common.auth_request);
+               auth_client_request_abort(client->common.auth_request);
                client->common.auth_request = NULL;
        }
 
@@ -82,8 +83,6 @@ static void client_auth_abort(struct pop3_client *client, const char *msg)
                io_remove(client->common.io);
        client->common.io = client->common.fd == -1 ? NULL :
                io_add(client->common.fd, IO_READ, client_input, client);
-
-       client_unref(client);
 }
 
 static void master_callback(struct client *_client, int success)
@@ -101,7 +100,6 @@ static void master_callback(struct client *_client, int success)
        }
 
        client_destroy(client, reason);
-       client_unref(client);
 }
 
 static void client_send_auth_data(struct pop3_client *client,
@@ -124,15 +122,15 @@ static void client_send_auth_data(struct pop3_client *client,
 }
 
 static void login_callback(struct auth_request *request,
-                          struct auth_login_reply *reply,
-                          const unsigned char *data, struct client *_client)
+                          struct auth_client_request_reply *reply,
+                          const unsigned char *data, void *context)
 {
-       struct pop3_client *client = (struct pop3_client *) _client;
+       struct pop3_client *client = context;
        const char *error;
        const void *ptr;
        size_t size;
 
-       switch (auth_callback(request, reply, data, _client,
+       switch (auth_callback(request, reply, data, &client->common,
                              master_callback, &error)) {
        case -1:
                /* login failed */
@@ -141,7 +139,7 @@ static void login_callback(struct auth_request *request,
 
        case 0:
                ptr = buffer_get_data(client->plain_login, &size);
-               auth_continue_request(request, ptr, size);
+               auth_client_request_continue(request, ptr, size);
 
                buffer_set_used_size(client->plain_login, 0);
                break;
@@ -182,9 +180,11 @@ int cmd_pass(struct pop3_client *client, const char *args)
        buffer_append_c(client->plain_login, '\0');
        buffer_append(client->plain_login, args, strlen(args));
 
-       client_ref(client);
-       if (auth_init_request(AUTH_MECH_PLAIN, AUTH_PROTOCOL_POP3,
-                             login_callback, &client->common, &error)) {
+       client->common.auth_request =
+               auth_client_request_new(auth_client, AUTH_MECH_PLAIN,
+                                       AUTH_PROTOCOL_POP3,
+                                       login_callback, client, &error);
+       if (client->common.auth_request != NULL) {
                /* don't read any input from client until login is finished */
                if (client->common.io != NULL) {
                        io_remove(client->common.io);
@@ -194,20 +194,18 @@ int cmd_pass(struct pop3_client *client, const char *args)
        } else {
                client_send_line(client,
                        t_strconcat("-ERR Login failed: ", error, NULL));
-               client_unref(client);
                return TRUE;
        }
 }
 
 static void authenticate_callback(struct auth_request *request,
-                                 struct auth_login_reply *reply,
-                                 const unsigned char *data,
-                                 struct client *_client)
+                                 struct auth_client_request_reply *reply,
+                                 const unsigned char *data, void *context)
 {
-       struct pop3_client *client = (struct pop3_client *) _client;
+       struct pop3_client *client = context;
        const char *error;
 
-       switch (auth_callback(request, reply, data, _client,
+       switch (auth_callback(request, reply, data, &client->common,
                              master_callback, &error)) {
        case -1:
                /* login failed */
@@ -255,9 +253,9 @@ static void client_auth_input(void *context)
        } else if (client->common.auth_request == NULL) {
                client_auth_abort(client, "Don't send unrequested data");
        } else {
-               auth_continue_request(client->common.auth_request,
-                                     buffer_get_data(buf, NULL),
-                                     buffer_get_used_size(buf));
+               auth_client_request_continue(client->common.auth_request,
+                                            buffer_get_data(buf, NULL),
+                                            buffer_get_used_size(buf));
        }
 
        /* clear sensitive data */
@@ -286,9 +284,11 @@ int cmd_auth(struct pop3_client *client, const char *args)
                return TRUE;
        }
 
-       client_ref(client);
-       if (auth_init_request(mech->mech, AUTH_PROTOCOL_POP3,
-                             authenticate_callback, &client->common, &error)) {
+       client->common.auth_request =
+               auth_client_request_new(auth_client, mech->mech,
+                                       AUTH_PROTOCOL_POP3,
+                                       authenticate_callback, client, &error);
+       if (client->common.auth_request != NULL) {
                /* following input data will go to authentication */
                if (client->common.io != NULL)
                        io_remove(client->common.io);
@@ -297,7 +297,6 @@ int cmd_auth(struct pop3_client *client, const char *args)
        } else {
                client_send_line(client, t_strconcat(
                        "-ERR Authentication failed: ", error, NULL));
-               client_unref(client);
        }
 
        return TRUE;
index 3c52cb1c599e0567e113f4c4e548898630cdc1dc..4d45addaade87f00feff2efad3921e29306e9c48 100644 (file)
@@ -11,7 +11,7 @@
 #include "strescape.h"
 #include "client.h"
 #include "client-authenticate.h"
-#include "auth-connection.h"
+#include "auth-client.h"
 #include "ssl-proxy.h"
 
 /* max. length of input command line (spec says 512) */
@@ -35,6 +35,8 @@
 static struct hash_table *clients;
 static struct timeout *to_idle;
 
+static int client_unref(struct pop3_client *client);
+
 static void client_set_title(struct pop3_client *client)
 {
        const char *addr;
@@ -157,14 +159,14 @@ void client_input(void *context)
        if (!client_read(client))
                return;
 
-       if (!auth_is_connected()) {
+       if (!auth_client_is_connected(auth_client)) {
                /* we're not yet connected to auth process -
                   don't allow any commands */
                client->input_blocked = TRUE;
                return;
        }
 
-       client_ref(client);
+       client->refcount++;
 
        o_stream_cork(client->output);
        while (!client->output->closed &&
@@ -280,6 +282,14 @@ void client_destroy(struct pop3_client *client, const char *reason)
        i_stream_close(client->input);
        o_stream_close(client->output);
 
+       if (client->common.auth_request != NULL) {
+               auth_client_request_abort(client->common.auth_request);
+                client->common.auth_request = NULL;
+       }
+
+       if (client->common.master_tag != 0)
+               master_request_abort(&client->common);
+
        if (client->common.io != NULL) {
                io_remove(client->common.io);
                client->common.io = NULL;
@@ -291,12 +301,7 @@ void client_destroy(struct pop3_client *client, const char *reason)
        client_unref(client);
 }
 
-void client_ref(struct pop3_client *client)
-{
-       client->refcount++;
-}
-
-int client_unref(struct pop3_client *client)
+static int client_unref(struct pop3_client *client)
 {
        if (--client->refcount > 0)
                return TRUE;
@@ -359,7 +364,7 @@ static void client_hash_check_io(void *key, void *value __attr_unused__,
        }
 }
 
-void clients_notify_auth_process(void)
+void clients_notify_auth_connected(void)
 {
        hash_foreach(clients, client_hash_check_io, NULL);
 }
index 1fc0525fdf0f0bb7e9b0a9712a903bff04edec9c..a1742a95a0db43587aae75d5b5854de61d1f040b 100644 (file)
@@ -27,9 +27,6 @@ struct pop3_client {
 struct client *client_create(int fd, struct ip_addr *ip, int ssl);
 void client_destroy(struct pop3_client *client, const char *reason);
 
-void client_ref(struct pop3_client *client);
-int client_unref(struct pop3_client *client);
-
 void client_send_line(struct pop3_client *client, const char *line);
 void client_syslog(struct pop3_client *client, const char *text);
 
diff --git a/src/pop3-login/common.h b/src/pop3-login/common.h
deleted file mode 100644 (file)
index 5a2a04d..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __COMMON_H
-#define __COMMON_H
-
-#include "lib.h"
-#include "../auth/auth-login-interface.h"
-
-extern int disable_plaintext_auth, process_per_connection, verbose_proctitle;
-extern unsigned int max_logging_users;
-extern unsigned int login_process_uid;
-
-void main_ref(void);
-void main_unref(void);
-
-void main_close_listen(void);
-
-#endif