Browse code

put argv_* functions into own file, add unit tests

misc.c is too crowded with different things to perform any
sane unit testing due to its dependencies. So, in order to re-write
the #ifdef'ed tests for the argv_* family of functions into unit
tests I moved them into a dedicated file.

Signed-off-by: Heiko Hund <heiko.hund@sophos.com>
Acked-by: David Sommerseth <davids@redhat.com>
Message-Id: <1477672963-5724-2-git-send-email-heiko.hund@sophos.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg12811.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>

Heiko Hund authored on 2016/10/29 01:42:37
Showing 9 changed files
... ...
@@ -1301,6 +1301,7 @@ AC_CONFIG_FILES([
1301 1301
         tests/unit_tests/plugins/Makefile
1302 1302
         tests/unit_tests/plugins/auth-pam/Makefile
1303 1303
         tests/unit_tests/example_test/Makefile
1304
+        tests/unit_tests/openvpn/Makefile
1304 1305
         vendor/Makefile
1305 1306
 	sample/Makefile
1306 1307
 	doc/Makefile
... ...
@@ -36,6 +36,7 @@ endif
36 36
 sbin_PROGRAMS = openvpn
37 37
 
38 38
 openvpn_SOURCES = \
39
+	argv.c argv.h \
39 40
 	base64.c base64.h \
40 41
 	basic.h \
41 42
 	buffer.c buffer.h \
42 43
new file mode 100644
... ...
@@ -0,0 +1,411 @@
0
+/*
1
+ *  OpenVPN -- An application to securely tunnel IP networks
2
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
3
+ *             session authentication and key exchange,
4
+ *             packet encryption, packet authentication, and
5
+ *             packet compression.
6
+ *
7
+ *  Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
8
+ *
9
+ *  This program is free software; you can redistribute it and/or modify
10
+ *  it under the terms of the GNU General Public License version 2
11
+ *  as published by the Free Software Foundation.
12
+ *
13
+ *  This program is distributed in the hope that it will be useful,
14
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ *  GNU General Public License for more details.
17
+ *
18
+ *  You should have received a copy of the GNU General Public License
19
+ *  along with this program (see the file COPYING included with this
20
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
21
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+ *
23
+ *
24
+ *  A printf-like function (that only recognizes a subset of standard printf
25
+ *  format operators) that prints arguments to an argv list instead
26
+ *  of a standard string.  This is used to build up argv arrays for passing
27
+ *  to execve.
28
+ */
29
+
30
+#ifdef HAVE_CONFIG_H
31
+#include "config.h"
32
+#elif defined(_MSC_VER)
33
+#include "config-msvc.h"
34
+#endif
35
+
36
+#include "syshead.h"
37
+
38
+#include "argv.h"
39
+#include "options.h"
40
+
41
+void
42
+argv_init (struct argv *a)
43
+{
44
+  a->capacity = 0;
45
+  a->argc = 0;
46
+  a->argv = NULL;
47
+  a->system_str = NULL;
48
+}
49
+
50
+struct argv
51
+argv_new (void)
52
+{
53
+  struct argv ret;
54
+  argv_init (&ret);
55
+  return ret;
56
+}
57
+
58
+void
59
+argv_reset (struct argv *a)
60
+{
61
+  size_t i;
62
+  for (i = 0; i < a->argc; ++i)
63
+    free (a->argv[i]);
64
+  free (a->argv);
65
+  free (a->system_str);
66
+  argv_init (a);
67
+}
68
+
69
+static void
70
+argv_extend (struct argv *a, const size_t newcap)
71
+{
72
+  if (newcap > a->capacity)
73
+    {
74
+      char **newargv;
75
+      size_t i;
76
+      ALLOC_ARRAY_CLEAR (newargv, char *, newcap);
77
+      for (i = 0; i < a->argc; ++i)
78
+        newargv[i] = a->argv[i];
79
+      free (a->argv);
80
+      a->argv = newargv;
81
+      a->capacity = newcap;
82
+    }
83
+}
84
+
85
+static void
86
+argv_grow (struct argv *a, const size_t add)
87
+{
88
+  const size_t newargc = a->argc + add + 1;
89
+  ASSERT (newargc > a->argc);
90
+  argv_extend (a, adjust_power_of_2 (newargc));
91
+}
92
+
93
+static void
94
+argv_append (struct argv *a, char *str) /* str must have been malloced or be NULL */
95
+{
96
+  argv_grow (a, 1);
97
+  a->argv[a->argc++] = str;
98
+}
99
+
100
+static void
101
+argv_system_str_append (struct argv *a, const char *str, const bool enquote)
102
+{
103
+  if (str)
104
+    {
105
+      char *newstr;
106
+
107
+      /* compute length of new system_str */
108
+      size_t l = strlen (str) + 1; /* space for new string plus trailing '\0' */
109
+      if (a->system_str)
110
+        l += strlen (a->system_str) + 1; /* space for existing string + space (" ") separator */
111
+      if (enquote)
112
+        l += 2; /* space for two quotes */
113
+
114
+      /* build new system_str */
115
+      newstr = (char *) malloc (l);
116
+      newstr[0] = '\0';
117
+      check_malloc_return (newstr);
118
+      if (a->system_str)
119
+        {
120
+          strcpy (newstr, a->system_str);
121
+          strcat (newstr, " ");
122
+        }
123
+      if (enquote)
124
+        strcat (newstr, "\"");
125
+      strcat (newstr, str);
126
+      if (enquote)
127
+        strcat (newstr, "\"");
128
+      free (a->system_str);
129
+      a->system_str = newstr;
130
+    }
131
+}
132
+
133
+static char *
134
+argv_extract_cmd_name (const char *path)
135
+{
136
+  char *ret = NULL;
137
+  if (path)
138
+    {
139
+      char *path_cp = string_alloc(path, NULL); /* POSIX basename() implementaions may modify its arguments */
140
+      const char *bn = basename (path_cp);
141
+      if (bn)
142
+        {
143
+          char *dot = NULL;
144
+          ret = string_alloc (bn, NULL);
145
+          dot = strrchr (ret, '.');
146
+          if (dot)
147
+            *dot = '\0';
148
+          free(path_cp);
149
+          if (ret[0] == '\0')
150
+            {
151
+              free(ret);
152
+              ret = NULL;
153
+            }
154
+        }
155
+    }
156
+  return ret;
157
+}
158
+
159
+const char *
160
+argv_system_str (const struct argv *a)
161
+{
162
+  return a->system_str;
163
+}
164
+
165
+static struct argv
166
+argv_clone (const struct argv *a, const size_t headroom)
167
+{
168
+  struct argv r;
169
+  size_t i;
170
+
171
+  argv_init (&r);
172
+  for (i = 0; i < headroom; ++i)
173
+    argv_append (&r, NULL);
174
+  if (a)
175
+    {
176
+      for (i = 0; i < a->argc; ++i)
177
+        argv_append (&r, string_alloc (a->argv[i], NULL));
178
+      r.system_str = string_alloc (a->system_str, NULL);
179
+    }
180
+  return r;
181
+}
182
+
183
+struct argv
184
+argv_insert_head (const struct argv *a, const char *head)
185
+{
186
+  struct argv r;
187
+  char *s;
188
+
189
+  r = argv_clone (a, 1);
190
+  r.argv[0] = string_alloc (head, NULL);
191
+  s = r.system_str;
192
+  r.system_str = string_alloc (head, NULL);
193
+  if (s)
194
+    {
195
+      argv_system_str_append (&r, s, false);
196
+      free (s);
197
+    }
198
+  return r;
199
+}
200
+
201
+char *
202
+argv_term (const char **f)
203
+{
204
+  const char *p = *f;
205
+  const char *term = NULL;
206
+  size_t termlen = 0;
207
+
208
+  if (*p == '\0')
209
+    return NULL;
210
+
211
+  while (true)
212
+    {
213
+      const int c = *p;
214
+      if (c == '\0')
215
+        break;
216
+      if (term)
217
+        {
218
+          if (!isspace (c))
219
+            ++termlen;
220
+          else
221
+            break;
222
+        }
223
+      else
224
+        {
225
+          if (!isspace (c))
226
+            {
227
+              term = p;
228
+              termlen = 1;
229
+            }
230
+        }
231
+      ++p;
232
+    }
233
+  *f = p;
234
+
235
+  if (term)
236
+    {
237
+      char *ret;
238
+      ASSERT (termlen > 0);
239
+      ret = malloc (termlen + 1);
240
+      check_malloc_return (ret);
241
+      memcpy (ret, term, termlen);
242
+      ret[termlen] = '\0';
243
+      return ret;
244
+    }
245
+  else
246
+    return NULL;
247
+}
248
+
249
+const char *
250
+argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags)
251
+{
252
+  if (a->argv)
253
+    return print_argv ((const char **)a->argv, gc, flags);
254
+  else
255
+    return "";
256
+}
257
+
258
+void
259
+argv_msg (const int msglev, const struct argv *a)
260
+{
261
+  struct gc_arena gc = gc_new ();
262
+  msg (msglev, "%s", argv_str (a, &gc, 0));
263
+  gc_free (&gc);
264
+}
265
+
266
+void
267
+argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix)
268
+{
269
+  struct gc_arena gc = gc_new ();
270
+  msg (msglev, "%s: %s", prefix, argv_str (a, &gc, 0));
271
+  gc_free (&gc);
272
+}
273
+
274
+void
275
+argv_printf (struct argv *a, const char *format, ...)
276
+{
277
+  va_list arglist;
278
+  va_start (arglist, format);
279
+  argv_printf_arglist (a, format, 0, arglist);
280
+  va_end (arglist);
281
+ }
282
+
283
+void
284
+argv_printf_cat (struct argv *a, const char *format, ...)
285
+{
286
+  va_list arglist;
287
+  va_start (arglist, format);
288
+  argv_printf_arglist (a, format, APA_CAT, arglist);
289
+  va_end (arglist);
290
+}
291
+
292
+void
293
+argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist)
294
+{
295
+  struct gc_arena gc = gc_new ();
296
+  char *term;
297
+  const char *f = format;
298
+
299
+  if (!(flags & APA_CAT))
300
+    argv_reset (a);
301
+  argv_extend (a, 1); /* ensure trailing NULL */
302
+
303
+  while ((term = argv_term (&f)) != NULL)
304
+    {
305
+      if (term[0] == '%')
306
+        {
307
+          if (!strcmp (term, "%s"))
308
+            {
309
+              char *s = va_arg (arglist, char *);
310
+              if (!s)
311
+                s = "";
312
+              argv_append (a, string_alloc (s, NULL));
313
+              argv_system_str_append (a, s, true);
314
+            }
315
+          else if (!strcmp (term, "%sc"))
316
+            {
317
+              char *s = va_arg (arglist, char *);
318
+              if (s)
319
+                {
320
+                  int nparms;
321
+                  char *parms[MAX_PARMS+1];
322
+                  int i;
323
+
324
+                  nparms = parse_line (s, parms, MAX_PARMS, "SCRIPT-ARGV", 0, D_ARGV_PARSE_CMD, &gc);
325
+                  if (nparms)
326
+                    {
327
+                      for (i = 0; i < nparms; ++i)
328
+                        argv_append (a, string_alloc (parms[i], NULL));
329
+                    }
330
+                  else
331
+                    argv_append (a, string_alloc (s, NULL));
332
+
333
+                  argv_system_str_append (a, s, false);
334
+                }
335
+              else
336
+                {
337
+                  argv_append (a, string_alloc ("", NULL));
338
+                  argv_system_str_append (a, "echo", false);
339
+                }
340
+            }
341
+          else if (!strcmp (term, "%d"))
342
+            {
343
+              char numstr[64];
344
+              openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
345
+              argv_append (a, string_alloc (numstr, NULL));
346
+              argv_system_str_append (a, numstr, false);
347
+            }
348
+          else if (!strcmp (term, "%u"))
349
+            {
350
+              char numstr[64];
351
+              openvpn_snprintf (numstr, sizeof (numstr), "%u", va_arg (arglist, unsigned int));
352
+              argv_append (a, string_alloc (numstr, NULL));
353
+              argv_system_str_append (a, numstr, false);
354
+            }
355
+          else if (!strcmp (term, "%s/%d"))
356
+            {
357
+              char numstr[64];
358
+              char *s = va_arg (arglist, char *);
359
+
360
+              if (!s)
361
+                s = "";
362
+
363
+              openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
364
+
365
+              {
366
+                const size_t len = strlen(s) + strlen(numstr) + 2;
367
+                char *combined = (char *) malloc (len);
368
+                check_malloc_return (combined);
369
+
370
+                strcpy (combined, s);
371
+                strcat (combined, "/");
372
+                strcat (combined, numstr);
373
+                argv_append (a, combined);
374
+                argv_system_str_append (a, combined, false);
375
+              }
376
+            }
377
+          else if (!strcmp (term, "%s%sc"))
378
+            {
379
+              char *s1 = va_arg (arglist, char *);
380
+              char *s2 = va_arg (arglist, char *);
381
+              char *combined;
382
+              char *cmd_name;
383
+
384
+              if (!s1) s1 = "";
385
+              if (!s2) s2 = "";
386
+              combined = (char *) malloc (strlen(s1) + strlen(s2) + 1);
387
+              check_malloc_return (combined);
388
+              strcpy (combined, s1);
389
+              strcat (combined, s2);
390
+              argv_append (a, combined);
391
+
392
+              cmd_name = argv_extract_cmd_name (combined);
393
+              if (cmd_name)
394
+                {
395
+                  argv_system_str_append (a, cmd_name, false);
396
+                  free (cmd_name);
397
+                }
398
+            }
399
+          else
400
+            ASSERT (0);
401
+          free (term);
402
+        }
403
+      else
404
+        {
405
+          argv_append (a, term);
406
+          argv_system_str_append (a, term, false);
407
+        }
408
+    }
409
+  gc_free (&gc);
410
+}
0 411
new file mode 100644
... ...
@@ -0,0 +1,76 @@
0
+/*
1
+ *  OpenVPN -- An application to securely tunnel IP networks
2
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
3
+ *             session authentication and key exchange,
4
+ *             packet encryption, packet authentication, and
5
+ *             packet compression.
6
+ *
7
+ *  Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
8
+ *
9
+ *  This program is free software; you can redistribute it and/or modify
10
+ *  it under the terms of the GNU General Public License version 2
11
+ *  as published by the Free Software Foundation.
12
+ *
13
+ *  This program is distributed in the hope that it will be useful,
14
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ *  GNU General Public License for more details.
17
+ *
18
+ *  You should have received a copy of the GNU General Public License
19
+ *  along with this program (see the file COPYING included with this
20
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
21
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+ *
23
+ *
24
+ *  A printf-like function (that only recognizes a subset of standard printf
25
+ *  format operators) that prints arguments to an argv list instead
26
+ *  of a standard string.  This is used to build up argv arrays for passing
27
+ *  to execve.
28
+ */
29
+
30
+#ifndef ARGV_H
31
+#define ARGV_H
32
+
33
+#include "buffer.h"
34
+
35
+struct argv {
36
+  size_t capacity;
37
+  size_t argc;
38
+  char **argv;
39
+  char *system_str;
40
+};
41
+
42
+void argv_init (struct argv *a);
43
+struct argv argv_new (void);
44
+void argv_reset (struct argv *a);
45
+char *argv_term (const char **f);
46
+const char *argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags);
47
+struct argv argv_insert_head (const struct argv *a, const char *head);
48
+void argv_msg (const int msglev, const struct argv *a);
49
+void argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix);
50
+const char *argv_system_str (const struct argv *a);
51
+
52
+#define APA_CAT (1<<0) /* concatentate onto existing struct argv list */
53
+void argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist);
54
+
55
+void argv_printf (struct argv *a, const char *format, ...)
56
+#ifdef __GNUC__
57
+#if __USE_MINGW_ANSI_STDIO
58
+        __attribute__ ((format (gnu_printf, 2, 3)))
59
+#else
60
+        __attribute__ ((format (__printf__, 2, 3)))
61
+#endif
62
+#endif
63
+  ;
64
+
65
+void argv_printf_cat (struct argv *a, const char *format, ...)
66
+#ifdef __GNUC__
67
+#if __USE_MINGW_ANSI_STDIO
68
+        __attribute__ ((format (gnu_printf, 2, 3)))
69
+#else
70
+        __attribute__ ((format (__printf__, 2, 3)))
71
+#endif
72
+#endif
73
+  ;
74
+
75
+#endif
... ...
@@ -1588,465 +1588,6 @@ adjust_power_of_2 (size_t u)
1588 1588
 }
1589 1589
 
1590 1590
 /*
1591
- * A printf-like function (that only recognizes a subset of standard printf
1592
- * format operators) that prints arguments to an argv list instead
1593
- * of a standard string.  This is used to build up argv arrays for passing
1594
- * to execve.
1595
- */
1596
-
1597
-void
1598
-argv_init (struct argv *a)
1599
-{
1600
-  a->capacity = 0;
1601
-  a->argc = 0;
1602
-  a->argv = NULL;
1603
-  a->system_str = NULL;
1604
-}
1605
-
1606
-struct argv
1607
-argv_new (void)
1608
-{
1609
-  struct argv ret;
1610
-  argv_init (&ret);
1611
-  return ret;
1612
-}
1613
-
1614
-void
1615
-argv_reset (struct argv *a)
1616
-{
1617
-  size_t i;
1618
-  for (i = 0; i < a->argc; ++i)
1619
-    free (a->argv[i]);
1620
-  free (a->argv);
1621
-  free (a->system_str);
1622
-  argv_init (a);
1623
-}
1624
-
1625
-static void
1626
-argv_extend (struct argv *a, const size_t newcap)
1627
-{
1628
-  if (newcap > a->capacity)
1629
-    {
1630
-      char **newargv;
1631
-      size_t i;
1632
-      ALLOC_ARRAY_CLEAR (newargv, char *, newcap);
1633
-      for (i = 0; i < a->argc; ++i)
1634
-	newargv[i] = a->argv[i];
1635
-      free (a->argv);
1636
-      a->argv = newargv;
1637
-      a->capacity = newcap;
1638
-    }
1639
-}
1640
-
1641
-static void
1642
-argv_grow (struct argv *a, const size_t add)
1643
-{
1644
-  const size_t newargc = a->argc + add + 1;
1645
-  ASSERT (newargc > a->argc);
1646
-  argv_extend (a, adjust_power_of_2 (newargc));
1647
-}
1648
-
1649
-static void
1650
-argv_append (struct argv *a, char *str) /* str must have been malloced or be NULL */
1651
-{
1652
-  argv_grow (a, 1);
1653
-  a->argv[a->argc++] = str;
1654
-}
1655
-
1656
-static void
1657
-argv_system_str_append (struct argv *a, const char *str, const bool enquote)
1658
-{
1659
-  if (str)
1660
-    {
1661
-      char *newstr;
1662
-
1663
-      /* compute length of new system_str */
1664
-      size_t l = strlen (str) + 1; /* space for new string plus trailing '\0' */
1665
-      if (a->system_str)
1666
-	l += strlen (a->system_str) + 1; /* space for existing string + space (" ") separator */
1667
-      if (enquote)
1668
-	l += 2; /* space for two quotes */
1669
-
1670
-      /* build new system_str */
1671
-      newstr = (char *) malloc (l);
1672
-      newstr[0] = '\0';
1673
-      check_malloc_return (newstr);
1674
-      if (a->system_str)
1675
-	{
1676
-	  strcpy (newstr, a->system_str);
1677
-	  strcat (newstr, " ");
1678
-	}
1679
-      if (enquote)
1680
-	strcat (newstr, "\"");
1681
-      strcat (newstr, str);
1682
-      if (enquote)
1683
-	strcat (newstr, "\"");
1684
-      free (a->system_str);
1685
-      a->system_str = newstr;
1686
-    }
1687
-}
1688
-
1689
-static char *
1690
-argv_extract_cmd_name (const char *path)
1691
-{
1692
-  char *ret = NULL;
1693
-  if (path)
1694
-    {
1695
-      char *path_cp = string_alloc(path, NULL); /* POSIX basename() implementaions may modify its arguments */
1696
-      const char *bn = basename (path_cp);
1697
-      if (bn)
1698
-	{
1699
-	  char *dot = NULL;
1700
-	  ret = string_alloc (bn, NULL);
1701
-	  dot = strrchr (ret, '.');
1702
-	  if (dot)
1703
-	    *dot = '\0';
1704
-	  free(path_cp);
1705
-	  if (ret[0] == '\0')
1706
-	    {
1707
-	      free(ret);
1708
-	      ret = NULL;
1709
-	    }
1710
-	}
1711
-    }
1712
-  return ret;
1713
-}
1714
-
1715
-const char *
1716
-argv_system_str (const struct argv *a)
1717
-{
1718
-  return a->system_str;
1719
-}
1720
-
1721
-struct argv
1722
-argv_clone (const struct argv *a, const size_t headroom)
1723
-{
1724
-  struct argv r;
1725
-  size_t i;
1726
-
1727
-  argv_init (&r);
1728
-  for (i = 0; i < headroom; ++i)
1729
-    argv_append (&r, NULL);
1730
-  if (a)
1731
-    {
1732
-      for (i = 0; i < a->argc; ++i)
1733
-	argv_append (&r, string_alloc (a->argv[i], NULL));
1734
-      r.system_str = string_alloc (a->system_str, NULL);
1735
-    }
1736
-  return r;
1737
-}
1738
-
1739
-struct argv
1740
-argv_insert_head (const struct argv *a, const char *head)
1741
-{
1742
-  struct argv r;
1743
-  char *s;
1744
-
1745
-  r = argv_clone (a, 1);
1746
-  r.argv[0] = string_alloc (head, NULL);
1747
-  s = r.system_str;
1748
-  r.system_str = string_alloc (head, NULL);
1749
-  if (s)
1750
-    {
1751
-      argv_system_str_append (&r, s, false);
1752
-      free (s);
1753
-    }
1754
-  return r;
1755
-}
1756
-
1757
-char *
1758
-argv_term (const char **f)
1759
-{
1760
-  const char *p = *f;
1761
-  const char *term = NULL;
1762
-  size_t termlen = 0;
1763
-
1764
-  if (*p == '\0')
1765
-    return NULL;
1766
-
1767
-  while (true)
1768
-    {
1769
-      const int c = *p;
1770
-      if (c == '\0')
1771
-	break;
1772
-      if (term)
1773
-	{
1774
-	  if (!isspace (c))
1775
-	    ++termlen;
1776
-	  else
1777
-	    break;
1778
-	}
1779
-      else
1780
-	{
1781
-	  if (!isspace (c))
1782
-	    {
1783
-	      term = p;
1784
-	      termlen = 1;
1785
-	    }
1786
-	}
1787
-      ++p;
1788
-    }
1789
-  *f = p;
1790
-
1791
-  if (term)
1792
-    {
1793
-      char *ret;
1794
-      ASSERT (termlen > 0);
1795
-      ret = malloc (termlen + 1);
1796
-      check_malloc_return (ret);
1797
-      memcpy (ret, term, termlen);
1798
-      ret[termlen] = '\0';
1799
-      return ret;
1800
-    }
1801
-  else
1802
-    return NULL;
1803
-}
1804
-
1805
-const char *
1806
-argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags)
1807
-{
1808
-  if (a->argv)
1809
-    return print_argv ((const char **)a->argv, gc, flags);
1810
-  else
1811
-    return "";
1812
-}
1813
-
1814
-void
1815
-argv_msg (const int msglev, const struct argv *a)
1816
-{
1817
-  struct gc_arena gc = gc_new ();
1818
-  msg (msglev, "%s", argv_str (a, &gc, 0));
1819
-  gc_free (&gc);
1820
-}
1821
-
1822
-void
1823
-argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix)
1824
-{
1825
-  struct gc_arena gc = gc_new ();
1826
-  msg (msglev, "%s: %s", prefix, argv_str (a, &gc, 0));
1827
-  gc_free (&gc);
1828
-}
1829
-
1830
-void
1831
-argv_printf (struct argv *a, const char *format, ...)
1832
-{
1833
-  va_list arglist;
1834
-  va_start (arglist, format);
1835
-  argv_printf_arglist (a, format, 0, arglist);
1836
-  va_end (arglist);
1837
- }
1838
-
1839
-void
1840
-argv_printf_cat (struct argv *a, const char *format, ...)
1841
-{
1842
-  va_list arglist;
1843
-  va_start (arglist, format);
1844
-  argv_printf_arglist (a, format, APA_CAT, arglist);
1845
-  va_end (arglist);
1846
-}
1847
-
1848
-void
1849
-argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist)
1850
-{
1851
-  struct gc_arena gc = gc_new ();
1852
-  char *term;
1853
-  const char *f = format;
1854
-
1855
-  if (!(flags & APA_CAT))
1856
-    argv_reset (a);
1857
-  argv_extend (a, 1); /* ensure trailing NULL */
1858
-
1859
-  while ((term = argv_term (&f)) != NULL) 
1860
-    {
1861
-      if (term[0] == '%')
1862
-	{
1863
-	  if (!strcmp (term, "%s"))
1864
-	    {
1865
-	      char *s = va_arg (arglist, char *);
1866
-	      if (!s)
1867
-		s = "";
1868
-	      argv_append (a, string_alloc (s, NULL));
1869
-	      argv_system_str_append (a, s, true);
1870
-	    }
1871
-	  else if (!strcmp (term, "%sc"))
1872
-	    {
1873
-	      char *s = va_arg (arglist, char *);
1874
-	      if (s)
1875
-		{
1876
-		  int nparms;
1877
-		  char *parms[MAX_PARMS+1];
1878
-		  int i;
1879
-
1880
-		  nparms = parse_line (s, parms, MAX_PARMS, "SCRIPT-ARGV", 0, D_ARGV_PARSE_CMD, &gc);
1881
-		  if (nparms)
1882
-		    {
1883
-		      for (i = 0; i < nparms; ++i)
1884
-			argv_append (a, string_alloc (parms[i], NULL));
1885
-		    }
1886
-		  else
1887
-		    argv_append (a, string_alloc (s, NULL));
1888
-
1889
-		  argv_system_str_append (a, s, false);
1890
-		}
1891
-	      else
1892
-		{
1893
-		  argv_append (a, string_alloc ("", NULL));
1894
-		  argv_system_str_append (a, "echo", false);
1895
-		}
1896
-	    }
1897
-	  else if (!strcmp (term, "%d"))
1898
-	    {
1899
-	      char numstr[64];
1900
-	      openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
1901
-	      argv_append (a, string_alloc (numstr, NULL));
1902
-	      argv_system_str_append (a, numstr, false);
1903
-	    }
1904
-	  else if (!strcmp (term, "%u"))
1905
-	    {
1906
-	      char numstr[64];
1907
-	      openvpn_snprintf (numstr, sizeof (numstr), "%u", va_arg (arglist, unsigned int));
1908
-	      argv_append (a, string_alloc (numstr, NULL));
1909
-	      argv_system_str_append (a, numstr, false);
1910
-	    }
1911
-	  else if (!strcmp (term, "%s/%d"))
1912
-	    {
1913
-	      char numstr[64];
1914
-	      char *s = va_arg (arglist, char *);
1915
-
1916
-	      if (!s)
1917
-		s = "";
1918
-
1919
-	      openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
1920
-
1921
-	      {
1922
-		const size_t len = strlen(s) + strlen(numstr) + 2;
1923
-		char *combined = (char *) malloc (len);
1924
-		check_malloc_return (combined);
1925
-
1926
-		strcpy (combined, s);
1927
-		strcat (combined, "/");
1928
-		strcat (combined, numstr);
1929
-		argv_append (a, combined);
1930
-		argv_system_str_append (a, combined, false);
1931
-	      }
1932
-	    }
1933
-	  else if (!strcmp (term, "%s%sc"))
1934
-	    {
1935
-	      char *s1 = va_arg (arglist, char *);
1936
-	      char *s2 = va_arg (arglist, char *);
1937
-	      char *combined;
1938
-	      char *cmd_name;
1939
-
1940
-	      if (!s1) s1 = "";
1941
-	      if (!s2) s2 = "";
1942
-	      combined = (char *) malloc (strlen(s1) + strlen(s2) + 1);
1943
-	      check_malloc_return (combined);
1944
-	      strcpy (combined, s1);
1945
-	      strcat (combined, s2);
1946
-	      argv_append (a, combined);
1947
-
1948
-	      cmd_name = argv_extract_cmd_name (combined);
1949
-	      if (cmd_name)
1950
-		{
1951
-		  argv_system_str_append (a, cmd_name, false);
1952
-		  free (cmd_name);
1953
-		}
1954
-	    }
1955
-	  else
1956
-	    ASSERT (0);
1957
-	  free (term);
1958
-	}
1959
-      else
1960
-	{
1961
-	  argv_append (a, term);
1962
-	  argv_system_str_append (a, term, false);
1963
-	}
1964
-    }
1965
-  gc_free (&gc);
1966
-}
1967
-
1968
-#ifdef ARGV_TEST
1969
-void
1970
-argv_test (void)
1971
-{
1972
-  struct gc_arena gc = gc_new ();
1973
-  const char *s;
1974
-
1975
-  struct argv a;
1976
-
1977
-  argv_init (&a);
1978
-  argv_printf (&a, "%sc foo bar %s", "c:\\\\src\\\\test\\\\jyargs.exe", "foo bar");
1979
-  argv_msg_prefix (M_INFO, &a, "ARGV");
1980
-  msg (M_INFO, "ARGV-S: %s", argv_system_str(&a));
1981
-  /*openvpn_execve_check (&a, NULL, 0, "command failed");*/
1982
-
1983
-  argv_printf (&a, "%sc %s %s", "c:\\\\src\\\\test files\\\\batargs.bat", "foo", "bar");  
1984
-  argv_msg_prefix (M_INFO, &a, "ARGV");
1985
-  msg (M_INFO, "ARGV-S: %s", argv_system_str(&a));
1986
-  /*openvpn_execve_check (&a, NULL, 0, "command failed");*/
1987
-
1988
-  argv_printf (&a, "%s%sc foo bar %s %s/%d %d %u", "/foo", "/bar.exe", "one two", "1.2.3.4", 24, -69, 96);
1989
-  argv_msg_prefix (M_INFO, &a, "ARGV");
1990
-  msg (M_INFO, "ARGV-S: %s", argv_system_str(&a));
1991
-  /*openvpn_execve_check (&a, NULL, 0, "command failed");*/
1992
-
1993
-  argv_printf (&a, "this is a %s test of int %d unsigned %u", "FOO", -69, 42);
1994
-  s = argv_str (&a, &gc, PA_BRACKET);
1995
-  printf ("PF: %s\n", s);
1996
-  printf ("PF-S: %s\n", argv_system_str(&a));
1997
-
1998
-  {
1999
-    struct argv b = argv_insert_head (&a, "MARK");
2000
-    s = argv_str (&b, &gc, PA_BRACKET);
2001
-    printf ("PF: %s\n", s);
2002
-    printf ("PF-S: %s\n", argv_system_str(&b));
2003
-    argv_reset (&b);
2004
-  }
2005
-
2006
-  argv_printf (&a, "%sc foo bar %d", "\"multi term\" command      following \\\"spaces", 99);
2007
-  s = argv_str (&a, &gc, PA_BRACKET);
2008
-  printf ("PF: %s\n", s);
2009
-  printf ("PF-S: %s\n", argv_system_str(&a));
2010
-  argv_reset (&a);
2011
-
2012
-  s = argv_str (&a, &gc, PA_BRACKET);
2013
-  printf ("PF: %s\n", s);
2014
-  printf ("PF-S: %s\n", argv_system_str(&a));
2015
-  argv_reset (&a);
2016
-
2017
-  argv_printf (&a, "foo bar %d", 99);
2018
-  argv_printf_cat (&a, "bar %d foo %sc", 42, "nonesuch");
2019
-  argv_printf_cat (&a, "cool %s %d u %s/%d end", "frood", 4, "hello", 7);
2020
-  s = argv_str (&a, &gc, PA_BRACKET);
2021
-  printf ("PF: %s\n", s);
2022
-  printf ("PF-S: %s\n", argv_system_str(&a));
2023
-  argv_reset (&a);
2024
-
2025
-#if 0
2026
-  {
2027
-    char line[512];
2028
-    while (fgets (line, sizeof(line), stdin) != NULL)
2029
-      {
2030
-	char *term;
2031
-	const char *f = line;
2032
-	int i = 0;
2033
-
2034
-	while ((term = argv_term (&f)) != NULL) 
2035
-	  {
2036
-	    printf ("[%d] '%s'\n", i, term);
2037
-	    ++i;
2038
-	    free (term);
2039
-	  }
2040
-      }
2041
-  }
2042
-#endif
2043
-
2044
-  argv_reset (&a);
2045
-  gc_free (&gc);
2046
-}
2047
-#endif
2048
-
2049
-/*
2050 1591
  * Remove security-sensitive strings from control message
2051 1592
  * so that they will not be output to log file.
2052 1593
  */
