auth-worker-client.c revision 938835576b218f6bb9498d829cef9514f8609c6f
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "common.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "base64.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "ioloop.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "network.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "istream.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "ostream.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "str.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "auth-request.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "auth-worker-client.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include <stdlib.h>
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#define OUTBUF_THROTTLE_SIZE (1024*10)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct auth_worker_client {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int refcount;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth *auth;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int fd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct io *io;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct istream *input;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct ostream *output;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschauth_worker_client_check_throttle(struct auth_worker_client *client)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (o_stream_get_buffer_used_size(client->output) >=
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch OUTBUF_THROTTLE_SIZE) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* stop reading new requests until client has read the pending
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch replies. */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (client->io != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch io_remove(&client->io);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic struct auth_request *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschworker_auth_request_new(struct auth_worker_client *client, unsigned int id,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *args)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_request *auth_request;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *key, *value, *const *tmp;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request = auth_request_new_dummy(client->auth);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch client->refcount++;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request->context = client;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request->id = id;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (args != NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch for (tmp = t_strsplit(args, "\t"); *tmp != NULL; tmp++) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch value = strchr(*tmp, '=');
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (value == NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch continue;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch key = t_strdup_until(*tmp, value);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch value++;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch (void)auth_request_import(auth_request, key, value);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return auth_request;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschadd_userdb_replies(struct auth_stream_reply *reply,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_stream_reply *userdb_reply)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
499ca6dc5d746fd7a7efc6d497deede89553669fStephan Bosch const char *const *tmp;
499ca6dc5d746fd7a7efc6d497deede89553669fStephan Bosch
499ca6dc5d746fd7a7efc6d497deede89553669fStephan Bosch tmp = auth_stream_split(userdb_reply);
499ca6dc5d746fd7a7efc6d497deede89553669fStephan Bosch i_assert(*tmp != NULL);
499ca6dc5d746fd7a7efc6d497deede89553669fStephan Bosch /* first field is the user name */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch tmp++;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch for (; *tmp != NULL; tmp++) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_import(reply,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch t_strconcat("userdb_", *tmp, NULL));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void auth_worker_send_reply(struct auth_worker_client *client,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch string_t *str)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (shutdown_request)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch o_stream_send_str(client->output, "SHUTDOWN\n");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch o_stream_send(client->output, str_data(str), str_len(str));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void verify_plain_callback(enum passdb_result result,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_request *request)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_worker_client *client = request->context;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_stream_reply *reply;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch string_t *str;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (request->passdb_failure && result == PASSDB_RESULT_OK)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch result = PASSDB_RESULT_PASSWORD_MISMATCH;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch reply = auth_stream_reply_init(pool_datastack_create());
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_add(reply, NULL, dec2str(request->id));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (result == PASSDB_RESULT_OK)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_add(reply, "OK", NULL);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch else {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_add(reply, "FAIL", NULL);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_add(reply, NULL,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch t_strdup_printf("%d", result));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (result != PASSDB_RESULT_INTERNAL_FAILURE) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_add(reply, NULL, request->user);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_add(reply, NULL,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch request->passdb_password == NULL ? "" :
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch request->passdb_password);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (request->no_password)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_add(reply, "nopassword", NULL);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (request->extra_fields != NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *fields =
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_export(request->extra_fields);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_import(reply, fields);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (request->extra_cache_fields != NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *fields =
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_export(request->extra_cache_fields);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_import(reply, fields);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str = auth_stream_reply_get_str(reply);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str_append_c(str, '\n');
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_send_reply(client, str);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request_unref(&request);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_client_check_throttle(client);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_client_unref(&client);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschauth_worker_handle_passv(struct auth_worker_client *client,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int id, const char *args)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* verify plaintext password */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_request *auth_request;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_passdb *passdb;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *password;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int passdb_id;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch passdb_id = atoi(t_strcut(args, '\t'));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch args = strchr(args, '\t');
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (args == NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("BUG: Auth worker server sent us invalid PASSV");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch args++;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch password = t_strcut(args, '\t');
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch args = strchr(args, '\t');
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (args != NULL) args++;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request = worker_auth_request_new(client, id, args);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request->mech_password =
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch p_strdup(auth_request->pool, password);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (auth_request->user == NULL || auth_request->service == NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("BUG: PASSV had missing parameters");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request_unref(&auth_request);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch passdb = auth_request->passdb;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch while (passdb != NULL && passdb->id != passdb_id)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch passdb = passdb->next;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (passdb == NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* could be a masterdb */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch passdb = auth_request->auth->masterdbs;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch while (passdb != NULL && passdb->id != passdb_id)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch passdb = passdb->next;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (passdb == NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("BUG: PASSV had invalid passdb ID");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request_unref(&auth_request);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request->passdb = passdb;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch passdb->passdb->iface.
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch verify_plain(auth_request, password, verify_plain_callback);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschlookup_credentials_callback(enum passdb_result result,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const unsigned char *credentials, size_t size,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_request *request)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_worker_client *client = request->context;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_stream_reply *reply;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch string_t *str;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (request->passdb_failure && result == PASSDB_RESULT_OK)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch result = PASSDB_RESULT_PASSWORD_MISMATCH;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch reply = auth_stream_reply_init(pool_datastack_create());
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_add(reply, NULL, dec2str(request->id));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (result != PASSDB_RESULT_OK) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_add(reply, "FAIL", NULL);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_add(reply, NULL,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch t_strdup_printf("%d", result));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch } else {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_add(reply, "OK", NULL);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_add(reply, NULL, request->user);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
9249c80276766fdc4d31fc3eebc22fba7d53d77cStephan Bosch str = t_str_new(64);
9249c80276766fdc4d31fc3eebc22fba7d53d77cStephan Bosch str_printfa(str, "{%s.b64}", request->credentials_scheme);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch base64_encode(credentials, size, str);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_add(reply, NULL, str_c(str));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (request->extra_fields != NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *fields =
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_export(request->extra_fields);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_import(reply, fields);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (request->extra_cache_fields != NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *fields =
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_export(request->extra_cache_fields);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_stream_reply_import(reply, fields);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (request->userdb_reply != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch add_userdb_replies(reply, request->userdb_reply);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str = auth_stream_reply_get_str(reply);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str_append_c(str, '\n');
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_send_reply(client, str);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request_unref(&request);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_client_check_throttle(client);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_client_unref(&client);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschauth_worker_handle_passl(struct auth_worker_client *client,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int id, const char *args)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* lookup credentials */
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch struct auth_request *auth_request;
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch const char *scheme;
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch unsigned int passdb_id;
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch passdb_id = atoi(t_strcut(args, '\t'));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch args = strchr(args, '\t');
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (args == NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("BUG: Auth worker server sent us invalid PASSL");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch args++;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch scheme = t_strcut(args, '\t');
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch args = strchr(args, '\t');
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (args != NULL) args++;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request = worker_auth_request_new(client, id, args);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request->credentials_scheme = p_strdup(auth_request->pool, scheme);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (auth_request->user == NULL || auth_request->service == NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("BUG: PASSL had missing parameters");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request_unref(&auth_request);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch while (auth_request->passdb->id != passdb_id) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request->passdb = auth_request->passdb->next;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (auth_request->passdb == NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("BUG: PASSL had invalid passdb ID");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request_unref(&auth_request);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (auth_request->passdb->passdb->iface.lookup_credentials == NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("BUG: PASSL lookup not supported by given passdb");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request_unref(&auth_request);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request->passdb->passdb->iface.
40a926a1aeae93b3d4944b56eacb013d3059b549Stephan Bosch lookup_credentials(auth_request, lookup_credentials_callback);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschset_credentials_callback(bool success, struct auth_request *request)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_worker_client *client = request->context;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch string_t *str;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str = t_str_new(64);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str_printfa(str, "%u\t%s\n", request->id, success ? "OK" : "FAIL");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_send_reply(client, str);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
6b312949dcd641f1196dd299240dec03b46b5042Stephan Bosch auth_request_unref(&request);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_client_check_throttle(client);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_client_unref(&client);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void
b85a1bcaa9f82dd5b326967da5f1a26595173ee9Stephan Boschauth_worker_handle_setcred(struct auth_worker_client *client,
b85a1bcaa9f82dd5b326967da5f1a26595173ee9Stephan Bosch unsigned int id, const char *args)
b85a1bcaa9f82dd5b326967da5f1a26595173ee9Stephan Bosch{
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Bosch struct auth_request *auth_request;
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Bosch unsigned int passdb_id;
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Bosch const char *data;
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Bosch
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Bosch passdb_id = atoi(t_strcut(args, '\t'));
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Bosch args = strchr(args, '\t');
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Bosch if (args == NULL) {
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Bosch i_error("BUG: Auth worker server sent us invalid SETCRED");
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Bosch return;
b85a1bcaa9f82dd5b326967da5f1a26595173ee9Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch args++;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
55f1e5a6f22a7ea13a12b17be715e661e7f02471Stephan Bosch data = t_strcut(args, '\t');
55f1e5a6f22a7ea13a12b17be715e661e7f02471Stephan Bosch args = strchr(args, '\t');
55f1e5a6f22a7ea13a12b17be715e661e7f02471Stephan Bosch if (args != NULL) args++;
55f1e5a6f22a7ea13a12b17be715e661e7f02471Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request = worker_auth_request_new(client, id, args);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (auth_request->user == NULL || auth_request->service == NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("BUG: SETCRED had missing parameters");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request_unref(&auth_request);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch while (auth_request->passdb->id != passdb_id) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request->passdb = auth_request->passdb->next;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (auth_request->passdb == NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("BUG: SETCRED had invalid passdb ID");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request_unref(&auth_request);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request->passdb->passdb->iface.
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch set_credentials(auth_request, data, set_credentials_callback);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschlookup_user_callback(enum userdb_result result,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_request *auth_request)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_worker_client *client = auth_request->context;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_stream_reply *reply = auth_request->userdb_reply;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch string_t *str;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (auth_request->userdb_lookup_failed)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch result = USERDB_RESULT_INTERNAL_FAILURE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str = t_str_new(128);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str_printfa(str, "%u\t", auth_request->id);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch switch (result) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case USERDB_RESULT_INTERNAL_FAILURE:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str_append(str, "FAIL\t");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case USERDB_RESULT_USER_UNKNOWN:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str_append(str, "NOTFOUND\t");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case USERDB_RESULT_OK:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str_append(str, "OK\t");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str_append(str, auth_stream_reply_export(reply));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str_append_c(str, '\n');
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_send_reply(client, str);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request_unref(&auth_request);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_client_check_throttle(client);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_client_unref(&client);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschauth_worker_handle_user(struct auth_worker_client *client,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int id, const char *args)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* lookup user */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_request *auth_request;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int num;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch num = atoi(t_strcut(args, '\t'));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch args = strchr(args, '\t');
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (args != NULL) args++;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request = worker_auth_request_new(client, id, args);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (auth_request->user == NULL || auth_request->service == NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("BUG: USER had missing parameters");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request_unref(&auth_request);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch for (; num > 0; num--) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request->userdb = auth_request->userdb->next;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (auth_request->userdb == NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("BUG: USER had invalid userdb num");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request_unref(&auth_request);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_request->userdb->userdb->iface->
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch lookup(auth_request, lookup_user_callback);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic bool
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschauth_worker_handle_line(struct auth_worker_client *client, const char *line)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *p;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int id;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch p = strchr(line, '\t');
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (p == NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return FALSE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch id = (unsigned int)strtoul(t_strdup_until(line, p), NULL, 10);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch line = p + 1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (strncmp(line, "PASSV\t", 6) == 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_handle_passv(client, id, line + 6);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch else if (strncmp(line, "PASSL\t", 6) == 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_handle_passl(client, id, line + 6);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch else if (strncmp(line, "SETCRED\t", 8) == 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_handle_setcred(client, id, line + 8);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch else if (strncmp(line, "USER\t", 5) == 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_handle_user(client, id, line + 5);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return TRUE;
e69ac57b1a97e56011e988564985728be31bfb2aStephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void auth_worker_input(struct auth_worker_client *client)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch char *line;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch bool ret;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch switch (i_stream_read(client->input)) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case 0:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case -1:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* disconnected */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_client_destroy(&client);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case -2:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* buffer full */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("BUG: Auth worker server sent us more than %d bytes",
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch (int)AUTH_WORKER_MAX_LINE_LENGTH);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_client_destroy(&client);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch client->refcount++;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch while ((line = i_stream_next_line(client->input)) != NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch T_BEGIN {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ret = auth_worker_handle_line(client, line);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch } T_END;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (!ret) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_client_destroy(&client);
3aabd70db569ee56c48ad3a8d216091e7cb07215Stephan Bosch break;
3aabd70db569ee56c48ad3a8d216091e7cb07215Stephan Bosch }
3aabd70db569ee56c48ad3a8d216091e7cb07215Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_client_unref(&client);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic int auth_worker_output(struct auth_worker_client *client)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (o_stream_flush(client->output) < 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_client_destroy(&client);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return 1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (o_stream_get_buffer_used_size(client->output) <=
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch OUTBUF_THROTTLE_SIZE/3 && client->io == NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* allow input again */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch client->io = io_add(client->fd, IO_READ,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch auth_worker_input, client);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return 1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct auth_worker_client *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschauth_worker_client_create(struct auth *auth, int fd)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_worker_client *client;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch client = i_new(struct auth_worker_client, 1);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch client->refcount = 1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch client->auth = auth;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch client->fd = fd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch client->input = i_stream_create_fd(fd, AUTH_WORKER_MAX_LINE_LENGTH,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch FALSE);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch client->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch o_stream_set_flush_callback(client->output, auth_worker_output, client);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch client->io = io_add(fd, IO_READ, auth_worker_input, client);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return client;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid auth_worker_client_destroy(struct auth_worker_client **_client)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct auth_worker_client *client = *_client;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch *_client = NULL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (client->fd == -1)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_close(client->input);
o_stream_close(client->output);
if (client->io != NULL)
io_remove(&client->io);
net_disconnect(client->fd);
client->fd = -1;
io_loop_stop(ioloop);
}
void auth_worker_client_unref(struct auth_worker_client **_client)
{
struct auth_worker_client *client = *_client;
if (--client->refcount > 0) {
*_client = NULL;
return;
}
if (client->fd != -1)
auth_worker_client_destroy(_client);
i_stream_unref(&client->input);
o_stream_unref(&client->output);
i_free(client);
}