auth-master-connection.c revision 8eea67470c1bd8562a62e7445d930bb2079b1a43
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
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenstruct auth_listener {
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen struct auth_master_connection *master;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen int client_listener;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen int fd;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen char *path;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen struct io *io;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen};
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstruct master_userdb_request {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_master_connection *conn;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen unsigned int tag;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen};
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenstatic void auth_master_connection_close(struct auth_master_connection *conn);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic int auth_master_connection_unref(struct auth_master_connection *conn);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
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 */
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_master_connection_close(conn);
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 */
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_master_connection_close(conn);
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 */
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_master_connection_close(conn);
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
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainenstatic void master_get_handshake_reply(struct auth_master_connection *master)
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen{
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen struct mech_module_list *list;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen buffer_t *buf;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen struct auth_client_handshake_reply reply;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen struct auth_client_handshake_mech_desc mech_desc;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen uint32_t mech_desc_offset;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen memset(&reply, 0, sizeof(reply));
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen memset(&mech_desc, 0, sizeof(mech_desc));
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen reply.server_pid = master->pid;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen buf = buffer_create_dynamic(default_pool, 128, (size_t)-1);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen for (list = mech_modules; list != NULL; list = list->next)
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen reply.mech_count++;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen buffer_set_used_size(buf, sizeof(reply) +
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen sizeof(mech_desc) * reply.mech_count);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen mech_desc_offset = sizeof(reply);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen for (list = mech_modules; list != NULL; list = list->next) {
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen mech_desc.name_idx = buffer_get_used_size(buf) - sizeof(reply);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen mech_desc.plaintext = list->module.plaintext;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen mech_desc.advertise = list->module.advertise;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen memcpy(buffer_get_space_unsafe(buf, mech_desc_offset,
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen sizeof(mech_desc)),
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen &mech_desc, sizeof(mech_desc));
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen buffer_append(buf, list->module.mech_name,
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen strlen(list->module.mech_name) + 1);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen mech_desc_offset += sizeof(mech_desc);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen }
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
8eea67470c1bd8562a62e7445d930bb2079b1a43Timo Sirainen reply.data_size = buffer_get_used_size(buf) - sizeof(reply);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen memcpy(buffer_get_space_unsafe(buf, 0, sizeof(reply)),
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen &reply, sizeof(reply));
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen master->handshake_reply = buffer_free_without_data(buf);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen}
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenstatic void
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenauth_master_connection_set_fd(struct auth_master_connection *conn, int fd)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen{
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
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen conn->output = o_stream_create_file(fd, default_pool,
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen MAX_OUTBUF_SIZE, FALSE);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen conn->io = io_add(fd, IO_READ, master_input, conn);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen conn->fd = fd;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen}
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstruct auth_master_connection *
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenauth_master_connection_create(int fd, unsigned int pid)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_master_connection *conn;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn = i_new(struct auth_master_connection, 1);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->refcount = 1;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->pid = pid;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->fd = fd;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen conn->listeners_buf =
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen buffer_create_dynamic(default_pool, 64, (size_t)-1);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen if (fd != -1)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_master_connection_set_fd(conn, fd);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen master_get_handshake_reply(conn);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen return conn;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainenvoid auth_master_connection_send_handshake(struct auth_master_connection *conn)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen{
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen struct auth_master_handshake_reply reply;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* just a note to master that we're ok. if we die before,
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen master should shutdown itself. */
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen if (conn->output != NULL) {
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen memset(&reply, 0, sizeof(reply));
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen reply.server_pid = conn->pid;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen o_stream_send(conn->output, &reply, sizeof(reply));
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen }
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen}
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenstatic void auth_master_connection_close(struct auth_master_connection *conn)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen{
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen if (!standalone)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen io_loop_stop(ioloop);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen if (close(conn->fd) < 0)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen i_error("close(): %m");
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen conn->fd = -1;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen o_stream_close(conn->output);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen conn->output = NULL;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen io_remove(conn->io);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen conn->io = NULL;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenvoid auth_master_connection_destroy(struct auth_master_connection *conn)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen struct auth_listener **l;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen size_t i, size;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen if (conn->destroyed)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen conn->destroyed = TRUE;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_client_connections_deinit(conn);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen if (conn->fd != -1)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_master_connection_close(conn);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen l = buffer_get_modifyable_data(conn->listeners_buf, &size);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen size /= sizeof(*l);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen for (i = 0; i < size; i++) {
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen net_disconnect(l[i]->fd);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen io_remove(l[i]->io);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen if (l[i]->path != NULL) {
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen (void)unlink(l[i]->path);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen i_free(l[i]->path);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen }
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen i_free(l[i]);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen }
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen buffer_free(conn->listeners_buf);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen conn->listeners_buf = NULL;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen auth_master_connection_unref(conn);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic int auth_master_connection_unref(struct auth_master_connection *conn)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (--conn->refcount > 0)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return TRUE;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen if (conn->output != NULL)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen o_stream_unref(conn->output);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen i_free(conn->handshake_reply);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen i_free(conn);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return FALSE;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainenstatic void auth_accept(void *context)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen{
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen struct auth_listener *l = context;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen int fd;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen fd = net_accept(l->fd, NULL, NULL);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen if (fd < 0) {
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen if (fd < -1)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen i_fatal("accept() failed: %m");
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen } else {
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen net_set_nonblock(fd, TRUE);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen if (l->client_listener)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen (void)auth_client_connection_create(l->master, fd);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen else {
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen /* we'll just replace the previous master.. */
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_master_connection_set_fd(l->master, fd);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_master_connection_send_handshake(l->master);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen }
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen }
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen}
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainenvoid auth_master_connection_add_listener(struct auth_master_connection *conn,
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen int fd, const char *path, int client)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen{
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen struct auth_listener *l;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen l = i_new(struct auth_listener, 1);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen l->master = conn;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen l->client_listener = client;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen l->fd = fd;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen l->path = i_strdup(path);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen l->io = io_add(fd, IO_READ, auth_accept, l);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen buffer_append(conn->listeners_buf, &l, sizeof(l));
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen}