]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Ensure that argument to parse_line has always space for final sentinel
authorArne Schwabe <arne@rfc2549.org>
Thu, 15 Dec 2022 19:01:38 +0000 (20:01 +0100)
committerGert Doering <gert@greenie.muc.de>
Fri, 16 Dec 2022 08:53:09 +0000 (09:53 +0100)
This fixes two places were we do not have enough space in the array
of parameters given to parse_line for the final NULL parameter that
signal the end of the parsed argument errors.

Both these cases can lead to a buffer overflow. But both of these
cases require root/admin access to OpenVPN:

- parse_argv, only able to trigger if starting openvpn from the command
  line, at this point you cannot  gain more privileges than you already
  have.

  Way to reproduce, compile with ASAN and run:

       openvpn --tls-verify a a a a a a a a a a a a a a a

- remove_iroutes_from_push_route_list

This operates on the list of pushed entries that is generated
by the server itself. So trigger this, you need to have control
over config, management interface, a plugin or cdd files.

The parse_argv problem was found by Trial of Bits. I found the
remove_iroutes_from_push_route_list problem by looking for similar
problems.

Reported-By: Trial of Bits (TOB-OVPN-4)
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20221215190143.2107896-4-arne@rfc2549.org>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg25734.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
(cherry picked from commit 749beb6d0cb9f8628997bb656ba2f64e31cac377)

src/openvpn/options.c
src/openvpn/push.c

index 192c672570f1388d833eea7100d96ee6d8fac75f..b0f8bed0fbc302ec148c3a256e2160c0d8363ef7 100644 (file)
@@ -4657,8 +4657,6 @@ parse_argv(struct options *options,
            unsigned int *option_types_found,
            struct env_set *es)
 {
-    int i, j;
-
     /* usage message */
     if (argc <= 1)
     {
@@ -4668,7 +4666,7 @@ parse_argv(struct options *options,
     /* config filename specified only? */
     if (argc == 2 && strncmp(argv[1], "--", 2))
     {
-        char *p[MAX_PARMS];
+        char *p[MAX_PARMS+1];
         CLEAR(p);
         p[0] = "config";
         p[1] = argv[1];
@@ -4677,9 +4675,9 @@ parse_argv(struct options *options,
     else
     {
         /* parse command line */
-        for (i = 1; i < argc; ++i)
+        for (int i = 1; i < argc; ++i)
         {
-            char *p[MAX_PARMS];
+            char *p[MAX_PARMS+1];
             CLEAR(p);
             p[0] = argv[i];
             if (strncmp(p[0], "--", 2))
@@ -4691,6 +4689,7 @@ parse_argv(struct options *options,
                 p[0] += 2;
             }
 
+            int j;
             for (j = 1; j < MAX_PARMS; ++j)
             {
                 if (i + j < argc)
index 52c6e8200dcb9c4d78aedd10c72dfc0035d2fa5c..e65852d507c6f8c99ef70e973c4196746f04eca9 100644 (file)
@@ -808,13 +808,13 @@ remove_iroutes_from_push_route_list(struct options *o)
         /* cycle through the push list */
         while (e)
         {
-            char *p[MAX_PARMS];
+            char *p[MAX_PARMS+1];
             bool enable = true;
 
             /* parse the push item */
             CLEAR(p);
             if (e->enable
-                && parse_line(e->option, p, SIZE(p), "[PUSH_ROUTE_REMOVE]", 1, D_ROUTE_DEBUG, &gc))
+                && parse_line(e->option, p, SIZE(p)-1, "[PUSH_ROUTE_REMOVE]", 1, D_ROUTE_DEBUG, &gc))
             {
                 /* is the push item a route directive? */
                 if (p[0] && !strcmp(p[0], "route") && !p[3])