]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-oauth2: Fix memory leak if HTTP URL parsing fails.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 15 Mar 2017 23:12:57 +0000 (01:12 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 15 Mar 2017 23:38:24 +0000 (01:38 +0200)
Also delay calling the callback. The callers don't necessarily expect an
immediate callback (auth/db-oauth2.c doesn't).

src/lib-oauth2/oauth2-introspect.c
src/lib-oauth2/oauth2-private.h
src/lib-oauth2/oauth2-refresh.c
src/lib-oauth2/oauth2-token-validate.c
src/lib-oauth2/oauth2.c

index e0da0f892eb04339afb89b96e03d10166c8b4fca..a89f1e3901c578bd93cf8f6c0cedbf8931a04b3f 100644 (file)
@@ -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;
        }
 
index c5d89585b73da7d137e7847b0b5b610c1aafc925..1a14fd57d8c829160e0ef9ef9f3453e3048603ca 100644 (file)
@@ -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,
index 77a3a84c02bd6dc63fead68bd4ffbebcd58a63db..4cfe16a68ddb4d05dd59073bd734c8fb761bc125 100644 (file)
@@ -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;
        }
 
index 958d7461b2d846bcb4e5023b6fd1fd0bbd840204..955cdace475122169ba69af11130d0dc6c7c5285 100644 (file)
@@ -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;
        }
 
index 9cd54caa9f01d0472164caf9c98ce54bf19aa8db..83545b8e0d161fb4edff6fb5c6cd6b91f73575c0 100644 (file)
@@ -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);
 }