client-connect "docc CLIENT-CONNECT"
would fail to work because execve would try to execute
a script called "docc CLIENT-CONNECT" instead of "docc"
with "CLIENT-CONNECT" as the first argument.
This patch fixes the issue, bringing the script argument
semantics back to pre 2.1_rc9 behavior in order to preserve
backward compatibility while still using execve or CreateProcess
to execute the script/executable.
git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@3311 e7ae566f-a301-0410-adde-c780ea21d3b5
| ... | ... |
@@ -235,258 +235,6 @@ int openvpn_snprintf(char *str, size_t size, const char *format, ...) |
| 235 | 235 |
} |
| 236 | 236 |
|
| 237 | 237 |
/* |
| 238 |
- * A printf-like function (that only recognizes a subset of standard printf |
|
| 239 |
- * format operators) that prints arguments to an argv list instead |
|
| 240 |
- * of a standard string. This is used to build up argv arrays for passing |
|
| 241 |
- * to execve. |
|
| 242 |
- */ |
|
| 243 |
- |
|
| 244 |
-void |
|
| 245 |
-argv_init (struct argv *a) |
|
| 246 |
-{
|
|
| 247 |
- a->argc = 0; |
|
| 248 |
- a->argv = NULL; |
|
| 249 |
-} |
|
| 250 |
- |
|
| 251 |
-struct argv |
|
| 252 |
-argv_new (void) |
|
| 253 |
-{
|
|
| 254 |
- struct argv ret; |
|
| 255 |
- argv_init (&ret); |
|
| 256 |
- return ret; |
|
| 257 |
-} |
|
| 258 |
- |
|
| 259 |
-void |
|
| 260 |
-argv_reset (struct argv *a) |
|
| 261 |
-{
|
|
| 262 |
- size_t i; |
|
| 263 |
- for (i = 0; i < a->argc; ++i) |
|
| 264 |
- free (a->argv[i]); |
|
| 265 |
- free (a->argv); |
|
| 266 |
- a->argc = 0; |
|
| 267 |
- a->argv = NULL; |
|
| 268 |
-} |
|
| 269 |
- |
|
| 270 |
-size_t |
|
| 271 |
-argv_argc (const char *format) |
|
| 272 |
-{
|
|
| 273 |
- char *term; |
|
| 274 |
- const char *f = format; |
|
| 275 |
- size_t argc = 0; |
|
| 276 |
- |
|
| 277 |
- while ((term = argv_term (&f)) != NULL) |
|
| 278 |
- {
|
|
| 279 |
- ++argc; |
|
| 280 |
- free (term); |
|
| 281 |
- } |
|
| 282 |
- return argc; |
|
| 283 |
-} |
|
| 284 |
- |
|
| 285 |
-struct argv |
|
| 286 |
-argv_insert_head (const struct argv *a, const char *head) |
|
| 287 |
-{
|
|
| 288 |
- struct argv r; |
|
| 289 |
- size_t i; |
|
| 290 |
- |
|
| 291 |
- r.argc = (a ? a->argc : 0) + 1; |
|
| 292 |
- ALLOC_ARRAY_CLEAR (r.argv, char *, r.argc + 1); |
|
| 293 |
- r.argv[0] = string_alloc (head, NULL); |
|
| 294 |
- if (a) |
|
| 295 |
- {
|
|
| 296 |
- for (i = 0; i < a->argc; ++i) |
|
| 297 |
- r.argv[i+1] = string_alloc (a->argv[i], NULL); |
|
| 298 |
- } |
|
| 299 |
- return r; |
|
| 300 |
-} |
|
| 301 |
- |
|
| 302 |
-char * |
|
| 303 |
-argv_term (const char **f) |
|
| 304 |
-{
|
|
| 305 |
- const char *p = *f; |
|
| 306 |
- const char *term = NULL; |
|
| 307 |
- size_t termlen = 0; |
|
| 308 |
- |
|
| 309 |
- if (*p == '\0') |
|
| 310 |
- return NULL; |
|
| 311 |
- |
|
| 312 |
- while (true) |
|
| 313 |
- {
|
|
| 314 |
- const int c = *p; |
|
| 315 |
- if (c == '\0') |
|
| 316 |
- break; |
|
| 317 |
- if (term) |
|
| 318 |
- {
|
|
| 319 |
- if (!isspace (c)) |
|
| 320 |
- ++termlen; |
|
| 321 |
- else |
|
| 322 |
- break; |
|
| 323 |
- } |
|
| 324 |
- else |
|
| 325 |
- {
|
|
| 326 |
- if (!isspace (c)) |
|
| 327 |
- {
|
|
| 328 |
- term = p; |
|
| 329 |
- termlen = 1; |
|
| 330 |
- } |
|
| 331 |
- } |
|
| 332 |
- ++p; |
|
| 333 |
- } |
|
| 334 |
- *f = p; |
|
| 335 |
- |
|
| 336 |
- if (term) |
|
| 337 |
- {
|
|
| 338 |
- char *ret; |
|
| 339 |
- ASSERT (termlen > 0); |
|
| 340 |
- ret = malloc (termlen + 1); |
|
| 341 |
- check_malloc_return (ret); |
|
| 342 |
- memcpy (ret, term, termlen); |
|
| 343 |
- ret[termlen] = '\0'; |
|
| 344 |
- return ret; |
|
| 345 |
- } |
|
| 346 |
- else |
|
| 347 |
- return NULL; |
|
| 348 |
-} |
|
| 349 |
- |
|
| 350 |
-const char * |
|
| 351 |
-argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags) |
|
| 352 |
-{
|
|
| 353 |
- if (a->argv) |
|
| 354 |
- return print_argv ((const char **)a->argv, gc, flags); |
|
| 355 |
- else |
|
| 356 |
- return ""; |
|
| 357 |
-} |
|
| 358 |
- |
|
| 359 |
-void |
|
| 360 |
-argv_msg (const int msglev, const struct argv *a) |
|
| 361 |
-{
|
|
| 362 |
- struct gc_arena gc = gc_new (); |
|
| 363 |
- msg (msglev, "%s", argv_str (a, &gc, 0)); |
|
| 364 |
- gc_free (&gc); |
|
| 365 |
-} |
|
| 366 |
- |
|
| 367 |
-void |
|
| 368 |
-argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix) |
|
| 369 |
-{
|
|
| 370 |
- struct gc_arena gc = gc_new (); |
|
| 371 |
- msg (msglev, "%s: %s", prefix, argv_str (a, &gc, 0)); |
|
| 372 |
- gc_free (&gc); |
|
| 373 |
-} |
|
| 374 |
- |
|
| 375 |
-void |
|
| 376 |
-argv_printf (struct argv *a, const char *format, ...) |
|
| 377 |
-{
|
|
| 378 |
- va_list arglist; |
|
| 379 |
- va_start (arglist, format); |
|
| 380 |
- argv_printf_arglist (a, format, 0, arglist); |
|
| 381 |
- va_end (arglist); |
|
| 382 |
- } |
|
| 383 |
- |
|
| 384 |
-void |
|
| 385 |
-argv_printf_cat (struct argv *a, const char *format, ...) |
|
| 386 |
-{
|
|
| 387 |
- va_list arglist; |
|
| 388 |
- va_start (arglist, format); |
|
| 389 |
- argv_printf_arglist (a, format, APA_CAT, arglist); |
|
| 390 |
- va_end (arglist); |
|
| 391 |
-} |
|
| 392 |
- |
|
| 393 |
-void |
|
| 394 |
-argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist) |
|
| 395 |
-{
|
|
| 396 |
- char *term; |
|
| 397 |
- const char *f = format; |
|
| 398 |
- size_t argc = 0; |
|
| 399 |
- |
|
| 400 |
- if (flags & APA_CAT) |
|
| 401 |
- {
|
|
| 402 |
- char **old_argv = a->argv; |
|
| 403 |
- size_t i; |
|
| 404 |
- argc = a->argc; |
|
| 405 |
- a->argc += argv_argc (format); |
|
| 406 |
- ALLOC_ARRAY_CLEAR (a->argv, char *, a->argc + 1); |
|
| 407 |
- for (i = 0; i < argc; ++i) |
|
| 408 |
- a->argv[i] = old_argv[i]; |
|
| 409 |
- free (old_argv); |
|
| 410 |
- } |
|
| 411 |
- else |
|
| 412 |
- {
|
|
| 413 |
- argv_reset (a); |
|
| 414 |
- a->argc = argv_argc (format); |
|
| 415 |
- ALLOC_ARRAY_CLEAR (a->argv, char *, a->argc + 1); |
|
| 416 |
- } |
|
| 417 |
- |
|
| 418 |
- while ((term = argv_term (&f)) != NULL) |
|
| 419 |
- {
|
|
| 420 |
- ASSERT (argc < a->argc); |
|
| 421 |
- if (term[0] == '%') |
|
| 422 |
- {
|
|
| 423 |
- if (!strcmp (term, "%s")) |
|
| 424 |
- {
|
|
| 425 |
- char *s = va_arg (arglist, char *); |
|
| 426 |
- if (!s) |
|
| 427 |
- s = ""; |
|
| 428 |
- a->argv[argc++] = string_alloc (s, NULL); |
|
| 429 |
- } |
|
| 430 |
- else if (!strcmp (term, "%d")) |
|
| 431 |
- {
|
|
| 432 |
- char numstr[64]; |
|
| 433 |
- openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int)); |
|
| 434 |
- a->argv[argc++] = string_alloc (numstr, NULL); |
|
| 435 |
- } |
|
| 436 |
- else if (!strcmp (term, "%u")) |
|
| 437 |
- {
|
|
| 438 |
- char numstr[64]; |
|
| 439 |
- openvpn_snprintf (numstr, sizeof (numstr), "%u", va_arg (arglist, unsigned int)); |
|
| 440 |
- a->argv[argc++] = string_alloc (numstr, NULL); |
|
| 441 |
- } |
|
| 442 |
- else if (!strcmp (term, "%s/%d")) |
|
| 443 |
- {
|
|
| 444 |
- char numstr[64]; |
|
| 445 |
- char *s = va_arg (arglist, char *); |
|
| 446 |
- |
|
| 447 |
- if (!s) |
|
| 448 |
- s = ""; |
|
| 449 |
- |
|
| 450 |
- openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int)); |
|
| 451 |
- |
|
| 452 |
- {
|
|
| 453 |
- const size_t len = strlen(s) + strlen(numstr) + 2; |
|
| 454 |
- char *combined = (char *) malloc (len); |
|
| 455 |
- check_malloc_return (combined); |
|
| 456 |
- |
|
| 457 |
- strcpy (combined, s); |
|
| 458 |
- strcat (combined, "/"); |
|
| 459 |
- strcat (combined, numstr); |
|
| 460 |
- a->argv[argc++] = combined; |
|
| 461 |
- } |
|
| 462 |
- } |
|
| 463 |
- else if (!strcmp (term, "%s%s")) |
|
| 464 |
- {
|
|
| 465 |
- char *s1 = va_arg (arglist, char *); |
|
| 466 |
- char *s2 = va_arg (arglist, char *); |
|
| 467 |
- char *combined; |
|
| 468 |
- |
|
| 469 |
- if (!s1) s1 = ""; |
|
| 470 |
- if (!s2) s2 = ""; |
|
| 471 |
- combined = (char *) malloc (strlen(s1) + strlen(s2) + 1); |
|
| 472 |
- check_malloc_return (combined); |
|
| 473 |
- strcpy (combined, s1); |
|
| 474 |
- strcat (combined, s2); |
|
| 475 |
- a->argv[argc++] = combined; |
|
| 476 |
- } |
|
| 477 |
- else |
|
| 478 |
- ASSERT (0); |
|
| 479 |
- free (term); |
|
| 480 |
- } |
|
| 481 |
- else |
|
| 482 |
- {
|
|
| 483 |
- a->argv[argc++] = term; |
|
| 484 |
- } |
|
| 485 |
- } |
|
| 486 |
- ASSERT (argc == a->argc); |
|
| 487 |
-} |
|
| 488 |
- |
|
| 489 |
-/* |
|
| 490 | 238 |
* write a string to the end of a buffer that was |
| 491 | 239 |
* truncated by buf_printf |
| 492 | 240 |
*/ |
| ... | ... |
@@ -60,6 +60,7 @@ struct buffer |
| 60 | 60 |
|
| 61 | 61 |
/* used by argv_x functions */ |
| 62 | 62 |
struct argv {
|
| 63 |
+ size_t capacity; |
|
| 63 | 64 |
size_t argc; |
| 64 | 65 |
char **argv; |
| 65 | 66 |
}; |
| ... | ... |
@@ -293,37 +294,6 @@ int openvpn_snprintf(char *str, size_t size, const char *format, ...) |
| 293 | 293 |
; |
| 294 | 294 |
|
| 295 | 295 |
/* |
| 296 |
- * A printf-like function (that only recognizes a subset of standard printf |
|
| 297 |
- * format operators) that prints arguments to an argv list instead |
|
| 298 |
- * of a standard string. This is used to build up argv arrays for passing |
|
| 299 |
- * to execve. |
|
| 300 |
- */ |
|
| 301 |
-void argv_init (struct argv *a); |
|
| 302 |
-struct argv argv_new (void); |
|
| 303 |
-void argv_reset (struct argv *a); |
|
| 304 |
-size_t argv_argc (const char *format); |
|
| 305 |
-char *argv_term (const char **f); |
|
| 306 |
-const char *argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags); |
|
| 307 |
-struct argv argv_insert_head (const struct argv *a, const char *head); |
|
| 308 |
-void argv_msg (const int msglev, const struct argv *a); |
|
| 309 |
-void argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix); |
|
| 310 |
- |
|
| 311 |
-#define APA_CAT (1<<0) /* concatentate onto existing struct argv list */ |
|
| 312 |
-void argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist); |
|
| 313 |
- |
|
| 314 |
-void argv_printf (struct argv *a, const char *format, ...) |
|
| 315 |
-#ifdef __GNUC__ |
|
| 316 |
- __attribute__ ((format (printf, 2, 3))) |
|
| 317 |
-#endif |
|
| 318 |
- ; |
|
| 319 |
- |
|
| 320 |
-void argv_printf_cat (struct argv *a, const char *format, ...) |
|
| 321 |
-#ifdef __GNUC__ |
|
| 322 |
- __attribute__ ((format (printf, 2, 3))) |
|
| 323 |
-#endif |
|
| 324 |
- ; |
|
| 325 |
- |
|
| 326 |
-/* |
|
| 327 | 296 |
* remove/add trailing characters |
| 328 | 297 |
*/ |
| 329 | 298 |
|
| ... | ... |
@@ -75,6 +75,7 @@ |
| 75 | 75 |
#define D_CLOSE LOGLEV(2, 22, 0) /* show socket and TUN/TAP close */ |
| 76 | 76 |
#define D_SHOW_OCC_HASH LOGLEV(2, 23, 0) /* show MD5 hash of option compatibility string */ |
| 77 | 77 |
#define D_PROXY LOGLEV(2, 24, 0) /* show http proxy control packets */ |
| 78 |
+#define D_ARGV LOGLEV(2, 25, 0) /* show struct argv errors */ |
|
| 78 | 79 |
|
| 79 | 80 |
#define D_TLS_DEBUG_LOW LOGLEV(3, 20, 0) /* low frequency info from tls_session routines */ |
| 80 | 81 |
#define D_GREMLIN LOGLEV(3, 30, 0) /* show simulated outage info from gremlin module */ |
| ... | ... |
@@ -923,7 +923,7 @@ do_route (const struct options *options, |
| 923 | 923 |
{
|
| 924 | 924 |
struct argv argv = argv_new (); |
| 925 | 925 |
setenv_str (es, "script_type", "route-up"); |
| 926 |
- argv_printf (&argv, "%s", options->route_script); |
|
| 926 |
+ argv_printf (&argv, "%sc", options->route_script); |
|
| 927 | 927 |
openvpn_execve_check (&argv, es, S_SCRIPT, "Route script failed"); |
| 928 | 928 |
argv_reset (&argv); |
| 929 | 929 |
} |
| ... | ... |
@@ -220,7 +220,7 @@ run_up_down (const char *command, |
| 220 | 220 |
ASSERT (arg); |
| 221 | 221 |
setenv_str (es, "script_type", script_type); |
| 222 | 222 |
argv_printf (&argv, |
| 223 |
- "%s %s %d %d %s %s %s", |
|
| 223 |
+ "%sc %s %d %d %s %s %s", |
|
| 224 | 224 |
command, |
| 225 | 225 |
arg, |
| 226 | 226 |
tun_mtu, link_mtu, |
| ... | ... |
@@ -1190,24 +1190,6 @@ absolute_pathname (const char *pathname) |
| 1190 | 1190 |
return false; |
| 1191 | 1191 |
} |
| 1192 | 1192 |
|
| 1193 |
-/* |
|
| 1194 |
- * Return the next largest power of 2 |
|
| 1195 |
- * or u if u is a power of 2. |
|
| 1196 |
- */ |
|
| 1197 |
-unsigned int |
|
| 1198 |
-adjust_power_of_2 (unsigned int u) |
|
| 1199 |
-{
|
|
| 1200 |
- unsigned int ret = 1; |
|
| 1201 |
- |
|
| 1202 |
- while (ret < u) |
|
| 1203 |
- {
|
|
| 1204 |
- ret <<= 1; |
|
| 1205 |
- ASSERT (ret > 0); |
|
| 1206 |
- } |
|
| 1207 |
- |
|
| 1208 |
- return ret; |
|
| 1209 |
-} |
|
| 1210 |
- |
|
| 1211 | 1193 |
#ifdef HAVE_GETPASS |
| 1212 | 1194 |
|
| 1213 | 1195 |
static FILE * |
| ... | ... |
@@ -1666,56 +1648,309 @@ openvpn_sleep (const int n) |
| 1666 | 1666 |
sleep (n); |
| 1667 | 1667 |
} |
| 1668 | 1668 |
|
| 1669 |
-#if 0 |
|
| 1670 | 1669 |
/* |
| 1671 |
- * Configure PATH. On Windows, sometimes PATH is not set correctly |
|
| 1672 |
- * by default. |
|
| 1670 |
+ * Return the next largest power of 2 |
|
| 1671 |
+ * or u if u is a power of 2. |
|
| 1673 | 1672 |
*/ |
| 1673 |
+size_t |
|
| 1674 |
+adjust_power_of_2 (size_t u) |
|
| 1675 |
+{
|
|
| 1676 |
+ size_t ret = 1; |
|
| 1677 |
+ |
|
| 1678 |
+ while (ret < u) |
|
| 1679 |
+ {
|
|
| 1680 |
+ ret <<= 1; |
|
| 1681 |
+ ASSERT (ret > 0); |
|
| 1682 |
+ } |
|
| 1683 |
+ |
|
| 1684 |
+ return ret; |
|
| 1685 |
+} |
|
| 1686 |
+ |
|
| 1687 |
+/* |
|
| 1688 |
+ * A printf-like function (that only recognizes a subset of standard printf |
|
| 1689 |
+ * format operators) that prints arguments to an argv list instead |
|
| 1690 |
+ * of a standard string. This is used to build up argv arrays for passing |
|
| 1691 |
+ * to execve. |
|
| 1692 |
+ */ |
|
| 1693 |
+ |
|
| 1674 | 1694 |
void |
| 1675 |
-configure_path (void) |
|
| 1695 |
+argv_init (struct argv *a) |
|
| 1676 | 1696 |
{
|
| 1677 |
-#ifdef WIN32 |
|
| 1678 |
- FILE *fp; |
|
| 1679 |
- fp = fopen ("c:\\windows\\system32\\route.exe", "rb");
|
|
| 1680 |
- if (fp) |
|
| 1697 |
+ a->capacity = 0; |
|
| 1698 |
+ a->argc = 0; |
|
| 1699 |
+ a->argv = NULL; |
|
| 1700 |
+} |
|
| 1701 |
+ |
|
| 1702 |
+struct argv |
|
| 1703 |
+argv_new (void) |
|
| 1704 |
+{
|
|
| 1705 |
+ struct argv ret; |
|
| 1706 |
+ argv_init (&ret); |
|
| 1707 |
+ return ret; |
|
| 1708 |
+} |
|
| 1709 |
+ |
|
| 1710 |
+void |
|
| 1711 |
+argv_reset (struct argv *a) |
|
| 1712 |
+{
|
|
| 1713 |
+ size_t i; |
|
| 1714 |
+ for (i = 0; i < a->argc; ++i) |
|
| 1715 |
+ free (a->argv[i]); |
|
| 1716 |
+ free (a->argv); |
|
| 1717 |
+ argv_init (a); |
|
| 1718 |
+} |
|
| 1719 |
+ |
|
| 1720 |
+static void |
|
| 1721 |
+argv_extend (struct argv *a, const size_t newcap) |
|
| 1722 |
+{
|
|
| 1723 |
+ if (newcap > a->capacity) |
|
| 1681 | 1724 |
{
|
| 1682 |
- const int bufsiz = 4096; |
|
| 1683 |
- struct gc_arena gc = gc_new (); |
|
| 1684 |
- struct buffer oldpath = alloc_buf_gc (bufsiz, &gc); |
|
| 1685 |
- struct buffer newpath = alloc_buf_gc (bufsiz, &gc); |
|
| 1686 |
- const char* delim = ";"; |
|
| 1687 |
- DWORD status; |
|
| 1688 |
- fclose (fp); |
|
| 1689 |
- status = GetEnvironmentVariable ("PATH", BPTR(&oldpath), (DWORD)BCAP(&oldpath));
|
|
| 1690 |
-#if 0 |
|
| 1691 |
- status = 0; |
|
| 1692 |
-#endif |
|
| 1693 |
- if (!status) |
|
| 1725 |
+ char **newargv; |
|
| 1726 |
+ size_t i; |
|
| 1727 |
+ ALLOC_ARRAY_CLEAR (newargv, char *, newcap); |
|
| 1728 |
+ for (i = 0; i < a->argc; ++i) |
|
| 1729 |
+ newargv[i] = a->argv[i]; |
|
| 1730 |
+ free (a->argv); |
|
| 1731 |
+ a->argv = newargv; |
|
| 1732 |
+ a->capacity = newcap; |
|
| 1733 |
+ } |
|
| 1734 |
+} |
|
| 1735 |
+ |
|
| 1736 |
+static void |
|
| 1737 |
+argv_grow (struct argv *a, const size_t add) |
|
| 1738 |
+{
|
|
| 1739 |
+ const size_t newargc = a->argc + add + 1; |
|
| 1740 |
+ ASSERT (newargc > a->argc); |
|
| 1741 |
+ argv_extend (a, adjust_power_of_2 (newargc)); |
|
| 1742 |
+} |
|
| 1743 |
+ |
|
| 1744 |
+static void |
|
| 1745 |
+argv_append (struct argv *a, char *str) /* str must have been malloced or be NULL */ |
|
| 1746 |
+{
|
|
| 1747 |
+ argv_grow (a, 1); |
|
| 1748 |
+ a->argv[a->argc++] = str; |
|
| 1749 |
+} |
|
| 1750 |
+ |
|
| 1751 |
+struct argv |
|
| 1752 |
+argv_clone (const struct argv *a, const size_t headroom) |
|
| 1753 |
+{
|
|
| 1754 |
+ struct argv r; |
|
| 1755 |
+ size_t i; |
|
| 1756 |
+ |
|
| 1757 |
+ argv_init (&r); |
|
| 1758 |
+ for (i = 0; i < headroom; ++i) |
|
| 1759 |
+ argv_append (&r, NULL); |
|
| 1760 |
+ if (a) |
|
| 1761 |
+ {
|
|
| 1762 |
+ for (i = 0; i < a->argc; ++i) |
|
| 1763 |
+ argv_append (&r, string_alloc (a->argv[i], NULL)); |
|
| 1764 |
+ } |
|
| 1765 |
+ return r; |
|
| 1766 |
+} |
|
| 1767 |
+ |
|
| 1768 |
+struct argv |
|
| 1769 |
+argv_insert_head (const struct argv *a, const char *head) |
|
| 1770 |
+{
|
|
| 1771 |
+ struct argv r; |
|
| 1772 |
+ |
|
| 1773 |
+ r = argv_clone (a, 1); |
|
| 1774 |
+ r.argv[0] = string_alloc (head, NULL); |
|
| 1775 |
+ |
|
| 1776 |
+ return r; |
|
| 1777 |
+} |
|
| 1778 |
+ |
|
| 1779 |
+char * |
|
| 1780 |
+argv_term (const char **f) |
|
| 1781 |
+{
|
|
| 1782 |
+ const char *p = *f; |
|
| 1783 |
+ const char *term = NULL; |
|
| 1784 |
+ size_t termlen = 0; |
|
| 1785 |
+ |
|
| 1786 |
+ if (*p == '\0') |
|
| 1787 |
+ return NULL; |
|
| 1788 |
+ |
|
| 1789 |
+ while (true) |
|
| 1790 |
+ {
|
|
| 1791 |
+ const int c = *p; |
|
| 1792 |
+ if (c == '\0') |
|
| 1793 |
+ break; |
|
| 1794 |
+ if (term) |
|
| 1694 | 1795 |
{
|
| 1695 |
- *BPTR(&oldpath) = '\0'; |
|
| 1696 |
- delim = ""; |
|
| 1796 |
+ if (!isspace (c)) |
|
| 1797 |
+ ++termlen; |
|
| 1798 |
+ else |
|
| 1799 |
+ break; |
|
| 1697 | 1800 |
} |
| 1698 |
- buf_printf (&newpath, "C:\\WINDOWS\\System32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem%s%s", |
|
| 1699 |
- delim, |
|
| 1700 |
- BSTR(&oldpath)); |
|
| 1701 |
- SetEnvironmentVariable ("PATH", BSTR(&newpath));
|
|
| 1702 |
-#if 0 |
|
| 1703 |
- status = GetEnvironmentVariable ("PATH", BPTR(&oldpath), (DWORD)BCAP(&oldpath));
|
|
| 1704 |
- if (status > 0) |
|
| 1705 |
- printf ("PATH: %s\n", BSTR(&oldpath));
|
|
| 1706 |
-#endif |
|
| 1707 |
- gc_free (&gc); |
|
| 1801 |
+ else |
|
| 1802 |
+ {
|
|
| 1803 |
+ if (!isspace (c)) |
|
| 1804 |
+ {
|
|
| 1805 |
+ term = p; |
|
| 1806 |
+ termlen = 1; |
|
| 1807 |
+ } |
|
| 1808 |
+ } |
|
| 1809 |
+ ++p; |
|
| 1708 | 1810 |
} |
| 1709 |
-#endif |
|
| 1811 |
+ *f = p; |
|
| 1812 |
+ |
|
| 1813 |
+ if (term) |
|
| 1814 |
+ {
|
|
| 1815 |
+ char *ret; |
|
| 1816 |
+ ASSERT (termlen > 0); |
|
| 1817 |
+ ret = malloc (termlen + 1); |
|
| 1818 |
+ check_malloc_return (ret); |
|
| 1819 |
+ memcpy (ret, term, termlen); |
|
| 1820 |
+ ret[termlen] = '\0'; |
|
| 1821 |
+ return ret; |
|
| 1822 |
+ } |
|
| 1823 |
+ else |
|
| 1824 |
+ return NULL; |
|
| 1825 |
+} |
|
| 1826 |
+ |
|
| 1827 |
+const char * |
|
| 1828 |
+argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags) |
|
| 1829 |
+{
|
|
| 1830 |
+ if (a->argv) |
|
| 1831 |
+ return print_argv ((const char **)a->argv, gc, flags); |
|
| 1832 |
+ else |
|
| 1833 |
+ return ""; |
|
| 1834 |
+} |
|
| 1835 |
+ |
|
| 1836 |
+void |
|
| 1837 |
+argv_msg (const int msglev, const struct argv *a) |
|
| 1838 |
+{
|
|
| 1839 |
+ struct gc_arena gc = gc_new (); |
|
| 1840 |
+ msg (msglev, "%s", argv_str (a, &gc, 0)); |
|
| 1841 |
+ gc_free (&gc); |
|
| 1842 |
+} |
|
| 1843 |
+ |
|
| 1844 |
+void |
|
| 1845 |
+argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix) |
|
| 1846 |
+{
|
|
| 1847 |
+ struct gc_arena gc = gc_new (); |
|
| 1848 |
+ msg (msglev, "%s: %s", prefix, argv_str (a, &gc, 0)); |
|
| 1849 |
+ gc_free (&gc); |
|
| 1850 |
+} |
|
| 1851 |
+ |
|
| 1852 |
+void |
|
| 1853 |
+argv_printf (struct argv *a, const char *format, ...) |
|
| 1854 |
+{
|
|
| 1855 |
+ va_list arglist; |
|
| 1856 |
+ va_start (arglist, format); |
|
| 1857 |
+ argv_printf_arglist (a, format, 0, arglist); |
|
| 1858 |
+ va_end (arglist); |
|
| 1859 |
+ } |
|
| 1860 |
+ |
|
| 1861 |
+void |
|
| 1862 |
+argv_printf_cat (struct argv *a, const char *format, ...) |
|
| 1863 |
+{
|
|
| 1864 |
+ va_list arglist; |
|
| 1865 |
+ va_start (arglist, format); |
|
| 1866 |
+ argv_printf_arglist (a, format, APA_CAT, arglist); |
|
| 1867 |
+ va_end (arglist); |
|
| 1868 |
+} |
|
| 1869 |
+ |
|
| 1870 |
+void |
|
| 1871 |
+argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist) |
|
| 1872 |
+{
|
|
| 1873 |
+ struct gc_arena gc = gc_new (); |
|
| 1874 |
+ char *term; |
|
| 1875 |
+ const char *f = format; |
|
| 1876 |
+ |
|
| 1877 |
+ if (!(flags & APA_CAT)) |
|
| 1878 |
+ argv_reset (a); |
|
| 1879 |
+ argv_extend (a, 1); /* ensure trailing NULL */ |
|
| 1880 |
+ |
|
| 1881 |
+ while ((term = argv_term (&f)) != NULL) |
|
| 1882 |
+ {
|
|
| 1883 |
+ if (term[0] == '%') |
|
| 1884 |
+ {
|
|
| 1885 |
+ if (!strcmp (term, "%s")) |
|
| 1886 |
+ {
|
|
| 1887 |
+ char *s = va_arg (arglist, char *); |
|
| 1888 |
+ if (!s) |
|
| 1889 |
+ s = ""; |
|
| 1890 |
+ argv_append (a, string_alloc (s, NULL)); |
|
| 1891 |
+ } |
|
| 1892 |
+ else if (!strcmp (term, "%sc")) |
|
| 1893 |
+ {
|
|
| 1894 |
+ char *s = va_arg (arglist, char *); |
|
| 1895 |
+ if (s) |
|
| 1896 |
+ {
|
|
| 1897 |
+ int nparms; |
|
| 1898 |
+ char *parms[MAX_PARMS+1]; |
|
| 1899 |
+ int i; |
|
| 1900 |
+ |
|
| 1901 |
+ nparms = parse_line (s, parms, MAX_PARMS, "SCRIPT-ARGV", 0, M_FATAL, &gc); |
|
| 1902 |
+ for (i = 0; i < nparms; ++i) |
|
| 1903 |
+ argv_append (a, string_alloc (parms[i], NULL)); |
|
| 1904 |
+ } |
|
| 1905 |
+ else |
|
| 1906 |
+ argv_append (a, string_alloc ("", NULL));
|
|
| 1907 |
+ } |
|
| 1908 |
+ else if (!strcmp (term, "%d")) |
|
| 1909 |
+ {
|
|
| 1910 |
+ char numstr[64]; |
|
| 1911 |
+ openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int)); |
|
| 1912 |
+ argv_append (a, string_alloc (numstr, NULL)); |
|
| 1913 |
+ } |
|
| 1914 |
+ else if (!strcmp (term, "%u")) |
|
| 1915 |
+ {
|
|
| 1916 |
+ char numstr[64]; |
|
| 1917 |
+ openvpn_snprintf (numstr, sizeof (numstr), "%u", va_arg (arglist, unsigned int)); |
|
| 1918 |
+ argv_append (a, string_alloc (numstr, NULL)); |
|
| 1919 |
+ } |
|
| 1920 |
+ else if (!strcmp (term, "%s/%d")) |
|
| 1921 |
+ {
|
|
| 1922 |
+ char numstr[64]; |
|
| 1923 |
+ char *s = va_arg (arglist, char *); |
|
| 1924 |
+ |
|
| 1925 |
+ if (!s) |
|
| 1926 |
+ s = ""; |
|
| 1927 |
+ |
|
| 1928 |
+ openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int)); |
|
| 1929 |
+ |
|
| 1930 |
+ {
|
|
| 1931 |
+ const size_t len = strlen(s) + strlen(numstr) + 2; |
|
| 1932 |
+ char *combined = (char *) malloc (len); |
|
| 1933 |
+ check_malloc_return (combined); |
|
| 1934 |
+ |
|
| 1935 |
+ strcpy (combined, s); |
|
| 1936 |
+ strcat (combined, "/"); |
|
| 1937 |
+ strcat (combined, numstr); |
|
| 1938 |
+ argv_append (a, combined); |
|
| 1939 |
+ } |
|
| 1940 |
+ } |
|
| 1941 |
+ else if (!strcmp (term, "%s%s")) |
|
| 1942 |
+ {
|
|
| 1943 |
+ char *s1 = va_arg (arglist, char *); |
|
| 1944 |
+ char *s2 = va_arg (arglist, char *); |
|
| 1945 |
+ char *combined; |
|
| 1946 |
+ |
|
| 1947 |
+ if (!s1) s1 = ""; |
|
| 1948 |
+ if (!s2) s2 = ""; |
|
| 1949 |
+ combined = (char *) malloc (strlen(s1) + strlen(s2) + 1); |
|
| 1950 |
+ check_malloc_return (combined); |
|
| 1951 |
+ strcpy (combined, s1); |
|
| 1952 |
+ strcat (combined, s2); |
|
| 1953 |
+ argv_append (a, combined); |
|
| 1954 |
+ } |
|
| 1955 |
+ else |
|
| 1956 |
+ ASSERT (0); |
|
| 1957 |
+ free (term); |
|
| 1958 |
+ } |
|
| 1959 |
+ else |
|
| 1960 |
+ {
|
|
| 1961 |
+ argv_append (a, term); |
|
| 1962 |
+ } |
|
| 1963 |
+ } |
|
| 1964 |
+ gc_free (&gc); |
|
| 1710 | 1965 |
} |
| 1711 |
-#endif |
|
| 1712 | 1966 |
|
| 1713 | 1967 |
#ifdef ARGV_TEST |
| 1714 | 1968 |
void |
| 1715 | 1969 |
argv_test (void) |
| 1716 | 1970 |
{
|
| 1717 | 1971 |
struct gc_arena gc = gc_new (); |
| 1718 |
- char line[512]; |
|
| 1719 | 1972 |
const char *s; |
| 1720 | 1973 |
|
| 1721 | 1974 |
struct argv a; |
| ... | ... |
@@ -1729,7 +1964,7 @@ argv_test (void) |
| 1729 | 1729 |
#endif |
| 1730 | 1730 |
|
| 1731 | 1731 |
argv_msg_prefix (M_INFO, &a, "ARGV"); |
| 1732 |
- openvpn_execve_check (&a, NULL, 0, "command failed"); |
|
| 1732 |
+ //openvpn_execve_check (&a, NULL, 0, "command failed"); |
|
| 1733 | 1733 |
|
| 1734 | 1734 |
argv_printf (&a, "this is a %s test of int %d unsigned %u", "FOO", -69, 42); |
| 1735 | 1735 |
s = argv_str (&a, &gc, PA_BRACKET); |
| ... | ... |
@@ -1742,7 +1977,7 @@ argv_test (void) |
| 1742 | 1742 |
printf ("%s\n", s);
|
| 1743 | 1743 |
} |
| 1744 | 1744 |
|
| 1745 |
- argv_printf (&a, "foo bar %d", 99); |
|
| 1745 |
+ argv_printf (&a, "%sc foo bar %d", "\"multi term\" command following \\\"spaces", 99); |
|
| 1746 | 1746 |
s = argv_str (&a, &gc, PA_BRACKET); |
| 1747 | 1747 |
argv_reset (&a); |
| 1748 | 1748 |
printf ("%s\n", s);
|
| ... | ... |
@@ -1752,25 +1987,28 @@ argv_test (void) |
| 1752 | 1752 |
printf ("%s\n", s);
|
| 1753 | 1753 |
|
| 1754 | 1754 |
argv_printf (&a, "foo bar %d", 99); |
| 1755 |
- argv_printf_cat (&a, "bar %d foo", 42); |
|
| 1755 |
+ argv_printf_cat (&a, "bar %d foo %sc", 42, "nonesuch"); |
|
| 1756 | 1756 |
argv_printf_cat (&a, "cool %s %d u %s/%d end", "frood", 4, "hello", 7); |
| 1757 | 1757 |
s = argv_str (&a, &gc, PA_BRACKET); |
| 1758 | 1758 |
printf ("%s\n", s);
|
| 1759 | 1759 |
|
| 1760 | 1760 |
#if 0 |
| 1761 |
- while (fgets (line, sizeof(line), stdin) != NULL) |
|
| 1762 |
- {
|
|
| 1763 |
- char *term; |
|
| 1764 |
- const char *f = line; |
|
| 1765 |
- int i = 0; |
|
| 1766 |
- |
|
| 1767 |
- while ((term = argv_term (&f)) != NULL) |
|
| 1768 |
- {
|
|
| 1769 |
- printf ("[%d] '%s'\n", i, term);
|
|
| 1770 |
- ++i; |
|
| 1771 |
- free (term); |
|
| 1772 |
- } |
|
| 1773 |
- } |
|
| 1761 |
+ {
|
|
| 1762 |
+ char line[512]; |
|
| 1763 |
+ while (fgets (line, sizeof(line), stdin) != NULL) |
|
| 1764 |
+ {
|
|
| 1765 |
+ char *term; |
|
| 1766 |
+ const char *f = line; |
|
| 1767 |
+ int i = 0; |
|
| 1768 |
+ |
|
| 1769 |
+ while ((term = argv_term (&f)) != NULL) |
|
| 1770 |
+ {
|
|
| 1771 |
+ printf ("[%d] '%s'\n", i, term);
|
|
| 1772 |
+ ++i; |
|
| 1773 |
+ free (term); |
|
| 1774 |
+ } |
|
| 1775 |
+ } |
|
| 1776 |
+ } |
|
| 1774 | 1777 |
#endif |
| 1775 | 1778 |
|
| 1776 | 1779 |
argv_reset (&a); |
| ... | ... |
@@ -221,9 +221,6 @@ bool delete_file (const char *filename); |
| 221 | 221 |
/* return true if pathname is absolute */ |
| 222 | 222 |
bool absolute_pathname (const char *pathname); |
| 223 | 223 |
|
| 224 |
-/* return the next largest power of 2 */ |
|
| 225 |
-unsigned int adjust_power_of_2 (unsigned int u); |
|
| 226 |
- |
|
| 227 | 224 |
/* |
| 228 | 225 |
* Get and store a username/password |
| 229 | 226 |
*/ |
| ... | ... |
@@ -300,4 +297,37 @@ extern const char *iproute_path; |
| 300 | 300 |
#define SSEC_PW_ENV 3 /* allow calling of built-in programs and user-defined scripts that may receive a password as an environmental variable */ |
| 301 | 301 |
extern int script_security; /* GLOBAL */ |
| 302 | 302 |
|
| 303 |
+/* return the next largest power of 2 */ |
|
| 304 |
+size_t adjust_power_of_2 (size_t u); |
|
| 305 |
+ |
|
| 306 |
+/* |
|
| 307 |
+ * A printf-like function (that only recognizes a subset of standard printf |
|
| 308 |
+ * format operators) that prints arguments to an argv list instead |
|
| 309 |
+ * of a standard string. This is used to build up argv arrays for passing |
|
| 310 |
+ * to execve. |
|
| 311 |
+ */ |
|
| 312 |
+void argv_init (struct argv *a); |
|
| 313 |
+struct argv argv_new (void); |
|
| 314 |
+void argv_reset (struct argv *a); |
|
| 315 |
+char *argv_term (const char **f); |
|
| 316 |
+const char *argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags); |
|
| 317 |
+struct argv argv_insert_head (const struct argv *a, const char *head); |
|
| 318 |
+void argv_msg (const int msglev, const struct argv *a); |
|
| 319 |
+void argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix); |
|
| 320 |
+ |
|
| 321 |
+#define APA_CAT (1<<0) /* concatentate onto existing struct argv list */ |
|
| 322 |
+void argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist); |
|
| 323 |
+ |
|
| 324 |
+void argv_printf (struct argv *a, const char *format, ...) |
|
| 325 |
+#ifdef __GNUC__ |
|
| 326 |
+ __attribute__ ((format (printf, 2, 3))) |
|
| 327 |
+#endif |
|
| 328 |
+ ; |
|
| 329 |
+ |
|
| 330 |
+void argv_printf_cat (struct argv *a, const char *format, ...) |
|
| 331 |
+#ifdef __GNUC__ |
|
| 332 |
+ __attribute__ ((format (printf, 2, 3))) |
|
| 333 |
+#endif |
|
| 334 |
+ ; |
|
| 335 |
+ |
|
| 303 | 336 |
#endif |
| ... | ... |
@@ -103,7 +103,7 @@ learn_address_script (const struct multi_context *m, |
| 103 | 103 |
{
|
| 104 | 104 |
struct argv argv = argv_new (); |
| 105 | 105 |
setenv_str (es, "script_type", "learn-address"); |
| 106 |
- argv_printf (&argv, "%s %s %s", |
|
| 106 |
+ argv_printf (&argv, "%sc %s %s", |
|
| 107 | 107 |
m->top.options.learn_address_script, |
| 108 | 108 |
op, |
| 109 | 109 |
mroute_addr_print (addr, &gc)); |
| ... | ... |
@@ -473,7 +473,7 @@ multi_client_disconnect_script (struct multi_context *m, |
| 473 | 473 |
{
|
| 474 | 474 |
struct argv argv = argv_new (); |
| 475 | 475 |
setenv_str (mi->context.c2.es, "script_type", "client-disconnect"); |
| 476 |
- argv_printf (&argv, "%s", mi->context.options.client_disconnect_script); |
|
| 476 |
+ argv_printf (&argv, "%sc", mi->context.options.client_disconnect_script); |
|
| 477 | 477 |
openvpn_execve_check (&argv, mi->context.c2.es, S_SCRIPT, "client-disconnect command failed"); |
| 478 | 478 |
argv_reset (&argv); |
| 479 | 479 |
} |
| ... | ... |
@@ -1568,7 +1568,7 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi |
| 1568 | 1568 |
|
| 1569 | 1569 |
delete_file (dc_file); |
| 1570 | 1570 |
|
| 1571 |
- argv_printf (&argv, "%s %s", |
|
| 1571 |
+ argv_printf (&argv, "%sc %s", |
|
| 1572 | 1572 |
mi->context.options.client_connect_script, |
| 1573 | 1573 |
dc_file); |
| 1574 | 1574 |
|
| ... | ... |
@@ -1539,7 +1539,7 @@ ipchange_fmt (const bool include_cmd, struct argv *argv, const struct link_socke |
| 1539 | 1539 |
const char *ip = print_sockaddr_ex (&info->lsa->actual.dest, NULL, 0, gc); |
| 1540 | 1540 |
const char *port = print_sockaddr_ex (&info->lsa->actual.dest, NULL, PS_DONT_SHOW_ADDR|PS_SHOW_PORT, gc); |
| 1541 | 1541 |
if (include_cmd) |
| 1542 |
- argv_printf (argv, "%s %s %s", |
|
| 1542 |
+ argv_printf (argv, "%sc %s %s", |
|
| 1543 | 1543 |
info->ipchange_command, |
| 1544 | 1544 |
ip, |
| 1545 | 1545 |
port); |
| ... | ... |
@@ -718,7 +718,7 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx) |
| 718 | 718 |
|
| 719 | 719 |
setenv_str (opt->es, "script_type", "tls-verify"); |
| 720 | 720 |
|
| 721 |
- argv_printf (&argv, "%s %d %s", |
|
| 721 |
+ argv_printf (&argv, "%sc %d %s", |
|
| 722 | 722 |
opt->verify_command, |
| 723 | 723 |
ctx->error_depth, |
| 724 | 724 |
subject); |
| ... | ... |
@@ -2937,7 +2937,7 @@ verify_user_pass_script (struct tls_session *session, const struct user_pass *up |
| 2937 | 2937 |
setenv_untrusted (session); |
| 2938 | 2938 |
|
| 2939 | 2939 |
/* format command line */ |
| 2940 |
- argv_printf (&argv, "%s %s", session->opt->auth_user_pass_verify_script, tmp_file); |
|
| 2940 |
+ argv_printf (&argv, "%sc %s", session->opt->auth_user_pass_verify_script, tmp_file); |
|
| 2941 | 2941 |
|
| 2942 | 2942 |
/* call command */ |
| 2943 | 2943 |
retval = openvpn_execve (&argv, session->opt->es, S_SCRIPT); |