auth-request-handler.c revision ecbc1c76e469e2a9a14e71da59c48b82ab04cde6
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2005-2016 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"
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:
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
ef1ff1af5a38ad2b0bc77b3236c4c2d79f2c530fAki 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,
f0cd1d0022590d0a0d84f57e362774c2e96e2ea8Timo Sirainen auth_failure_timeout, (void *)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
95087a44db62e87db2dc90845e359b70f1699bbdAki 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{
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
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (request->internal_failure)
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_append(str, "\ttemp");
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen else if (request->master_user != NULL) {
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen /* authentication succeeded, but we can't log in
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen as the wanted user */
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_append(str, "\tauthz");
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen }
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 }
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen auth_str_append_extra_fields(request, str);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen switch (request->passdb_result) {
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen case PASSDB_RESULT_INTERNAL_FAILURE:
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen case PASSDB_RESULT_SCHEME_NOT_AVAILABLE:
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen case PASSDB_RESULT_USER_UNKNOWN:
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen case PASSDB_RESULT_PASSWORD_MISMATCH:
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen case PASSDB_RESULT_OK:
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen break;
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen case PASSDB_RESULT_USER_DISABLED:
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_append(str, "\tuser_disabled");
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen break;
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen case PASSDB_RESULT_PASS_EXPIRED:
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_append(str, "\tpass_expired");
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen break;
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen }
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
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void auth_request_handler_auth_fail(struct auth_request_handler *handler,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen 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
eb7b8855cc45292334056f425645215e348ec493Timo Sirainen str_printfa(str, "FAIL\t%u\treason=", request->id);
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
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> [...] */
3c296d819c54e21ce05c3d2eeeedc79be42ac593Timo Sirainen list = t_strsplit_tab(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
4f2248a8a70985c7295afc3bf91c848e81d740d9Timo Sirainen /* Empty initial response is a "=" base64 string. Completely empty
4f2248a8a70985c7295afc3bf91c848e81d740d9Timo Sirainen string shouldn't really be sent, but at least Exim does it,
4f2248a8a70985c7295afc3bf91c848e81d740d9Timo Sirainen so just allow it for backwards compatibility.. */
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen if (initial_resp != NULL && *initial_resp != '\0') {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen size_t len = strlen(initial_resp);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buf = buffer_create_dynamic(pool_datastack_create(),
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen MAX_BASE64_DECODED_SIZE(len));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (base64_decode(initial_resp, len, NULL, buf) < 0) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_auth_fail(handler, request,
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);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buf = buffer_create_dynamic(pool_datastack_create(),
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen MAX_BASE64_DECODED_SIZE(data_len));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (base64_decode(data, data_len, NULL, buf) < 0) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_auth_fail(handler, request,
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;
a550b0fbcf7e876eeb88f4528209ed28cc416752Timo Sirainen unsigned int i, count;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen time_t diff;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen count = aqueue_count(auth_failures);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (count == 0) {
a3b3e5b452be15049a1f8bfd5b3bb640af41121cTimo Sirainen if (to_auth_failures != NULL)
a3b3e5b452be15049a1f8bfd5b3bb640af41121cTimo Sirainen timeout_remove(&to_auth_failures);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen return;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_requests = array_idx_modifiable(&auth_failures_arr, 0);
a550b0fbcf7e876eeb88f4528209ed28cc416752Timo Sirainen for (i = 0; i < count; i++) {
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request = auth_requests[aqueue_idx(auth_failures, 0)];
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* FIXME: assumess 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;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen aqueue_delete_tail(auth_failures);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
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,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen &uchar_nul, 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
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (to_auth_failures != NULL)
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen timeout_remove(&to_auth_failures);
657afb33796f8216c568ad813627da89970760beTimo Sirainen}