bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "auth-common.h"
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen#include "base64.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "ioloop.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "net.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "istream.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "ostream.h"
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen#include "hex-binary.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "str.h"
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen#include "strescape.h"
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen#include "process-title.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "master-service.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "auth-request.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "auth-worker-client.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen#define AUTH_WORKER_WARN_DISCONNECTED_LONG_CMD_SECS 30
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#define OUTBUF_THROTTLE_SIZE (1024*10)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen#define CLIENT_STATE_HANDSHAKE "handshaking"
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen#define CLIENT_STATE_ITER "iterating users"
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen#define CLIENT_STATE_IDLE "idling"
12d38e76ba7f70d6219c89ec7416fea0d5de7e02Timo Sirainen#define CLIENT_STATE_STOP "waiting for shutdown"
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstruct auth_worker_client {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen int refcount;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct auth *auth;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen int fd;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct io *io;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct istream *input;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct ostream *output;
3a7113e3e2dac0e333e1a3f62af7d682896f59c6Timo Sirainen struct timeout *to_idle;
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen time_t cmd_start;
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool version_received:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool dbhash_received:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool error_sent:1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen};
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstruct auth_worker_list_context {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct auth_worker_client *client;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen struct auth_request *auth_request;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct userdb_iterate_context *iter;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen bool sending, sent, done;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen};
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainenstruct auth_worker_client *auth_worker_client;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainenstatic bool auth_worker_client_error = FALSE;
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic void auth_worker_input(struct auth_worker_client *client);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic int auth_worker_output(struct auth_worker_client *client);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainenvoid auth_worker_refresh_proctitle(const char *state)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen{
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen if (!global_auth_settings->verbose_proctitle || !worker)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen return;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen if (auth_worker_client_error)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen state = "error";
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen else if (auth_worker_client == NULL)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen state = "waiting for connection";
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen process_title_set(t_strdup_printf("worker: %s", state));
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen}
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenauth_worker_client_check_throttle(struct auth_worker_client *client)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (o_stream_get_buffer_used_size(client->output) >=
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen OUTBUF_THROTTLE_SIZE) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* stop reading new requests until client has read the pending
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen replies. */
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek io_remove(&client->io);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomibool auth_worker_auth_request_new(struct auth_worker_client *client, unsigned int id,
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi const char *const *args, struct auth_request **request_r)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct auth_request *auth_request;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen const char *key, *value;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen auth_request = auth_request_new_dummy();
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen client->refcount++;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen auth_request->context = client;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen auth_request->id = id;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen for (; *args != NULL; args++) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen value = strchr(*args, '=');
83d2e37f065eabe38dc92db485c5ca39ee43ce05Timo Sirainen if (value == NULL)
026d971be5201aed5ccf60138900770e42cf0de5Timo Sirainen (void)auth_request_import(auth_request, *args, "");
83d2e37f065eabe38dc92db485c5ca39ee43ce05Timo Sirainen else {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen key = t_strdup_until(*args, value++);
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen (void)auth_request_import(auth_request, key, value);
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi if (auth_request->user == NULL || auth_request->service == NULL) {
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi auth_request_unref(&auth_request);
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi return FALSE;
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi }
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen /* reset changed-fields, so we'll export only the ones that were
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen changed by this lookup. */
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen auth_fields_snapshot(auth_request->extra_fields);
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen if (auth_request->userdb_reply != NULL)
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen auth_fields_snapshot(auth_request->userdb_reply);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen auth_request_init(auth_request);
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi *request_r = auth_request;
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi return TRUE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
798cfe56c9871262770384da1239162b3800cce1Timo Sirainenstatic void auth_worker_send_reply(struct auth_worker_client *client,
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen struct auth_request *request,
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen string_t *str)
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen{
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen time_t cmd_duration = time(NULL) - client->cmd_start;
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainen const char *p;
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen
3a7113e3e2dac0e333e1a3f62af7d682896f59c6Timo Sirainen if (worker_restart_request)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(client->output, "RESTART\n");
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(client->output, str_data(str), str_len(str));
d1ba8ecbb936ace90179d2292952546708d68f71Timo Sirainen if (o_stream_flush(client->output) < 0 && request != NULL &&
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen cmd_duration > AUTH_WORKER_WARN_DISCONNECTED_LONG_CMD_SECS) {
4b1781e4c64be52e25b5994e5242dbe696cc7d29Timo Sirainen p = i_strchr_to_next(str_c(str), '\t');
4b1781e4c64be52e25b5994e5242dbe696cc7d29Timo Sirainen p = p == NULL ? "BUG" : t_strcut(p, '\t');
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainen
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen i_warning("Auth master disconnected us while handling "
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainen "request for %s for %ld secs (result=%s)",
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainen request->user, (long)cmd_duration, p);
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen }
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen}
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainenstatic void
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainenreply_append_extra_fields(string_t *str, struct auth_request *request)
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen{
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen if (!auth_fields_is_empty(request->extra_fields)) {
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen str_append_c(str, '\t');
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen /* export only the fields changed by this lookup, so the
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen changed-flag gets preserved correctly on the master side as
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen well. */
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen auth_fields_append(request->extra_fields, str,
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen AUTH_FIELD_FLAG_CHANGED,
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen AUTH_FIELD_FLAG_CHANGED);
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen }
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen if (request->userdb_reply != NULL &&
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen auth_fields_is_empty(request->userdb_reply)) {
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen /* all userdb_* fields had NULL values. we'll still
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen need to tell this to the master */
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen str_append(str, "\tuserdb_"AUTH_REQUEST_USER_KEY_IGNORE);
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen }
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen}
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void verify_plain_callback(enum passdb_result result,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct auth_request *request)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct auth_worker_client *client = request->context;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen string_t *str;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen if (request->failed && result == PASSDB_RESULT_OK)
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen result = PASSDB_RESULT_PASSWORD_MISMATCH;
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen str = t_str_new(128);
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen str_printfa(str, "%u\t", request->id);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (result == PASSDB_RESULT_OK)
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi if (auth_fields_exists(request->extra_fields, "noauthenticate"))
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi str_append(str, "NEXT");
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi else
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi str_append(str, "OK");
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen else
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen str_printfa(str, "FAIL\t%d", result);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (result != PASSDB_RESULT_INTERNAL_FAILURE) {
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen str_append_c(str, '\t');
865a82c1e9bba11609835a36674964649025bf77Timo Sirainen if (request->user_changed_by_lookup)
865a82c1e9bba11609835a36674964649025bf77Timo Sirainen str_append_tabescaped(str, request->user);
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen str_append_c(str, '\t');
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen if (request->passdb_password != NULL)
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen str_append_tabescaped(str, request->passdb_password);
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen reply_append_extra_fields(str, request);
5d4855d7b4dcffb6975ed8e3c9c376dac74e5c8aTimo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_append_c(str, '\n');
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen auth_worker_send_reply(client, request, str);
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_unref(&request);
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen auth_worker_client_check_throttle(client);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_worker_client_unref(&client);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainenstatic bool
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenauth_worker_handle_passv(struct auth_worker_client *client,
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen unsigned int id, const char *const *args)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* verify plaintext password */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct auth_request *auth_request;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen struct auth_passdb *passdb;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char *password;
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen unsigned int passdb_id;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* <passdb id> <password> [<args>] */
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (str_to_uint(args[0], &passdb_id) < 0 || args[1] == NULL) {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen i_error("BUG: Auth worker server sent us invalid PASSV");
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return FALSE;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen }
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen password = args[1];
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi if (!auth_worker_auth_request_new(client, id, args + 2, &auth_request)) {
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi i_error("BUG: Auth worker server sent us invalid PASSV");
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return FALSE;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen }
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi auth_request->mech_password =
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi p_strdup(auth_request->pool, password);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen passdb = auth_request->passdb;
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen while (passdb != NULL && passdb->passdb->id != passdb_id)
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen passdb = passdb->next;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen if (passdb == NULL) {
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen /* could be a masterdb */
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen passdb = auth_request_get_auth(auth_request)->masterdbs;
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen while (passdb != NULL && passdb->passdb->id != passdb_id)
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen passdb = passdb->next;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen if (passdb == NULL) {
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen i_error("BUG: PASSV had invalid passdb ID");
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_unref(&auth_request);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return FALSE;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen }
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen }
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen auth_request->passdb = passdb;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen passdb->passdb->iface.
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen verify_plain(auth_request, password, verify_plain_callback);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return TRUE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomistatic bool
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomiauth_worker_handle_passw(struct auth_worker_client *client,
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi unsigned int id, const char *const *args)
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi{
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi struct auth_request *request;
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi string_t *str;
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi const char *password;
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi const char *crypted, *scheme;
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi unsigned int passdb_id;
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi int ret;
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi if (str_to_uint(args[0], &passdb_id) < 0 || args[1] == NULL ||
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi args[2] == NULL) {
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi i_error("BUG: Auth worker server sent us invalid PASSW");
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi return FALSE;
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi }
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi password = args[1];
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi crypted = args[2];
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi scheme = password_get_scheme(&crypted);
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi if (scheme == NULL) {
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi i_error("BUG: Auth worker server sent us invalid PASSW (scheme is NULL)");
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi return FALSE;
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi }
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi if (!auth_worker_auth_request_new(client, id, args + 3, &request)) {
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi i_error("BUG: PASSW had missing parameters");
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi return FALSE;
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi }
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi request->mech_password =
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi p_strdup(request->pool, password);
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi ret = auth_request_password_verify(request, password,
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi crypted, scheme, "cache");
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi str = t_str_new(128);
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi str_printfa(str, "%u\t", request->id);
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi if (ret == 1)
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi str_printfa(str, "OK\t\t");
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi else if (ret == 0)
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi str_printfa(str, "FAIL\t%d", PASSDB_RESULT_PASSWORD_MISMATCH);
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi else
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi str_printfa(str, "FAIL\t%d", PASSDB_RESULT_INTERNAL_FAILURE);
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi str_append_c(str, '\n');
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi auth_worker_send_reply(client, request, str);
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi auth_request_unref(&request);
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi auth_worker_client_check_throttle(client);
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi auth_worker_client_unref(&client);
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi return TRUE;
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi}
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainenstatic void
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainenlookup_credentials_callback(enum passdb_result result,
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen const unsigned char *credentials, size_t size,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct auth_request *request)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct auth_worker_client *client = request->context;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen string_t *str;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen if (request->failed && result == PASSDB_RESULT_OK)
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen result = PASSDB_RESULT_PASSWORD_MISMATCH;
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen str = t_str_new(128);
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen str_printfa(str, "%u\t", request->id);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi if (result != PASSDB_RESULT_OK && result != PASSDB_RESULT_NEXT)
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen str_printfa(str, "FAIL\t%d", result);
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen else {
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi if (result == PASSDB_RESULT_NEXT)
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi str_append(str, "NEXT\t");
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi else
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi str_append(str, "OK\t");
865a82c1e9bba11609835a36674964649025bf77Timo Sirainen if (request->user_changed_by_lookup)
865a82c1e9bba11609835a36674964649025bf77Timo Sirainen str_append_tabescaped(str, request->user);
3db05c8c00faca6ab9ac8391e1d6977365f4d1b3Timo Sirainen str_append_c(str, '\t');
f0ecd925c7feb815c4b9acf84772fcd56c02319bTimo Sirainen if (request->credentials_scheme[0] != '\0') {
3db05c8c00faca6ab9ac8391e1d6977365f4d1b3Timo Sirainen str_printfa(str, "{%s.b64}", request->credentials_scheme);
f0ecd925c7feb815c4b9acf84772fcd56c02319bTimo Sirainen base64_encode(credentials, size, str);
f0ecd925c7feb815c4b9acf84772fcd56c02319bTimo Sirainen } else {
f0ecd925c7feb815c4b9acf84772fcd56c02319bTimo Sirainen i_assert(size == 0);
f0ecd925c7feb815c4b9acf84772fcd56c02319bTimo Sirainen }
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen reply_append_extra_fields(str, request);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_append_c(str, '\n');
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen auth_worker_send_reply(client, request, str);
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_unref(&request);
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen auth_worker_client_check_throttle(client);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_worker_client_unref(&client);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainenstatic bool
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenauth_worker_handle_passl(struct auth_worker_client *client,
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen unsigned int id, const char *const *args)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* lookup credentials */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct auth_request *auth_request;
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen const char *scheme;
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen unsigned int passdb_id;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* <passdb id> <scheme> [<args>] */
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (str_to_uint(args[0], &passdb_id) < 0 || args[1] == NULL) {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen i_error("BUG: Auth worker server sent us invalid PASSL");
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return FALSE;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen }
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen scheme = args[1];
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi if (!auth_worker_auth_request_new(client, id, args + 2, &auth_request)) {
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen i_error("BUG: PASSL had missing parameters");
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return FALSE;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen }
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi auth_request->credentials_scheme = p_strdup(auth_request->pool, scheme);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen while (auth_request->passdb->passdb->id != passdb_id) {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen auth_request->passdb = auth_request->passdb->next;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (auth_request->passdb == NULL) {
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen i_error("BUG: PASSL had invalid passdb ID");
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_unref(&auth_request);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return FALSE;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen }
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen }
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen if (auth_request->passdb->passdb->iface.lookup_credentials == NULL) {
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen i_error("BUG: PASSL lookup not supported by given passdb");
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen auth_request_unref(&auth_request);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return FALSE;
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen }
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen
430c0b0c370bebeeceba2e206be76bc134742f41Timo Sirainen auth_request->prefer_plain_credentials = TRUE;
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen auth_request->passdb->passdb->iface.
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen lookup_credentials(auth_request, lookup_credentials_callback);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return TRUE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainenstatic void
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainenset_credentials_callback(bool success, struct auth_request *request)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen{
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen struct auth_worker_client *client = request->context;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen string_t *str;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen str = t_str_new(64);
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen str_printfa(str, "%u\t%s\n", request->id, success ? "OK" : "FAIL");
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen auth_worker_send_reply(client, request, str);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen auth_request_unref(&request);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen auth_worker_client_check_throttle(client);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen auth_worker_client_unref(&client);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen}
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainenstatic bool
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainenauth_worker_handle_setcred(struct auth_worker_client *client,
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen unsigned int id, const char *const *args)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen{
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen struct auth_request *auth_request;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen unsigned int passdb_id;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen const char *creds;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* <passdb id> <credentials> [<args>] */
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (str_to_uint(args[0], &passdb_id) < 0 || args[1] == NULL) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen i_error("BUG: Auth worker server sent us invalid SETCRED");
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return FALSE;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen creds = args[1];
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi if (!auth_worker_auth_request_new(client, id, args + 2, &auth_request)) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen i_error("BUG: SETCRED had missing parameters");
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return FALSE;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen while (auth_request->passdb->passdb->id != passdb_id) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen auth_request->passdb = auth_request->passdb->next;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (auth_request->passdb == NULL) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen i_error("BUG: SETCRED had invalid passdb ID");
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen auth_request_unref(&auth_request);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return FALSE;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen auth_request->passdb->passdb->iface.
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen set_credentials(auth_request, creds, set_credentials_callback);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return TRUE;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen}
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainenlookup_user_callback(enum userdb_result result,
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen struct auth_request *auth_request)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct auth_worker_client *client = auth_request->context;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen string_t *str;
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen str = t_str_new(128);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_printfa(str, "%u\t", auth_request->id);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen switch (result) {
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen case USERDB_RESULT_INTERNAL_FAILURE:
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen str_append(str, "FAIL\t");
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen break;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen case USERDB_RESULT_USER_UNKNOWN:
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen str_append(str, "NOTFOUND\t");
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen break;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen case USERDB_RESULT_OK:
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen str_append(str, "OK\t");
865a82c1e9bba11609835a36674964649025bf77Timo Sirainen if (auth_request->user_changed_by_lookup)
865a82c1e9bba11609835a36674964649025bf77Timo Sirainen str_append_tabescaped(str, auth_request->user);
75b4cc30566e22675b9e7b19b15a7fd929d8f54cTimo Sirainen str_append_c(str, '\t');
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen /* export only the fields changed by this lookup */
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen auth_fields_append(auth_request->userdb_reply, str,
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen AUTH_FIELD_FLAG_CHANGED,
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen AUTH_FIELD_FLAG_CHANGED);
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen if (auth_request->userdb_lookup_tempfailed)
88e9835c4d8973c62cd4db1ec7324ff46dd3ff15Timo Sirainen str_append(str, "\ttempfail");
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen break;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_append_c(str, '\n');
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen auth_worker_send_reply(client, auth_request, str);
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_unref(&auth_request);
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen auth_worker_client_check_throttle(client);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_worker_client_unref(&client);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainenstatic struct auth_userdb *
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainenauth_userdb_find_by_id(struct auth_userdb *userdbs, unsigned int id)
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen{
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen struct auth_userdb *db;
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen for (db = userdbs; db != NULL; db = db->next) {
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen if (db->userdb->id == id)
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen return db;
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen }
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen return NULL;
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen}
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainenstatic bool
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenauth_worker_handle_user(struct auth_worker_client *client,
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen unsigned int id, const char *const *args)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* lookup user */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct auth_request *auth_request;
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen unsigned int userdb_id;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* <userdb id> [<args>] */
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (str_to_uint(args[0], &userdb_id) < 0) {
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen i_error("BUG: Auth worker server sent us invalid USER");
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen return FALSE;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen }
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi if (!auth_worker_auth_request_new(client, id, args + 1, &auth_request)) {
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen i_error("BUG: USER had missing parameters");
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return FALSE;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen }
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen
6dd436dbf05c6c96fc4b6873bb9b44ede860edd7Timo Sirainen auth_request->userdb_lookup = TRUE;
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen auth_request->userdb =
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen auth_userdb_find_by_id(auth_request->userdb, userdb_id);
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen if (auth_request->userdb == NULL) {
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen i_error("BUG: USER had invalid userdb ID");
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen auth_request_unref(&auth_request);
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen return FALSE;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen }
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
3bfdab77880db25dbdc8bf48c2cfc2d50b98e426Aki Tuomi if (auth_request->userdb_reply == NULL)
3bfdab77880db25dbdc8bf48c2cfc2d50b98e426Aki Tuomi auth_request_init_userdb_reply(auth_request);
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen auth_request->userdb->userdb->iface->
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen lookup(auth_request, lookup_user_callback);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return TRUE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainenstatic void
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainenauth_worker_client_idle_kill(struct auth_worker_client *client ATTR_UNUSED)
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen{
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen auth_worker_client_send_shutdown();
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen}
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainenstatic void
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainenauth_worker_client_set_idle_timeout(struct auth_worker_client *client)
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen{
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen unsigned int idle_kill_secs;
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen i_assert(client->to_idle == NULL);
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen idle_kill_secs = master_service_get_idle_kill_secs(master_service);
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen if (idle_kill_secs > 0) {
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen client->to_idle = timeout_add(idle_kill_secs * 1000,
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen auth_worker_client_idle_kill,
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen client);
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen }
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen}
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic void list_iter_deinit(struct auth_worker_list_context *ctx)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct auth_worker_client *client = ctx->client;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen string_t *str;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
7cba14a4c3beb026a2862ee50d24c554fa713329Timo Sirainen i_assert(client->io == NULL);
7cba14a4c3beb026a2862ee50d24c554fa713329Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen str = t_str_new(32);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen if (ctx->auth_request->userdb->userdb->iface->
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen iterate_deinit(ctx->iter) < 0)
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen str_printfa(str, "%u\tFAIL\n", ctx->auth_request->id);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen else
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen str_printfa(str, "%u\tOK\n", ctx->auth_request->id);
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen auth_worker_send_reply(client, NULL, str);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen client->io = io_add(client->fd, IO_READ, auth_worker_input, client);
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen auth_worker_client_set_idle_timeout(client);
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen o_stream_set_flush_callback(client->output, auth_worker_output, client);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen auth_request_unref(&ctx->auth_request);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen auth_worker_client_unref(&client);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen i_free(ctx);
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic void list_iter_callback(const char *user, void *context)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct auth_worker_list_context *ctx = context;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen string_t *str;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (user == NULL) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (ctx->sending)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->done = TRUE;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen else
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen list_iter_deinit(ctx);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen if (!ctx->sending)
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen o_stream_cork(ctx->client->output);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen T_BEGIN {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen str = t_str_new(128);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen str_printfa(str, "%u\t*\t%s\n", ctx->auth_request->id, user);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(ctx->client->output, str_data(str), str_len(str));
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen } T_END;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (ctx->sending) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* avoid recursively looping to this same function */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->sent = TRUE;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen do {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->sending = TRUE;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->sent = FALSE;
3340fc9aeaa655dc3bb8f329ebdfcb38a5121949Timo Sirainen T_BEGIN {
3340fc9aeaa655dc3bb8f329ebdfcb38a5121949Timo Sirainen ctx->auth_request->userdb->userdb->iface->
3340fc9aeaa655dc3bb8f329ebdfcb38a5121949Timo Sirainen iterate_next(ctx->iter);
3340fc9aeaa655dc3bb8f329ebdfcb38a5121949Timo Sirainen } T_END;
1ce47e48d7231da6f18f02eab6bab6451b4ef12aTimo Sirainen if (o_stream_get_buffer_used_size(ctx->client->output) > OUTBUF_THROTTLE_SIZE) {
1ce47e48d7231da6f18f02eab6bab6451b4ef12aTimo Sirainen if (o_stream_flush(ctx->client->output) < 0) {
1ce47e48d7231da6f18f02eab6bab6451b4ef12aTimo Sirainen ctx->done = TRUE;
1ce47e48d7231da6f18f02eab6bab6451b4ef12aTimo Sirainen break;
1ce47e48d7231da6f18f02eab6bab6451b4ef12aTimo Sirainen }
1ce47e48d7231da6f18f02eab6bab6451b4ef12aTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen } while (ctx->sent &&
1ce47e48d7231da6f18f02eab6bab6451b4ef12aTimo Sirainen o_stream_get_buffer_used_size(ctx->client->output) <= OUTBUF_THROTTLE_SIZE);
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen o_stream_uncork(ctx->client->output);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->sending = FALSE;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (ctx->done)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen list_iter_deinit(ctx);
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen else
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen o_stream_set_flush_pending(ctx->client->output, TRUE);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic int auth_worker_list_output(struct auth_worker_list_context *ctx)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen int ret;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if ((ret = o_stream_flush(ctx->client->output)) < 0) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen list_iter_deinit(ctx);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return 1;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
3340fc9aeaa655dc3bb8f329ebdfcb38a5121949Timo Sirainen if (ret > 0) T_BEGIN {
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen ctx->auth_request->userdb->userdb->iface->
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen iterate_next(ctx->iter);
3340fc9aeaa655dc3bb8f329ebdfcb38a5121949Timo Sirainen } T_END;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return 1;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainenstatic bool
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenauth_worker_handle_list(struct auth_worker_client *client,
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen unsigned int id, const char *const *args)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct auth_worker_list_context *ctx;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct auth_userdb *userdb;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen unsigned int userdb_id;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (str_to_uint(args[0], &userdb_id) < 0) {
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen i_error("BUG: Auth worker server sent us invalid LIST");
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen return FALSE;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen userdb = auth_userdb_find_by_id(client->auth->userdbs, userdb_id);
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen if (userdb == NULL) {
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen i_error("BUG: LIST had invalid userdb ID");
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen return FALSE;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx = i_new(struct auth_worker_list_context, 1);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->client = client;
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi if (!auth_worker_auth_request_new(client, id, args + 1, &ctx->auth_request)) {
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen i_error("BUG: LIST had missing parameters");
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen i_free(ctx);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen return FALSE;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen }
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi ctx->auth_request->userdb = userdb;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen io_remove(&ctx->client->io);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&ctx->client->to_idle);
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen o_stream_set_flush_callback(ctx->client->output,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen auth_worker_list_output, ctx);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen ctx->iter = ctx->auth_request->userdb->userdb->iface->
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen iterate_init(ctx->auth_request, list_iter_callback, ctx);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen ctx->auth_request->userdb->userdb->iface->iterate_next(ctx->iter);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return TRUE;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenauth_worker_handle_line(struct auth_worker_client *client, const char *line)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen const char *const *args;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen unsigned int id;
459b483806babd159daa8b461377281d89bb3bdcTimo Sirainen bool ret = FALSE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
3bfdab77880db25dbdc8bf48c2cfc2d50b98e426Aki Tuomi args = t_strsplit_tabescaped(line);
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (args[0] == NULL || args[1] == NULL || args[2] == NULL ||
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen str_to_uint(args[0], &id) < 0) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen i_error("BUG: Invalid input: %s", line);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return FALSE;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen io_loop_time_refresh();
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen client->cmd_start = ioloop_time;
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen auth_worker_refresh_proctitle(args[1]);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen if (strcmp(args[1], "PASSV") == 0)
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen ret = auth_worker_handle_passv(client, id, args + 2);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen else if (strcmp(args[1], "PASSL") == 0)
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen ret = auth_worker_handle_passl(client, id, args + 2);
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi else if (strcmp(args[1], "PASSW") == 0)
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi ret = auth_worker_handle_passw(client, id, args + 2);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen else if (strcmp(args[1], "SETCRED") == 0)
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen ret = auth_worker_handle_setcred(client, id, args + 2);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen else if (strcmp(args[1], "USER") == 0)
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen ret = auth_worker_handle_user(client, id, args + 2);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen else if (strcmp(args[1], "LIST") == 0)
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen ret = auth_worker_handle_list(client, id, args + 2);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen else {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen i_error("BUG: Auth-worker received unknown command: %s",
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen args[1]);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen }
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen if (client->io != NULL)
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return ret;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainenstatic bool auth_worker_verify_db_hash(const char *line)
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen{
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen string_t *str;
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen unsigned char passdb_md5[MD5_RESULTLEN];
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen unsigned char userdb_md5[MD5_RESULTLEN];
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen passdbs_generate_md5(passdb_md5);
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen userdbs_generate_md5(userdb_md5);
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen str = t_str_new(128);
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen str_append(str, "DBHASH\t");
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen binary_to_hex_append(str, passdb_md5, sizeof(passdb_md5));
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen str_append_c(str, '\t');
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen binary_to_hex_append(str, userdb_md5, sizeof(userdb_md5));
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen return strcmp(line, str_c(str)) == 0;
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen}
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenstatic void auth_worker_input(struct auth_worker_client *client)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen char *line;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen bool ret;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen switch (i_stream_read(client->input)) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen case 0:
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen case -1:
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* disconnected */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_worker_client_destroy(&client);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen case -2:
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* buffer full */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_error("BUG: Auth worker server sent us more than %d bytes",
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen (int)AUTH_WORKER_MAX_LINE_LENGTH);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_worker_client_destroy(&client);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen if (!client->version_received) {
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen line = i_stream_next_line(client->input);
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen if (line == NULL)
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen return;
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen if (!version_string_verify(line, "auth-worker",
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen AUTH_WORKER_PROTOCOL_MAJOR_VERSION)) {
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen i_error("Auth worker not compatible with this server "
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen "(mixed old and new binaries?)");
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen auth_worker_client_destroy(&client);
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen return;
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen }
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen client->version_received = TRUE;
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen }
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen if (!client->dbhash_received) {
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen line = i_stream_next_line(client->input);
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen if (line == NULL)
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen return;
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen if (!auth_worker_verify_db_hash(line)) {
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen i_error("Auth worker sees different passdbs/userdbs "
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen "than auth server. Maybe config just changed "
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen "and this goes away automatically?");
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen auth_worker_client_destroy(&client);
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen return;
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen }
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen client->dbhash_received = TRUE;
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen }
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen client->refcount++;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen while ((line = i_stream_next_line(client->input)) != NULL) {
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ret = auth_worker_handle_line(client, line);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (!ret) {
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen struct auth_worker_client *client2 = client;
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen auth_worker_client_destroy(&client2);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen break;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
02967c39a2f4922fe433718e0f9ef0e6031c432bTimo Sirainen if (client->to_idle != NULL)
02967c39a2f4922fe433718e0f9ef0e6031c432bTimo Sirainen timeout_reset(client->to_idle);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_worker_client_unref(&client);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenstatic int auth_worker_output(struct auth_worker_client *client)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (o_stream_flush(client->output) < 0) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_worker_client_destroy(&client);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return 1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (o_stream_get_buffer_used_size(client->output) <=
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen OUTBUF_THROTTLE_SIZE/3 && client->io == NULL) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* allow input again */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen client->io = io_add(client->fd, IO_READ,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen auth_worker_input, client);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return 1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstruct auth_worker_client *
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenauth_worker_client_create(struct auth *auth, int fd)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct auth_worker_client *client;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen client = i_new(struct auth_worker_client, 1);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen client->refcount = 1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen client->auth = auth;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen client->fd = fd;
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi client->input = i_stream_create_fd(fd, AUTH_WORKER_MAX_LINE_LENGTH);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi client->output = o_stream_create_fd(fd, (size_t)-1);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_set_no_error_handling(client->output, TRUE);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen o_stream_set_flush_callback(client->output, auth_worker_output, client);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen client->io = io_add(fd, IO_READ, auth_worker_input, client);
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen auth_worker_client_set_idle_timeout(client);
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_HANDSHAKE);
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen auth_worker_client = client;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen if (auth_worker_client_error)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen auth_worker_client_send_error();
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return client;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid auth_worker_client_destroy(struct auth_worker_client **_client)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct auth_worker_client *client = *_client;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *_client = NULL;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (client->fd == -1)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_stream_close(client->input);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen o_stream_close(client->output);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&client->to_idle);
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek io_remove(&client->io);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen net_disconnect(client->fd);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen client->fd = -1;
7cba14a4c3beb026a2862ee50d24c554fa713329Timo Sirainen auth_worker_client_unref(&client);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen auth_worker_client = NULL;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen auth_worker_refresh_proctitle("");
7cba14a4c3beb026a2862ee50d24c554fa713329Timo Sirainen master_service_client_connection_destroyed(master_service);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid auth_worker_client_unref(struct auth_worker_client **_client)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct auth_worker_client *client = *_client;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
4e65040b019c061d242c8bc19bf76009679b8a15Timo Sirainen *_client = NULL;
4e65040b019c061d242c8bc19bf76009679b8a15Timo Sirainen
4e65040b019c061d242c8bc19bf76009679b8a15Timo Sirainen if (--client->refcount > 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen i_stream_unref(&client->input);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen o_stream_unref(&client->output);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_free(client);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainenvoid auth_worker_client_send_error(void)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen{
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen auth_worker_client_error = TRUE;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen if (auth_worker_client != NULL &&
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen !auth_worker_client->error_sent) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(auth_worker_client->output, "ERROR\n");
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen auth_worker_client->error_sent = TRUE;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen }
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen auth_worker_refresh_proctitle("");
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen}
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainenvoid auth_worker_client_send_success(void)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen{
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen auth_worker_client_error = FALSE;
a355fad576bc0c95b11161cf48b48d343229a2b3Timo Sirainen if (auth_worker_client == NULL)
a355fad576bc0c95b11161cf48b48d343229a2b3Timo Sirainen return;
a355fad576bc0c95b11161cf48b48d343229a2b3Timo Sirainen if (auth_worker_client->error_sent) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(auth_worker_client->output, "SUCCESS\n");
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen auth_worker_client->error_sent = FALSE;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen }
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen if (auth_worker_client->io != NULL)
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen}
3a7113e3e2dac0e333e1a3f62af7d682896f59c6Timo Sirainen
3a7113e3e2dac0e333e1a3f62af7d682896f59c6Timo Sirainenvoid auth_worker_client_send_shutdown(void)
3a7113e3e2dac0e333e1a3f62af7d682896f59c6Timo Sirainen{
3a7113e3e2dac0e333e1a3f62af7d682896f59c6Timo Sirainen if (auth_worker_client != NULL)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(auth_worker_client->output, "SHUTDOWN\n");
12d38e76ba7f70d6219c89ec7416fea0d5de7e02Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_STOP);
3a7113e3e2dac0e333e1a3f62af7d682896f59c6Timo Sirainen}