auth-request-handler.c revision aefe17424820c57bcb05b0aaec4a930e8222bacc
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2005-2012 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"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "str.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"
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen#include "auth-master-connection.h"
657afb33796f8216c568ad813627da89970760beTimo Sirainen#include "auth-request-handler.h"
657afb33796f8216c568ad813627da89970760beTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include <stdlib.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;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct hash_table *requests;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int connect_uid, client_pid;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_callback_t *callback;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen void *context;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_callback_t *master_callback;
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen unsigned int destroyed:1;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen};
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainenstatic ARRAY_DEFINE(auth_failures_arr, struct auth_request *);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainenstatic struct aqueue *auth_failures;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic struct timeout *to_auth_failures;
657afb33796f8216c568ad813627da89970760beTimo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainenstatic void auth_failure_timeout(void *context);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen#undef auth_request_handler_create
657afb33796f8216c568ad813627da89970760beTimo Sirainenstruct auth_request_handler *
9be4e6701d086c009f3db1913a148139ea180420Timo Sirainenauth_request_handler_create(auth_request_callback_t *callback, void *context,
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen auth_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;
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen handler->requests = hash_table_create(default_pool, pool, 0, NULL, NULL);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->callback = callback;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->context = context;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->master_callback = master_callback;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return handler;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainenunsigned int
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenauth_request_handler_get_request_count(struct auth_request_handler *handler)
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen{
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen return hash_table_count(handler->requests);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainenvoid auth_request_handler_abort_requests(struct auth_request_handler *handler)
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen{
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen struct hash_iterate_context *iter;
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen void *key, *value;
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen iter = hash_table_iterate_init(handler->requests);
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen while (hash_table_iterate(iter, &key, &value)) {
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen struct auth_request *auth_request = value;
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen
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);
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen hash_table_remove(handler->requests, key);
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen break;
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen case AUTH_REQUEST_STATE_PASSDB:
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen case AUTH_REQUEST_STATE_USERDB:
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen /* can't abort a pending passdb/userdb lookup */
8c6c6b95f482d2a2cdc74db5582aeb24871e3579Timo Sirainen break;
8c6c6b95f482d2a2cdc74db5582aeb24871e3579Timo Sirainen case AUTH_REQUEST_STATE_MAX:
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen i_unreached();
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen }
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen }
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen hash_table_iterate_deinit(&iter);
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen}
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainenvoid auth_request_handler_unref(struct auth_request_handler **_handler)
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen{
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen struct auth_request_handler *handler = *_handler;
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen *_handler = NULL;
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen i_assert(handler->refcount > 0);
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen if (--handler->refcount > 0)
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen return;
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen i_assert(hash_table_count(handler->requests) == 0);
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen /* notify parent that we're done with all requests */
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen handler->callback(NULL, handler->context);
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen hash_table_destroy(&handler->requests);
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen pool_unref(&handler->pool);
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen}
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo 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
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen i_assert(!handler->destroyed);
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen handler->destroyed = TRUE;
657afb33796f8216c568ad813627da89970760beTimo Sirainen auth_request_handler_unref(&handler);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainenvoid auth_request_handler_set(struct auth_request_handler *handler,
657afb33796f8216c568ad813627da89970760beTimo Sirainen unsigned int connect_uid,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int client_pid)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
657afb33796f8216c568ad813627da89970760beTimo Sirainen handler->connect_uid = connect_uid;
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen handler->client_pid = client_pid;
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen}
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainenstatic void auth_request_handler_remove(struct auth_request_handler *handler,
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen struct auth_request *request)
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen{
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen i_assert(request->handler == handler);
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen
e69e7b734b625de1f8921b7e0d92afa1df6b900dTimo Sirainen if (request->removed_from_handler) {
e69e7b734b625de1f8921b7e0d92afa1df6b900dTimo Sirainen /* already removed it */
e69e7b734b625de1f8921b7e0d92afa1df6b900dTimo Sirainen return;
e69e7b734b625de1f8921b7e0d92afa1df6b900dTimo Sirainen }
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen request->removed_from_handler = TRUE;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainen /* if db lookup is stuck, this call doesn't actually free the auth
657afb33796f8216c568ad813627da89970760beTimo Sirainen request, so make sure we don't get back here. */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen timeout_remove(&request->to_abort);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen hash_table_remove(handler->requests, POINTER_CAST(request->id));
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen auth_request_unref(&request);
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen}
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void get_client_extra_fields(struct auth_request *request,
bbf81c8fc6f21382707673dc6bd7b87ffc27981bTimo Sirainen struct auth_stream_reply *reply)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen{
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen const char **fields, *extra_fields;
bbf81c8fc6f21382707673dc6bd7b87ffc27981bTimo Sirainen unsigned int src;
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen bool seen_pass = FALSE;
bbf81c8fc6f21382707673dc6bd7b87ffc27981bTimo Sirainen
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen if (auth_stream_is_empty(request->extra_fields))
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen return;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen extra_fields = auth_stream_reply_export(request->extra_fields);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen if (!request->proxy && strstr(extra_fields, "userdb_") == NULL) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* optimization: there are no userdb_* fields, we can just
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen import */
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen auth_stream_reply_import(reply, extra_fields);
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen return;
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen }
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen fields = t_strsplit_tab(extra_fields);
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen for (src = 0; fields[src] != NULL; src++) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (strncmp(fields[src], "userdb_", 7) != 0) {
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen if (!seen_pass && strncmp(fields[src], "pass=", 5) == 0)
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen seen_pass = TRUE;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen auth_stream_reply_import(reply, fields[src]);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (request->proxy) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* we're proxying */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (!seen_pass && request->mech_password != NULL) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* send back the password that was sent by user
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen (not the password in passdb). */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen auth_stream_reply_add(reply, "pass",
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen request->mech_password);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen if (request->master_user != NULL) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* the master username needs to be forwarded */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_stream_reply_add(reply, "master",
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen request->master_user);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen}
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainenstatic void
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainenauth_request_handle_failure(struct auth_request *request,
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen struct auth_stream_reply *reply)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen{
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen struct auth_request_handler *handler = request->handler;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (request->delayed_failure) {
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen /* we came here from flush_failures() */
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen handler->callback(reply, handler->context);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen return;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen /* remove the request from requests-list */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_request_ref(request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_handler_remove(handler, request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (request->no_failure_delay) {
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen /* passdb specifically requested not to delay the reply. */
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen handler->callback(reply, handler->context);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_unref(&request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen return;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen /* failure. don't announce it immediately to avoid
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen a) timing attacks, b) flooding */
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen request->delayed_failure = TRUE;
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen handler->refcount++;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen if (auth_penalty != NULL) {
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_penalty_update(auth_penalty, request,
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen request->last_penalty + 1);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo 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 =
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen timeout_add(AUTH_FAILURE_DELAY_CHECK_MSECS,
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen auth_failure_timeout, NULL);
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenstatic void
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenauth_request_handler_reply_success_finish(struct auth_request *request)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen struct auth_request_handler *handler = request->handler;
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen struct auth_stream_reply *reply;
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen if (request->last_penalty != 0 && auth_penalty != NULL) {
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen /* reset penalty */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_penalty_update(auth_penalty, request, 0);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "OK", NULL);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "user", request->user);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen get_client_extra_fields(request, reply);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (request->no_login || handler->master_callback == NULL) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* this request doesn't have to wait for master
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen process to pick it up. delete it */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_request_handler_remove(handler, request);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->callback(reply, handler->context);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
0fec6dfc23e568bae53f03c9491df7f64473dd67Timo Sirainen
3d8f3c378de13e32018e2b116f6b67bd69cd28fbTimo Sirainenstatic void
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainenauth_request_handler_reply_failure_finish(struct auth_request *request)
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen{
1cc683c5d442a1a3bed5a18c1fb37180cb7ef84bTimo Sirainen struct auth_stream_reply *reply;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "FAIL", NULL);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (request->user != NULL)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_stream_reply_add(reply, "user", request->user);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen else if (request->original_username != NULL) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "user",
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen request->original_username);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (request->internal_failure)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_stream_reply_add(reply, "temp", NULL);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen else if (request->master_user != NULL) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* authentication succeeded, but we can't log in
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen as the wanted user */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "authz", NULL);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (request->no_failure_delay)
0fec6dfc23e568bae53f03c9491df7f64473dd67Timo Sirainen auth_stream_reply_add(reply, "nodelay", NULL);
0fec6dfc23e568bae53f03c9491df7f64473dd67Timo Sirainen get_client_extra_fields(request, reply);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_request_handle_failure(request, reply);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
708ea1c397d89586af66c97d74c907f3f2b95134Timo Sirainenstatic void
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenauth_request_handler_proxy_callback(bool success, struct auth_request *request)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen{
708ea1c397d89586af66c97d74c907f3f2b95134Timo Sirainen struct auth_request_handler *handler = request->handler;
708ea1c397d89586af66c97d74c907f3f2b95134Timo Sirainen
708ea1c397d89586af66c97d74c907f3f2b95134Timo Sirainen if (success)
708ea1c397d89586af66c97d74c907f3f2b95134Timo Sirainen auth_request_handler_reply_success_finish(request);
708ea1c397d89586af66c97d74c907f3f2b95134Timo Sirainen else
e5dec382163b476bed16dbf7eb470913a9bbdbe1Timo Sirainen auth_request_handler_reply_failure_finish(request);
e5dec382163b476bed16dbf7eb470913a9bbdbe1Timo Sirainen auth_request_handler_unref(&handler);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenvoid auth_request_handler_reply(struct auth_request *request,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen enum auth_client_result result,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen const void *auth_reply, size_t reply_size)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request_handler *handler = request->handler;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct auth_stream_reply *reply;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen string_t *str;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen int ret;
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen if (handler->destroyed) {
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen /* the client connection was already closed. we can't do
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen anything but abort this request */
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen request->internal_failure = TRUE;
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen result = AUTH_CLIENT_RESULT_FAILURE;
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen /* make sure this request is set to finished state
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen (it's not with result=continue) */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_set_state(request, AUTH_REQUEST_STATE_FINISHED);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen switch (result) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen case AUTH_CLIENT_RESULT_CONTINUE:
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_stream_reply_add(reply, "CONT", NULL);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen str = t_str_new(MAX_BASE64_ENCODED_SIZE(reply_size));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen base64_encode(auth_reply, reply_size, str);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_stream_reply_add(reply, NULL, str_c(str));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->accept_input = TRUE;
657afb33796f8216c568ad813627da89970760beTimo Sirainen handler->callback(reply, handler->context);
657afb33796f8216c568ad813627da89970760beTimo Sirainen break;
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen case AUTH_CLIENT_RESULT_SUCCESS:
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen if (reply_size > 0) {
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen str = t_str_new(MAX_BASE64_ENCODED_SIZE(reply_size));
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen base64_encode(auth_reply, reply_size, str);
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen auth_stream_reply_add(request->extra_fields, "resp", str_c(str));
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen }
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen ret = auth_request_proxy_finish(request,
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen auth_request_handler_proxy_callback);
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen if (ret < 0)
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen auth_request_handler_reply_failure_finish(request);
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen else if (ret > 0)
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen auth_request_handler_reply_success_finish(request);
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen else
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen return;
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen break;
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen case AUTH_CLIENT_RESULT_FAILURE:
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen auth_request_proxy_finish_failure(request);
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen auth_request_handler_reply_failure_finish(request);
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen break;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen }
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen /* NOTE: request may be destroyed now */
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen auth_request_handler_unref(&handler);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen}
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainenvoid auth_request_handler_reply_continue(struct auth_request *request,
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen const void *reply, size_t reply_size)
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen{
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen auth_request_handler_reply(request, AUTH_CLIENT_RESULT_CONTINUE,
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen reply, reply_size);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen}
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainenstatic void auth_request_handler_auth_fail(struct auth_request_handler *handler,
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen struct auth_request *request,
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen const char *reason)
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen{
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen struct auth_stream_reply *reply;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen auth_request_log_info(request, request->mech->mech_name, "%s", reason);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen auth_stream_reply_add(reply, "FAIL", NULL);
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen auth_stream_reply_add(reply, "reason", reason);
657afb33796f8216c568ad813627da89970760beTimo Sirainen
7242e1ce7803b83bc82e239ef111b47c1c72dd4bAndrey Panin handler->callback(reply, handler->context);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_remove(handler, request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void auth_request_timeout(struct auth_request *request)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen const char *str;
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen str = t_strdup_printf("Request %u.%u timeouted after %u secs, state=%d",
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->handler->client_pid, request->id,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen (unsigned int)(time(NULL) - request->last_access),
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen request->state);
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen if (request->state != AUTH_REQUEST_STATE_MECH_CONTINUE) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* client's fault */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_log_error(request, request->mech->mech_name,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "%s", str);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen } else if (request->set->verbose) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_log_info(request, request->mech->mech_name,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "%s", str);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_remove(request->handler, request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void auth_request_penalty_finish(struct auth_request *request)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen timeout_remove(&request->to_penalty);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_initial(request);
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen}
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenauth_penalty_callback(unsigned int penalty, struct auth_request *request)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int secs;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->last_penalty = penalty;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (penalty == 0)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_initial(request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen else {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen secs = auth_penalty_to_secs(penalty);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->to_penalty = timeout_add(secs * 1000,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_penalty_finish,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainenbool auth_request_handler_auth_begin(struct auth_request_handler *handler,
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen const char *args)
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen{
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen const struct mech_module *mech;
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen struct auth_request *request;
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen const char *const *list, *name, *arg, *initial_resp;
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen void *initial_resp_data;
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen unsigned int id;
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen buffer_t *buf;
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen i_assert(!handler->destroyed);
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen /* <id> <mechanism> [...] */
7904d81873b36f8464c96be415881f92518452e6Timo Sirainen list = t_strsplit_tab(args);
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen if (list[0] == NULL || list[1] == NULL ||
66d2db642fe24d555d113ba463e446b038d476efTimo 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
7904d81873b36f8464c96be415881f92518452e6Timo Sirainen mech = mech_module_find(list[1]);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (mech == NULL) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* unsupported mechanism */
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen i_error("BUG: Authentication client %u requested unsupported "
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen "authentication mechanism %s", handler->client_pid,
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen str_sanitize(list[1], MAX_MECH_NAME_LEN));
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen return FALSE;
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen }
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen request = auth_request_new(mech);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->handler = handler;
d99107ddf4d9bccb710994482daf65276a9d6321Timo Sirainen request->connect_uid = handler->connect_uid;
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen request->client_pid = handler->client_pid;
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen request->id = id;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen /* parse optional parameters */
258ff7d4f03dd9d29eca3664e4acacdf7f528234Timo 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 {
4f2248a8a70985c7295afc3bf91c848e81d740d9Timo Sirainen name = t_strdup_until(*list, arg);
4f2248a8a70985c7295afc3bf91c848e81d740d9Timo Sirainen arg++;
4f2248a8a70985c7295afc3bf91c848e81d740d9Timo Sirainen }
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (auth_request_import_auth(request, name, arg))
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen ;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen else if (strcmp(name, "resp") == 0) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen initial_resp = arg;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* this must be the last parameter */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen list++;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen break;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen if (*list != NULL) {
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen i_error("BUG: Authentication client %u "
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen "sent AUTH parameters after 'resp'",
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen handler->client_pid);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_unref(&request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return FALSE;
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen }
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (request->service == NULL) {
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen i_error("BUG: Authentication client %u "
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen "didn't specify service in request",
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen handler->client_pid);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_unref(&request);
657afb33796f8216c568ad813627da89970760beTimo Sirainen return FALSE;
657afb33796f8216c568ad813627da89970760beTimo Sirainen }
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (hash_table_lookup(handler->requests, POINTER_CAST(id)) != NULL) {
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen i_error("BUG: Authentication client %u "
657afb33796f8216c568ad813627da89970760beTimo Sirainen "sent a duplicate ID %u", handler->client_pid, id);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_unref(&request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return FALSE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_init(request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->to_abort = timeout_add(MASTER_AUTH_SERVER_TIMEOUT_SECS * 1000,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_timeout, request);
c53a3c54d388c0031aaa642e6b14d46eb86d9485Timo Sirainen hash_table_insert(handler->requests, POINTER_CAST(id), request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (request->set->ssl_require_client_cert &&
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen !request->valid_client_cert) {
ccb77e2f63626ec46e5745ef4f38baa8e8e504fcTimo Sirainen /* we fail without valid certificate */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_auth_fail(handler, request,
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen "Client didn't present valid SSL certificate");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* Empty initial response is a "=" base64 string. Completely empty
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen string shouldn't really be sent, but at least Exim does it,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen so just allow it for backwards compatibility.. */
cac6735a6cd73f2b815a1f3c1e21855075e7c81eTimo Sirainen if (initial_resp != NULL && *initial_resp != '\0') {
cac6735a6cd73f2b815a1f3c1e21855075e7c81eTimo Sirainen size_t len = strlen(initial_resp);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo 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 }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen initial_resp_data =
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen p_malloc(request->pool, I_MAX(buf->used, 1));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen memcpy(initial_resp_data, buf->data, buf->used);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->initial_response = initial_resp_data;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->initial_response_len = buf->used;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* handler is referenced until auth_request_handler_reply()
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen is called. */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->refcount++;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* before we start authenticating, see if we need to wait first */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_penalty_lookup(auth_penalty, request, auth_penalty_callback);
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen return TRUE;
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenbool auth_request_handler_auth_continue(struct auth_request_handler *handler,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen const char *args)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen const char *data;
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen size_t data_len;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buffer_t *buf;
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen unsigned int id;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen data = strchr(args, '\t');
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (data == NULL || str_to_uint(t_strdup_until(args, data), &id) < 0) {
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen i_error("BUG: Authentication client sent broken CONT request");
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen return FALSE;
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen }
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen data++;
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen request = hash_table_lookup(handler->requests, POINTER_CAST(id));
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen if (request == NULL) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct auth_stream_reply *reply;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "FAIL", NULL);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(id));
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen auth_stream_reply_add(reply, "reason",
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen "Authentication request timed out");
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen handler->callback(reply, handler->context);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen return TRUE;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen }
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen /* accept input only once after mechanism has sent a CONT reply */
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen if (!request->accept_input) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_request_handler_auth_fail(handler, request,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen "Unexpected continuation");
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen return TRUE;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen request->accept_input = FALSE;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
7e078be0d6f12ca56860641d36e3c517e3046895Timo Sirainen data_len = strlen(data);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen buf = buffer_create_dynamic(pool_datastack_create(),
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen MAX_BASE64_DECODED_SIZE(data_len));
7e078be0d6f12ca56860641d36e3c517e3046895Timo Sirainen if (base64_decode(data, data_len, NULL, buf) < 0) {
7e078be0d6f12ca56860641d36e3c517e3046895Timo Sirainen auth_request_handler_auth_fail(handler, request,
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen "Invalid base64 data in continued response");
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen return TRUE;
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen }
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen /* handler is referenced until auth_request_handler_reply()
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen is called. */
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen handler->refcount++;
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen auth_request_continue(request, buf->data, buf->used);
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen return TRUE;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen}
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainenstatic void userdb_callback(enum userdb_result result,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request_handler *handler = request->handler;
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen struct auth_stream_reply *reply;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen const char *value;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainen i_assert(request->state == AUTH_REQUEST_STATE_USERDB);
657afb33796f8216c568ad813627da89970760beTimo Sirainen
daa7e7459749ae8f82cd3eed9c44522d81c609a3Timo Sirainen auth_request_set_state(request, AUTH_REQUEST_STATE_FINISHED);
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainen if (request->userdb_lookup_failed)
657afb33796f8216c568ad813627da89970760beTimo Sirainen result = USERDB_RESULT_INTERNAL_FAILURE;
657afb33796f8216c568ad813627da89970760beTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen switch (result) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen case USERDB_RESULT_INTERNAL_FAILURE:
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "FAIL", NULL);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen if (request->userdb_lookup_failed) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen value = auth_stream_reply_find(request->userdb_reply,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "reason");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (value != NULL)
647eed98cb795ee9e42911750402dab720b57514Timo Sirainen auth_stream_reply_add(reply, "reason", value);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
daa7e7459749ae8f82cd3eed9c44522d81c609a3Timo Sirainen break;
daa7e7459749ae8f82cd3eed9c44522d81c609a3Timo Sirainen case USERDB_RESULT_USER_UNKNOWN:
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "NOTFOUND", NULL);
daa7e7459749ae8f82cd3eed9c44522d81c609a3Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen break;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen case USERDB_RESULT_OK:
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_stream_reply_add(reply, "USER", NULL);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (request->master_user != NULL &&
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen auth_stream_reply_find(request->userdb_reply,
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen "master_user") == NULL) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_stream_reply_add(request->userdb_reply,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "master_user",
647eed98cb795ee9e42911750402dab720b57514Timo Sirainen request->master_user);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (*request->set->anonymous_username != '\0' &&
0a8ec3c561c26c492a50511692650ea302cc8c14Timo Sirainen strcmp(request->user,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->set->anonymous_username) == 0) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* this is an anonymous login, either via ANONYMOUS
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen SASL mechanism or simply logging in as the anonymous
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen user via another mechanism */
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen auth_stream_reply_add(request->userdb_reply,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "anonymous", NULL);
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_stream_reply_import(reply,
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen auth_stream_reply_export(request->userdb_reply));
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen break;
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->master_callback(reply, request->master);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_master_connection_unref(&request->master);
daa7e7459749ae8f82cd3eed9c44522d81c609a3Timo Sirainen auth_request_unref(&request);
657afb33796f8216c568ad813627da89970760beTimo Sirainen auth_request_handler_unref(&handler);
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainenbool auth_request_handler_master_request(struct auth_request_handler *handler,
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen struct auth_master_connection *master,
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen unsigned int id,
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen unsigned int client_id)
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen{
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen struct auth_request *request;
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen struct auth_stream_reply *reply;
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainen request = hash_table_lookup(handler->requests, POINTER_CAST(client_id));
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (request == NULL) {
a550b0fbcf7e876eeb88f4528209ed28cc416752Timo Sirainen i_error("Master request %u.%u not found",
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen handler->client_pid, client_id);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_stream_reply_add(reply, "FAIL", NULL);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(id));
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (handler->master_callback == NULL)
a3b3e5b452be15049a1f8bfd5b3bb640af41121cTimo Sirainen return FALSE;
a3b3e5b452be15049a1f8bfd5b3bb640af41121cTimo Sirainen handler->master_callback(reply, master);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen return TRUE;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_ref(request);
a550b0fbcf7e876eeb88f4528209ed28cc416752Timo Sirainen auth_request_handler_remove(handler, request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (request->state != AUTH_REQUEST_STATE_FINISHED ||
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen !request->successful) {
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen i_error("Master requested unfinished authentication request "
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen "%u.%u", handler->client_pid, client_id);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen auth_stream_reply_add(reply, "FAIL", NULL);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(id));
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen handler->master_callback(reply, master);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_unref(&request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen } else {
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen /* the request isn't being referenced anywhere anymore,
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen so we can do a bit of kludging.. replace the request's
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen old client_id with master's id. */
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_set_state(request, AUTH_REQUEST_STATE_USERDB);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->id = id;
657afb33796f8216c568ad813627da89970760beTimo Sirainen request->master = master;
657afb33796f8216c568ad813627da89970760beTimo Sirainen
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen /* master and handler are referenced until userdb_callback i
657afb33796f8216c568ad813627da89970760beTimo Sirainen s called. */
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_master_connection_ref(master);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->refcount++;
657afb33796f8216c568ad813627da89970760beTimo Sirainen auth_request_lookup_user(request, userdb_callback);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen}
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainenvoid auth_request_handler_cancel_request(struct auth_request_handler *handler,
657afb33796f8216c568ad813627da89970760beTimo Sirainen unsigned int client_id)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
657afb33796f8216c568ad813627da89970760beTimo Sirainen struct auth_request *request;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen request = hash_table_lookup(handler->requests, POINTER_CAST(client_id));
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (request != NULL)
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_handler_remove(handler, request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen}
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainenvoid auth_request_handler_flush_failures(bool flush_all)
{
struct auth_request **auth_requests, *auth_request;
unsigned int i, count;
time_t diff;
count = aqueue_count(auth_failures);
if (count == 0) {
if (to_auth_failures != NULL)
timeout_remove(&to_auth_failures);
return;
}
auth_requests = array_idx_modifiable(&auth_failures_arr, 0);
for (i = 0; i < count; i++) {
auth_request = auth_requests[aqueue_idx(auth_failures, 0)];
/* FIXME: assumess that failure_delay is always the same. */
diff = ioloop_time - auth_request->last_access;
if (diff < (time_t)auth_request->set->failure_delay &&
!flush_all)
break;
aqueue_delete_tail(auth_failures);
i_assert(auth_request->state == AUTH_REQUEST_STATE_FINISHED);
auth_request_handler_reply(auth_request,
AUTH_CLIENT_RESULT_FAILURE, NULL, 0);
auth_request_unref(&auth_request);
}
}
static void auth_failure_timeout(void *context ATTR_UNUSED)
{
auth_request_handler_flush_failures(FALSE);
}
void auth_request_handler_init(void)
{
i_array_init(&auth_failures_arr, 128);
auth_failures = aqueue_init(&auth_failures_arr.arr);
}
void auth_request_handler_deinit(void)
{
auth_request_handler_flush_failures(TRUE);
array_free(&auth_failures_arr);
aqueue_deinit(&auth_failures);
if (to_auth_failures != NULL)
timeout_remove(&to_auth_failures);
}