auth-process.c revision 6ef7e31619edfaa17ed044b45861d106a86191ef
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/* Copyright (C) 2002 Timo Sirainen */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include "common.h"
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include "ioloop.h"
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include "env-util.h"
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include "fd-close-on-exec.h"
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include "unix-socket-create.h"
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include "network.h"
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include "istream.h"
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include "ostream.h"
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include "str.h"
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include "restrict-access.h"
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include "restrict-process-size.h"
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include "auth-process.h"
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include "../auth/auth-master-interface.h"
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include "log.h"
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <stdlib.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <unistd.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <pwd.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <syslog.h>
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#define MAX_INBUF_SIZE 8192
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#define MAX_OUTBUF_SIZE 65536
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
62ef8476c4f1cb016de161827d921418dee4b031Yuri Pankovstruct auth_process_group {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng struct auth_process_group *next;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int listen_fd;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng struct auth_settings *set;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
c3affd820c380dd131cbf6584013c11487d84089Michael Lim unsigned int process_count;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng struct auth_process *processes;
c3affd820c380dd131cbf6584013c11487d84089Michael Lim};
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstruct auth_process {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng struct auth_process *next;
82a2fc4751cef28c0bdc327d02012bf8796083b9James Carlson
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng struct auth_process_group *group;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng pid_t pid;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int fd;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng struct io *io;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct istream *input;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng struct ostream *output;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da0006029e69465355313f503741ac6ebe0d513bGirish Moodalbail int worker_listen_fd;
c3affd820c380dd131cbf6584013c11487d84089Michael Lim struct io *worker_io;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
c3affd820c380dd131cbf6584013c11487d84089Michael Lim struct hash_table *requests;
285e94f91fd7deba72e31d9ecf23ec4769a8323bMichael Lim
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng unsigned int external:1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng unsigned int version_received:1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng unsigned int initialized:1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng unsigned int in_auth_reply:1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng};
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic struct timeout *to;
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic unsigned int auth_tag;
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic struct auth_process_group *process_groups;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void auth_process_destroy(struct auth_process *p);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic int create_auth_worker(struct auth_process *process, int fd);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid auth_process_request(struct auth_process *process, unsigned int login_pid,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng unsigned int login_id, void *context)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng string_t *str;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ssize_t ret;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng t_push();
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng str = t_str_new(256);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng str_printfa(str, "REQUEST\t%u\t%u\t%u\n",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ++auth_tag, login_pid, login_id);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = o_stream_send(process->output, str_data(str), str_len(str));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ret != (ssize_t)str_len(str)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ret >= 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* FIXME: well .. I'm not sure if it'd be better to
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng just block here. I don't think this condition should
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng happen often, so this could mean that the auth
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng process is stuck. Or that the computer is just
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng too heavily loaded. Possibility to block infinitely
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng is annoying though, so for now don't do it. */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng i_warning("Auth process %s transmit buffer full, "
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "killing..", dec2str(process->pid));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng auth_process_destroy(process);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng hash_insert(process->requests, POINTER_CAST(auth_tag), context);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng t_pop();
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic bool
da14cebe459d3275048785f25bd869cb09b5307fEric Chengauth_process_input_user(struct auth_process *process, const char *args)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng void *context;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng const char *const *list;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng unsigned int id;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* <id> <userid> [..] */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng list = t_strsplit(args, "\t");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (list[0] == NULL || list[1] == NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng i_error("BUG: Auth process %s sent corrupted USER line",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng dec2str(process->pid));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng id = (unsigned int)strtoul(list[0], NULL, 10);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng context = hash_lookup(process->requests, POINTER_CAST(id));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (context == NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng i_error("BUG: Auth process %s sent unrequested reply with ID "
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "%u", dec2str(process->pid), id);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng auth_master_callback(list[1], list + 2, context);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng hash_remove(process->requests, POINTER_CAST(id));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return TRUE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic bool
da14cebe459d3275048785f25bd869cb09b5307fEric Chengauth_process_input_notfound(struct auth_process *process, const char *args)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng void *context;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng unsigned int id;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng id = (unsigned int)strtoul(args, NULL, 10);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng context = hash_lookup(process->requests, POINTER_CAST(id));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (context == NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng i_error("BUG: Auth process %s sent unrequested reply with ID "
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "%u", dec2str(process->pid), id);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng auth_master_callback(NULL, NULL, context);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng hash_remove(process->requests, POINTER_CAST(id));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return TRUE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic bool
da14cebe459d3275048785f25bd869cb09b5307fEric Chengauth_process_input_spid(struct auth_process *process, const char *args)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng unsigned int pid;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (process->initialized) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng i_error("BUG: Authentication server re-handshaking");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng pid = (unsigned int)strtoul(args, NULL, 10);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (pid == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng i_error("BUG: Authentication server said it's PID 0");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (process->pid != 0 && process->pid != (pid_t)pid) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng i_error("BUG: Authentication server sent invalid SPID "
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "(%u != %s)", pid, dec2str(process->pid));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng process->pid = pid;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng process->initialized = TRUE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return TRUE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskeystatic bool
da14cebe459d3275048785f25bd869cb09b5307fEric Chengauth_process_input_fail(struct auth_process *process, const char *args)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng void *context;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng const char *error;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng unsigned int id;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng error = strchr(args, '\t');
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (error != NULL)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng error++;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey id = (unsigned int)strtoul(args, NULL, 10);
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng context = hash_lookup(process->requests, POINTER_CAST(id));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (context == NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng i_error("BUG: Auth process %s sent unrequested reply with ID "
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "%u", dec2str(process->pid), id);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return FALSE;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng auth_master_callback(NULL, NULL, context);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng hash_remove(process->requests, POINTER_CAST(id));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return TRUE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void auth_process_input(void *context)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng struct auth_process *process = context;
3efde6d032b3bcd6957e912c3f2a59253f28a9dcSowmini Varadhan const char *line;
3efde6d032b3bcd6957e912c3f2a59253f28a9dcSowmini Varadhan bool ret;
3efde6d032b3bcd6957e912c3f2a59253f28a9dcSowmini Varadhan
3efde6d032b3bcd6957e912c3f2a59253f28a9dcSowmini Varadhan switch (i_stream_read(process->input)) {
3efde6d032b3bcd6957e912c3f2a59253f28a9dcSowmini Varadhan case 0:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng case -1:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* disconnected */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng auth_process_destroy(process);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng case -2:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* buffer full */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng i_error("BUG: Auth process %s sent us more than %d "
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "bytes of data", dec2str(process->pid),
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (int)MAX_INBUF_SIZE);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng auth_process_destroy(process);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!process->version_received) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng line = i_stream_next_line(process->input);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (line == NULL)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* make sure the major version matches */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (strncmp(line, "VERSION\t", 8) != 0 ||
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng atoi(t_strcut(line + 8, '\t')) !=
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng AUTH_MASTER_PROTOCOL_MAJOR_VERSION) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng i_error("Auth process %s not compatible with master "
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "process (mixed old and new binaries?)",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng dec2str(process->pid));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng auth_process_destroy(process);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng process->version_received = TRUE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng while ((line = i_stream_next_line(process->input)) != NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng t_push();
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (strncmp(line, "USER\t", 5) == 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ret = auth_process_input_user(process, line + 5);
2d40c3b296fd82c4f1f14694b16f9b39d9fa0e4aPrakash Jalan else if (strncmp(line, "NOTFOUND\t", 9) == 0)
2d40c3b296fd82c4f1f14694b16f9b39d9fa0e4aPrakash Jalan ret = auth_process_input_notfound(process, line + 9);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng else if (strncmp(line, "FAIL\t", 5) == 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = auth_process_input_fail(process, line + 5);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng else if (strncmp(line, "SPID\t", 5) == 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = auth_process_input_spid(process, line + 5);
2d40c3b296fd82c4f1f14694b16f9b39d9fa0e4aPrakash Jalan else
2d40c3b296fd82c4f1f14694b16f9b39d9fa0e4aPrakash Jalan ret = TRUE;
2d40c3b296fd82c4f1f14694b16f9b39d9fa0e4aPrakash Jalan t_pop();
2d40c3b296fd82c4f1f14694b16f9b39d9fa0e4aPrakash Jalan
2d40c3b296fd82c4f1f14694b16f9b39d9fa0e4aPrakash Jalan if (!ret) {
2d40c3b296fd82c4f1f14694b16f9b39d9fa0e4aPrakash Jalan auth_process_destroy(process);
2d40c3b296fd82c4f1f14694b16f9b39d9fa0e4aPrakash Jalan break;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void auth_worker_input(void *context)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct auth_process *p = context;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer int fd;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer fd = net_accept(p->worker_listen_fd, NULL, NULL);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (fd < 0) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (fd == -2)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_fatal("net_accept(worker) failed: %m");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer net_set_nonblock(fd, TRUE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer fd_close_on_exec(fd, TRUE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer create_auth_worker(p, fd);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic struct auth_process *
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerauth_process_new(pid_t pid, int fd, struct auth_process_group *group)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct auth_process *p;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer const char *path, *handshake;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (pid != 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_AUTH);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer p = i_new(struct auth_process, 1);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer p->group = group;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer p->pid = pid;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer p->fd = fd;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer p->io = io_add(fd, IO_READ, auth_process_input, p);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer p->input = i_stream_create_file(fd, default_pool,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MAX_INBUF_SIZE, FALSE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer p->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer FALSE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer p->requests = hash_create(default_pool, default_pool, 0, NULL, NULL);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer group->process_count++;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer path = t_strdup_printf("%s/auth-worker.%s",
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer group->set->chroot != NULL ? group->set->chroot :
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer group->set->parent->defaults->base_dir,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer dec2str(pid));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer p->worker_listen_fd =
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer unix_socket_create(path, 0600, group->set->uid,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer group->set->gid, 16);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (p->worker_listen_fd == -1)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_fatal("Couldn't create auth worker listener");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer net_set_nonblock(p->worker_listen_fd, TRUE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer fd_close_on_exec(p->worker_listen_fd, TRUE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer p->worker_io = io_add(p->worker_listen_fd, IO_READ,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer auth_worker_input, p);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer handshake = t_strdup_printf("VERSION\t%u\t%u\n",
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer AUTH_MASTER_PROTOCOL_MAJOR_VERSION,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer AUTH_MASTER_PROTOCOL_MINOR_VERSION);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void)o_stream_send_str(p->output, handshake);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer p->next = group->processes;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer group->processes = p;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return p;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void auth_process_destroy(struct auth_process *p)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct hash_iterate_context *iter;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer void *key, *value;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct auth_process **pos;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer const char *path;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (!p->initialized && io_loop_is_running(ioloop) && !p->external) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_error("Auth process died too early - shutting down");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer io_loop_stop(ioloop);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer for (pos = &p->group->processes; *pos != NULL; pos = &(*pos)->next) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (*pos == p) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer *pos = p->next;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer p->group->process_count--;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer path = t_strdup_printf("%s/auth-worker.%s",
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer p->group->set->chroot != NULL ?
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer p->group->set->chroot :
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer p->group->set->parent->defaults->base_dir,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer dec2str(p->pid));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void)unlink(path);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (close(p->worker_listen_fd) < 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_error("close(worker_listen) failed: %m");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer io_remove(p->worker_io);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer iter = hash_iterate_init(p->requests);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer while (hash_iterate(iter, &key, &value))
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer auth_master_callback(NULL, NULL, value);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer hash_iterate_deinit(iter);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer hash_destroy(p->requests);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_stream_unref(p->input);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer o_stream_unref(p->output);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer io_remove(p->io);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (close(p->fd) < 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_error("close(auth) failed: %m");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_free(p);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyersocket_settings_env_put(const char *env_base, struct socket_settings *set)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (set->path == NULL)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strdup_printf("%s=%s", env_base, set->path));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (set->mode != 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strdup_printf("%s_MODE=%o", env_base, set->mode));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (set->user != NULL)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strdup_printf("%s_USER=%s", env_base, set->user));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (set->group != NULL)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strdup_printf("%s_GROUP=%s", env_base, set->group));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic int connect_auth_socket(struct auth_process_group *group,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer const char *path)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct auth_process *auth;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer int fd;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer fd = net_connect_unix(path);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (fd == -1) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_error("net_connect_unix(%s) failed: %m", path);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return -1;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer net_set_nonblock(fd, TRUE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer fd_close_on_exec(fd, TRUE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer auth = auth_process_new(0, fd, group);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer auth->external = TRUE;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void auth_set_environment(struct auth_settings *set)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct auth_socket_settings *as;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct auth_passdb_settings *ap;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct auth_userdb_settings *au;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer const char *str;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer int i;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /* setup access environment */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer restrict_access_set_env(set->user, set->uid, set->gid, set->chroot,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer 0, 0, NULL);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /* set other environment */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put("DOVECOT_MASTER=1");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strconcat("AUTH_NAME=", set->name, NULL));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strconcat("MECHANISMS=", set->mechanisms, NULL));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strconcat("REALMS=", set->realms, NULL));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strconcat("DEFAULT_REALM=", set->default_realm, NULL));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strconcat("USERNAME_CHARS=", set->username_chars, NULL));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strconcat("USERNAME_TRANSLATION=",
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer set->username_translation, NULL));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strconcat("ANONYMOUS_USERNAME=",
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer set->anonymous_username, NULL));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strdup_printf("CACHE_SIZE=%u", set->cache_size));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strdup_printf("CACHE_TTL=%u", set->cache_ttl));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer for (ap = set->passdbs, i = 1; ap != NULL; ap = ap->next, i++) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strdup_printf("PASSDB_%u_DRIVER=%s", i, ap->driver));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (ap->args != NULL) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strdup_printf("PASSDB_%u_ARGS=%s",
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i, ap->args));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (ap->deny)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strdup_printf("PASSDB_%u_DENY=1", i));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer for (au = set->userdbs, i = 1; au != NULL; au = au->next, i++) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strdup_printf("USERDB_%u_DRIVER=%s", i, au->driver));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (au->args != NULL) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strdup_printf("USERDB_%u_ARGS=%s",
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i, au->args));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer for (as = set->sockets, i = 1; as != NULL; as = as->next, i++) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (strcmp(as->type, "listen") != 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer continue;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer str = t_strdup_printf("AUTH_%u", i);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer socket_settings_env_put(str, &as->client);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer socket_settings_env_put(t_strconcat(str, "_MASTER", NULL),
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer &as->master);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (set->verbose)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put("VERBOSE=1");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (set->debug)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put("VERBOSE_DEBUG=1");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (set->ssl_require_client_cert)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put("SSL_REQUIRE_CLIENT_CERT=1");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (set->ssl_username_from_cert)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put("SSL_USERNAME_FROM_CERT=1");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (set->krb5_keytab != NULL) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /* Environment used by Kerberos 5 library directly */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strconcat("KRB5_KTNAME=", set->krb5_keytab, NULL));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer restrict_process_size(set->process_size, (unsigned int)-1);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic int create_auth_process(struct auth_process_group *group)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct auth_socket_settings *as;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer const char *prefix, *executable;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct log_io *log;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer pid_t pid;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer int fd[2], log_fd, i;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /* see if this is a connect socket */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer as = group->set->sockets;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (as != NULL && strcmp(as->type, "connect") == 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return connect_auth_socket(group, as->master.path);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /* create communication to process with a socket pair */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_error("socketpair() failed: %m");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return -1;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer log_fd = log_create_pipe(&log, 0);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (log_fd < 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer pid = -1;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer else {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer pid = fork();
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (pid < 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_error("fork() failed: %m");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (pid < 0) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void)close(fd[0]);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void)close(fd[1]);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void)close(log_fd);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return -1;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (pid != 0) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /* master */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer prefix = t_strdup_printf("auth(%s): ", group->set->name);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer log_set_prefix(log, prefix);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer net_set_nonblock(fd[0], TRUE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer fd_close_on_exec(fd[0], TRUE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer auth_process_new(pid, fd[0], group);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void)close(fd[1]);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void)close(log_fd);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer prefix = t_strdup_printf("master-auth(%s): ", group->set->name);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer log_set_prefix(log, prefix);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /* move master communication handle to 0 */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (dup2(fd[1], 0) < 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_fatal("dup2(stdin) failed: %m");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void)close(fd[0]);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void)close(fd[1]);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /* set stdout to /dev/null, so anything written into it gets ignored. */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (dup2(null_fd, 1) < 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_fatal("dup2(stdout) failed: %m");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (dup2(log_fd, 2) < 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_fatal("dup2(stderr) failed: %m");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer child_process_init_env();
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (group->listen_fd != 3) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (dup2(group->listen_fd, 3) < 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_fatal("dup2() failed: %m");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer fd_close_on_exec(3, FALSE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer for (i = 0; i <= 2; i++)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer fd_close_on_exec(i, FALSE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer auth_set_environment(group->set);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strdup_printf("AUTH_WORKER_PATH=%s/auth-worker.%s",
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer group->set->chroot != NULL ? "" :
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer group->set->parent->defaults->base_dir,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer dec2str(getpid())));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer env_put(t_strdup_printf("AUTH_WORKER_MAX_COUNT=%u",
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer group->set->worker_max_count));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /* make sure we don't leak syslog fd, but do it last so that
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer any errors above will be logged */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer closelog();
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer executable = group->set->executable;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer client_process_exec(executable, "");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", executable);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return -1;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic int create_auth_worker(struct auth_process *process, int fd)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct log_io *log;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer const char *prefix, *executable;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer pid_t pid;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer int log_fd, i;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer log_fd = log_create_pipe(&log, 0);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (log_fd < 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer pid = -1;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer else {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer pid = fork();
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (pid < 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_error("fork() failed: %m");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (pid < 0) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void)close(log_fd);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return -1;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (pid != 0) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /* master */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_AUTH_WORKER);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer prefix = t_strdup_printf("auth-worker(%s): ",
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer process->group->set->name);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer log_set_prefix(log, prefix);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void)close(fd);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void)close(log_fd);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer prefix = t_strdup_printf("master-auth-worker(%s): ",
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer process->group->set->name);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer log_set_prefix(log, prefix);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /* set stdin and stdout to /dev/null, so anything written into it
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer gets ignored. */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (dup2(null_fd, 0) < 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_fatal("dup2(stdin) failed: %m");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (dup2(null_fd, 1) < 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_fatal("dup2(stdout) failed: %m");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (dup2(log_fd, 2) < 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_fatal("dup2(stderr) failed: %m");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (dup2(fd, 4) < 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_fatal("dup2(4) failed: %m");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer for (i = 0; i <= 2; i++)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer fd_close_on_exec(i, FALSE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer fd_close_on_exec(4, FALSE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer child_process_init_env();
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer auth_set_environment(process->group->set);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /* make sure we don't leak syslog fd, but do it last so that
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer any errors above will be logged */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer closelog();
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer executable = t_strconcat(process->group->set->executable, " -w", NULL);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer client_process_exec(executable, "");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", executable);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return -1;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstruct auth_process *auth_process_find(unsigned int pid)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct auth_process_group *group;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct auth_process *p;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer for (group = process_groups; group != NULL; group = group->next) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer for (p = group->processes; p != NULL; p = p->next) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if ((unsigned int)p->pid == pid)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return p;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return NULL;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void auth_process_group_create(struct auth_settings *auth_set)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct auth_process_group *group;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer const char *path;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer group = i_new(struct auth_process_group, 1);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer group->set = auth_set;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer group->next = process_groups;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer process_groups = group;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (auth_set->sockets != NULL &&
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer strcmp(auth_set->sockets->type, "connect") == 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer path = t_strconcat(auth_set->parent->defaults->login_dir, "/",
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer auth_set->name, NULL);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer group->listen_fd = unix_socket_create(path, 0660, master_uid,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer auth_set->parent->login_gid, 16);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (group->listen_fd == -1)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_fatal("Couldn't create auth process listener");
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer net_set_nonblock(group->listen_fd, TRUE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer fd_close_on_exec(group->listen_fd, TRUE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void auth_process_group_destroy(struct auth_process_group *group)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct auth_process *next;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer const char *path;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer while (group->processes != NULL) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer next = group->processes->next;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer auth_process_destroy(group->processes);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer group->processes = next;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer path = t_strconcat(group->set->parent->defaults->login_dir, "/",
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer group->set->name, NULL);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void)unlink(path);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (close(group->listen_fd) < 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_error("close(%s) failed: %m", path);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer i_free(group);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyervoid auth_processes_destroy_all(void)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct auth_process_group *next;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer while (process_groups != NULL) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer next = process_groups->next;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer auth_process_group_destroy(process_groups);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer process_groups = next;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void auth_process_groups_create(struct server_settings *server)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct auth_settings *auth_set;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer while (server != NULL) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer auth_set = server->auths;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer for (; auth_set != NULL; auth_set = auth_set->next)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer auth_process_group_create(auth_set);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer server = server->next;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerauth_processes_start_missing(void *context __attr_unused__)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct auth_process_group *group;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer unsigned int count;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (process_groups == NULL) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /* first time here, create the groups */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer auth_process_groups_create(settings_root);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer for (group = process_groups; group != NULL; group = group->next) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer count = group->process_count;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer for (; count < group->set->count; count++)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void)create_auth_process(group);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyervoid auth_processes_init(void)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer process_groups = NULL;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer to = timeout_add(1000, auth_processes_start_missing, NULL);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyervoid auth_processes_deinit(void)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer timeout_remove(to);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer auth_processes_destroy_all();
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer