allowing users to configure the default shell through windows registry (#215)

This commit is contained in:
bagajjal 2017-10-16 10:45:11 -07:00 committed by Manoj Ampalam
parent 7a4a10a224
commit 9c95d8e2bb
2 changed files with 125 additions and 15 deletions

View File

@ -255,8 +255,11 @@ struct key_translation keys[] = {
static SHORT lastX = 0;
static SHORT lastY = 0;
static wchar_t system32_path[PATH_MAX];
static wchar_t cmd_exe_path[PATH_MAX];
static wchar_t system32_path[PATH_MAX + 1] = { 0, };
static wchar_t cmd_exe_path[PATH_MAX + 1] = { 0, };
static wchar_t default_shell_path[PATH_MAX + 3] = { 0, }; /* 2 - quotes, 1 - Null terminator */
static wchar_t default_shell_cmd_option[10] = { 0, }; /* for cmd.exe/powershell it is "/c", for bash.exe it is "-c" */
static BOOL is_default_shell_configured = FALSE;
SHORT currentLine = 0;
consoleEvent* head = NULL;
@ -1192,19 +1195,70 @@ cleanup:
}
wchar_t *
w32_cmd_path()
get_default_shell_path()
{
HKEY reg_key = 0;
int tmp_len = PATH_MAX;
errno_t r = 0;
if ((r = wcsncpy_s(cmd_exe_path, _countof(cmd_exe_path), system32_path, wcsnlen(system32_path, _countof(system32_path)) + 1)) != 0) {
printf_s("wcsncpy_s failed with error: %d.", r);
REGSAM mask = STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY;
wchar_t *tmp = malloc(PATH_MAX + 1);
if (!tmp) {
printf_s("get_default_shell_path(), Unable to allocate memory");
exit(255);
}
if ((r = wcscat_s(cmd_exe_path, _countof(cmd_exe_path), L"\\cmd.exe")) != 0) {
printf_s("wcscat_s failed with error: %d.", r);
memset(tmp, 0, PATH_MAX + 1);
memset(default_shell_path, 0, _countof(default_shell_path));
if ((RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\OpenSSH", 0, mask, &reg_key) == ERROR_SUCCESS) &&
(RegQueryValueExW(reg_key, L"DefaultShell", 0, NULL, (LPBYTE)tmp, &tmp_len) == ERROR_SUCCESS) &&
(tmp)) {
is_default_shell_configured = TRUE;
/* If required, add quotes to the default shell. */
if (tmp[0] != L'"') {
default_shell_path[0] = L'\"';
wcscat_s(default_shell_path, _countof(default_shell_path), tmp);
wcscat_s(default_shell_path, _countof(default_shell_path), L"\"");
} else
wcscat_s(default_shell_path, _countof(default_shell_path), tmp);
/* Fetch the default shell command option.
* For cmd.exe/powershell.exe it is "/c", for bash.exe it is "-c".
* For cmd.exe/powershell.exe/bash.exe, verify if present otherwise auto-populate.
*/
memset(tmp, 0, PATH_MAX + 1);
if ((RegQueryValueExW(reg_key, L"DefaultShellCommandOption", 0, NULL, (LPBYTE)tmp, &tmp_len) == ERROR_SUCCESS)) {
wcscat_s(default_shell_cmd_option, _countof(default_shell_cmd_option), L" ");
wcscat_s(default_shell_cmd_option, _countof(default_shell_cmd_option), tmp);
wcscat_s(default_shell_cmd_option, _countof(default_shell_cmd_option), L" ");
}
}
if (((r = wcsncpy_s(cmd_exe_path, _countof(cmd_exe_path), system32_path, wcsnlen(system32_path, _countof(system32_path)) + 1)) != 0) ||
((r = wcscat_s(cmd_exe_path, _countof(cmd_exe_path), L"\\cmd.exe")) != 0)) {
printf_s("get_default_shell_path(), wcscat_s failed with error: %d.", r);
exit(255);
}
return cmd_exe_path;
/* if default shell is not configured then use cmd.exe as the default shell */
if (!is_default_shell_configured)
wcscat_s(default_shell_path, _countof(default_shell_path), cmd_exe_path);
memset(default_shell_cmd_option, 0, _countof(default_shell_cmd_option));
if (!default_shell_cmd_option[0]) {
if (wcsstr(default_shell_path, L"cmd.exe") || wcsstr(default_shell_path, L"powershell.exe"))
wcscat_s(default_shell_cmd_option, _countof(default_shell_cmd_option), L" /c ");
else if (wcsstr(default_shell_path, L"bash.exe"))
wcscat_s(default_shell_cmd_option, _countof(default_shell_cmd_option), L" -c ");
}
if (tmp)
free(tmp);
return default_shell_path;
}
int
@ -1280,10 +1334,24 @@ start_with_pty(wchar_t *command)
GOTO_CLEANUP_ON_FALSE(SetHandleInformation(pipe_in, HANDLE_FLAG_INHERIT, 0));
cmd[0] = L'\0';
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, w32_cmd_path()));
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, get_default_shell_path()));
if (command) {
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c "));
if(default_shell_cmd_option[0])
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, default_shell_cmd_option));
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, command));
} else {
/* Launch the default shell through cmd.exe.
* If we don't launch default shell through cmd.exe then the powershell colors are rendered badly to the ssh client.
*/
if (is_default_shell_configured) {
wchar_t tmp_cmd[PATH_MAX + 1] = {0,};
wcscat_s(tmp_cmd, _countof(tmp_cmd), cmd);
cmd[0] = L'\0';
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, cmd_exe_path));
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c "));
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, tmp_cmd));
}
}
SetConsoleCtrlHandler(NULL, FALSE);
@ -1454,9 +1522,11 @@ start_withno_pty(wchar_t *command)
/* if above failed with FILE_NOT_FOUND, try running the provided command under cmd*/
if (run_under_cmd) {
cmd[0] = L'\0';
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, w32_cmd_path()));
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, get_default_shell_path()));
if (command) {
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c "));
if (default_shell_cmd_option[0])
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, default_shell_cmd_option));
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, command));
}

