[PATCH v1] win32: quote arguments that cmd.exe would reinterpret
Gert Doering <[email protected]>
| Newsgroups | gmane.network.openvpn.devel |
|---|---|
| Message-ID | <[email protected]> |
From: Lev Stipakov <[email protected]> wide_cmd_line() only quoted arguments containing a space, so & | < > ^ % ( ) and ! were passed unquoted. CreateProcess() runs .bat and .cmd files through cmd.exe, which parses the command line again, so a certificate subject passed to --tls-verify could start a second command (CERT/CC VU#123335). Quote on those characters too. Double quotes are already replaced with '_', so nothing else needs escaping. The delimiters , ; and = are left out: cmd.exe uses them to separate %1..%9 but cannot run anything with them, and quoting them would change what existing scripts receive. GitHub: OpenVPN/openvpn-private-issues#159 Reported-By: Clouditera Security; Z.ai Security; NSFOCUS <[email protected]> CVE: 2026-84256 Change-Id: I68429deb39c0bae335d46a4170973a14c644ccf9 Signed-off-by: Lev Stipakov <[email protected]> Acked-by: Heiko Hund <[email protected]> Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1891 --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1891 This mail reflects revision 1 of this Change. Acked-by according to Gerrit (reflected above): Heiko Hund <[email protected]> diff --git a/src/openvpn/win32.c b/src/openvpn/win32.c index 44b010d..d527160 100644 --- a/src/openvpn/win32.c +++ b/src/openvpn/win32.c @@ -936,6 +936,22 @@ } } +/* special to cmd.exe, which CreateProcess() uses to run .bat/.cmd (VU#123335) */ +#define CMD_QUOTE_TRIGGERS " &|<>^%()!" + +static bool +argv_element_needs_quotes(const char *str) +{ + for (const char *c = str; *c != '\0'; ++c) + { + if (strchr(CMD_QUOTE_TRIGGERS, *c) != NULL) + { + return true; + } + } + return false; +} + static WCHAR * wide_cmd_line(const struct argv *a, struct gc_arena *gc) { @@ -974,13 +990,13 @@ { buf_printf(&buf, " "); } - if (string_class(work, CC_ANY, CC_SPACE)) + if (argv_element_needs_quotes(work)) { - buf_printf(&buf, "%s", work); + buf_printf(&buf, "\"%s\"", work); } else { - buf_printf(&buf, "\"%s\"", work); + buf_printf(&buf, "%s", work); } }