auth-request-handler.c revision 52d3cbc21e8fe482b9b8c832f3921824a7aa6ebe
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (C) 2005 Timo Sirainen */
657afb33796f8216c568ad813627da89970760beTimo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "common.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "ioloop.h"
a550b0fbcf7e876eeb88f4528209ed28cc416752Timo Sirainen#include "buffer.h"
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen#include "base64.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "hash.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "str.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "str-sanitize.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "auth-request.h"
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen#include "auth-request-handler.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen#include <stdlib.h>
657afb33796f8216c568ad813627da89970760beTimo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainenstruct auth_request_handler {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen int refcount;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen pool_t pool;
a3b3e5b452be15049a1f8bfd5b3bb640af41121cTimo Sirainen struct hash_table *requests;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth *auth;
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;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen};
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic buffer_t *auth_failures_buf;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic struct timeout *to_auth_failures;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstruct auth_request_handler *
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenauth_request_handler_create(struct auth *auth,
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_callback_t *callback, void *context,
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_callback_t *master_callback)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
657afb33796f8216c568ad813627da89970760beTimo Sirainen struct auth_request_handler *handler;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen pool_t pool;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen pool = pool_alloconly_create("auth request handler", 4096);
657afb33796f8216c568ad813627da89970760beTimo Sirainen
9b62bbaf33d4516b5dffb36c3ea32ce217e7fbb1Timo Sirainen handler = p_new(pool, struct auth_request_handler, 1);
657afb33796f8216c568ad813627da89970760beTimo Sirainen handler->refcount = 1;
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen handler->pool = pool;
657afb33796f8216c568ad813627da89970760beTimo Sirainen handler->requests = hash_create(default_pool, pool, 0, NULL, NULL);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->auth = auth;
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
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenvoid auth_request_handler_unref(struct auth_request_handler **_handler)
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request_handler *handler = *_handler;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct hash_iterate_context *iter;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen void *key, *value;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen *_handler = NULL;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_assert(handler->refcount > 0);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (--handler->refcount > 0)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen iter = hash_iterate_init(handler->requests);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen while (hash_iterate(iter, &key, &value)) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *auth_request = value;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_unref(&auth_request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen hash_iterate_deinit(iter);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* notify parent that we're done with all requests */
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen handler->callback(NULL, handler->context);
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen
b1e6ea3323b4d753909f79226a8a98d854f819faTimo Sirainen hash_destroy(handler->requests);
b1e6ea3323b4d753909f79226a8a98d854f819faTimo Sirainen pool_unref(handler->pool);
b1e6ea3323b4d753909f79226a8a98d854f819faTimo Sirainen}
b1e6ea3323b4d753909f79226a8a98d854f819faTimo Sirainen
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainenvoid auth_request_handler_set(struct auth_request_handler *handler,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int connect_uid,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int client_pid)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->connect_uid = connect_uid;
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen handler->client_pid = client_pid;
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainenstatic void auth_request_handler_remove(struct auth_request_handler *handler,
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen struct auth_request *request)
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen{
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen hash_remove(handler->requests, POINTER_CAST(request->id));
657afb33796f8216c568ad813627da89970760beTimo Sirainen auth_request_unref(&request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainenvoid auth_request_handler_check_timeouts(struct auth_request_handler *handler)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct hash_iterate_context *iter;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen void *key, *value;
657afb33796f8216c568ad813627da89970760beTimo Sirainen
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen iter = hash_iterate_init(handler->requests);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen while (hash_iterate(iter, &key, &value)) {
657afb33796f8216c568ad813627da89970760beTimo Sirainen struct auth_request *request = value;
657afb33796f8216c568ad813627da89970760beTimo Sirainen
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen if (request->created + AUTH_REQUEST_TIMEOUT < ioloop_time)
657afb33796f8216c568ad813627da89970760beTimo Sirainen auth_request_handler_remove(handler, request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen hash_iterate_deinit(iter);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainenstatic const char *get_client_extra_fields(struct auth_request *request)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen string_t *str;
fda2c460c58f50bf035680187be606542a8c1dacTimo Sirainen const char **fields, *extra_fields;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int src, dest;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen bool seen_pass = FALSE;
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen extra_fields = request->extra_fields == NULL ? NULL :
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_stream_reply_export(request->extra_fields);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (!request->proxy) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (extra_fields == NULL)
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen return NULL;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen /* we only wish to remove all fields prefixed with "userdb_" */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (strstr(extra_fields, "userdb_") == NULL)
bbf81c8fc6f21382707673dc6bd7b87ffc27981bTimo Sirainen return extra_fields;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen
bbf81c8fc6f21382707673dc6bd7b87ffc27981bTimo Sirainen str = t_str_new(128);
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen fields = t_strsplit(extra_fields, "\t");
bbf81c8fc6f21382707673dc6bd7b87ffc27981bTimo Sirainen for (src = dest = 0; fields[src] != NULL; src++) {
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen if (strncmp(fields[src], "userdb_", 7) != 0) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (str_len(str) > 0)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen str_append_c(str, '\t');
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (!seen_pass && strncmp(fields[src], "pass=", 5) == 0)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen seen_pass = TRUE;
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen str_append(str, fields[src]);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen if (request->proxy && !seen_pass && request->mech_password != NULL) {
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen /* we're proxying - send back the password that was
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen sent by user (not the password in passdb). */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen str_printfa(str, "\tpass=%s", request->mech_password);
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen return str_len(str) == 0 ? NULL : str_c(str);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen}
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainenstatic void auth_callback(struct auth_request *request,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen enum auth_client_result result,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen const void *reply, size_t reply_size)
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen{
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen struct auth_request_handler *handler = request->context;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen string_t *str;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen const char *fields;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen t_push();
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen str = t_str_new(128 + MAX_BASE64_ENCODED_SIZE(reply_size));
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen switch (result) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen case AUTH_CLIENT_RESULT_CONTINUE:
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen str_printfa(str, "CONT\t%u\t", request->id);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen base64_encode(reply, reply_size, str);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen request->accept_input = TRUE;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen handler->callback(str_c(str), handler->context);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen break;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen case AUTH_CLIENT_RESULT_SUCCESS:
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen str_printfa(str, "OK\t%u\tuser=%s", request->id, request->user);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (reply_size > 0) {
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen str_append(str, "\tresp=");
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen base64_encode(reply, reply_size, str);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen fields = get_client_extra_fields(request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (fields != NULL) {
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen str_append_c(str, '\t');
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen str_append(str, fields);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (request->no_login || handler->master_callback == NULL) {
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen /* this request doesn't have to wait for master
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen process to pick it up. delete it */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_request_handler_remove(handler, request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen handler->callback(str_c(str), handler->context);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen break;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen case AUTH_CLIENT_RESULT_FAILURE:
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen str_printfa(str, "FAIL\t%u", request->id);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (request->user != NULL)
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen str_printfa(str, "\tuser=%s", request->user);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (request->internal_failure)
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen str_append(str, "\ttemp");
f42581dd841281a4434e5c52488e0eda9716c891Timo Sirainen fields = get_client_extra_fields(request);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen if (fields != NULL) {
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen str_append_c(str, '\t');
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen str_append(str, fields);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (request->delayed_failure) {
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen /* we came here from flush_failures() */
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen handler->callback(str_c(str), handler->context);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen break;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* remove the request from requests-list */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_ref(request);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_request_handler_remove(handler, request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (request->no_failure_delay) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* passdb specifically requested not to delay the
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen reply. */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->callback(str_c(str), handler->context);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_request_unref(&request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen } else {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* failure. don't announce it immediately to avoid
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen a) timing attacks, b) flooding */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen request->delayed_failure = TRUE;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen handler->refcount++;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen buffer_append(auth_failures_buf,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen &request, sizeof(request));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen break;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* NOTE: request may be destroyed now */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_unref(&handler);
0fec6dfc23e568bae53f03c9491df7f64473dd67Timo Sirainen
3d8f3c378de13e32018e2b116f6b67bd69cd28fbTimo Sirainen t_pop();
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen}
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
f42581dd841281a4434e5c52488e0eda9716c891Timo Sirainenstatic void auth_request_handler_auth_fail(struct auth_request_handler *handler,
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen struct auth_request *request,
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen const char *reason)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen{
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen string_t *reply = t_str_new(64);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_log_info(request, request->mech->mech_name, "%s", reason);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen str_printfa(reply, "FAIL\t%u\treason=%s", request->id, reason);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen handler->callback(str_c(reply), handler->context);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_request_handler_remove(handler, request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenbool auth_request_handler_auth_begin(struct auth_request_handler *handler,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen const char *args)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct mech_module *mech;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen const char *const *list, *name, *arg, *initial_resp;
0fec6dfc23e568bae53f03c9491df7f64473dd67Timo Sirainen const void *initial_resp_data;
0fec6dfc23e568bae53f03c9491df7f64473dd67Timo Sirainen size_t initial_resp_len;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen unsigned int id;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen buffer_t *buf;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen bool valid_client_cert;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
708ea1c397d89586af66c97d74c907f3f2b95134Timo Sirainen /* <id> <mechanism> [...] */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen list = t_strsplit(args, "\t");
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (list[0] == NULL || list[1] == NULL) {
708ea1c397d89586af66c97d74c907f3f2b95134Timo Sirainen i_error("BUG: Authentication client %u "
708ea1c397d89586af66c97d74c907f3f2b95134Timo Sirainen "sent broken AUTH request", handler->client_pid);
708ea1c397d89586af66c97d74c907f3f2b95134Timo Sirainen return FALSE;
708ea1c397d89586af66c97d74c907f3f2b95134Timo Sirainen }
708ea1c397d89586af66c97d74c907f3f2b95134Timo Sirainen
e5dec382163b476bed16dbf7eb470913a9bbdbe1Timo Sirainen id = (unsigned int)strtoul(list[0], NULL, 10);
e5dec382163b476bed16dbf7eb470913a9bbdbe1Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen mech = mech_module_find(list[1]);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (mech == NULL) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* unsupported mechanism */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_error("BUG: Authentication client %u requested unsupported "
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "authentication mechanism %s", handler->client_pid,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen str_sanitize(list[1], MAX_MECH_NAME_LEN));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return FALSE;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request = auth_request_new(handler->auth, mech, auth_callback, handler);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->connect_uid = handler->connect_uid;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->client_pid = handler->client_pid;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->id = id;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* parse optional parameters */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen initial_resp = NULL;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen valid_client_cert = FALSE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen for (list += 2; *list != NULL; list++) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen arg = strchr(*list, '=');
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (arg == NULL) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen name = *list;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen arg = "";
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen } else {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen name = t_strdup_until(*list, arg);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen arg++;
657afb33796f8216c568ad813627da89970760beTimo Sirainen }
657afb33796f8216c568ad813627da89970760beTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen if (auth_request_import(request, name, arg))
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen ;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen else if (strcmp(name, "valid-client-cert") == 0)
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen valid_client_cert = TRUE;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen else if (strcmp(name, "resp") == 0) {
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen initial_resp = arg;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen /* this must be the last parameter */
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen list++;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen break;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen }
e76073ebaf90fa29abfdc364873acf78983949aaTimo 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);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen return FALSE;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen }
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen if (request->service == NULL) {
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen i_error("BUG: Authentication client %u "
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen "didn't specify service in request",
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen handler->client_pid);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen return FALSE;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen }
657afb33796f8216c568ad813627da89970760beTimo Sirainen
7242e1ce7803b83bc82e239ef111b47c1c72dd4bAndrey Panin hash_insert(handler->requests, POINTER_CAST(id), request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (request->auth->ssl_require_client_cert && !valid_client_cert) {
e76073ebaf90fa29abfdc364873acf78983949aaTimo 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
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (initial_resp == NULL) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen initial_resp_data = NULL;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen initial_resp_len = 0;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen } else {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen size_t len = strlen(initial_resp);
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 = buf->data;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen initial_resp_len = buf->used;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* handler is referenced until auth_callback is called. */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->refcount++;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_initial(request, initial_resp_data, initial_resp_len);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
66d2db642fe24d555d113ba463e446b038d476efTimo 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;
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');
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (data++ == NULL) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_error("BUG: Authentication client sent broken CONT request");
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen return FALSE;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen }
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen id = (unsigned int)strtoul(args, NULL, 10);
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen request = hash_lookup(handler->requests, POINTER_CAST(id));
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen if (request == NULL) {
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen string_t *reply = t_str_new(64);
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen str_printfa(reply, "FAIL\t%u\treason=Timeouted", id);
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen handler->callback(str_c(reply), handler->context);
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen return TRUE;
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen }
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen /* accept input only once after mechanism has sent a CONT reply */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (!request->accept_input) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_auth_fail(handler, request,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "Unexpected continuation");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->accept_input = FALSE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen data_len = strlen(data);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buf = buffer_create_dynamic(pool_datastack_create(),
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen MAX_BASE64_DECODED_SIZE(data_len));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (base64_decode(data, data_len, NULL, buf) < 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen auth_request_handler_auth_fail(handler, request,
258ff7d4f03dd9d29eca3664e4acacdf7f528234Timo Sirainen "Invalid base64 data in continued response");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* handler is referenced until auth_callback is called. */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->refcount++;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_continue(request, buf->data, buf->used);
4f2248a8a70985c7295afc3bf91c848e81d740d9Timo Sirainen return TRUE;
4f2248a8a70985c7295afc3bf91c848e81d740d9Timo Sirainen}
4f2248a8a70985c7295afc3bf91c848e81d740d9Timo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainenstatic void userdb_callback(struct auth_stream_reply *reply,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request)
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request_handler *handler = request->context;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen string_t *str;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_assert(request->state == AUTH_REQUEST_STATE_USERDB);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->state = AUTH_REQUEST_STATE_FINISHED;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen str = t_str_new(256);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen if (reply == NULL)
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen str_printfa(str, "NOTFOUND\t%u", request->id);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen else {
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen if (request->master_user != NULL) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_stream_reply_add(reply, "master_user",
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->master_user);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen str_printfa(str, "USER\t%u\t", request->id);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen str_append(str, auth_stream_reply_export(reply));
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen }
f42581dd841281a4434e5c52488e0eda9716c891Timo Sirainen handler->master_callback(str_c(str), request->master);
f42581dd841281a4434e5c52488e0eda9716c891Timo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_unref(&request);
657afb33796f8216c568ad813627da89970760beTimo Sirainen auth_request_handler_unref(&handler);
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenvoid auth_request_handler_master_request(struct auth_request_handler *handler,
657afb33796f8216c568ad813627da89970760beTimo Sirainen struct auth_master_connection *master,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int id,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int client_id)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen string_t *reply;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen reply = t_str_new(64);
ccb77e2f63626ec46e5745ef4f38baa8e8e504fcTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request = hash_lookup(handler->requests, POINTER_CAST(client_id));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (request == NULL) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_error("Master request %u.%u not found",
ccb77e2f63626ec46e5745ef4f38baa8e8e504fcTimo Sirainen handler->client_pid, client_id);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen str_printfa(reply, "NOTFOUND\t%u", id);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->master_callback(str_c(reply), master);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return;
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_request_ref(request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_remove(handler, request);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (request->state != AUTH_REQUEST_STATE_FINISHED ||
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen !request->successful) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen i_error("Master requested unfinished authentication request "
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen "%u.%u", handler->client_pid, client_id);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen str_printfa(reply, "NOTFOUND\t%u", id);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->master_callback(str_c(reply), master);
66d2db642fe24d555d113ba463e446b038d476efTimo 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. */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->state = AUTH_REQUEST_STATE_USERDB;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->id = id;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->context = handler;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->master = master;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* handler is referenced until userdb_callback is called. */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->refcount++;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_lookup_user(request, userdb_callback);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenvoid auth_request_handler_flush_failures(void)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request **auth_request;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen size_t i, size;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request = buffer_get_modifiable_data(auth_failures_buf, &size);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen size /= sizeof(*auth_request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen for (i = 0; i < size; i++) {
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen i_assert(auth_request[i]->state == AUTH_REQUEST_STATE_FINISHED);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request[i]->callback(auth_request[i],
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen AUTH_CLIENT_RESULT_FAILURE, NULL, 0);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_request_unref(&auth_request[i]);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen buffer_set_used_size(auth_failures_buf, 0);
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen}
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainenstatic void auth_failure_timeout(void *context __attr_unused__)
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen{
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen auth_request_handler_flush_failures();
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen}
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainenvoid auth_request_handler_init(void)
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen{
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_failures_buf = buffer_create_dynamic(default_pool, 1024);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen to_auth_failures = timeout_add(2000, auth_failure_timeout, NULL);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen}
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenvoid auth_request_handler_deinit(void)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen{
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen buffer_free(auth_failures_buf);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen timeout_remove(&to_auth_failures);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen}
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen