Skip to content

Commit

Permalink
auth: Fix leaking memory if auth client disconnects with pending pena…
Browse files Browse the repository at this point in the history
…lty delays

 * auth penalty lookup returns that auth_request needs a penalty delay
 * during the penalty timeout auth client disconnects
 * auth requests are freed, but auth_request_handler isn't unreferenced

This resulted in memory leak, and after recent changes also logging warnings
about event leaks.
  • Loading branch information
sirainen committed Aug 28, 2020
1 parent 01a1129 commit 1e3f43e
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/auth/auth-request-handler.c
Expand Up @@ -366,6 +366,8 @@ void auth_request_handler_reply(struct auth_request *request,
const void *auth_reply, size_t reply_size)
{
struct auth_request_handler *handler = request->handler;

request->handler_pending_reply = FALSE;
handler->reply_callback(request, result, auth_reply, reply_size);
}

Expand Down Expand Up @@ -439,6 +441,15 @@ auth_request_handler_default_reply_continue(struct auth_request *request,
reply, reply_size);
}

void auth_request_handler_abort(struct auth_request *request)
{
i_assert(request->handler_pending_reply);

/* request destroyed while waiting for auth_request_penalty_finish()
to be called. */
auth_request_handler_unref(&request->handler);
}

static void
auth_request_handler_auth_fail_code(struct auth_request_handler *handler,
struct auth_request *request,
Expand Down Expand Up @@ -665,6 +676,7 @@ bool auth_request_handler_auth_begin(struct auth_request_handler *handler,
/* handler is referenced until auth_request_handler_reply()
is called. */
handler->refcount++;
request->handler_pending_reply = TRUE;

/* before we start authenticating, see if we need to wait first */
auth_penalty_lookup(auth_penalty, request, auth_penalty_callback);
Expand Down
2 changes: 2 additions & 0 deletions src/auth/auth-request-handler.h
Expand Up @@ -50,6 +50,8 @@ void auth_request_handler_reply(struct auth_request *request,
const void *reply, size_t reply_size);
void auth_request_handler_reply_continue(struct auth_request *request,
const void *reply, size_t reply_size);
void auth_request_handler_abort(struct auth_request *request);

unsigned int
auth_request_handler_get_request_count(struct auth_request_handler *handler);
bool auth_request_handler_master_request(struct auth_request_handler *handler,
Expand Down
3 changes: 3 additions & 0 deletions src/auth/auth-request.c
Expand Up @@ -331,6 +331,9 @@ void auth_request_unref(struct auth_request **_request)

i_assert(array_count(&request->authdb_event) == 0);

if (request->handler_pending_reply)
auth_request_handler_abort(request);

event_unref(&request->mech_event);
event_unref(&request->event);
auth_request_stats_send(request);
Expand Down
1 change: 1 addition & 0 deletions src/auth/auth-request.h
Expand Up @@ -176,6 +176,7 @@ struct auth_request {
bool userdbs_seen_internal_failure:1;

/* current state: */
bool handler_pending_reply:1;
bool accept_cont_input:1;
bool prefer_plain_credentials:1;
bool in_delayed_failure_queue:1;
Expand Down

0 comments on commit 1e3f43e

Please sign in to comment.