auth-master-connection.c revision 76213404317a7ed17bec0beadb5137c82785d816
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "common.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "buffer.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "hash.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "ioloop.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "ostream.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "network.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "mech.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "userdb.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "auth-client-connection.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "auth-master-connection.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen#include <unistd.h>
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#define MAX_OUTBUF_SIZE (1024*50)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic struct auth_master_reply failure_reply =
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstruct master_userdb_request {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_master_connection *conn;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen unsigned int tag;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen};
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic int auth_master_connection_unref(struct auth_master_connection *conn);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic size_t reply_add(buffer_t *buf, const char *str)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen size_t index;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (str == NULL || *str == '\0')
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return (size_t)-1;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen index = buffer_get_used_size(buf) - sizeof(struct auth_master_reply);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen buffer_append(buf, str, strlen(str)+1);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return index;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic struct auth_master_reply *
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenfill_reply(const struct user_data *user, size_t *reply_size)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_master_reply reply, *reply_p;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen buffer_t *buf;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen char *p;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
cd466fe7b84b0223735a6469c7f7bc225f65996dTimo Sirainen buf = buffer_create_dynamic(pool_datastack_create(),
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen sizeof(reply) + 256, (size_t)-1);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen memset(&reply, 0, sizeof(reply));
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen buffer_append(buf, &reply, sizeof(reply));
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply.success = TRUE;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply.uid = user->uid;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply.gid = user->gid;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply.system_user_idx = reply_add(buf, user->system_user);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply.virtual_user_idx = reply_add(buf, user->virtual_user);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply.mail_idx = reply_add(buf, user->mail);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen p = user->home != NULL ? strstr(user->home, "/./") : NULL;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (p == NULL) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply.home_idx = reply_add(buf, user->home);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply.chroot_idx = reply_add(buf, NULL);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen } else {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* wu-ftpd like <chroot>/./<home> */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply.chroot_idx =
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply_add(buf, t_strdup_until(user->home, p));
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply.home_idx = reply_add(buf, p + 3);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen *reply_size = buffer_get_used_size(buf);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply.data_size = *reply_size - sizeof(reply);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply_p = buffer_get_space_unsafe(buf, 0, sizeof(reply));
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen *reply_p = reply;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return reply_p;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic void master_send_reply(struct auth_master_connection *conn,
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_master_reply *reply,
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen size_t reply_size, unsigned int tag)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen ssize_t ret;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply->tag = tag;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen for (;;) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen ret = o_stream_send(conn->output, reply, reply_size);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (ret < 0) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* master died, kill ourself too */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen io_loop_stop(ioloop);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen break;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if ((size_t)ret == reply_size)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen break;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* buffer full, we have to block */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen i_warning("Master transmit buffer full, blocking..");
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (o_stream_flush(conn->output) < 0) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* transmit error, probably master died */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen io_loop_stop(ioloop);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen break;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic void userdb_callback(struct user_data *user, void *context)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct master_userdb_request *master_request = context;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_master_reply *reply;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen size_t reply_size;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (auth_master_connection_unref(master_request->conn)) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (user == NULL) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen master_send_reply(master_request->conn, &failure_reply,
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen sizeof(failure_reply),
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen master_request->tag);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen } else {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply = fill_reply(user, &reply_size);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen master_send_reply(master_request->conn, reply,
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen reply_size, master_request->tag);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen i_free(master_request);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic void master_handle_request(struct auth_master_connection *conn,
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_master_request *request)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_client_connection *client_conn;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_request *auth_request;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct master_userdb_request *master_request;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen client_conn = auth_client_connection_lookup(conn, request->client_pid);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen auth_request = client_conn == NULL ? NULL :
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen hash_lookup(client_conn->auth_requests,
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen POINTER_CAST(request->id));
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (auth_request == NULL) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (verbose) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen i_info("Master request %u.%u not found",
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen request->client_pid, request->id);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen master_send_reply(conn, &failure_reply, sizeof(failure_reply),
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen request->tag);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen } else {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen master_request = i_new(struct master_userdb_request, 1);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen master_request->conn = conn;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen master_request->tag = request->tag;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->refcount++;
3b94ff5951db4d4eddb7a80ed4e3f61207202635Timo Sirainen userdb->lookup(auth_request, userdb_callback,
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen master_request);
7a87427770874f38d1d299635b37d699f9772860Timo Sirainen
7a87427770874f38d1d299635b37d699f9772860Timo Sirainen /* the auth request is finished, we don't need it anymore */
bbef8d37812f877525ca57e7ed206094e1efe288Timo Sirainen mech_request_free(auth_request, request->id);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic void master_input(void *context)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_master_connection *conn = context;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen int ret;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen ret = net_receive(conn->fd,
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->request_buf + conn->request_pos,
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen sizeof(conn->request_buf) - conn->request_pos);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (ret < 0) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* master died, kill ourself too */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen io_loop_stop(ioloop);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->request_pos += ret;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (conn->request_pos >= sizeof(conn->request_buf)) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* reply is now read */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen master_handle_request(conn, (struct auth_master_request *)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->request_buf);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->request_pos = 0;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstruct auth_master_connection *
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenauth_master_connection_new(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;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen conn->listeners_buf =
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen buffer_create_dynamic(default_pool, 64, (size_t)-1);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen if (fd != -1) {
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen conn->output = o_stream_create_file(fd, default_pool,
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen MAX_OUTBUF_SIZE, FALSE);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen conn->io = io_add(fd, IO_READ, master_input, conn);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen }
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen return conn;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainenvoid auth_master_connection_send_handshake(struct auth_master_connection *conn)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* just a note to master that we're ok. if we die before,
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen master should shutdown itself. */
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen if (conn->output != NULL)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen o_stream_send(conn->output, "O", 1);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenvoid auth_master_connection_free(struct auth_master_connection *conn)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen struct auth_client_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
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen if (conn->fd != -1) {
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen if (close(conn->fd) < 0)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen i_error("close(): %m");
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen conn->fd = -1;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen o_stream_close(conn->output);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen io_remove(conn->io);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen conn->io = NULL;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen }
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);
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{
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen struct auth_client_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);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen (void)auth_client_connection_create(l->master, fd);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen }
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen}
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainenvoid auth_master_connection_add_listener(struct auth_master_connection *conn,
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen int fd, const char *path)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen{
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen struct auth_client_listener *l;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen l = i_new(struct auth_client_listener, 1);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen l->master = conn;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen l->fd = fd;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen l->path = i_strdup(path);
76213404317a7ed17bec0beadb5137c82785d816Timo 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}