auth-master-connection.c revision 16f816d3f3c32ae3351834253f52ddd0212bcbf3
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher/* Copyright (C) 2002 Timo Sirainen */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher#include "common.h"
33396dc46ea52c18f47db1b5d590880806521005Sumit Bose#include "array.h"
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher#include "buffer.h"
33396dc46ea52c18f47db1b5d590880806521005Sumit Bose#include "hash.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "str.h"
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose#include "ioloop.h"
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose#include "istream.h"
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose#include "ostream.h"
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose#include "network.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "userdb.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "auth-request-handler.h"
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher#include "auth-master-interface.h"
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher#include "auth-client-connection.h"
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher#include "auth-master-listener.h"
e65df5b966b27e13283c65f59f99ac44781e0333Simo Sorce#include "auth-master-connection.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include <unistd.h>
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include <stdlib.h>
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#define MAX_INBUF_SIZE 1024
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#define MAX_OUTBUF_SIZE (1024*50)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagherstruct master_userdb_request {
cc98edd9479d4622634a1275c98058916c14059aStephen Gallagher struct auth_master_connection *conn;
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher unsigned int id;
cc98edd9479d4622634a1275c98058916c14059aStephen Gallagher struct auth_request *auth_request;
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina};
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březinastatic int master_output(void *context);
1183d29d87c5c7439cf2364b7d7324d4a13b6e35Stephen Gallagher
1183d29d87c5c7439cf2364b7d7324d4a13b6e35Stephen Gallaghervoid auth_master_request_callback(const char *reply, void *context)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct auth_master_connection *conn = context;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct const_iovec iov[2];
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (conn->listener->auth->verbose_debug)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_info("master out: %s", reply);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher iov[0].iov_base = reply;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher iov[0].iov_len = strlen(reply);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher iov[1].iov_base = "\n";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher iov[1].iov_len = 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (void)o_stream_sendv(conn->output, iov, 2);
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce}
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorcestatic int
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorcemaster_input_request(struct auth_master_connection *conn, const char *args)
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce{
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce struct auth_client_connection *client_conn;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *const *list;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int id, client_pid, client_id;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* <id> <client-pid> <client-id> */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher list = t_strsplit(args, "\t");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (list[0] == NULL || list[1] == NULL || list[2] == NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_error("BUG: Master sent broken REQUEST");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return FALSE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher id = (unsigned int)strtoul(list[0], NULL, 10);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher client_pid = (unsigned int)strtoul(list[1], NULL, 10);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher client_id = (unsigned int)strtoul(list[2], NULL, 10);
d921c1eba437662437847279f251a0a5d8f70127Maxim
d921c1eba437662437847279f251a0a5d8f70127Maxim client_conn = auth_client_connection_lookup(conn->listener, client_pid);
d921c1eba437662437847279f251a0a5d8f70127Maxim if (client_conn == NULL) {
d921c1eba437662437847279f251a0a5d8f70127Maxim i_error("Master requested auth for nonexisting client %u",
d921c1eba437662437847279f251a0a5d8f70127Maxim client_pid);
d921c1eba437662437847279f251a0a5d8f70127Maxim (void)o_stream_send_str(conn->output,
d921c1eba437662437847279f251a0a5d8f70127Maxim t_strdup_printf("NOTFOUND\t%u\n", id));
327127bb7fcc07f882209f029e14026de1b23c94Maxim } else {
327127bb7fcc07f882209f029e14026de1b23c94Maxim auth_request_handler_master_request(
327127bb7fcc07f882209f029e14026de1b23c94Maxim client_conn->request_handler, conn, id, client_id);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina return TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagheruser_callback(const char *result, struct auth_request *auth_request)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct auth_master_connection *conn = auth_request->context;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce string_t *str;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str = t_str_new(128);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (result == NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str_printfa(str, "NOTFOUND\t%u\n", auth_request->id);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher else {
4b6a0d0b3d42e5fdb457f47d9adfa5e66b160256Stephen Gallagher str_printfa(str, "USER\t%u\t", auth_request->id);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str_append(str, result);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str_append_c(str, '\n');
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (void)o_stream_send(conn->output, str_data(str), str_len(str));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher auth_request_unref(auth_request);
068dbee9ca7bf5b37330eff91c94ae10f288d09fJakub Hrozek}
98ce3c3e85a4bb2e1822bf8ab2a1c2ab9e3dd61dJakub Hrozek
be65f065fef1d387281096ef095a2acef39ecc12Jakub Hrozekstatic int
e124844907ed6973915e4d56f5442ecd07535a12Jakub Hrozekmaster_input_user(struct auth_master_connection *conn, const char *args)
f36078af138f052cd9a30360867b0ebd0805af5eJakub Hrozek{
34c78b745eb349eef2b0f13ef2b722632aebe619Jan Cholasta struct auth_request *auth_request;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *const *list, *name, *arg;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* <id> <userid> [<parameters>] */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher list = t_strsplit(args, "\t");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (list[0] == NULL || list[1] == NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_error("BUG: Master sent broken USER");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return FALSE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher auth_request = auth_request_new_dummy(conn->listener->auth);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher auth_request->id = (unsigned int)strtoul(list[0], NULL, 10);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher auth_request->user = p_strdup(auth_request->pool, list[1]);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher auth_request->context = conn;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (list += 2; *list != NULL; list++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher arg = strchr(*list, '=');
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (arg == NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher name = *list;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher arg = "";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher name = t_strdup_until(*list, arg);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher arg++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek (void)auth_request_import(auth_request, name, arg);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher if (auth_request->service == NULL) {
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher i_error("BUG: Master sent USER request without service");
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher auth_request_unref(auth_request);
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher return FALSE;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher }
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher auth_request_lookup_user(auth_request, user_callback);
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher return TRUE;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher}
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagherstatic int
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallaghermaster_input_die(struct auth_master_connection *conn)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek return TRUE;
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek}
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozekstatic void master_input(void *context)
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct auth_master_connection *conn = context;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher char *line;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher switch (i_stream_read(conn->input)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher case 0:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher case -1:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* disconnected */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher auth_master_connection_destroy(conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher case -2:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* buffer full */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_error("BUG: Master sent us more than %d bytes",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (int)MAX_INBUF_SIZE);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher auth_master_connection_destroy(conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek if (!conn->version_received) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher line = i_stream_next_line(conn->input);
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek if (line == NULL)
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek return;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek /* make sure the major version matches */
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek if (strncmp(line, "VERSION\t", 8) != 0 ||
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek atoi(t_strcut(line + 8, '\t')) !=
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek AUTH_MASTER_PROTOCOL_MAJOR_VERSION) {
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek i_error("Master not compatible with this server "
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek "(mixed old and new binaries?)");
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek auth_master_connection_destroy(conn);
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek return;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek }
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek conn->version_received = TRUE;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek }
6f51c802311fd81a409a26763ed45b28a3234d0dJakub Hrozek
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek while ((line = i_stream_next_line(conn->input)) != NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (conn->listener->auth->verbose_debug)
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek i_info("master in: %s", line);
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher
f5b6f977d4144c28e9c66f3f1c9d634d595d1117Marko Myllynen t_push();
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strncmp(line, "REQUEST\t", 8) == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = master_input_request(conn, line + 8);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher else if (strncmp(line, "USER\t", 5) == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = master_input_user(conn, line + 5);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher else if (strcmp(line, "DIE") == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = master_input_die(conn);
72e60fd4eabcfbcdbfe01e8c38b94052bc6c2067Jakub Hrozek else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* ignore unknown command */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher t_pop();
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!ret) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher auth_master_connection_destroy(conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
5352c9b3609bca63814f9f6f03dbbbadf6c6333aStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int master_output(void *context)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek struct auth_master_connection *conn = context;
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek int ret;
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek if ((ret = o_stream_flush(conn->output)) < 0) {
505383ec905863bb8f4f563f694b9bf077f9002cJakub Hrozek /* transmit error, probably master died */
505383ec905863bb8f4f563f694b9bf077f9002cJakub Hrozek auth_master_connection_destroy(conn);
172c07013d1ea99447a780fd36f49d5c3a76981bJakub Hrozek return 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (o_stream_get_buffer_used_size(conn->output) <= MAX_OUTBUF_SIZE/2) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* allow input again */
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce conn->io = io_add(conn->fd, IO_READ, master_input, conn);
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce }
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce return 1;
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce}
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce
336879aabae137f9a81304f147fb0d43001654b0Simo Sorcestruct auth_master_connection *
336879aabae137f9a81304f147fb0d43001654b0Simo Sorceauth_master_connection_create(struct auth_master_listener *listener, int fd)
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce{
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce struct auth_master_connection *conn;
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce conn = i_new(struct auth_master_connection, 1);
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce conn->listener = listener;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->fd = fd;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->input = i_stream_create_file(fd, default_pool,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MAX_INBUF_SIZE, FALSE);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->output = o_stream_create_file(fd, default_pool,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (size_t)-1, FALSE);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher o_stream_set_flush_callback(conn->output, master_output, conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conn->io = io_add(fd, IO_READ, master_input, conn);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_append(&listener->masters, &conn, 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return conn;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervoid auth_master_connection_send_handshake(struct auth_master_connection *conn)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *line;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
96c73559adfbdac96720008fc022cb1d540b53c3Jakub Hrozek if (conn->output == NULL)
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher return;
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek
f660877b38e563c4aa0cb1431624069808873fecJakub Hrozek line = t_strdup_printf("VERSION\t%u\t%u\nSPID\t%u\n",
f660877b38e563c4aa0cb1431624069808873fecJakub Hrozek AUTH_MASTER_PROTOCOL_MAJOR_VERSION,
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher AUTH_MASTER_PROTOCOL_MINOR_VERSION,
conn->listener->pid);
(void)o_stream_send_str(conn->output, line);
}
void auth_master_connection_destroy(struct auth_master_connection *conn)
{
struct auth_master_connection *const *conns;
unsigned int i, count;
if (conn->destroyed)
return;
conn->destroyed = TRUE;
if (conn->fd != -1) {
if (close(conn->fd) < 0)
i_error("close(): %m");
}
if (conn->input != NULL)
i_stream_unref(conn->input);
if (conn->output != NULL)
o_stream_unref(conn->output);
if (conn->io != NULL)
io_remove(conn->io);
conns = array_get(&conn->listener->masters, &count);
for (i = 0; i < count; i++) {
if (conns[i] == conn) {
array_delete(&conn->listener->masters, i, 1);
break;
}
}
if (!standalone && auth_master_listeners_masters_left() == 0)
io_loop_stop(ioloop);
i_free(conn);
}