Ported bash based E2E tests and integrated security fix for cve-2018-15473(#346)

- Updated code to dynamic load Lsa functions until RS5 SDK includes them
 - Add conpty support in openssh
- Fixed Wierd characters (?25l) are seen, when logged in from ssh client
- Backspace doesn't work in powershell window
- Changes to support ssh-shellhost as an alternative shell
- Added support to have ssh-shellhost work as a standby shell (ssh-shellhost -c "cmdline") simply executes cmdline via CreateProcess
- Added E2E test cases and fixed unittests broken from prior changes
- Added PTY launch interface that supports both conpty and ssh-shellhost pty.
- Implemented PTY control channel in ssh-shellhost that supports Window resize events.
- Fixed regression with starting a PTY session with an explicit command
- modified ssh-shellhost pty argument to ---pty to remove ambiguity in cases when both -p and -c are present in commandline. Ex. ssh-shellhost.exe -c "myprogram -p -c argument"
This commit is contained in:
Manoj Ampalam 2018-10-04 14:16:02 -07:00 committed by GitHub
parent 0840af06bf
commit af4e4113b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
70 changed files with 1678 additions and 502 deletions

10
auth.c
View File

@ -589,8 +589,13 @@ getpwnamallow(const char *user)
#endif
struct passwd *pw;
struct connection_info *ci = get_connection_info(1, options.use_dns);
#ifdef WINDOWS
/* getpwname - normalizes the incoming user and makes it lowercase */
pw = getpwnam(user);
ci->user = pw? pw->pw_name: user;
#else
ci->user = user;
#endif // WINDOWS
parse_server_match_config(&options, ci);
log_change_level(options.log_level);
process_permitopen(ssh, &options);
@ -598,8 +603,9 @@ getpwnamallow(const char *user)
#if defined(_AIX) && defined(HAVE_SETAUTHDB)
aix_setauthdb(user);
#endif
#ifndef WINDOWS
pw = getpwnam(user);
#endif
#if defined(_AIX) && defined(HAVE_SETAUTHDB)
aix_restoreauthdb();

View File

@ -90,19 +90,15 @@ userauth_pubkey(struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
struct passwd *pw = authctxt->pw;
struct sshbuf *b;
struct sshbuf *b = NULL;
struct sshkey *key = NULL;
char *pkalg, *userstyle = NULL, *key_s = NULL, *ca_s = NULL;
u_char *pkblob, *sig, have_sig;
char *pkalg = NULL, *userstyle = NULL, *key_s = NULL, *ca_s = NULL;
u_char *pkblob = NULL, *sig = NULL, have_sig;
size_t blen, slen;
int r, pktype;
int authenticated = 0;
struct sshauthopt *authopts = NULL;
if (!authctxt->valid) {
debug2("%s: disabled because of invalid user", __func__);
return 0;
}
if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0 ||
(r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 ||
(r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0)
@ -169,6 +165,11 @@ userauth_pubkey(struct ssh *ssh)
fatal("%s: sshbuf_put_string session id: %s",
__func__, ssh_err(r));
}
if (!authctxt->valid || authctxt->user == NULL) {
debug2("%s: disabled because of invalid user",
__func__);
goto done;
}
/* reconstruct packet */
xasprintf(&userstyle, "%s%s%s", authctxt->user,
authctxt->style ? ":" : "",
@ -185,7 +186,6 @@ userauth_pubkey(struct ssh *ssh)
#ifdef DEBUG_PK
sshbuf_dump(b, stderr);
#endif
/* test for correct signature */
authenticated = 0;
if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) &&
@ -194,7 +194,6 @@ userauth_pubkey(struct ssh *ssh)
authenticated = 1;
}
sshbuf_free(b);
free(sig);
auth2_record_key(authctxt, authenticated, key);
} else {
debug("%s: test pkalg %s pkblob %s%s%s",
@ -205,6 +204,11 @@ userauth_pubkey(struct ssh *ssh)
if ((r = sshpkt_get_end(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
if (!authctxt->valid || authctxt->user == NULL) {
debug2("%s: disabled because of invalid user",
__func__);
goto done;
}
/* XXX fake reply and always send PK_OK ? */
/*
* XXX this allows testing whether a user is allowed
@ -238,6 +242,7 @@ done:
free(pkblob);
free(key_s);
free(ca_s);
free(sig);
return authenticated;
}

View File

@ -0,0 +1,276 @@
param (
# Path to openssh binaries
[Parameter(Mandatory=$true)] [string] $OpenSSHBinPath,
# Path of regress folder which has all the bash testcases.
[Parameter(Mandatory=$true)] [string] $BashTestsPath,
# Path to CYGWIN / WSL.
[Parameter(Mandatory=$true)] [string] $ShellPath,
# Individual bash test file (Ex - connect.sh)
[Parameter(Mandatory=$false)] [string[]] $TestFilePath,
[Parameter(Mandatory=$false)] [string] $ArtifactsPath=".",
[switch] $SkipCleanup,
[switch] $SkipInstallSSHD
)
# Resolve the relative paths
$OpenSSHBinPath=resolve-path $OpenSSHBinPath -ErrorAction Stop | select -ExpandProperty Path
$BashTestsPath=resolve-path $BashTestsPath -ErrorAction Stop | select -ExpandProperty Path
$ShellPath=resolve-path $ShellPath -ErrorAction Stop | select -ExpandProperty Path
$ArtifactsPath=resolve-path $ArtifactsPath -ErrorAction Stop | select -ExpandProperty Path
if ($TestFilePath) {
$TestFilePath=resolve-path $TestFilePath -ErrorAction Stop | select -ExpandProperty Path
# convert to bash format
$TestFilePath=$TestFilePath -replace "\\","/"
}
# Make sure config.h exists. It is used by bashstests (Ex - sftp-glob.sh, cfgparse.sh)
# first check in $BashTestsPath folder. If not then it's parent folder. If not then in the $OpenSSHBinPath
if(Test-Path "$BashTestsPath\config.h" -PathType Leaf) {
$configPath="$BashTestsPath\config.h"
} elseif(Test-Path "$BashTestsPath\..\config.h" -PathType Leaf) {
$configPath=resolve-path "$BashTestsPath\..\config.h" -ErrorAction Stop | select -ExpandProperty Path
} elseif(Test-Path "$OpenSSHBinPath\config.h" -PathType Leaf) {
$configPath="$OpenSSHBinPath\config.h"
} else {
Write-Error "Couldn't find config.h"
exit
}
# store user directory
$user_pwd=pwd | select -ExpandProperty Path
# If we are using a SKU with desired OpenSSH binaries then we can skip these steps.
if(!$SkipInstallSSHD) {
# Make sure install-sshd.ps1 exists.
if(!(Test-Path "$PSScriptRoot\install-sshd.ps1" -PathType Leaf)) {
Write-Error "$PSScriptRoot\install-sshd.ps1 doesn't exists"
exit
}
# Make sure uninstall-sshd.ps1 exists.
if(!(Test-Path "$PSScriptRoot\uninstall-sshd.ps1" -PathType Leaf)) {
Write-Error "$PSScriptRoot\uninstall-sshd.ps1 doesn't exists"
exit
}
#copy to binary folder and execute install-sshd.ps1
Copy-Item $PSScriptRoot\install-sshd.ps1 -Force $OpenSSHBinPath
Copy-Item $PSScriptRoot\uninstall-sshd.ps1 -Force $OpenSSHBinPath
# We need ssh-agent to be installed as service to run some bash tests.
& "$OpenSSHBinPath\install-sshd.ps1"
}
try
{
# set the default shell
$registryPath = "HKLM:\Software\OpenSSH"
$dfltShell = "DefaultShell"
# Fetch the user configured default shell.
$out=(Get-ItemProperty -Path $registryPath -Name $dfltShell -ErrorAction SilentlyContinue)
if($out) {
$user_default_shell = $out.$dfltShell
Write-Output "User configured default shell: $user_default_shell"
}
if (!(Test-Path $registryPath)) {
# start and stop the sshd so that "HKLM:\Software\OpenSSH" registry path is created.
Start-Service sshd -ErrorAction Stop
Stop-Service sshd -ErrorAction SilentlyContinue
}
Set-ItemProperty -Path $registryPath -Name $dfltShell -Value $ShellPath -Force
$out=(Get-ItemProperty -Path $registryPath -Name $dfltShell -ErrorAction SilentlyContinue)
if($out.$dfltShell -ne $ShellPath) {
Write-Output "Failed to set HKLM:\Software\OpenSSH\DefaultShell to $ShellPath"
exit
}
# Prepend shell path to PATH. This is required to make the shell commands (like sleep, cat, etc) work properly.
$env:TEST_SHELL_PATH=$ShellPath -replace "\\","/"
$TEST_SHELL_DIR=split-path $ShellPath
if(!$env:path.StartsWith($TEST_SHELL_DIR, "CurrentCultureIgnoreCase"))
{
$env:path=$TEST_SHELL_DIR+";"+$env:path
}
$BashTestsPath=$BashTestsPath -replace "\\","/"
Push-location $BashTestsPath
# BUILDDIR: config.h location.
# BUILDDIR is used by bashstests (Ex - sftp-glob.sh, cfgparse.sh)
$BUILDDIR=resolve-path(split-path $configpath) | select -ExpandProperty Path
$tmp=&$ShellPath -c pwd
if ($tmp.StartsWith("/cygdrive/")) {
$shell_drv_fmt="/cygdrive/" # "/cygdrive/" - cygwin
$BUILDDIR=&$ShellPath -c "cygpath -u '$BUILDDIR'"
$OpenSSHBinPath_shell_fmt=&$ShellPath -c "cygpath -u '$OpenSSHBinPath'"
$BashTestsPath=&$ShellPath -c "cygpath -u '$BashTestsPath'"
} elseif ($tmp.StartsWith("/mnt/")) {
$shell_drv_fmt="/mnt/" # "/mnt/" - WSL bash
$BUILDDIR=&$ShellPath -c "wslpath -u '$BUILDDIR'"
$OpenSSHBinPath_shell_fmt=&$ShellPath -c "wslpath -u '$OpenSSHBinPath'"
$BashTestsPath=&$ShellPath -c "wslpath -u '$BashTestsPath'"
}
#set the environment variables.
$env:ShellPath=$ShellPath
$env:SSH_TEST_ENVIRONMENT=1
$env:TEST_SSH_TRACE="yes"
$env:TEST_SHELL="/bin/sh"
$env:TEST_SSH_PORT=22
$env:TEST_SSH_SSH=$OpenSSHBinPath_shell_fmt+"/ssh.exe"
$env:TEST_SSH_SSHD=$OpenSSHBinPath_shell_fmt+"/sshd.exe"
$env:TEST_SSH_SSHAGENT=$OpenSSHBinPath_shell_fmt+"/ssh-agent.exe"
$env:TEST_SSH_SSHADD=$OpenSSHBinPath_shell_fmt+"/ssh-add.exe"
$env:TEST_SSH_SSHKEYGEN=$OpenSSHBinPath_shell_fmt+"/ssh-keygen.exe"
$env:TEST_SSH_SSHKEYSCAN=$OpenSSHBinPath_shell_fmt+"/ssh-keyscan.exe"
$env:TEST_SSH_SFTP=$OpenSSHBinPath_shell_fmt+"/sftp.exe"
$env:TEST_SSH_SFTPSERVER=$OpenSSHBinPath_shell_fmt+"/sftp-server.exe"
$env:TEST_SSH_SCP=$OpenSSHBinPath_shell_fmt+"/scp.exe"
$env:BUILDDIR=$BUILDDIR
$env:TEST_WINDOWS_SSH=1
$user = &"$env:windir\system32\whoami.exe"
if($user.Contains($env:COMPUTERNAME.ToLower())) {
# for local accounts, skip COMPUTERNAME
$user = Split-Path $user -leaf
$env:TEST_SSH_USER=$user
} else {
# for domain user convert "domain\user" to "domain/user".
$user = $user -replace "\\","/"
$env:TEST_SSH_USER = $user
$env:TEST_SSH_USER_DOMAIN = Split-Path $user
}
# output to terminal
Write-Output "USER: $env:TEST_SSH_USER"
Write-Output "DOMAIN: $env:TEST_SSH_USER_DOMAIN"
Write-Output "OpenSSHBinPath: $OpenSSHBinPath_shell_fmt"
Write-Output "BUILDDIR: $BUILDDIR"
Write-Output "BashTestsPath: $BashTestsPath"
# remove, create the temp test directory
$temp_test_path="temp_test"
$null = Remove-Item -Recurse -Force $temp_test_path -ErrorAction SilentlyContinue
$null = New-Item -ItemType directory -Path $temp_test_path -ErrorAction Stop
# remove the summary, output files.
$test_summary="$ArtifactsPath\\bashtest_summary.txt"
$test_output="$ArtifactsPath\\bashtest_output.txt"
$null = Remove-Item -Force $test_summary -ErrorAction SilentlyContinue
$null = Remove-Item -Force $test_output -ErrorAction SilentlyContinue
[int]$total_tests = 0
[int]$total_tests_passed = 0
[int]$total_tests_failed = 0
[string]$failed_testcases = [string]::Empty
# These are the known failed testcases.
# agent.sh, krl.sh - User Cert authentication fails
# key-options.sh - pty testcases are failing (bug in conpty. conpty fails to launch cygwin bash)
# integrity.sh - It's dependent on regress\modpipe.exe, test is complicated. Need to debug more
# authinfo.sh - spawned conpty inherits all the environment variables from sshd.
# forward-control.sh - Need to debug more.
[string]$known_failed_testcases = "agent.sh key-options.sh forward-control.sh integrity.sh krl.sh authinfo.sh"
[string]$known_failed_testcases_skipped = [string]::Empty
$start_time = (Get-Date)
if($TestFilePath) {
# User can specify individual test file path.
$all_tests=$TestFilePath
} else {
# picking the gawk.exe from bash folder.
# TODO - check if gawk.exe is present in WSL.
$all_tests=gawk.exe 'sub(/.*LTESTS=/,""""){f=1} f{print $1; if (!/\\\\/) exit}' Makefile
}
foreach($test_case in $all_tests) {
if($TestFilePath) {
$TEST=$test_case
} else {
if(!$test_case.Contains(".sh")) {
$TEST=$BashTestsPath+"/"+$test_case+".sh"
} else {
$TEST=$BashTestsPath+"/"+$test_case
}
}
$test_case_name = [System.IO.Path]::GetFileName($TEST)
if($known_failed_testcases.Contains($test_case_name))
{
Write-Output "Skip the known failed test:$test_case_name"
$known_failed_testcases_skipped = $known_failed_testcases_skipped + "$test_case_name "
}
else
{
$msg="Executing $test_case_name " +[System.DateTime]::Now
Write-Output $msg
&$env:ShellPath -c "/usr/bin/sh $BashTestsPath/test-exec.sh $BashTestsPath/$temp_test_path $TEST" #>$null 2>&1
if($?)
{
$msg="$test_case_name PASSED " +[System.DateTime]::Now
Write-Output $msg
$total_tests_passed++
}
else
{
$msg="$test_case_name FAILED " +[System.DateTime]::Now
Write-Output $msg
$total_tests_failed++
$failed_testcases=$failed_testcases + "$test_case_name "
}
}
$total_tests++
}
$end_time = (Get-Date)
# Create artifacts
"Start time: $start_time" | Out-File -FilePath $test_summary -Append
"End time: $end_time" | Out-File -FilePath $test_summary -Append
"Total execution time: " + (NEW-TIMESPAN -Start $start_time -End $end_time).ToString("hh\:mm\:ss") | Out-File -FilePath $test_summary -Append
"Tests executed: $total_tests" | Out-File -FilePath $test_summary -Append
"Tests passed: $total_tests_passed" | Out-File -FilePath $test_summary -Append
"Tests failed: $total_tests_failed" | Out-File -FilePath $test_summary -Append
"Failed tests: $failed_testcases" | Out-File -FilePath $test_summary -Append
"Skipped known failed tests: $known_failed_testcases_skipped" | Out-File -FilePath $test_summary -Append
Write-Output "Artifacts are saved to $ArtifactsPath"
#output the summary
Write-Output "================================="
cat $test_summary
Write-Output "================================="
}
finally
{
# remove temp test directory
if (!$SkipCleanup)
{
# remove temp test folder
&$ShellPath -c "rm -rf $BashTestsPath/temp_test"
if(!$SkipInstallSSHD) {
# Uninstall the sshd, ssh-agent service
& "$PSScriptRoot\uninstall-sshd.ps1"
}
# Remove the test environment variable
Remove-Item ENV:\SSH_TEST_ENVIRONMENT
# Revert to user configured default shell.
if($user_default_shell) {
Set-ItemProperty -Path $registryPath -Name $dfltShell -Value $user_default_shell -Force
$out=(Get-ItemProperty -Path $registryPath -Name $dfltShell -ErrorAction SilentlyContinue)
if($out.$dfltShell -eq $user_default_shell) {
Write-Output "Reverted user configured default shell to $user_default_shell"
} else {
Write-Output "Failed to set HKLM:\Software\OpenSSH\DefaultShell to $user_default_shell"
}
} else {
Remove-ItemProperty -Path $registryPath -Name $dfltShell -ErrorAction SilentlyContinue
}
}
Push-location $user_pwd
}

View File

@ -819,7 +819,7 @@
/* #undef HAVE_SETEGID */
/* Define to 1 if you have the `setenv' function. */
/* #undef HAVE_SETENV */
#define HAVE_SETENV 1
/* Define to 1 if you have the `seteuid' function. */
/* #undef HAVE_SETEUID */
@ -1699,4 +1699,5 @@
#define _PATH_SSH_PROGRAM "ssh.exe"
#define _PATH_LS "dir"
#define FORK_NOT_SUPPORTED 1
#define HAVE_FREEZERO
#define HAVE_FREEZERO
#define FILESYSTEM_NO_BACKSLASH

View File

@ -23,6 +23,7 @@
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\spawn.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32api_proxies.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\win32_usertoken_utils.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\conhost_conpty.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />

View File

@ -330,6 +330,7 @@ createFile_flags_setup(int flags, mode_t mode, struct createFile_flags* cf_flags
break;
case O_WRONLY:
cf_flags->dwDesiredAccess = GENERIC_WRITE;
cf_flags->dwShareMode = FILE_SHARE_WRITE;
break;
case O_RDWR:
cf_flags->dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
@ -474,7 +475,7 @@ fileio_open(const char *path_utf8, int flags, mode_t mode)
if (handle == INVALID_HANDLE_VALUE) {
errno = errno_from_Win32LastError();
debug3("failed to open file:%s error:%d", path_utf8, GetLastError());
debug3("failed to open file:%S error:%d", path_utf16, GetLastError());
goto cleanup;
}
@ -1157,45 +1158,46 @@ int
fileio_symlink(const char *target, const char *linkpath)
{
DWORD ret = -1;
char target_modified[PATH_MAX] = { 0 };
char *linkpath_resolved = NULL, *target_resolved = NULL;
if (target == NULL || linkpath == NULL) {
errno = EFAULT;
return -1;
}
wchar_t *target_utf16 = resolved_path_utf16(target);
wchar_t *linkpath_utf16 = resolved_path_utf16(linkpath);
wchar_t *resolved_utf16 = _wcsdup(target_utf16);
if (target_utf16 == NULL || linkpath_utf16 == NULL)
/* First resolve linkpath */
if (NULL == (linkpath_resolved = resolved_path_utf8(linkpath)))
goto cleanup;
if (resolved_utf16 == NULL) {
errno = ENOMEM;
goto cleanup;
}
/* Relative targets are relative to the link and not our current directory
* so attempt to calculate a resolvable path by removing the link file name
* leaving only the parent path and then append the relative link:
* C:\Path\Link with Link->SubDir\Target to C:\Path\SubDir\Target
*/
if (!is_absolute_path(target)) {
/* allocate area to hold the total possible path */
free(resolved_utf16);
size_t resolved_len = (wcslen(target_utf16) + wcslen(linkpath_utf16) + 1);
resolved_utf16 = malloc(resolved_len * sizeof(wchar_t));
if (resolved_utf16 == NULL) {
errno = ENOMEM;
goto cleanup;
}
strcpy_s(target_modified, _countof(target_modified), linkpath_resolved);
convertToBackslash(target_modified);
char *tmp = NULL;
/* copy the relative target to the end of the link's parent */
wcscpy_s(resolved_utf16, resolved_len, linkpath_utf16);
convertToBackslashW(resolved_utf16);
wchar_t * ptr = wcsrchr(resolved_utf16, L'\\');
if (ptr == NULL) wcscpy_s(resolved_utf16, resolved_len, target_utf16);
else wcscpy_s(ptr + 1, resolved_len - (ptr + 1 - resolved_utf16), target_utf16);
if (tmp = strrchr(target_modified, '\\'))
strcpy_s(tmp + 1, _countof(target_modified) - (tmp + 1 - target_modified), target);
else
strcpy_s(target_modified, _countof(target_modified), target);
} else {
/* resolve target */
if (NULL == (target_resolved = resolved_path_utf8(target)))
goto cleanup;
strcpy_s(target_modified, _countof(target_modified), target_resolved);
}
wchar_t *linkpath_utf16 = resolved_path_utf16(linkpath);
wchar_t *resolved_target_utf16 = utf8_to_utf16(target_modified);
if (resolved_target_utf16 == NULL || linkpath_utf16 == NULL) {
errno = ENOMEM;
goto cleanup;
}
/* unlike other platforms, we need to know whether the symbolic link target is
@ -1204,7 +1206,7 @@ fileio_symlink(const char *target, const char *linkpath)
* limitation of only creating symlink with valid targets
*/
WIN32_FILE_ATTRIBUTE_DATA attributes = { 0 };
if (GetFileAttributesExW(resolved_utf16, GetFileExInfoStandard, &attributes) == FALSE) {
if (GetFileAttributesExW(resolved_target_utf16, GetFileExInfoStandard, &attributes) == FALSE) {
errno = errno_from_Win32LastError();
goto cleanup;
}
@ -1218,8 +1220,8 @@ fileio_symlink(const char *target, const char *linkpath)
* context so we try both operations, attempting privileged version first.
* note: 0x2 = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
*/
if (CreateSymbolicLinkW(linkpath_utf16, target_utf16, create_flags) == 0) {
if (CreateSymbolicLinkW(linkpath_utf16, target_utf16, create_flags | 0x2) == 0) {
if (CreateSymbolicLinkW(linkpath_utf16, resolved_target_utf16, create_flags) == 0) {
if (CreateSymbolicLinkW(linkpath_utf16, resolved_target_utf16, create_flags | 0x2) == 0) {
errno = errno_from_Win32LastError();
goto cleanup;
}
@ -1228,12 +1230,18 @@ fileio_symlink(const char *target, const char *linkpath)
ret = 0;
cleanup:
if (target_utf16)
free(target_utf16);
if (linkpath_utf16)
free(linkpath_utf16);
if (resolved_utf16)
free(resolved_utf16);
if (resolved_target_utf16)
free(resolved_target_utf16);
if (linkpath_resolved)
free(linkpath_resolved);
if (target_resolved)
free(target_resolved);
return ret;
}

View File

@ -2,4 +2,5 @@
#include STDLIB_H
#define environ _environ
void freezero(void *, size_t);
void freezero(void *, size_t);
int setenv(const char *name, const char *value, int rewrite);

View File

@ -279,7 +279,7 @@ w32_fopen_utf8(const char *input_path, const char *mode)
goto cleanup;
if ((_wfopen_s(&f, wpath, wmode) != 0) || (f == NULL)) {
debug3("Failed to open file:%s error:%d", input_path, errno);
debug3("Failed to open file:%S error:%d", wpath, errno);
goto cleanup;
}
@ -512,6 +512,10 @@ strmode(mode_t mode, char *p)
int
w32_chmod(const char *pathname, mode_t mode)
{
/* TODO -
* _wchmod() doesn't behave like unix "chmod" command.
* _wchmod() only toggles the read-only bit and it doesn't touch ACL.
*/
int ret;
wchar_t *resolvedPathName_utf16 = resolved_path_utf16(pathname);
if (resolvedPathName_utf16 == NULL)
@ -685,11 +689,16 @@ w32_rename(const char *old_name, const char *new_name)
* 1) if the new_name is file, then delete it so that _wrename will succeed.
* 2) if the new_name is directory and it is empty then delete it so that _wrename will succeed.
*/
struct w32_stat st;
if (w32_stat(new_name, &st) != -1) {
if (((st.st_mode & _S_IFMT) == _S_IFREG))
struct _stat64 st_new;
struct _stat64 st_old;
if ((fileio_stat(new_name, &st_new) != -1) &&
(fileio_stat(old_name, &st_old) != -1)) {
if (((st_old.st_mode & _S_IFMT) == _S_IFREG) &&
((st_new.st_mode & _S_IFMT) == _S_IFREG))
w32_unlink(new_name);
else {
if (((st_old.st_mode & _S_IFMT) == _S_IFDIR) &&
((st_new.st_mode & _S_IFMT) == _S_IFDIR)) {
DIR *dirp = opendir(new_name);
if (NULL != dirp) {
struct dirent *dp = readdir(dirp);
@ -769,7 +778,7 @@ w32_getcwd(char *buffer, int maxlen)
return NULL;
}
if (strcpy_s(buffer, maxlen, putf8))
if (strcpy_s(buffer, maxlen, putf8))
return NULL;
free(putf8);
@ -782,7 +791,7 @@ w32_getcwd(char *buffer, int maxlen)
memcmp(chroot_path, buffer, chroot_path_len) != 0 ||
(c != '\0' && c!= '\\') ) {
errno = EOTHER;
error("cwb is not currently within chroot");
error("cwd is not currently within chroot");
return NULL;
}
@ -795,7 +804,7 @@ w32_getcwd(char *buffer, int maxlen)
char *tail = buffer + chroot_path_len;
memmove_s(buffer, maxlen, tail, strlen(tail) + 1);
}
}
}
return buffer;
}
@ -880,15 +889,36 @@ convertToForwardslash(char *str)
* path to produce a canonicalized absolute pathname.
*/
char *
realpath(const char *path, char resolved[PATH_MAX])
realpath(const char *inputpath, char resolved[PATH_MAX])
{
if (!path || !resolved) return NULL;
char path[PATH_MAX] = { 0, }, tempPath[PATH_MAX] = { 0, }, *ret = NULL;
int is_win_path = 1;
char tempPath[PATH_MAX];
size_t path_len = strlen(path);
if (!inputpath || !resolved)
return NULL;
size_t path_len = strlen(inputpath);
resolved[0] = '\0';
if (path_len > PATH_MAX - 1) {
if (path_len > PATH_MAX) {
errno = EINVAL;
return NULL;
}
if (is_bash_test_env() && bash_to_win_path(inputpath, path, _countof(path)))
is_win_path = 0;
if (is_win_path) {
if (_strnicmp(inputpath, PROGRAM_DATA, strlen(PROGRAM_DATA)) == 0) {
strcat_s(path, PATH_MAX, __progdata);
strcat_s(path, PATH_MAX, &inputpath[strlen(PROGRAM_DATA)]);
} else {
memcpy_s(path, PATH_MAX, inputpath, strlen(inputpath));
}
}
path_len = strlen(path);
if (path_len > PATH_MAX) {
errno = EINVAL;
return NULL;
}
@ -897,7 +927,8 @@ realpath(const char *path, char resolved[PATH_MAX])
if (path_len == 1 && (path[0] == '/' || path[0] == '\\')) {
resolved[0] = '/';
resolved[1] = '\0';
return resolved;
ret = resolved;
goto done;
}
/* resolve this common case scenario to root */
@ -909,7 +940,8 @@ realpath(const char *path, char resolved[PATH_MAX])
if (strcmp(tmplate, resolved) == 0) {
resolved[0] = '/';
resolved[1] = '\0';
return resolved;
ret = resolved;
goto done;
}
}
@ -921,17 +953,22 @@ realpath(const char *path, char resolved[PATH_MAX])
w32_getcwd(resolved + chroot_path_len, PATH_MAX - chroot_path_len);
strcat_s(resolved, PATH_MAX, "/");
}
/* TODO - This logic will fail if the chroot_path is more than PATH_MAX/2.
* resolved variable is of PATH_MAX.
* We first copy chroot_path to resolved variable then incoming path (which can be again chroot_path).
* In this case strcat_s will thrown a run time insufficient buffer exception.
*/
strcat_s(resolved, PATH_MAX, path);
}
else if ((path_len >= 2) && (path[0] == '/') && path[1] && (path[2] == ':')) {
if((errno = strncpy_s(resolved, PATH_MAX, path + 1, path_len)) != 0 ) /* skip the first '/' */ {
debug3("memcpy_s failed with error: %d.", errno);
return NULL;
goto done;
}
}
else if(( errno = strncpy_s(resolved, PATH_MAX, path, path_len + 1)) != 0) {
debug3("memcpy_s failed with error: %d.", errno);
return NULL;
goto done;
}
if ((resolved[0]) && (resolved[1] == ':') && (resolved[2] == '\0')) { /* make "x:" as "x:\\" */
@ -941,21 +978,20 @@ realpath(const char *path, char resolved[PATH_MAX])
if (_fullpath(tempPath, resolved, PATH_MAX) == NULL) {
errno = EINVAL;
return NULL;
goto done;
}
if (chroot_path) {
if (strlen(tempPath) < strlen(chroot_path)) {
errno = EACCES;
return NULL;
goto done;
}
if (memcmp(chroot_path, tempPath, strlen(chroot_path)) != 0) {
errno = EACCES;
return NULL;
goto done;
}
resolved[0] = '\0';
if (strlen(tempPath) == strlen(chroot_path))
/* realpath is the same as chroot_path */
@ -965,21 +1001,41 @@ realpath(const char *path, char resolved[PATH_MAX])
if (resolved[0] != '\\') {
errno = EACCES;
return NULL;
goto done;
}
convertToForwardslash(resolved);
return resolved;
ret = resolved;
goto done;
}
else {
convertToForwardslash(tempPath);
resolved[0] = '/'; /* will be our first slash in /x:/users/test1 format */
if ((errno = strncpy_s(resolved + 1, PATH_MAX - 1, tempPath, sizeof(tempPath) - 1)) != 0) {
debug3("memcpy_s failed with error: %d.", errno);
return NULL;
goto done;
}
return resolved;
ret = resolved;
goto done;
}
done:
return ret;
}
/* on error returns NULL and sets errno */
char*
resolved_path_utf8(const char *input_path)
{
wchar_t *resolved_path_w = resolved_path_utf16(input_path);
char *resolved_path = NULL;
if (resolved_path_w) {
resolved_path = utf16_to_utf8(resolved_path_w);
free(resolved_path_w);
}
return resolved_path;
}
/* on error returns NULL and sets errno */
@ -987,70 +1043,26 @@ wchar_t*
resolved_path_utf16(const char *input_path)
{
wchar_t *resolved_path = NULL;
char real_path[PATH_MAX];
if (!input_path) {
errno = EINVAL;
return NULL;
}
if (chroot_path) {
char actual_path[MAX_PATH], jail_path[MAX_PATH];
if (realpath(input_path, jail_path) == NULL)
return NULL;
actual_path[0] = '\0';
strcat_s(actual_path, MAX_PATH, chroot_path);
strcat_s(actual_path, MAX_PATH, jail_path);
resolved_path = utf8_to_utf16(actual_path);
}
else
resolved_path = utf8_to_utf16(input_path);
if (resolved_path == NULL) {
errno = ENOMEM;
if (realpath(input_path, real_path) == NULL)
return NULL;
}
int resolved_len = (int) wcslen(resolved_path);
const int variable_len = (int) wcslen(PROGRAM_DATAW);
/* search for program data flag and switch it with the real path */
if (_wcsnicmp(resolved_path, PROGRAM_DATAW, variable_len) == 0) {
wchar_t * program_data = get_program_data_path();
const int programdata_len = (int) wcslen(program_data);
const int changed_req = programdata_len - variable_len;
/* allocate more memory if required */
if (changed_req > 0) {
wchar_t * resolved_path_new = realloc(resolved_path,
(resolved_len + changed_req + 1) * sizeof(wchar_t));
if (resolved_path_new == NULL) {
debug3("%s: memory allocation failed.", __FUNCTION__);
free(resolved_path);
errno = ENOMEM;
return NULL;
}
else resolved_path = resolved_path_new;
}
/* shift memory contents over based on side of the new string */
wmemmove_s(&resolved_path[variable_len + changed_req], resolved_len - variable_len + 1,
&resolved_path[variable_len], resolved_len - variable_len + 1);
resolved_len += changed_req;
wmemcpy_s(resolved_path, resolved_len + 1, program_data, programdata_len);
}
if (resolved_path[0] == L'/' && iswalpha(resolved_path[1]) && resolved_path[2] == L':') {
/* shift memory to remove forward slash including null terminator */
wmemmove_s(resolved_path, resolved_len + 1, resolved_path + 1, (resolved_len + 1 - 1));
/* if just a drive letter path, make x: into x:\ */
if (resolved_path[2] == L'\0') {
resolved_path[2] = L'\\';
resolved_path[3] = L'\0';
}
if (chroot_path) {
char actual_path[PATH_MAX] = { 0 };
strcat_s(actual_path, _countof(actual_path), chroot_path);
strcat_s(actual_path, _countof(actual_path), real_path);
resolved_path = utf8_to_utf16(actual_path);
} else {
if ((strlen(real_path) == 1) && (real_path[0] == '/'))
resolved_path = utf8_to_utf16(real_path);
else
resolved_path = utf8_to_utf16(real_path + 1); /* account for preceding / in real_path */
}
return resolved_path;
@ -1301,21 +1313,6 @@ cleanup:
return ret;
}
wchar_t*
get_program_data_path()
{
static wchar_t ssh_cfg_dir_path_w[PATH_MAX] = L"";
if (wcslen(ssh_cfg_dir_path_w) > 0) return ssh_cfg_dir_path_w;
int return_val = ExpandEnvironmentStringsW(L"%ProgramData%", ssh_cfg_dir_path_w, PATH_MAX);
if (return_val > PATH_MAX)
fatal("%s, buffer too small to expand:%s", __func__, "%ProgramData%");
else if (!return_val)
fatal("%s, failed to expand:%s error:%s", __func__, "%ProgramData%", GetLastError());
return ssh_cfg_dir_path_w;
}
/* Windows absolute paths - \abc, /abc, c:\abc, c:/abc, __PROGRAMDATA__\openssh\sshd_config */
int
is_absolute_path(const char *path)
@ -1406,6 +1403,30 @@ freezero(void *ptr, size_t sz)
free(ptr);
}
int
setenv(const char *name, const char *value, int rewrite)
{
errno_t result = 0;
/* If rewrite is 0, then set only if the variable name doesn't already exist in environment */
if (!rewrite) {
char *envValue = NULL;
size_t len = 0;
_dupenv_s(&envValue, &len, name);
if (envValue)
return result; /* return success (as per setenv manpage) */
}
if (!(result = _putenv_s(name, value)))
return 0;
else {
error("failed to set the environment variable:%s to value:%s, error:%d", name, value, result);
errno = result;
return -1;
}
}
int
chroot(const char *path)
{
@ -1567,7 +1588,7 @@ cleanup:
char*
build_session_commandline(const char *shell, const char* shell_arg, const char *command)
{
enum sh_type { SH_OTHER, SH_CMD, SH_PS, SH_BASH } shell_type = SH_OTHER;
enum sh_type { SH_OTHER, SH_CMD, SH_PS, SH_BASH, SH_CYGWIN } shell_type = SH_OTHER;
enum cmd_type { CMD_OTHER, CMD_SFTP, CMD_SCP } command_type = CMD_OTHER;
char *progdir = __progdir, *cmd_sp = NULL, *cmdline = NULL, *ret = NULL, *p;
int len, progdir_len = (int)strlen(progdir);
@ -1586,6 +1607,9 @@ do { \
shell_type = SH_PS;
else if (strstr(shell, "\\bash"))
shell_type = SH_BASH;
else if (strstr(shell, "cygwin")) {
shell_type = SH_CYGWIN;
}
/* special case where incoming command needs to be adjusted */
do {
@ -1659,7 +1683,7 @@ do { \
p = cmd_sp;
if (shell_type == SH_CMD) {
if ((shell_type == SH_CMD) || (shell_type == SH_CYGWIN)) {
CMDLINE_APPEND(p, "\"");
CMDLINE_APPEND(p, progdir);
@ -1667,7 +1691,6 @@ do { \
CMDLINE_APPEND(p, "\\scp.exe\"");
else
CMDLINE_APPEND(p, "\\sftp-server.exe\"");
} else {
if (command_type == CMD_SCP)
CMDLINE_APPEND(p, "scp.exe");
@ -1675,6 +1698,11 @@ do { \
CMDLINE_APPEND(p, "sftp-server.exe");
}
if (shell_type == SH_CYGWIN) {
*p = '\0';
convertToForwardslash(cmd_sp);
}
CMDLINE_APPEND(p, command_args);
*p = '\0';
command = cmd_sp;
@ -1684,7 +1712,12 @@ do { \
len +=(int) strlen(shell) + 3;/* 3 for " around shell path and trailing space */
if (command) {
len += 15; /* for shell command argument, typically -c or /c */
len += (int)strlen(command) + 5; /* 5 for possible " around command and null term*/
int extra_buffer_len = 0;
if (is_bash_test_env())
extra_buffer_len = 50; /* 50 - To escape double quotes or backslash in command (Ex - yes-head.sh) */
len += (int)strlen(command) + 5 + extra_buffer_len; /* 5 for possible " around command and null term*/
}
if ((cmdline = malloc(len)) == NULL) {
@ -1709,7 +1742,28 @@ do { \
/* Add double quotes around command */
CMDLINE_APPEND(p, "\"");
CMDLINE_APPEND(p, command);
if (is_bash_test_env()) {
/* Escape the double quotes and backslash as per CRT rules.
* Right now this logic is applied only in bash test environment.
* TODO - verify if this logic is applicable to all the shells.
*/
for (int i = 0; i < strlen(command); i++) {
if (command[i] == '\\') {
CMDLINE_APPEND(p, "\\");
CMDLINE_APPEND(p, "\\"); // For every backslash add another backslash.
}
else if (command[i] == '\"') {
CMDLINE_APPEND(p, "\\"); // Add backslash for every double quote.
CMDLINE_APPEND(p, "\"");
}
else {
*p++ = command[i];
}
}
} else {
CMDLINE_APPEND(p, command);
}
CMDLINE_APPEND(p, "\"");
}
*p = '\0';
@ -1722,4 +1776,39 @@ done:
free(cmdline);
return ret;
}
}
BOOL
is_bash_test_env()
{
char *envValue = NULL;
size_t len = 0;
BOOL retVal = FALSE;
_dupenv_s(&envValue, &len, "SSH_TEST_ENVIRONMENT");
if ((NULL != envValue) && atoi(envValue))
retVal = TRUE;
if (envValue)
free(envValue);
return retVal;
}
int
bash_to_win_path(const char *in, char *out, const size_t out_len)
{
int retVal = 0;
const size_t cygwin_path_prefix_len = strlen(CYGWIN_PATH_PREFIX);
if (_strnicmp(in, CYGWIN_PATH_PREFIX, cygwin_path_prefix_len) == 0) {
memset(out, 0, out_len);
out[0] = in[cygwin_path_prefix_len];
out[1] = ':';
strcat_s(out, out_len, &in[cygwin_path_prefix_len + 1]);
retVal = 1;
} else {
strcat_s(out, out_len, in);
}
return retVal;
}

View File

@ -19,6 +19,7 @@
#define IS_VALID_HANDLE(h) (!IS_INVALID_HANDLE(h))
#define PROGRAM_DATA "__PROGRAMDATA__"
#define PROGRAM_DATAW L"__PROGRAMDATA__"
#define CYGWIN_PATH_PREFIX "/cygdrive/"
#define errno_from_Win32LastError() errno_from_Win32Error(GetLastError())
@ -36,6 +37,10 @@ extern char* __progname;
extern char* __progdir;
extern wchar_t* __wprogdir;
/* %programdata% value */
extern char* __progdata;
extern wchar_t* __wprogdata;
static char *machine_domain_name;
extern char* chroot_path;
@ -44,6 +49,7 @@ extern wchar_t* chroot_pathw;
/* removes first '/' for Windows paths that are unix styled. Ex: /c:/ab.cd */
wchar_t * resolved_path_utf16(const char *);
char* resolved_path_utf8(const char *);
void w32posix_initialize();
void w32posix_done();
void init_prog_paths();
@ -57,7 +63,6 @@ int file_attr_to_st_mode(wchar_t * path, DWORD attributes);
void invalid_parameter_handler(const wchar_t *, const wchar_t *, const wchar_t *, unsigned int, uintptr_t);
void to_lower_case(char *s);
void to_wlower_case(wchar_t *s);
wchar_t* get_program_data_path();
HANDLE get_user_token(const char* user, int impersonation);
int load_user_profile(HANDLE user_token, char* user);
int create_directory_withsddl(wchar_t *path, wchar_t *sddl);
@ -71,3 +76,5 @@ int exec_command_with_pty(wchar_t*, STARTUPINFOW*, PROCESS_INFORMATION*, int);
char* get_custom_lsa_package();
wchar_t* get_final_path_by_handle(HANDLE h);
int lookup_principal_name(const wchar_t * sam_account_name, wchar_t * user_principal_name);
BOOL is_bash_test_env();
int bash_to_win_path(const char *in, char *out, const size_t out_len);

View File

@ -157,7 +157,7 @@ get_passwd(const wchar_t * user_utf16, PSID sid)
{
wchar_t user_resolved[DNLEN + 1 + UNLEN + 1];
struct passwd *ret = NULL;
wchar_t *sid_string = NULL;
wchar_t *sid_string = NULL, *tmp = NULL, *user_utf16_modified = NULL;
wchar_t reg_path[PATH_MAX], profile_home[PATH_MAX], profile_home_exp[PATH_MAX];
DWORD reg_path_len = PATH_MAX;
HKEY reg_key = 0;
@ -171,13 +171,29 @@ get_passwd(const wchar_t * user_utf16, PSID sid)
errno = 0;
if (reset_pw() != 0)
return NULL;
/*
* We support both "domain\user" and "domain/user" formats.
* But win32 APIs only accept domain\user format so convert it.
*/
if (user_utf16) {
user_utf16_modified = _wcsdup(user_utf16);
if (!user_utf16_modified) {
errno = ENOMEM;
error("%s failed to duplicate %s", __func__, user_utf16);
goto cleanup;
}
if (tmp = wcsstr(user_utf16_modified, L"/"))
*tmp = L'\\';
}
/* skip forward lookup on name if sid was passed in */
if (sid != NULL)
CopySid(sizeof(binary_sid), binary_sid, sid);
/* else attempt to lookup the account; this will verify the account is valid and
* is will return its sid and the realm that owns it */
else if(LookupAccountNameW(NULL, user_utf16, binary_sid, &sid_size,
else if(LookupAccountNameW(NULL, user_utf16_modified, binary_sid, &sid_size,
domain_name, &domain_name_size, &account_type) == 0) {
errno = ENOENT;
debug("%s: LookupAccountName() failed: %d.", __FUNCTION__, GetLastError());
@ -215,8 +231,8 @@ get_passwd(const wchar_t * user_utf16, PSID sid)
goto cleanup;
}
/* if standard local user name, just use name without decoration */
if (_wcsicmp(domain_name, computer_name) == 0)
/* If standard local user name, just use name without decoration */
if ((_wcsicmp(domain_name, computer_name) == 0))
wcscpy_s(user_resolved, ARRAYSIZE(user_resolved), user_name);
/* put any other format in sam compatible format */

View File

@ -115,8 +115,7 @@ ReadThread(_In_ LPVOID lpParameter)
if (p) {
*p = '\0';
pio->read_details.buf_size = (DWORD)strlen(pio->read_details.buf);
pio->sync_read_status.transferred = pio->read_details.buf_size;
pio->sync_read_status.transferred = (DWORD)strlen(pio->read_details.buf);
}
}
}

View File

@ -42,6 +42,7 @@
#include "tnnet.h"
extern bool gbVTAppMode;
extern BOOL isAnsiParsingRequired;
char *glob_out = NULL;
int glob_outlen = 0;
int glob_space = 0;
@ -139,6 +140,14 @@ ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen)
BOOL bCapsOn = FALSE;
BOOL bShift = FALSE;
int modKey = 0;
char *FN_KEY = NULL;
char *SHIFT_FN_KEY = NULL;
char *ALT_FN_KEY = NULL;
char *CTRL_FN_KEY = NULL;
char *SHIFT_ALT_FN_KEY = NULL;
char *SHIFT_CTRL_FN_KEY = NULL;
char *ALT_CTRL_FN_KEY = NULL;
char *SHIFT_ALT_CTRL_FN_KEY = NULL;
glob_out = destin;
glob_space = destinlen;
@ -353,125 +362,168 @@ ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen)
case VK_CAPITAL:
break; /* NOP on these */
case VK_F1:
/* If isAnsiParsingRequired is false then we use XTERM VT sequence */
FN_KEY = isAnsiParsingRequired ? PF1_KEY : XTERM_PF1_KEY;
SHIFT_FN_KEY = isAnsiParsingRequired ? SHIFT_PF1_KEY : XTERM_SHIFT_PF1_KEY;
ALT_FN_KEY = isAnsiParsingRequired ? ALT_PF1_KEY : XTERM_ALT_PF1_KEY;
CTRL_FN_KEY = isAnsiParsingRequired ? CTRL_PF1_KEY : XTERM_CTRL_PF1_KEY;
SHIFT_ALT_FN_KEY = isAnsiParsingRequired ? SHIFT_ALT_PF1_KEY : XTERM_SHIFT_ALT_PF1_KEY;
SHIFT_CTRL_FN_KEY = isAnsiParsingRequired ? SHIFT_CTRL_PF1_KEY : XTERM_SHIFT_CTRL_PF1_KEY;
ALT_CTRL_FN_KEY = isAnsiParsingRequired ? ALT_CTRL_PF1_KEY : XTERM_ALT_CTRL_PF1_KEY;
SHIFT_ALT_CTRL_FN_KEY = isAnsiParsingRequired ? SHIFT_ALT_CTRL_PF1_KEY : XTERM_SHIFT_ALT_CTRL_PF1_KEY;
if (dwControlKeyState == 0)
NetWriteString2(pParams->Socket, (char *)PF1_KEY, strlen(PF1_KEY), 0);
NetWriteString2(pParams->Socket, (char *)FN_KEY, strlen(FN_KEY), 0);
else if (dwControlKeyState == SHIFT_PRESSED)
NetWriteString2(pParams->Socket, (char *)SHIFT_PF1_KEY, strlen(SHIFT_PF1_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_FN_KEY, strlen(SHIFT_FN_KEY), 0);
else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED)
NetWriteString2(pParams->Socket, (char *)CTRL_PF1_KEY, strlen(CTRL_PF1_KEY), 0);
NetWriteString2(pParams->Socket, (char *)CTRL_FN_KEY, strlen(CTRL_FN_KEY), 0);
else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED)
NetWriteString2(pParams->Socket, (char *)ALT_PF1_KEY, strlen(ALT_PF1_KEY), 0);
NetWriteString2(pParams->Socket, (char *)ALT_FN_KEY, strlen(ALT_FN_KEY), 0);
else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
(dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
(dwControlKeyState & RIGHT_CTRL_PRESSED)))
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF1_KEY, strlen(SHIFT_ALT_CTRL_PF1_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_FN_KEY, strlen(SHIFT_ALT_CTRL_FN_KEY), 0);
else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) &&
((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED)))
NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF1_KEY, strlen(ALT_CTRL_PF1_KEY), 0);
NetWriteString2(pParams->Socket, (char *)ALT_CTRL_FN_KEY, strlen(ALT_CTRL_FN_KEY), 0);
else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
(dwControlKeyState & LEFT_ALT_PRESSED)))
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF1_KEY, strlen(SHIFT_ALT_PF1_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_FN_KEY, strlen(SHIFT_ALT_FN_KEY), 0);
else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
(dwControlKeyState & RIGHT_CTRL_PRESSED)))
NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF1_KEY, strlen(SHIFT_CTRL_PF1_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_FN_KEY, strlen(SHIFT_CTRL_FN_KEY), 0);
break;
case VK_F2:
/* If isAnsiParsingRequired is false then we use XTERM VT sequence */
FN_KEY = isAnsiParsingRequired ? PF2_KEY : XTERM_PF2_KEY;
SHIFT_FN_KEY = isAnsiParsingRequired ? SHIFT_PF2_KEY : XTERM_SHIFT_PF2_KEY;
ALT_FN_KEY = isAnsiParsingRequired ? ALT_PF2_KEY : XTERM_ALT_PF2_KEY;
CTRL_FN_KEY = isAnsiParsingRequired ? CTRL_PF2_KEY : XTERM_CTRL_PF2_KEY;
SHIFT_ALT_FN_KEY = isAnsiParsingRequired ? SHIFT_ALT_PF2_KEY : XTERM_SHIFT_ALT_PF2_KEY;
SHIFT_CTRL_FN_KEY = isAnsiParsingRequired ? SHIFT_CTRL_PF2_KEY : XTERM_SHIFT_CTRL_PF2_KEY;
ALT_CTRL_FN_KEY = isAnsiParsingRequired ? ALT_CTRL_PF2_KEY : XTERM_ALT_CTRL_PF2_KEY;
SHIFT_ALT_CTRL_FN_KEY = isAnsiParsingRequired ? SHIFT_ALT_CTRL_PF2_KEY : XTERM_SHIFT_ALT_CTRL_PF2_KEY;
if (dwControlKeyState == 0)
NetWriteString2(pParams->Socket, (char *)PF2_KEY, strlen(PF2_KEY), 0);
NetWriteString2(pParams->Socket, (char *)FN_KEY, strlen(FN_KEY), 0);
else if (dwControlKeyState == SHIFT_PRESSED)
NetWriteString2(pParams->Socket, (char *)SHIFT_PF2_KEY, strlen(SHIFT_PF2_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_FN_KEY, strlen(SHIFT_FN_KEY), 0);
else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED)
NetWriteString2(pParams->Socket, (char *)CTRL_PF2_KEY, strlen(CTRL_PF2_KEY), 0);
NetWriteString2(pParams->Socket, (char *)CTRL_FN_KEY, strlen(CTRL_FN_KEY), 0);
else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED)
NetWriteString2(pParams->Socket, (char *)ALT_PF2_KEY, strlen(ALT_PF2_KEY), 0);
NetWriteString2(pParams->Socket, (char *)ALT_FN_KEY, strlen(ALT_FN_KEY), 0);
else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
(dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
(dwControlKeyState & RIGHT_CTRL_PRESSED)))
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF2_KEY, strlen(SHIFT_ALT_CTRL_PF2_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_FN_KEY, strlen(SHIFT_ALT_CTRL_FN_KEY), 0);
else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) &&
((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED)))
NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF2_KEY, strlen(ALT_CTRL_PF2_KEY), 0);
NetWriteString2(pParams->Socket, (char *)ALT_CTRL_FN_KEY, strlen(ALT_CTRL_FN_KEY), 0);
else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
(dwControlKeyState & LEFT_ALT_PRESSED)))
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF2_KEY, strlen(SHIFT_ALT_PF2_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_FN_KEY, strlen(SHIFT_ALT_FN_KEY), 0);
else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
(dwControlKeyState & RIGHT_CTRL_PRESSED)))
NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF2_KEY, strlen(SHIFT_CTRL_PF2_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_FN_KEY, strlen(SHIFT_CTRL_FN_KEY), 0);
break;
case VK_F3:
/* If isAnsiParsingRequired is false then we use XTERM VT sequence */
FN_KEY = isAnsiParsingRequired ? PF3_KEY : XTERM_PF3_KEY;
SHIFT_FN_KEY = isAnsiParsingRequired ? SHIFT_PF3_KEY : XTERM_SHIFT_PF3_KEY;
ALT_FN_KEY = isAnsiParsingRequired ? ALT_PF3_KEY : XTERM_ALT_PF3_KEY;
CTRL_FN_KEY = isAnsiParsingRequired ? CTRL_PF3_KEY : XTERM_CTRL_PF3_KEY;
SHIFT_ALT_FN_KEY = isAnsiParsingRequired ? SHIFT_ALT_PF3_KEY : XTERM_SHIFT_ALT_PF3_KEY;
SHIFT_CTRL_FN_KEY = isAnsiParsingRequired ? SHIFT_CTRL_PF3_KEY : XTERM_SHIFT_CTRL_PF3_KEY;
ALT_CTRL_FN_KEY = isAnsiParsingRequired ? ALT_CTRL_PF3_KEY : XTERM_ALT_CTRL_PF3_KEY;
SHIFT_ALT_CTRL_FN_KEY = isAnsiParsingRequired ? SHIFT_ALT_CTRL_PF3_KEY : XTERM_SHIFT_ALT_CTRL_PF3_KEY;
if (dwControlKeyState == 0)
NetWriteString2(pParams->Socket, (char *)PF3_KEY, strlen(PF3_KEY), 0);
NetWriteString2(pParams->Socket, (char *)FN_KEY, strlen(FN_KEY), 0);
else if (dwControlKeyState == SHIFT_PRESSED)
NetWriteString2(pParams->Socket, (char *)SHIFT_PF3_KEY, strlen(SHIFT_PF3_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_FN_KEY, strlen(SHIFT_FN_KEY), 0);
else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED)
NetWriteString2(pParams->Socket, (char *)CTRL_PF3_KEY, strlen(CTRL_PF3_KEY), 0);
NetWriteString2(pParams->Socket, (char *)CTRL_FN_KEY, strlen(CTRL_FN_KEY), 0);
else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED)
NetWriteString2(pParams->Socket, (char *)ALT_PF3_KEY, strlen(ALT_PF3_KEY), 0);
NetWriteString2(pParams->Socket, (char *)ALT_FN_KEY, strlen(ALT_FN_KEY), 0);
else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
(dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
(dwControlKeyState & RIGHT_CTRL_PRESSED)))
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF3_KEY, strlen(SHIFT_ALT_CTRL_PF3_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_FN_KEY, strlen(SHIFT_ALT_CTRL_FN_KEY), 0);
else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) &&
((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED)))
NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF3_KEY, strlen(ALT_CTRL_PF3_KEY), 0);
NetWriteString2(pParams->Socket, (char *)ALT_CTRL_FN_KEY, strlen(ALT_CTRL_FN_KEY), 0);
else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
(dwControlKeyState & LEFT_ALT_PRESSED)))
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF3_KEY, strlen(SHIFT_ALT_PF3_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_FN_KEY, strlen(SHIFT_ALT_FN_KEY), 0);
else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
(dwControlKeyState & RIGHT_CTRL_PRESSED)))
NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF3_KEY, strlen(SHIFT_CTRL_PF3_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_FN_KEY, strlen(SHIFT_CTRL_FN_KEY), 0);
break;
case VK_F4:
/* If isAnsiParsingRequired is false then we use XTERM VT sequence */
FN_KEY = isAnsiParsingRequired ? PF4_KEY : XTERM_PF4_KEY;
SHIFT_FN_KEY = isAnsiParsingRequired ? SHIFT_PF4_KEY : XTERM_SHIFT_PF4_KEY;
ALT_FN_KEY = isAnsiParsingRequired ? ALT_PF4_KEY : XTERM_ALT_PF4_KEY;
CTRL_FN_KEY = isAnsiParsingRequired ? CTRL_PF4_KEY : XTERM_CTRL_PF4_KEY;
SHIFT_ALT_FN_KEY = isAnsiParsingRequired ? SHIFT_ALT_PF4_KEY : XTERM_SHIFT_ALT_PF4_KEY;
SHIFT_CTRL_FN_KEY = isAnsiParsingRequired ? SHIFT_CTRL_PF4_KEY : XTERM_SHIFT_CTRL_PF4_KEY;
ALT_CTRL_FN_KEY = isAnsiParsingRequired ? ALT_CTRL_PF4_KEY : XTERM_ALT_CTRL_PF4_KEY;
SHIFT_ALT_CTRL_FN_KEY = isAnsiParsingRequired ? SHIFT_ALT_CTRL_PF4_KEY : XTERM_SHIFT_ALT_CTRL_PF4_KEY;
if (dwControlKeyState == 0)
NetWriteString2(pParams->Socket, (char *)PF4_KEY, strlen(PF4_KEY), 0);
NetWriteString2(pParams->Socket, (char *)FN_KEY, strlen(FN_KEY), 0);
else if (dwControlKeyState == SHIFT_PRESSED)
NetWriteString2(pParams->Socket, (char *)SHIFT_PF4_KEY, strlen(SHIFT_PF4_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_FN_KEY, strlen(SHIFT_FN_KEY), 0);
else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED)
NetWriteString2(pParams->Socket, (char *)CTRL_PF4_KEY, strlen(CTRL_PF4_KEY), 0);
NetWriteString2(pParams->Socket, (char *)CTRL_FN_KEY, strlen(CTRL_FN_KEY), 0);
else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED)
NetWriteString2(pParams->Socket, (char *)ALT_PF4_KEY, strlen(ALT_PF4_KEY), 0);
NetWriteString2(pParams->Socket, (char *)ALT_FN_KEY, strlen(ALT_FN_KEY), 0);
else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
(dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
(dwControlKeyState & RIGHT_CTRL_PRESSED)))
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF4_KEY, strlen(SHIFT_ALT_CTRL_PF4_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_FN_KEY, strlen(SHIFT_ALT_CTRL_FN_KEY), 0);
else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) &&
((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED)))
NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF4_KEY, strlen(ALT_CTRL_PF4_KEY), 0);
NetWriteString2(pParams->Socket, (char *)ALT_CTRL_FN_KEY, strlen(ALT_CTRL_FN_KEY), 0);
else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
(dwControlKeyState & LEFT_ALT_PRESSED)))
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF4_KEY, strlen(SHIFT_ALT_PF4_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_FN_KEY, strlen(SHIFT_ALT_FN_KEY), 0);
else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
(dwControlKeyState & RIGHT_CTRL_PRESSED)))
NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF4_KEY, strlen(SHIFT_CTRL_PF4_KEY), 0);
NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_FN_KEY, strlen(SHIFT_CTRL_FN_KEY), 0);
break;
case VK_F5:
if (dwControlKeyState == 0)

