auth-worker-client.c revision bd354c19cb93c07ade79477674328a54146ea332
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2005 Timo Sirainen */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "common.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "ioloop.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "network.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "istream.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "ostream.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "str.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "auth-request.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include "auth-worker-client.h"
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#include <stdlib.h>
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen#define OUTBUF_THROTTLE_SIZE (1024*10)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstruct auth_worker_client {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen int refcount;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct auth *auth;
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen int fd;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct io *io;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct istream *input;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct ostream *output;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen};
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic void auth_worker_client_unref(struct auth_worker_client *client);
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic void
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenauth_worker_client_check_throttle(struct auth_worker_client *client)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen{
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (o_stream_get_buffer_used_size(client->output) >=
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen OUTBUF_THROTTLE_SIZE) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* stop reading new requests until client has read the pending
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen replies. */
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen if (client->io != NULL) {
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen io_remove(client->io);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen client->io = NULL;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen}
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic struct auth_request *
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenworker_auth_request_new(struct auth_worker_client *client, unsigned int id,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen const char *args)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen{
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct auth_request *auth_request;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen const char *key, *value, *const *tmp;
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_request = auth_request_new_dummy(client->auth);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen client->refcount++;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_request->context = client;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_request->id = id;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen t_push();
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen for (tmp = t_strsplit(args, "\t"); *tmp != NULL; tmp++) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen value = strchr(*tmp, '=');
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (value == NULL)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen continue;
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen key = t_strdup_until(*tmp, value);
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen value++;
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (strcmp(key, "user") == 0) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_request->user =
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen p_strdup(auth_request->pool, value);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen } else if (strcmp(key, "service") == 0) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_request->service =
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen p_strdup(auth_request->pool, value);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen } else if (strcmp(key, "lip") == 0)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen net_addr2ip(value, &auth_request->local_ip);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen else if (strcmp(key, "rip") == 0)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen net_addr2ip(value, &auth_request->remote_ip);
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen t_pop();
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return auth_request;
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen}
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainenstatic void verify_plain_callback(enum passdb_result result,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct auth_request *request)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen{
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen struct auth_worker_client *client = request->context;
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen string_t *str;
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen str = t_str_new(64);
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen str_printfa(str, "%u\t", request->id);
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (result != PASSDB_RESULT_OK)
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen str_printfa(str, "FAIL\t%d", result);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen else {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen str_append(str, "OK\t");
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen if (request->passdb_password != NULL)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen str_append(str, request->passdb_password);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen str_append_c(str, '\t');
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (request->extra_fields != NULL)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen str_append_str(str, request->extra_fields);
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen str_append_c(str, '\n');
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen o_stream_send(client->output, str_data(str), str_len(str));
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen auth_worker_client_check_throttle(client);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_worker_client_unref(client);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen}
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic void
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenauth_worker_handle_passv(struct auth_worker_client *client,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen unsigned int id, const char *args)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen{
01ca85e6e763cfa0d146166fdd60654f04f51199Timo Sirainen /* verify plaintext password */
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen struct auth_request *auth_request;
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen const char *password;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen unsigned int num;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen num = atoi(t_strcut(args, '\t'));
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen args = strchr(args, '\t');
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (args == NULL) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen i_error("BUG: Auth worker server sent us invalid PASSV");
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen return;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen args++;
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen password = t_strcut(args, '\t');
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen args = strchr(args, '\t');
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (args != NULL) args++;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_request = worker_auth_request_new(client, id, args);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_request->mech_password =
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen p_strdup(auth_request->pool, password);
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen for (; num > 0; num--) {
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen auth_request->passdb = auth_request->passdb->next;
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen if (auth_request->passdb == NULL) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen i_error("BUG: PASSV had invalid passdb num");
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen auth_request->passdb->passdb->verify_plain(auth_request, password,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen verify_plain_callback);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen}
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic void
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenlookup_credentials_callback(enum passdb_result result, const char *credentials,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct auth_request *request)
6cb3c4f4276531258be706821e034f1f0a8cd276Timo Sirainen{
6cb3c4f4276531258be706821e034f1f0a8cd276Timo Sirainen struct auth_worker_client *client = request->context;
6cb3c4f4276531258be706821e034f1f0a8cd276Timo Sirainen string_t *str;
6cb3c4f4276531258be706821e034f1f0a8cd276Timo Sirainen
6cb3c4f4276531258be706821e034f1f0a8cd276Timo Sirainen str = t_str_new(64);
6cb3c4f4276531258be706821e034f1f0a8cd276Timo Sirainen str_printfa(str, "%u\t", request->id);
6cb3c4f4276531258be706821e034f1f0a8cd276Timo Sirainen
6cb3c4f4276531258be706821e034f1f0a8cd276Timo Sirainen if (result != PASSDB_RESULT_OK)
6cb3c4f4276531258be706821e034f1f0a8cd276Timo Sirainen str_printfa(str, "FAIL\t%d", result);
6cb3c4f4276531258be706821e034f1f0a8cd276Timo Sirainen else {
6cb3c4f4276531258be706821e034f1f0a8cd276Timo Sirainen str_printfa(str, "OK\t{%s}%s\t",
01ca85e6e763cfa0d146166fdd60654f04f51199Timo Sirainen passdb_credentials_to_str(request->credentials),
01ca85e6e763cfa0d146166fdd60654f04f51199Timo Sirainen credentials);
01ca85e6e763cfa0d146166fdd60654f04f51199Timo Sirainen if (request->extra_fields != NULL)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen str_append_str(str, request->extra_fields);
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen str_append_c(str, '\n');
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen o_stream_send(client->output, str_data(str), str_len(str));
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_worker_client_check_throttle(client);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_worker_client_unref(client);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen}
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic void
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenauth_worker_handle_passl(struct auth_worker_client *client,
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen unsigned int id, const char *args)
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen{
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* lookup credentials */
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen struct auth_request *auth_request;
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen const char *credentials_str;
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen enum passdb_credentials credentials;
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen unsigned int num;
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen num = atoi(t_strcut(args, '\t'));
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen args = strchr(args, '\t');
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen if (args == NULL) {
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen i_error("BUG: Auth worker server sent us invalid PASSL");
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen return;
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen }
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen args++;
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen credentials_str = t_strcut(args, '\t');
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen args = strchr(args, '\t');
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen if (args != NULL) args++;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen credentials = atoi(credentials_str);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
064ccad9cea2a75a0d6caa2c679b6cd22be58174Timo Sirainen auth_request = worker_auth_request_new(client, id, args);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_request->credentials = credentials;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen for (; num > 0; num--) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_request->passdb = auth_request->passdb->next;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (auth_request->passdb == NULL) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen i_error("BUG: PASSL had invalid passdb num");
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
6cb3c4f4276531258be706821e034f1f0a8cd276Timo Sirainen }
6cb3c4f4276531258be706821e034f1f0a8cd276Timo Sirainen
6cb3c4f4276531258be706821e034f1f0a8cd276Timo Sirainen auth_request->passdb->passdb->
6cb3c4f4276531258be706821e034f1f0a8cd276Timo Sirainen lookup_credentials(auth_request, credentials,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen lookup_credentials_callback);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen}
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic void
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainenlookup_user_callback(const char *result, struct auth_request *auth_request)
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen{
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen struct auth_worker_client *client = auth_request->context;
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen string_t *str;
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen str = t_str_new(64);
51c331377beb4a2acb81aee4d12bc8ef6c496625Timo Sirainen str_printfa(str, "%u\t", auth_request->id);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (result != NULL)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen str_append(str, result);
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen str_append_c(str, '\n');
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen o_stream_send(client->output, str_data(str), str_len(str));
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_worker_client_check_throttle(client);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_worker_client_unref(client);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen}
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic void
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenauth_worker_handle_user(struct auth_worker_client *client,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen unsigned int id, const char *args)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen{
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* lookup user */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct auth_request *auth_request;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen unsigned int num;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen num = atoi(t_strcut(args, '\t'));
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen args = strchr(args, '\t');
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen if (args != NULL) args++;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_request = worker_auth_request_new(client, id, args);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen for (; num > 0; num--) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_request->userdb = auth_request->userdb->next;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (auth_request->userdb == NULL) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen i_error("BUG: USER had invalid userdb num");
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen }
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen auth_request->userdb->userdb->
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen lookup(auth_request, lookup_user_callback);
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen}
c2f2a6cdf7dd55a4aabe72495cabb4deaa59cffcTimo Sirainen
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainenstatic int
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainenauth_worker_handle_line(struct auth_worker_client *client, const char *line)
675b2b1c4587a79478062b05725da61afa5d8045Timo Sirainen{
01ca85e6e763cfa0d146166fdd60654f04f51199Timo Sirainen const char *p;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen unsigned int id;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen p = strchr(line, '\t');
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (p == NULL)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return FALSE;
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen
cc3da53f3a49304a251bfae88f814505326ac210Timo Sirainen id = (unsigned int)strtoul(t_strdup_until(line, p), NULL, 10);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen line = p + 1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (strncmp(line, "PASSV\t", 6) == 0)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_worker_handle_passv(client, id, line + 6);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen else if (strncmp(line, "PASSL\t", 6) == 0)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_worker_handle_passl(client, id, line + 6);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen else if (strncmp(line, "USER\t", 5) == 0)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_worker_handle_user(client, id, line + 5);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
4bd6702bfcb3568959acdb3cb68450aa76ed703bTimo Sirainen return TRUE;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen}
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic void auth_worker_input(void *context)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen{
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct auth_worker_client *client = context;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen char *line;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen int ret;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen switch (i_stream_read(client->input)) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen case 0:
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen return;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen case -1:
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* disconnected */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_worker_client_destroy(client);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen case -2:
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen /* buffer full */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen i_error("BUG: Auth worker server sent us more than %d bytes",
c52eba0224a0ff239f4778a7f6ed5ce38d92a5ddTimo Sirainen (int)AUTH_WORKER_MAX_LINE_LENGTH);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_worker_client_destroy(client);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen client->refcount++;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen while ((line = i_stream_next_line(client->input)) != NULL) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen t_push();
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen ret = auth_worker_handle_line(client, line);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen t_pop();
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (!ret) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_worker_client_destroy(client);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen break;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_worker_client_unref(client);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen}
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic int auth_worker_output(void *context)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen{
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct auth_worker_client *client = context;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen if (o_stream_flush(client->output) < 0) {
200500ebd3c93a5771e7ae2f442659b9acb16eb6Timo Sirainen auth_worker_client_destroy(client);
200500ebd3c93a5771e7ae2f442659b9acb16eb6Timo Sirainen return 1;
200500ebd3c93a5771e7ae2f442659b9acb16eb6Timo Sirainen }
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen if (o_stream_get_buffer_used_size(client->output) <=
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen OUTBUF_THROTTLE_SIZE/3 && client->io == NULL) {
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen /* allow input again */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen client->io = io_add(client->fd, IO_READ,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_worker_input, client);
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return 1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen}
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainen
f3aff3c6bf32d5bb0a61993b76a3fbe5ad798c09Timo Sirainenstruct auth_worker_client *
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenauth_worker_client_create(struct auth *auth, int fd)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen{
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen struct auth_worker_client *client;
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen client = i_new(struct auth_worker_client, 1);
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen client->refcount = 1;
1ff487015234b23c32cf8bb4c9f8c02922535b8eTimo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen client->auth = auth;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen client->fd = fd;
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen client->input =
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen i_stream_create_file(fd, default_pool,
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen AUTH_WORKER_MAX_LINE_LENGTH, FALSE);
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen client->output =
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen o_stream_create_file(fd, default_pool, (size_t)-1, FALSE);
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen o_stream_set_flush_callback(client->output, auth_worker_output, client);
e161a5225abda0837b5deb8746ef808ba5e98d94Timo Sirainen client->io = io_add(fd, IO_READ, auth_worker_input, client);
e161a5225abda0837b5deb8746ef808ba5e98d94Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return client;
e161a5225abda0837b5deb8746ef808ba5e98d94Timo Sirainen}
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainenvoid auth_worker_client_destroy(struct auth_worker_client *client)
15362cdf9df29fef8795e865957e17ec027a9ebfTimo Sirainen{
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen if (client->fd == -1)
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen return;
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen i_stream_close(client->input);
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen o_stream_close(client->output);
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen if (client->io != NULL) {
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen io_remove(client->io);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen client->io = NULL;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen }
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen net_disconnect(client->fd);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen client->fd = -1;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen io_loop_stop(ioloop);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen auth_worker_client_unref(client);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen}
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenstatic void auth_worker_client_unref(struct auth_worker_client *client)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen{
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen if (--client->refcount > 0)
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen return;
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen i_stream_unref(client->input);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen o_stream_unref(client->output);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen i_free(client);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen}
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen