From: Timo Sirainen Date: Wed, 15 Mar 2017 23:12:57 +0000 (+0200) Subject: lib-oauth2: Fix memory leak if HTTP URL parsing fails. X-Git-Tag: 2.3.0.rc1~1945 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=070caf28f190230fc211f22ba8fbd8e26aec06fd;p=thirdparty%2Fdovecot%2Fcore.git lib-oauth2: Fix memory leak if HTTP URL parsing fails. Also delay calling the callback. The callers don't necessarily expect an immediate callback (auth/db-oauth2.c doesn't). --- diff --git a/src/lib-oauth2/oauth2-introspect.c b/src/lib-oauth2/oauth2-introspect.c index e0da0f892e..a89f1e3901 100644 --- a/src/lib-oauth2/oauth2-introspect.c +++ b/src/lib-oauth2/oauth2-introspect.c @@ -55,6 +55,16 @@ oauth2_introspect_response(const struct http_response *response, } } +static void oauth2_introspection_delayed_error(struct oauth2_request *req) +{ + struct oauth2_introspection_result fail = { + .success = FALSE, + .error = req->delayed_error + }; + oauth2_introspection_callback(req, &fail); + oauth2_request_free_internal(req); +} + #undef oauth2_introspection_start struct oauth2_request* oauth2_introspection_start(const struct oauth2_settings *set, @@ -67,9 +77,6 @@ oauth2_introspection_start(const struct oauth2_settings *set, pool_t pool = pool_alloconly_create_clean("oauth2 introspection", 1024); struct oauth2_request *req = p_new(pool, struct oauth2_request, 1); - struct oauth2_introspection_result fail = { - .success = FALSE, - }; struct http_url *url; const char *error; @@ -87,9 +94,10 @@ oauth2_introspection_start(const struct oauth2_settings *set, if (http_url_parse(str_c(enc), NULL, HTTP_URL_ALLOW_USERINFO_PART, pool, &url, &error) < 0) { - fail.error = t_strdup_printf("http_url_parse(%s) failed: %s", - str_c(enc), error); - oauth2_introspection_callback(req, &fail); + req->delayed_error = p_strdup_printf(pool, + "http_url_parse(%s) failed: %s", str_c(enc), error); + req->to_delayed_error = timeout_add_short(0, + oauth2_introspection_delayed_error, req); return req; } diff --git a/src/lib-oauth2/oauth2-private.h b/src/lib-oauth2/oauth2-private.h index c5d89585b7..1a14fd57d8 100644 --- a/src/lib-oauth2/oauth2-private.h +++ b/src/lib-oauth2/oauth2-private.h @@ -11,6 +11,9 @@ struct oauth2_request { struct istream *is; struct io *io; + const char *delayed_error; + struct timeout *to_delayed_error; + const char *username; void (*json_parsed_cb)(struct oauth2_request*, bool success, diff --git a/src/lib-oauth2/oauth2-refresh.c b/src/lib-oauth2/oauth2-refresh.c index 77a3a84c02..4cfe16a68d 100644 --- a/src/lib-oauth2/oauth2-refresh.c +++ b/src/lib-oauth2/oauth2-refresh.c @@ -95,6 +95,16 @@ oauth2_refresh_response(const struct http_response *response, } } +static void oauth2_refresh_delayed_error(struct oauth2_request *req) +{ + struct oauth2_refresh_result fail = { + .success = FALSE, + .error = req->delayed_error + }; + oauth2_refresh_callback(req, &fail); + oauth2_request_free_internal(req); +} + #undef oauth2_refresh_start struct oauth2_request* oauth2_refresh_start(const struct oauth2_settings *set, @@ -109,9 +119,6 @@ oauth2_refresh_start(const struct oauth2_settings *set, p_new(pool, struct oauth2_request, 1); struct http_url *url; const char *error; - struct oauth2_refresh_result fail = { - .success = FALSE - }; req->pool = pool; req->set = set; @@ -121,9 +128,11 @@ oauth2_refresh_start(const struct oauth2_settings *set, if (http_url_parse(req->set->refresh_url, NULL, HTTP_URL_ALLOW_USERINFO_PART, pool, &url, &error) < 0) { - fail.error = t_strdup_printf("http_url_parse(%s) failed: %s", - req->set->refresh_url, error); - oauth2_refresh_callback(req, &fail); + req->delayed_error = p_strdup_printf(pool, + "http_url_parse(%s) failed: %s", + req->set->refresh_url, error); + req->to_delayed_error = timeout_add_short(0, + oauth2_refresh_delayed_error, req); return req; } diff --git a/src/lib-oauth2/oauth2-token-validate.c b/src/lib-oauth2/oauth2-token-validate.c index 958d7461b2..955cdace47 100644 --- a/src/lib-oauth2/oauth2-token-validate.c +++ b/src/lib-oauth2/oauth2-token-validate.c @@ -83,6 +83,16 @@ oauth2_token_validate_response(const struct http_response *response, } } +static void oauth2_token_validation_delayed_error(struct oauth2_request *req) +{ + struct oauth2_token_validation_result fail = { + .success = FALSE, + .error = req->delayed_error + }; + oauth2_token_validation_callback(req, &fail); + oauth2_request_free_internal(req); +} + #undef oauth2_token_validation_start struct oauth2_request* oauth2_token_validation_start(const struct oauth2_settings *set, @@ -94,9 +104,6 @@ oauth2_token_validation_start(const struct oauth2_settings *set, struct http_url *url; const char *error; - struct oauth2_token_validation_result fail = { - .success = FALSE - }; pool_t pool = pool_alloconly_create_clean("oauth2 token_validation", 1024); struct oauth2_request *req = @@ -113,9 +120,10 @@ oauth2_token_validation_start(const struct oauth2_settings *set, if (http_url_parse(str_c(enc), NULL, HTTP_URL_ALLOW_USERINFO_PART, pool, &url, &error) < 0) { - fail.error = t_strdup_printf("http_url_parse(%s) failed: %s", - str_c(enc), error); - oauth2_token_validation_callback(req, &fail); + req->delayed_error = p_strdup_printf(pool, + "http_url_parse(%s) failed: %s", str_c(enc), error); + req->to_delayed_error = timeout_add_short(0, + oauth2_token_validation_delayed_error, req); return req; } diff --git a/src/lib-oauth2/oauth2.c b/src/lib-oauth2/oauth2.c index 9cd54caa9f..83545b8e0d 100644 --- a/src/lib-oauth2/oauth2.c +++ b/src/lib-oauth2/oauth2.c @@ -73,6 +73,8 @@ oauth2_request_abort(struct oauth2_request **_req) void oauth2_request_free_internal(struct oauth2_request *req) { + if (req->to_delayed_error != NULL) + timeout_remove(&req->to_delayed_error); pool_unref(&req->pool); }