... ...
@@ -25,6 +25,7 @@
25 25
 #ifndef MISC_H
26 26
 #define MISC_H
27 27
 
28
+#include "argv.h"
28 29
 #include "basic.h"
29 30
 #include "common.h"
30 31
 #include "integer.h"
... ...
@@ -37,14 +38,6 @@
37 37
 /* forward declarations */
38 38
 struct plugin_list;
39 39
 
40
-/* used by argv_x functions */
41
-struct argv {
42
-  size_t capacity;
43
-  size_t argc;
44
-  char **argv;
45
-  char *system_str;
46
-};
47
-
48 40
 /*
49 41
  * Handle environmental variable lists
50 42
  */
... ...
@@ -325,45 +318,6 @@ extern int script_security; /* GLOBAL */
325 325
 /* return the next largest power of 2 */
326 326
 size_t adjust_power_of_2 (size_t u);
327 327
 
328
-/*
329
- * A printf-like function (that only recognizes a subset of standard printf
330
- * format operators) that prints arguments to an argv list instead
331
- * of a standard string.  This is used to build up argv arrays for passing
332
- * to execve.
333
- */
334
-void argv_init (struct argv *a);
335
-struct argv argv_new (void);
336
-void argv_reset (struct argv *a);
337
-char *argv_term (const char **f);
338
-const char *argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags);
339
-struct argv argv_insert_head (const struct argv *a, const char *head);
340
-void argv_msg (const int msglev, const struct argv *a);
341
-void argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix);
342
-const char *argv_system_str (const struct argv *a);
343
-
344
-#define APA_CAT (1<<0) /* concatentate onto existing struct argv list */
345
-void argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist);
346
-
347
-void argv_printf (struct argv *a, const char *format, ...)
348
-#ifdef __GNUC__
349
-#if __USE_MINGW_ANSI_STDIO
350
-	__attribute__ ((format (gnu_printf, 2, 3)))
351
-#else
352
-	__attribute__ ((format (__printf__, 2, 3)))
353
-#endif
354
-#endif
355
-  ;
356
-
357
-void argv_printf_cat (struct argv *a, const char *format, ...)
358
-#ifdef __GNUC__
359
-#if __USE_MINGW_ANSI_STDIO
360
-	__attribute__ ((format (gnu_printf, 2, 3)))
361
-#else
362
-	__attribute__ ((format (__printf__, 2, 3)))
363
-#endif
364
-#endif
365
-  ;
366
-
367 328
 #define COMPAT_FLAG_QUERY         0       /** compat_flags operator: Query for a flag */
368 329
 #define COMPAT_FLAG_SET           (1<<0)  /** compat_flags operator: Set a compat flag */
369 330
 #define COMPAT_NAMES              (1<<1)  /** compat flag: --compat-names set */
... ...
@@ -1,5 +1,5 @@
1 1
 AUTOMAKE_OPTIONS = foreign
2 2
 
3 3
 if CMOCKA_INITIALIZED
4
-SUBDIRS = example_test plugins
4
+SUBDIRS = example_test plugins openvpn
5 5
 endif
6 6
new file mode 100644
... ...
@@ -0,0 +1,15 @@
0
+AUTOMAKE_OPTIONS = foreign
1
+
2
+check_PROGRAMS = argv_testdriver
3
+
4
+TESTS = $(check_PROGRAMS)
5
+
6
+openvpn_srcdir = $(top_srcdir)/src/openvpn
7
+compat_srcdir = $(top_srcdir)/src/compat
8
+
9
+argv_testdriver_CFLAGS  = @TEST_CFLAGS@ -I$(openvpn_srcdir) -I$(compat_srcdir)
10
+argv_testdriver_LDFLAGS = @TEST_LDFLAGS@ -L$(openvpn_srcdir) -Wl,--wrap=parse_line
11
+argv_testdriver_SOURCES = test_argv.c \
12
+	$(openvpn_srcdir)/platform.c \
13
+	$(openvpn_srcdir)/buffer.c \
14
+	$(openvpn_srcdir)/argv.c
0 15
new file mode 100644
... ...
@@ -0,0 +1,194 @@
0
+#include "config.h"
1
+#include "syshead.h"
2
+
3
+#include <stdio.h>
4
+#include <unistd.h>
5
+#include <stdlib.h>
6
+#include <stdarg.h>
7
+#include <string.h>
8
+#include <setjmp.h>
9
+#include <cmocka.h>
10
+#include <assert.h>
11
+
12
+#include "argv.h"
13
+#include "buffer.h"
14
+
15
+/*
16
+ * Dummy symbols that need to be defined due to them being
17
+ * referenced in #include'd header files and their includes
18
+ */
19
+unsigned int x_debug_level;
20
+bool dont_mute (unsigned int flags) { return true; }
21
+void assert_failed (const char *filename, int line, const char *condition) { exit(0); }
22
+void out_of_memory (void) { }
23
+void x_msg (const unsigned int flags, const char *format, ...) { }
24
+
25
+/*
26
+ * This is defined here to prevent #include'ing misc.h
27
+ * which makes things difficult beyond any recognition
28
+ */
29
+size_t
30
+adjust_power_of_2 (size_t u)
31
+{
32
+  size_t ret = 1;
33
+
34
+  while (ret < u)
35
+    {
36
+      ret <<= 1;
37
+      assert (ret > 0);
38
+    }
39
+
40
+  return ret;
41
+}
42
+
43
+/* Defines for use in the tests and the mock parse_line() */
44
+#define PATH1       "/s p a c e"
45
+#define PATH2       "/foo bar/baz"
46
+#define PARAM1      "param1"
47
+#define PARAM2      "param two"
48
+#define SCRIPT_CMD  "\"" PATH1 PATH2 "\"" PARAM1 "\"" PARAM2 "\""
49
+
50
+int
51
+__wrap_parse_line (const char *line, char **p, const int n, const char *file,
52
+                   const int line_num, int msglevel, struct gc_arena *gc)
53
+{
54
+  p[0] = PATH1 PATH2;
55
+  p[1] = PARAM1;
56
+  p[2] = PARAM2;
57
+  return 3;
58
+}
59
+
60
+static void
61
+argv_printf__multiple_spaces_in_format__parsed_as_one (void **state)
62
+{
63
+  struct argv a = argv_new ();
64
+
65
+  argv_printf (&a, "    %s     %s  %d   ", PATH1, PATH2, 42);
66
+  assert_int_equal (a.argc, 3);
67
+
68
+  argv_reset (&a);
69
+}
70
+
71
+static void
72
+argv_printf_cat__multiple_spaces_in_format__parsed_as_one (void **state)
73
+{
74
+  struct argv a = argv_new ();
75
+
76
+  argv_printf (&a, "%s ", PATH1);
77
+  argv_printf_cat (&a, " %s  %s", PATH2, PARAM1);
78
+  assert_int_equal (a.argc, 3);
79
+
80
+  argv_reset (&a);
81
+}
82
+
83
+static void
84
+argv_printf__combined_path_with_spaces__argc_correct (void **state)
85
+{
86
+  struct argv a = argv_new ();
87
+
88
+  argv_printf (&a, "%s%sc", PATH1, PATH2);
89
+  assert_int_equal (a.argc, 1);
90
+
91
+  argv_printf (&a, "%s%sc %d", PATH1, PATH2, 42);
92
+  assert_int_equal (a.argc, 2);
93
+
94
+  argv_printf (&a, "foo %s%sc %s x y", PATH2, PATH1, "foo");
95
+  assert_int_equal (a.argc, 5);
96
+
97
+  argv_reset (&a);
98
+}
99
+
100
+static void
101
+argv_printf__script_command__argc_correct (void **state)
102
+{
103
+  struct argv a = argv_new ();
104
+
105
+  argv_printf (&a, "%sc", SCRIPT_CMD);
106
+  assert_int_equal (a.argc, 3);
107
+
108
+  argv_printf (&a, "bar baz %sc %d %s", SCRIPT_CMD, 42, PATH1);
109
+  assert_int_equal (a.argc, 7);
110
+
111
+  argv_reset (&a);
112
+}
113
+
114
+static void
115
+argv_printf_cat__used_twice__argc_correct (void **state)
116
+{
117
+  struct argv a = argv_new ();
118
+
119
+  argv_printf (&a, "%s %s %s", PATH1, PATH2, PARAM1);
120
+  argv_printf_cat (&a, "%s", PARAM2);
121
+  argv_printf_cat (&a, "foo");
122
+  assert_int_equal (a.argc, 5);
123
+
124
+  argv_reset (&a);
125
+}
126
+
127
+static void
128
+argv_str__multiple_argv__correct_output (void **state)
129
+{
130
+  struct argv a = argv_new ();
131
+  struct gc_arena gc = gc_new ();
132
+  const char *output;
133
+
134
+  argv_printf (&a, "%s%sc", PATH1, PATH2);
135
+  argv_printf_cat (&a, "%s", PARAM1);
136
+  argv_printf_cat (&a, "%s", PARAM2);
137
+  output = argv_str (&a, &gc, PA_BRACKET);
138
+  assert_string_equal (output, "[" PATH1 PATH2 "] [" PARAM1 "] [" PARAM2 "]");
139
+
140
+  argv_reset (&a);
141
+  gc_free (&gc);
142
+}
143
+
144
+static void
145
+argv_insert_head__empty_argv__head_only (void **state)
146
+{
147
+  struct argv a = argv_new ();
148
+  struct argv b;
149
+
150
+  b = argv_insert_head (&a, PATH1);
151
+  assert_int_equal (b.argc, 1);
152
+  assert_string_equal (b.argv[0], PATH1);
153
+  argv_reset (&b);
154
+
155
+  argv_reset (&a);
156
+}
157
+
158
+static void
159
+argv_insert_head__non_empty_argv__head_added (void **state)
160
+{
161
+  struct argv a = argv_new ();
162
+  struct argv b;
163
+  int i;
164
+
165
+  argv_printf (&a, "%s", PATH2);
166
+  b = argv_insert_head (&a, PATH1);
167
+  assert_int_equal (b.argc, a.argc + 1);
168
+  for (i = 0; i < b.argc; i++) {
169
+    if (i == 0)
170
+      assert_string_equal (b.argv[i], PATH1);
171
+    else
172
+      assert_string_equal (b.argv[i], a.argv[i - 1]);
173
+  }
174
+  argv_reset (&b);
175
+
176
+  argv_reset (&a);
177
+}
178
+
179
+int
180
+main(void)
181
+{
182
+  const struct CMUnitTest tests[] = {
183
+    cmocka_unit_test (argv_printf__multiple_spaces_in_format__parsed_as_one),
184
+    cmocka_unit_test (argv_printf_cat__multiple_spaces_in_format__parsed_as_one),
185
+    cmocka_unit_test (argv_printf__combined_path_with_spaces__argc_correct),
186
+    cmocka_unit_test (argv_printf__script_command__argc_correct),
187
+    cmocka_unit_test (argv_printf_cat__used_twice__argc_correct),
188
+    cmocka_unit_test (argv_str__multiple_argv__correct_output),
189
+    cmocka_unit_test (argv_insert_head__non_empty_argv__head_added),
190
+  };
191
+
192
+  return cmocka_run_group_tests_name ("argv", tests, NULL, NULL);
193
+}