auth-process.c revision fe594abcaff07e7f69be1ce3bfcc7a62ff033e74
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include "common.h"
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include "ioloop.h"
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include "env-util.h"
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include "fd-close-on-exec.h"
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include "network.h"
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include "istream.h"
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include "ostream.h"
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include "restrict-access.h"
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include "restrict-process-size.h"
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include "auth-process.h"
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include "log.h"
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include <stdlib.h>
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include <unistd.h>
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include <pwd.h>
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include <syslog.h>
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#include <sys/stat.h>
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen#define MAX_INBUF_SIZE \
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen (sizeof(struct auth_master_reply) + AUTH_MASTER_MAX_REPLY_DATA_SIZE)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstruct auth_process_group {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_process_group *next;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen int listen_fd;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_settings *set;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen unsigned int process_count;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_process *processes;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen};
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainenstruct auth_process {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_process *next;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_process_group *group;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen pid_t pid;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen int fd;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct io *io;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct istream *input;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct ostream *output;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_master_reply auth_reply;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct hash_table *requests;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen unsigned int external:1;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen unsigned int initialized:1;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen unsigned int in_auth_reply:1;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen};
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstatic struct timeout *to;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstatic unsigned int auth_tag;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstatic struct auth_process_group *process_groups;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstatic void auth_process_destroy(struct auth_process *p);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstatic int handle_reply(struct auth_process *process,
030e247340315f4425d297a00b439a4df72bf70cPhil Carmody struct auth_master_reply *reply,
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen const unsigned char *data)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen size_t nul_pos;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen void *context;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen context = hash_lookup(process->requests, POINTER_CAST(reply->tag));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (context == NULL) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_error("Auth process %s sent unrequested reply with tag %u",
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen dec2str(process->pid), reply->tag);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return TRUE;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* make sure the reply looks OK */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (reply->data_size == 0) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen nul_pos = 0;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen data = (const unsigned char *) "";
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen } else {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen nul_pos = reply->data_size-1;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (data[nul_pos] != '\0') {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_error("Auth process %s sent invalid reply",
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen dec2str(process->pid));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return FALSE;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* fix the request so that all the values point to \0 terminated
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen strings */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (reply->system_user_idx >= reply->data_size)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen reply->system_user_idx = nul_pos;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (reply->virtual_user_idx >= reply->data_size)
0b3e92b6043435c5aa9f1cf1d04b632f3e19abd9Phil Carmody reply->virtual_user_idx = nul_pos;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (reply->home_idx >= reply->data_size)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen reply->home_idx = nul_pos;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (reply->chroot_idx >= reply->data_size)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen reply->chroot_idx = nul_pos;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (reply->mail_idx >= reply->data_size)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen reply->mail_idx = nul_pos;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth_master_callback(reply, data, context);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen hash_remove(process->requests, POINTER_CAST(reply->tag));
54e5dadb95d8b7ffce6b5a1f6dbba22044663451Timo Sirainen return TRUE;
54e5dadb95d8b7ffce6b5a1f6dbba22044663451Timo Sirainen}
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenvoid auth_process_request(struct auth_process *process, unsigned int login_pid,
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen unsigned int login_id, void *context)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_master_request req;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen ssize_t ret;
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen req.tag = ++auth_tag;
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen req.id = login_id;
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen req.client_pid = login_pid;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen ret = o_stream_send(process->output, &req, sizeof(req));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if ((size_t)ret != sizeof(req)) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (ret >= 0) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* FIXME: well .. I'm not sure if it'd be better to
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen just block here. I don't think this condition should
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen happen often, so this could mean that the auth
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen process is stuck. Or that the computer is just
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen too heavily loaded. Possibility to block infinitely
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen is annoying though, so for now don't do it. */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_warning("Auth process %s transmit buffer full, "
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen "killing..", dec2str(process->pid));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth_process_destroy(process);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return;
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen }
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen hash_insert(process->requests, POINTER_CAST(req.tag), context);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen}
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstatic void auth_process_input(void *context)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_process *p = context;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen const unsigned char *data;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen size_t size;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen switch (i_stream_read(p->input)) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen case 0:
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen case -1:
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* disconnected */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth_process_destroy(p);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen case -2:
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* buffer full */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_error("BUG: Auth process %s sent us more than %d "
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen "bytes of data", dec2str(p->pid), (int)MAX_INBUF_SIZE);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth_process_destroy(p);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (!p->initialized) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_master_handshake_reply rec;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen data = i_stream_get_data(p->input, &size);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (size < sizeof(rec))
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen memcpy(&rec, data, sizeof(rec));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_stream_skip(p->input, sizeof(rec));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (rec.server_pid == 0) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_fatal("Auth process sent invalid initialization "
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen "notification");
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen p->pid = rec.server_pid;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen p->initialized = TRUE;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen for (;;) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (!p->in_auth_reply) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen data = i_stream_get_data(p->input, &size);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (size < sizeof(p->auth_reply))
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen break;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen p->in_auth_reply = TRUE;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen memcpy(&p->auth_reply, data, sizeof(p->auth_reply));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_stream_skip(p->input, sizeof(p->auth_reply));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen data = i_stream_get_data(p->input, &size);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (size < p->auth_reply.data_size)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen break;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* reply is now read */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (!handle_reply(p, &p->auth_reply, data)) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth_process_destroy(p);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen break;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen p->in_auth_reply = FALSE;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_stream_skip(p->input, p->auth_reply.data_size);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen}
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstatic struct auth_process *
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenauth_process_new(pid_t pid, int fd, struct auth_process_group *group)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_process *p;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (pid != 0)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_AUTH);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen p = i_new(struct auth_process, 1);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen p->group = group;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen p->pid = pid;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen p->fd = fd;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen p->io = io_add(fd, IO_READ, auth_process_input, p);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen p->input = i_stream_create_file(fd, default_pool,
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen MAX_INBUF_SIZE, FALSE);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen p->output = o_stream_create_file(fd, default_pool,
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen sizeof(struct auth_master_request)*100,
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen FALSE);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen p->requests = hash_create(default_pool, default_pool, 0, NULL, NULL);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen p->next = group->processes;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen group->processes = p;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen group->process_count++;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return p;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen}
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstatic void auth_process_destroy(struct auth_process *p)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct hash_iterate_context *iter;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen void *key, *value;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_process **pos;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (!p->initialized && io_loop_is_running(ioloop) && !p->external) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_error("Auth process died too early - shutting down");
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen io_loop_stop(ioloop);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen for (pos = &p->group->processes; *pos != NULL; pos = &(*pos)->next) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (*pos == p) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen *pos = p->next;
f24202d1a342ac63fb8c28e6fa74e16d37f29ca3Timo Sirainen break;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen p->group->process_count--;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
46b823ac3bce2c0f9f0fc73911e48d3a77b04fbeTimo Sirainen iter = hash_iterate_init(p->requests);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen while (hash_iterate(iter, &key, &value))
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth_master_callback(NULL, NULL, value);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen hash_iterate_deinit(iter);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen hash_destroy(p->requests);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_stream_unref(p->input);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen o_stream_unref(p->output);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen io_remove(p->io);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (close(p->fd) < 0)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_error("close(auth) failed: %m");
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_free(p);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen}
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstatic void
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainensocket_settings_env_put(const char *env_base, struct socket_settings *set)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (env_base == NULL)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen env_put(t_strdup_printf("%s_PATH=%s", env_base, set->path));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (set->mode != 0)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen env_put(t_strdup_printf("%s_MODE=%u", env_base, set->mode));
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi if (set->user != NULL)
534e41e436a7546f36f61e0dc49c0c191d850f6bPhil Carmody env_put(t_strdup_printf("%s_USER=%s", env_base, set->user));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (set->group != NULL)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen env_put(t_strdup_printf("%s_GROUP=%s", env_base, set->group));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen}
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstatic int connect_auth_socket(struct auth_process_group *group,
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen const char *path)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_process *auth;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen int fd;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen fd = net_connect_unix(path);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (fd == -1) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_error("net_connect_unix(%s) failed: %m", path);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return -1;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen net_set_nonblock(fd, TRUE);
46b823ac3bce2c0f9f0fc73911e48d3a77b04fbeTimo Sirainen fd_close_on_exec(fd, TRUE);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth = auth_process_new(0, fd, group);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth->external = TRUE;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return 0;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen}
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstatic int create_auth_process(struct auth_process_group *group)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen static char *argv[] = { NULL, NULL };
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_socket_settings *as;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen const char *prefix, *str;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct log_io *log;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen pid_t pid;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen int fd[2], log_fd, i;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* see if this is a connect socket */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen as = group->set->sockets;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (as != NULL && strcmp(as->type, "connect") == 0)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return connect_auth_socket(group, as->master.path);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* create communication to process with a socket pair */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0) {
85da8c055280cd45553b6b335e9fb226d6e2801eTimo Sirainen i_error("socketpair() failed: %m");
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return -1;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen log_fd = log_create_pipe(&log);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (log_fd < 0)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen pid = -1;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen else {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen pid = fork();
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (pid < 0)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_error("fork() failed: %m");
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (pid < 0) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen (void)close(fd[0]);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen (void)close(fd[1]);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen (void)close(log_fd);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return -1;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (pid != 0) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* master */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen prefix = t_strdup_printf("auth(%s): ", group->set->name);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen log_set_prefix(log, prefix);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen net_set_nonblock(fd[0], TRUE);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen fd_close_on_exec(fd[0], TRUE);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth_process_new(pid, fd[0], group);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen (void)close(fd[1]);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen (void)close(log_fd);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return 0;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen prefix = t_strdup_printf("master-auth(%s): ", group->set->name);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen log_set_prefix(log, prefix);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* move master communication handle to 0 */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (dup2(fd[1], 0) < 0)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_fatal("dup2(stdin) failed: %m");
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen (void)close(fd[0]);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen (void)close(fd[1]);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* set stdout to /dev/null, so anything written into it gets ignored. */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (dup2(null_fd, 1) < 0)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_fatal("dup2(stdout) failed: %m");
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (dup2(log_fd, 2) < 0)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_fatal("dup2(stderr) failed: %m");
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen child_process_init_env();
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* move login communication handle to 3. do it last so we can be
534e41e436a7546f36f61e0dc49c0c191d850f6bPhil Carmody sure it's not closed afterwards. */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (group->listen_fd != 3) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (dup2(group->listen_fd, 3) < 0)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_fatal("dup2() failed: %m");
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen for (i = 0; i <= 3; i++)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen fd_close_on_exec(i, FALSE);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* setup access environment */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen restrict_access_set_env(group->set->user, group->set->uid,
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen group->set->gid, group->set->chroot,
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen 0, 0, NULL);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* set other environment */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen env_put(t_strconcat("AUTH_PROCESS=", dec2str(getpid()), NULL));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen env_put(t_strconcat("MECHANISMS=", group->set->mechanisms, NULL));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen env_put(t_strconcat("REALMS=", group->set->realms, NULL));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen env_put(t_strconcat("DEFAULT_REALM=", group->set->default_realm, NULL));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen env_put(t_strconcat("USERDB=", group->set->userdb, NULL));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen env_put(t_strconcat("PASSDB=", group->set->passdb, NULL));
00cc12d660b35bc955f97d30af660f3879b35a3cTimo Sirainen env_put(t_strconcat("USERNAME_CHARS=", group->set->username_chars, NULL));
00cc12d660b35bc955f97d30af660f3879b35a3cTimo Sirainen env_put(t_strconcat("ANONYMOUS_USERNAME=",
030e247340315f4425d297a00b439a4df72bf70cPhil Carmody group->set->anonymous_username, NULL));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen for (as = group->set->sockets, i = 1; as != NULL; as = as->next, i++) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (strcmp(as->type, "listen") != 0)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen continue;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen str = t_strdup_printf("AUTH_%u", i);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen socket_settings_env_put(str, &as->client);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen socket_settings_env_put(t_strconcat(str, "_MASTER", NULL),
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen &as->master);
030e247340315f4425d297a00b439a4df72bf70cPhil Carmody }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
030e247340315f4425d297a00b439a4df72bf70cPhil Carmody if (group->set->use_cyrus_sasl)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen env_put("USE_CYRUS_SASL=1");
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (group->set->verbose)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen env_put("VERBOSE=1");
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (group->set->debug)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen env_put("VERBOSE_DEBUG=1");
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (group->set->ssl_require_client_cert)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen env_put("SSL_REQUIRE_CLIENT_CERT=1");
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen restrict_process_size(group->set->process_size, (unsigned int)-1);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
030e247340315f4425d297a00b439a4df72bf70cPhil Carmody /* make sure we don't leak syslog fd, but do it last so that
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen any errors above will be logged */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen closelog();
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* hide the path, it's ugly */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen argv[0] = strrchr(group->set->executable, '/');
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (argv[0] == NULL)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen argv[0] = i_strdup(group->set->executable);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen else
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen argv[0]++;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen execv(group->set->executable, argv);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m",
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen group->set->executable);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return -1;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen}
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstruct auth_process *auth_process_find(unsigned int pid)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_process_group *group;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_process *p;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen for (group = process_groups; group != NULL; group = group->next) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen for (p = group->processes; p != NULL; p = p->next) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if ((unsigned int)p->pid == pid)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return p;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
573424407a2d3c1453638a643583a7cf10c129e1Phil Carmody
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return NULL;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen}
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstatic void auth_process_group_create(struct auth_settings *auth_set)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_process_group *group;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen const char *path;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen mode_t old_umask;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen group = i_new(struct auth_process_group, 1);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen group->set = auth_set;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen group->next = process_groups;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen process_groups = group;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (auth_set->sockets != NULL &&
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen strcmp(auth_set->sockets->type, "connect") == 0)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen return;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* create socket for listening auth requests from login */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen path = t_strconcat(auth_set->parent->defaults->login_dir, "/",
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth_set->name, NULL);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen (void)unlink(path);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen old_umask = umask(0117); /* we want 0660 mode for the socket */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen group->listen_fd = net_listen_unix(path);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen umask(old_umask);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (group->listen_fd < 0)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_fatal("Can't listen in UNIX socket %s: %m", path);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen net_set_nonblock(group->listen_fd, TRUE);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen fd_close_on_exec(group->listen_fd, TRUE);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* set correct permissions */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (chown(path, master_uid, auth_set->parent->login_gid) < 0) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_fatal("login: chown(%s, %s, %s) failed: %m",
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen path, dec2str(master_uid),
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen dec2str(auth_set->parent->login_gid));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen}
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstatic void auth_process_group_destroy(struct auth_process_group *group)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_process *next;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen while (group->processes != NULL) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen next = group->processes->next;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth_process_destroy(group->processes);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen group->processes = next;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen (void)unlink(t_strconcat(group->set->parent->defaults->login_dir, "/",
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen group->set->name, NULL));
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (close(group->listen_fd) < 0)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_error("close(auth group %s) failed: %m", group->set->name);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen i_free(group);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen}
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenvoid auth_processes_destroy_all(void)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_process_group *next;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen while (process_groups != NULL) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen next = process_groups->next;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth_process_group_destroy(process_groups);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen process_groups = next;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen}
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstatic void auth_process_groups_create(struct server_settings *server)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
573424407a2d3c1453638a643583a7cf10c129e1Phil Carmody struct auth_settings *auth_set;
573424407a2d3c1453638a643583a7cf10c129e1Phil Carmody
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen while (server != NULL) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth_set = server->auths;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen for (; auth_set != NULL; auth_set = auth_set->next)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth_process_group_create(auth_set);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen server = server->next;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen}
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenstatic void
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenauth_processes_start_missing(void *context __attr_unused__)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen struct auth_process_group *group;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen unsigned int count;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen if (process_groups == NULL) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen /* first time here, create the groups */
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth_process_groups_create(settings_root);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen for (group = process_groups; group != NULL; group = group->next) {
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen count = group->process_count;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen for (; count < group->set->count; count++)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen (void)create_auth_process(group);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen }
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen}
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenvoid auth_processes_init(void)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen process_groups = NULL;
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen to = timeout_add(1000, auth_processes_start_missing, NULL);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen}
030e247340315f4425d297a00b439a4df72bf70cPhil Carmody
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainenvoid auth_processes_deinit(void)
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen{
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen timeout_remove(to);
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen auth_processes_destroy_all();
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen}
a914bff43644dd9b3977244203839ca74161e40cTimo Sirainen