View File

@ -94,8 +94,8 @@
#define SHIFT_PF8_KEY "\x1b[19;2~"
#define SHIFT_PF9_KEY "\x1b[20;2~"
#define SHIFT_PF10_KEY "\x1b[21;2~"
#define SHIFT_PF11_KEY "\x1b[24;2~"
#define SHIFT_PF12_KEY "\x1b[25;2~"
#define SHIFT_PF11_KEY "\x1b[23;2~"
#define SHIFT_PF12_KEY "\x1b[24;2~"
#define ALT_PF1_KEY "\x1b[11;3~"
#define ALT_PF2_KEY "\x1b[12;3~"
@ -107,21 +107,21 @@
#define ALT_PF8_KEY "\x1b[19;3~"
#define ALT_PF9_KEY "\x1b[20;3~"
#define ALT_PF10_KEY "\x1b[21;3~"
#define ALT_PF11_KEY "\x1b[24;3~"
#define ALT_PF12_KEY "\x1b[25;3~"
#define ALT_PF11_KEY "\x1b[23;3~"
#define ALT_PF12_KEY "\x1b[24;3~"
#define CTRL_PF1_KEY "\x1b[11;4~"
#define CTRL_PF2_KEY "\x1b[12;4~"
#define CTRL_PF3_KEY "\x1b[13;4~"
#define CTRL_PF4_KEY "\x1b[14;4~"
#define CTRL_PF5_KEY "\x1b[15;4~"
#define CTRL_PF6_KEY "\x1b[17;4~"
#define CTRL_PF7_KEY "\x1b[18;4~"
#define CTRL_PF8_KEY "\x1b[19;4~"
#define CTRL_PF9_KEY "\x1b[20;4~"
#define CTRL_PF10_KEY "\x1b[21;4~"
#define CTRL_PF11_KEY "\x1b[24;4~"
#define CTRL_PF12_KEY "\x1b[25;4~"
#define CTRL_PF1_KEY "\x1b[11;5~"
#define CTRL_PF2_KEY "\x1b[12;5~"
#define CTRL_PF3_KEY "\x1b[13;5~"
#define CTRL_PF4_KEY "\x1b[14;5~"
#define CTRL_PF5_KEY "\x1b[15;5~"
#define CTRL_PF6_KEY "\x1b[17;5~"
#define CTRL_PF7_KEY "\x1b[18;5~"
#define CTRL_PF8_KEY "\x1b[19;5~"
#define CTRL_PF9_KEY "\x1b[20;5~"
#define CTRL_PF10_KEY "\x1b[21;5~"
#define CTRL_PF11_KEY "\x1b[23;5~"
#define CTRL_PF12_KEY "\x1b[24;5~"
#define SHIFT_CTRL_PF1_KEY "\x1b[11;6~"
#define SHIFT_CTRL_PF2_KEY "\x1b[12;6~"
@ -133,21 +133,21 @@
#define SHIFT_CTRL_PF8_KEY "\x1b[19;6~"
#define SHIFT_CTRL_PF9_KEY "\x1b[20;6~"
#define SHIFT_CTRL_PF10_KEY "\x1b[21;6~"
#define SHIFT_CTRL_PF11_KEY "\x1b[24;6~"
#define SHIFT_CTRL_PF12_KEY "\x1b[25;6~"
#define SHIFT_CTRL_PF11_KEY "\x1b[23;6~"
#define SHIFT_CTRL_PF12_KEY "\x1b[24;6~"
#define SHIFT_ALT_PF1_KEY "\x1b[11;5~"
#define SHIFT_ALT_PF2_KEY "\x1b[12;5~"
#define SHIFT_ALT_PF3_KEY "\x1b[13;5~"
#define SHIFT_ALT_PF4_KEY "\x1b[14;5~"
#define SHIFT_ALT_PF5_KEY "\x1b[15;5~"
#define SHIFT_ALT_PF6_KEY "\x1b[17;5~"
#define SHIFT_ALT_PF7_KEY "\x1b[18;5~"
#define SHIFT_ALT_PF8_KEY "\x1b[19;5~"
#define SHIFT_ALT_PF9_KEY "\x1b[20;5~"
#define SHIFT_ALT_PF10_KEY "\x1b[21;5~"
#define SHIFT_ALT_PF11_KEY "\x1b[24;5~"
#define SHIFT_ALT_PF12_KEY "\x1b[25;5~"
#define SHIFT_ALT_PF1_KEY "\x1b[11;4~"
#define SHIFT_ALT_PF2_KEY "\x1b[12;4~"
#define SHIFT_ALT_PF3_KEY "\x1b[13;4~"
#define SHIFT_ALT_PF4_KEY "\x1b[14;4~"
#define SHIFT_ALT_PF5_KEY "\x1b[15;4~"
#define SHIFT_ALT_PF6_KEY "\x1b[17;4~"
#define SHIFT_ALT_PF7_KEY "\x1b[18;4~"
#define SHIFT_ALT_PF8_KEY "\x1b[19;4~"
#define SHIFT_ALT_PF9_KEY "\x1b[20;4~"
#define SHIFT_ALT_PF10_KEY "\x1b[21;4~"
#define SHIFT_ALT_PF11_KEY "\x1b[23;4~"
#define SHIFT_ALT_PF12_KEY "\x1b[24;4~"
#define ALT_CTRL_PF1_KEY "\x1b[11;7~"
#define ALT_CTRL_PF2_KEY "\x1b[12;7~"
@ -159,8 +159,8 @@
#define ALT_CTRL_PF8_KEY "\x1b[19;7~"
#define ALT_CTRL_PF9_KEY "\x1b[20;7~"
#define ALT_CTRL_PF10_KEY "\x1b[21;7~"
#define ALT_CTRL_PF11_KEY "\x1b[24;7~"
#define ALT_CTRL_PF12_KEY "\x1b[25;7~"
#define ALT_CTRL_PF11_KEY "\x1b[23;7~"
#define ALT_CTRL_PF12_KEY "\x1b[24;7~"
#define SHIFT_ALT_CTRL_PF1_KEY "\x1b[11;8~"
#define SHIFT_ALT_CTRL_PF2_KEY "\x1b[12;8~"
@ -172,8 +172,49 @@
#define SHIFT_ALT_CTRL_PF8_KEY "\x1b[19;8~"
#define SHIFT_ALT_CTRL_PF9_KEY "\x1b[20;8~"
#define SHIFT_ALT_CTRL_PF10_KEY "\x1b[21;8~"
#define SHIFT_ALT_CTRL_PF11_KEY "\x1b[24;8~"
#define SHIFT_ALT_CTRL_PF12_KEY "\x1b[25;8~"
#define SHIFT_ALT_CTRL_PF11_KEY "\x1b[23;8~"
#define SHIFT_ALT_CTRL_PF12_KEY "\x1b[24;8~"
/* XTERM (https://github.com/mintty/mintty/wiki/Keycodes#function-keys) */
#define XTERM_PF1_KEY "\x1bOP"
#define XTERM_PF2_KEY "\x1bOQ"
#define XTERM_PF3_KEY "\x1bOR"
#define XTERM_PF4_KEY "\x1bOS"
#define XTERM_SHIFT_PF1_KEY "\x1b[1;2P"
#define XTERM_SHIFT_PF2_KEY "\x1b[1;2Q"
#define XTERM_SHIFT_PF3_KEY "\x1b[1;2R"
#define XTERM_SHIFT_PF4_KEY "\x1b[1;2S"
#define XTERM_ALT_PF1_KEY "\x1b[1;3P"
#define XTERM_ALT_PF2_KEY "\x1b[1;3Q"
#define XTERM_ALT_PF3_KEY "\x1b[1;3R"
#define XTERM_ALT_PF4_KEY "\x1b[1;3S"
#define XTERM_CTRL_PF1_KEY "\x1b[1;5P"
#define XTERM_CTRL_PF2_KEY "\x1b[1;5Q"
#define XTERM_CTRL_PF3_KEY "\x1b[1;5R"
#define XTERM_CTRL_PF4_KEY "\x1b[1;5S"
#define XTERM_SHIFT_ALT_PF1_KEY "\x1b[1;4P"
#define XTERM_SHIFT_ALT_PF2_KEY "\x1b[1;4Q"
#define XTERM_SHIFT_ALT_PF3_KEY "\x1b[1;4R"
#define XTERM_SHIFT_ALT_PF4_KEY "\x1b[1;4S"
#define XTERM_SHIFT_CTRL_PF1_KEY "\x1b[1;6P"
#define XTERM_SHIFT_CTRL_PF2_KEY "\x1b[1;6Q"
#define XTERM_SHIFT_CTRL_PF3_KEY "\x1b[1;6R"
#define XTERM_SHIFT_CTRL_PF4_KEY "\x1b[1;6S"
#define XTERM_ALT_CTRL_PF1_KEY "\x1b[1;7P"
#define XTERM_ALT_CTRL_PF2_KEY "\x1b[1;7Q"
#define XTERM_ALT_CTRL_PF3_KEY "\x1b[1;7R"
#define XTERM_ALT_CTRL_PF4_KEY "\x1b[1;7S"
#define XTERM_SHIFT_ALT_CTRL_PF1_KEY "\x1b[1;8P"
#define XTERM_SHIFT_ALT_CTRL_PF2_KEY "\x1b[1;8Q"
#define XTERM_SHIFT_ALT_CTRL_PF3_KEY "\x1b[1;8R"
#define XTERM_SHIFT_ALT_CTRL_PF4_KEY "\x1b[1;8S"
#define TERMINAL_ID "\x1b[?1;2c"
#define STATUS_REPORT "\x1b[2;5R"

View File

@ -78,6 +78,9 @@ char* __progname = "";
char* __progdir = "";
wchar_t* __wprogdir = L"";
/* __progdata */
char* __progdata = "";
wchar_t* __wprogdata = L"";
/* initializes mapping table*/
static int
@ -196,7 +199,7 @@ init_prog_paths()
if ((__wprogdir = _wcsdup(wpgmptr)) == NULL ||
(__progdir = utf16_to_utf8(__wprogdir)) == NULL)
fatal("out of memory");
fatal("%s out of memory", __func__);
__progname = strrchr(__progdir, '\\') + 1;
/* TODO: retain trailing \ at the end of progdir* variants ? */
@ -206,6 +209,16 @@ init_prog_paths()
/* strip .exe off __progname */
*(__progname + strlen(__progname) - 4) = '\0';
/* get %programdata% value */
size_t len = 0;
_dupenv_s(&__progdata, &len, "ProgramData");
if (!__progdata)
fatal("couldn't find ProgramData environment variable");
if(!(__wprogdata = utf8_to_utf16(__progdata)))
fatal("%s out of memory", __func__, __LINE__);
processed = 1;
}
@ -1028,22 +1041,33 @@ spawn_child_internal(char* cmd, char *const argv[], HANDLE in, HANDLE out, HANDL
DWORD cmdline_len = 0;
wchar_t * cmdline_utf16 = NULL;
int add_module_path = 0, ret = -1;
char *path = NULL;
/* should module path be added */
if (!cmd) {
error("%s invalid argument cmd:%s", __func__, cmd);
return -1;
return ret;
}
t = cmd;
if (!is_absolute_path(t) && prepend_module_path)
if (!(path = _strdup(cmd))) {
error("failed to duplicate %s", cmd);
return ret;
}
if (is_bash_test_env()) {
size_t len = strlen(path) + 1;
memset(path, 0, len);
bash_to_win_path(cmd, path, len);
}
if (!is_absolute_path(path) && prepend_module_path)
add_module_path = 1;
/* compute total cmdline len*/
if (add_module_path)
cmdline_len += (DWORD)strlen(__progdir) + 1 + (DWORD)strlen(cmd) + 1 + 2;
cmdline_len += (DWORD)strlen(__progdir) + 1 + (DWORD)strlen(path) + 1 + 2;
else
cmdline_len += (DWORD)strlen(cmd) + 1 + 2;
cmdline_len += (DWORD)strlen(path) + 1 + 2;
if (argv) {
t1 = argv;
@ -1058,19 +1082,34 @@ spawn_child_internal(char* cmd, char *const argv[], HANDLE in, HANDLE out, HANDL
/* add current module path to start if needed */
t = cmdline;
if (argv && argv[0])
*t++ = '\"';
*t++ = '\"';
if (add_module_path) {
memcpy(t, __progdir, strlen(__progdir));
t += strlen(__progdir);
*t++ = '\\';
}
memcpy(t, cmd, strlen(cmd));
t += strlen(cmd);
/* Add double quotes around the executable path
* path can be c:\cygwin64\bin\sh.exe "<e:\openssh\regress\ssh-log-wrapper.sh>"
* Please note that, this logic is not just bash test specific.
*/
const char *exe_extenstion = ".exe";
const char *tmp = NULL;
if ((tmp = strstr(path, exe_extenstion)) && (strlen(tmp) > strlen(exe_extenstion))) {
tmp += strlen(exe_extenstion); /* move the pointer to the end of ".exe" */
memcpy(t, path, strlen(path)-strlen(tmp));
t += strlen(path) - strlen(tmp);
if (argv && argv[0])
*t++ = '\"';
memcpy(t, tmp, strlen(tmp));
t += strlen(tmp);
} else {
memcpy(t, path, strlen(path));
t += strlen(path);
*t++ = '\"';
}
if (argv) {
t1 = argv;
@ -1125,6 +1164,8 @@ cleanup:
free(cmdline);
if (cmdline_utf16)
free(cmdline_utf16);
if (path)
free(path);
return ret;
}

View File

@ -111,7 +111,7 @@ openlog_file()
tail--;
wchar_t ssh_cfg_path[PATH_MAX] = {0 ,};
wcscat_s(ssh_cfg_path, _countof(ssh_cfg_path), get_program_data_path()); /* "%programData%" */
wcscat_s(ssh_cfg_path, _countof(ssh_cfg_path), __wprogdata); /* "%programData%" */
wcscat_s(ssh_cfg_path, _countof(ssh_cfg_path), L"\\ssh"); /* "%programData%\\ssh" */
if ((wcsncat_s(log_file, PATH_MAX + 12, ssh_cfg_path, wcslen(ssh_cfg_path)) != 0) ||

View File

@ -219,9 +219,18 @@ ga_init(const char *user, gid_t base)
user_name = xstrdup(user);
if ((user_token = get_user_token(user_name, 0)) == NULL)
fatal("%s, unable to resolve user %s", __func__, user_name);
if ((user_token = get_user_token(user_name, 0)) == NULL) {
/*
* TODO - We need to fatal() all the times when we fail to generate the user token.
*/
if (get_custom_lsa_package()) {
error("%s, unable to resolve user %s", __func__, user_name);
return 0;
} else {
fatal("%s, unable to resolve user %s", __func__, user_name);
}
}
/*
* supposed to retun number of groups associated with user
* since we do lazy group evaluation, returning 1 here

View File

@ -73,18 +73,26 @@ CreateConPty(const wchar_t *cmdline,
debug3("pty commandline: %ls", conhostCmdline);
/*
* process CTRL+C input.
* Child processes will inherit this behavior.
*/
SetConsoleCtrlHandler(NULL, FALSE);
if (0 == CreateProcessW(NULL, conhostCmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, piPty)) {
debug("%s - failed to execute %ls, error:%d", __func__, conhostCmdline, GetLastError());
errno = EOTHER;
return -1;
}
/* disable Ctrl+C hander in this process*/
SetConsoleCtrlHandler(NULL, TRUE);
return 0;
}
int is_conpty_supported()
{
/* TODO - enable this once conpty changes are validated */
/* TODO - put conditional logic in here that determines if conpty is supported */
return 0;
}

View File

@ -81,8 +81,8 @@ static VOID WINAPI service_handler(DWORD dwControl)
case SERVICE_CONTROL_STOP: {
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 500);
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
/* TOTO - GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); doesn't seem to be invoking
* signal handler (native_sig_handler) when sshd runs as service
/* TODO - GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); doesn't seem to be invoking
* signal handler (native_sig_handler) when sshd runs as service
* So calling the signal handler directly to interrupt the deamon's main thread
* This is being called after reporting SERVICE_STOPPED because main thread does a exit()
* as part of handling Crtl+c
@ -100,7 +100,7 @@ static VOID WINAPI service_handler(DWORD dwControl)
}
#define SSH_HOSTKEY_GEN_CMDLINE L"ssh-keygen -A"
static void
static void
generate_host_keys()
{
DWORD dwError = 0;
@ -162,12 +162,12 @@ generate_host_keys()
* 2) Create %programdata%\ssh\logs - Administrator group(F), system(F)
* 3) copy <binary_location>\sshd_config_default to %programdata%\ssh\sshd_config
*/
static void
static void
create_prgdata_ssh_folder()
{
/* create ssh cfg folder */
wchar_t ssh_cfg_dir[PATH_MAX] = { 0, };
wcscpy_s(ssh_cfg_dir, _countof(ssh_cfg_dir), get_program_data_path());
wcscpy_s(ssh_cfg_dir, _countof(ssh_cfg_dir), __wprogdata);
wcscat_s(ssh_cfg_dir, _countof(ssh_cfg_dir), L"\\ssh");
if (create_directory_withsddl(ssh_cfg_dir, L"O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;AU)") < 0) {
printf("failed to create %s", ssh_cfg_dir);
@ -228,7 +228,7 @@ create_openssh_registry_key()
static void
prereq_setup()
{
{
create_prgdata_ssh_folder();
generate_host_keys();
create_openssh_registry_key();
@ -251,7 +251,7 @@ int sshd_main(int argc, wchar_t **wargv) {
w32posix_initialize();
r = main(argc, argv);
r = main(argc, argv);
w32posix_done();
return r;
}
@ -263,7 +263,7 @@ int wmain(int argc, wchar_t **wargv) {
wchar_t* path_utf16;
argc_original = argc;
wargv_original = wargv;
init_prog_paths();
/* change current directory to sshd.exe root */
_wchdir(__wprogdir);
@ -287,5 +287,3 @@ int scm_start_service(DWORD num, LPWSTR* args) {
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
return sshd_main(argc_original, wargv_original);
}

10
misc.c
View File

@ -784,6 +784,16 @@ parse_uri(const char *scheme, const char *uri, char **userp, char **hostp,
if ((cp = strchr(tmp, '@')) != NULL) {
char *delim;
#ifdef WINDOWS
/* TODO - This looks to be a core bug in unix code as user can be in UPN format
* The above line should be strrchr() instead of strchr.
* For time being, special handling when username is in User@domain format
*/
char *cp_1 = cp;
if ((cp_1 = strchr(cp + 1, '@')) != NULL)
cp = cp_1;
#endif
*cp = '\0';
/* Extract username and connection params */
if ((delim = strchr(tmp, ';')) != NULL) {

View File

@ -1661,6 +1661,43 @@ monitor_clear_keystate(struct monitor *pmonitor)
child_state = NULL;
}
void
monitor_send_authopt(struct monitor *pmonitor, int untrusted) {
struct sshbuf *m = NULL;
int r = 0;
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if (auth_opts != NULL && (r = sshauthopt_serialise(auth_opts, m, untrusted)) != 0)
fatal("%s: sshauthopt_serialise: %s", __func__, ssh_err(r));
if (ssh_msg_send(pmonitor->m_sendfd, 0, m) == -1)
fatal("%s: ssh_msg_send failed", __func__);
sshbuf_free(m);
}
void
monitor_recv_authopt(struct monitor*pmonitor) {
Buffer m;
int r = 0;
buffer_init(&m);
if (ssh_msg_recv(pmonitor->m_recvfd, &m) == -1)
fatal("%s: ssh_msg_recv failed", __func__);
if (buffer_get_char(&m) != 0)
fatal("%s: version mismatch", __func__);
if ((r = sshauthopt_deserialise(&m, &auth_opts)) != 0)
fatal("%s: sshauthopt_deserialise: %s",
__func__, ssh_err(r));
buffer_free(&m);
}
void
monitor_apply_keystate(struct monitor *pmonitor)
{
@ -1889,3 +1926,4 @@ mm_answer_gss_userok(int sock, Buffer *m)
}
#endif /* GSSAPI */

View File

@ -480,11 +480,18 @@ default_ssh_port(void)
static int
execute_in_shell(const char *cmd)
{
char *shell;
#ifdef WINDOWS
fatal("LocalCommand execution is not supported on Windows yet");
return 0;
int retVal = -1;
wchar_t *cmd_w = utf8_to_utf16(cmd);
if (cmd_w) {
retVal = _wsystem(cmd_w);
free(cmd_w);
}
return retVal;
#else /* !WINDOWS */
char *shell;
pid_t pid;
int devnull, status;
extern uid_t original_real_uid;

5
regress/.gitattributes vendored Normal file
View File

@ -0,0 +1,5 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Declare files that will always have LF line endings on checkout.
*.sh text eol=lf

View File

@ -14,6 +14,9 @@ run_trial()
result=`${SSHD} -f $OBJ/sshd_proxy -T \
-C user=${user},addr=${addr},host=${host},laddr=${laddr},lport=${lport} | \
awk '/^forcecommand/ {print $2}'`
if [ "$os" == "windows" ]; then
result=${result/$'\r'/} # remove CR (carriage return)
fi
if [ "$result" != "$expected" ]; then
fail "failed '$descr' expected $expected got $result"
fi

View File

@ -2,7 +2,10 @@
# Placed in the Public Domain.
tid="agent timeout test"
if [ "$os" == "windows" ]; then
echo "skipped (not supported on WINDOWS platform)"
exit 0
fi
SSHAGENT_TIMEOUT=10
trace "start agent"

View File

@ -14,7 +14,11 @@ r=$?
if [ $r -ne 0 ]; then
fatal "could not start ssh-agent: exit code $r"
fi
if [ "$os" == "windows" ]; then
#windows ssh-agent doesn't support "-s" option so we need to set SSH_AUTH_SOCK env here.
SSH_AUTH_SOCK="\\\\.\\pipe\\openssh-ssh-agent"
${SSHADD} -D
fi
${SSHADD} -l > /dev/null 2>&1
if [ $? -ne 1 ]; then
fail "ssh-add -l did not fail with exit code 1"

View File

@ -30,9 +30,18 @@ for s in 0 10 100 1000 10000 100000 ; do
trace "test banner size $s"
verbose "test $tid: size $s"
( ${SSH} -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \
cmp $OBJ/banner.in $OBJ/banner.out ) || \
fail "banner size $s mismatch"
if [ "$os" == "windows" ]; then
# For windows, compare files by ignoring line breaks (CR vs CRLF).
# CYGWIN created files (banner.in) will have CR.
# SSH output files (banner.out) will have CRLF.
( ${SSH} -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \
diff --strip-trailing-cr $OBJ/banner.in $OBJ/banner.out ) || \
fail "banner size $s mismatch"
else
( ${SSH} -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \
cmp $OBJ/banner.in $OBJ/banner.out ) || \
fail "banner size $s mismatch"
fi
done
trace "test suppress banner (-q)"

View File

@ -9,6 +9,9 @@ rm -f $OBJ/cert_host_key* $OBJ/host_krl_*
# Allow all hostkey/pubkey types, prefer certs for the client
types=""
for i in `$SSH -Q key`; do
if [ "$os" == "windows" ]; then
i=${i/$'\r'/} # remove CR (carriage return)
fi
if [ -z "$types" ]; then
types="$i"
continue
@ -59,7 +62,12 @@ touch $OBJ/host_revoked_plain
touch $OBJ/host_revoked_cert
cat $OBJ/host_ca_key.pub $OBJ/host_ca_key2.pub > $OBJ/host_revoked_ca
PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'`
if [ "$os" == "windows" ]; then
# remove CR (carriage return)
PLAIN_TYPES=`$SSH -Q key-plain | sed 's/\r$//' | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'`
else
PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'`
fi
if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then
PLAIN_TYPES="$PLAIN_TYPES rsa-sha2-256 rsa-sha2-512"

View File

@ -6,8 +6,12 @@ tid="certified user keys"
rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
if [ "$os" == "windows" ]; then
# remove CR (carriage return)
PLAIN_TYPES=`$SSH -Q key-plain | sed 's/\r$//' | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
else
PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
fi
EXTRA_TYPES=""
if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then

View File

@ -86,9 +86,17 @@ _EOF
trial() {
_host="$1"
_exp="$2"
if [ "$os" == "windows" ]; then
# Fix the file permissions (ACLs)
OBJ_WIN=`windows_path $OBJ`
powershell.exe /c "get-acl $OBJ_WIN/authorized_keys_$USER | set-acl $OBJ_WIN/ssh_config.i.*"
fi
${REAL_SSH} -F $OBJ/ssh_config.i -G "$_host" > $OBJ/ssh_config.out ||
fatal "ssh config parse failed"
_got=`grep -i '^hostname ' $OBJ/ssh_config.out | awk '{print $2}'`
if [ "$os" == "windows" ]; then
_got=`echo $_got | sed 's/\r$//'` # remove CR (carriage return)
fi
if test "x$_exp" != "x$_got" ; then
fail "host $_host include fail: expected $_exp got $_got"
fi
@ -227,9 +235,18 @@ _EOF
trial() {
_host="$1"
_exp="$2"
if [ "$os" == "windows" ]; then
OBJ_WIN=`windows_path $OBJ`
# Fix the file permissions (ACLs)
powershell.exe /c "get-acl $OBJ_WIN/authorized_keys_$USER | set-acl $OBJ_WIN/ssh_config.i.*"
fi
${REAL_SSH} -F $OBJ/ssh_config.i -G "$_host" > $OBJ/ssh_config.out ||
fatal "ssh config parse failed"
_got=`grep -i '^hostname ' $OBJ/ssh_config.out | awk '{print $2}'`
if [ "$os" == "windows" ]; then
# remove CR (carriage return)
_got=`echo $_got | sed 's/\r$//'`
fi
if test "x$_exp" != "x$_got" ; then
fail "host $_host include fail: expected $_exp got $_got"
fi

View File

@ -23,19 +23,30 @@ start_client()
sleep 1
n=`expr $n + 1`
if test $n -gt 60; then
kill $client_pid
if [ "$os" == "windows" ]; then
# We can't kill windows process from cygwin / wsl so use "stop-process"
powershell.exe /c "stop-process -id $client_pid"
else
kill $client_pid
fi
fatal "timeout waiting for background ssh"
fi
done
done
}
stop_client()
{
pid=`cat $pidfile`
if [ ! -z "$pid" ]; then
kill $pid
if [ "$os" == "windows" ]; then
# We can't kill windows process from cygwin / wsl so use "stop-process"
powershell.exe /c "stop-process -id $pid"
powershell.exe /c "stop-process -name sleep"
else
if [ ! -z "$pid" ]; then
kill $pid
fi
wait
fi
wait
}
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
@ -46,7 +57,13 @@ echo "PermitOpen 127.0.0.1:2 127.0.0.1:3 127.0.0.1:$PORT" >>$OBJ/sshd_config
grep -v AuthorizedKeysFile $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
echo "AuthorizedKeysFile /dev/null" >>$OBJ/sshd_proxy
echo "PermitOpen 127.0.0.1:1" >>$OBJ/sshd_proxy
echo "Match user $USER" >>$OBJ/sshd_proxy
if [ "$os" == "windows" ]; then
# If User is domainuser then it will be in "domain/user" so convert it to "domain\user"
echo "Match user ${USER//\//\\}" >>$OBJ/sshd_proxy
else
echo "Match user $USER" >>$OBJ/sshd_proxy
fi
echo "AuthorizedKeysFile /dev/null $OBJ/authorized_keys_%u" >>$OBJ/sshd_proxy
echo "Match Address 127.0.0.1" >>$OBJ/sshd_proxy
echo "PermitOpen 127.0.0.1:2 127.0.0.1:3 127.0.0.1:$PORT" >>$OBJ/sshd_proxy
@ -91,7 +108,12 @@ stop_client
cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
echo "PermitOpen 127.0.0.1:1 127.0.0.1:$PORT 127.0.0.2:2" >>$OBJ/sshd_proxy
echo "Match User $USER" >>$OBJ/sshd_proxy
if [ "$os" == "windows" ]; then
# If User is domainuser then it will be in "domain/user" so convert it to "domain\user"
echo "Match user ${USER//\//\\}" >>$OBJ/sshd_proxy
else
echo "Match user $USER" >>$OBJ/sshd_proxy
fi
echo "PermitOpen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy
# Test that a Match overrides a PermitOpen in the global section

View File

@ -49,11 +49,18 @@ EOD
[ X${SKIP_IPV6} = Xyes ] || cat >> $OBJ/sshd_config.1 <<EOD
listenaddress ::1
EOD
($SUDO ${SSHD} -T -f $OBJ/sshd_config.1 | \
grep 'listenaddress ' >$OBJ/sshd_config.2 &&
diff $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \
fail "listenaddress order 1"
if [ "$os" == "windows" ]; then
# Ignore the CR (carriage return) during diff
($SUDO ${SSHD} -T -f $OBJ/sshd_config.1 | \
grep 'listenaddress ' >$OBJ/sshd_config.2 &&
diff --strip-trailing-cr $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \
fail "listenaddress order 1"
else
($SUDO ${SSHD} -T -f $OBJ/sshd_config.1 | \
grep 'listenaddress ' >$OBJ/sshd_config.2 &&
diff $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \
fail "listenaddress order 1"
fi
# test 2: listenaddress first
cat > $OBJ/sshd_config.1 <<EOD
${SSHD_KEYS}
@ -65,11 +72,18 @@ EOD
[ X${SKIP_IPV6} = Xyes ] || cat >> $OBJ/sshd_config.1 <<EOD
listenaddress ::1
EOD
($SUDO ${SSHD} -T -f $OBJ/sshd_config.1 | \
grep 'listenaddress ' >$OBJ/sshd_config.2 &&
diff $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \
fail "listenaddress order 2"
if [ "$os" == "windows" ]; then
# Ignore the CR (carriage return) during diff
($SUDO ${SSHD} -T -f $OBJ/sshd_config.1 | \
grep 'listenaddress ' >$OBJ/sshd_config.2 &&
diff --strip-trailing-cr $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \
fail "listenaddress order 2"
else
($SUDO ${SSHD} -T -f $OBJ/sshd_config.1 | \
grep 'listenaddress ' >$OBJ/sshd_config.2 &&
diff $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \
fail "listenaddress order 2"
fi
# cleanup
rm -f $OBJ/sshd_config.[012]

View File

@ -3,6 +3,12 @@
tid="dynamic forwarding"
if [ "$os" == "windows" ]; then
# Windows, ssh.exe -S option is not supported on windows
echo "skipped, not applicable on windows OS"
exit 0
fi
FWDPORT=`expr $PORT + 1`
if have_prog nc && nc -h 2>&1 | grep "proxy address" >/dev/null; then

View File

@ -2,6 +2,11 @@
# Placed in the Public Domain.
tid="environment passing"
if [ "$os" == "windows" ]; then
# Windows, ssh client hungs.. To be investigated..
echo "skipped, not applicable on windows OS"
exit 0
fi
# NB accepted env vars are in test-exec.sh (_XXX_TEST_* and _XXX_TEST)

View File

@ -28,7 +28,12 @@ ${SSH} -F $OBJ/ssh_proxy somehost false || fail "forced command in key"
cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
echo "ForceCommand false" >> $OBJ/sshd_proxy
echo "Match User $USER" >> $OBJ/sshd_proxy
if [ "$os" == "windows" ]; then
# If User is domainuser then it will be in "domain/user" so convert it to "domain\user"
echo "Match user ${USER//\//\\}" >>$OBJ/sshd_proxy
else
echo "Match User $USER" >>$OBJ/sshd_proxy
fi
echo " ForceCommand true" >> $OBJ/sshd_proxy
trace "forced command with match"

View File

@ -3,6 +3,12 @@
tid="local and remote forwarding"
if [ "$os" == "windows" ]; then
# Windows, ssh.exe -S option is not supported on windows
echo "skipped, not applicable on windows OS"
exit 0
fi
DATA=/bin/ls${EXEEXT}
start_sshd

View File

@ -4,7 +4,14 @@
tid="expand %h and %n"
echo 'PermitLocalCommand yes' >> $OBJ/ssh_proxy
printf 'LocalCommand printf "%%%%s\\n" "%%n" "%%h"\n' >> $OBJ/ssh_proxy
if [ "$os" == "windows" ]; then
# Use bash shell for local command execution as the default shell in windows is cmd.exe
printf 'LocalCommand ' >> $OBJ/ssh_proxy
printf $TEST_SHELL_PATH >> $OBJ/ssh_proxy
printf ' -c "printf \\"%%%%s\\n\\" \\"%%n\\" \\"%%h\\""\n' >> $OBJ/ssh_proxy
else
printf 'LocalCommand printf "%%%%s\\n" "%%n" "%%h"\n' >> $OBJ/ssh_proxy
fi
cat >$OBJ/expect <<EOE
somehost

View File

@ -11,10 +11,19 @@ r=$?
[ $r -ne 0 ] && fatal "could not start ssh-agent: exit code $r"
grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig
if [ "$os" == "windows" ]; then
# Windows ssh-agent doesn't support "-s" option so we need to set SSH_AUTH_SOCK env here.
SSH_AUTH_SOCK="\\\\.\\pipe\\openssh-ssh-agent"
${SSHADD} -D
fi
echo "HostKeyAgent $SSH_AUTH_SOCK" >> $OBJ/sshd_proxy.orig
trace "load hostkeys"
for k in `${SSH} -Q key-plain` ; do
if [ "$os" == "windows" ]; then
k=${k/$'\r'/} # remove CR (carriage return)
fi
${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k"
(
printf 'localhost-with-alias,127.0.0.1,::1 '
@ -32,6 +41,9 @@ unset SSH_AUTH_SOCK
for ps in no yes; do
for k in `${SSH} -Q key-plain` ; do
if [ "$os" == "windows" ]; then
k=${k/$'\r'/} # remove CR (carriage return)
fi
verbose "key type $k privsep=$ps"
cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy
@ -48,6 +60,10 @@ for ps in no yes; do
done
done
if [ "$os" == "windows" ]; then
#keys added through ssh-add are stored in windows registry so delete them.
${SSHADD} -D
fi
trace "kill agent"
${SSHAGENT} -k > /dev/null

View File

@ -16,6 +16,9 @@ trace "prepare hostkeys"
nkeys=0
all_algs=""
for k in `${SSH} -Q key-plain` ; do
if [ "$os" == "windows" ]; then
k=`echo $k | sed 's/\r$//'` # remove CR (carriage return)
fi
${SSHKEYGEN} -qt $k -f $OBJ/hkr.$k -N '' || fatal "ssh-keygen $k"
echo "Hostkey $OBJ/hkr.${k}" >> $OBJ/sshd_proxy.orig
nkeys=`expr $nkeys + 1`
@ -63,6 +66,9 @@ check_key_present ssh-rsa || fail "didn't learn keys"
# Check each key type
for k in `${SSH} -Q key-plain` ; do
if [ "$os" == "windows" ]; then
k=`echo $k | sed 's/\r$//'` # remove CR (carriage return)
fi
verbose "learn additional hostkeys, type=$k"
dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$k,$all_algs
expect_nkeys $nkeys "learn hostkeys $k"

View File

@ -7,10 +7,17 @@ cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
# start at byte 2900 (i.e. after kex) and corrupt at different offsets
tries=10
startoffset=2900
macs=`${SSH} -Q mac`
# The following are not MACs, but ciphers with integrated integrity. They are
# handled specially below.
macs="$macs `${SSH} -Q cipher-auth`"
if [ "$os" == "windows" ]; then
# remove CR (Carriage return)
macs=`${SSH} -Q mac | sed 's/\r$//'`
macs="$macs `${SSH} -Q cipher-auth | sed 's/\r$//'`"
else
macs=`${SSH} -Q mac`
macs="$macs `${SSH} -Q cipher-auth`"
fi
# avoid DH group exchange as the extra traffic makes it harder to get the
# offset into the stream right.
@ -28,7 +35,12 @@ for m in $macs; do
etmo=0
ecnt=0
skip=0
for off in `jot $tries $startoffset`; do
if [ "$os" == "windows" ]; then
offsets=$(seq $startoffset 1 $((startoffset+tries))) # use seq instead of jot
else
offsets=`jot $tries $startoffset`
fi
for off in $offsets; do
skip=`expr $skip - 1`
if [ $skip -gt 0 ]; then
# avoid modifying the high bytes of the length

View File

@ -8,12 +8,21 @@ cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
# Make server accept all key exchanges.
ALLKEX=`${SSH} -Q kex`
if [ "$os" == "windows" ]; then
# Remove CR (carriage return)
ALLKEX=`${SSH} -Q kex | sed 's/\r$//'`
else
ALLKEX=`${SSH} -Q kex`
fi
KEXOPT=`echo $ALLKEX | tr ' ' ,`
echo "KexAlgorithms=$KEXOPT" >> $OBJ/sshd_proxy
tries="1 2 3 4"
for k in `${SSH} -Q kex`; do
if [ "$os" == "windows" ]; then
k=${k/$'\r'/} # Remove CR (carriage return)
fi
verbose "kex $k"
for i in $tries; do
${SSH} -F $OBJ/ssh_proxy -o KexAlgorithms=$k x true

View File

@ -6,7 +6,11 @@ tid="change passphrase for key"
S1="secret1"
S2="2secret"
KEYTYPES=`${SSH} -Q key-plain`
if [ "$os" == "windows" ]; then
KEYTYPES=`${SSH} -Q key-plain | sed 's/\r$//'` # remove CR (carriage return)
else
KEYTYPES=`${SSH} -Q key-plain`
fi
for t in $KEYTYPES; do
# generate user key for agent

View File

@ -25,9 +25,14 @@ for t in rsa dsa; do
fail "$t import rfc4716 public"
cut -f1,2 -d " " $OBJ/$t-key.pub >$OBJ/$t-key-nocomment.pub
cmp $OBJ/$t-key-nocomment.pub $OBJ/$t-rfc-imported || \
fail "$t imported differs from original"
if [ "$os" == "windows" ]; then
# Ignore CR (carriage return) while comparing files
diff --strip-trailing-cr $OBJ/$t-key-nocomment.pub $OBJ/$t-rfc-imported || \
fail "$t imported differs from original"
else
cmp $OBJ/$t-key-nocomment.pub $OBJ/$t-rfc-imported || \
fail "$t imported differs from original"
fi
rm -f $OBJ/$t-key $OBJ/$t-key.pub $OBJ/$t-key-rfc $OBJ/$t-key-rfc.pub \
$OBJ/$t-rfc-imported $OBJ/$t-key-nocomment.pub
done

View File

@ -135,47 +135,87 @@ check_hashed_find host-h "find multiple hosts"
# Attempt remove key on invalid file.
cp $OBJ/kh.invalid.orig $OBJ/kh.invalid
${SSHKEYGEN} -qf $OBJ/kh.invalid -R host-a 2>/dev/null
diff $OBJ/kh.invalid $OBJ/kh.invalid.orig || fail "remove on invalid succeeded"
if [ "$os" == "windows" ]; then
# Ignore CR (carriage return) while comparing files
diff --strip-trailing-cr $OBJ/kh.invalid $OBJ/kh.invalid.orig || fail "remove on invalid succeeded"
else
diff $OBJ/kh.invalid $OBJ/kh.invalid.orig || fail "remove on invalid succeeded"
fi
# Remove key
cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-a 2>/dev/null
grep -v "^host-a " $OBJ/kh.hosts.orig > $OBJ/kh.expect
diff $OBJ/kh.hosts $OBJ/kh.expect || fail "remove simple"
if [ "$os" == "windows" ]; then
# Ignore CR (carriage return) while comparing files
diff --strip-trailing-cr $OBJ/kh.hosts $OBJ/kh.expect || fail "remove simple"
else
diff $OBJ/kh.hosts $OBJ/kh.expect || fail "remove simple"
fi
# Remove CA key
cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-c 2>/dev/null
# CA key should not be removed.
diff $OBJ/kh.hosts $OBJ/kh.hosts.orig || fail "remove CA"
if [ "$os" == "windows" ]; then
# Ignore CR (carriage return) while comparing files
diff --strip-trailing-cr $OBJ/kh.hosts $OBJ/kh.hosts.orig || fail "remove CA"
else
diff $OBJ/kh.hosts $OBJ/kh.hosts.orig || fail "remove CA"
fi
# Remove revoked key
cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-d 2>/dev/null
# revoked key should not be removed.
diff $OBJ/kh.hosts $OBJ/kh.hosts.orig || fail "remove revoked"
if [ "$os" == "windows" ]; then
# Ignore CR (carriage return) while comparing files
diff --strip-trailing-cr $OBJ/kh.hosts $OBJ/kh.hosts.orig || fail "remove revoked"
else
diff $OBJ/kh.hosts $OBJ/kh.hosts.orig || fail "remove revoked"
fi
# Remove wildcard
cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-e.blahblah 2>/dev/null
grep -v "^host-e[*] " $OBJ/kh.hosts.orig > $OBJ/kh.expect
diff $OBJ/kh.hosts $OBJ/kh.expect || fail "remove wildcard"
if [ "$os" == "windows" ]; then
# Ignore CR (carriage return) while comparing files
diff --strip-trailing-cr $OBJ/kh.hosts $OBJ/kh.expect || fail "remove wildcard"
else
diff $OBJ/kh.hosts $OBJ/kh.expect || fail "remove wildcard"
fi
# Remove multiple
cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-h 2>/dev/null
grep -v "^host-f," $OBJ/kh.hosts.orig > $OBJ/kh.expect
diff $OBJ/kh.hosts $OBJ/kh.expect || fail "remove wildcard"
if [ "$os" == "windows" ]; then
# Ignore CR (carriage return) while comparing files
diff --strip-trailing-cr $OBJ/kh.hosts $OBJ/kh.expect || fail "remove wildcard"
else
diff $OBJ/kh.hosts $OBJ/kh.expect || fail "remove wildcard"
fi
# Attempt hash on invalid file
cp $OBJ/kh.invalid.orig $OBJ/kh.invalid
${SSHKEYGEN} -qf $OBJ/kh.invalid -H 2>/dev/null && fail "hash invalid succeeded"
diff $OBJ/kh.invalid $OBJ/kh.invalid.orig || fail "invalid file modified"
if [ "$os" == "windows" ]; then
# Ignore CR (carriage return) while comparing files
diff --strip-trailing-cr $OBJ/kh.invalid $OBJ/kh.invalid.orig || fail "invalid file modified"
else
diff $OBJ/kh.invalid $OBJ/kh.invalid.orig || fail "invalid file modified"
fi
# Hash valid file
cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
${SSHKEYGEN} -qf $OBJ/kh.hosts -H 2>/dev/null || fail "hash failed"
diff $OBJ/kh.hosts.old $OBJ/kh.hosts.orig || fail "backup differs"
if [ "$os" == "windows" ]; then
# Ignore CR (carriage return) while comparing files
diff --strip-trailing-cr $OBJ/kh.hosts.old $OBJ/kh.hosts.orig || fail "backup differs"
else
diff $OBJ/kh.hosts.old $OBJ/kh.hosts.orig || fail "backup differs"
fi
grep "^host-[abfgh]" $OBJ/kh.hosts && fail "original hostnames persist"
cp $OBJ/kh.hosts $OBJ/kh.hashed.orig

View File

@ -8,7 +8,12 @@ rm -f ${OBJ}/host.dsa
start_sshd
KEYTYPES=`${SSH} -Q key-plain`
if [ "$os" == "windows" ]; then
# Remove CR (carriage return)
KEYTYPES=`${SSH} -Q key-plain | sed 's/\r$//'`
else
KEYTYPES=`${SSH} -Q key-plain`
fi
for t in $KEYTYPES; do
trace "keyscan type $t"
${SSHKEYSCAN} -t $t -p $PORT 127.0.0.1 127.0.0.1 127.0.0.1 \

View File

@ -46,7 +46,12 @@ EOF
# A specification that revokes some certificated by key ID.
touch $OBJ/revoked-keyid
for n in 1 2 3 4 10 15 30 50 `jot 500 300` 999 1000 1001 1002; do
if [ "$os" == "windows" ]; then
revokedids=$(seq 300 1 $((500+300))) # use seq instead of jot
else
revokedids=`jot 500 300`
fi
for n in 1 2 3 4 10 15 30 50 $revokedids 999 1000 1001 1002; do
test "x$n" = "x499" && continue
# Fill in by-ID revocation spec.
echo "id: revoked $n" >> $OBJ/revoked-keyid

View File

@ -90,8 +90,15 @@ ${SSH} $opts -i $OBJ/user_key2 proxy true || fatal "key2 failed"
# Allow only DSA in main config, Ed25519 for user.
verbose "match w/ matching"
prepare_config "PubkeyAcceptedKeyTypes ssh-dss" \
"Match user $USER" "PubkeyAcceptedKeyTypes +ssh-ed25519"
if [ "$os" == "windows" ]; then
# If User is domainuser then it will be in "domain/user" so convert it to "domain\user"
prepare_config "PubkeyAcceptedKeyTypes ssh-dss" \
"Match user ${USER//\//\\}" "PubkeyAcceptedKeyTypes +ssh-ed25519"
else
prepare_config "PubkeyAcceptedKeyTypes ssh-dss" \
"Match user $USER" "PubkeyAcceptedKeyTypes +ssh-ed25519"
fi
${SSH} $certopts proxy true || fatal "cert failed"
${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed"
${SSH} $opts -i $OBJ/user_key4 proxy true && fatal "key4 succeeded"

View File

@ -8,6 +8,11 @@ echo 'LocalCommand echo foo' >> $OBJ/ssh_proxy
verbose "test $tid: proto $p localcommand"
a=`${SSH} -F $OBJ/ssh_proxy somehost true`
if [ "$os" == "windows" ]; then
a=`echo $a | tr -d '\r\n'` # Remove CR (carriage return)
fi
if [ "$a" != "foo" ] ; then
fail "$tid proto $p"
fi

View File

@ -5,6 +5,13 @@ CTL=/tmp/openssh.regress.ctl-sock.$$
tid="connection multiplexing"
if [ "$os" == "windows" ]; then
# Windows, ssh.exe -S option is not supported on windows
echo "skipped, not applicable on windows OS"
exit 0
fi
NC=$OBJ/netcat
trace "will use ProxyCommand $proxycmd"

View File

@ -2,7 +2,12 @@
# Placed in the Public Domain.
tid="simple connect after reconfigure"
if [ "$os" == "windows" ]; then
# In windows, sshd service process will not restart if we kill it.
# This test case is not applicable to windows OS.
echo "skipped, not applicable on windows OS"
exit 0
fi
# we need the full path to sshd for -HUP
if test "x$USE_VALGRIND" = "x" ; then
case $SSHD in

View File

@ -40,8 +40,8 @@ stop_sshd
cp $OBJ/sshd_config.orig $OBJ/sshd_config
# cygwin can't fork a deleted binary
if [ "$os" != "cygwin" ]; then
# cygwin, windows can't fork a deleted binary
if [ "$os" != "cygwin" ] && [ "$os" != "windows" ]; then
verbose "test reexec fallback"

View File

@ -21,7 +21,11 @@ ssh_data_rekeying()
fi
rm -f ${COPY} ${LOG}
_opts="$_opts -oCompression=no"
${SSH} <${DATA} $_opts -v -F $OBJ/ssh_proxy somehost "cat > ${COPY}"
if [ "$os" == "windows" ]; then
cat ${DATA} | ${SSH} $_opts -v -F $OBJ/ssh_proxy somehost "cat > ${COPY}"
else
${SSH} <${DATA} $_opts -v -F $OBJ/ssh_proxy somehost "cat > ${COPY}"
fi
if [ $? -ne 0 ]; then
fail "ssh failed ($@)"
fi
@ -70,8 +74,13 @@ done
for s in 5 10; do
verbose "client rekeylimit default ${s}"
rm -f ${COPY} ${LOG}
${SSH} < ${DATA} -oCompression=no -oRekeyLimit="default $s" -F \
$OBJ/ssh_proxy somehost "cat >${COPY};sleep $s;sleep 3"
if [ "$os" == "windows" ]; then
cat ${DATA} | ${SSH} -oCompression=no -oRekeyLimit="default $s" -F \
$OBJ/ssh_proxy somehost "cat >${COPY};sleep $s;sleep 3"
else
${SSH} < ${DATA} -oCompression=no -oRekeyLimit="default $s" -F \
$OBJ/ssh_proxy somehost "cat >${COPY};sleep $s;sleep 3"
fi
if [ $? -ne 0 ]; then
fail "ssh failed"
fi
@ -159,7 +168,9 @@ for size in 16 1k 1K 1m 1M 1g 1G 4G 8G; do
awk '/rekeylimit/{print $2}'`
s=`$SUDO ${SSHD} -T -o "rekeylimit $size $time" -f $OBJ/sshd_proxy | \
awk '/rekeylimit/{print $3}'`
if [ "$os" == "windows" ]; then
s=${s/$'\r'/} # Remove CR (carriage return)
fi
if [ "$bytes" != "$b" ]; then
fatal "rekeylimit size: expected $bytes bytes got $b"
fi

View File

@ -11,8 +11,13 @@ DIR2=${COPY}.dd2
SRC=`dirname ${SCRIPT}`
cp ${SRC}/scp-ssh-wrapper.sh ${OBJ}/scp-ssh-wrapper.scp
chmod 755 ${OBJ}/scp-ssh-wrapper.scp
scpopts="-q -S ${OBJ}/scp-ssh-wrapper.scp"
# scpopts should be an array to preverse the double quotes
if [ "$os" == "windows" ]; then
scpopts=(-q -S "$TEST_SHELL_PATH ${OBJ}/scp-ssh-wrapper.scp")
else
chmod 755 ${OBJ}/scp-ssh-wrapper.scp
scpopts=(-q -S ${OBJ}/scp-ssh-wrapper.scp)
fi
export SCP # used in scp-ssh-wrapper.scp
scpclean() {
@ -26,31 +31,31 @@ egrep -v '^ +(Port|User) +.*$' $OBJ/ssh_config.orig > $OBJ/ssh_config
verbose "$tid: simple copy local file to remote file"
scpclean
$SCP $scpopts ${DATA} "scp://${USER}@somehost:${PORT}/${COPY}" || fail "copy failed"
$SCP "${scpopts[@]}" ${DATA} "scp://${USER}@somehost:${PORT}/${COPY}" || fail "copy failed"
cmp ${DATA} ${COPY} || fail "corrupted copy"
verbose "$tid: simple copy remote file to local file"
scpclean
$SCP $scpopts "scp://${USER}@somehost:${PORT}/${DATA}" ${COPY} || fail "copy failed"
$SCP "${scpopts[@]}" "scp://${USER}@somehost:${PORT}/${DATA}" ${COPY} || fail "copy failed"
cmp ${DATA} ${COPY} || fail "corrupted copy"
verbose "$tid: simple copy local file to remote dir"
scpclean
cp ${DATA} ${COPY}
$SCP $scpopts ${COPY} "scp://${USER}@somehost:${PORT}/${DIR}" || fail "copy failed"
$SCP "${scpopts[@]}" ${COPY} "scp://${USER}@somehost:${PORT}/${DIR}" || fail "copy failed"
cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
verbose "$tid: simple copy remote file to local dir"
scpclean
cp ${DATA} ${COPY}
$SCP $scpopts "scp://${USER}@somehost:${PORT}/${COPY}" ${DIR} || fail "copy failed"
$SCP "${scpopts[@]}" "scp://${USER}@somehost:${PORT}/${COPY}" ${DIR} || fail "copy failed"
cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
verbose "$tid: recursive local dir to remote dir"
scpclean
rm -rf ${DIR2}
cp ${DATA} ${DIR}/copy
$SCP $scpopts -r ${DIR} "scp://${USER}@somehost:${PORT}/${DIR2}" || fail "copy failed"
$SCP "${scpopts[@]}" -r ${DIR} "scp://${USER}@somehost:${PORT}/${DIR2}" || fail "copy failed"
for i in $(cd ${DIR} && echo *); do
cmp ${DIR}/$i ${DIR2}/$i || fail "corrupted copy"
done
@ -59,7 +64,7 @@ verbose "$tid: recursive remote dir to local dir"
scpclean
rm -rf ${DIR2}
cp ${DATA} ${DIR}/copy
$SCP $scpopts -r "scp://${USER}@somehost:${PORT}/${DIR}" ${DIR2} || fail "copy failed"
$SCP "${scpopts[@]}" -r "scp://${USER}@somehost:${PORT}/${DIR}" ${DIR2} || fail "copy failed"
for i in $(cd ${DIR} && echo *); do
cmp ${DIR}/$i ${DIR2}/$i || fail "corrupted copy"
done

View File

@ -19,7 +19,12 @@ DIR2=${COPY}.dd2
SRC=`dirname ${SCRIPT}`
cp ${SRC}/scp-ssh-wrapper.sh ${OBJ}/scp-ssh-wrapper.scp
chmod 755 ${OBJ}/scp-ssh-wrapper.scp
scpopts="-q -S ${OBJ}/scp-ssh-wrapper.scp"
# scpopts should be an array to preverse the double quotes
if [ "$os" == "windows" ]; then
scpopts=(-q -S "$TEST_SHELL_PATH ${OBJ}/scp-ssh-wrapper.scp")
else
scpopts=(-q -S ${OBJ}/scp-ssh-wrapper.scp)
fi
export SCP # used in scp-ssh-wrapper.scp
scpclean() {
@ -29,63 +34,63 @@ scpclean() {
verbose "$tid: simple copy local file to local file"
scpclean
$SCP $scpopts ${DATA} ${COPY} || fail "copy failed"
$SCP "${scpopts[@]}" ${DATA} ${COPY} 2>&1 1>/dev/null || fail "copy failed"
cmp ${DATA} ${COPY} || fail "corrupted copy"
verbose "$tid: simple copy local file to remote file"
scpclean
$SCP $scpopts ${DATA} somehost:${COPY} || fail "copy failed"
$SCP "${scpopts[@]}" ${DATA} somehost:${COPY} || fail "copy failed"
cmp ${DATA} ${COPY} || fail "corrupted copy"
verbose "$tid: simple copy remote file to local file"
scpclean
$SCP $scpopts somehost:${DATA} ${COPY} || fail "copy failed"
$SCP "${scpopts[@]}" somehost:${DATA} ${COPY} || fail "copy failed"
cmp ${DATA} ${COPY} || fail "corrupted copy"
verbose "$tid: simple copy local file to remote dir"
scpclean
cp ${DATA} ${COPY}
$SCP $scpopts ${COPY} somehost:${DIR} || fail "copy failed"
$SCP "${scpopts[@]}" ${COPY} somehost:${DIR} || fail "copy failed"
cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
verbose "$tid: simple copy local file to local dir"
scpclean
cp ${DATA} ${COPY}
$SCP $scpopts ${COPY} ${DIR} || fail "copy failed"
$SCP "${scpopts[@]}" ${COPY} ${DIR} 2>&1 1>/dev/null || fail "copy failed"
cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
verbose "$tid: simple copy remote file to local dir"
scpclean
cp ${DATA} ${COPY}
$SCP $scpopts somehost:${COPY} ${DIR} || fail "copy failed"
$SCP "${scpopts[@]}" somehost:${COPY} ${DIR} || fail "copy failed"
cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
verbose "$tid: recursive local dir to remote dir"
scpclean
rm -rf ${DIR2}
cp ${DATA} ${DIR}/copy
$SCP $scpopts -r ${DIR} somehost:${DIR2} || fail "copy failed"
$SCP "${scpopts[@]}" -r ${DIR} somehost:${DIR2} || fail "copy failed"
diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
verbose "$tid: recursive local dir to local dir"
scpclean
rm -rf ${DIR2}
cp ${DATA} ${DIR}/copy
$SCP $scpopts -r ${DIR} ${DIR2} || fail "copy failed"
$SCP "${scpopts[@]}" -r ${DIR} ${DIR2} 2>&1 1>/dev/null || fail "copy failed"
diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
verbose "$tid: recursive remote dir to local dir"
scpclean
rm -rf ${DIR2}
cp ${DATA} ${DIR}/copy
$SCP $scpopts -r somehost:${DIR} ${DIR2} || fail "copy failed"
$SCP "${scpopts[@]}" -r somehost:${DIR} ${DIR2} || fail "copy failed"
diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
verbose "$tid: shell metacharacters"
scpclean
(cd ${DIR} && \
touch '`touch metachartest`' && \
$SCP $scpopts *metachar* ${DIR2} 2>/dev/null; \
$SCP "${scpopts[@]}" *metachar* ${DIR2} 2>&1 2>/dev/null; \
[ ! -f metachartest ] ) || fail "shell metacharacters"
if [ ! -z "$SUDO" ]; then
@ -96,7 +101,7 @@ if [ ! -z "$SUDO" ]; then
cp ${DATA} ${DIR2}/copy
chmod 660 ${DIR2}/copy
$SUDO chown root ${DIR2}/copy
$SCP -p $scpopts somehost:${DIR}/\* ${DIR2} >/dev/null 2>&1
$SCP -p "${scpopts[@]}" somehost:${DIR}/\* ${DIR2} >/dev/null 2>&1
$SUDO diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
$SUDO rm ${DIR2}/copy
fi
@ -106,12 +111,12 @@ for i in 0 1 2 3 4; do
SCPTESTMODE=badserver_$i
export DIR SCPTESTMODE
scpclean
$SCP $scpopts somehost:${DATA} ${DIR} >/dev/null 2>/dev/null
$SCP "${scpopts[@]}" somehost:${DATA} ${DIR} >/dev/null 2>/dev/null
[ -d {$DIR}/rootpathdir ] && fail "allows dir relative to root dir"
[ -d ${DIR}/dotpathdir ] && fail "allows dir creation in non-recursive mode"
scpclean
$SCP -r $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null
$SCP -r "${scpopts[@]}" somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null
[ -d ${DIR}/dotpathdir ] && fail "allows dir creation outside of subdir"
done
@ -119,7 +124,7 @@ verbose "$tid: detect non-directory target"
scpclean
echo a > ${COPY}
echo b > ${COPY2}
$SCP $scpopts ${DATA} ${COPY} ${COPY2}
$SCP "${scpopts[@]}" ${DATA} ${COPY} ${COPY2}
cmp ${COPY} ${COPY2} >/dev/null && fail "corrupt target"
scpclean

View File

@ -20,7 +20,11 @@ QUOTECOPY=${COPY}".\"blah\""
QUOTECOPY_ARG=${COPY}'.\"blah\"'
# File with spaces
SPACECOPY="${COPY} this has spaces.txt"
SPACECOPY_ARG="${COPY}\ this\ has\ spaces.txt"
if [ "$os" == "windows" ]; then
SPACECOPY_ARG="\"${COPY} this has spaces.txt\""
else
SPACECOPY_ARG="${COPY}\ this\ has\ spaces.txt"
fi
# File with glob metacharacters
GLOBMETACOPY="${COPY} [metachar].txt"
@ -77,7 +81,7 @@ echo "get \"$DATA\" $COPY" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "get failed"
cmp $DATA ${COPY} || fail "corrupted copy after get"
if [ "$os" != "cygwin" ]; then
if [ "$os" != "cygwin" ] && [ "$os" != "windows" ]; then
rm -f ${QUOTECOPY}
cp $DATA ${QUOTECOPY}
verbose "$tid: get filename with quotes"
@ -136,7 +140,7 @@ echo "put $DATA $COPY" | \
${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "put failed"
cmp $DATA ${COPY} || fail "corrupted copy after put"
if [ "$os" != "cygwin" ]; then
if [ "$os" != "cygwin" ] && [ "$os" != "windows" ]; then
rm -f ${QUOTECOPY}
verbose "$tid: put filename with quotes"
echo "put $DATA \"$QUOTECOPY_ARG\"" | \

View File

@ -57,12 +57,15 @@ test "x$nobs" = "x" && touch "${QSLASH}" "${ESLASH}" "${SLASH}"
# target message expected unexpected
sftp_ls "${DIR}/fil*" "file glob" "${DATA}" ""
sftp_ls "${BASE}/d*" "dir glob" "`basename ${DATA}`" ""
sftp_ls "${DIR}/g-wild\"*\"" "quoted glob" "g-wild*" "g-wildx"
sftp_ls "${DIR}/g-wild\*" "escaped glob" "g-wild*" "g-wildx"
sftp_ls "${DIR}/g-quote\\\"" "escaped quote" "g-quote\"" ""
sftp_ls "\"${DIR}/g-quote\\\"\"" "quoted quote" "g-quote\"" ""
sftp_ls "'${DIR}/g-quote\"'" "single-quoted quote" "g-quote\"" ""
sftp_ls "${DIR}/g-q\\ space" "escaped space" "g-q space" ""
if [ "$os" != "windows" ]; then
sftp_ls "${DIR}/g-wild\"*\"" "quoted glob" "g-wild*" "g-wildx"
sftp_ls "${DIR}/g-wild\*" "escaped glob" "g-wild*" "g-wildx"
sftp_ls "${DIR}/g-quote\\\"" "escaped quote" "g-quote\"" ""
sftp_ls "\"${DIR}/g-quote\\\"\"" "quoted quote" "g-quote\"" ""
sftp_ls "'${DIR}/g-quote\"'" "single-quoted quote" "g-quote\"" ""
sftp_ls "${DIR}/g-q\\ space" "escaped space" "g-q space" ""
fi
sftp_ls "'${DIR}/g-q space'" "quoted space" "g-q space" ""
sftp_ls "${DIR}/g-sl\\\\ash" "escaped slash" "g-sl\\ash" "" "$nobs"
sftp_ls "'${DIR}/g-sl\\\\ash'" "quoted slash" "g-sl\\ash" "" "$nobs"

View File

@ -14,7 +14,11 @@ prepare_server() {
}
run_client() {
echo "$@" | ${SFTP} -D ${TEST_SFTP_SERVER} -vvvb - >$CLIENT_LOG 2>&1
if [ "$os" == "windows" ]; then
echo "$@" | ${SFTP} -D "$TEST_SHELL_PATH ${TEST_SFTP_SERVER}" -vvvb - >$CLIENT_LOG 2>&1
else
echo "$@" | ${SFTP} -D ${TEST_SFTP_SERVER} -vvvb - >$CLIENT_LOG 2>&1
fi
}
prepare_files() {
@ -22,6 +26,10 @@ prepare_files() {
rm -f ${COPY} ${COPY}.1
test -d ${COPY}.dd && { rmdir ${COPY}.dd || fatal "rmdir ${COPY}.dd"; }
test -z "$_prep" && return
if [ "$os" == "windows" ]; then
# Remove starting, ending double-quotes
_prep=`echo $_prep | sed -e 's/^"//' -e 's/"$//'`
fi
sh -c "$_prep" || fail "preparation failed: \"$_prep\""
}
@ -88,12 +96,21 @@ ro_test \
"cmp $DATA $COPY" \
"test ! -f $COPY"
ro_test \
if [ "$os" == "windows" ]; then
ro_test \
"setstat" \
"chmod 0700 $COPY" \
"\"powershell.exe /c new-item `windows_path $OBJ`/copy 1>/dev/null; powershell.exe /c set-itemproperty `windows_path $OBJ`/copy -Name IsReadOnly -Value 1\"" \
"powershell.exe /c \"(Get-ChildItem `windows_path $OBJ`/copy).IsReadOnly\" 1>/dev/null" \
"powershell.exe /c \"!(Get-ChildItem $`windows_path $OBJ`/copy).IsReadOnly\" 1>/dev/null"
else
ro_test \
"setstat" \
"chmod 0700 $COPY" \
"touch $COPY; chmod 0400 $COPY" \
"test -x $COPY" \
"test ! -x $COPY"
fi
ro_test \
"rm" \
@ -188,13 +205,23 @@ perm_test \
"realpath,opendir,stat,lstat" \
"ls -ln $OBJ"
perm_test \
"setstat" \
"realpath,stat,lstat" \
"chmod 0700 $COPY" \
"touch $COPY; chmod 0400 $COPY" \
"test -x $COPY" \
"test ! -x $COPY"
if [ "$os" == "windows" ]; then
perm_test \
"setstat" \
"realpath,stat,lstat" \
"chmod 0700 $COPY" \
"\"powershell.exe /c new-item `windows_path $OBJ`/copy 1>/dev/null; powershell.exe /c set-itemproperty `windows_path $OBJ`/copy -Name IsReadOnly -Value 1\"" \
"powershell.exe /c \"(Get-ChildItem `windows_path $OBJ`/copy).IsReadOnly\" 1>/dev/null" \
"powershell.exe /c \"!(Get-ChildItem `windows_path $OBJ`/copy).IsReadOnly\" 1>/dev/null"
else
perm_test \
"setstat" \
"realpath,stat,lstat" \
"chmod 0700 $COPY" \
"touch $COPY; chmod 0400 $COPY" \
"test -x $COPY" \
"test ! -x $COPY"
fi
perm_test \
"remove" \

View File

@ -23,18 +23,18 @@ egrep -v '^ +(Port|User) +.*$' $OBJ/ssh_config.orig > $OBJ/ssh_config
verbose "$tid: non-interactive fetch to local file"
sftpclean
${SFTP} -q -S "$SSH" -F $OBJ/ssh_config "sftp://${USER}@somehost:${PORT}/${DATA}" ${COPY} || fail "copy failed"
${SFTP} -q -S "$TEST_SHELL_PATH $SSH" -F $OBJ/ssh_config "sftp://${USER}@somehost:${PORT}/${DATA}" ${COPY} || fail "copy failed"
cmp ${DATA} ${COPY} || fail "corrupted copy"
verbose "$tid: non-interactive fetch to local dir"
sftpclean
cp ${DATA} ${COPY}
${SFTP} -q -S "$SSH" -F $OBJ/ssh_config "sftp://${USER}@somehost:${PORT}/${COPY}" ${DIR} || fail "copy failed"
${SFTP} -q -S "$TEST_SHELL_PATH $SSH" -F $OBJ/ssh_config "sftp://${USER}@somehost:${PORT}/${COPY}" ${DIR} || fail "copy failed"
cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
verbose "$tid: put to remote directory (trailing slash)"
sftpclean
${SFTP} -q -S "$SSH" -F $OBJ/ssh_config -b - \
${SFTP} -q -S "$TEST_SHELL_PATH $SSH" -F $OBJ/ssh_config -b - \
"sftp://${USER}@somehost:${PORT}/${DIR}/" > /dev/null 2>&1 << EOF
version
put ${DATA} copy
@ -48,7 +48,7 @@ fi
verbose "$tid: put to remote directory (no slash)"
sftpclean
${SFTP} -q -S "$SSH" -F $OBJ/ssh_config -b - \
${SFTP} -q -S "$TEST_SHELL_PATH $SSH" -F $OBJ/ssh_config -b - \
"sftp://${USER}@somehost:${PORT}/${DIR}" > /dev/null 2>&1 << EOF
version
put ${DATA} copy

View File

@ -10,19 +10,37 @@ verbose "reparse minimal config"
verbose "ssh -W opts"
f=`${SSH} -GF $OBJ/ssh_config host | awk '/exitonforwardfailure/{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
test "$f" = "no" || fail "exitonforwardfailure default"
f=`${SSH} -GF $OBJ/ssh_config -W a:1 h | awk '/exitonforwardfailure/{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
test "$f" = "yes" || fail "exitonforwardfailure enable"
f=`${SSH} -GF $OBJ/ssh_config -W a:1 -o exitonforwardfailure=no h | \
awk '/exitonforwardfailure/{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
test "$f" = "no" || fail "exitonforwardfailure override"
f=`${SSH} -GF $OBJ/ssh_config host | awk '/clearallforwardings/{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
test "$f" = "no" || fail "clearallforwardings default"
f=`${SSH} -GF $OBJ/ssh_config -W a:1 h | awk '/clearallforwardings/{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
test "$f" = "yes" || fail "clearallforwardings enable"
f=`${SSH} -GF $OBJ/ssh_config -W a:1 -o clearallforwardings=no h | \
awk '/clearallforwardings/{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
test "$f" = "no" || fail "clearallforwardings override"
# cleanup

View File

@ -7,19 +7,26 @@
_POSIX2_VERSION=199209
export _POSIX2_VERSION
case `uname -s 2>/dev/null` in
OSF1*)
BIN_SH=xpg4
export BIN_SH
;;
CYGWIN_NT-5.0)
os=cygwin
TEST_SSH_IPV6=no
;;
CYGWIN*)
os=cygwin
;;
esac
if [ "x$TEST_WINDOWS_SSH" != "x" ]; then
os="windows"
fi
if [ "$os" != "windows" ]; then
case `uname -s 2>/dev/null` in
OSF1*)
BIN_SH=xpg4
export BIN_SH
;;
CYGWIN_NT-5.0)
os=cygwin
TEST_SSH_IPV6=no
;;
CYGWIN*)
os=cygwin
;;
esac
fi
if [ ! -z "$TEST_SSH_PORT" ]; then
PORT="$TEST_SSH_PORT"
@ -27,14 +34,20 @@ else
PORT=4242
fi
if [ -x /usr/ucb/whoami ]; then
USER=`/usr/ucb/whoami`
elif whoami >/dev/null 2>&1; then
USER=`whoami`
elif logname >/dev/null 2>&1; then
USER=`logname`
if [ "$os" == "windows" ]; then
USER=$TEST_SSH_USER
USER_DOMAIN=$TEST_SSH_USER_DOMAIN
LOGNAME=$USER
else
USER=`id -un`
if [ -x /usr/ucb/whoami ]; then
USER=`/usr/ucb/whoami`
elif whoami >/dev/null 2>&1; then
USER=`whoami`
elif logname >/dev/null 2>&1; then
USER=`logname`
else
USER=`id -un`
fi
fi
OBJ=$1
@ -213,7 +226,11 @@ fi
# because sftp and scp don't handle spaces in arguments.
SSHLOGWRAP=$OBJ/ssh-log-wrapper.sh
echo "#!/bin/sh" > $SSHLOGWRAP
echo "exec ${SSH} -E${TEST_SSH_LOGFILE} "'"$@"' >>$SSHLOGWRAP
if [ "$os" == "windows" ]; then
echo "exec ${SSH} -T -E${TEST_SSH_LOGFILE} "'"$@"' >>$SSHLOGWRAP
else
echo "exec ${SSH} -E${TEST_SSH_LOGFILE} "'"$@"' >>$SSHLOGWRAP
fi
chmod a+rx $OBJ/ssh-log-wrapper.sh
REAL_SSH="$SSH"
@ -229,6 +246,9 @@ cat ${SSHAGENT_BIN} >${DATA}
chmod u+w ${DATA}
COPY=$OBJ/copy
rm -f ${COPY}
if [ "$os" == "windows" ]; then
EXEEXT=".exe"
fi
increase_datafile_size()
{
@ -242,6 +262,11 @@ export SSH SSHD SSHAGENT SSHADD SSHKEYGEN SSHKEYSCAN SFTP SFTPSERVER SCP
#echo $SSH $SSHD $SSHAGENT $SSHADD $SSHKEYGEN $SSHKEYSCAN $SFTP $SFTPSERVER $SCP
# Portable specific functions
windows_path()
{
cygpath -m $1
}
have_prog()
{
saved_IFS="$IFS"
@ -289,29 +314,34 @@ md5 () {
stop_sshd ()
{
if [ -f $PIDFILE ]; then
pid=`$SUDO cat $PIDFILE`
if [ "X$pid" = "X" ]; then
echo no sshd running
else
if [ $pid -lt 2 ]; then
echo bad pid for sshd: $pid
# windows process can't be stopped using kill command so use stop-process
if [ "$os" == "windows" ]; then
powershell.exe /c "stop-process -Name sshd -Force" >/dev/null 2>&1
else
if [ -f $PIDFILE ]; then
pid=`$SUDO cat $PIDFILE`
if [ "X$pid" = "X" ]; then
echo no sshd running
else
$SUDO kill $pid
trace "wait for sshd to exit"
i=0;
while [ -f $PIDFILE -a $i -lt 5 ]; do
i=`expr $i + 1`
sleep $i
done
if test -f $PIDFILE; then
if $SUDO kill -0 $pid; then
echo "sshd didn't exit " \
"port $PORT pid $pid"
else
echo "sshd died without cleanup"
if [ $pid -lt 2 ]; then
echo bad pid for sshd: $pid
else
$SUDO kill $pid
trace "wait for sshd to exit"
i=0;
while [ -f $PIDFILE -a $i -lt 5 ]; do
i=`expr $i + 1`
sleep $i
done
if test -f $PIDFILE; then
if $SUDO kill -0 $pid; then
echo "sshd didn't exit " \
"port $PORT pid $pid"
else
echo "sshd died without cleanup"
fi
exit 1
fi
exit 1
fi
fi
fi
@ -321,11 +351,19 @@ stop_sshd ()
# helper
cleanup ()
{
if [ "x$SSH_PID" != "x" ]; then
if [ $SSH_PID -lt 2 ]; then
echo bad pid for ssh: $SSH_PID
else
kill $SSH_PID
# windows process can't be stopped using kill command so use stop-process
if [ "$os" == "windows" ]; then
powershell.exe /c "stop-process -Name ssh-agent -Force" >/dev/null 2>&1
if [ "x$SSH_PID" != "x" ]; then
powershell.exe /c "stop-process -Id $SSH_PID -Force" >/dev/null 2>&1
fi
else
if [ "x$SSH_PID" != "x" ]; then
if [ $SSH_PID -lt 2 ]; then
echo bad pid for ssh: $SSH_PID
else
kill $SSH_PID
fi
fi
fi
stop_sshd
@ -451,6 +489,21 @@ fi
rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER
SSH_KEYTYPES="rsa ed25519"
if [ "$os" == "windows" ]; then
first_key_type=${SSH_KEYTYPES%% *}
if [ "x$USER_DOMAIN" != "x" ]; then
# For domain user, create folders
if [ ! -d $OBJ/authorized_keys_$USER_DOMAIN ]; then
mkdir $OBJ/authorized_keys_$USER_DOMAIN
fi
if [ ! -d $OBJ/authorized_principals_$USER_DOMAIN ]; then
mkdir $OBJ/authorized_principals_$USER_DOMAIN
fi
if [ ! -d /var/run/principals_command_$USER_DOMAIN ]; then
mkdir /var/run/principals_command_$USER_DOMAIN
fi
fi
fi
trace "generate keys"
for t in ${SSH_KEYTYPES}; do
@ -473,12 +526,21 @@ for t in ${SSH_KEYTYPES}; do
# use key as host key, too
$SUDO cp $OBJ/$t $OBJ/host.$t
if [ "$os" == "windows" ]; then
# set the file permissions (ACLs) properly
powershell.exe /c "get-acl `windows_path $OBJ`/$t | set-acl `windows_path $OBJ`/host.$t"
fi
echo HostKey $OBJ/host.$t >> $OBJ/sshd_config
# don't use SUDO for proxy connect
echo HostKey $OBJ/$t >> $OBJ/sshd_proxy
done
chmod 644 $OBJ/authorized_keys_$USER
if [ "$os" == "windows" ]; then
# set the file permissions (ACLs) properly
powershell.exe /c "get-acl `windows_path $OBJ`/$first_key_type | set-acl `windows_path $OBJ`/authorized_keys_$USER"
fi
# Activate Twisted Conch tests if the binary is present
REGRESS_INTEROP_CONCH=no
@ -536,7 +598,11 @@ fi
# create a proxy version of the client config
(
cat $OBJ/ssh_config
echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy
if [ "$os" == "windows" ]; then
echo proxycommand `windows_path ${SSHD}` -i -f `windows_path $OBJ`/sshd_proxy
else
echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy
fi
) > $OBJ/ssh_proxy
# check proxy config
@ -546,7 +612,14 @@ start_sshd ()
{
# start sshd
$SUDO ${SSHD} -f $OBJ/sshd_config "$@" -t || fatal "sshd_config broken"
$SUDO ${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE
if [ "$os" == "windows" ]; then
# In windows, we need to explicitly remove the sshd pid file.
rm -rf $PIDFILE
#TODO (Code BUG) : -E<sshd.log> is writing the data the cygwin terminal.
${SSHD} -f $OBJ/sshd_config "$@" &
else
$SUDO ${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE
fi
trace "wait for sshd"
i=0;

View File

@ -8,6 +8,10 @@ cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
for c in `${SSH} -Q cipher`; do
n=0
for m in `${SSH} -Q mac`; do
if [ "$os" == "windows" ]; then
c=${c/$'\r'/} # remove CR (carriage return)
m=${m/$'\r'/} # remove CR (carriage return)
fi
trace "cipher $c mac $m"
verbose "test $tid: cipher $c mac $m"
cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy

View File

@ -579,9 +579,12 @@ file_symlink_tests()
/* verify readlink() output against symlink() input */
char readlink_buf[MAX_PATH] = "";
/* readlink returns the absolute path */
int readlink_ret = readlink(lnk_utf8, readlink_buf, MAX_PATH);
ASSERT_INT_EQ(readlink_ret, strlen(tgt_name_utf8));
ASSERT_INT_EQ(0, memcmp(readlink_buf, tgt_name_utf8, readlink_ret));
char tgt_name_uft8_realpath[PATH_MAX] = { 0 };
realpath(tgt_utf8, tgt_name_uft8_realpath);
ASSERT_INT_EQ(readlink_ret, strlen(tgt_name_uft8_realpath));
ASSERT_INT_EQ(0, memcmp(readlink_buf, tgt_name_uft8_realpath, readlink_ret));
/* verify lstat() gets the reference to the link */
struct w32_stat statbuf;

View File

@ -72,6 +72,8 @@ test_sanitizedpath()
wchar_t *win32prgdir = utf8_to_utf16(win32prgdir_utf8);
wchar_t *ret = resolved_path_utf16(win32prgdir_utf8);
/* resolved path will return in unix file format ex - c:/test/1/ */
convertToBackslashW(ret);
retValue = wcscmp(win32prgdir, ret);
ASSERT_INT_EQ(retValue, 0);
free(ret);
@ -83,6 +85,8 @@ test_sanitizedpath()
tmp_path[win32prgdir_len+1] = '\0';
ret = resolved_path_utf16(tmp_path);
/* resolved path will return in unix file format ex - c:/test/1/ */
convertToBackslashW(ret);
retValue = wcscmp(win32prgdir, ret);
ASSERT_INT_EQ(retValue, 0);
free(ret);
@ -92,6 +96,8 @@ test_sanitizedpath()
s1[0] = '/', s1[1] = win32prgdir[0], s1[2] = ':', s1[3] = '\0';
s2[0] = win32prgdir[0], s2[1] = ':', s2[2] = '\\', s2[3] = '\0';
ret = resolved_path_utf16(s1);
/* resolved path will return in unix file format ex - c:/test/1/ */
convertToBackslashW(ret);
retValue = wcscmp(ret, s2);
ASSERT_INT_EQ(retValue, 0);
free(ret);

View File

@ -462,7 +462,7 @@ socket_nonblocking_io_tests()
void
socket_select_tests() {
int s, r;
int num_bytes = 1024 * 1024 * 2; //2 MB
int num_bytes = 1024 * 1024 * 4; //4 MB
int bytes_sent = 0;
int bytes_received = 0;
int seed = 326;

64
scp.c
View File

@ -214,13 +214,34 @@ do_local_cmd(arglist *a)
cmd = xmalloc(cmdlen);
cmd[0] = '\0';
for (i = 0; i < a->num; i++) {
if(i != 0)
strcat_s(cmd, cmdlen, " ");
strcat_s(cmd, cmdlen, a->list[i]);
char *path = a->list[i];
if (is_bash_test_env()) {
char resolved[PATH_MAX] = { 0, };
convertToForwardslash(path);
if(bash_to_win_path(path, resolved, _countof(resolved)))
convertToBackslash(resolved);
strcat(cmd, " ");
strcat(cmd, resolved);
} else {
if (i != 0)
strcat_s(cmd, cmdlen, " ");
strcat_s(cmd, cmdlen, a->list[i]);
}
}
wchar_t *cmd_w = utf8_to_utf16(cmd);
if (cmd_w) {
if (_wsystem(cmd_w))
return -1;
free(cmd_w);
return 0;
} else {
error("%s out of memory", __func__);
return -1;
}
if (system(cmd))
return -1;
return 0;
}
#else /* !WINDOWS */
@ -298,7 +319,7 @@ do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout)
/* Fork a child to execute the command on the remote host using ssh. */
#ifdef FORK_NOT_SUPPORTED
replacearg(&args, 0, "%s", ssh_program);
replacearg(&args, 0, "%s", ssh_program);
if (port != -1) {
addargs(&args, "-p");
addargs(&args, "%d", port);
@ -389,8 +410,8 @@ do_cmd2(char *host, char *remuser, int port, char *cmd, int fdin, int fdout)
/* Fork a child to execute the command on the remote host using ssh. */
#ifdef FORK_NOT_SUPPORTED
/* generate command line and spawn_child */
replacearg(&args, 0, "%s", ssh_program);
/* generate command line and spawn_child */
replacearg(&args, 0, "%s", ssh_program);
if (port != -1) {
addargs(&args, "-p");
addargs(&args, "%d", port);
@ -910,16 +931,23 @@ tolocal(int argc, char **argv)
addargs(&alist, "/S /E /H");
if (pflag)
addargs(&alist, "/K /X");
addargs(&alist, "/Y /F /I");
addargs(&alist, "%s", argv[i]);
addargs(&alist, "/Y /F /I");
addargs(&alist, "%s", argv[i]);
if ((last = strrchr(argv[i], '\\')) == NULL)
last = argv[i];
else
++last;
addargs(&alist, "%s%s%s", argv[argc - 1],
strcmp(argv[argc - 1], "\\") ? "\\" : "", last);
/* This logic is added to align with UNIX behavior.
* If the argv[argc-1] exists then append direcorty name from argv[i]
*/
if (0 == stat(argv[argc - 1], &stb) && (S_ISDIR(stb.st_mode))) {
if ((last = strrchr(argv[i], '\\')) == NULL)
last = argv[i];
else
++last;
addargs(&alist, "%s%s%s", argv[argc - 1],
strcmp(argv[argc - 1], "\\") ? "\\" : "", last);
} else {
addargs(&alist, "%s", argv[argc - 1]);
}
} else {
addargs(&alist, "%s", _PATH_COPY);
addargs(&alist, "/Y");

View File

@ -982,7 +982,11 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
}
if (ci->user == NULL)
match_test_missing_fatal("User", "user");
#ifdef WINDOWS
if (match_pattern_list(ci->user, arg, 1) != 1)
#else
if (match_pattern_list(ci->user, arg, 0) != 1)
#endif
result = 0;
else
debug("user %.100s matched 'User %.100s' at "
@ -2279,17 +2283,46 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
* h) user@domain@hostip
*/
/* convert the users, user groups to lower case */
for(int i = 0; i < options->num_allow_users; i++)
char *tmp = NULL;
for (int i = 0; i < options->num_allow_users; i++) {
/* For domain user we need special handling.
* We support both "domain\user" and "domain/user" formats.
*/
if (tmp = strstr(options->allow_users[i], "/"))
*tmp = '\\';
lowercase(options->allow_users[i]);
}
for (int i = 0; i < options->num_deny_users; i++) {
/* For domain user we need special handling.
* We support both "domain\user" and "domain/user" formats.
*/
if (tmp = strstr(options->deny_users[i], "/"))
*tmp = '\\';
for (int i = 0; i < options->num_deny_users; i++)
lowercase(options->deny_users[i]);
}
for (int i = 0; i < options->num_allow_groups; i++) {
/* For domain group we need special handling.
* We support both "domain\group" and "domain/group" formats.
*/
if (tmp = strstr(options->allow_groups[i], "/"))
*tmp = '\\';
for (int i = 0; i < options->num_allow_groups; i++)
lowercase(options->allow_groups[i]);
}
for (int i = 0; i < options->num_deny_groups; i++) {
/* For domain group we need special handling.
* We support both "domain\group" and "domain/group" formats.
*/
if (tmp = strstr(options->deny_groups[i], "/"))
*tmp = '\\';
for (int i = 0; i < options->num_deny_groups; i++)
lowercase(options->deny_groups[i]);
}
#endif // WINDOWS
}

118
session.c
View File

@ -369,7 +369,7 @@ xauth_valid_string(const char *s)
* - Interactive shell/commands are executed using ssh-shellhost.exe
* - ssh-shellhost.exe implements server-side PTY for Windows
*/
static char ** do_setup_env(struct ssh *ssh, Session *s, const char *shell);
#define UTF8_TO_UTF16_WITH_CLEANUP(o, i) do { \
if (o != NULL) free(o); \
@ -382,8 +382,8 @@ xauth_valid_string(const char *s)
goto cleanup; \
} while(0)
/* TODO - built env var set and pass it along with CreateProcess */
/* set user environment variables from user profile */
/* TODO - built env var set and pass it along with CreateProcess */
/* set user environment variables from user profile */
static void
setup_session_user_vars(wchar_t* profile_path)
{
@ -396,11 +396,22 @@ setup_session_user_vars(wchar_t* profile_path)
LONG ret;
SetEnvironmentVariableW(L"USERPROFILE", profile_path);
if (profile_path[0] && profile_path[1] == L':') {
SetEnvironmentVariableW(L"HOMEPATH", profile_path + 2);
wchar_t wc = profile_path[2];
profile_path[2] = L'\0';
SetEnvironmentVariableW(L"HOMEDRIVE", profile_path);
profile_path[2] = wc;
} else {
SetEnvironmentVariableW(L"HOMEPATH", profile_path);
}
swprintf_s(path, _countof(path), L"%s\\AppData\\Local", profile_path);
SetEnvironmentVariableW(L"LOCALAPPDATA", path);
swprintf_s(path, _countof(path), L"%s\\AppData\\Roaming", profile_path);
SetEnvironmentVariableW(L"APPDATA", path);
ret = RegOpenKeyExW(HKEY_CURRENT_USER, L"Environment", 0, KEY_QUERY_VALUE, &reg_key);
if (ret != ERROR_SUCCESS)
//error("Error retrieving user environment variables. RegOpenKeyExW returned %d", ret);
@ -462,55 +473,20 @@ cleanup:
free(path_value);
}
static int
setup_session_vars(Session* s)
static int
setup_session_env(struct ssh *ssh, Session* s)
{
wchar_t *pw_dir_w = NULL, *tmp = NULL;
int i = 0, ret = -1;
char *env_name = NULL, *env_value = NULL, *t = NULL, **env = NULL, *path_env_val = NULL;
char buf[1024] = { 0 };
wchar_t wbuf[1024] = { 0 };
wchar_t *env_name_w = NULL, *env_value_w = NULL, *pw_dir_w = NULL, *tmp = NULL, wbuf[1024] = { 0, };
char *laddr, *c;
int ret = -1;
struct ssh *ssh = active_state; /* XXX */
UTF8_TO_UTF16_WITH_CLEANUP(pw_dir_w, s->pw->pw_dir);
/* skip domain part (if there) while setting USERNAME */
/* skip domain part (if present) while setting USERNAME */
c = strchr(s->pw->pw_name, '\\');
UTF8_TO_UTF16_WITH_CLEANUP(tmp, c ? c + 1 : s->pw->pw_name);
SetEnvironmentVariableW(L"USERNAME", tmp);
if (s->display) {
UTF8_TO_UTF16_WITH_CLEANUP(tmp, s->display);
SetEnvironmentVariableW(L"DISPLAY", tmp);
}
SetEnvironmentVariableW(L"USERPROFILE", pw_dir_w);
if (pw_dir_w[0] && pw_dir_w[1] == L':') {
SetEnvironmentVariableW(L"HOMEPATH", pw_dir_w + 2);
wchar_t wc = pw_dir_w[2];
pw_dir_w[2] = L'\0';
SetEnvironmentVariableW(L"HOMEDRIVE", pw_dir_w);
pw_dir_w[2] = wc;
} else {
SetEnvironmentVariableW(L"HOMEPATH", pw_dir_w);
}
snprintf(buf, sizeof buf, "%.50s %d %d",
ssh->remote_ipaddr, ssh->remote_port, ssh->local_port);
SetEnvironmentVariableA("SSH_CLIENT", buf);
laddr = get_local_ipaddr(packet_get_connection_in());
snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
ssh->remote_ipaddr, ssh->remote_port, laddr, ssh->local_port);
free(laddr);
SetEnvironmentVariableA("SSH_CONNECTION", buf);
if (original_command) {
UTF8_TO_UTF16_WITH_CLEANUP(tmp, original_command);
SetEnvironmentVariableW(L"SSH_ORIGINAL_COMMAND", tmp);
}
if ((s->term) && (s->term[0]))
SetEnvironmentVariableA("TERM", s->term);
if (!s->is_subsystem) {
_snprintf(buf, ARRAYSIZE(buf), "%s@%s", s->pw->pw_name, getenv("COMPUTERNAME"));
@ -525,13 +501,50 @@ setup_session_vars(Session* s)
SetEnvironmentVariableW(L"PROMPT", wbuf);
}
/* setup any user specific env variables */
setup_session_user_vars(pw_dir_w);
setup_session_user_vars(pw_dir_w); /* setup user specific env variables */
env = do_setup_env(ssh, s, s->pw->pw_shell);
while (env_name = env[i]) {
if (t = strstr(env[i++], "=")) {
/* SKIP, if not applicable on WINDOWS
PATH is already set.
MAIL is not applicable.
*/
if ((0 == strncmp(env_name, "PATH=", strlen("PATH="))) ||
(0 == strncmp(env_name, "MAIL=", strlen("MAIL=")))) {
continue;
}
env_value = t + 1;
*t = '\0';
UTF8_TO_UTF16_WITH_CLEANUP(env_name_w, env_name);
UTF8_TO_UTF16_WITH_CLEANUP(env_value_w, env_value);
SetEnvironmentVariableW(env_name_w, env_value_w);
}
}
ret = 0;
cleanup:
free(pw_dir_w);
free(tmp);
cleanup :
if (pw_dir_w)
free(pw_dir_w);
if (tmp)
free(tmp);
if (env_name_w)
free(env_name_w);
if (env_value_w)
free(env_value_w);
if (env) {
i = 0;
while (t = env[i++])
free(t);
free(env);
}
return ret;
}
@ -568,7 +581,7 @@ int do_exec_windows(struct ssh *ssh, Session *s, const char *command, int pty) {
if (environment_set)
break;
if (setup_session_vars(s) != 0)
if (setup_session_env(ssh, s) != 0)
goto cleanup;
environment_set = 1;
@ -637,7 +650,7 @@ int do_exec_windows(struct ssh *ssh, Session *s, const char *command, int pty) {
!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &job_info, sizeof(job_info)) ||
!AssignProcessToJobObject(job, pi.hProcess) ||
!DuplicateHandle(GetCurrentProcess(), job, pi.hProcess, &job_dup, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
error("cannot associate job object: %d", GetLastError());
error("cannot associate job object: %d", GetLastError());
errno = EOTHER;
TerminateProcess(pi.hProcess, 255);
CloseHandle(pi.hProcess);
@ -2207,6 +2220,7 @@ session_window_change_req(struct ssh *ssh, Session *s)
s->xpixel = packet_get_int();
s->ypixel = packet_get_int();
packet_check_eom();
pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
return 1;
}

42
sftp.c
View File

@ -70,6 +70,9 @@ typedef void EditLine;
#include "sshbuf.h"
#include "sftp-common.h"
#include "sftp-client.h"
#ifdef WINDOWS
#include "misc_internal.h"
#endif // WINDOWS
#define DEFAULT_COPY_BUFLEN 32768 /* Size of buffer for up/download */
#define DEFAULT_NUM_REQUESTS 64 /* # concurrent outstanding requests */
@ -295,15 +298,30 @@ static void
local_do_shell(const char *args)
{
#ifdef WINDOWS
/* execute via system call in Windows*/
char cmd_path[PATH_MAX] = { 0, };
if (!*args){
/* execute via system call in Windows*/
if (!*args) {
char cmd_path[PATH_MAX] = { 0, };
if (!GetSystemDirectory(cmd_path, sizeof(cmd_path)))
fatal("GetSystemDirectory failed");
strcat_s(cmd_path, PATH_MAX, "\\cmd.exe");
args = cmd_path;
} else {
if (is_bash_test_env()) {
char *cygwin_path_prefix_start = NULL;
if (cygwin_path_prefix_start = strstr(args, CYGWIN_PATH_PREFIX)) {
int len = strlen(cygwin_path_prefix_start) + 1;
char *tmp = malloc(len);
memset(tmp, 0, len);
bash_to_win_path(cygwin_path_prefix_start, tmp, len);
strcpy_s(cygwin_path_prefix_start, len, tmp); /* override the original string */
if (tmp)
free(tmp);
}
}
convertToBackslash((char *) args);
}
@ -403,9 +421,6 @@ make_absolute(char *p, const char *pwd)
p = abs_str;
}
/* convert '\\' to '/' */
convertToForwardslash(p);
/* Append "/" if needed to the absolute windows path */
if (p && p[0] != '\0' && p[1] == ':') {
s1 = path_append("/", p);
@ -2556,11 +2571,13 @@ main(int argc, char **argv)
}
break;
}
/* TODO: need to debug this. this parameter doesn't make sense
file2 = *(argv + 1);
*/
#ifdef WINDOWS
if (argc == (optind + 2))
file2 = *(argv + 1);
#else
file2 = *(argv + 1);
#endif
if (!*host) {
fprintf(stderr, "Missing hostname\n");
usage();
@ -2586,7 +2603,12 @@ main(int argc, char **argv)
connect_to_server(ssh_program, args.list, &in, &out);
} else {
args.list = NULL;
#ifdef WINDOWS
addargs(&args, "sftp-server.exe");
#elif
addargs(&args, "sftp-server");
#endif // WINDOWS
connect_to_server(sftp_direct, args.list, &in, &out);
}

View File

@ -232,6 +232,10 @@ ssh_proxy_connect(struct ssh *ssh, const char *host, u_short port,
spawn_argv[1] = NULL;
pid = -1;
/* disable inheritance */
fcntl(pin[1], F_SETFD, FD_CLOEXEC);
fcntl(pout[0], F_SETFD, FD_CLOEXEC);
if (posix_spawn_file_actions_init(&actions) != 0 ||
posix_spawn_file_actions_adddup2(&actions, pin[0], STDIN_FILENO) != 0 ||
posix_spawn_file_actions_adddup2(&actions, pout[1], STDOUT_FILENO) != 0)
@ -1572,8 +1576,19 @@ int
ssh_local_cmd(const char *args)
{
#ifdef WINDOWS
fatal("executing local command is not supported in Windows yet");
return 0;
if (!options.permit_local_command ||
args == NULL || !*args)
return (1);
int retVal = -1;
wchar_t *args_w = utf8_to_utf16(args);
if (args_w) {
retVal = _wsystem(args_w);
free(args_w);
}
return retVal;
#else /* !WINDOWS */
char *shell;
pid_t pid;

53
sshd.c
View File

@ -199,7 +199,8 @@ int have_agent = 0;
int privsep_unauth_child = 0;
int privsep_auth_child = 0;
int tmp_sock = 0;
int io_sock_in = 0;
int io_sock_out = 0;
/*
* Any really sensitive data in the application is contained in this
@ -684,13 +685,13 @@ recv_hostkeys_state(int fd)
fatal("%s: ssh_msg_recv failed", __func__);
if (buffer_get_char(m) != 0)
fatal("%s: recv_hostkeys_state version mismatch", __func__);
fatal("%s: version mismatch", __func__);
int num = buffer_get_int(m);
sensitive_data.host_keys = xcalloc(num, sizeof(struct sshkey *));
sensitive_data.host_pubkeys = xcalloc(num, sizeof(struct sshkey *));
sensitive_data.host_certificates = xcalloc(num, sizeof(struct sshkey *));
for (int i = 0; i < num; i++) {
int num_host_key_files = buffer_get_int(m);
sensitive_data.host_keys = xcalloc(num_host_key_files, sizeof(struct sshkey *));
sensitive_data.host_pubkeys = xcalloc(num_host_key_files, sizeof(struct sshkey *));
sensitive_data.host_certificates = xcalloc(num_host_key_files, sizeof(struct sshkey *));
for (int i = 0; i < num_host_key_files; i++) {
blob = buffer_get_string_ptr(m, &blen);
sensitive_data.host_pubkeys[i] = NULL;
sensitive_data.host_keys[i] = NULL;
@ -700,7 +701,8 @@ recv_hostkeys_state(int fd)
sensitive_data.host_pubkeys[i] = key;
}
}
for (int i = 0; i < num; i++) {
for (int i = 0; i < num_host_key_files; i++) {
blob = buffer_get_string_ptr(m, &blen);
sensitive_data.host_certificates[i] = NULL;
if (blen) {
@ -750,7 +752,27 @@ static char**
privsep_child_cmdline(int authenticated)
{
char** argv = rexec_argv ? rexec_argv : saved_argv;
int argc = rexec_argv ? rexec_argc : saved_argc - 1;
int argc = 0;
if (rexec_argv)
argc = rexec_argc;
else {
if (rexeced_flag)
argc = saved_argc - 1; // override '-R'
else {
char **tmp = xcalloc(saved_argc + 1 + 1, sizeof(*saved_argv)); // 1 - extra argument "-y/-z", 1 - NULL
int i = 0;
for (i = 0; (int)i < saved_argc; i++) {
tmp[i] = xstrdup(saved_argv[i]);
free(saved_argv[i]);
}
free(saved_argv);
argv = saved_argv = tmp;
argc = saved_argc;
}
}
if (authenticated)
argv[argc] = "-z";
else
@ -801,8 +823,8 @@ privsep_preauth(Authctxt *authctxt)
posix_spawn_file_actions_t actions;
if (posix_spawn_file_actions_init(&actions) != 0 ||
posix_spawn_file_actions_adddup2(&actions, tmp_sock, STDIN_FILENO) != 0 ||
posix_spawn_file_actions_adddup2(&actions, tmp_sock, STDOUT_FILENO) != 0 ||
posix_spawn_file_actions_adddup2(&actions, io_sock_in, STDIN_FILENO) != 0 ||
posix_spawn_file_actions_adddup2(&actions, io_sock_out, STDOUT_FILENO) != 0 ||
posix_spawn_file_actions_adddup2(&actions, pmonitor->m_recvfd, PRIVSEP_MONITOR_FD) != 0 ||
posix_spawn_file_actions_adddup2(&actions, pmonitor->m_log_sendfd, PRIVSEP_LOG_FD) != 0 )
fatal("posix_spawn initialization failed");
@ -923,8 +945,8 @@ privsep_postauth(Authctxt *authctxt)
posix_spawn_file_actions_t actions;
if (posix_spawn_file_actions_init(&actions) != 0 ||
posix_spawn_file_actions_adddup2(&actions, tmp_sock, STDIN_FILENO) != 0 ||
posix_spawn_file_actions_adddup2(&actions, tmp_sock, STDOUT_FILENO) != 0 ||
posix_spawn_file_actions_adddup2(&actions, io_sock_in, STDIN_FILENO) != 0 ||
posix_spawn_file_actions_adddup2(&actions, io_sock_out, STDOUT_FILENO) != 0 ||
posix_spawn_file_actions_adddup2(&actions, pmonitor->m_recvfd, PRIVSEP_MONITOR_FD) != 0)
fatal("posix_spawn initialization failed");
@ -942,6 +964,7 @@ privsep_postauth(Authctxt *authctxt)
send_autxctx_state(authctxt, pmonitor->m_sendfd);
monitor_send_keystate(pmonitor);
monitor_clear_keystate(pmonitor);
monitor_send_authopt(pmonitor, 0); // 0 - trusted.
monitor_child_postauth(pmonitor);
/* NEVERREACHED */
exit(0);
@ -956,6 +979,7 @@ privsep_postauth(Authctxt *authctxt)
do_setusercontext(authctxt->pw);
monitor_apply_keystate(pmonitor);
monitor_recv_authopt(pmonitor);
packet_set_authenticated();
skip:
return;
@ -2383,7 +2407,8 @@ done_loading_hostkeys:
* Register our connection. This turns encryption off because we do
* not have a key.
*/
tmp_sock = sock_in;
io_sock_in = sock_in;
io_sock_out = sock_out;
packet_set_connection(sock_in, sock_out);
packet_set_server();
ssh = active_state; /* XXX */

View File

@ -59,6 +59,9 @@
#include "match.h"
#include "xmss_fast.h"
#ifdef WINDOWS
#include <lmcons.h>
#endif
/* openssh private key file format */
#define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
@ -2646,7 +2649,27 @@ sshkey_cert_check_authority(const struct sshkey *k,
} else if (name != NULL) {
principal_matches = 0;
for (i = 0; i < k->cert->nprincipals; i++) {
#ifdef WINDOWS
char cert_principal_name_copy[UNLEN + DNLEN + 1 + 1] = { 0, };
strcpy_s(cert_principal_name_copy, _countof(cert_principal_name_copy), k->cert->principals[i]);
/*
* For domain user we need special handling.
* We support both "domain\user" and "domain/user" formats.
* compare user, domain separately.
*/
if (strstr(name, "/") || strstr(name, "\\")) {
char *tmp = NULL;
if (tmp = strstr(cert_principal_name_copy, "/"))
*tmp = '\\';
}
/* In windows, usernames are case insensitive */
if (_strcmpi(name, cert_principal_name_copy) == 0) {
#else
if (strcmp(name, k->cert->principals[i]) == 0) {
#endif
principal_matches = 1;
break;
}