tests/unit_tests/plugins/Makefile
tests/unit_tests/plugins/auth-pam/Makefile
tests/unit_tests/example_test/Makefile
+ tests/unit_tests/openvpn/Makefile
vendor/Makefile
sample/Makefile
doc/Makefile
sbin_PROGRAMS = openvpn
openvpn_SOURCES = \
+ argv.c argv.h \
base64.c base64.h \
basic.h \
buffer.c buffer.h \
--- /dev/null
+/*
+ * OpenVPN -- An application to securely tunnel IP networks
+ * over a single TCP/UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ * A printf-like function (that only recognizes a subset of standard printf
+ * format operators) that prints arguments to an argv list instead
+ * of a standard string. This is used to build up argv arrays for passing
+ * to execve.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#elif defined(_MSC_VER)
+#include "config-msvc.h"
+#endif
+
+#include "syshead.h"
+
+#include "argv.h"
+#include "options.h"
+
+void
+argv_init (struct argv *a)
+{
+ a->capacity = 0;
+ a->argc = 0;
+ a->argv = NULL;
+ a->system_str = NULL;
+}
+
+struct argv
+argv_new (void)
+{
+ struct argv ret;
+ argv_init (&ret);
+ return ret;
+}
+
+void
+argv_reset (struct argv *a)
+{
+ size_t i;
+ for (i = 0; i < a->argc; ++i)
+ free (a->argv[i]);
+ free (a->argv);
+ free (a->system_str);
+ argv_init (a);
+}
+
+static void
+argv_extend (struct argv *a, const size_t newcap)
+{
+ if (newcap > a->capacity)
+ {
+ char **newargv;
+ size_t i;
+ ALLOC_ARRAY_CLEAR (newargv, char *, newcap);
+ for (i = 0; i < a->argc; ++i)
+ newargv[i] = a->argv[i];
+ free (a->argv);
+ a->argv = newargv;
+ a->capacity = newcap;
+ }
+}
+
+static void
+argv_grow (struct argv *a, const size_t add)
+{
+ const size_t newargc = a->argc + add + 1;
+ ASSERT (newargc > a->argc);
+ argv_extend (a, adjust_power_of_2 (newargc));
+}
+
+static void
+argv_append (struct argv *a, char *str) /* str must have been malloced or be NULL */
+{
+ argv_grow (a, 1);
+ a->argv[a->argc++] = str;
+}
+
+static void
+argv_system_str_append (struct argv *a, const char *str, const bool enquote)
+{
+ if (str)
+ {
+ char *newstr;
+
+ /* compute length of new system_str */
+ size_t l = strlen (str) + 1; /* space for new string plus trailing '\0' */
+ if (a->system_str)
+ l += strlen (a->system_str) + 1; /* space for existing string + space (" ") separator */
+ if (enquote)
+ l += 2; /* space for two quotes */
+
+ /* build new system_str */
+ newstr = (char *) malloc (l);
+ newstr[0] = '\0';
+ check_malloc_return (newstr);
+ if (a->system_str)
+ {
+ strcpy (newstr, a->system_str);
+ strcat (newstr, " ");
+ }
+ if (enquote)
+ strcat (newstr, "\"");
+ strcat (newstr, str);
+ if (enquote)
+ strcat (newstr, "\"");
+ free (a->system_str);
+ a->system_str = newstr;
+ }
+}
+
+static char *
+argv_extract_cmd_name (const char *path)
+{
+ char *ret = NULL;
+ if (path)
+ {
+ char *path_cp = string_alloc(path, NULL); /* POSIX basename() implementaions may modify its arguments */
+ const char *bn = basename (path_cp);
+ if (bn)
+ {
+ char *dot = NULL;
+ ret = string_alloc (bn, NULL);
+ dot = strrchr (ret, '.');
+ if (dot)
+ *dot = '\0';
+ free(path_cp);
+ if (ret[0] == '\0')
+ {
+ free(ret);
+ ret = NULL;
+ }
+ }
+ }
+ return ret;
+}
+
+const char *
+argv_system_str (const struct argv *a)
+{
+ return a->system_str;
+}
+
+static struct argv
+argv_clone (const struct argv *a, const size_t headroom)
+{
+ struct argv r;
+ size_t i;
+
+ argv_init (&r);
+ for (i = 0; i < headroom; ++i)
+ argv_append (&r, NULL);
+ if (a)
+ {
+ for (i = 0; i < a->argc; ++i)
+ argv_append (&r, string_alloc (a->argv[i], NULL));
+ r.system_str = string_alloc (a->system_str, NULL);
+ }
+ return r;
+}
+
+struct argv
+argv_insert_head (const struct argv *a, const char *head)
+{
+ struct argv r;
+ char *s;
+
+ r = argv_clone (a, 1);
+ r.argv[0] = string_alloc (head, NULL);
+ s = r.system_str;
+ r.system_str = string_alloc (head, NULL);
+ if (s)
+ {
+ argv_system_str_append (&r, s, false);
+ free (s);
+ }
+ return r;
+}
+
+char *
+argv_term (const char **f)
+{
+ const char *p = *f;
+ const char *term = NULL;
+ size_t termlen = 0;
+
+ if (*p == '\0')
+ return NULL;
+
+ while (true)
+ {
+ const int c = *p;
+ if (c == '\0')
+ break;
+ if (term)
+ {
+ if (!isspace (c))
+ ++termlen;
+ else
+ break;
+ }
+ else
+ {
+ if (!isspace (c))
+ {
+ term = p;
+ termlen = 1;
+ }
+ }
+ ++p;
+ }
+ *f = p;
+
+ if (term)
+ {
+ char *ret;
+ ASSERT (termlen > 0);
+ ret = malloc (termlen + 1);
+ check_malloc_return (ret);
+ memcpy (ret, term, termlen);
+ ret[termlen] = '\0';
+ return ret;
+ }
+ else
+ return NULL;
+}
+
+const char *
+argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags)
+{
+ if (a->argv)
+ return print_argv ((const char **)a->argv, gc, flags);
+ else
+ return "";
+}
+
+void
+argv_msg (const int msglev, const struct argv *a)
+{
+ struct gc_arena gc = gc_new ();
+ msg (msglev, "%s", argv_str (a, &gc, 0));
+ gc_free (&gc);
+}
+
+void
+argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix)
+{
+ struct gc_arena gc = gc_new ();
+ msg (msglev, "%s: %s", prefix, argv_str (a, &gc, 0));
+ gc_free (&gc);
+}
+
+void
+argv_printf (struct argv *a, const char *format, ...)
+{
+ va_list arglist;
+ va_start (arglist, format);
+ argv_printf_arglist (a, format, 0, arglist);
+ va_end (arglist);
+ }
+
+void
+argv_printf_cat (struct argv *a, const char *format, ...)
+{
+ va_list arglist;
+ va_start (arglist, format);
+ argv_printf_arglist (a, format, APA_CAT, arglist);
+ va_end (arglist);
+}
+
+void
+argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist)
+{
+ struct gc_arena gc = gc_new ();
+ char *term;
+ const char *f = format;
+
+ if (!(flags & APA_CAT))
+ argv_reset (a);
+ argv_extend (a, 1); /* ensure trailing NULL */
+
+ while ((term = argv_term (&f)) != NULL)
+ {
+ if (term[0] == '%')
+ {
+ if (!strcmp (term, "%s"))
+ {
+ char *s = va_arg (arglist, char *);
+ if (!s)
+ s = "";
+ argv_append (a, string_alloc (s, NULL));
+ argv_system_str_append (a, s, true);
+ }
+ else if (!strcmp (term, "%sc"))
+ {
+ char *s = va_arg (arglist, char *);
+ if (s)
+ {
+ int nparms;
+ char *parms[MAX_PARMS+1];
+ int i;
+
+ nparms = parse_line (s, parms, MAX_PARMS, "SCRIPT-ARGV", 0, D_ARGV_PARSE_CMD, &gc);
+ if (nparms)
+ {
+ for (i = 0; i < nparms; ++i)
+ argv_append (a, string_alloc (parms[i], NULL));
+ }
+ else
+ argv_append (a, string_alloc (s, NULL));
+
+ argv_system_str_append (a, s, false);
+ }
+ else
+ {
+ argv_append (a, string_alloc ("", NULL));
+ argv_system_str_append (a, "echo", false);
+ }
+ }
+ else if (!strcmp (term, "%d"))
+ {
+ char numstr[64];
+ openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
+ argv_append (a, string_alloc (numstr, NULL));
+ argv_system_str_append (a, numstr, false);
+ }
+ else if (!strcmp (term, "%u"))
+ {
+ char numstr[64];
+ openvpn_snprintf (numstr, sizeof (numstr), "%u", va_arg (arglist, unsigned int));
+ argv_append (a, string_alloc (numstr, NULL));
+ argv_system_str_append (a, numstr, false);
+ }
+ else if (!strcmp (term, "%s/%d"))
+ {
+ char numstr[64];
+ char *s = va_arg (arglist, char *);
+
+ if (!s)
+ s = "";
+
+ openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
+
+ {
+ const size_t len = strlen(s) + strlen(numstr) + 2;
+ char *combined = (char *) malloc (len);
+ check_malloc_return (combined);
+
+ strcpy (combined, s);
+ strcat (combined, "/");
+ strcat (combined, numstr);
+ argv_append (a, combined);
+ argv_system_str_append (a, combined, false);
+ }
+ }
+ else if (!strcmp (term, "%s%sc"))
+ {
+ char *s1 = va_arg (arglist, char *);
+ char *s2 = va_arg (arglist, char *);
+ char *combined;
+ char *cmd_name;
+
+ if (!s1) s1 = "";
+ if (!s2) s2 = "";
+ combined = (char *) malloc (strlen(s1) + strlen(s2) + 1);
+ check_malloc_return (combined);
+ strcpy (combined, s1);
+ strcat (combined, s2);
+ argv_append (a, combined);
+
+ cmd_name = argv_extract_cmd_name (combined);
+ if (cmd_name)
+ {
+ argv_system_str_append (a, cmd_name, false);
+ free (cmd_name);
+ }
+ }
+ else
+ ASSERT (0);
+ free (term);
+ }
+ else
+ {
+ argv_append (a, term);
+ argv_system_str_append (a, term, false);
+ }
+ }
+ gc_free (&gc);
+}
--- /dev/null
+/*
+ * OpenVPN -- An application to securely tunnel IP networks
+ * over a single TCP/UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ * A printf-like function (that only recognizes a subset of standard printf
+ * format operators) that prints arguments to an argv list instead
+ * of a standard string. This is used to build up argv arrays for passing
+ * to execve.
+ */
+
+#ifndef ARGV_H
+#define ARGV_H
+
+#include "buffer.h"
+
+struct argv {
+ size_t capacity;
+ size_t argc;
+ char **argv;
+ char *system_str;
+};
+
+void argv_init (struct argv *a);
+struct argv argv_new (void);
+void argv_reset (struct argv *a);
+char *argv_term (const char **f);
+const char *argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags);
+struct argv argv_insert_head (const struct argv *a, const char *head);
+void argv_msg (const int msglev, const struct argv *a);
+void argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix);
+const char *argv_system_str (const struct argv *a);
+
+#define APA_CAT (1<<0) /* concatentate onto existing struct argv list */
+void argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist);
+
+void argv_printf (struct argv *a, const char *format, ...)
+#ifdef __GNUC__
+#if __USE_MINGW_ANSI_STDIO
+ __attribute__ ((format (gnu_printf, 2, 3)))
+#else
+ __attribute__ ((format (__printf__, 2, 3)))
+#endif
+#endif
+ ;
+
+void argv_printf_cat (struct argv *a, const char *format, ...)
+#ifdef __GNUC__
+#if __USE_MINGW_ANSI_STDIO
+ __attribute__ ((format (gnu_printf, 2, 3)))
+#else
+ __attribute__ ((format (__printf__, 2, 3)))
+#endif
+#endif
+ ;
+
+#endif
return ret;
}
-/*
- * A printf-like function (that only recognizes a subset of standard printf
- * format operators) that prints arguments to an argv list instead
- * of a standard string. This is used to build up argv arrays for passing
- * to execve.
- */
-
-void
-argv_init (struct argv *a)
-{
- a->capacity = 0;
- a->argc = 0;
- a->argv = NULL;
- a->system_str = NULL;
-}
-
-struct argv
-argv_new (void)
-{
- struct argv ret;
- argv_init (&ret);
- return ret;
-}
-
-void
-argv_reset (struct argv *a)
-{
- size_t i;
- for (i = 0; i < a->argc; ++i)
- free (a->argv[i]);
- free (a->argv);
- free (a->system_str);
- argv_init (a);
-}
-
-static void
-argv_extend (struct argv *a, const size_t newcap)
-{
- if (newcap > a->capacity)
- {
- char **newargv;
- size_t i;
- ALLOC_ARRAY_CLEAR (newargv, char *, newcap);
- for (i = 0; i < a->argc; ++i)
- newargv[i] = a->argv[i];
- free (a->argv);
- a->argv = newargv;
- a->capacity = newcap;
- }
-}
-
-static void
-argv_grow (struct argv *a, const size_t add)
-{
- const size_t newargc = a->argc + add + 1;
- ASSERT (newargc > a->argc);
- argv_extend (a, adjust_power_of_2 (newargc));
-}
-
-static void
-argv_append (struct argv *a, char *str) /* str must have been malloced or be NULL */
-{
- argv_grow (a, 1);
- a->argv[a->argc++] = str;
-}
-
-static void
-argv_system_str_append (struct argv *a, const char *str, const bool enquote)
-{
- if (str)
- {
- char *newstr;
-
- /* compute length of new system_str */
- size_t l = strlen (str) + 1; /* space for new string plus trailing '\0' */
- if (a->system_str)
- l += strlen (a->system_str) + 1; /* space for existing string + space (" ") separator */
- if (enquote)
- l += 2; /* space for two quotes */
-
- /* build new system_str */
- newstr = (char *) malloc (l);
- newstr[0] = '\0';
- check_malloc_return (newstr);
- if (a->system_str)
- {
- strcpy (newstr, a->system_str);
- strcat (newstr, " ");
- }
- if (enquote)
- strcat (newstr, "\"");
- strcat (newstr, str);
- if (enquote)
- strcat (newstr, "\"");
- free (a->system_str);
- a->system_str = newstr;
- }
-}
-
-static char *
-argv_extract_cmd_name (const char *path)
-{
- char *ret = NULL;
- if (path)
- {
- char *path_cp = string_alloc(path, NULL); /* POSIX basename() implementaions may modify its arguments */
- const char *bn = basename (path_cp);
- if (bn)
- {
- char *dot = NULL;
- ret = string_alloc (bn, NULL);
- dot = strrchr (ret, '.');
- if (dot)
- *dot = '\0';
- free(path_cp);
- if (ret[0] == '\0')
- {
- free(ret);
- ret = NULL;
- }
- }
- }
- return ret;
-}
-
-const char *
-argv_system_str (const struct argv *a)
-{
- return a->system_str;
-}
-
-struct argv
-argv_clone (const struct argv *a, const size_t headroom)
-{
- struct argv r;
- size_t i;
-
- argv_init (&r);
- for (i = 0; i < headroom; ++i)
- argv_append (&r, NULL);
- if (a)
- {
- for (i = 0; i < a->argc; ++i)
- argv_append (&r, string_alloc (a->argv[i], NULL));
- r.system_str = string_alloc (a->system_str, NULL);
- }
- return r;
-}
-
-struct argv
-argv_insert_head (const struct argv *a, const char *head)
-{
- struct argv r;
- char *s;
-
- r = argv_clone (a, 1);
- r.argv[0] = string_alloc (head, NULL);
- s = r.system_str;
- r.system_str = string_alloc (head, NULL);
- if (s)
- {
- argv_system_str_append (&r, s, false);
- free (s);
- }
- return r;
-}
-
-char *
-argv_term (const char **f)
-{
- const char *p = *f;
- const char *term = NULL;
- size_t termlen = 0;
-
- if (*p == '\0')
- return NULL;
-
- while (true)
- {
- const int c = *p;
- if (c == '\0')
- break;
- if (term)
- {
- if (!isspace (c))
- ++termlen;
- else
- break;
- }
- else
- {
- if (!isspace (c))
- {
- term = p;
- termlen = 1;
- }
- }
- ++p;
- }
- *f = p;
-
- if (term)
- {
- char *ret;
- ASSERT (termlen > 0);
- ret = malloc (termlen + 1);
- check_malloc_return (ret);
- memcpy (ret, term, termlen);
- ret[termlen] = '\0';
- return ret;
- }
- else
- return NULL;
-}
-
-const char *
-argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags)
-{
- if (a->argv)
- return print_argv ((const char **)a->argv, gc, flags);
- else
- return "";
-}
-
-void
-argv_msg (const int msglev, const struct argv *a)
-{
- struct gc_arena gc = gc_new ();
- msg (msglev, "%s", argv_str (a, &gc, 0));
- gc_free (&gc);
-}
-
-void
-argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix)
-{
- struct gc_arena gc = gc_new ();
- msg (msglev, "%s: %s", prefix, argv_str (a, &gc, 0));
- gc_free (&gc);
-}
-
-void
-argv_printf (struct argv *a, const char *format, ...)
-{
- va_list arglist;
- va_start (arglist, format);
- argv_printf_arglist (a, format, 0, arglist);
- va_end (arglist);
- }
-
-void
-argv_printf_cat (struct argv *a, const char *format, ...)
-{
- va_list arglist;
- va_start (arglist, format);
- argv_printf_arglist (a, format, APA_CAT, arglist);
- va_end (arglist);
-}
-
-void
-argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist)
-{
- struct gc_arena gc = gc_new ();
- char *term;
- const char *f = format;
-
- if (!(flags & APA_CAT))
- argv_reset (a);
- argv_extend (a, 1); /* ensure trailing NULL */
-
- while ((term = argv_term (&f)) != NULL)
- {
- if (term[0] == '%')
- {
- if (!strcmp (term, "%s"))
- {
- char *s = va_arg (arglist, char *);
- if (!s)
- s = "";
- argv_append (a, string_alloc (s, NULL));
- argv_system_str_append (a, s, true);
- }
- else if (!strcmp (term, "%sc"))
- {
- char *s = va_arg (arglist, char *);
- if (s)
- {
- int nparms;
- char *parms[MAX_PARMS+1];
- int i;
-
- nparms = parse_line (s, parms, MAX_PARMS, "SCRIPT-ARGV", 0, D_ARGV_PARSE_CMD, &gc);
- if (nparms)
- {
- for (i = 0; i < nparms; ++i)
- argv_append (a, string_alloc (parms[i], NULL));
- }
- else
- argv_append (a, string_alloc (s, NULL));
-
- argv_system_str_append (a, s, false);
- }
- else
- {
- argv_append (a, string_alloc ("", NULL));
- argv_system_str_append (a, "echo", false);
- }
- }
- else if (!strcmp (term, "%d"))
- {
- char numstr[64];
- openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
- argv_append (a, string_alloc (numstr, NULL));
- argv_system_str_append (a, numstr, false);
- }
- else if (!strcmp (term, "%u"))
- {
- char numstr[64];
- openvpn_snprintf (numstr, sizeof (numstr), "%u", va_arg (arglist, unsigned int));
- argv_append (a, string_alloc (numstr, NULL));
- argv_system_str_append (a, numstr, false);
- }
- else if (!strcmp (term, "%s/%d"))
- {
- char numstr[64];
- char *s = va_arg (arglist, char *);
-
- if (!s)
- s = "";
-
- openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
-
- {
- const size_t len = strlen(s) + strlen(numstr) + 2;
- char *combined = (char *) malloc (len);
- check_malloc_return (combined);
-
- strcpy (combined, s);
- strcat (combined, "/");
- strcat (combined, numstr);
- argv_append (a, combined);
- argv_system_str_append (a, combined, false);
- }
- }
- else if (!strcmp (term, "%s%sc"))
- {
- char *s1 = va_arg (arglist, char *);
- char *s2 = va_arg (arglist, char *);
- char *combined;
- char *cmd_name;
-
- if (!s1) s1 = "";
- if (!s2) s2 = "";
- combined = (char *) malloc (strlen(s1) + strlen(s2) + 1);
- check_malloc_return (combined);
- strcpy (combined, s1);
- strcat (combined, s2);
- argv_append (a, combined);
-
- cmd_name = argv_extract_cmd_name (combined);
- if (cmd_name)
- {
- argv_system_str_append (a, cmd_name, false);
- free (cmd_name);
- }
- }
- else
- ASSERT (0);
- free (term);
- }
- else
- {
- argv_append (a, term);
- argv_system_str_append (a, term, false);
- }
- }
- gc_free (&gc);
-}
-
-#ifdef ARGV_TEST
-void
-argv_test (void)
-{
- struct gc_arena gc = gc_new ();
- const char *s;
-
- struct argv a;
-
- argv_init (&a);
- argv_printf (&a, "%sc foo bar %s", "c:\\\\src\\\\test\\\\jyargs.exe", "foo bar");
- argv_msg_prefix (M_INFO, &a, "ARGV");
- msg (M_INFO, "ARGV-S: %s", argv_system_str(&a));
- /*openvpn_execve_check (&a, NULL, 0, "command failed");*/
-
- argv_printf (&a, "%sc %s %s", "c:\\\\src\\\\test files\\\\batargs.bat", "foo", "bar");
- argv_msg_prefix (M_INFO, &a, "ARGV");
- msg (M_INFO, "ARGV-S: %s", argv_system_str(&a));
- /*openvpn_execve_check (&a, NULL, 0, "command failed");*/
-
- argv_printf (&a, "%s%sc foo bar %s %s/%d %d %u", "/foo", "/bar.exe", "one two", "1.2.3.4", 24, -69, 96);
- argv_msg_prefix (M_INFO, &a, "ARGV");
- msg (M_INFO, "ARGV-S: %s", argv_system_str(&a));
- /*openvpn_execve_check (&a, NULL, 0, "command failed");*/
-
- argv_printf (&a, "this is a %s test of int %d unsigned %u", "FOO", -69, 42);
- s = argv_str (&a, &gc, PA_BRACKET);
- printf ("PF: %s\n", s);
- printf ("PF-S: %s\n", argv_system_str(&a));
-
- {
- struct argv b = argv_insert_head (&a, "MARK");
- s = argv_str (&b, &gc, PA_BRACKET);
- printf ("PF: %s\n", s);
- printf ("PF-S: %s\n", argv_system_str(&b));
- argv_reset (&b);
- }
-
- argv_printf (&a, "%sc foo bar %d", "\"multi term\" command following \\\"spaces", 99);
- s = argv_str (&a, &gc, PA_BRACKET);
- printf ("PF: %s\n", s);
- printf ("PF-S: %s\n", argv_system_str(&a));
- argv_reset (&a);
-
- s = argv_str (&a, &gc, PA_BRACKET);
- printf ("PF: %s\n", s);
- printf ("PF-S: %s\n", argv_system_str(&a));
- argv_reset (&a);
-
- argv_printf (&a, "foo bar %d", 99);
- argv_printf_cat (&a, "bar %d foo %sc", 42, "nonesuch");
- argv_printf_cat (&a, "cool %s %d u %s/%d end", "frood", 4, "hello", 7);
- s = argv_str (&a, &gc, PA_BRACKET);
- printf ("PF: %s\n", s);
- printf ("PF-S: %s\n", argv_system_str(&a));
- argv_reset (&a);
-
-#if 0
- {
- char line[512];
- while (fgets (line, sizeof(line), stdin) != NULL)
- {
- char *term;
- const char *f = line;
- int i = 0;
-
- while ((term = argv_term (&f)) != NULL)
- {
- printf ("[%d] '%s'\n", i, term);
- ++i;
- free (term);
- }
- }
- }
-#endif
-
- argv_reset (&a);
- gc_free (&gc);
-}
-#endif
-
/*
* Remove security-sensitive strings from control message
* so that they will not be output to log file.
#ifndef MISC_H
#define MISC_H
+#include "argv.h"
#include "basic.h"
#include "common.h"
#include "integer.h"
/* forward declarations */
struct plugin_list;
-/* used by argv_x functions */
-struct argv {
- size_t capacity;
- size_t argc;
- char **argv;
- char *system_str;
-};
-
/*
* Handle environmental variable lists
*/
/* return the next largest power of 2 */
size_t adjust_power_of_2 (size_t u);
-/*
- * A printf-like function (that only recognizes a subset of standard printf
- * format operators) that prints arguments to an argv list instead
- * of a standard string. This is used to build up argv arrays for passing
- * to execve.
- */
-void argv_init (struct argv *a);
-struct argv argv_new (void);
-void argv_reset (struct argv *a);
-char *argv_term (const char **f);
-const char *argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags);
-struct argv argv_insert_head (const struct argv *a, const char *head);
-void argv_msg (const int msglev, const struct argv *a);
-void argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix);
-const char *argv_system_str (const struct argv *a);
-
-#define APA_CAT (1<<0) /* concatentate onto existing struct argv list */
-void argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist);
-
-void argv_printf (struct argv *a, const char *format, ...)
-#ifdef __GNUC__
-#if __USE_MINGW_ANSI_STDIO
- __attribute__ ((format (gnu_printf, 2, 3)))
-#else
- __attribute__ ((format (__printf__, 2, 3)))
-#endif
-#endif
- ;
-
-void argv_printf_cat (struct argv *a, const char *format, ...)
-#ifdef __GNUC__
-#if __USE_MINGW_ANSI_STDIO
- __attribute__ ((format (gnu_printf, 2, 3)))
-#else
- __attribute__ ((format (__printf__, 2, 3)))
-#endif
-#endif
- ;
-
#define COMPAT_FLAG_QUERY 0 /** compat_flags operator: Query for a flag */
#define COMPAT_FLAG_SET (1<<0) /** compat_flags operator: Set a compat flag */
#define COMPAT_NAMES (1<<1) /** compat flag: --compat-names set */
AUTOMAKE_OPTIONS = foreign
if CMOCKA_INITIALIZED
-SUBDIRS = example_test plugins
+SUBDIRS = example_test plugins openvpn
endif
--- /dev/null
+AUTOMAKE_OPTIONS = foreign
+
+check_PROGRAMS = argv_testdriver
+
+TESTS = $(check_PROGRAMS)
+
+openvpn_srcdir = $(top_srcdir)/src/openvpn
+compat_srcdir = $(top_srcdir)/src/compat
+
+argv_testdriver_CFLAGS = @TEST_CFLAGS@ -I$(openvpn_srcdir) -I$(compat_srcdir)
+argv_testdriver_LDFLAGS = @TEST_LDFLAGS@ -L$(openvpn_srcdir) -Wl,--wrap=parse_line
+argv_testdriver_SOURCES = test_argv.c \
+ $(openvpn_srcdir)/platform.c \
+ $(openvpn_srcdir)/buffer.c \
+ $(openvpn_srcdir)/argv.c
--- /dev/null
+#include "config.h"
+#include "syshead.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+
+#include "argv.h"
+#include "buffer.h"
+
+/*
+ * Dummy symbols that need to be defined due to them being
+ * referenced in #include'd header files and their includes
+ */
+unsigned int x_debug_level;
+bool dont_mute (unsigned int flags) { return true; }
+void assert_failed (const char *filename, int line, const char *condition) { exit(0); }
+void out_of_memory (void) { }
+void x_msg (const unsigned int flags, const char *format, ...) { }
+
+/*
+ * This is defined here to prevent #include'ing misc.h
+ * which makes things difficult beyond any recognition
+ */
+size_t
+adjust_power_of_2 (size_t u)
+{
+ size_t ret = 1;
+
+ while (ret < u)
+ {
+ ret <<= 1;
+ assert (ret > 0);
+ }
+
+ return ret;
+}
+
+/* Defines for use in the tests and the mock parse_line() */
+#define PATH1 "/s p a c e"
+#define PATH2 "/foo bar/baz"
+#define PARAM1 "param1"
+#define PARAM2 "param two"
+#define SCRIPT_CMD "\"" PATH1 PATH2 "\"" PARAM1 "\"" PARAM2 "\""
+
+int
+__wrap_parse_line (const char *line, char **p, const int n, const char *file,
+ const int line_num, int msglevel, struct gc_arena *gc)
+{
+ p[0] = PATH1 PATH2;
+ p[1] = PARAM1;
+ p[2] = PARAM2;
+ return 3;
+}
+
+static void
+argv_printf__multiple_spaces_in_format__parsed_as_one (void **state)
+{
+ struct argv a = argv_new ();
+
+ argv_printf (&a, " %s %s %d ", PATH1, PATH2, 42);
+ assert_int_equal (a.argc, 3);
+
+ argv_reset (&a);
+}
+
+static void
+argv_printf_cat__multiple_spaces_in_format__parsed_as_one (void **state)
+{
+ struct argv a = argv_new ();
+
+ argv_printf (&a, "%s ", PATH1);
+ argv_printf_cat (&a, " %s %s", PATH2, PARAM1);
+ assert_int_equal (a.argc, 3);
+
+ argv_reset (&a);
+}
+
+static void
+argv_printf__combined_path_with_spaces__argc_correct (void **state)
+{
+ struct argv a = argv_new ();
+
+ argv_printf (&a, "%s%sc", PATH1, PATH2);
+ assert_int_equal (a.argc, 1);
+
+ argv_printf (&a, "%s%sc %d", PATH1, PATH2, 42);
+ assert_int_equal (a.argc, 2);
+
+ argv_printf (&a, "foo %s%sc %s x y", PATH2, PATH1, "foo");
+ assert_int_equal (a.argc, 5);
+
+ argv_reset (&a);
+}
+
+static void
+argv_printf__script_command__argc_correct (void **state)
+{
+ struct argv a = argv_new ();
+
+ argv_printf (&a, "%sc", SCRIPT_CMD);
+ assert_int_equal (a.argc, 3);
+
+ argv_printf (&a, "bar baz %sc %d %s", SCRIPT_CMD, 42, PATH1);
+ assert_int_equal (a.argc, 7);
+
+ argv_reset (&a);
+}
+
+static void
+argv_printf_cat__used_twice__argc_correct (void **state)
+{
+ struct argv a = argv_new ();
+
+ argv_printf (&a, "%s %s %s", PATH1, PATH2, PARAM1);
+ argv_printf_cat (&a, "%s", PARAM2);
+ argv_printf_cat (&a, "foo");
+ assert_int_equal (a.argc, 5);
+
+ argv_reset (&a);
+}
+
+static void
+argv_str__multiple_argv__correct_output (void **state)
+{
+ struct argv a = argv_new ();
+ struct gc_arena gc = gc_new ();
+ const char *output;
+
+ argv_printf (&a, "%s%sc", PATH1, PATH2);
+ argv_printf_cat (&a, "%s", PARAM1);
+ argv_printf_cat (&a, "%s", PARAM2);
+ output = argv_str (&a, &gc, PA_BRACKET);
+ assert_string_equal (output, "[" PATH1 PATH2 "] [" PARAM1 "] [" PARAM2 "]");
+
+ argv_reset (&a);
+ gc_free (&gc);
+}
+
+static void
+argv_insert_head__empty_argv__head_only (void **state)
+{
+ struct argv a = argv_new ();
+ struct argv b;
+
+ b = argv_insert_head (&a, PATH1);
+ assert_int_equal (b.argc, 1);
+ assert_string_equal (b.argv[0], PATH1);
+ argv_reset (&b);
+
+ argv_reset (&a);
+}
+
+static void
+argv_insert_head__non_empty_argv__head_added (void **state)
+{
+ struct argv a = argv_new ();
+ struct argv b;
+ int i;
+
+ argv_printf (&a, "%s", PATH2);
+ b = argv_insert_head (&a, PATH1);
+ assert_int_equal (b.argc, a.argc + 1);
+ for (i = 0; i < b.argc; i++) {
+ if (i == 0)
+ assert_string_equal (b.argv[i], PATH1);
+ else
+ assert_string_equal (b.argv[i], a.argv[i - 1]);
+ }
+ argv_reset (&b);
+
+ argv_reset (&a);
+}
+
+int
+main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test (argv_printf__multiple_spaces_in_format__parsed_as_one),
+ cmocka_unit_test (argv_printf_cat__multiple_spaces_in_format__parsed_as_one),
+ cmocka_unit_test (argv_printf__combined_path_with_spaces__argc_correct),
+ cmocka_unit_test (argv_printf__script_command__argc_correct),
+ cmocka_unit_test (argv_printf_cat__used_twice__argc_correct),
+ cmocka_unit_test (argv_str__multiple_argv__correct_output),
+ cmocka_unit_test (argv_insert_head__non_empty_argv__head_added),
+ };
+
+ return cmocka_run_group_tests_name ("argv", tests, NULL, NULL);
+}