auth-master-connection.c revision 4b8c92b4773677a7b4064816e469eeafc976ba75
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "common.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "buffer.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "hash.h"
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen#include "str.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "ioloop.h"
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen#include "istream.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "ostream.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "network.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "mech.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "userdb.h"
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen#include "auth-master-interface.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "auth-client-connection.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "auth-master-connection.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen#include <unistd.h>
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen#include <stdlib.h>
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen#define MAX_INBUF_SIZE 1024
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#define MAX_OUTBUF_SIZE (1024*50)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenstruct auth_listener {
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen struct auth_master_connection *master;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen int client_listener;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen int fd;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen char *path;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen struct io *io;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen};
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstruct master_userdb_request {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_master_connection *conn;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen unsigned int id;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct auth_request *auth_request;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen};
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainenstatic int master_output(void *context);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenstatic void auth_master_connection_close(struct auth_master_connection *conn);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic int auth_master_connection_unref(struct auth_master_connection *conn);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenstatic void master_send(struct auth_master_connection *conn,
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen const char *fmt, ...) __attr_format__(2, 3);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenstatic void master_send(struct auth_master_connection *conn,
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen const char *fmt, ...)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen va_list args;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen string_t *str;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen t_push();
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen va_start(args, fmt);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen str = t_str_new(256);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen str_vprintfa(str, fmt, args);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen str_append_c(str, '\n');
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen (void)o_stream_send(conn->output, str_data(str), str_len(str));
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen va_end(args);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen t_pop();
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenstatic void append_user_reply(string_t *str, const struct user_data *user)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen const char *p;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen str_printfa(str, "%s\tuid=%s\tgid=%s", user->virtual_user,
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen dec2str(user->uid), dec2str(user->gid));
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (user->system_user != NULL)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen str_printfa(str, "\tsystem_user=%s", user->system_user);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (user->mail != NULL)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen str_printfa(str, "\tmail=%s", user->mail);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen p = user->home != NULL ? strstr(user->home, "/./") : NULL;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (p == NULL) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (user->home != NULL)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen str_printfa(str, "\thome=%s", user->home);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen } else {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* wu-ftpd like <chroot>/./<home> */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen str_printfa(str, "\thome=%s\tchroot=%s",
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen p + 3, t_strdup_until(user->home, p));
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenstatic void userdb_callback(const struct user_data *user, void *context)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct master_userdb_request *master_request = context;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen string_t *str;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (auth_master_connection_unref(master_request->conn)) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (user == NULL) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen master_send(master_request->conn, "NOTFOUND\t%u",
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen master_request->id);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen } else {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen str = t_str_new(256);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen str_printfa(str, "USER\t%u\t", master_request->id);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen append_user_reply(str, user);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen master_send(master_request->conn, "%s", str_c(str));
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen auth_request_destroy(master_request->auth_request);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen i_free(master_request);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenstatic int
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenmaster_input_request(struct auth_master_connection *conn, const char *args)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_client_connection *client_conn;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct master_userdb_request *master_request;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen struct auth_request *request;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen const char *const *list;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen unsigned int id, client_pid, client_id;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen /* <id> <client-pid> <client-id> */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen list = t_strsplit(args, "\t");
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (list[0] == NULL || list[1] == NULL || list[2] == NULL) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_error("BUG: Master sent broken REQUEST");
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen return FALSE;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen }
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen id = (unsigned int)strtoul(list[0], NULL, 10);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen client_pid = (unsigned int)strtoul(list[1], NULL, 10);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen client_id = (unsigned int)strtoul(list[2], NULL, 10);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen client_conn = auth_client_connection_lookup(conn, client_pid);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen request = client_conn == NULL ? NULL :
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen hash_lookup(client_conn->auth_requests,
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen POINTER_CAST(client_id));
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (request == NULL) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (verbose) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen i_info("Master request %u.%u not found",
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen client_pid, client_id);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen master_send(conn, "NOTFOUND\t%u", id);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen } else {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen master_request = i_new(struct master_userdb_request, 1);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen master_request->conn = conn;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen master_request->id = id;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen master_request->auth_request = request;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->refcount++;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen userdb->lookup(request, userdb_callback, master_request);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen return TRUE;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen}
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenstatic int
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenmaster_input_die(struct auth_master_connection *conn)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen{
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen return TRUE;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic void master_input(void *context)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_master_connection *conn = context;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen char *line;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen int ret;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen switch (i_stream_read(conn->input)) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen case 0:
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen return;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen case -1:
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen /* disconnected */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen auth_master_connection_close(conn);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen return;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen case -2:
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen /* buffer full */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_error("BUG: Master sent us more than %d bytes",
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen (int)MAX_INBUF_SIZE);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_master_connection_close(conn);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen if (!conn->version_received) {
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen line = i_stream_next_line(conn->input);
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen if (line == NULL)
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen return;
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen /* make sure the major version matches */
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen if (strncmp(line, "VERSION\t", 8) != 0 ||
4b8c92b4773677a7b4064816e469eeafc976ba75Timo Sirainen atoi(t_strcut(line + 8, '\t')) !=
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen AUTH_MASTER_PROTOCOL_MAJOR_VERSION) {
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen i_error("Master not compatible with this server "
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen "(mixed old and new binaries?)");
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen auth_master_connection_close(conn);
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen return;
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen }
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen conn->version_received = TRUE;
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen }
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen while ((line = i_stream_next_line(conn->input)) != NULL) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen t_push();
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (strncmp(line, "REQUEST\t", 8) == 0)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen ret = master_input_request(conn, line + 8);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen else if (strcmp(line, "DIE") == 0)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen ret = master_input_die(conn);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen else {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen /* ignore unknown command */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen ret = TRUE;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen }
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen t_pop();
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (!ret) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen auth_master_connection_close(conn);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen return;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainenstatic int master_output(void *context)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen{
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen struct auth_master_connection *conn = context;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen int ret;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if ((ret = o_stream_flush(conn->output)) < 0) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* transmit error, probably master died */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen auth_master_connection_close(conn);
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen return 1;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (o_stream_get_buffer_used_size(conn->output) <= MAX_OUTBUF_SIZE/2) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* allow input again */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen conn->io = io_add(conn->fd, IO_READ, master_input, conn);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen return 1;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen}
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenstatic void
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenauth_master_connection_set_fd(struct auth_master_connection *conn, int fd)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen{
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (conn->input != NULL)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_stream_unref(conn->input);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen if (conn->output != NULL)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen o_stream_unref(conn->output);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen if (conn->io != NULL)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen io_remove(conn->io);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen conn->input = i_stream_create_file(fd, default_pool,
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen MAX_INBUF_SIZE, FALSE);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen conn->output = o_stream_create_file(fd, default_pool,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen (size_t)-1, FALSE);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen o_stream_set_flush_callback(conn->output, master_output, conn);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen conn->io = io_add(fd, IO_READ, master_input, conn);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen conn->fd = fd;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen}
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstruct auth_master_connection *
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenauth_master_connection_create(int fd, unsigned int pid)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_master_connection *conn;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn = i_new(struct auth_master_connection, 1);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->refcount = 1;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->pid = pid;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->fd = fd;
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen conn->listeners_buf = buffer_create_dynamic(default_pool, 64);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen if (fd != -1)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_master_connection_set_fd(conn, fd);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen return conn;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainenvoid auth_master_connection_send_handshake(struct auth_master_connection *conn)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen{
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen if (conn->output != NULL) {
4b8c92b4773677a7b4064816e469eeafc976ba75Timo Sirainen master_send(conn, "VERSION\t%u\t%u\nSPID\t%u\n",
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen AUTH_MASTER_PROTOCOL_MAJOR_VERSION,
2cb3e318bdfee05d1de2d8c8942ff790edd3ea3fTimo Sirainen AUTH_MASTER_PROTOCOL_MINOR_VERSION, conn->pid);
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen }
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen}
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenstatic void auth_master_connection_close(struct auth_master_connection *conn)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen{
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen if (!standalone)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen io_loop_stop(ioloop);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen if (close(conn->fd) < 0)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen i_error("close(): %m");
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen conn->fd = -1;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen o_stream_close(conn->output);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen conn->output = NULL;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (conn->io != NULL) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen io_remove(conn->io);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen conn->io = NULL;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenvoid auth_master_connection_destroy(struct auth_master_connection *conn)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen struct auth_listener **l;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen size_t i, size;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen if (conn->destroyed)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen conn->destroyed = TRUE;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_client_connections_deinit(conn);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen if (conn->fd != -1)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_master_connection_close(conn);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen l = buffer_get_modifyable_data(conn->listeners_buf, &size);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen size /= sizeof(*l);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen for (i = 0; i < size; i++) {
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen net_disconnect(l[i]->fd);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen io_remove(l[i]->io);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen if (l[i]->path != NULL) {
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen (void)unlink(l[i]->path);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen i_free(l[i]->path);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen }
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen i_free(l[i]);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen }
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen buffer_free(conn->listeners_buf);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen conn->listeners_buf = NULL;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen auth_master_connection_unref(conn);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic int auth_master_connection_unref(struct auth_master_connection *conn)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (--conn->refcount > 0)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return TRUE;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen if (conn->output != NULL)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen o_stream_unref(conn->output);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen i_free(conn);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return FALSE;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainenstatic void auth_accept(void *context)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen{
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen struct auth_listener *l = context;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen int fd;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen fd = net_accept(l->fd, NULL, NULL);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen if (fd < 0) {
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen if (fd < -1)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen i_fatal("accept() failed: %m");
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen } else {
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen net_set_nonblock(fd, TRUE);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen if (l->client_listener)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen (void)auth_client_connection_create(l->master, fd);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen else {
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen /* we'll just replace the previous master.. */
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_master_connection_set_fd(l->master, fd);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_master_connection_send_handshake(l->master);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen }
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen }
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen}
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainenvoid auth_master_connection_add_listener(struct auth_master_connection *conn,
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen int fd, const char *path, int client)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen{
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen struct auth_listener *l;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen l = i_new(struct auth_listener, 1);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen l->master = conn;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen l->client_listener = client;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen l->fd = fd;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen l->path = i_strdup(path);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen l->io = io_add(fd, IO_READ, auth_accept, l);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen buffer_append(conn->listeners_buf, &l, sizeof(l));
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen}