bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
657afb33796f8216c568ad813627da89970760beTimo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "auth-common.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "ioloop.h"
a550b0fbcf7e876eeb88f4528209ed28cc416752Timo Sirainen#include "array.h"
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen#include "aqueue.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "base64.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "hash.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "net.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "str.h"
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen#include "strescape.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "str-sanitize.h"
d99107ddf4d9bccb710994482daf65276a9d6321Timo Sirainen#include "master-interface.h"
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen#include "auth-penalty.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "auth-request.h"
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch#include "auth-token.h"
8de6351e4f658b1100f0c19ea1af84ef2fe38753Stephan Bosch#include "auth-client-connection.h"
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen#include "auth-master-connection.h"
657afb33796f8216c568ad813627da89970760beTimo Sirainen#include "auth-request-handler.h"
ecbc1c76e469e2a9a14e71da59c48b82ab04cde6Timo Sirainen#include "auth-policy.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
a3b3e5b452be15049a1f8bfd5b3bb640af41121cTimo Sirainen#define AUTH_FAILURE_DELAY_CHECK_MSECS 500
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstruct auth_request_handler {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen int refcount;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen pool_t pool;
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen HASH_TABLE(void *, struct auth_request *) requests;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int connect_uid, client_pid;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
6aafdd81aa1e12c127941c1ebd87e8ee4697ec3eTimo Sirainen auth_client_request_callback_t *callback;
6aafdd81aa1e12c127941c1ebd87e8ee4697ec3eTimo Sirainen struct auth_client_connection *conn;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
6aafdd81aa1e12c127941c1ebd87e8ee4697ec3eTimo Sirainen auth_master_request_callback_t *master_callback;
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool destroyed:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool token_auth:1;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen};
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainenstatic ARRAY(struct auth_request *) auth_failures_arr;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainenstatic struct aqueue *auth_failures;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic struct timeout *to_auth_failures;
657afb33796f8216c568ad813627da89970760beTimo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenstatic void auth_failure_timeout(void *context) ATTR_NULL(1);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainenstruct auth_request_handler *
6aafdd81aa1e12c127941c1ebd87e8ee4697ec3eTimo Sirainenauth_request_handler_create(bool token_auth, auth_client_request_callback_t *callback,
6aafdd81aa1e12c127941c1ebd87e8ee4697ec3eTimo Sirainen struct auth_client_connection *conn,
6aafdd81aa1e12c127941c1ebd87e8ee4697ec3eTimo Sirainen auth_master_request_callback_t *master_callback)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request_handler *handler;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen pool_t pool;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen pool = pool_alloconly_create("auth request handler", 4096);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler = p_new(pool, struct auth_request_handler, 1);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->refcount = 1;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->pool = pool;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen hash_table_create_direct(&handler->requests, pool, 0);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->callback = callback;
6aafdd81aa1e12c127941c1ebd87e8ee4697ec3eTimo Sirainen handler->conn = conn;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->master_callback = master_callback;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch handler->token_auth = token_auth;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return handler;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
a7e2c98560cf54dc656711a237cb07da8a5a9ee4Timo Sirainenunsigned int
a7e2c98560cf54dc656711a237cb07da8a5a9ee4Timo Sirainenauth_request_handler_get_request_count(struct auth_request_handler *handler)
a7e2c98560cf54dc656711a237cb07da8a5a9ee4Timo Sirainen{
a7e2c98560cf54dc656711a237cb07da8a5a9ee4Timo Sirainen return hash_table_count(handler->requests);
a7e2c98560cf54dc656711a237cb07da8a5a9ee4Timo Sirainen}
a7e2c98560cf54dc656711a237cb07da8a5a9ee4Timo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainenvoid auth_request_handler_abort_requests(struct auth_request_handler *handler)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen struct hash_iterate_context *iter;
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen void *key;
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen struct auth_request *auth_request;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen iter = hash_table_iterate_init(handler->requests);
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen while (hash_table_iterate(iter, handler->requests, &key, &auth_request)) {
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen switch (auth_request->state) {
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen case AUTH_REQUEST_STATE_NEW:
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen case AUTH_REQUEST_STATE_MECH_CONTINUE:
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen case AUTH_REQUEST_STATE_FINISHED:
3951689971f3478e910507c1078cf0123de63866Timo Sirainen auth_request->removed_from_handler = TRUE;
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen auth_request_unref(&auth_request);
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen hash_table_remove(handler->requests, key);
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen break;
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen case AUTH_REQUEST_STATE_PASSDB:
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen case AUTH_REQUEST_STATE_USERDB:
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen /* can't abort a pending passdb/userdb lookup */
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen break;
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen case AUTH_REQUEST_STATE_MAX:
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen i_unreached();
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen }
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen }
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen hash_table_iterate_deinit(&iter);
8c6c6b95f482d2a2cdc74db5582aeb24871e3579Timo Sirainen}
8c6c6b95f482d2a2cdc74db5582aeb24871e3579Timo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainenvoid auth_request_handler_unref(struct auth_request_handler **_handler)
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen{
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen struct auth_request_handler *handler = *_handler;
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen *_handler = NULL;
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen i_assert(handler->refcount > 0);
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen if (--handler->refcount > 0)
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen return;
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen i_assert(hash_table_count(handler->requests) == 0);
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen /* notify parent that we're done with all requests */
6aafdd81aa1e12c127941c1ebd87e8ee4697ec3eTimo Sirainen handler->callback(NULL, handler->conn);
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen hash_table_destroy(&handler->requests);
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen pool_unref(&handler->pool);
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen}
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainenvoid auth_request_handler_destroy(struct auth_request_handler **_handler)
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen{
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen struct auth_request_handler *handler = *_handler;
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen *_handler = NULL;
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen i_assert(!handler->destroyed);
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen handler->destroyed = TRUE;
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen auth_request_handler_unref(&handler);
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen}
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
70905e51a5148bd5613cb04720807177474a2496Timo Sirainenvoid auth_request_handler_set(struct auth_request_handler *handler,
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen unsigned int connect_uid,
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen unsigned int client_pid)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->connect_uid = connect_uid;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->client_pid = client_pid;
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void auth_request_handler_remove(struct auth_request_handler *handler,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen i_assert(request->handler == handler);
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen if (request->removed_from_handler) {
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen /* already removed it */
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen return;
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen }
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen request->removed_from_handler = TRUE;
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen
e69e7b734b625de1f8921b7e0d92afa1df6b900dTimo Sirainen /* if db lookup is stuck, this call doesn't actually free the auth
e69e7b734b625de1f8921b7e0d92afa1df6b900dTimo Sirainen request, so make sure we don't get back here. */
e69e7b734b625de1f8921b7e0d92afa1df6b900dTimo Sirainen timeout_remove(&request->to_abort);
e69e7b734b625de1f8921b7e0d92afa1df6b900dTimo Sirainen
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen hash_table_remove(handler->requests, POINTER_CAST(request->id));
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_unref(&request);
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
eb7b8855cc45292334056f425645215e348ec493Timo Sirainenstatic void
eb7b8855cc45292334056f425645215e348ec493Timo Sirainenauth_str_add_keyvalue(string_t *dest, const char *key, const char *value)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_append_c(dest, '\t');
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_append(dest, key);
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_append_c(dest, '=');
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_append_tabescaped(dest, value);
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
eb7b8855cc45292334056f425645215e348ec493Timo Sirainenstatic void
eb7b8855cc45292334056f425645215e348ec493Timo Sirainenauth_str_append_extra_fields(struct auth_request *request, string_t *dest)
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen{
0693f78ec64fd8ffedbf84408e6b4fc9c4c2b89fTimo Sirainen if (!auth_fields_is_empty(request->extra_fields)) {
0693f78ec64fd8ffedbf84408e6b4fc9c4c2b89fTimo Sirainen str_append_c(dest, '\t');
0693f78ec64fd8ffedbf84408e6b4fc9c4c2b89fTimo Sirainen auth_fields_append(request->extra_fields, dest,
0693f78ec64fd8ffedbf84408e6b4fc9c4c2b89fTimo Sirainen AUTH_FIELD_FLAG_HIDDEN, 0);
0693f78ec64fd8ffedbf84408e6b4fc9c4c2b89fTimo Sirainen }
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen
4981c1da73ffef4aff69c1af179a872bd1b68d9fTimo Sirainen if (request->original_username != NULL &&
e5d6ec3335b472e9bd9895d75b7723706c69e9fbTimo Sirainen null_strcmp(request->original_username, request->user) != 0 &&
e5d6ec3335b472e9bd9895d75b7723706c69e9fbTimo Sirainen !auth_fields_exists(request->extra_fields, "original_user")) {
c7eb1ffb7c73cb5d9c1316bbecd02947441a40d4Timo Sirainen auth_str_add_keyvalue(dest, "original_user",
c7eb1ffb7c73cb5d9c1316bbecd02947441a40d4Timo Sirainen request->original_username);
c7eb1ffb7c73cb5d9c1316bbecd02947441a40d4Timo Sirainen }
e5d6ec3335b472e9bd9895d75b7723706c69e9fbTimo Sirainen if (request->master_user != NULL &&
e5d6ec3335b472e9bd9895d75b7723706c69e9fbTimo Sirainen !auth_fields_exists(request->extra_fields, "auth_user"))
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen auth_str_add_keyvalue(dest, "auth_user", request->master_user);
c7eb1ffb7c73cb5d9c1316bbecd02947441a40d4Timo Sirainen
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen if (!request->auth_only &&
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen auth_fields_exists(request->extra_fields, "proxy")) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* we're proxying */
ee6df9526e9716b3f1734d85b566e00fc41208bcTimo Sirainen if (!auth_fields_exists(request->extra_fields, "pass") &&
cd5a70b520f84f929e1994a797666f872ec30435Timo Sirainen request->mech_password != NULL) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* send back the password that was sent by user
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen (not the password in passdb). */
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen auth_str_add_keyvalue(dest, "pass",
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen request->mech_password);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
b82590193a2ebc23fcdf61a692d879fe53f996d1Timo Sirainen if (request->master_user != NULL &&
ee6df9526e9716b3f1734d85b566e00fc41208bcTimo Sirainen !auth_fields_exists(request->extra_fields, "master")) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* the master username needs to be forwarded */
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen auth_str_add_keyvalue(dest, "master",
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen request->master_user);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainenstatic void
eb7b8855cc45292334056f425645215e348ec493Timo Sirainenauth_request_handle_failure(struct auth_request *request, const char *reply)
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen{
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen struct auth_request_handler *handler = request->handler;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen if (request->in_delayed_failure_queue) {
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen /* we came here from flush_failures() */
6aafdd81aa1e12c127941c1ebd87e8ee4697ec3eTimo Sirainen handler->callback(reply, handler->conn);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen return;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen /* remove the request from requests-list */
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_ref(request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_handler_remove(handler, request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
41ff6e6a4a085786d4c15a58c7c50a28e2110c3fAki Tuomi if (request->set->policy_report_after_auth)
41ff6e6a4a085786d4c15a58c7c50a28e2110c3fAki Tuomi auth_policy_report(request);
ef1ff1af5a38ad2b0bc77b3236c4c2d79f2c530fAki Tuomi
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen if (auth_fields_exists(request->extra_fields, "nodelay")) {
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen /* passdb specifically requested not to delay the reply. */
6aafdd81aa1e12c127941c1ebd87e8ee4697ec3eTimo Sirainen handler->callback(reply, handler->conn);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_unref(&request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen return;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen /* failure. don't announce it immediately to avoid
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen a) timing attacks, b) flooding */
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen request->in_delayed_failure_queue = TRUE;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen handler->refcount++;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen if (auth_penalty != NULL) {
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen auth_penalty_update(auth_penalty, request,
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen request->last_penalty + 1);
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen }
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen auth_request_refresh_last_access(request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen aqueue_append(auth_failures, &request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (to_auth_failures == NULL) {
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen to_auth_failures =
4b335788eb41dec2de5f78459d96387fcc710010Timo Sirainen timeout_add_short(AUTH_FAILURE_DELAY_CHECK_MSECS,
677b75f90d81eafe742896d6570a2f63ce501d05Josef 'Jeff' Sipek auth_failure_timeout, NULL);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen}
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainenstatic void
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainenauth_request_handler_reply_success_finish(struct auth_request *request)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen{
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen struct auth_request_handler *handler = request->handler;
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen string_t *str = t_str_new(128);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (request->last_penalty != 0 && auth_penalty != NULL) {
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen /* reset penalty */
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_penalty_update(auth_penalty, request, 0);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen }
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
068ac108503f9b3c81bbdac3b95db545d479188aTimo Sirainen /* sanitize these fields, since the login code currently assumes they
068ac108503f9b3c81bbdac3b95db545d479188aTimo Sirainen are exactly in this format. */
068ac108503f9b3c81bbdac3b95db545d479188aTimo Sirainen auth_fields_booleanize(request->extra_fields, "nologin");
068ac108503f9b3c81bbdac3b95db545d479188aTimo Sirainen auth_fields_booleanize(request->extra_fields, "proxy");
068ac108503f9b3c81bbdac3b95db545d479188aTimo Sirainen
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_printfa(str, "OK\t%u\tuser=", request->id);
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_append_tabescaped(str, request->user);
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen auth_str_append_extra_fields(request, str);
95087a44db62e87db2dc90845e359b70f1699bbdAki Tuomi
41ff6e6a4a085786d4c15a58c7c50a28e2110c3fAki Tuomi if (request->set->policy_report_after_auth)
41ff6e6a4a085786d4c15a58c7c50a28e2110c3fAki Tuomi auth_policy_report(request);
95087a44db62e87db2dc90845e359b70f1699bbdAki Tuomi
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen if (handler->master_callback == NULL ||
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen auth_fields_exists(request->extra_fields, "nologin") ||
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen auth_fields_exists(request->extra_fields, "proxy")) {
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen /* this request doesn't have to wait for master
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen process to pick it up. delete it */
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_remove(handler, request);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen }
ef1ff1af5a38ad2b0bc77b3236c4c2d79f2c530fAki Tuomi
6aafdd81aa1e12c127941c1ebd87e8ee4697ec3eTimo Sirainen handler->callback(str_c(str), handler->conn);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen}
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainenstatic void
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainenauth_request_handler_reply_failure_finish(struct auth_request *request)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen{
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch const char *code = NULL;
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen string_t *str = t_str_new(128);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
3d14f452f62077f849a1fce9f302843c2635f108Timo Sirainen auth_fields_remove(request->extra_fields, "nologin");
3d14f452f62077f849a1fce9f302843c2635f108Timo Sirainen
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_printfa(str, "FAIL\t%u", request->id);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (request->user != NULL)
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen auth_str_add_keyvalue(str, "user", request->user);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen else if (request->original_username != NULL) {
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen auth_str_add_keyvalue(str, "user",
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen request->original_username);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen }
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch if (request->internal_failure) {
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch code = AUTH_CLIENT_FAIL_CODE_TEMPFAIL;
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch } else if (request->master_user != NULL) {
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen /* authentication succeeded, but we can't log in
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen as the wanted user */
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch code = AUTH_CLIENT_FAIL_CODE_AUTHZFAILED;
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch } else {
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch switch (request->passdb_result) {
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch case PASSDB_RESULT_NEXT:
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch case PASSDB_RESULT_INTERNAL_FAILURE:
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch case PASSDB_RESULT_SCHEME_NOT_AVAILABLE:
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch case PASSDB_RESULT_USER_UNKNOWN:
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch case PASSDB_RESULT_PASSWORD_MISMATCH:
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch case PASSDB_RESULT_OK:
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch break;
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch case PASSDB_RESULT_USER_DISABLED:
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch code = AUTH_CLIENT_FAIL_CODE_USER_DISABLED;
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch break;
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch case PASSDB_RESULT_PASS_EXPIRED:
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch code = AUTH_CLIENT_FAIL_CODE_PASS_EXPIRED;
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch break;
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch }
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen }
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen if (auth_fields_exists(request->extra_fields, "nodelay")) {
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen /* this is normally a hidden field, need to add it explicitly */
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_append(str, "\tnodelay");
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen }
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch if (code != NULL) {
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch str_append(str, "\tcode=");
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch str_append(str, code);
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen }
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch auth_str_append_extra_fields(request, str);
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen auth_request_handle_failure(request, str_c(str));
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen}
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainenstatic void
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainenauth_request_handler_proxy_callback(bool success, struct auth_request *request)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen{
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen struct auth_request_handler *handler = request->handler;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (success)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_reply_success_finish(request);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen else
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_reply_failure_finish(request);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_unref(&handler);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen}
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainenvoid auth_request_handler_reply(struct auth_request *request,
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen enum auth_client_result result,
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen const void *auth_reply, size_t reply_size)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen struct auth_request_handler *handler = request->handler;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen string_t *str;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen int ret;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen if (handler->destroyed) {
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen /* the client connection was already closed. we can't do
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen anything but abort this request */
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen request->internal_failure = TRUE;
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen result = AUTH_CLIENT_RESULT_FAILURE;
e8a96ad5c10e9d5c0c4e2e88dd09a38fdb3e34b4Timo Sirainen /* make sure this request is set to finished state
e8a96ad5c10e9d5c0c4e2e88dd09a38fdb3e34b4Timo Sirainen (it's not with result=continue) */
e8a96ad5c10e9d5c0c4e2e88dd09a38fdb3e34b4Timo Sirainen auth_request_set_state(request, AUTH_REQUEST_STATE_FINISHED);
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen }
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen switch (result) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen case AUTH_CLIENT_RESULT_CONTINUE:
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str = t_str_new(16 + MAX_BASE64_ENCODED_SIZE(reply_size));
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_printfa(str, "CONT\t%u\t", request->id);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen base64_encode(auth_reply, reply_size, str);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen request->accept_cont_input = TRUE;
6aafdd81aa1e12c127941c1ebd87e8ee4697ec3eTimo Sirainen handler->callback(str_c(str), handler->conn);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen break;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen case AUTH_CLIENT_RESULT_SUCCESS:
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (reply_size > 0) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen str = t_str_new(MAX_BASE64_ENCODED_SIZE(reply_size));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen base64_encode(auth_reply, reply_size, str);
ee6df9526e9716b3f1734d85b566e00fc41208bcTimo Sirainen auth_fields_add(request->extra_fields, "resp",
ee6df9526e9716b3f1734d85b566e00fc41208bcTimo Sirainen str_c(str), 0);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen ret = auth_request_proxy_finish(request,
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_proxy_callback);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (ret < 0)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_reply_failure_finish(request);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen else if (ret > 0)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_reply_success_finish(request);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen else
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen return;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen break;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen case AUTH_CLIENT_RESULT_FAILURE:
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_proxy_finish_failure(request);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_reply_failure_finish(request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen break;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* NOTE: request may be destroyed now */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_handler_unref(&handler);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainenvoid auth_request_handler_reply_continue(struct auth_request *request,
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen const void *reply, size_t reply_size)
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen{
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen auth_request_handler_reply(request, AUTH_CLIENT_RESULT_CONTINUE,
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen reply, reply_size);
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen}
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Boschstatic void
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Boschauth_request_handler_auth_fail_code(struct auth_request_handler *handler,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request,
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch const char *fail_code, const char *reason)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen string_t *str = t_str_new(128);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(request, AUTH_SUBSYS_MECH, "%s", reason);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch str_printfa(str, "FAIL\t%u", request->id);
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch if (*fail_code != '\0') {
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch str_append(str, "\tcode=");
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch str_append(str, fail_code);
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch }
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch str_append(str, "\treason=");
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_append_tabescaped(str, reason);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
6aafdd81aa1e12c127941c1ebd87e8ee4697ec3eTimo Sirainen handler->callback(str_c(str), handler->conn);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_remove(handler, request);
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Boschstatic void auth_request_handler_auth_fail
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch(struct auth_request_handler *handler, struct auth_request *request,
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch const char *reason)
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch{
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch auth_request_handler_auth_fail_code(handler, request, "", reason);
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch}
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainenstatic void auth_request_timeout(struct auth_request *request)
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen{
ec7a751d45871fb36b19121fd4d7bd33145bf222Timo Sirainen unsigned int secs = (unsigned int)(time(NULL) - request->last_access);
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen if (request->state != AUTH_REQUEST_STATE_MECH_CONTINUE) {
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen /* client's fault */
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_error(request, AUTH_SUBSYS_MECH,
ec7a751d45871fb36b19121fd4d7bd33145bf222Timo Sirainen "Request %u.%u timed out after %u secs, state=%d",
ec7a751d45871fb36b19121fd4d7bd33145bf222Timo Sirainen request->handler->client_pid, request->id,
ec7a751d45871fb36b19121fd4d7bd33145bf222Timo Sirainen secs, request->state);
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen } else if (request->set->verbose) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(request, AUTH_SUBSYS_MECH,
ec7a751d45871fb36b19121fd4d7bd33145bf222Timo Sirainen "Request timed out waiting for client to continue authentication "
ec7a751d45871fb36b19121fd4d7bd33145bf222Timo Sirainen "(%u secs)", secs);
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen }
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen auth_request_handler_remove(request->handler, request);
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen}
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainenstatic void auth_request_penalty_finish(struct auth_request *request)
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen{
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen timeout_remove(&request->to_penalty);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen auth_request_initial(request);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen}
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainenstatic void
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainenauth_penalty_callback(unsigned int penalty, struct auth_request *request)
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen{
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen unsigned int secs;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen request->last_penalty = penalty;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen if (penalty == 0)
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen auth_request_initial(request);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen else {
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen secs = auth_penalty_to_secs(penalty);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen request->to_penalty = timeout_add(secs * 1000,
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen auth_request_penalty_finish,
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen request);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen }
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen}
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainenbool auth_request_handler_auth_begin(struct auth_request_handler *handler,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen const char *args)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
7242e1ce7803b83bc82e239ef111b47c1c72dd4bAndrey Panin const struct mech_module *mech;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen const char *const *list, *name, *arg, *initial_resp;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen void *initial_resp_data;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int id;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buffer_t *buf;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen i_assert(!handler->destroyed);
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* <id> <mechanism> [...] */
7a60e1dc9e93ef3f7c7fe1af6385a0bfa1e31bc3Timo Sirainen list = t_strsplit_tabescaped(args);
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (list[0] == NULL || list[1] == NULL ||
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen str_to_uint(list[0], &id) < 0) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_error("BUG: Authentication client %u "
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "sent broken AUTH request", handler->client_pid);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return FALSE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (handler->token_auth) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch mech = &mech_dovecot_token;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (strcmp(list[1], mech->mech_name) != 0) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch /* unsupported mechanism */
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch i_error("BUG: Authentication client %u requested invalid "
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch "authentication mechanism %s (DOVECOT-TOKEN required)",
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch handler->client_pid, str_sanitize(list[1], MAX_MECH_NAME_LEN));
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch return FALSE;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch }
4ac2e38bdb450d13b62be41638b12df9e0658009Stephan Bosch } else {
4ac2e38bdb450d13b62be41638b12df9e0658009Stephan Bosch struct auth *auth_default = auth_default_service();
4ac2e38bdb450d13b62be41638b12df9e0658009Stephan Bosch mech = mech_register_find(auth_default->reg, list[1]);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (mech == NULL) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch /* unsupported mechanism */
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch i_error("BUG: Authentication client %u requested unsupported "
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch "authentication mechanism %s", handler->client_pid,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch str_sanitize(list[1], MAX_MECH_NAME_LEN));
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch return FALSE;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen request = auth_request_new(mech);
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen request->handler = handler;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->connect_uid = handler->connect_uid;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->client_pid = handler->client_pid;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->id = id;
e31bf6003e580bcb28af333119da9dd1e16fc811Timo Sirainen request->auth_only = handler->master_callback == NULL;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* parse optional parameters */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen initial_resp = NULL;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen for (list += 2; *list != NULL; list++) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen arg = strchr(*list, '=');
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (arg == NULL) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen name = *list;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen arg = "";
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen } else {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen name = t_strdup_until(*list, arg);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen arg++;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
ab122a3bbae3b5fd2aad66e2f2840149d98cee52Timo Sirainen if (auth_request_import_auth(request, name, arg))
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen ;
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen else if (strcmp(name, "resp") == 0) {
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen initial_resp = arg;
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen /* this must be the last parameter */
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen list++;
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen break;
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen }
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen }
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen if (*list != NULL) {
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen i_error("BUG: Authentication client %u "
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen "sent AUTH parameters after 'resp'",
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen handler->client_pid);
7904d81873b36f8464c96be415881f92518452e6Timo Sirainen auth_request_unref(&request);
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen return FALSE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (request->service == NULL) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_error("BUG: Authentication client %u "
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "didn't specify service in request",
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->client_pid);
7904d81873b36f8464c96be415881f92518452e6Timo Sirainen auth_request_unref(&request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return FALSE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen if (hash_table_lookup(handler->requests, POINTER_CAST(id)) != NULL) {
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen i_error("BUG: Authentication client %u "
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen "sent a duplicate ID %u", handler->client_pid, id);
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen auth_request_unref(&request);
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen return FALSE;
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen }
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen auth_request_init(request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
d99107ddf4d9bccb710994482daf65276a9d6321Timo Sirainen request->to_abort = timeout_add(MASTER_AUTH_SERVER_TIMEOUT_SECS * 1000,
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen auth_request_timeout, request);
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen hash_table_insert(handler->requests, POINTER_CAST(id), request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen if (request->set->ssl_require_client_cert &&
258ff7d4f03dd9d29eca3664e4acacdf7f528234Timo Sirainen !request->valid_client_cert) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* we fail without valid certificate */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_auth_fail(handler, request,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "Client didn't present valid SSL certificate");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch /* Handle initial respose */
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch if (initial_resp == NULL) {
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch /* No initial response */
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch request->initial_response = NULL;
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch request->initial_response_len = 0;
8de6351e4f658b1100f0c19ea1af84ef2fe38753Stephan Bosch } else if (handler->conn->version_minor < 2 && *initial_resp == '\0') {
8de6351e4f658b1100f0c19ea1af84ef2fe38753Stephan Bosch /* Some authentication clients like Exim send and empty initial
8de6351e4f658b1100f0c19ea1af84ef2fe38753Stephan Bosch response field when it is in fact absent in the
8de6351e4f658b1100f0c19ea1af84ef2fe38753Stephan Bosch authentication command. This was allowed for older versions
8de6351e4f658b1100f0c19ea1af84ef2fe38753Stephan Bosch of the Dovecot authentication protocol. */
8de6351e4f658b1100f0c19ea1af84ef2fe38753Stephan Bosch request->initial_response = NULL;
8de6351e4f658b1100f0c19ea1af84ef2fe38753Stephan Bosch request->initial_response_len = 0;
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch } else if (*initial_resp == '\0' || strcmp(initial_resp, "=") == 0 ) {
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch /* Empty initial response - Protocols that use SASL often
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch use '=' to indicate an empty initial response; i.e., to
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch distinguish it from an absent initial response. However, that
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch should not be conveyed to the SASL layer (it is not even
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch valid Base64); only the empty string should be passed on.
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch Still, we recognize it here anyway, because we used to make
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch the same mistake. */
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch request->initial_response = uchar_empty_ptr;
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch request->initial_response_len = 0;
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch } else {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen size_t len = strlen(initial_resp);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e4b72bd73bfffda7906faa248eab31f936cfc6faStephan Bosch /* Initial response encoded in Bas64 */
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi buf = t_buffer_create(MAX_BASE64_DECODED_SIZE(len));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (base64_decode(initial_resp, len, NULL, buf) < 0) {
8ac6623677005256bf99ab33a2ed98c69c1d656cStephan Bosch auth_request_handler_auth_fail_code(handler, request,
8ac6623677005256bf99ab33a2ed98c69c1d656cStephan Bosch AUTH_CLIENT_FAIL_CODE_INVALID_BASE64,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "Invalid base64 data in initial response");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen initial_resp_data =
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen p_malloc(request->pool, I_MAX(buf->used, 1));
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen memcpy(initial_resp_data, buf->data, buf->used);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen request->initial_response = initial_resp_data;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen request->initial_response_len = buf->used;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen /* handler is referenced until auth_request_handler_reply()
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen is called. */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->refcount++;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen /* before we start authenticating, see if we need to wait first */
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen auth_penalty_lookup(auth_penalty, request, auth_penalty_callback);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenbool auth_request_handler_auth_continue(struct auth_request_handler *handler,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen const char *args)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen const char *data;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen size_t data_len;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buffer_t *buf;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int id;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen data = strchr(args, '\t');
c53a3c54d388c0031aaa642e6b14d46eb86d9485Timo Sirainen if (data == NULL || str_to_uint(t_strdup_until(args, data), &id) < 0) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_error("BUG: Authentication client sent broken CONT request");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return FALSE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
ccb77e2f63626ec46e5745ef4f38baa8e8e504fcTimo Sirainen data++;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen request = hash_table_lookup(handler->requests, POINTER_CAST(id));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (request == NULL) {
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen const char *reply = t_strdup_printf(
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen "FAIL\t%u\treason=Authentication request timed out", id);
6aafdd81aa1e12c127941c1ebd87e8ee4697ec3eTimo Sirainen handler->callback(reply, handler->conn);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* accept input only once after mechanism has sent a CONT reply */
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen if (!request->accept_cont_input) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_auth_fail(handler, request,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "Unexpected continuation");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen request->accept_cont_input = FALSE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen data_len = strlen(data);
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi buf = t_buffer_create(MAX_BASE64_DECODED_SIZE(data_len));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (base64_decode(data, data_len, NULL, buf) < 0) {
8ac6623677005256bf99ab33a2ed98c69c1d656cStephan Bosch auth_request_handler_auth_fail_code(handler, request,
8ac6623677005256bf99ab33a2ed98c69c1d656cStephan Bosch AUTH_CLIENT_FAIL_CODE_INVALID_BASE64,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "Invalid base64 data in continued response");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen /* handler is referenced until auth_request_handler_reply()
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen is called. */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->refcount++;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_continue(request, buf->data, buf->used);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainenstatic void auth_str_append_userdb_extra_fields(struct auth_request *request,
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen string_t *dest)
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen{
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen str_append_c(dest, '\t');
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen auth_fields_append(request->userdb_reply, dest,
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen AUTH_FIELD_FLAG_HIDDEN, 0);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen if (request->master_user != NULL &&
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen !auth_fields_exists(request->userdb_reply, "master_user")) {
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen auth_str_add_keyvalue(dest, "master_user",
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen request->master_user);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen }
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen if (*request->set->anonymous_username != '\0' &&
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen strcmp(request->user, request->set->anonymous_username) == 0) {
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen /* this is an anonymous login, either via ANONYMOUS
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen SASL mechanism or simply logging in as the anonymous
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen user via another mechanism */
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen str_append(dest, "\tanonymous");
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen }
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen /* generate auth_token when master service provided session_pid */
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen if (request->request_auth_token &&
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen request->session_pid != (pid_t)-1) {
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen const char *auth_token =
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen auth_token_get(request->service,
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen dec2str(request->session_pid),
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen request->user,
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen request->session_id);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen auth_str_add_keyvalue(dest, "auth_token", auth_token);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen }
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen if (request->master_user != NULL) {
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen auth_str_add_keyvalue(dest, "auth_user", request->master_user);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen } else if (request->original_username != NULL &&
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen strcmp(request->original_username, request->user) != 0) {
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen auth_str_add_keyvalue(dest, "auth_user",
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen request->original_username);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen }
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen}
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainenstatic void userdb_callback(enum userdb_result result,
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen struct auth_request *request)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen struct auth_request_handler *handler = request->handler;
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen string_t *str;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen const char *value;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen i_assert(request->state == AUTH_REQUEST_STATE_USERDB);
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen auth_request_set_state(request, AUTH_REQUEST_STATE_FINISHED);
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen if (request->userdb_lookup_tempfailed)
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen result = USERDB_RESULT_INTERNAL_FAILURE;
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str = t_str_new(128);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen switch (result) {
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen case USERDB_RESULT_INTERNAL_FAILURE:
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_printfa(str, "FAIL\t%u", request->id);
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen if (request->userdb_lookup_tempfailed) {
ee6df9526e9716b3f1734d85b566e00fc41208bcTimo Sirainen value = auth_fields_find(request->userdb_reply, "reason");
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen if (value != NULL)
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen auth_str_add_keyvalue(str, "reason", value);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen }
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen break;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen case USERDB_RESULT_USER_UNKNOWN:
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_printfa(str, "NOTFOUND\t%u", request->id);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen break;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen case USERDB_RESULT_OK:
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_printfa(str, "USER\t%u\t", request->id);
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_append_tabescaped(str, request->user);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen auth_str_append_userdb_extra_fields(request, str);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen break;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen handler->master_callback(str_c(str), request->master);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen auth_master_connection_unref(&request->master);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_unref(&request);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_handler_unref(&handler);
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Boschstatic bool
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Boschauth_master_request_failed(struct auth_request_handler *handler,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch struct auth_master_connection *master,
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen unsigned int id)
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch{
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (handler->master_callback == NULL)
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch return FALSE;
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen handler->master_callback(t_strdup_printf("FAIL\t%u", id), master);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch return TRUE;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch}
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch
daa7e7459749ae8f82cd3eed9c44522d81c609a3Timo Sirainenbool auth_request_handler_master_request(struct auth_request_handler *handler,
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen struct auth_master_connection *master,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch unsigned int id, unsigned int client_id,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch const char *const *params)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch struct net_unix_cred cred;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen request = hash_table_lookup(handler->requests, POINTER_CAST(client_id));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (request == NULL) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_error("Master request %u.%u not found",
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->client_pid, client_id);
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen return auth_master_request_failed(handler, master, id);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_ref(request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_remove(handler, request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch for (; *params != NULL; params++) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch const char *name, *param = strchr(*params, '=');
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (param == NULL) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch name = *params;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch param = "";
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch } else {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch name = t_strdup_until(*params, param);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch param++;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch }
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch (void)auth_request_import_master(request, name, param);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch }
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch /* verify session pid if specified and possible */
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (request->session_pid != (pid_t)-1 &&
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch net_getunixcred(master->fd, &cred) == 0 &&
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch cred.pid != (pid_t)-1 && request->session_pid != cred.pid) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch i_error("Session pid %ld provided by master for request %u.%u "
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch "did not match peer credentials (pid=%ld, uid=%ld)",
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch (long)request->session_pid,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch handler->client_pid, client_id,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch (long)cred.pid, (long)cred.uid);
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen return auth_master_request_failed(handler, master, id);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch }
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen if (request->state != AUTH_REQUEST_STATE_FINISHED ||
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen !request->successful) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_error("Master requested unfinished authentication request "
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "%u.%u", handler->client_pid, client_id);
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen handler->master_callback(t_strdup_printf("FAIL\t%u", id),
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen master);
0a8ec3c561c26c492a50511692650ea302cc8c14Timo Sirainen auth_request_unref(&request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen } else {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* the request isn't being referenced anywhere anymore,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen so we can do a bit of kludging.. replace the request's
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen old client_id with master's id. */
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen auth_request_set_state(request, AUTH_REQUEST_STATE_USERDB);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->id = id;
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen request->master = master;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen /* master and handler are referenced until userdb_callback i
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen s called. */
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen auth_master_connection_ref(master);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->refcount++;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_lookup_user(request, userdb_callback);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
daa7e7459749ae8f82cd3eed9c44522d81c609a3Timo Sirainen return TRUE;
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainenvoid auth_request_handler_cancel_request(struct auth_request_handler *handler,
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen unsigned int client_id)
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen{
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen struct auth_request *request;
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen request = hash_table_lookup(handler->requests, POINTER_CAST(client_id));
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen if (request != NULL)
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen auth_request_handler_remove(handler, request);
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen}
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainenvoid auth_request_handler_flush_failures(bool flush_all)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen struct auth_request **auth_requests, *auth_request;
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen unsigned int i, j, count;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen time_t diff;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen count = aqueue_count(auth_failures);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (count == 0) {
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&to_auth_failures);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen return;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_requests = array_idx_modifiable(&auth_failures_arr, 0);
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen /* count the number of requests that we need to flush */
a550b0fbcf7e876eeb88f4528209ed28cc416752Timo Sirainen for (i = 0; i < count; i++) {
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen auth_request = auth_requests[aqueue_idx(auth_failures, i)];
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
19557f192d37cd54a1a090a8a26d9d47265e4413Aki Tuomi /* FIXME: assumes that failure_delay is always the same. */
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen diff = ioloop_time - auth_request->last_access;
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen if (diff < (time_t)auth_request->set->failure_delay &&
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen !flush_all)
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen break;
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen }
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen /* shuffle these requests to try to prevent any kind of timing attacks
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen where attacker performs multiple requests in parallel and attempts
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen to figure out results based on the order of replies. */
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen count = i;
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen for (i = 0; i < count; i++) {
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen j = random() % (count - i) + i;
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen auth_request = auth_requests[aqueue_idx(auth_failures, i)];
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen /* swap i & j */
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen auth_requests[aqueue_idx(auth_failures, i)] =
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen auth_requests[aqueue_idx(auth_failures, j)];
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen auth_requests[aqueue_idx(auth_failures, j)] = auth_request;
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen }
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen /* flush the requests */
e18b4e41d9718a199a1980688787c2743c870002Timo Sirainen for (i = 0; i < count; i++) {
b20202007c06fa77da44d00fbac7f029cb6d8f86Aki Tuomi auth_request = auth_requests[aqueue_idx(auth_failures, 0)];
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen aqueue_delete_tail(auth_failures);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
b20202007c06fa77da44d00fbac7f029cb6d8f86Aki Tuomi i_assert(auth_request != NULL);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen i_assert(auth_request->state == AUTH_REQUEST_STATE_FINISHED);
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen auth_request_handler_reply(auth_request,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen AUTH_CLIENT_RESULT_FAILURE,
5965eaa2d972e6264cecaf54091cd43019bc7d1fTimo Sirainen uchar_empty_ptr, 0);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_unref(&auth_request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenstatic void auth_failure_timeout(void *context ATTR_UNUSED)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_handler_flush_failures(FALSE);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenvoid auth_request_handler_init(void)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen i_array_init(&auth_failures_arr, 128);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_failures = aqueue_init(&auth_failures_arr.arr);
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenvoid auth_request_handler_deinit(void)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_handler_flush_failures(TRUE);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen array_free(&auth_failures_arr);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen aqueue_deinit(&auth_failures);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&to_auth_failures);
657afb33796f8216c568ad813627da89970760beTimo Sirainen}