bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen#define AUTH_WORKER_WARN_DISCONNECTED_LONG_CMD_SECS 30
12d38e76ba7f70d6219c89ec7416fea0d5de7e02Timo Sirainen#define CLIENT_STATE_STOP "waiting for shutdown"
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic void auth_worker_input(struct auth_worker_client *client);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic int auth_worker_output(struct auth_worker_client *client);
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainenvoid auth_worker_refresh_proctitle(const char *state)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen if (!global_auth_settings->verbose_proctitle || !worker)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen process_title_set(t_strdup_printf("worker: %s", state));
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenauth_worker_client_check_throttle(struct auth_worker_client *client)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (o_stream_get_buffer_used_size(client->output) >=
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* stop reading new requests until client has read the pending
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)
026d971be5201aed5ccf60138900770e42cf0de5Timo Sirainen (void)auth_request_import(auth_request, *args, "");
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen (void)auth_request_import(auth_request, key, value);
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi if (auth_request->user == NULL || auth_request->service == NULL) {
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 auth_fields_snapshot(auth_request->userdb_reply);
798cfe56c9871262770384da1239162b3800cce1Timo Sirainenstatic void auth_worker_send_reply(struct auth_worker_client *client,
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen time_t cmd_duration = time(NULL) - client->cmd_start;
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainen const char *p;
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) {
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen i_warning("Auth master disconnected us while handling "
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainen "request for %s for %ld secs (result=%s)",
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainenreply_append_extra_fields(string_t *str, struct auth_request *request)
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen if (!auth_fields_is_empty(request->extra_fields)) {
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 auth_fields_append(request->extra_fields, str,
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);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void verify_plain_callback(enum passdb_result result,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct auth_worker_client *client = request->context;
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen if (request->failed && result == PASSDB_RESULT_OK)
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi if (auth_fields_exists(request->extra_fields, "noauthenticate"))
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (result != PASSDB_RESULT_INTERNAL_FAILURE) {
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen str_append_tabescaped(str, request->passdb_password);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenauth_worker_handle_passv(struct auth_worker_client *client,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* verify plaintext password */
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");
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");
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen while (passdb != NULL && passdb->passdb->id != passdb_id)
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)
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen verify_plain(auth_request, password, verify_plain_callback);
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomiauth_worker_handle_passw(struct auth_worker_client *client,
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi if (str_to_uint(args[0], &passdb_id) < 0 || args[1] == NULL ||
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi i_error("BUG: Auth worker server sent us invalid PASSW");
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi i_error("BUG: Auth worker server sent us invalid PASSW (scheme is NULL)");
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi if (!auth_worker_auth_request_new(client, id, args + 3, &request)) {
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi ret = auth_request_password_verify(request, password,
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi else if (ret == 0)
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi str_printfa(str, "FAIL\t%d", PASSDB_RESULT_PASSWORD_MISMATCH);
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi str_printfa(str, "FAIL\t%d", PASSDB_RESULT_INTERNAL_FAILURE);
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainenlookup_credentials_callback(enum passdb_result result,
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen const unsigned char *credentials, size_t size,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct auth_worker_client *client = request->context;
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen if (request->failed && result == PASSDB_RESULT_OK)
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi if (result != PASSDB_RESULT_OK && result != PASSDB_RESULT_NEXT)
3db05c8c00faca6ab9ac8391e1d6977365f4d1b3Timo Sirainen str_printfa(str, "{%s.b64}", request->credentials_scheme);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenauth_worker_handle_passl(struct auth_worker_client *client,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* lookup credentials */
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");
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi if (!auth_worker_auth_request_new(client, id, args + 2, &auth_request)) {
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi auth_request->credentials_scheme = p_strdup(auth_request->pool, scheme);
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen while (auth_request->passdb->passdb->id != passdb_id) {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen auth_request->passdb = auth_request->passdb->next;
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen if (auth_request->passdb->passdb->iface.lookup_credentials == NULL) {
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen i_error("BUG: PASSL lookup not supported by given passdb");
430c0b0c370bebeeceba2e206be76bc134742f41Timo Sirainen auth_request->prefer_plain_credentials = TRUE;
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen lookup_credentials(auth_request, lookup_credentials_callback);
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainenset_credentials_callback(bool success, struct auth_request *request)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen struct auth_worker_client *client = request->context;
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen str_printfa(str, "%u\t%s\n", request->id, success ? "OK" : "FAIL");
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainenauth_worker_handle_setcred(struct auth_worker_client *client,
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");
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi if (!auth_worker_auth_request_new(client, id, args + 2, &auth_request)) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen i_error("BUG: SETCRED had missing parameters");
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen while (auth_request->passdb->passdb->id != passdb_id) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen auth_request->passdb = auth_request->passdb->next;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen i_error("BUG: SETCRED had invalid passdb ID");
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen set_credentials(auth_request, creds, set_credentials_callback);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainenlookup_user_callback(enum userdb_result result,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct auth_worker_client *client = auth_request->context;
865a82c1e9bba11609835a36674964649025bf77Timo Sirainen str_append_tabescaped(str, auth_request->user);
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen /* export only the fields changed by this lookup */
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen auth_fields_append(auth_request->userdb_reply, str,
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen auth_worker_send_reply(client, auth_request, str);
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainenstatic struct auth_userdb *
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainenauth_userdb_find_by_id(struct auth_userdb *userdbs, unsigned int id)
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen for (db = userdbs; db != NULL; db = db->next) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenauth_worker_handle_user(struct auth_worker_client *client,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* lookup user */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* <userdb id> [<args>] */
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen i_error("BUG: Auth worker server sent us invalid USER");
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi if (!auth_worker_auth_request_new(client, id, args + 1, &auth_request)) {
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen auth_userdb_find_by_id(auth_request->userdb, userdb_id);
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainenauth_worker_client_idle_kill(struct auth_worker_client *client ATTR_UNUSED)
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainenauth_worker_client_set_idle_timeout(struct auth_worker_client *client)
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen idle_kill_secs = master_service_get_idle_kill_secs(master_service);
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen client->to_idle = timeout_add(idle_kill_secs * 1000,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic void list_iter_deinit(struct auth_worker_list_context *ctx)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct auth_worker_client *client = ctx->client;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen if (ctx->auth_request->userdb->userdb->iface->
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen str_printfa(str, "%u\tFAIL\n", ctx->auth_request->id);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen str_printfa(str, "%u\tOK\n", ctx->auth_request->id);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen client->io = io_add(client->fd, IO_READ, auth_worker_input, client);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen o_stream_set_flush_callback(client->output, auth_worker_output, client);
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic void list_iter_callback(const char *user, void *context)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct auth_worker_list_context *ctx = context;
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 /* avoid recursively looping to this same function */
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 o_stream_get_buffer_used_size(ctx->client->output) <= OUTBUF_THROTTLE_SIZE);
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen o_stream_set_flush_pending(ctx->client->output, TRUE);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic int auth_worker_list_output(struct auth_worker_list_context *ctx)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if ((ret = o_stream_flush(ctx->client->output)) < 0) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenauth_worker_handle_list(struct auth_worker_client *client,
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen i_error("BUG: Auth worker server sent us invalid LIST");
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen userdb = auth_userdb_find_by_id(client->auth->userdbs, userdb_id);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx = i_new(struct auth_worker_list_context, 1);
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi if (!auth_worker_auth_request_new(client, id, args + 1, &ctx->auth_request)) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen o_stream_set_flush_callback(ctx->client->output,
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);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenauth_worker_handle_line(struct auth_worker_client *client, const char *line)
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (args[0] == NULL || args[1] == NULL || args[2] == NULL ||
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen ret = auth_worker_handle_passv(client, id, args + 2);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen ret = auth_worker_handle_passl(client, id, args + 2);
dc3ee76ef7907b1a9fc61975fdeedb422853ce50Aki Tuomi ret = auth_worker_handle_passw(client, id, args + 2);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen ret = auth_worker_handle_setcred(client, id, args + 2);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen ret = auth_worker_handle_user(client, id, args + 2);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen ret = auth_worker_handle_list(client, id, args + 2);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen i_error("BUG: Auth-worker received unknown command: %s",
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainenstatic bool auth_worker_verify_db_hash(const char *line)
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen binary_to_hex_append(str, passdb_md5, sizeof(passdb_md5));
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen binary_to_hex_append(str, userdb_md5, sizeof(userdb_md5));
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenstatic void auth_worker_input(struct auth_worker_client *client)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* disconnected */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* buffer full */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_error("BUG: Auth worker server sent us more than %d bytes",
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen if (!version_string_verify(line, "auth-worker",
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen i_error("Auth worker not compatible with this server "
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen "(mixed old and new binaries?)");
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?");
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen while ((line = i_stream_next_line(client->input)) != NULL) {
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenstatic int auth_worker_output(struct auth_worker_client *client)
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 Sirainenauth_worker_client_create(struct auth *auth, int 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);
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_HANDSHAKE);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid auth_worker_client_destroy(struct auth_worker_client **_client)
7cba14a4c3beb026a2862ee50d24c554fa713329Timo Sirainen master_service_client_connection_destroyed(master_service);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid auth_worker_client_unref(struct auth_worker_client **_client)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(auth_worker_client->output, "ERROR\n");
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(auth_worker_client->output, "SUCCESS\n");
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(auth_worker_client->output, "SHUTDOWN\n");