I think this is not possible without an external script file.
The first thing to realize is that in OpenSSH, the command specified for Match Exec
needs to be enclosed in double quotes (in the config file), since the argument to Exec
is matched using strdelim
:
readconf.c::match_cfg_line
/* All other criteria require an argument */
if ((arg = strdelim(&cp)) == NULL ||
*arg == '\0' || *arg == '#') {
error("Missing Match criteria for %s", attrib);
result = -1;
goto out;
}
and strdelim
only accepts double quotes as delimiters:
misc.c::strdelim_internal
#define QUOTE "\""
/* return next token in configuration line */
static char *
strdelim_internal(char **s, int split_equals)
{
char *old;
int wspace = 0;
if (*s == NULL)
return NULL;
old = *s;
*s = strpbrk(*s,
split_equals ? WHITESPACE QUOTE "=" : WHITESPACE QUOTE);
if (*s == NULL)
return (old);
if (*s[0] == '\"') {
memmove(*s, *s + 1, strlen(*s)); /* move nul too */
/* Find matching quote */
if ((*s = strpbrk(*s, QUOTE)) == NULL) {
return (NULL); /* no matching quote */
} else {
*s[0] = '\0';
*s += strspn(*s + 1, WHITESPACE) + 1;
return (old);
}
}
// ...
So, only double quotes can be used to delimit the command.
Then, the second thing to realize is that in OpenSSH for Windows, the command used in the Exec
directive is executed using system
:
readconf.c::execute_in_shell
/*
* Execute a command in a shell.
* Return its exit status or -1 on abnormal exit.
*/
static int
execute_in_shell(const char *cmd)
{
char *shell;
pid_t pid;
int status;
#ifdef WINDOWS
return system(cmd);
#else
and thus it is executed in cmd.exe
(see https://learn.microsoft.com/en-us/cpp/c-language/system-function?view=msvc-170). In cmd.exe
, you need to use double quotes to enclose arguments, single quotes have no special meaning.
The problem is that there is no way in OpenSSH to escape the inner double quotes.
To go back to your examples:
# This gives error ${CMDVAR} is not recognized
"powershell -command ${CMDVAR}"
Here it's unclear what is in CMDVAR
, and as mentioned above you would need escaped double quotes around ${CMDVAR}
, which is not possible currently with OpenSSH.
# This executes the script but hangs at script exit
"powershell myscript.ps1"
Maybe this could work with "powershell -File myscript.ps1"
?
# This simply hangs
"powershell -command 'my long script with ^"embedded^" quotes"
A mentioned, cmd.exe needs double quotes so the arguments to -command
would need to be enclosed in escaped double quotes, which is not currently possible with OpenSSH.