auth-master-connection.c revision 645397402d1d0c755cd485ecf721b59b6babc874
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 "userdb.h"
657afb33796f8216c568ad813627da89970760beTimo Sirainen#include "auth-request-handler.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;
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen enum listener_type type;
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
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainenstatic array_t ARRAY_DEFINE(master_connections,
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen struct auth_master_connection *);
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainenstatic int master_output(void *context);
70905e51a5148bd5613cb04720807177474a2496Timo Sirainenstatic void auth_listener_destroy(struct auth_listener *l);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainenvoid auth_master_request_callback(const char *reply, void *context)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
657afb33796f8216c568ad813627da89970760beTimo Sirainen struct auth_master_connection *conn = context;
657afb33796f8216c568ad813627da89970760beTimo Sirainen struct const_iovec iov[2];
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen if (conn->auth->verbose_debug)
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen i_info("master out: %s", reply);
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainen iov[0].iov_base = reply;
657afb33796f8216c568ad813627da89970760beTimo Sirainen iov[0].iov_len = strlen(reply);
657afb33796f8216c568ad813627da89970760beTimo Sirainen iov[1].iov_base = "\n";
657afb33796f8216c568ad813627da89970760beTimo Sirainen iov[1].iov_len = 1;
a7bee3930831a9261fa6180d02af29c484d862e9Timo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainen (void)o_stream_sendv(conn->output, iov, 2);
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;
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);
657afb33796f8216c568ad813627da89970760beTimo Sirainen if (client_conn == NULL) {
657afb33796f8216c568ad813627da89970760beTimo Sirainen i_error("Master requested auth for nonexisting client %u",
657afb33796f8216c568ad813627da89970760beTimo Sirainen client_pid);
657afb33796f8216c568ad813627da89970760beTimo Sirainen (void)o_stream_send_str(conn->output,
657afb33796f8216c568ad813627da89970760beTimo Sirainen t_strdup_printf("NOTFOUND\t%u\n", id));
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen } else {
657afb33796f8216c568ad813627da89970760beTimo Sirainen auth_request_handler_master_request(
657afb33796f8216c568ad813627da89970760beTimo Sirainen client_conn->request_handler, id, client_id);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen return TRUE;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen}
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainenstatic void
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainenuser_callback(const char *result, struct auth_request *auth_request)
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen{
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen struct auth_master_connection *conn = auth_request->context;
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen string_t *str;
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen str = t_str_new(128);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen if (result == NULL)
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen str_printfa(str, "NOTFOUND\t%u\n", auth_request->id);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen else {
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen str_printfa(str, "USER\t%u\t", auth_request->id);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen str_append(str, result);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen str_append_c(str, '\n');
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen }
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen (void)o_stream_send(conn->output, str_data(str), str_len(str));
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen}
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainenstatic int
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainenmaster_input_user(struct auth_master_connection *conn, const char *args)
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen{
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen struct auth_request *auth_request;
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen const char *const *list;
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen /* <id> <userid> */
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen list = t_strsplit(args, "\t");
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen if (list[0] == NULL || list[1] == NULL) {
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen i_error("BUG: Master sent broken USER");
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen return FALSE;
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen }
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen auth_request = auth_request_new_dummy(conn->auth);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen auth_request->id = (unsigned int)strtoul(list[0], NULL, 10);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen auth_request->user = p_strdup(auth_request->pool, list[1]);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen auth_request->context = conn;
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen auth_request_lookup_user(auth_request, user_callback);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen return TRUE;
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen}
9398c0935613ba038cf2275ff66c43b25092cfd0Timo 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 */
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen auth_master_connection_destroy(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);
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen auth_master_connection_destroy(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?)");
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen auth_master_connection_destroy(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) {
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen if (conn->auth->verbose_debug)
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen i_info("master in: %s", line);
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen t_push();
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (strncmp(line, "REQUEST\t", 8) == 0)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen ret = master_input_request(conn, line + 8);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen else if (strncmp(line, "USER\t", 5) == 0)
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen ret = master_input_user(conn, line + 5);
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) {
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen auth_master_connection_destroy(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 */
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen auth_master_connection_destroy(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 *
657afb33796f8216c568ad813627da89970760beTimo Sirainenauth_master_connection_create(struct auth *auth, int fd)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_master_connection *conn;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn = i_new(struct auth_master_connection, 1);
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen conn->auth = auth;
657afb33796f8216c568ad813627da89970760beTimo Sirainen conn->pid = (unsigned int)getpid();
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);
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen array_append(&master_connections, &conn, 1);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen return conn;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainenvoid auth_master_connection_send_handshake(struct auth_master_connection *conn)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen{
657afb33796f8216c568ad813627da89970760beTimo Sirainen const char *line;
657afb33796f8216c568ad813627da89970760beTimo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainen if (conn->output == NULL)
657afb33796f8216c568ad813627da89970760beTimo Sirainen return;
657afb33796f8216c568ad813627da89970760beTimo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainen line = t_strdup_printf("VERSION\t%u\t%u\nSPID\t%u\n",
657afb33796f8216c568ad813627da89970760beTimo Sirainen AUTH_MASTER_PROTOCOL_MAJOR_VERSION,
657afb33796f8216c568ad813627da89970760beTimo Sirainen AUTH_MASTER_PROTOCOL_MINOR_VERSION, conn->pid);
657afb33796f8216c568ad813627da89970760beTimo Sirainen (void)o_stream_send_str(conn->output, line);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen}
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenvoid auth_master_connection_destroy(struct auth_master_connection *conn)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen struct auth_master_connection *const *conns;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen struct auth_listener **l;
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen unsigned int i, count;
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
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen if (conn->fd != -1) {
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen if (close(conn->fd) < 0)
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen i_error("close(): %m");
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen }
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen if (conn->input != NULL)
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen i_stream_unref(conn->input);
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen if (conn->output != NULL)
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen o_stream_unref(conn->output);
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen if (conn->io != NULL)
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen io_remove(conn->io);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen while (conn->listeners_buf->used > 0) {
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen l = buffer_get_modifyable_data(conn->listeners_buf, NULL);
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen auth_listener_destroy(*l);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen }
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen buffer_free(conn->listeners_buf);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen conn->listeners_buf = NULL;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen conns = array_get(&master_connections, &count);
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen for (i = 0; i < count; i++) {
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen if (conns[i] == conn) {
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen array_delete(&master_connections, i, 1);
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen break;
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen }
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen }
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen if (!standalone && array_count(&master_connections) == 0)
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen io_loop_stop(ioloop);
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen i_free(conn);
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)
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen i_fatal("accept(type %d) failed: %m", l->type);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen } else {
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen net_set_nonblock(fd, TRUE);
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen switch (l->type) {
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen case LISTENER_CLIENT:
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen (void)auth_client_connection_create(l->master, fd);
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen break;
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen case LISTENER_MASTER:
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen /* we'll just replace the previous master.. */
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_master_connection_set_fd(l->master, fd);
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen auth_master_connection_send_handshake(l->master);
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen break;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen }
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen }
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen}
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainenvoid auth_master_connection_add_listener(struct auth_master_connection *conn,
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen int fd, const char *path,
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen enum listener_type type)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen{
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen struct auth_listener *l;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen l = i_new(struct auth_listener, 1);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen l->master = conn;
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen l->type = type;
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}
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen
70905e51a5148bd5613cb04720807177474a2496Timo Sirainenstatic void auth_listener_destroy(struct auth_listener *l)
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen{
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen struct auth_listener **lp;
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen size_t i, size;
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen lp = buffer_get_modifyable_data(l->master->listeners_buf, &size);
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen size /= sizeof(*lp);
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen for (i = 0; i < size; i++) {
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen if (lp[i] == l) {
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen buffer_delete(l->master->listeners_buf,
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen i * sizeof(l), sizeof(l));
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen break;
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen }
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen }
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen net_disconnect(l->fd);
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen io_remove(l->io);
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen if (l->path != NULL) {
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen (void)unlink(l->path);
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen i_free(l->path);
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen }
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen i_free(l);
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen}
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainenvoid auth_master_connections_send_handshake(void)
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen{
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen struct auth_master_connection *const *conns;
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen unsigned int i, count;
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen conns = array_get(&master_connections, &count);
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen for (i = 0; i < count; i++)
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen auth_master_connection_send_handshake(conns[i]);
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen}
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainenvoid auth_master_connections_init(void)
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen{
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen ARRAY_CREATE(&master_connections, default_pool,
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen struct auth_master_connection *, 16);
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen}
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainenvoid auth_master_connections_deinit(void)
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen{
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen struct auth_master_connection *const *conns;
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen unsigned int i, count;
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen conns = array_get(&master_connections, &count);
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen for (i = count; i > 0; i--)
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen auth_master_connection_destroy(conns[i]);
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen array_free(&master_connections);
645397402d1d0c755cd485ecf721b59b6babc874Timo Sirainen}