master-connection.c revision 22535a9e685e29214082878e37a267157044618e
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (C) 2002 Timo Sirainen */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "common.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "buffer.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "hash.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "ioloop.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "ostream.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "network.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "mech.h"
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen#include "userdb.h"
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen#include "login-connection.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "master-connection.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "auth-master-interface.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#define MAX_OUTBUF_SIZE (1024*50)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic struct auth_master_reply failure_reply;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic struct ostream *output;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic struct io *io_master;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
da7f1a07f583df8905684a7b78469960afd7c78dPhil Carmodystatic unsigned int master_pos;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic char master_buf[sizeof(struct auth_master_request)];
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainenstatic size_t reply_add(buffer_t *buf, const char *str)
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen{
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen size_t index;
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen if (str == NULL || *str == '\0')
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen return (size_t)-1;
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen
da7f1a07f583df8905684a7b78469960afd7c78dPhil Carmody index = buffer_get_used_size(buf) - sizeof(struct auth_master_reply);
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen buffer_append(buf, str, strlen(str)+1);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return index;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic struct auth_master_reply *
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenfill_reply(const struct user_data *user, size_t *reply_size)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct auth_master_reply *reply;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen buffer_t *buf;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen buf = buffer_create_dynamic(data_stack_pool,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen sizeof(*reply) + 256, (size_t)-1);
263fa7b43fb222f9805b80f62090907fe3f9ec13Timo Sirainen reply = buffer_append_space(buf, sizeof(*reply));
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen reply->success = TRUE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen reply->chroot = user->chroot;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen reply->uid = user->uid;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen reply->gid = user->gid;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen reply->system_user_idx = reply_add(buf, user->system_user);
f7f25f9e1a38678d0e97d2e609beac16285fac6bTimo Sirainen reply->virtual_user_idx = reply_add(buf, user->virtual_user);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen reply->home_idx = reply_add(buf, user->home);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen reply->mail_idx = reply_add(buf, user->mail);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen *reply_size = buffer_get_used_size(buf);
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen reply->data_size = *reply_size - sizeof(*reply);
35fcdde46a71ac151c2518d48c841019f1181bb2Timo Sirainen return reply;
35fcdde46a71ac151c2518d48c841019f1181bb2Timo Sirainen}
35fcdde46a71ac151c2518d48c841019f1181bb2Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void send_reply(struct auth_master_reply *reply, size_t reply_size,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen unsigned int tag)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ssize_t ret;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen reply->tag = tag;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen for (;;) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ret = o_stream_send(output, reply, reply_size);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (ret < 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* master died, kill ourself too */
5733207dc3ec10e6e5a6e0a8b30fbd1b061062b9Timo Sirainen io_loop_stop(ioloop);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen break;
3e10cd470988298dc2b37f548ad03da4d7c11ffaTimo Sirainen }
009217abb57a24a4076092e8e4e165545747839eStephan Bosch
eb209d12e3b1cfed564c35cf19fdb1bf7fcc6811Timo Sirainen if ((size_t)ret == reply_size)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen break;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* buffer full, we have to block */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_warning("Master transmit buffer full, blocking..");
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (o_stream_flush(output) < 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* transmit error, probably master died */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen io_loop_stop(ioloop);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen break;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
df27aa70a3f0250767eb8a154981cd7f5dadcc91Timo Sirainen }
861f53be0cc2fa5665f3c107a7576e2a53bb2eb0Timo Sirainen}
3e10cd470988298dc2b37f548ad03da4d7c11ffaTimo Sirainen
861f53be0cc2fa5665f3c107a7576e2a53bb2eb0Timo Sirainenstatic void userdb_callback(struct user_data *user, void *context)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen unsigned int tag = POINTER_CAST_TO(context, unsigned int);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct auth_master_reply *reply;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen size_t reply_size;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (user == NULL)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen send_reply(&failure_reply, sizeof(failure_reply), tag);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen else {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen reply = fill_reply(user, &reply_size);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen send_reply(reply, reply_size, tag);
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen }
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen}
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void master_handle_request(struct auth_master_request *request,
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen int fd __attr_unused__)
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen{
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen struct login_connection *login_conn;
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen struct auth_request *auth_request;
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen login_conn = login_connection_lookup(request->login_pid);
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen auth_request = login_conn == NULL ? NULL :
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen hash_lookup(login_conn->auth_requests,
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen POINTER_CAST(request->id));
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen if (request == NULL)
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen send_reply(&failure_reply, sizeof(failure_reply), request->tag);
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen else {
935960e45571872e38f730964f8ca1d116a1b532Timo Sirainen userdb->lookup(auth_request->user, auth_request->realm,
userdb_callback, POINTER_CAST(request->tag));
mech_request_free(login_conn, auth_request, request->id);
}
}
static void master_input(void *context __attr_unused__)
{
int ret;
ret = net_receive(MASTER_SOCKET_FD, master_buf + master_pos,
sizeof(master_buf) - master_pos);
if (ret < 0) {
/* master died, kill ourself too */
io_loop_stop(ioloop);
return;
}
master_pos += ret;
if (master_pos < sizeof(master_buf))
return;
/* reply is now read */
master_handle_request((struct auth_master_request *) master_buf,
MASTER_SOCKET_FD);
master_pos = 0;
}
void master_connection_init(void)
{
memset(&failure_reply, 0, sizeof(failure_reply));
master_pos = 0;
output = o_stream_create_file(MASTER_SOCKET_FD, default_pool,
MAX_OUTBUF_SIZE, IO_PRIORITY_DEFAULT,
FALSE);
io_master = io_add(MASTER_SOCKET_FD, IO_READ, master_input, NULL);
/* just a note to master that we're ok. if we die before,
master should shutdown itself. */
o_stream_send(output, "O", 1);
}
void master_connection_deinit(void)
{
o_stream_unref(output);
io_remove(io_master);
}