View File

@ -67,7 +67,19 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
Options = '-i $identifyFile -l $($server.localAdminUserName)'
}
)#>
$defaultRegistryPath = "HKLM:\Software\OpenSSH"
$registryKeyName = "DefaultShell"
function ConfigureDefaultShell {
param([string]$default_shell_path)
if (!(Test-Path $defaultRegistryPath)) {
New-Item -Path $defaultRegistryPath -Force | Out-Null
New-ItemProperty -Path $defaultRegistryPath -Name $registryKeyName -Value $default_shell_path -PropertyType String -Force
} else {
New-ItemProperty -Path $defaultRegistryPath -Name $registryKeyName -Value $default_shell_path -PropertyType String -Force
}
}
}
BeforeEach {
@ -133,6 +145,34 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
}#>
}
Context "$tC - configure default shell Scenarios" {
BeforeAll {$tI=1}
AfterAll{$tC++}
AfterEach {
Remove-ItemProperty -Name $registryKeyName -Path $defaultRegistryPath -ErrorAction SilentlyContinue
}
It "$tC.$tI - default shell as powershell" {
$shell_path = (Get-Command powershell.exe -ErrorAction SilentlyContinue).path
if($shell_path -ne $null) {
ConfigureDefaultShell -default_shell_path $shell_path
$o = ssh test_target Write-Output 1234
$o | Should Be "1234"
}
}
It "$tC.$tI - default shell as cmd" {
$shell_path = (Get-Command cmd.exe -ErrorAction SilentlyContinue).path
if($shell_path -ne $null) {
ConfigureDefaultShell -default_shell_path $shell_path
$o = ssh test_target where cmd
$o | Should Contain "cmd"
}
}
}
Context "$tC - cmdline parameters" {
BeforeAll {$tI=1}