<commit_before>/* Copyright (c) 2005-2010 Dovecot authors, see the included COPYING file */

#include "auth-common.h"
#include "ioloop.h"
#include "array.h"
#include "aqueue.h"
#include "base64.h"
#include "hash.h"
#include "str.h"
#include "str-sanitize.h"
#include "auth-penalty.h"
#include "auth-request.h"
#include "auth-master-connection.h"
#include "auth-request-handler.h"

#include <stdlib.h>

#define AUTH_FAILURE_DELAY_CHECK_MSECS 500

struct auth_request_handler {
	int refcount;
	pool_t pool;
	struct hash_table *requests;

        unsigned int connect_uid, client_pid;

	auth_request_callback_t *callback;
	void *context;

	auth_request_callback_t *master_callback;
};

static ARRAY_DEFINE(auth_failures_arr, struct auth_request *);
static struct aqueue *auth_failures;
static struct timeout *to_auth_failures;

static void auth_failure_timeout(void *context);

#undef auth_request_handler_create
struct auth_request_handler *
auth_request_handler_create(auth_request_callback_t *callback, void *context,
			    auth_request_callback_t *master_callback)
{
	struct auth_request_handler *handler;
	pool_t pool;

	pool = pool_alloconly_create("auth request handler", 4096);

	handler = p_new(pool, struct auth_request_handler, 1);
	handler->refcount = 1;
	handler->pool = pool;
	handler->requests = hash_table_create(default_pool, pool, 0, NULL, NULL);
	handler->callback = callback;
	handler->context = context;
	handler->master_callback = master_callback;
	return handler;
}

void auth_request_handler_unref(struct auth_request_handler **_handler)
{
        struct auth_request_handler *handler = *_handler;
	struct hash_iterate_context *iter;
	void *key, *value;

	*_handler = NULL;
	i_assert(handler->refcount > 0);
	if (--handler->refcount > 0)
		return;

	iter = hash_table_iterate_init(handler->requests);
	while (hash_table_iterate(iter, &key, &value)) {
		struct auth_request *auth_request = value;

		auth_request_unref(&auth_request);
	}
	hash_table_iterate_deinit(&iter);

	/* notify parent that we're done with all requests */
	handler->callback(NULL, handler->context);

	hash_table_destroy(&handler->requests);
	pool_unref(&handler->pool);
}

void auth_request_handler_set(struct auth_request_handler *handler,
			      unsigned int connect_uid,
			      unsigned int client_pid)
{
	handler->connect_uid = connect_uid;
	handler->client_pid = client_pid;
}

static void auth_request_handler_remove(struct auth_request_handler *handler,
					struct auth_request *request)
{
	i_assert(request->handler == handler);

	hash_table_remove(handler->requests, POINTER_CAST(request->id));
	auth_request_unref(&request);
}

static void get_client_extra_fields(struct auth_request *request,
				    struct auth_stream_reply *reply)
{
	const char **fields, *extra_fields;
	unsigned int src;
	bool seen_pass = FALSE;

	if (auth_stream_is_empty(request->extra_fields))
		return;

	extra_fields = auth_stream_reply_export(request->extra_fields);

	if (!request->proxy) {
		/* we only wish to remove all fields prefixed with "userdb_" */
		if (strstr(extra_fields, "userdb_") == NULL) {
			auth_stream_reply_import(reply, extra_fields);
			return;
		}
	}

	fields = t_strsplit(extra_fields, "\t");
	for (src = 0; fields[src] != NULL; src++) {<commit_msg>auth: Don't crash when auth requests timeout.<commit_after>/* Copyright (c) 2005-2010 Dovecot authors, see the included COPYING file */

#include "auth-common.h"
#include "ioloop.h"
#include "array.h"
#include "aqueue.h"
#include "base64.h"
#include "hash.h"
#include "str.h"
#include "str-sanitize.h"
#include "auth-penalty.h"
#include "auth-request.h"
#include "auth-master-connection.h"
#include "auth-request-handler.h"

#include <stdlib.h>

#define AUTH_FAILURE_DELAY_CHECK_MSECS 500

struct auth_request_handler {
	int refcount;
	pool_t pool;
	struct hash_table *requests;

        unsigned int connect_uid, client_pid;

	auth_request_callback_t *callback;
	void *context;

	auth_request_callback_t *master_callback;
};

static ARRAY_DEFINE(auth_failures_arr, struct auth_request *);
static struct aqueue *auth_failures;
static struct timeout *to_auth_failures;

static void auth_failure_timeout(void *context);

#undef auth_request_handler_create
struct auth_request_handler *
auth_request_handler_create(auth_request_callback_t *callback, void *context,
			    auth_request_callback_t *master_callback)
{
	struct auth_request_handler *handler;
	pool_t pool;

	pool = pool_alloconly_create("auth request handler", 4096);

	handler = p_new(pool, struct auth_request_handler, 1);
	handler->refcount = 1;
	handler->pool = pool;
	handler->requests = hash_table_create(default_pool, pool, 0, NULL, NULL);
	handler->callback = callback;
	handler->context = context;
	handler->master_callback = master_callback;
	return handler;
}

void auth_request_handler_unref(struct auth_request_handler **_handler)
{
        struct auth_request_handler *handler = *_handler;
	struct hash_iterate_context *iter;
	void *key, *value;

	*_handler = NULL;
	i_assert(handler->refcount > 0);
	if (--handler->refcount > 0)
		return;

	iter = hash_table_iterate_init(handler->requests);
	while (hash_table_iterate(iter, &key, &value)) {
		struct auth_request *auth_request = value;

		auth_request_unref(&auth_request);
	}
	hash_table_iterate_deinit(&iter);

	/* notify parent that we're done with all requests */
	handler->callback(NULL, handler->context);

	hash_table_destroy(&handler->requests);
	pool_unref(&handler->pool);
}

void auth_request_handler_set(struct auth_request_handler *handler,
			      unsigned int connect_uid,
			      unsigned int client_pid)
{
	handler->connect_uid = connect_uid;
	handler->client_pid = client_pid;
}

static void auth_request_handler_remove(struct auth_request_handler *handler,
					struct auth_request *request)
{
	i_assert(request->handler == handler);

	/* if db lookup is stuck, this call doesn't actually free the auth
	   request, so make sure we don't get back here. */
	timeout_remove(&request->to_abort);

	hash_table_remove(handler->requests, POINTER_CAST(request->id));
	auth_request_unref(&request);
}

static void get_client_extra_fields(struct auth_request *request,
				    struct auth_stream_reply *reply)
{
	const char **fields, *extra_fields;
	unsigned int src;
	bool seen_pass = FALSE;

	if (auth_stream_is_empty(request->extra_fields))
		return;

	extra_fields = auth_stream_reply_export(request->extra_fields);

	if (!request->proxy) {
		/* we only wish to remove all fields prefixed with "userdb_" */
		if (strstr(extra_fields, "userdb_") == NULL) {
			auth_stream_reply_import(reply, extra_fields);
			return;
		}
	}

	fields = t_strsplit(extra_fields, "\t");
	for (src = 0; fields[src] != NULL; src++) {
{'fraction_non_alphanumeric': 0.11049888309754281, 'fraction_numerical': 0.006850335070737156, 'mean_word_length': 5.629812438302073, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 52, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3374632', 'n_tokens_mistral': 2342, 'n_tokens_neox': 2189, 'n_words': 512}