auth-worker-client.c revision 5afc76d0215c5f7631dec06ef864d59f0686a0a8
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen/* Copyright (c) 2005-2013 Dovecot authors, see the included COPYING file */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "auth-common.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "base64.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "ioloop.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "net.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "istream.h"
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen#include "ostream.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "hex-binary.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "str.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "strescape.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "process-title.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "master-service.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "auth-request.h"
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen#include "auth-worker-client.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include <stdlib.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define OUTBUF_THROTTLE_SIZE (1024*10)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define CLIENT_STATE_HANDSHAKE "handshaking"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define CLIENT_STATE_ITER "iterating users"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define CLIENT_STATE_IDLE "idling"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define CLIENT_STATE_STOP "waiting for shutdown"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstruct auth_worker_client {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen int refcount;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct auth *auth;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen int fd;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct io *io;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct istream *input;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct ostream *output;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct timeout *to_idle;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen unsigned int version_received:1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen unsigned int dbhash_received:1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen unsigned int error_sent:1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen};
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstruct auth_worker_list_context {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct auth_worker_client *client;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct auth_request *auth_request;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct userdb_iterate_context *iter;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen bool sending, sent, done;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen};
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstruct auth_worker_client *auth_worker_client;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic bool auth_worker_client_error = FALSE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void auth_worker_input(struct auth_worker_client *client);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic int auth_worker_output(struct auth_worker_client *client);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenvoid auth_worker_refresh_proctitle(const char *state)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (!global_auth_settings->verbose_proctitle || !worker)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (auth_worker_client_error)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen state = "error";
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen else if (auth_worker_client == NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen state = "waiting for connection";
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen process_title_set(t_strdup_printf("worker: %s", state));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenauth_worker_client_check_throttle(struct auth_worker_client *client)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (o_stream_get_buffer_used_size(client->output) >=
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen OUTBUF_THROTTLE_SIZE) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* stop reading new requests until client has read the pending
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen replies. */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (client->io != NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen io_remove(&client->io);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic struct auth_request *
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenworker_auth_request_new(struct auth_worker_client *client, unsigned int id,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *const *args)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct auth_request *auth_request;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *key, *value;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen auth_request = auth_request_new_dummy();
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->refcount++;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen auth_request->context = client;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen auth_request->id = id;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen for (; *args != NULL; args++) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen value = strchr(*args, '=');
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (value == NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen (void)auth_request_import(auth_request, *args, NULL);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen else {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen key = t_strdup_until(*args, value++);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen (void)auth_request_import(auth_request, key, value);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen auth_request_init(auth_request);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return auth_request;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void auth_worker_send_reply(struct auth_worker_client *client,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen string_t *str)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (worker_restart_request)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen o_stream_nsend_str(client->output, "RESTART\n");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen o_stream_nsend(client->output, str_data(str), str_len(str));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenreply_append_extra_fields(string_t *str, struct auth_request *request)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (!auth_fields_is_empty(request->extra_fields)) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen str_append_c(str, '\t');
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen auth_fields_append(request->extra_fields, str, 0, 0);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (request->userdb_reply != NULL &&
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen auth_fields_is_empty(request->userdb_reply)) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* all userdb_* fields had NULL values. we'll still
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen need to tell this to the master */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen str_append(str, "\tuserdb_"AUTH_REQUEST_USER_KEY_IGNORE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void verify_plain_callback(enum passdb_result result,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct auth_request *request)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct auth_worker_client *client = request->context;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen string_t *str;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (request->failed && result == PASSDB_RESULT_OK)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen result = PASSDB_RESULT_PASSWORD_MISMATCH;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen str = t_str_new(128);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen str_printfa(str, "%u\t", request->id);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (result == PASSDB_RESULT_OK)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen str_append(str, "OK");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen else
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen str_printfa(str, "FAIL\t%d", result);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (result != PASSDB_RESULT_INTERNAL_FAILURE) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen str_append_c(str, '\t');
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen str_append_tabescaped(str, request->user);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen str_append_c(str, '\t');
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (request->passdb_password != NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen str_append_tabescaped(str, request->passdb_password);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen reply_append_extra_fields(str, request);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen str_append_c(str, '\n');
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen auth_worker_send_reply(client, str);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen auth_request_unref(&request);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen auth_worker_client_check_throttle(client);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen auth_worker_client_unref(&client);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic bool
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenauth_worker_handle_passv(struct auth_worker_client *client,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen unsigned int id, const char *const *args)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* verify plaintext password */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct auth_request *auth_request;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct auth_passdb *passdb;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *password;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen unsigned int passdb_id;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* <passdb id> <password> [<args>] */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (str_to_uint(args[0], &passdb_id) < 0 || args[1] == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("BUG: Auth worker server sent us invalid PASSV");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen password = args[1];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request = worker_auth_request_new(client, id, args + 2);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request->mech_password =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p_strdup(auth_request->pool, password);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (auth_request->user == NULL || auth_request->service == NULL) {
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen i_error("BUG: PASSV had missing parameters");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request_unref(&auth_request);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen passdb = auth_request->passdb;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (passdb != NULL && passdb->passdb->id != passdb_id)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen passdb = passdb->next;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (passdb == NULL) {
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen /* could be a masterdb */
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen passdb = auth_request_get_auth(auth_request)->masterdbs;
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen while (passdb != NULL && passdb->passdb->id != passdb_id)
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen passdb = passdb->next;
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen if (passdb == NULL) {
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen i_error("BUG: PASSV had invalid passdb ID");
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen auth_request_unref(&auth_request);
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen return FALSE;
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen }
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen }
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen auth_request->passdb = passdb;
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen passdb->passdb->iface.
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen verify_plain(auth_request, password, verify_plain_callback);
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen return TRUE;
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen}
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainen
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainenstatic void
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainenlookup_credentials_callback(enum passdb_result result,
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen const unsigned char *credentials, size_t size,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct auth_request *request)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct auth_worker_client *client = request->context;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen string_t *str;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (request->failed && result == PASSDB_RESULT_OK)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen result = PASSDB_RESULT_PASSWORD_MISMATCH;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen str = t_str_new(128);
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen str_printfa(str, "%u\t", request->id);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (result != PASSDB_RESULT_OK)
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen str_printfa(str, "FAIL\t%d", result);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen else {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen str_append(str, "OK\t");
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen str_append_tabescaped(str, request->user);
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen str_printfa(str, "\t{%s.b64}", request->credentials_scheme);
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen base64_encode(credentials, size, str);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen reply_append_extra_fields(str, request);
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen }
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen str_append_c(str, '\n');
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen auth_worker_send_reply(client, str);
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen auth_request_unref(&request);
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen auth_worker_client_check_throttle(client);
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen auth_worker_client_unref(&client);
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen}
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainenstatic bool
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainenauth_worker_handle_passl(struct auth_worker_client *client,
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen unsigned int id, const char *const *args)
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen{
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen /* lookup credentials */
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen struct auth_request *auth_request;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen const char *scheme;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen unsigned int passdb_id;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen /* <passdb id> <scheme> [<args>] */
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (str_to_uint(args[0], &passdb_id) < 0 || args[1] == NULL) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen i_error("BUG: Auth worker server sent us invalid PASSL");
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen return FALSE;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen }
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen scheme = args[1];
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request = worker_auth_request_new(client, id, args + 2);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request->credentials_scheme = p_strdup(auth_request->pool, scheme);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (auth_request->user == NULL || auth_request->service == NULL) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen i_error("BUG: PASSL had missing parameters");
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request_unref(&auth_request);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen return FALSE;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen }
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen while (auth_request->passdb->passdb->id != passdb_id) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request->passdb = auth_request->passdb->next;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (auth_request->passdb == NULL) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen i_error("BUG: PASSL had invalid passdb ID");
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request_unref(&auth_request);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen return FALSE;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen }
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen }
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (auth_request->passdb->passdb->iface.lookup_credentials == NULL) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen i_error("BUG: PASSL lookup not supported by given passdb");
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request_unref(&auth_request);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen return FALSE;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen }
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request->prefer_plain_credentials = TRUE;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request->passdb->passdb->iface.
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen lookup_credentials(auth_request, lookup_credentials_callback);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen return TRUE;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen}
0db4290d60bfa00774f628276d38654c56abd68cTimo Sirainen
0db4290d60bfa00774f628276d38654c56abd68cTimo Sirainenstatic void
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenset_credentials_callback(bool success, struct auth_request *request)
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen{
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen struct auth_worker_client *client = request->context;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen string_t *str;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen str = t_str_new(64);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen str_printfa(str, "%u\t%s\n", request->id, success ? "OK" : "FAIL");
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_worker_send_reply(client, str);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request_unref(&request);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_worker_client_check_throttle(client);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_worker_client_unref(&client);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen}
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenstatic bool
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenauth_worker_handle_setcred(struct auth_worker_client *client,
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen unsigned int id, const char *const *args)
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen{
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen struct auth_request *auth_request;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen unsigned int passdb_id;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen const char *creds;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen /* <passdb id> <credentials> [<args>] */
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (str_to_uint(args[0], &passdb_id) < 0 || args[1] == NULL) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen i_error("BUG: Auth worker server sent us invalid SETCRED");
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen return FALSE;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen }
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen creds = args[1];
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen auth_request = worker_auth_request_new(client, id, args + 2);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (auth_request->user == NULL || auth_request->service == NULL) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen i_error("BUG: SETCRED had missing parameters");
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request_unref(&auth_request);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen return FALSE;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen }
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen while (auth_request->passdb->passdb->id != passdb_id) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request->passdb = auth_request->passdb->next;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (auth_request->passdb == NULL) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen i_error("BUG: SETCRED had invalid passdb ID");
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request_unref(&auth_request);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen return FALSE;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen }
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen }
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request->passdb->passdb->iface.
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen set_credentials(auth_request, creds, set_credentials_callback);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen return TRUE;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen}
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenstatic void
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenlookup_user_callback(enum userdb_result result,
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen struct auth_request *auth_request)
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen{
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen struct auth_worker_client *client = auth_request->context;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen string_t *str;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen str = t_str_new(128);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen str_printfa(str, "%u\t", auth_request->id);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen switch (result) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen case USERDB_RESULT_INTERNAL_FAILURE:
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen str_append(str, "FAIL\t");
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen break;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen case USERDB_RESULT_USER_UNKNOWN:
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen str_append(str, "NOTFOUND\t");
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen break;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen case USERDB_RESULT_OK:
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen str_append(str, "OK\t");
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_fields_append(auth_request->userdb_reply, str, 0, 0);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (auth_request->userdb_lookup_failed)
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen str_append(str, "\ttempfail");
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen break;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen }
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen str_append_c(str, '\n');
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_worker_send_reply(client, str);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request_unref(&auth_request);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_worker_client_check_throttle(client);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_worker_client_unref(&client);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen}
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenstatic struct auth_userdb *
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenauth_userdb_find_by_id(struct auth_userdb *userdbs, unsigned int id)
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen{
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen struct auth_userdb *db;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen for (db = userdbs; db != NULL; db = db->next) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (db->userdb->id == id)
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen return db;
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen }
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen return NULL;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen}
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenstatic bool
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenauth_worker_handle_user(struct auth_worker_client *client,
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen unsigned int id, const char *const *args)
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen{
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen /* lookup user */
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen struct auth_request *auth_request;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen unsigned int userdb_id;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen /* <userdb id> [<args>] */
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (str_to_uint(args[0], &userdb_id) < 0) {
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen i_error("BUG: Auth worker server sent us invalid USER");
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen return FALSE;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen }
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request = worker_auth_request_new(client, id, args + 1);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (auth_request->user == NULL || auth_request->service == NULL) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_error("BUG: USER had missing parameters");
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen auth_request_unref(&auth_request);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen }
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen auth_request->userdb =
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen auth_userdb_find_by_id(auth_request->userdb, userdb_id);
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen if (auth_request->userdb == NULL) {
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen i_error("BUG: USER had invalid userdb ID");
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen auth_request_unref(&auth_request);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request->userdb->userdb->iface->
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lookup(auth_request, lookup_user_callback);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenauth_worker_client_idle_kill(struct auth_worker_client *client ATTR_UNUSED)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen auth_worker_client_send_shutdown();
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainenstatic void
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainenauth_worker_client_set_idle_timeout(struct auth_worker_client *client)
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int idle_kill_secs;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen i_assert(client->to_idle == NULL);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen idle_kill_secs = master_service_get_idle_kill_secs(master_service);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (idle_kill_secs > 0) {
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen client->to_idle = timeout_add(idle_kill_secs * 1000,
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen auth_worker_client_idle_kill,
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen client);
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen }
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen}
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainenstatic void list_iter_deinit(struct auth_worker_list_context *ctx)
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen{
e1ca7af110ea6eeb6303bdd8f07c172b11dff2faTimo Sirainen struct auth_worker_client *client = ctx->client;
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen string_t *str;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen i_assert(client->io == NULL);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen str = t_str_new(32);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen if (ctx->auth_request->userdb->userdb->iface->
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen iterate_deinit(ctx->iter) < 0)
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen str_printfa(str, "%u\tFAIL\n", ctx->auth_request->id);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen else
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen str_printfa(str, "%u\tOK\n", ctx->auth_request->id);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen auth_worker_send_reply(client, str);
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen client->io = io_add(client->fd, IO_READ, auth_worker_input, client);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen auth_worker_client_set_idle_timeout(client);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen o_stream_set_flush_callback(client->output, auth_worker_output, client);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_request_unref(&ctx->auth_request);
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen auth_worker_client_unref(&client);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen i_free(ctx);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen}
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainenstatic void list_iter_callback(const char *user, void *context)
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen{
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen struct auth_worker_list_context *ctx = context;
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen string_t *str;
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen if (user == NULL) {
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen if (ctx->sending)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen ctx->done = TRUE;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen else
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen list_iter_deinit(ctx);
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen return;
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen }
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (!ctx->sending)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen o_stream_cork(ctx->client->output);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen T_BEGIN {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str = t_str_new(128);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_printfa(str, "%u\t*\t%s\n", ctx->auth_request->id, user);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen o_stream_nsend(ctx->client->output, str_data(str), str_len(str));
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen } T_END;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen
770cbd7d71f9e97256ecfcd8bfc134f7f048dafcTimo Sirainen if (ctx->sending) {
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen /* avoid recursively looping to this same function */
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen ctx->sent = TRUE;
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen return;
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen }
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen do {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->sending = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->sent = FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen T_BEGIN {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen ctx->auth_request->userdb->userdb->iface->
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen iterate_next(ctx->iter);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen } T_END;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (o_stream_get_buffer_used_size(ctx->client->output) > OUTBUF_THROTTLE_SIZE) {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (o_stream_flush(ctx->client->output) < 0) {
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen ctx->done = TRUE;
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen break;
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen }
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen }
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen } while (ctx->sent &&
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen o_stream_get_buffer_used_size(ctx->client->output) <= OUTBUF_THROTTLE_SIZE);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen o_stream_uncork(ctx->client->output);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen ctx->sending = FALSE;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (ctx->done)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen list_iter_deinit(ctx);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen else
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen o_stream_set_flush_pending(ctx->client->output, TRUE);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen}
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainenstatic int auth_worker_list_output(struct auth_worker_list_context *ctx)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen{
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen int ret;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if ((ret = o_stream_flush(ctx->client->output)) < 0) {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen list_iter_deinit(ctx);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen return 1;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen }
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (ret > 0) T_BEGIN {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen ctx->auth_request->userdb->userdb->iface->
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen iterate_next(ctx->iter);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen } T_END;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen return 1;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen}
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainenstatic bool
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainenauth_worker_handle_list(struct auth_worker_client *client,
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen unsigned int id, const char *const *args)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen{
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen struct auth_worker_list_context *ctx;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen struct auth_userdb *userdb;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen unsigned int userdb_id;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen if (str_to_uint(args[0], &userdb_id) < 0) {
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen i_error("BUG: Auth worker server sent us invalid LIST");
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen return FALSE;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen }
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen userdb = auth_userdb_find_by_id(client->auth->userdbs, userdb_id);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen if (userdb == NULL) {
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen i_error("BUG: LIST had invalid userdb ID");
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen return FALSE;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen }
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen ctx = i_new(struct auth_worker_list_context, 1);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen ctx->client = client;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen ctx->auth_request = worker_auth_request_new(client, id, args + 1);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen ctx->auth_request->userdb = userdb;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen if (ctx->auth_request->user == NULL ||
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen ctx->auth_request->service == NULL) {
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen i_error("BUG: LIST had missing parameters");
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen auth_request_unref(&ctx->auth_request);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen i_free(ctx);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen return FALSE;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen }
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen io_remove(&ctx->client->io);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen if (ctx->client->to_idle != NULL)
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen timeout_remove(&ctx->client->to_idle);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen o_stream_set_flush_callback(ctx->client->output,
659fe5d24825b160cae512538088020d97a60239Timo Sirainen auth_worker_list_output, ctx);
6f66e585998aa88a4b0ccad531d329a103325d57Timo Sirainen ctx->iter = ctx->auth_request->userdb->userdb->iface->
6f66e585998aa88a4b0ccad531d329a103325d57Timo Sirainen iterate_init(ctx->auth_request, list_iter_callback, ctx);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen ctx->auth_request->userdb->userdb->iface->iterate_next(ctx->iter);
6f66e585998aa88a4b0ccad531d329a103325d57Timo Sirainen return TRUE;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen}
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainenstatic bool
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainenauth_worker_handle_line(struct auth_worker_client *client, const char *line)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen{
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen const char *const *args;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen unsigned int id;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen bool ret = FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen args = t_strsplit_tab(line);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (args[0] == NULL || args[1] == NULL || args[2] == NULL ||
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen str_to_uint(args[0], &id) < 0) {
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen i_error("BUG: Invalid input: %s", line);
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen auth_worker_refresh_proctitle(args[1]);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen if (strcmp(args[1], "PASSV") == 0)
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen ret = auth_worker_handle_passv(client, id, args + 2);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen else if (strcmp(args[1], "PASSL") == 0)
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ret = auth_worker_handle_passl(client, id, args + 2);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen else if (strcmp(args[1], "SETCRED") == 0)
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen ret = auth_worker_handle_setcred(client, id, args + 2);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen else if (strcmp(args[1], "USER") == 0)
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen ret = auth_worker_handle_user(client, id, args + 2);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen else if (strcmp(args[1], "LIST") == 0)
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen ret = auth_worker_handle_list(client, id, args + 2);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else {
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen i_error("BUG: Auth-worker received unknown command: %s",
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen args[1]);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen }
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen if (client->io != NULL)
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen return ret;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen}
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainenstatic bool auth_worker_verify_db_hash(const char *line)
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen{
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen string_t *str;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen unsigned char passdb_md5[MD5_RESULTLEN];
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen unsigned char userdb_md5[MD5_RESULTLEN];
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen passdbs_generate_md5(passdb_md5);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen userdbs_generate_md5(userdb_md5);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen str = t_str_new(128);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen str_append(str, "DBHASH\t");
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen binary_to_hex_append(str, passdb_md5, sizeof(passdb_md5));
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen str_append_c(str, '\t');
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen binary_to_hex_append(str, userdb_md5, sizeof(userdb_md5));
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen return strcmp(line, str_c(str)) == 0;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen}
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainenstatic void auth_worker_input(struct auth_worker_client *client)
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen{
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen char *line;
6f66e585998aa88a4b0ccad531d329a103325d57Timo Sirainen bool ret;
6f66e585998aa88a4b0ccad531d329a103325d57Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen switch (i_stream_read(client->input)) {
6f66e585998aa88a4b0ccad531d329a103325d57Timo Sirainen case 0:
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen return;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen case -1:
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen /* disconnected */
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen auth_worker_client_destroy(&client);
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen return;
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen case -2:
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen /* buffer full */
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen i_error("BUG: Auth worker server sent us more than %d bytes",
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen (int)AUTH_WORKER_MAX_LINE_LENGTH);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen auth_worker_client_destroy(&client);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen return;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen }
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen if (!client->version_received) {
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen line = i_stream_next_line(client->input);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen if (line == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen if (!version_string_verify(line, "auth-worker",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen AUTH_WORKER_PROTOCOL_MAJOR_VERSION)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("Auth worker not compatible with this server "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "(mixed old and new binaries?)");
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen auth_worker_client_destroy(&client);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen return;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen }
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen client->version_received = TRUE;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen }
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen if (!client->dbhash_received) {
6f66e585998aa88a4b0ccad531d329a103325d57Timo Sirainen line = i_stream_next_line(client->input);
6f66e585998aa88a4b0ccad531d329a103325d57Timo Sirainen if (line == NULL)
6f66e585998aa88a4b0ccad531d329a103325d57Timo Sirainen return;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
6f66e585998aa88a4b0ccad531d329a103325d57Timo Sirainen if (!auth_worker_verify_db_hash(line)) {
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen i_error("Auth worker sees different passdbs/userdbs "
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen "than auth server. Maybe config just changed "
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen "and this goes away automatically?");
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen auth_worker_client_destroy(&client);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen return;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen }
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen client->dbhash_received = TRUE;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen }
6f66e585998aa88a4b0ccad531d329a103325d57Timo Sirainen
6f66e585998aa88a4b0ccad531d329a103325d57Timo Sirainen client->refcount++;
6f66e585998aa88a4b0ccad531d329a103325d57Timo Sirainen while ((line = i_stream_next_line(client->input)) != NULL) {
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen T_BEGIN {
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen ret = auth_worker_handle_line(client, line);
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen } T_END;
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen
7fb7365a8fad104a17538a73c338ee3d3420e7b0Timo Sirainen if (!ret) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct auth_worker_client *client2 = client;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen auth_worker_client_destroy(&client2);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (client->to_idle != NULL)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen timeout_reset(client->to_idle);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen auth_worker_client_unref(&client);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen}
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainenstatic int auth_worker_output(struct auth_worker_client *client)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (o_stream_flush(client->output) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_worker_client_destroy(&client);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e05181d973025627ba08b631c12c07c3bbc99528Timo Sirainen if (o_stream_get_buffer_used_size(client->output) <=
0b3662995e9fa0d0d857ec5350ce2b1ee6d3b94fTimo Sirainen OUTBUF_THROTTLE_SIZE/3 && client->io == NULL) {
0b3662995e9fa0d0d857ec5350ce2b1ee6d3b94fTimo Sirainen /* allow input again */
0b3662995e9fa0d0d857ec5350ce2b1ee6d3b94fTimo Sirainen client->io = io_add(client->fd, IO_READ,
0b3662995e9fa0d0d857ec5350ce2b1ee6d3b94fTimo Sirainen auth_worker_input, client);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen}
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct auth_worker_client *
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainenauth_worker_client_create(struct auth *auth, int fd)
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct auth_worker_client *client;
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client = i_new(struct auth_worker_client, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client->refcount = 1;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen client->auth = auth;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen client->fd = fd;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen client->input = i_stream_create_fd(fd, AUTH_WORKER_MAX_LINE_LENGTH,
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen FALSE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen o_stream_set_no_error_handling(client->output, TRUE);
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen o_stream_set_flush_callback(client->output, auth_worker_output, client);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client->io = io_add(fd, IO_READ, auth_worker_input, client);
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen auth_worker_client_set_idle_timeout(client);
a87e5f15283e057c7dc26dd9db7b616268c95ca7Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_HANDSHAKE);
a87e5f15283e057c7dc26dd9db7b616268c95ca7Timo Sirainen
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen auth_worker_client = client;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen if (auth_worker_client_error)
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen auth_worker_client_send_error();
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen return client;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen}
a87e5f15283e057c7dc26dd9db7b616268c95ca7Timo Sirainen
a87e5f15283e057c7dc26dd9db7b616268c95ca7Timo Sirainenvoid auth_worker_client_destroy(struct auth_worker_client **_client)
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen{
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen struct auth_worker_client *client = *_client;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen *_client = NULL;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen if (client->fd == -1)
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen return;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen i_stream_close(client->input);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen o_stream_close(client->output);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen if (client->to_idle != NULL)
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen timeout_remove(&client->to_idle);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen if (client->io != NULL)
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen io_remove(&client->io);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen net_disconnect(client->fd);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen client->fd = -1;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen auth_worker_client_unref(&client);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen auth_worker_client = NULL;
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen auth_worker_refresh_proctitle("");
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen master_service_client_connection_destroyed(master_service);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen}
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainenvoid auth_worker_client_unref(struct auth_worker_client **_client)
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen{
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen struct auth_worker_client *client = *_client;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *_client = NULL;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (--client->refcount > 0)
a87e5f15283e057c7dc26dd9db7b616268c95ca7Timo Sirainen return;
a87e5f15283e057c7dc26dd9db7b616268c95ca7Timo Sirainen
a87e5f15283e057c7dc26dd9db7b616268c95ca7Timo Sirainen i_stream_unref(&client->input);
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen o_stream_unref(&client->output);
c93cd163f9c1d4b0ca29f49cbfdbf474caeef5bfTimo Sirainen i_free(client);
c93cd163f9c1d4b0ca29f49cbfdbf474caeef5bfTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid auth_worker_client_send_error(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_worker_client_error = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (auth_worker_client != NULL &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen !auth_worker_client->error_sent) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen o_stream_nsend_str(auth_worker_client->output, "ERROR\n");
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen auth_worker_client->error_sent = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen auth_worker_refresh_proctitle("");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid auth_worker_client_send_success(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen auth_worker_client_error = FALSE;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (auth_worker_client != NULL &&
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen auth_worker_client->error_sent) {
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen o_stream_nsend_str(auth_worker_client->output, "SUCCESS\n");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_worker_client->error_sent = FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (auth_worker_client->io != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid auth_worker_client_send_shutdown(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen if (auth_worker_client != NULL)
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen o_stream_nsend_str(auth_worker_client->output, "SHUTDOWN\n");
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_STOP);
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen}
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen