aboutsummaryrefslogtreecommitdiff
path: root/buffer.c
diff options
context:
space:
mode:
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2008-07-26 07:27:03 +0000
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2008-07-26 07:27:03 +0000
commit5a2e9a2587372aeb4b74fa1aadf53283ed7cae10 (patch)
treebc79922f81699bc51c2ac047309e6ab594eebcd2 /buffer.c
parentAdded argv_x functions to buffer.[ch] to be used to safely build (diff)
downloadopenvpn-5a2e9a2587372aeb4b74fa1aadf53283ed7cae10.tar.xz
Completely revamped the system for calling external programs and scripts:
* All external programs and scripts are now called by execve() on unix and CreateProcess on Windows. * The system() function is no longer used. * Argument lists for external programs and scripts are now built by the new argv_printf function which natively outputs to string arrays (i.e. char *argv[] lists), never truncates its output, and eliminates the security issues inherent in formatting and parsing command lines, and dealing with argument quoting. * The --script-security directive has been added to offer policy controls on OpenVPN's execution of external programs and scripts. Also added a new plugin example (openvpn/plugin/examples/log.c) that logs information to stdout for every plugin method called by OpenVPN. git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@3122 e7ae566f-a301-0410-adde-c780ea21d3b5
Diffstat (limited to 'buffer.c')
-rw-r--r--buffer.c132
1 files changed, 80 insertions, 52 deletions
diff --git a/buffer.c b/buffer.c
index c7eab07..b62d4b8 100644
--- a/buffer.c
+++ b/buffer.c
@@ -240,6 +240,14 @@ argv_init (struct argv *a)
a->argv = NULL;
}
+struct argv
+argv_new (void)
+{
+ struct argv ret;
+ argv_init (&ret);
+ return ret;
+}
+
void
argv_reset (struct argv *a)
{
@@ -266,6 +274,23 @@ argv_argc (const char *format)
return argc;
}
+struct argv
+argv_insert_head (const struct argv *a, const char *head)
+{
+ struct argv r;
+ size_t i;
+
+ r.argc = (a ? a->argc : 0) + 1;
+ ALLOC_ARRAY_CLEAR (r.argv, char *, r.argc + 1);
+ r.argv[0] = string_alloc (head, NULL);
+ if (a)
+ {
+ for (i = 0; i < a->argc; ++i)
+ r.argv[i+1] = string_alloc (a->argv[i], NULL);
+ }
+ return r;
+}
+
char *
argv_term (const char **f)
{
@@ -324,6 +349,22 @@ argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags)
}
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;
@@ -373,7 +414,10 @@ argv_printf_arglist (struct argv *a, const char *format, const unsigned int flag
{
if (!strcmp (term, "%s"))
{
- a->argv[argc++] = string_alloc (va_arg (arglist, char *), NULL);
+ char *s = va_arg (arglist, char *);
+ if (!s)
+ s = "";
+ a->argv[argc++] = string_alloc (s, NULL);
}
else if (!strcmp (term, "%d"))
{
@@ -387,6 +431,41 @@ argv_printf_arglist (struct argv *a, const char *format, const unsigned int flag
openvpn_snprintf (numstr, sizeof (numstr), "%u", va_arg (arglist, unsigned int));
a->argv[argc++] = string_alloc (numstr, NULL);
}
+ 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);
+ a->argv[argc++] = combined;
+ }
+ }
+ else if (!strcmp (term, "%s%s"))
+ {
+ char *s1 = va_arg (arglist, char *);
+ char *s2 = va_arg (arglist, char *);
+ char *combined;
+
+ if (!s1) s1 = "";
+ if (!s2) s2 = "";
+ combined = (char *) malloc (strlen(s1) + strlen(s2) + 1);
+ check_malloc_return (combined);
+ strcpy (combined, s1);
+ strcat (combined, s2);
+ a->argv[argc++] = combined;
+ }
else
ASSERT (0);
free (term);
@@ -399,57 +478,6 @@ argv_printf_arglist (struct argv *a, const char *format, const unsigned int flag
ASSERT (argc == a->argc);
}
-#ifdef ARGV_TEST
-void
-argv_test (void)
-{
- struct gc_arena gc = gc_new ();
- char line[512];
- const char *s;
-
- struct argv a;
- argv_init (&a);
- argv_printf (&a, "this is a %s test of int %d unsigned %u", "FOO", -69, 42);
- s = argv_str (&a, &gc, PA_BRACKET);
- argv_reset (&a);
- printf ("%s\n", s);
-
- argv_init (&a);
- argv_printf (&a, "foo bar %d", 99);
- s = argv_str (&a, &gc, PA_BRACKET);
- argv_reset (&a);
- printf ("%s\n", s);
-
- argv_init (&a);
- s = argv_str (&a, &gc, PA_BRACKET);
- argv_reset (&a);
- printf ("%s\n", s);
-
- argv_init (&a);
- argv_printf (&a, "foo bar %d", 99);
- argv_printf_cat (&a, "bar %d foo", 42);
- argv_printf_cat (&a, "cool %s %d u", "frood", 4);
- s = argv_str (&a, &gc, PA_BRACKET);
- argv_reset (&a);
- printf ("%s\n", s);
-
- 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);
- }
- }
- gc_free (&gc);
-}
-#endif
-
/*
* write a string to the end of a buffer that was
* truncated by buf_printf