From: Timo Sirainen Date: Fri, 3 Nov 2023 11:03:47 +0000 (+0200) Subject: login-common: Fix accessing freed memory when handling delayed final SASL responses X-Git-Tag: 2.4.0~2459 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=74058bd864024938af08cb1d9d60c613cbd55e59;p=thirdparty%2Fdovecot%2Fcore.git login-common: Fix accessing freed memory when handling delayed final SASL responses auth_request is freed already after authenticate_callback() is called, but delayed response handler still attempted to use it. --- diff --git a/src/login-common/client-common.c b/src/login-common/client-common.c index 00904c1365..e863ccc038 100644 --- a/src/login-common/client-common.c +++ b/src/login-common/client-common.c @@ -450,6 +450,7 @@ void client_destroy(struct client *client, const char *reason) timeout_remove(&client->to_disconnect); timeout_remove(&client->to_auth_waiting); str_free(&client->auth_response); + i_free(client->auth_conn_cookie); if (client->proxy_password != NULL) { safe_memset(client->proxy_password, 0, diff --git a/src/login-common/client-common.h b/src/login-common/client-common.h index 017e06f495..6db4884a4c 100644 --- a/src/login-common/client-common.h +++ b/src/login-common/client-common.h @@ -211,6 +211,8 @@ struct client { struct anvil_query *anvil_query; struct anvil_request *anvil_request; + char *auth_conn_cookie; + unsigned int auth_server_pid; unsigned int master_auth_id; /* Tag that can be used with login_client_request_abort() to abort sending client fd to mail process. authenticating is always TRUE diff --git a/src/login-common/sasl-server.c b/src/login-common/sasl-server.c index 147474fc69..4655b34933 100644 --- a/src/login-common/sasl-server.c +++ b/src/login-common/sasl-server.c @@ -250,21 +250,19 @@ anvil_lookup_callback(const char *reply, struct anvil_request *req) } static void -anvil_check_too_many_connections(struct client *client, - struct auth_client_request *request) +anvil_check_too_many_connections(struct client *client) { struct anvil_request *req; - const char *query, *cookie; + const char *query; buffer_t buf; req = i_new(struct anvil_request, 1); req->client = client; - req->auth_pid = auth_client_request_get_server_pid(request); + req->auth_pid = client->auth_server_pid; buffer_create_from_data(&buf, req->cookie, sizeof(req->cookie)); - cookie = auth_client_request_get_cookie(request); - if (strlen(cookie) == LOGIN_REQUEST_COOKIE_SIZE*2) - (void)hex_to_binary(cookie, &buf); + if (strlen(client->auth_conn_cookie) == LOGIN_REQUEST_COOKIE_SIZE*2) + (void)hex_to_binary(client->auth_conn_cookie, &buf); if (client->virtual_user == NULL || client->set->mail_max_userip_connections == 0) { @@ -323,9 +321,6 @@ args_parse_user(struct client *client, const char *key, const char *value) static void sasl_server_auth_success_finish(struct client *client, const char *const *args) { - struct auth_client_request *request = client->auth_request; - - client->auth_request = NULL; if (client->auth_nologin) { client->authenticating = FALSE; call_client_callback(client, SASL_SERVER_REPLY_SUCCESS, @@ -333,7 +328,7 @@ sasl_server_auth_success_finish(struct client *client, const char *const *args) } else if (!sasl_server_check_login(client)) { i_assert(!client->authenticating); } else { - anvil_check_too_many_connections(client, request); + anvil_check_too_many_connections(client); } } @@ -361,7 +356,14 @@ authenticate_callback(struct auth_client_request *request, data_base64, NULL); break; case AUTH_REQUEST_STATUS_OK: + client->auth_request = NULL; client->master_auth_id = auth_client_request_get_id(request); + client->auth_server_pid = + auth_client_request_get_server_pid(request); + i_free(client->auth_conn_cookie); + client->auth_conn_cookie = + i_strdup(auth_client_request_get_cookie(request)); + client->auth_successes++; client->auth_passdb_args = p_strarray_dup(client->pool, args); client->postlogin_socket_path = NULL;