auth-master-connection.c revision 137ea7ca34005345aa2304a940149b7f3774d727
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (C) 2002 Timo Sirainen */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "common.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "array.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "buffer.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "hash.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "str.h"
a991cfe2157e58ee43bc580f517ce9ef0dfb7acfStephan Bosch#include "ioloop.h"
de0181258ab66b527ad8dc7e51a8efa76b4658d0Stephan Bosch#include "istream.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "ostream.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "network.h"
86ab71bf134573e45dd9ab6bde9d55da4c44fc48Timo Sirainen#include "userdb.h"
0d5c9a80e91a4073d5fd6820e9ddce2755221f64Stephan Bosch#include "auth-request-handler.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "auth-master-interface.h"
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch#include "auth-client-connection.h"
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch#include "auth-master-listener.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "auth-master-connection.h"
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include <unistd.h>
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include <stdlib.h>
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen#define MAX_INBUF_SIZE 1024
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen#define MAX_OUTBUF_SIZE (1024*50)
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainenstruct master_userdb_request {
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen struct auth_master_connection *conn;
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen unsigned int id;
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen struct auth_request *auth_request;
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen};
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainenstatic int master_output(void *context);
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid auth_master_request_callback(const char *reply, void *context)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct auth_master_connection *conn = context;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct const_iovec iov[2];
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (conn->listener->auth->verbose_debug)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch i_info("master out: %s", reply);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch iov[0].iov_base = reply;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch iov[0].iov_len = strlen(reply);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch iov[1].iov_base = "\n";
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch iov[1].iov_len = 1;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch (void)o_stream_sendv(conn->output, iov, 2);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic int
7384b4e78eaab44693c985192276e31322155e32Stephan Boschmaster_input_request(struct auth_master_connection *conn, const char *args)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct auth_client_connection *client_conn;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const char *const *list;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch unsigned int id, client_pid, client_id;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* <id> <client-pid> <client-id> */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch list = t_strsplit(args, "\t");
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (list[0] == NULL || list[1] == NULL || list[2] == NULL) {
d6a88217c273cc67f5de93949bdd065a15eeabe0Stephan Bosch i_error("BUG: Master sent broken REQUEST");
9145c8b5eda526d05bd4a7ced20f6f6f2ff8df03Stephan Bosch return FALSE;
9145c8b5eda526d05bd4a7ced20f6f6f2ff8df03Stephan Bosch }
9145c8b5eda526d05bd4a7ced20f6f6f2ff8df03Stephan Bosch
7abab3b191860a3d77af5192b0649833c8a0c803Stephan Bosch id = (unsigned int)strtoul(list[0], NULL, 10);
7abab3b191860a3d77af5192b0649833c8a0c803Stephan Bosch client_pid = (unsigned int)strtoul(list[1], NULL, 10);
7abab3b191860a3d77af5192b0649833c8a0c803Stephan Bosch client_id = (unsigned int)strtoul(list[2], NULL, 10);
7abab3b191860a3d77af5192b0649833c8a0c803Stephan Bosch
7abab3b191860a3d77af5192b0649833c8a0c803Stephan Bosch client_conn = auth_client_connection_lookup(conn->listener, client_pid);
7a358ecd8918d1280a0b68cdf348c23f6721c799Stephan Bosch if (client_conn == NULL) {
7a358ecd8918d1280a0b68cdf348c23f6721c799Stephan Bosch i_error("Master requested auth for nonexisting client %u",
7abab3b191860a3d77af5192b0649833c8a0c803Stephan Bosch client_pid);
7abab3b191860a3d77af5192b0649833c8a0c803Stephan Bosch (void)o_stream_send_str(conn->output,
7abab3b191860a3d77af5192b0649833c8a0c803Stephan Bosch t_strdup_printf("NOTFOUND\t%u\n", id));
7abab3b191860a3d77af5192b0649833c8a0c803Stephan Bosch } else {
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch auth_request_handler_master_request(
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch client_conn->request_handler, conn, id, client_id);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return TRUE;
47a53a80656dc400ff8effdc1432a69fbf5ae8baTimo Sirainen}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic void
7384b4e78eaab44693c985192276e31322155e32Stephan Boschuser_callback(struct auth_stream_reply *reply,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct auth_request *auth_request)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct auth_master_connection *conn = auth_request->context;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch string_t *str;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
47a53a80656dc400ff8effdc1432a69fbf5ae8baTimo Sirainen str = t_str_new(128);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (reply == NULL)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch str_printfa(str, "NOTFOUND\t%u\n", auth_request->id);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch else {
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch str_printfa(str, "USER\t%u\t", auth_request->id);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch str_append(str, auth_stream_reply_export(reply));
5b6bfa39481f719c1fd6ed3febeaf7f0be9e8886Timo Sirainen str_append_c(str, '\n');
5b6bfa39481f719c1fd6ed3febeaf7f0be9e8886Timo Sirainen }
5b6bfa39481f719c1fd6ed3febeaf7f0be9e8886Timo Sirainen (void)o_stream_send(conn->output, str_data(str), str_len(str));
5b6bfa39481f719c1fd6ed3febeaf7f0be9e8886Timo Sirainen auth_request_unref(auth_request);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic int
7384b4e78eaab44693c985192276e31322155e32Stephan Boschmaster_input_user(struct auth_master_connection *conn, const char *args)
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch{
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch struct auth_request *auth_request;
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch const char *const *list, *name, *arg;
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch /* <id> <userid> [<parameters>] */
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch list = t_strsplit(args, "\t");
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch if (list[0] == NULL || list[1] == NULL) {
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch i_error("BUG: Master sent broken USER");
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch return FALSE;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch }
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch auth_request = auth_request_new_dummy(conn->listener->auth);
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch auth_request->id = (unsigned int)strtoul(list[0], NULL, 10);
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch auth_request->user = p_strdup(auth_request->pool, list[1]);
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch auth_request->context = conn;
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch for (list += 2; *list != NULL; list++) {
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch arg = strchr(*list, '=');
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch if (arg == NULL) {
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch name = *list;
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch arg = "";
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch } else {
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch name = t_strdup_until(*list, arg);
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch arg++;
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch }
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch (void)auth_request_import(auth_request, name, arg);
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch }
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch if (auth_request->service == NULL) {
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch i_error("BUG: Master sent USER request without service");
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch auth_request_unref(auth_request);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch return FALSE;
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch }
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch auth_request_lookup_user(auth_request, user_callback);
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch return TRUE;
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch}
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch
e46130f48a6962734bfde7e71906d3894bedf45bStephan Boschstatic int
e46130f48a6962734bfde7e71906d3894bedf45bStephan Boschmaster_input_die(struct auth_master_connection *conn)
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch{
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch return TRUE;
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch}
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch
e46130f48a6962734bfde7e71906d3894bedf45bStephan Boschstatic void master_input(void *context)
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch{
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch struct auth_master_connection *conn = context;
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch char *line;
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch int ret;
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch switch (i_stream_read(conn->input)) {
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch case 0:
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch return;
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch case -1:
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch /* disconnected */
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch auth_master_connection_destroy(conn);
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch return;
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch case -2:
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch /* buffer full */
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch i_error("BUG: Master sent us more than %d bytes",
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch (int)MAX_INBUF_SIZE);
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch auth_master_connection_destroy(conn);
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch return;
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch }
e46130f48a6962734bfde7e71906d3894bedf45bStephan Bosch
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch if (!conn->version_received) {
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch line = i_stream_next_line(conn->input);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch if (line == NULL)
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch return;
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch /* make sure the major version matches */
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch if (strncmp(line, "VERSION\t", 8) != 0 ||
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch atoi(t_strcut(line + 8, '\t')) !=
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch AUTH_MASTER_PROTOCOL_MAJOR_VERSION) {
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch i_error("Master not compatible with this server "
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch "(mixed old and new binaries?)");
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch auth_master_connection_destroy(conn);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch return;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch }
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch conn->version_received = TRUE;
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch }
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch while ((line = i_stream_next_line(conn->input)) != NULL) {
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch if (conn->listener->auth->verbose_debug)
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch i_info("master in: %s", line);
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch t_push();
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch if (strncmp(line, "REQUEST\t", 8) == 0)
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch ret = master_input_request(conn, line + 8);
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch else if (strncmp(line, "USER\t", 5) == 0)
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch ret = master_input_user(conn, line + 5);
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch else if (strcmp(line, "DIE") == 0)
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch ret = master_input_die(conn);
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch else {
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch /* ignore unknown command */
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch ret = TRUE;
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch }
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch t_pop();
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch if (!ret) {
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch auth_master_connection_destroy(conn);
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch return;
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch }
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch }
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch}
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Boschstatic int master_output(void *context)
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch{
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch struct auth_master_connection *conn = context;
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch int ret;
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch if ((ret = o_stream_flush(conn->output)) < 0) {
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch /* transmit error, probably master died */
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch auth_master_connection_destroy(conn);
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch return 1;
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch }
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch if (o_stream_get_buffer_used_size(conn->output) <= MAX_OUTBUF_SIZE/2) {
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch /* allow input again */
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch conn->io = io_add(conn->fd, IO_READ, master_input, conn);
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch }
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch return 1;
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch}
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Boschstruct auth_master_connection *
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Boschauth_master_connection_create(struct auth_master_listener *listener, int fd)
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct auth_master_connection *conn;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
e9228a3918aa0243eff4aae1ff5462bd3198417fTimo Sirainen conn = i_new(struct auth_master_connection, 1);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch conn->listener = listener;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch conn->fd = fd;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch conn->input = i_stream_create_file(fd, default_pool,
d1f964d3f1dd9c5868b134c4f44dd63f3722eef7Timo Sirainen MAX_INBUF_SIZE, FALSE);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch conn->output = o_stream_create_file(fd, default_pool,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch (size_t)-1, FALSE);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch o_stream_set_flush_callback(conn->output, master_output, conn);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch conn->io = io_add(fd, IO_READ, master_input, conn);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch array_append(&listener->masters, &conn, 1);
d1f964d3f1dd9c5868b134c4f44dd63f3722eef7Timo Sirainen return conn;
d1f964d3f1dd9c5868b134c4f44dd63f3722eef7Timo Sirainen}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
d1f964d3f1dd9c5868b134c4f44dd63f3722eef7Timo Sirainenvoid auth_master_connection_send_handshake(struct auth_master_connection *conn)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
79f8a20424633e806447bc9375a5ab403aabc758Stephan Bosch const char *line;
79f8a20424633e806447bc9375a5ab403aabc758Stephan Bosch
79f8a20424633e806447bc9375a5ab403aabc758Stephan Bosch if (conn->output == NULL)
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch return;
3e9055cee8e331a84522dd1e65d0d0e09a4e8803Stephan Bosch
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch line = t_strdup_printf("VERSION\t%u\t%u\nSPID\t%u\n",
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch AUTH_MASTER_PROTOCOL_MAJOR_VERSION,
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch AUTH_MASTER_PROTOCOL_MINOR_VERSION,
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch conn->listener->pid);
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainen (void)o_stream_send_str(conn->output, line);
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainen}
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainen
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainenvoid auth_master_connection_destroy(struct auth_master_connection *conn)
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainen{
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch struct auth_master_connection *const *conns;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch unsigned int i, count;
a991cfe2157e58ee43bc580f517ce9ef0dfb7acfStephan Bosch
fb1be3de0159d6a10e916ad992e2bc53be64c6d5Timo Sirainen if (conn->destroyed)
fb1be3de0159d6a10e916ad992e2bc53be64c6d5Timo Sirainen return;
129596c93692b21d6c6b1313b389774af24c2983Stephan Bosch conn->destroyed = TRUE;
fca68889b287d8eed4babe72a231bd6079da012dStephan Bosch
204ee6ed414f5e4eeb6f6c10763b55daf56f11acJosef 'Jeff' Sipek if (conn->fd != -1) {
204ee6ed414f5e4eeb6f6c10763b55daf56f11acJosef 'Jeff' Sipek if (close(conn->fd) < 0)
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch i_error("close(): %m");
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (conn->input != NULL)
d1f964d3f1dd9c5868b134c4f44dd63f3722eef7Timo Sirainen i_stream_unref(conn->input);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (conn->output != NULL)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch o_stream_unref(conn->output);
79f8a20424633e806447bc9375a5ab403aabc758Stephan Bosch if (conn->io != NULL)
79f8a20424633e806447bc9375a5ab403aabc758Stephan Bosch io_remove(conn->io);
79f8a20424633e806447bc9375a5ab403aabc758Stephan Bosch
79f8a20424633e806447bc9375a5ab403aabc758Stephan Bosch conns = array_get(&conn->listener->masters, &count);
79f8a20424633e806447bc9375a5ab403aabc758Stephan Bosch for (i = 0; i < count; i++) {
d1f964d3f1dd9c5868b134c4f44dd63f3722eef7Timo Sirainen if (conns[i] == conn) {
d1f964d3f1dd9c5868b134c4f44dd63f3722eef7Timo Sirainen array_delete(&conn->listener->masters, i, 1);
79f8a20424633e806447bc9375a5ab403aabc758Stephan Bosch break;
79f8a20424633e806447bc9375a5ab403aabc758Stephan Bosch }
79f8a20424633e806447bc9375a5ab403aabc758Stephan Bosch }
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch if (!standalone && auth_master_listeners_masters_left() == 0)
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch io_loop_stop(ioloop);
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch i_free(conn);
79f8a20424633e806447bc9375a5ab403aabc758Stephan Bosch}
79f8a20424633e806447bc9375a5ab403aabc758Stephan Bosch