Mercurial > dovecot > original-hg > dovecot-1.2
changeset 3074:3feb38ff17f5 HEAD
Moving code around.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 09 Jan 2005 02:49:18 +0200 |
parents | 7e0caae73c59 |
children | 9cb91ed5a110 |
files | src/auth/Makefile.am src/auth/auth-client-connection.c src/auth/auth-client-connection.h src/auth/auth-master-connection.c src/auth/auth-master-connection.h src/auth/auth-request-handler.c src/auth/auth-request-handler.h src/auth/auth-request.c src/auth/auth-request.h src/auth/main.c src/auth/mech-apop.c src/master/auth-process.c |
diffstat | 12 files changed, 692 insertions(+), 575 deletions(-) [+] |
line wrap: on
line diff
--- a/src/auth/Makefile.am Sun Jan 09 02:48:02 2005 +0200 +++ b/src/auth/Makefile.am Sun Jan 09 02:49:18 2005 +0200 @@ -38,6 +38,7 @@ auth-master-connection.c \ auth-module.c \ auth-request.c \ + auth-request-handler.c \ db-ldap.c \ db-sql.c \ db-passwd-file.c \ @@ -80,6 +81,7 @@ auth-master-connection.h \ auth-module.h \ auth-request.h \ + auth-request-handler.h \ db-ldap.h \ db-sql.h \ db-passwd-file.h \
--- a/src/auth/auth-client-connection.c Sun Jan 09 02:48:02 2005 +0200 +++ b/src/auth/auth-client-connection.c Sun Jan 09 02:49:18 2005 +0200 @@ -1,39 +1,32 @@ -/* Copyright (C) 2002-2003 Timo Sirainen */ +/* Copyright (C) 2002-2005 Timo Sirainen */ #include "common.h" #include "ioloop.h" #include "istream.h" #include "ostream.h" #include "network.h" -#include "base64.h" -#include "buffer.h" -#include "hash.h" #include "str.h" -#include "str-sanitize.h" #include "safe-memset.h" -#include "auth-request.h" +#include "auth-request-handler.h" +#include "auth-client-interface.h" #include "auth-client-connection.h" #include "auth-master-connection.h" #include <stdlib.h> -/* Used only for string sanitization. */ -#define MAX_MECH_NAME_LEN 64 - -#define MAX_OUTBUF_SIZE (1024*50) +#define OUTBUF_THROTTLE_SIZE (1024*50) static void auth_client_connection_unref(struct auth_client_connection *conn); -static void -auth_client_connection_destroy_wait(struct auth_client_connection *conn); +static void auth_client_input(void *context); static void auth_client_send(struct auth_client_connection *conn, const char *fmt, ...) __attr_format__(2, 3); + static void auth_client_send(struct auth_client_connection *conn, const char *fmt, ...) { va_list args; string_t *str; - ssize_t ret; i_assert(conn->refcount > 1); @@ -42,114 +35,32 @@ str = t_str_new(256); str_vprintfa(str, fmt, args); str_append_c(str, '\n'); - ret = o_stream_send(conn->output, str_data(str), str_len(str)); - if (ret != (ssize_t)str->used) { - i_warning("Authentication client %u: " - "Transmit buffer full, killing it", conn->pid); - auth_client_connection_destroy_wait(conn); + (void)o_stream_send(conn->output, str_data(str), str_len(str)); + + if (o_stream_get_buffer_used_size(conn->output) >= + OUTBUF_THROTTLE_SIZE) { + /* stop reading new requests until client has read the pending + replies. */ + if (conn->io != NULL) { + io_remove(conn->io); + conn->io = NULL; + } } va_end(args); t_pop(); } -static const char *get_client_extra_fields(struct auth_request *request) +static void auth_callback(const char *reply, void *context) { - const char **fields; - unsigned int src, dest; - - if (request->extra_fields == NULL) - return NULL; - - /* we only wish to remove all fields prefixed with "userdb_" */ - if (strstr(request->extra_fields, "userdb_") == NULL) - return request->extra_fields; - - fields = t_strsplit(request->extra_fields, "\t"); - for (src = dest = 0; fields[src] != NULL; src++) { - if (strncmp(fields[src], "userdb_", 7) == 0) - fields[dest++] = fields[src]; - } - fields[dest] = NULL; - return t_strarray_join(fields, "\t"); -} - -static void auth_callback(struct auth_request *request, - enum auth_client_result result, - const void *reply, size_t reply_size) -{ - string_t *str = NULL; - const char *fields; - ssize_t ret; - - t_push(); + struct auth_client_connection *conn = context; - switch (result) { - case AUTH_CLIENT_RESULT_CONTINUE: - str = t_str_new(32 + MAX_BASE64_ENCODED_SIZE(reply_size)); - str_printfa(str, "CONT\t%u\t", request->id); - base64_encode(reply, reply_size, str); - request->accept_input = TRUE; - break; - case AUTH_CLIENT_RESULT_SUCCESS: - str = t_str_new(128 + MAX_BASE64_ENCODED_SIZE(reply_size)); - str_printfa(str, "OK\t%u\tuser=%s", request->id, request->user); - if (reply_size > 0) { - str_append(str, "\tresp="); - base64_encode(reply, reply_size, str); - } - t_push(); - fields = get_client_extra_fields(request); - if (fields != NULL) { - str_append_c(str, '\t'); - str_append(str, fields); - } - t_pop(); - break; - case AUTH_CLIENT_RESULT_FAILURE: - str = t_str_new(128); - str_printfa(str, "FAIL\t%u", request->id); - if (request->user != NULL) - str_printfa(str, "\tuser=%s", request->user); - if (request->internal_failure) - str_append(str, "\ttemp"); - t_push(); - fields = get_client_extra_fields(request); - if (fields != NULL) { - str_append_c(str, '\t'); - str_append(str, fields); - } - t_pop(); - break; + if (reply == NULL) { + /* handler destroyed */ + auth_client_connection_unref(conn); + return; } - str_append_c(str, '\n'); - - ret = o_stream_send(request->conn->output, str->data, str->used); - if (ret < 0) - auth_client_connection_destroy(request->conn); - else if ((size_t)ret != str->used) { - i_warning("Authentication client %u: " - "Transmit buffer full, killing it", - request->conn->pid); - auth_client_connection_destroy_wait(request->conn); - } - t_pop(); - - auth_client_connection_unref(request->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; + auth_client_send(conn, "%s", reply); } static int @@ -158,10 +69,7 @@ struct auth_client_connection *old; unsigned int pid; - if (conn->pid != 0) { - i_error("BUG: Authentication client re-handshaking"); - return FALSE; - } + i_assert(conn->pid == 0); pid = (unsigned int)strtoul(args, NULL, 10); if (pid == 0) { @@ -173,6 +81,7 @@ if (old != NULL) { /* already exists. it's possible that it just reconnected, see if the old connection is still there. */ + i_assert(old != conn); if (i_stream_read(old->input) == -1) { auth_client_connection_destroy(old); old = NULL; @@ -185,167 +94,54 @@ return FALSE; } + /* handshake complete, we can now actually start serving requests */ + conn->refcount++; + if (!AUTH_MASTER_IS_DUMMY(conn->master)) { + conn->request_handler = + auth_request_handler_create(conn->auth, + conn->connect_uid, pid, auth_callback, conn, + auth_master_request_callback, conn->master); + } else { + conn->request_handler = + auth_request_handler_create(conn->auth, + conn->connect_uid, pid, + auth_callback, conn, + NULL, NULL); + } conn->pid = pid; return TRUE; } -static int -auth_client_input_auth(struct auth_client_connection *conn, const char *args) +static int auth_client_output(void *context) { - struct mech_module *mech; - struct auth_request *request; - const char *const *list, *name, *arg, *initial_resp; - const void *initial_resp_data; - size_t initial_resp_len; - unsigned int id; - buffer_t *buf; - int valid_client_cert; - - if (conn->pid == 0) { - i_error("BUG: Authentication client %u didn't send handshake", - conn->pid); - return FALSE; - } + struct auth_client_connection *conn = context; - /* <id> <mechanism> [...] */ - list = t_strsplit(args, "\t"); - if (list[0] == NULL || list[1] == NULL) { - i_error("BUG: Authentication client %u " - "sent broken AUTH request", conn->pid); - return FALSE; - } - - id = (unsigned int)strtoul(list[0], NULL, 10); - - mech = mech_module_find(list[1]); - if (mech == NULL) { - /* unsupported mechanism */ - i_error("BUG: Authentication client %u requested unsupported " - "authentication mechanism %s", conn->pid, - str_sanitize(list[1], MAX_MECH_NAME_LEN)); - return FALSE; + if (o_stream_flush(conn->output) < 0) { + auth_client_connection_destroy(conn); + return 1; } - request = auth_request_new(conn->auth, mech, auth_callback); - hash_insert(conn->auth_requests, POINTER_CAST(id), request); - - request->conn = conn; - request->id = id; - - /* parse optional parameters */ - initial_resp = NULL; - valid_client_cert = FALSE; - for (list += 2; *list != NULL; list++) { - arg = strchr(*list, '='); - if (arg == NULL) { - name = *list; - arg = ""; - } else { - name = t_strdup_until(*list, arg); - arg++; - } - - if (strcmp(name, "lip") == 0) - (void)net_addr2ip(arg, &request->local_ip); - else if (strcmp(name, "rip") == 0) - (void)net_addr2ip(arg, &request->remote_ip); - else if (strcmp(name, "service") == 0) - request->service = p_strdup(request->pool, arg); - else if (strcmp(name, "resp") == 0) - initial_resp = arg; - else if (strcmp(name, "valid-client-cert") == 0) - valid_client_cert = TRUE; + if (o_stream_get_buffer_used_size(conn->output) <= + OUTBUF_THROTTLE_SIZE/3 && conn->io == NULL) { + /* allow input again */ + conn->io = io_add(conn->fd, IO_READ, auth_client_input, conn); } - - if (request->service == NULL) { - i_error("BUG: Authentication client %u " - "didn't specify service in request", conn->pid); - auth_request_destroy(request); - return FALSE; - } - - if (request->auth->ssl_require_client_cert && !valid_client_cert) { - /* we fail without valid certificate */ - auth_request_log_info(request, "ssl-cert-check", - "Client didn't present valid SSL certificate"); - auth_request_destroy(request); - auth_client_send(conn, "FAIL\t%u", id); - return TRUE; - } - - if (initial_resp == NULL) { - initial_resp_data = NULL; - initial_resp_len = 0; - } else { - size_t len = strlen(initial_resp); - buf = buffer_create_dynamic(pool_datastack_create(), - MAX_BASE64_DECODED_SIZE(len)); - if (base64_decode(initial_resp, len, NULL, buf) < 0) { - auth_request_log_info(request, mech->mech_name, - "Invalid base64 data in initial response"); - auth_request_destroy(request); - auth_client_send(conn, "FAIL\t%u\t" - "reason=Invalid base64 data in initial " - "response", id); - return TRUE; - } - initial_resp_data = buf->data; - initial_resp_len = buf->used; - } - - /* connection is referenced only until auth_callback is called. */ - conn->refcount++; - auth_request_initial(request, initial_resp_data, initial_resp_len); - return TRUE; + return 1; } static int -auth_client_input_cont(struct auth_client_connection *conn, const char *args) +auth_client_handle_line(struct auth_client_connection *conn, const char *line) { - struct auth_request *request; - const char *data; - size_t data_len; - buffer_t *buf; - unsigned int id; - - data = strchr(args, '\t'); - if (data++ == NULL) { - i_error("BUG: Authentication client %u " - "sent broken CONT request", conn->pid); - return FALSE; + if (strncmp(line, "AUTH\t", 5) == 0) { + return auth_request_handler_auth_begin(conn->request_handler, + line + 5); + } + if (strncmp(line, "CONT\t", 5) == 0) { + return auth_request_handler_auth_continue(conn->request_handler, + line + 5); } - id = (unsigned int)strtoul(args, NULL, 10); - - request = hash_lookup(conn->auth_requests, POINTER_CAST(id)); - if (request == NULL) { - /* timeouted */ - auth_client_send(conn, "FAIL\t%u\treason=Timeouted", id); - return TRUE; - } - - if (!request->accept_input) { - auth_client_send(conn, "FAIL\t%u" - "\treason=Unexpected continuation", id); - auth_request_destroy(request); - return TRUE; - } - request->accept_input = FALSE; - - data_len = strlen(data); - buf = buffer_create_dynamic(pool_datastack_create(), - MAX_BASE64_DECODED_SIZE(data_len)); - if (base64_decode(data, data_len, NULL, buf) < 0) { - auth_request_log_info(request, request->mech->mech_name, - "Invalid base64 data in continued response"); - auth_client_send(conn, "FAIL\t%u\treason=Invalid base64 data " - "in continued response", id); - auth_request_destroy(request); - return TRUE; - } - - conn->refcount++; - auth_request_continue(request, buf->data, buf->used); + /* ignore unknown command */ return TRUE; } @@ -366,46 +162,48 @@ /* buffer full */ i_error("BUG: Auth client %u sent us more than %d bytes", conn->pid, (int)AUTH_CLIENT_MAX_LINE_LENGTH); - auth_client_connection_destroy_wait(conn); + auth_client_connection_destroy(conn); return; } - if (!conn->version_received) { + while (conn->request_handler == NULL) { + /* still handshaking */ line = i_stream_next_line(conn->input); if (line == NULL) return; - /* make sure the major version matches */ - if (strncmp(line, "VERSION\t", 8) != 0 || - atoi(t_strcut(line + 8, '\t')) != - AUTH_CLIENT_PROTOCOL_MAJOR_VERSION) { - i_error("Authentication client %u " - "not compatible with this server " - "(mixed old and new binaries?)", conn->pid); - auth_client_connection_destroy_wait(conn); - return; + if (!conn->version_received) { + /* make sure the major version matches */ + if (strncmp(line, "VERSION\t", 8) != 0 || + atoi(t_strcut(line + 8, '\t')) != + AUTH_CLIENT_PROTOCOL_MAJOR_VERSION) { + i_error("Authentication client " + "not compatible with this server " + "(mixed old and new binaries?)"); + auth_client_connection_destroy(conn); + return; + } + conn->version_received = TRUE; + continue; } - conn->version_received = TRUE; + + if (strncmp(line, "CPID\t", 5) == 0) { + if (!auth_client_input_cpid(conn, line + 5)) { + auth_client_connection_destroy(conn); + return; + } + } } - conn->refcount++; + conn->refcount++; while ((line = i_stream_next_line(conn->input)) != NULL) { t_push(); - if (strncmp(line, "AUTH\t", 5) == 0) - ret = auth_client_input_auth(conn, line + 5); - else if (strncmp(line, "CONT\t", 5) == 0) - ret = auth_client_input_cont(conn, line + 5); - else if (strncmp(line, "CPID\t", 5) == 0) - ret = auth_client_input_cpid(conn, line + 5); - else { - /* ignore unknown command */ - ret = TRUE; - } + ret = auth_client_handle_line(conn, line); safe_memset(line, 0, strlen(line)); t_pop(); if (!ret) { - auth_client_connection_destroy_wait(conn); + auth_client_connection_destroy(conn); break; } } @@ -420,27 +218,21 @@ struct const_iovec iov[2]; string_t *str; - pool_t pool; - - pool = pool_alloconly_create("Auth client", 4096); - conn = p_new(pool, struct auth_client_connection, 1); - conn->pool = pool; + conn = i_new(struct auth_client_connection, 1); conn->auth = master->auth; conn->master = master; conn->refcount = 1; conn->connect_uid = ++connect_uid_counter; conn->fd = fd; - conn->input = i_stream_create_file(fd, default_pool, - AUTH_CLIENT_MAX_LINE_LENGTH, - FALSE); - conn->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE, - FALSE); + conn->input = + i_stream_create_file(fd, default_pool, + AUTH_CLIENT_MAX_LINE_LENGTH, FALSE); + conn->output = + o_stream_create_file(fd, default_pool, (size_t)-1, FALSE); + o_stream_set_flush_callback(conn->output, auth_client_output, conn); 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; @@ -488,86 +280,46 @@ net_disconnect(conn->fd); conn->fd = -1; + if (conn->request_handler != NULL) + auth_request_handler_unref(conn->request_handler); + conn->master = NULL; auth_client_connection_unref(conn); } -static void -auth_client_connection_destroy_wait(struct auth_client_connection *conn) -{ - conn->delayed_destroy = TRUE; - - if (conn->io != NULL) { - io_remove(conn->io); - conn->io = NULL; - } -} - static void auth_client_connection_unref(struct auth_client_connection *conn) { - struct hash_iterate_context *iter; - void *key, *value; - if (--conn->refcount > 0) return; - iter = hash_iterate_init(conn->auth_requests); - while (hash_iterate(iter, &key, &value)) { - struct auth_request *auth_request = value; - - auth_request->conn = NULL; - auth_request_unref(auth_request); - } - hash_iterate_deinit(iter); - 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_client_connection_check_timeouts(struct auth_client_connection *conn) +struct auth_client_connection * +auth_client_connection_lookup(struct auth_master_connection *master, + unsigned int pid) { - struct hash_iterate_context *iter; - void *key, *value; - unsigned int secs; - int destroy = FALSE; + struct auth_client_connection *conn; - if (conn->delayed_destroy) { - auth_client_connection_destroy(conn); - return; + for (conn = master->clients; conn != NULL; conn = conn->next) { + if (conn->pid == pid) + return conn; } - iter = hash_iterate_init(conn->auth_requests); - while (hash_iterate(iter, &key, &value)) { - struct auth_request *auth_request = value; - - if (auth_request->created + AUTH_REQUEST_TIMEOUT < ioloop_time) { - secs = (unsigned int) (ioloop_time - - auth_request->created); - i_warning("Login process has too old (%us) requests, " - "killing it.", secs); - - destroy = TRUE; - break; - } - } - hash_iterate_deinit(iter); - - if (destroy) - auth_client_connection_destroy(conn); + return NULL; } static void request_timeout(void *context __attr_unused__) { struct auth_master_connection *master = context; - struct auth_client_connection *conn, *next; + struct auth_client_connection *conn; - for (conn = master->clients; conn != NULL; conn = next) { - next = conn->next; - auth_client_connection_check_timeouts(conn); + for (conn = master->clients; conn != NULL; conn = conn->next) { + if (conn->request_handler == NULL) + continue; + auth_request_handler_check_timeouts(conn->request_handler); } }
--- a/src/auth/auth-client-connection.h Sun Jan 09 02:48:02 2005 +0200 +++ b/src/auth/auth-client-connection.h Sun Jan 09 02:49:18 2005 +0200 @@ -13,14 +13,11 @@ struct istream *input; struct ostream *output; - pool_t pool; - struct hash_table *auth_requests; - unsigned int pid; unsigned int connect_uid; + struct auth_request_handler *request_handler; unsigned int version_received:1; - unsigned int delayed_destroy:1; }; struct auth_client_connection *
--- a/src/auth/auth-master-connection.c Sun Jan 09 02:48:02 2005 +0200 +++ b/src/auth/auth-master-connection.c Sun Jan 09 02:49:18 2005 +0200 @@ -9,7 +9,7 @@ #include "ostream.h" #include "network.h" #include "userdb.h" -#include "auth-request.h" +#include "auth-request-handler.h" #include "auth-master-interface.h" #include "auth-client-connection.h" #include "auth-master-connection.h" @@ -38,81 +38,23 @@ static void auth_master_connection_close(struct auth_master_connection *conn); static int auth_master_connection_unref(struct auth_master_connection *conn); -static void master_send(struct auth_master_connection *conn, - const char *fmt, ...) __attr_format__(2, 3); -static void master_send(struct auth_master_connection *conn, - const char *fmt, ...) +void auth_master_request_callback(const char *reply, void *context) { - va_list args; - string_t *str; - - t_push(); - va_start(args, fmt); - str = t_str_new(256); - str_vprintfa(str, fmt, args); - str_append_c(str, '\n'); - (void)o_stream_send(conn->output, str_data(str), str_len(str)); - va_end(args); - t_pop(); -} - -static void append_user_reply(string_t *str, const struct user_data *user) -{ - const char *p; - - str_printfa(str, "%s\tuid=%s\tgid=%s", user->virtual_user, - dec2str(user->uid), dec2str(user->gid)); - - if (user->system_user != NULL) - str_printfa(str, "\tsystem_user=%s", user->system_user); - if (user->mail != NULL) - str_printfa(str, "\tmail=%s", user->mail); + struct auth_master_connection *conn = context; + struct const_iovec iov[2]; - p = user->home != NULL ? strstr(user->home, "/./") : NULL; - if (p == NULL) { - if (user->home != NULL) - str_printfa(str, "\thome=%s", user->home); - } else { - /* wu-ftpd like <chroot>/./<home> */ - str_printfa(str, "\thome=%s\tchroot=%s", - p + 3, t_strdup_until(user->home, p)); - } -} - -static void userdb_callback(const struct user_data *user, void *context) -{ - struct master_userdb_request *master_request = context; - string_t *str; + iov[0].iov_base = reply; + iov[0].iov_len = strlen(reply); + iov[1].iov_base = "\n"; + iov[1].iov_len = 1; - if (user != NULL) { - auth_request_log_debug(master_request->auth_request, "userdb", - "uid=%s gid=%s home=%s mail=%s", - dec2str(user->uid), dec2str(user->gid), - user->home != NULL ? user->home : "", - user->mail != NULL ? user->mail : ""); - } - - if (auth_master_connection_unref(master_request->conn)) { - if (user == NULL) { - master_send(master_request->conn, "NOTFOUND\t%u", - master_request->id); - } else { - str = t_str_new(256); - str_printfa(str, "USER\t%u\t", master_request->id); - append_user_reply(str, user); - master_send(master_request->conn, "%s", str_c(str)); - } - } - auth_request_destroy(master_request->auth_request); - i_free(master_request); + (void)o_stream_sendv(conn->output, iov, 2); } static int master_input_request(struct auth_master_connection *conn, const char *args) { struct auth_client_connection *client_conn; - struct master_userdb_request *master_request; - struct auth_request *request; const char *const *list; unsigned int id, client_pid, client_id; @@ -128,27 +70,14 @@ client_id = (unsigned int)strtoul(list[2], NULL, 10); client_conn = auth_client_connection_lookup(conn, client_pid); - request = client_conn == NULL ? NULL : - hash_lookup(client_conn->auth_requests, - POINTER_CAST(client_id)); - - if (request == NULL) { - i_error("Master request %u.%u not found", - client_pid, client_id); - master_send(conn, "NOTFOUND\t%u", id); - } else if (!request->successful) { - i_error("Master requested unfinished authentication request " - "%u.%u", client_pid, client_id); - master_send(conn, "NOTFOUND\t%u", id); + if (client_conn == NULL) { + i_error("Master requested auth for nonexisting client %u", + client_pid); + (void)o_stream_send_str(conn->output, + t_strdup_printf("NOTFOUND\t%u\n", id)); } else { - master_request = i_new(struct master_userdb_request, 1); - master_request->conn = conn; - master_request->id = id; - master_request->auth_request = request; - - conn->refcount++; - auth_request_lookup_user(request, userdb_callback, - master_request); + auth_request_handler_master_request( + client_conn->request_handler, id, client_id); } return TRUE; } @@ -255,14 +184,14 @@ } struct auth_master_connection * -auth_master_connection_create(struct auth *auth, int fd, unsigned int pid) +auth_master_connection_create(struct auth *auth, int fd) { struct auth_master_connection *conn; conn = i_new(struct auth_master_connection, 1); conn->auth = auth; conn->refcount = 1; - conn->pid = pid; + conn->pid = (unsigned int)getpid(); conn->fd = fd; conn->listeners_buf = buffer_create_dynamic(default_pool, 64); if (fd != -1) @@ -272,11 +201,15 @@ void auth_master_connection_send_handshake(struct auth_master_connection *conn) { - if (conn->output != NULL) { - master_send(conn, "VERSION\t%u\t%u\nSPID\t%u\n", - AUTH_MASTER_PROTOCOL_MAJOR_VERSION, - AUTH_MASTER_PROTOCOL_MINOR_VERSION, conn->pid); - } + const char *line; + + if (conn->output == NULL) + return; + + line = t_strdup_printf("VERSION\t%u\t%u\nSPID\t%u\n", + AUTH_MASTER_PROTOCOL_MAJOR_VERSION, + AUTH_MASTER_PROTOCOL_MINOR_VERSION, conn->pid); + (void)o_stream_send_str(conn->output, line); } static void auth_master_connection_close(struct auth_master_connection *conn)
--- a/src/auth/auth-master-connection.h Sun Jan 09 02:48:02 2005 +0200 +++ b/src/auth/auth-master-connection.h Sun Jan 09 02:49:18 2005 +0200 @@ -23,10 +23,12 @@ #define AUTH_MASTER_IS_DUMMY(master) (master->fd == -1) struct auth_master_connection * -auth_master_connection_create(struct auth *auth, int fd, unsigned int pid); +auth_master_connection_create(struct auth *auth, int fd); void auth_master_connection_send_handshake(struct auth_master_connection *conn); void auth_master_connection_destroy(struct auth_master_connection *conn); +void auth_master_request_callback(const char *reply, void *context); + void auth_master_connection_add_listener(struct auth_master_connection *conn, int fd, const char *path, int client);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/auth/auth-request-handler.c Sun Jan 09 02:49:18 2005 +0200 @@ -0,0 +1,486 @@ +/* Copyright (C) 2005 Timo Sirainen */ + +#include "common.h" +#include "ioloop.h" +#include "buffer.h" +#include "base64.h" +#include "hash.h" +#include "str.h" +#include "str-sanitize.h" +#include "auth-request.h" +#include "auth-request-handler.h" + +#include <stdlib.h> + +/* Used only for string sanitization. */ +#define MAX_MECH_NAME_LEN 64 + +struct auth_request_handler { + int refcount; + pool_t pool; + struct hash_table *requests; + + struct auth *auth; + unsigned int connect_uid, client_pid; + + auth_request_callback_t *callback; + void *context; + + auth_request_callback_t *master_callback; + void *master_context; +}; + +static buffer_t *auth_failures_buf; +static struct timeout *to_auth_failures; + +struct auth_request_handler * +auth_request_handler_create(struct auth *auth, + unsigned int connect_uid, unsigned int client_pid, + auth_request_callback_t *callback, void *context, + auth_request_callback_t *master_callback, + void *master_context) +{ + struct auth_request_handler *handler; + pool_t pool; + + pool = pool_alloconly_create("auth request handler", 4096); + + handler = p_new(pool, struct auth_request_handler, 1); + handler->refcount = 1; + handler->pool = pool; + handler->requests = hash_create(default_pool, pool, 0, NULL, NULL); + handler->auth = auth; + handler->connect_uid = connect_uid; + handler->client_pid = client_pid; + handler->callback = callback; + handler->context = context; + handler->master_callback = master_callback; + handler->master_context = master_context; + return handler; +} + +void auth_request_handler_unref(struct auth_request_handler *handler) +{ + struct hash_iterate_context *iter; + void *key, *value; + + i_assert(handler->refcount > 0); + if (--handler->refcount > 0) + return; + + iter = hash_iterate_init(handler->requests); + while (hash_iterate(iter, &key, &value)) + auth_request_unref(value); + hash_iterate_deinit(iter); + + /* notify parent that we're done with all requests */ + handler->callback(NULL, handler->context); + + hash_destroy(handler->requests); + pool_unref(handler->pool); +} + +void auth_request_handler_check_timeouts(struct auth_request_handler *handler) +{ + struct hash_iterate_context *iter; + void *key, *value; + + iter = hash_iterate_init(handler->requests); + while (hash_iterate(iter, &key, &value)) { + struct auth_request *auth_request = value; + + if (auth_request->created + AUTH_REQUEST_TIMEOUT < ioloop_time) + hash_remove(handler->requests, key); + } + hash_iterate_deinit(iter); +} + +static void auth_request_handler_remove(struct auth_request_handler *handler, + struct auth_request *request) +{ + hash_remove(handler->requests, POINTER_CAST(request->id)); + auth_request_unref(request); +} + +static const char *get_client_extra_fields(struct auth_request *request) +{ + const char **fields; + unsigned int src, dest; + + if (request->extra_fields == NULL) + return NULL; + + /* we only wish to remove all fields prefixed with "userdb_" */ + if (strstr(request->extra_fields, "userdb_") == NULL) + return request->extra_fields; + + fields = t_strsplit(request->extra_fields, "\t"); + for (src = dest = 0; fields[src] != NULL; src++) { + if (strncmp(fields[src], "userdb_", 7) == 0) + fields[dest++] = fields[src]; + } + fields[dest] = NULL; + return t_strarray_join(fields, "\t"); +} + +static void auth_callback(struct auth_request *request, + enum auth_client_result result, + const void *reply, size_t reply_size) +{ + struct auth_request_handler *handler = request->context; + string_t *str = NULL; + const char *fields; + + t_push(); + + switch (result) { + case AUTH_CLIENT_RESULT_CONTINUE: + str = t_str_new(32 + MAX_BASE64_ENCODED_SIZE(reply_size)); + str_printfa(str, "CONT\t%u\t", request->id); + base64_encode(reply, reply_size, str); + request->accept_input = TRUE; + handler->callback(str_c(str), handler->context); + break; + case AUTH_CLIENT_RESULT_SUCCESS: + str = t_str_new(128 + MAX_BASE64_ENCODED_SIZE(reply_size)); + str_printfa(str, "OK\t%u\tuser=%s", request->id, request->user); + if (reply_size > 0) { + str_append(str, "\tresp="); + base64_encode(reply, reply_size, str); + } + fields = get_client_extra_fields(request); + if (fields != NULL) { + str_append_c(str, '\t'); + str_append(str, fields); + } + + if (request->no_login || handler->master_callback == NULL) { + /* this request doesn't have to wait for master + process to pick it up. delete it */ + auth_request_handler_remove(handler, request); + } + handler->callback(str_c(str), handler->context); + break; + case AUTH_CLIENT_RESULT_FAILURE: + str = t_str_new(128); + str_printfa(str, "FAIL\t%u", request->id); + if (request->user != NULL) + str_printfa(str, "\tuser=%s", request->user); + if (request->internal_failure) + str_append(str, "\ttemp"); + fields = get_client_extra_fields(request); + if (fields != NULL) { + str_append_c(str, '\t'); + str_append(str, fields); + } + + if (request->delayed_failure) { + /* we came here from flush_failures() */ + handler->callback(str_c(str), handler->context); + break; + } + + /* remove the request from requests-list */ + auth_request_ref(request); + auth_request_handler_remove(handler, request); + + if (request->no_failure_delay) { + /* passdb specifically requested not to delay the + reply. */ + handler->callback(str_c(str), handler->context); + } else { + /* failure. don't announce it immediately to avoid + a) timing attacks, b) flooding */ + request->delayed_failure = TRUE; + handler->refcount++; + buffer_append(auth_failures_buf, + &request, sizeof(request)); + } + break; + } + /* NOTE: request may be destroyed now */ + + auth_request_handler_unref(handler); + + t_pop(); +} + +static void auth_request_handler_auth_fail(struct auth_request_handler *handler, + struct auth_request *request, + const char *reason) +{ + const char *reply; + + auth_request_log_info(request, request->mech->mech_name, "%s", reason); + + reply = t_strdup_printf("FAIL\t%u\treason=%s", request->id, reason); + handler->callback(reply, handler->context); + auth_request_handler_remove(handler, request); +} + +int auth_request_handler_auth_begin(struct auth_request_handler *handler, + const char *args) +{ + struct mech_module *mech; + struct auth_request *request; + const char *const *list, *name, *arg, *initial_resp; + const void *initial_resp_data; + size_t initial_resp_len; + unsigned int id; + buffer_t *buf; + int valid_client_cert; + + /* <id> <mechanism> [...] */ + list = t_strsplit(args, "\t"); + if (list[0] == NULL || list[1] == NULL) { + i_error("BUG: Authentication client %u " + "sent broken AUTH request", handler->client_pid); + return FALSE; + } + + id = (unsigned int)strtoul(list[0], NULL, 10); + + mech = mech_module_find(list[1]); + if (mech == NULL) { + /* unsupported mechanism */ + i_error("BUG: Authentication client %u requested unsupported " + "authentication mechanism %s", handler->client_pid, + str_sanitize(list[1], MAX_MECH_NAME_LEN)); + return FALSE; + } + + request = auth_request_new(handler->auth, mech, auth_callback, handler); + request->connect_uid = handler->connect_uid; + request->client_pid = handler->client_pid; + request->id = id; + + /* parse optional parameters */ + initial_resp = NULL; + valid_client_cert = FALSE; + for (list += 2; *list != NULL; list++) { + arg = strchr(*list, '='); + if (arg == NULL) { + name = *list; + arg = ""; + } else { + name = t_strdup_until(*list, arg); + arg++; + } + + if (strcmp(name, "lip") == 0) + (void)net_addr2ip(arg, &request->local_ip); + else if (strcmp(name, "rip") == 0) + (void)net_addr2ip(arg, &request->remote_ip); + else if (strcmp(name, "service") == 0) + request->service = p_strdup(request->pool, arg); + else if (strcmp(name, "resp") == 0) + initial_resp = arg; + else if (strcmp(name, "valid-client-cert") == 0) + valid_client_cert = TRUE; + } + + if (request->service == NULL) { + i_error("BUG: Authentication client %u " + "didn't specify service in request", + handler->client_pid); + auth_request_unref(request); + return FALSE; + } + + hash_insert(handler->requests, POINTER_CAST(id), request); + + if (request->auth->ssl_require_client_cert && !valid_client_cert) { + /* we fail without valid certificate */ + auth_request_handler_auth_fail(handler, request, + "Client didn't present valid SSL certificate"); + return TRUE; + } + + if (initial_resp == NULL) { + initial_resp_data = NULL; + initial_resp_len = 0; + } else { + size_t len = strlen(initial_resp); + buf = buffer_create_dynamic(pool_datastack_create(), + MAX_BASE64_DECODED_SIZE(len)); + if (base64_decode(initial_resp, len, NULL, buf) < 0) { + auth_request_handler_auth_fail(handler, request, + "Invalid base64 data in initial response"); + return TRUE; + } + initial_resp_data = buf->data; + initial_resp_len = buf->used; + } + + /* handler is referenced until auth_callback is called. */ + handler->refcount++; + auth_request_initial(request, initial_resp_data, initial_resp_len); + return TRUE; +} + +int auth_request_handler_auth_continue(struct auth_request_handler *handler, + const char *args) +{ + struct auth_request *request; + const char *data; + size_t data_len; + buffer_t *buf; + unsigned int id; + + data = strchr(args, '\t'); + if (data++ == NULL) { + i_error("BUG: Authentication client sent broken CONT request"); + return FALSE; + } + + id = (unsigned int)strtoul(args, NULL, 10); + + request = hash_lookup(handler->requests, POINTER_CAST(id)); + if (request == NULL) { + data = t_strdup_printf("FAIL\t%u\treason=Timeouted", id); + handler->callback(data, handler->context); + return TRUE; + } + + /* accept input only once after mechanism has sent a CONT reply */ + if (!request->accept_input) { + auth_request_handler_auth_fail(handler, request, + "Unexpected continuation"); + return TRUE; + } + request->accept_input = FALSE; + + data_len = strlen(data); + buf = buffer_create_dynamic(pool_datastack_create(), + MAX_BASE64_DECODED_SIZE(data_len)); + if (base64_decode(data, data_len, NULL, buf) < 0) { + auth_request_handler_auth_fail(handler, request, + "Invalid base64 data in continued response"); + return TRUE; + } + + /* handler is referenced until auth_callback is called. */ + handler->refcount++; + auth_request_continue(request, buf->data, buf->used); + return TRUE; +} + +static void append_user_reply(string_t *str, const struct user_data *user) +{ + const char *p; + + str_printfa(str, "%s\tuid=%s\tgid=%s", user->virtual_user, + dec2str(user->uid), dec2str(user->gid)); + + if (user->system_user != NULL) + str_printfa(str, "\tsystem_user=%s", user->system_user); + if (user->mail != NULL) + str_printfa(str, "\tmail=%s", user->mail); + + p = user->home != NULL ? strstr(user->home, "/./") : NULL; + if (p == NULL) { + if (user->home != NULL) + str_printfa(str, "\thome=%s", user->home); + } else { + /* wu-ftpd like <chroot>/./<home> */ + str_printfa(str, "\thome=%s\tchroot=%s", + p + 3, t_strdup_until(user->home, p)); + } +} + +static void userdb_callback(const struct user_data *user, void *context) +{ + struct auth_request *request = context; + struct auth_request_handler *handler = request->context; + string_t *reply; + + if (user != NULL) { + auth_request_log_debug(request, "userdb", + "uid=%s gid=%s home=%s mail=%s", + dec2str(user->uid), dec2str(user->gid), + user->home != NULL ? user->home : "", + user->mail != NULL ? user->mail : ""); + } + + reply = t_str_new(256); + if (user == NULL) + str_printfa(reply, "NOTFOUND\t%u", request->id); + else { + str_printfa(reply, "USER\t%u\t", request->id); + append_user_reply(reply, user); + } + handler->master_callback(str_c(reply), handler->master_context); + + auth_request_unref(request); + auth_request_handler_unref(handler); +} + +void auth_request_handler_master_request(struct auth_request_handler *handler, + unsigned int id, + unsigned int client_id) +{ + struct auth_request *request; + const char *reply; + + request = hash_lookup(handler->requests, POINTER_CAST(client_id)); + if (request == NULL) { + i_error("Master request %u.%u not found", + handler->client_pid, client_id); + reply = t_strdup_printf("NOTFOUND\t%u", id); + handler->master_callback(reply, handler->master_context); + return; + } + + auth_request_ref(request); + auth_request_handler_remove(handler, request); + + if (!request->successful) { + i_error("Master requested unfinished authentication request " + "%u.%u", handler->client_pid, client_id); + reply = t_strdup_printf("NOTFOUND\t%u", id); + handler->master_callback(reply, handler->master_context); + } else { + /* the request isn't being referenced anywhere anymore, + so we can do a bit of kludging.. replace the request's + old client_id with master's id. */ + request->id = id; + request->context = handler; + + /* handler is referenced until userdb_callback is called. */ + handler->refcount++; + auth_request_lookup_user(request, userdb_callback, request); + } +} + +void auth_request_handlers_flush_failures(void) +{ + struct auth_request **auth_request; + size_t i, size; + + auth_request = buffer_get_modifyable_data(auth_failures_buf, &size); + size /= sizeof(*auth_request); + + for (i = 0; i < size; i++) { + auth_request[i]->callback(auth_request[i], + AUTH_CLIENT_RESULT_FAILURE, NULL, 0); + auth_request_unref(auth_request[i]); + } + buffer_set_used_size(auth_failures_buf, 0); +} + +static void auth_failure_timeout(void *context __attr_unused__) +{ + auth_request_handlers_flush_failures(); +} + +void auth_request_handlers_init(void) +{ + auth_failures_buf = buffer_create_dynamic(default_pool, 1024); + to_auth_failures = timeout_add(2000, auth_failure_timeout, NULL); +} + +void auth_request_handlers_deinit(void) +{ + buffer_free(auth_failures_buf); + timeout_remove(to_auth_failures); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/auth/auth-request-handler.h Sun Jan 09 02:49:18 2005 +0200 @@ -0,0 +1,29 @@ +#ifndef __AUTH_REQUEST_HANDLER_H +#define __AUTH_REQUEST_HANDLER_H + +typedef void auth_request_callback_t(const char *reply, void *context); + +struct auth_request_handler * +auth_request_handler_create(struct auth *auth, + unsigned int connect_uid, unsigned int client_pid, + auth_request_callback_t *callback, void *context, + auth_request_callback_t *master_callback, + void *master_context); +void auth_request_handler_unref(struct auth_request_handler *handler); + +void auth_request_handler_check_timeouts(struct auth_request_handler *handler); + +int auth_request_handler_auth_begin(struct auth_request_handler *handler, + const char *args); +int auth_request_handler_auth_continue(struct auth_request_handler *handler, + const char *args); +void auth_request_handler_master_request(struct auth_request_handler *handler, + unsigned int id, + unsigned int client_id); + +void auth_request_handlers_flush_failures(void); + +void auth_request_handlers_init(void); +void auth_request_handlers_deinit(void); + +#endif
--- a/src/auth/auth-request.c Sun Jan 09 02:48:02 2005 +0200 +++ b/src/auth/auth-request.c Sun Jan 09 02:49:18 2005 +0200 @@ -20,81 +20,41 @@ char *user_password, *password; }; -static buffer_t *auth_failures_buf; -static struct timeout *to_auth_failures; - struct auth_request * auth_request_new(struct auth *auth, struct mech_module *mech, - mech_callback_t *callback) + mech_callback_t *callback, void *context) { struct auth_request *request; request = mech->auth_new(); request->refcount = 1; + request->created = ioloop_time; + request->auth = auth; request->mech = mech; request->callback = callback; - request->created = ioloop_time; + request->context = context; return request; } -void auth_request_destroy(struct auth_request *request) -{ - i_assert(request->refcount > 0); - - if (request->destroyed) - return; - request->destroyed = TRUE; - - if (request->conn != NULL) { - hash_remove(request->conn->auth_requests, - POINTER_CAST(request->id)); - } - auth_request_unref(request); -} - void auth_request_success(struct auth_request *request, const void *data, size_t data_size) { - request->successful = TRUE; - if (request->conn != NULL) { - request->callback(request, AUTH_CLIENT_RESULT_SUCCESS, - data, data_size); - } + i_assert(!request->finished); + request->finished = TRUE; - if (request->no_login || request->conn == NULL || - AUTH_MASTER_IS_DUMMY(request->conn->master)) { - /* we don't have master process, the request is no longer - needed */ - auth_request_destroy(request); - } + request->successful = TRUE; + request->callback(request, AUTH_CLIENT_RESULT_SUCCESS, + data, data_size); } void auth_request_fail(struct auth_request *request) { - if (request->no_failure_delay) { - /* passdb specifically requested to to delay the reply. */ - request->callback(request, AUTH_CLIENT_RESULT_FAILURE, NULL, 0); - auth_request_destroy(request); - return; - } + i_assert(!request->finished); + request->finished = TRUE; - /* failure. don't announce it immediately to avoid - a) timing attacks, b) flooding */ - if (auth_failures_buf->used > 0) { - const struct auth_request *const *requests; - - requests = auth_failures_buf->data; - requests += auth_failures_buf->used/sizeof(*requests)-1; - i_assert(*requests != request); - } - - buffer_append(auth_failures_buf, &request, sizeof(request)); - - /* make sure the request isn't found anymore */ - auth_request_ref(request); - auth_request_destroy(request); + request->callback(request, AUTH_CLIENT_RESULT_FAILURE, NULL, 0); } void auth_request_internal_failure(struct auth_request *request) @@ -320,7 +280,7 @@ tab[5].value = net_ip2addr(&auth_request->local_ip); if (auth_request->remote_ip.family != 0) tab[6].value = net_ip2addr(&auth_request->remote_ip); - tab[7].value = dec2str(auth_request->conn->pid); + tab[7].value = dec2str(auth_request->client_pid); return tab; } @@ -397,39 +357,3 @@ t_pop(); va_end(va); } - -void auth_failure_buf_flush(void) -{ - struct auth_request **auth_request; - size_t i, size; - - auth_request = buffer_get_modifyable_data(auth_failures_buf, &size); - size /= sizeof(*auth_request); - - for (i = 0; i < size; i++) { - if (auth_request[i]->conn != NULL) { - auth_request[i]->callback(auth_request[i], - AUTH_CLIENT_RESULT_FAILURE, - NULL, 0); - } - auth_request_destroy(auth_request[i]); - } - buffer_set_used_size(auth_failures_buf, 0); -} - -static void auth_failure_timeout(void *context __attr_unused__) -{ - auth_failure_buf_flush(); -} - -void auth_requests_init(void) -{ - auth_failures_buf = buffer_create_dynamic(default_pool, 1024); - to_auth_failures = timeout_add(2000, auth_failure_timeout, NULL); -} - -void auth_requests_deinit(void) -{ - buffer_free(auth_failures_buf); - timeout_remove(to_auth_failures); -}
--- a/src/auth/auth-request.h Sun Jan 09 02:48:02 2005 +0200 +++ b/src/auth/auth-request.h Sun Jan 09 02:49:18 2005 +0200 @@ -17,37 +17,40 @@ struct mech_module *mech; struct auth *auth; - struct auth_client_connection *conn; + unsigned int connect_uid; + unsigned int client_pid; unsigned int id; time_t created; const char *service; struct ip_addr local_ip, remote_ip; + mech_callback_t *callback; + void *context; unsigned int successful:1; unsigned int internal_failure:1; + unsigned int finished:1; + unsigned int delayed_failure:1; unsigned int accept_input:1; unsigned int no_failure_delay:1; unsigned int no_login:1; unsigned int proxy:1; - unsigned int destroyed:1; /* ... mechanism specific data ... */ }; +struct auth_request * +auth_request_new(struct auth *auth, struct mech_module *mech, + mech_callback_t *callback, void *context); +void auth_request_ref(struct auth_request *request); +int auth_request_unref(struct auth_request *request); + void auth_request_success(struct auth_request *request, const void *data, size_t data_size); void auth_request_fail(struct auth_request *request); void auth_request_internal_failure(struct auth_request *request); -struct auth_request * -auth_request_new(struct auth *auth, struct mech_module *mech, - mech_callback_t *callback); -void auth_request_destroy(struct auth_request *request); -void auth_request_ref(struct auth_request *request); -int auth_request_unref(struct auth_request *request); - void auth_request_initial(struct auth_request *request, const unsigned char *data, size_t data_size); void auth_request_continue(struct auth_request *request, @@ -86,9 +89,4 @@ const char *subsystem, const char *format, ...) __attr_format__(3, 4); -void auth_failure_buf_flush(void); - -void auth_requests_init(void); -void auth_requests_deinit(void); - #endif
--- a/src/auth/main.c Sun Jan 09 02:48:02 2005 +0200 +++ b/src/auth/main.c Sun Jan 09 02:49:18 2005 +0200 @@ -11,7 +11,7 @@ #include "password-scheme.h" #include "mech.h" #include "auth.h" -#include "auth-request.h" +#include "auth-request-handler.h" #include "auth-master-connection.h" #include "auth-client-connection.h" @@ -153,7 +153,7 @@ str = t_strdup_printf("AUTH_%u_MASTER", i); master_fd = create_unix_listener(str); - master = auth_master_connection_create(auth, -1, getpid()); + master = auth_master_connection_create(auth, -1); if (master_fd != -1) { auth_master_connection_add_listener(master, master_fd, master_path, FALSE); @@ -191,19 +191,18 @@ { struct auth_master_connection *master, **master_p; size_t i, size; - const char *env; - unsigned int pid; + + process_start_time = ioloop_time; process_start_time = ioloop_time; mech_init(); auth_init(auth); - auth_requests_init(); + auth_request_handlers_init(); lib_init_signals(sig_quit); - env = getenv("AUTH_PROCESS"); - standalone = env == NULL; + standalone = getenv("DOVECOT_MASTER") == NULL; if (standalone) { /* starting standalone */ if (getenv("AUTH_1") == NULL) { @@ -230,12 +229,7 @@ i_fatal("chdir(/) failed: %m"); } } else { - pid = atoi(env); - if (pid == 0) - i_fatal("AUTH_PROCESS can't be 0"); - - master = auth_master_connection_create(auth, MASTER_SOCKET_FD, - pid); + master = auth_master_connection_create(auth, MASTER_SOCKET_FD); auth_master_connection_add_listener(master, LOGIN_LISTEN_FD, NULL, TRUE); auth_client_connections_init(master); @@ -257,7 +251,7 @@ if (lib_signal_kill != 0) i_warning("Killed with signal %d", lib_signal_kill); - auth_failure_buf_flush(); + auth_request_handlers_flush_failures(); master = buffer_get_modifyable_data(masters_buf, &size); size /= sizeof(*master); @@ -265,7 +259,7 @@ auth_master_connection_destroy(master[i]); password_schemes_deinit(); - auth_requests_deinit(); + auth_request_handlers_deinit(); auth_deinit(auth); mech_deinit();
--- a/src/auth/mech-apop.c Sun Jan 09 02:48:02 2005 +0200 +++ b/src/auth/mech-apop.c Sun Jan 09 02:49:18 2005 +0200 @@ -101,7 +101,7 @@ if (sscanf((const char *)data, "<%lx.%lx.%lx.", &pid, &connect_uid, ×tamp) != 3 || - connect_uid != auth_request->conn->connect_uid || + connect_uid != auth_request->connect_uid || pid != (unsigned long)getpid() || (time_t)timestamp < process_start_time) { auth_request_log_info(auth_request, "apop",
--- a/src/master/auth-process.c Sun Jan 09 02:48:02 2005 +0200 +++ b/src/master/auth-process.c Sun Jan 09 02:49:18 2005 +0200 @@ -473,7 +473,7 @@ 0, 0, NULL); /* set other environment */ - env_put(t_strconcat("AUTH_PROCESS=", dec2str(getpid()), NULL)); + env_put("DOVECOT_MASTER=1"); env_put(t_strconcat("MECHANISMS=", group->set->mechanisms, NULL)); env_put(t_strconcat("REALMS=", group->set->realms, NULL)); env_put(t_strconcat("DEFAULT_REALM=", group->set->default_realm, NULL));