-
Notifications
You must be signed in to change notification settings - Fork 7.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Memory leak in HTTP Digest Authentication (IDFGH-14071) #14885
Comments
Could it be fixed in the next stable release? |
The code does this: #ifdef CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH
} else if (client->connection_info.auth_type == HTTP_AUTH_TYPE_DIGEST && client->auth_data) {
client->auth_data->uri = NULL;
http_utils_assign_string(&client->auth_data->uri,client->connection_info.path,-1);
if (client->connection_info.query){
http_utils_append_string(&client->auth_data->uri,"?",-1);
http_utils_append_string(&client->auth_data->uri,client->connection_info.query,-1);
}
client->auth_data->cnonce = ((uint64_t)esp_random() << 32) + esp_random();
auth_response = http_auth_digest(client->connection_info.username, client->connection_info.password, client->auth_data);
#endif If you look at the allocation of Yet, the Thus the order of operations is:
In you example code, you're not calling the However, you're right that there's a potential leak path in that case, since the server will likely answer with an "401 Unauthorized" answer, leading to this line so that the perform will prepare again here and in turn this will call prepare again, leading to leaking the URI buffer. So, there are 2 possible fix up for this leak, either replace line 641 to read: free(client->auth_data->uri);
client->auth_data->uri = NULL; since it's ok to call free on a NULL pointer. or, better (to avoid fragmenting the heap), check if it's required to update the URI if one exists and reallocate only if required. This can be done easily like this: if (client->auth_data->uri
&& strlen(client->auth_data->uri) > (strlen(client->connection_info.path) + client->connection_info.query? strlen(client->connection_info.query) + 1 : 0)) {
free(client->auth_data->uri);
client->auth_data->uri = NULL;
} So meanwhile, you can simply call |
Thank you for your response. It seems that From my understanding of HTTP Digest Authentication, the process requires sending an initial request to the server to receive certain parameters (like the nonce). These parameters are then used to compute a proper response, which is included in a second request to authenticate successfully. Could you clarify where the preparation step for this process would typically occur in the code? |
You're right, I didn't check visibility of the method. In Digest authorization, either the client or the server can generate the nonce, so you don't need 2 actual requests per query. Once you know the realm (this requires an initial request), you can skip querying the nonce for later request. Digest authorization is being shifted out toward basic authentication over HTTPS which is, paradoxically, more secure than using MD5 for hashing/protecting the password. Anyway, this means that the only official way to create the right header is to go by redirections (401) like you did and then pay the price of an header memory leak as you've spotted. So use either fix I've listed to plug this leak. |
esp-idf/components/esp_http_client/esp_http_client.c
Line 641 in 7a305c0
I believe the URI should be freed before being set to null. When I try to dump it in previous line, it still contains the URI value.
Try this simple example that sends a GET request 100 times in a loop.
Since the URI consists of the path and query, longer values could exacerbate the leak.
Here's a simple Python server that listens on port 8000 and responds with "Hello" to all incoming requests:
The text was updated successfully, but these errors were encountered: