Browse code

Http-proxy: fix bug preventing proxy credentials caching

Caching proxy credentials was not working due to the
lack of handling already defined creds in get_user_pass(),
which prevented the caching from working properly.

Fix this issue by getting the value of c->first_time,
that indicates if we're at the first iteration
of the main loop and use it as second argument of the
get_user_pass_http(). Otherwise, on SIGUSR1 or SIGHUP
upon instance context restart credentials would be erased
every time.

The nocache member has been added to the struct
http_proxy_options and also a getter method to retrieve
that option from ssl has been added, by doing this
we're able to erase previous queried user credentials
to ensure correct operation.

Fixes: Trac #1187
Signed-off-by: Gianmarco De Gregori <gianmarco@mandelbit.com>
Acked-by: Gert Doering <gert@greenie.muc.de>
Change-Id: Ia3e06c0832c4ca0ab868c845279fb71c01a1a78a
Acked-by: Frank Lichtenheld <frank@lichtenheld.com>
Message-Id: <20240623200551.20092-1-gert@greenie.muc.de>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg28835.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
(cherry picked from commit 3cfd6f961d5c92bec283ac3616e1633b4e16760c)

Gianmarco De Gregori authored on 2024/06/24 05:05:51
Showing 7 changed files
... ...
@@ -19,9 +19,6 @@ which mode OpenVPN is configured as.
19 19
   When using ``--auth-nocache`` in combination with a user/password file
20 20
   and ``--chroot`` or ``--daemon``, make sure to use an absolute path.
21 21
 
22
-  This directive does not affect the ``--http-proxy`` username/password.
23
-  It is always cached.
24
-
25 22
 --cd dir
26 23
   Change directory to ``dir`` prior to reading any files such as
27 24
   configuration files, key files, scripts, etc. ``dir`` should be an
... ...
@@ -691,6 +691,8 @@ init_proxy_dowork(struct context *c)
691 691
 
692 692
     if (c->options.ce.http_proxy_options)
693 693
     {
694
+        c->options.ce.http_proxy_options->first_time = c->first_time;
695
+
694 696
         /* Possible HTTP proxy user/pass input */
695 697
         c->c1.http_proxy = http_proxy_new(c->options.ce.http_proxy_options);
696 698
         if (c->c1.http_proxy)
... ...
@@ -1653,6 +1653,7 @@ show_http_proxy_options(const struct http_proxy_options *o)
1653 1653
     SHOW_STR(auth_file);
1654 1654
     SHOW_STR(auth_file_up);
1655 1655
     SHOW_BOOL(inline_creds);
1656
+    SHOW_BOOL(nocache);
1656 1657
     SHOW_STR(http_version);
1657 1658
     SHOW_STR(user_agent);
1658 1659
     for  (i = 0; i < MAX_CUSTOM_HTTP_HEADER && o->custom_headers[i].name; i++)
... ...
@@ -3156,6 +3157,11 @@ options_postprocess_mutate_ce(struct options *o, struct connection_entry *ce)
3156 3156
         ce->flags |= CE_DISABLED;
3157 3157
     }
3158 3158
 
3159
+    if (ce->http_proxy_options)
3160
+    {
3161
+        ce->http_proxy_options->nocache = ssl_get_auth_nocache();
3162
+    }
3163
+
3159 3164
     /* our socks code is not fully IPv6 enabled yet (TCP works, UDP not)
3160 3165
      * so fall back to IPv4-only (trac #1221)
3161 3166
      */
... ...
@@ -276,7 +276,7 @@ get_user_pass_http(struct http_proxy_info *p, const bool force)
276 276
         {
277 277
             auth_file = p->options.auth_file_up;
278 278
         }
279
-        if (p->queried_creds)
279
+        if (p->queried_creds && !static_proxy_user_pass.nocache)
280 280
         {
281 281
             flags |= GET_USER_PASS_PREVIOUS_CREDS_FAILED;
282 282
         }
... ...
@@ -288,9 +288,14 @@ get_user_pass_http(struct http_proxy_info *p, const bool force)
288 288
                       auth_file,
289 289
                       UP_TYPE_PROXY,
290 290
                       flags);
291
-        p->queried_creds = true;
292
-        p->up = static_proxy_user_pass;
291
+        static_proxy_user_pass.nocache = p->options.nocache;
293 292
     }
293
+
294
+    /*
295
+     * Using cached credentials
296
+     */
297
+    p->queried_creds = true;
298
+    p->up = static_proxy_user_pass;
294 299
 }
295 300
 
296 301
 #if 0
... ...
@@ -541,7 +546,7 @@ http_proxy_new(const struct http_proxy_options *o)
541 541
     /* only basic and NTLM/NTLMv2 authentication supported so far */
542 542
     if (p->auth_method == HTTP_AUTH_BASIC || p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2)
543 543
     {
544
-        get_user_pass_http(p, true);
544
+        get_user_pass_http(p, p->options.first_time);
545 545
     }
546 546
 
547 547
 #if !NTLM
... ...
@@ -656,6 +661,11 @@ establish_http_proxy_passthru(struct http_proxy_info *p,
656 656
         || p->auth_method == HTTP_AUTH_NTLM)
657 657
     {
658 658
         get_user_pass_http(p, false);
659
+
660
+        if (p->up.nocache)
661
+        {
662
+            clear_user_pass_http();
663
+        }
659 664
     }
660 665
 
661 666
     /* are we being called again after getting the digest server nonce in the previous transaction? */
... ...
@@ -1031,13 +1041,6 @@ establish_http_proxy_passthru(struct http_proxy_info *p,
1031 1031
             }
1032 1032
             goto error;
1033 1033
         }
1034
-
1035
-        /* clear state */
1036
-        if (p->options.auth_retry)
1037
-        {
1038
-            clear_user_pass_http();
1039
-        }
1040
-        store_proxy_authenticate(p, NULL);
1041 1034
     }
1042 1035
 
1043 1036
     /* check return code, success = 200 */
... ...
@@ -57,6 +57,8 @@ struct http_proxy_options {
57 57
     const char *user_agent;
58 58
     struct http_custom_header custom_headers[MAX_CUSTOM_HTTP_HEADER];
59 59
     bool inline_creds; /* auth_file_up is inline credentials */
60
+    bool first_time; /* indicates if we need to wipe user creds at the first iteration of the main loop */
61
+    bool nocache;
60 62
 };
61 63
 
62 64
 struct http_proxy_options_simple {
... ...
@@ -499,6 +499,15 @@ ssl_set_auth_nocache(void)
499 499
 }
500 500
 
501 501
 /*
502
+ * Get the password caching
503
+ */
504
+bool
505
+ssl_get_auth_nocache(void)
506
+{
507
+    return passbuf.nocache;
508
+}
509
+
510
+/*
502 511
  * Set an authentication token
503 512
  */
504 513
 void
... ...
@@ -397,6 +397,11 @@ void auth_user_pass_setup(const char *auth_file, bool is_inline,
397 397
 void ssl_set_auth_nocache(void);
398 398
 
399 399
 /*
400
+ * Getter method for retrieving the auth-nocache option.
401
+ */
402
+bool ssl_get_auth_nocache(void);
403
+
404
+/*
400 405
  * Purge any stored authentication information, both for key files and tunnel
401 406
  * authentication. If PCKS #11 is enabled, purge authentication for that too.
402 407
  * Note that auth_token is not cleared.