diff --git a/Makefile.in b/Makefile.in index 5870e9e6..e247c0de 100644 --- a/Makefile.in +++ b/Makefile.in @@ -80,7 +80,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ canohost.o channels.o cipher.o cipher-aes.o cipher-aesctr.o \ cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \ compat.o crc32.o deattack.o fatal.o hostfile.o \ - log.o match.o md-sha256.o moduli.o nchan.o packet.o opacket.o \ + log.o match.o moduli.o nchan.o packet.o opacket.o \ readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \ atomicio.o key.o dispatch.o mac.o uidswap.o uuencode.o misc.o utf8.o \ monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ diff --git a/appveyor.yml b/appveyor.yml index a9a77d0e..bf622a1b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.0.10.0.{build} +version: 0.0.12.0.{build} image: Visual Studio 2015 branches: @@ -18,10 +18,6 @@ after_build: - ps: | Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking Install-OpenSSH - - ps: Write-Verbose "Restart computer ..." - - ps: Restart-Computer -Force - - ps: Start-Sleep -s 5 # Needs to be proceeded with -ps: as it's interpreted by AppVeyor - - ps: Write-Verbose "Restart computer completed!" before_test: - ps: | diff --git a/auth-pam.c b/auth-pam.c index bc8e5e02..9574d9ac 100644 --- a/auth-pam.c +++ b/auth-pam.c @@ -106,7 +106,6 @@ extern char *__progname; extern ServerOptions options; extern Buffer loginmsg; -extern int compat20; extern u_int utmp_len; /* so we don't silently change behaviour */ @@ -468,18 +467,16 @@ sshpam_thread(void *ctxtp) if (sshpam_err != PAM_SUCCESS) goto auth_fail; - if (compat20) { - if (!do_pam_account()) { - sshpam_err = PAM_ACCT_EXPIRED; + if (!do_pam_account()) { + sshpam_err = PAM_ACCT_EXPIRED; + goto auth_fail; + } + if (sshpam_authctxt->force_pwchange) { + sshpam_err = pam_chauthtok(sshpam_handle, + PAM_CHANGE_EXPIRED_AUTHTOK); + if (sshpam_err != PAM_SUCCESS) goto auth_fail; - } - if (sshpam_authctxt->force_pwchange) { - sshpam_err = pam_chauthtok(sshpam_handle, - PAM_CHANGE_EXPIRED_AUTHTOK); - if (sshpam_err != PAM_SUCCESS) - goto auth_fail; - sshpam_password_change_required(0); - } + sshpam_password_change_required(0); } buffer_put_cstring(&buffer, "OK"); diff --git a/configure.ac b/configure.ac index 82b28ce9..f7a04d55 100644 --- a/configure.ac +++ b/configure.ac @@ -179,6 +179,7 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int main(void) { return 0; }]])], CFLAGS="$saved_CFLAGS" if test "$GCC" = "yes" || test "$GCC" = "egcs"; then + OSSH_CHECK_CFLAG_COMPILE([-pipe]) OSSH_CHECK_CFLAG_COMPILE([-Qunused-arguments]) OSSH_CHECK_CFLAG_COMPILE([-Wunknown-warning-option]) OSSH_CHECK_CFLAG_COMPILE([-Wall]) @@ -2769,9 +2770,6 @@ if test "x$openssl" = "xyes" ; then #include <openssl/evp.h> #include <openssl/objects.h> #include <openssl/opensslv.h> - #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ - # error "OpenSSL < 0.9.8g has unreliable ECC code" - #endif ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); const EVP_MD *m = EVP_sha256(); /* We need this too */ @@ -2790,9 +2788,6 @@ if test "x$openssl" = "xyes" ; then #include <openssl/evp.h> #include <openssl/objects.h> #include <openssl/opensslv.h> - #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ - # error "OpenSSL < 0.9.8g has unreliable ECC code" - #endif ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp384r1); const EVP_MD *m = EVP_sha384(); /* We need this too */ @@ -2811,9 +2806,6 @@ if test "x$openssl" = "xyes" ; then #include <openssl/evp.h> #include <openssl/objects.h> #include <openssl/opensslv.h> - #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ - # error "OpenSSL < 0.9.8g has unreliable ECC code" - #endif ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1); const EVP_MD *m = EVP_sha512(); /* We need this too */ diff --git a/contrib/win32/openssh/AppveyorHelper.psm1 b/contrib/win32/openssh/AppveyorHelper.psm1 index f0f97c0f..3157150e 100644 --- a/contrib/win32/openssh/AppveyorHelper.psm1 +++ b/contrib/win32/openssh/AppveyorHelper.psm1 @@ -81,8 +81,6 @@ function Invoke-AppVeyorFull Set-OpenSSHTestParams Invoke-AppVeyorBuild Install-OpenSSH - Install-OpenSSHTestDependencies - Deploy-OpenSSHTests Setup-OpenSSHTestEnvironment Run-OpenSSHTests Publish-Artifact diff --git a/contrib/win32/openssh/OpenSSHBuildHelper.psm1 b/contrib/win32/openssh/OpenSSHBuildHelper.psm1 index 21adf883..345c7c7f 100644 --- a/contrib/win32/openssh/OpenSSHBuildHelper.psm1 +++ b/contrib/win32/openssh/OpenSSHBuildHelper.psm1 @@ -299,7 +299,10 @@ function Package-OpenSSH [string]$NativeHostArch = "x64", [ValidateSet('Debug', 'Release', '')] - [string]$Configuration = "Release" + [string]$Configuration = "Release", + + # Copy payload to DestinationPath instead of packaging + [string]$DestinationPath = "" ) [System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot @@ -311,9 +314,8 @@ function Package-OpenSSH } $buildDir = Join-Path $repositoryRoot ("bin\" + $folderName + "\" + $Configuration) $payload = "sshd.exe", "ssh.exe", "ssh-agent.exe", "ssh-add.exe", "sftp.exe" - $payload += "sftp-server.exe", "scp.exe", "ssh-lsa.dll", "ssh-shellhost.exe", "ssh-keygen.exe" + $payload += "sftp-server.exe", "scp.exe", "ssh-shellhost.exe", "ssh-keygen.exe" $payload += "sshd_config", "install-sshd.ps1", "uninstall-sshd.ps1" - $payload += "install-sshlsa.ps1", "uninstall-sshlsa.ps1" $packageName = "OpenSSH-Win64" if ($NativeHostArch -eq 'x86') { @@ -343,12 +345,29 @@ function Package-OpenSSH } } - Remove-Item ($packageDir + '.zip') -Force -ErrorAction SilentlyContinue - Compress-Archive -Path $packageDir -DestinationPath ($packageDir + '.zip') + if ($DestinationPath -ne "") { + if (Test-Path $DestinationPath) { + Remove-Item $DestinationPath\* -Force + } + else { + New-Item -ItemType Directory $DestinationPath | Out-Null + } + Copy-Item -Path $packageDir\* -Destination $DestinationPath -Force -Recurse + } + else { + Remove-Item ($packageDir + '.zip') -Force -ErrorAction SilentlyContinue + Compress-Archive -Path $packageDir -DestinationPath ($packageDir + '.zip') + } Remove-Item $packageDir -Recurse -Force -ErrorAction SilentlyContinue - Remove-Item ($symbolsDir + '.zip') -Force -ErrorAction SilentlyContinue - Compress-Archive -Path $symbolsDir -DestinationPath ($symbolsDir + '.zip') + + if ($DestinationPath -ne "") { + Copy-Item -Path $symbolsDir\* -Destination $DestinationPath -Force -Recurse + } + else { + Remove-Item ($symbolsDir + '.zip') -Force -ErrorAction SilentlyContinue + Compress-Archive -Path $symbolsDir -DestinationPath ($symbolsDir + '.zip') + } Remove-Item $symbolsDir -Recurse -Force -ErrorAction SilentlyContinue } @@ -436,97 +455,41 @@ function Get-SolutionFile <# .Synopsis - Deploy all required files to build a package and create zip file. + Deploy all required files to a location and install the binaries #> -function Deploy-Win32OpenSSHBinaries +function Install-OpenSSH { [CmdletBinding()] param - ( + ( [ValidateSet('Debug', 'Release', '')] [string]$Configuration = "", + [ValidateSet('x86', 'x64', '')] [string]$NativeHostArch = "", + [string]$OpenSSHDir = "$env:SystemDrive\OpenSSH" ) - if (-not (Test-Path -Path $OpenSSHDir -PathType Container)) + if ($Configuration -eq "") { - $null = New-Item -Path $OpenSSHDir -ItemType Directory -Force -ErrorAction Stop + $Configuration = 'Release' } - [string] $platform = $env:PROCESSOR_ARCHITECTURE - if(-not [String]::IsNullOrEmpty($NativeHostArch)) + if ($NativeHostArch -eq "") { - $folderName = $NativeHostArch - if($NativeHostArch -ieq 'x86') - { - $folderName = "Win32" - } - } - else - { - if($platform -ieq "AMD64") - { - $folderName = "x64" - } - else - { - $folderName = "Win32" - } - } - - if([String]::IsNullOrEmpty($Configuration)) - { - if( $folderName -ieq "Win32" ) - { - $RealConfiguration = "Debug" - } - else - { - $RealConfiguration = "Release" + $NativeHostArch = 'x64' + if ($env:PROCESSOR_ARCHITECTURE -eq 'x86') { + $NativeHostArch = 'x86' } } - else - { - $RealConfiguration = $Configuration - } - [System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot - - $sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "bin\$folderName\$RealConfiguration" - if((Get-Service ssh-agent -ErrorAction Ignore) -ne $null) { - Stop-Service ssh-agent -Force - } - Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHDir -Include *.exe,*.dll -Exclude *unittest*.* -Force -ErrorAction Stop - $sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "contrib\win32\openssh" - Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHDir -Include *.ps1,sshd_config -Exclude AnalyzeCodeDiff.ps1 -Force -ErrorAction Stop -} - -<# - .Synopsis - Deploy all required files to a location and install the binaries -#> -function Install-OpenSSH -{ - [CmdletBinding()] - param - ( - [ValidateSet('Debug', 'Release', '')] - [string]$Configuration = "", - - [ValidateSet('x86', 'x64', '')] - [string]$NativeHostArch = "", - - [string]$OpenSSHDir = "$env:SystemDrive\OpenSSH" - ) - - Deploy-Win32OpenSSHBinaries @PSBoundParameters + Package-OpenSSH -NativeHostArch $NativeHostArch -Configuration $Configuration -DestinationPath $OpenSSHDir Push-Location $OpenSSHDir & ( "$OpenSSHDir\install-sshd.ps1") .\ssh-keygen.exe -A - & ( "$OpenSSHDir\install-sshlsa.ps1") + #machine will be reboot after Install-openssh anyway $machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE') diff --git a/contrib/win32/openssh/Win32-OpenSSH.sln b/contrib/win32/openssh/Win32-OpenSSH.sln index f808422c..e70453bf 100644 --- a/contrib/win32/openssh/Win32-OpenSSH.sln +++ b/contrib/win32/openssh/Win32-OpenSSH.sln @@ -55,11 +55,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sshd", "sshd.vcxproj", "{F5 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "config", "config.vcxproj", "{8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh-lsa", "ssh-lsa.vcxproj", "{02FB3D98-6516-42C6-9762-98811A99960F}" - ProjectSection(ProjectDependencies) = postProject - {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} - EndProjectSection -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "posix_compat", "win32iocompat.vcxproj", "{0D02F0F0-013B-4EE3-906D-86517F3822C0}" ProjectSection(ProjectDependencies) = postProject {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} @@ -226,14 +221,6 @@ Global {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}.Release|x64.Build.0 = Release|x64 {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}.Release|x86.ActiveCfg = Release|Win32 {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}.Release|x86.Build.0 = Release|Win32 - {02FB3D98-6516-42C6-9762-98811A99960F}.Debug|x64.ActiveCfg = Debug|x64 - {02FB3D98-6516-42C6-9762-98811A99960F}.Debug|x64.Build.0 = Debug|x64 - {02FB3D98-6516-42C6-9762-98811A99960F}.Debug|x86.ActiveCfg = Debug|Win32 - {02FB3D98-6516-42C6-9762-98811A99960F}.Debug|x86.Build.0 = Debug|Win32 - {02FB3D98-6516-42C6-9762-98811A99960F}.Release|x64.ActiveCfg = Release|x64 - {02FB3D98-6516-42C6-9762-98811A99960F}.Release|x64.Build.0 = Release|x64 - {02FB3D98-6516-42C6-9762-98811A99960F}.Release|x86.ActiveCfg = Release|Win32 - {02FB3D98-6516-42C6-9762-98811A99960F}.Release|x86.Build.0 = Release|Win32 {0D02F0F0-013B-4EE3-906D-86517F3822C0}.Debug|x64.ActiveCfg = Debug|x64 {0D02F0F0-013B-4EE3-906D-86517F3822C0}.Debug|x64.Build.0 = Debug|x64 {0D02F0F0-013B-4EE3-906D-86517F3822C0}.Debug|x86.ActiveCfg = Debug|Win32 @@ -343,7 +330,6 @@ Global {6657614F-7821-4D55-96EF-7C3C4B551880} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E} {F58FF6BA-098B-4DB9-9609-A030DFB4D03F} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E} {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E} - {02FB3D98-6516-42C6-9762-98811A99960F} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E} {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E} {C0AE8A30-E4FA-49CE-A2B5-0C072C77EC64} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E} {F6644EC5-D6B6-42A1-828C-75E2977470E0} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E} diff --git a/contrib/win32/openssh/config.h.vs b/contrib/win32/openssh/config.h.vs index 7d5ea2ec..bb5030ec 100644 --- a/contrib/win32/openssh/config.h.vs +++ b/contrib/win32/openssh/config.h.vs @@ -297,7 +297,7 @@ /* Define to 1 if you have the declaration of `O_NONBLOCK', and to 0 if you don't. */ -#define HAVE_DECL_O_NONBLOCK 0 +#define HAVE_DECL_O_NONBLOCK 1 /* Define to 1 if you have the declaration of `passwdexpired', and to 0 if you don't. */ diff --git a/contrib/win32/openssh/keygen.vcxproj b/contrib/win32/openssh/keygen.vcxproj index 690ec33d..ac196225 100644 --- a/contrib/win32/openssh/keygen.vcxproj +++ b/contrib/win32/openssh/keygen.vcxproj @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="paths.targets" /> <ItemGroup Label="ProjectConfigurations"> @@ -186,6 +186,7 @@ <ItemGroup> <ClCompile Include="$(OpenSSH-Src-Path)ssh-keygen.c" /> <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c" /> + <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32-utf8.c" /> </ItemGroup> <ItemGroup> <ResourceCompile Include="version.rc" /> @@ -193,4 +194,4 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project> \ No newline at end of file +</Project> diff --git a/contrib/win32/openssh/keygen.vcxproj.filters b/contrib/win32/openssh/keygen.vcxproj.filters index dd9dd237..8c39fa3e 100644 --- a/contrib/win32/openssh/keygen.vcxproj.filters +++ b/contrib/win32/openssh/keygen.vcxproj.filters @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <Filter Include="Source Files"> @@ -21,10 +21,13 @@ <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32-utf8.c"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ResourceCompile Include="version.rc"> <Filter>Resource Files</Filter> </ResourceCompile> </ItemGroup> -</Project> \ No newline at end of file +</Project> diff --git a/contrib/win32/openssh/libssh.vcxproj b/contrib/win32/openssh/libssh.vcxproj index 16fff961..dc6ce550 100644 --- a/contrib/win32/openssh/libssh.vcxproj +++ b/contrib/win32/openssh/libssh.vcxproj @@ -240,7 +240,6 @@ <ClCompile Include="$(OpenSSH-Src-Path)log.c" /> <ClCompile Include="$(OpenSSH-Src-Path)mac.c" /> <ClCompile Include="$(OpenSSH-Src-Path)match.c" /> - <ClCompile Include="$(OpenSSH-Src-Path)md-sha256.c" /> <ClCompile Include="$(OpenSSH-Src-Path)misc.c" /> <ClCompile Include="$(OpenSSH-Src-Path)moduli.c" /> <ClCompile Include="$(OpenSSH-Src-Path)monitor_fdpass.c" /> diff --git a/contrib/win32/openssh/libssh.vcxproj.filters b/contrib/win32/openssh/libssh.vcxproj.filters index 1959987d..2af40a2d 100644 --- a/contrib/win32/openssh/libssh.vcxproj.filters +++ b/contrib/win32/openssh/libssh.vcxproj.filters @@ -177,9 +177,6 @@ <ClCompile Include="$(OpenSSH-Src-Path)match.c"> <Filter>Source Files</Filter> </ClCompile> - <ClCompile Include="$(OpenSSH-Src-Path)md-sha256.c"> - <Filter>Source Files</Filter> - </ClCompile> <ClCompile Include="$(OpenSSH-Src-Path)misc.c"> <Filter>Source Files</Filter> </ClCompile> diff --git a/contrib/win32/openssh/scp.vcxproj b/contrib/win32/openssh/scp.vcxproj index 7a922545..1a473315 100644 --- a/contrib/win32/openssh/scp.vcxproj +++ b/contrib/win32/openssh/scp.vcxproj @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="paths.targets" /> <ItemGroup Label="ProjectConfigurations"> @@ -22,6 +22,7 @@ <ItemGroup> <ClCompile Include="$(OpenSSH-Src-Path)scp.c" /> <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c" /> + <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32-utf8.c" /> </ItemGroup> <ItemGroup> <ResourceCompile Include="version.rc" /> @@ -191,4 +192,4 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project> \ No newline at end of file +</Project> diff --git a/contrib/win32/openssh/scp.vcxproj.filters b/contrib/win32/openssh/scp.vcxproj.filters index fccf50e0..e3784380 100644 --- a/contrib/win32/openssh/scp.vcxproj.filters +++ b/contrib/win32/openssh/scp.vcxproj.filters @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <Filter Include="Source Files"> @@ -21,10 +21,13 @@ <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32-utf8.c"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ResourceCompile Include="version.rc"> <Filter>Resource Files</Filter> </ResourceCompile> </ItemGroup> -</Project> \ No newline at end of file +</Project> diff --git a/contrib/win32/openssh/sftp.vcxproj b/contrib/win32/openssh/sftp.vcxproj index b5580335..c7ffb6da 100644 --- a/contrib/win32/openssh/sftp.vcxproj +++ b/contrib/win32/openssh/sftp.vcxproj @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="paths.targets" /> <ItemGroup Label="ProjectConfigurations"> @@ -26,6 +26,7 @@ <ClCompile Include="$(OpenSSH-Src-Path)sftp-glob.c" /> <ClCompile Include="$(OpenSSH-Src-Path)sftp.c" /> <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c" /> + <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32-utf8.c" /> </ItemGroup> <ItemGroup> <ResourceCompile Include="version.rc" /> @@ -197,4 +198,4 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project> \ No newline at end of file +</Project> diff --git a/contrib/win32/openssh/sftp.vcxproj.filters b/contrib/win32/openssh/sftp.vcxproj.filters index 04bc6520..60da32cc 100644 --- a/contrib/win32/openssh/sftp.vcxproj.filters +++ b/contrib/win32/openssh/sftp.vcxproj.filters @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <Filter Include="Source Files"> @@ -33,10 +33,13 @@ <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32-utf8.c"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ResourceCompile Include="version.rc"> <Filter>Resource Files</Filter> </ResourceCompile> </ItemGroup> -</Project> \ No newline at end of file +</Project> diff --git a/contrib/win32/openssh/ssh.vcxproj b/contrib/win32/openssh/ssh.vcxproj index d7279344..83c43367 100644 --- a/contrib/win32/openssh/ssh.vcxproj +++ b/contrib/win32/openssh/ssh.vcxproj @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="paths.targets" /> <ItemGroup Label="ProjectConfigurations"> @@ -298,8 +298,9 @@ <ClCompile Include="$(OpenSSH-Src-Path)sshconnect.c" /> <ClCompile Include="$(OpenSSH-Src-Path)sshconnect1.c" /> <ClCompile Include="$(OpenSSH-Src-Path)sshconnect2.c" /> - <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c" /> + <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c" /> <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshtty.c" /> + <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32-utf8.c" /> </ItemGroup> <ItemGroup> <ResourceCompile Include="version.rc" /> @@ -307,4 +308,4 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project> \ No newline at end of file +</Project> diff --git a/contrib/win32/openssh/ssh.vcxproj.filters b/contrib/win32/openssh/ssh.vcxproj.filters index 8acdd0e2..fae9a0fd 100644 --- a/contrib/win32/openssh/ssh.vcxproj.filters +++ b/contrib/win32/openssh/ssh.vcxproj.filters @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <Filter Include="Source Files"> @@ -311,10 +311,13 @@ <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshtty.c"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32-utf8.c"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ResourceCompile Include="version.rc"> <Filter>Resource Files</Filter> </ResourceCompile> </ItemGroup> -</Project> \ No newline at end of file +</Project> diff --git a/contrib/win32/openssh/version.rc b/contrib/win32/openssh/version.rc index c3fdf824..035ec265 100644 Binary files a/contrib/win32/openssh/version.rc and b/contrib/win32/openssh/version.rc differ diff --git a/contrib/win32/openssh/win32iocompat.vcxproj b/contrib/win32/openssh/win32iocompat.vcxproj index c2b0024b..51c41999 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj +++ b/contrib/win32/openssh/win32iocompat.vcxproj @@ -160,7 +160,6 @@ <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tncon.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tnnet.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\utf.c" /> - <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\win32-utf8.c" /> </ItemGroup> <ItemGroup> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" /> diff --git a/contrib/win32/openssh/win32iocompat.vcxproj.filters b/contrib/win32/openssh/win32iocompat.vcxproj.filters index 2152b5fa..456abfed 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj.filters +++ b/contrib/win32/openssh/win32iocompat.vcxproj.filters @@ -19,7 +19,6 @@ <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tncon.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tnnet.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\utf.c" /> - <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\win32-utf8.c" /> </ItemGroup> <ItemGroup> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" /> diff --git a/contrib/win32/win32compat/console.c b/contrib/win32/win32compat/console.c index 11650126..04c04ffe 100644 --- a/contrib/win32/win32compat/console.c +++ b/contrib/win32/win32compat/console.c @@ -1581,11 +1581,11 @@ get_console_handle(FILE *stream, DWORD * mode) file_num = (_fileno)(stream); if (file_num == -1) { - return -1; + return INVALID_HANDLE_VALUE; } lHandle = _get_osfhandle(file_num); if (lHandle == -1 && errno == EBADF) { - return -1; + return INVALID_HANDLE_VALUE; } type = GetFileType((HANDLE)lHandle); if (type == FILE_TYPE_CHAR && file_num >= 0 && file_num <= 2) { diff --git a/contrib/win32/win32compat/fileio.c b/contrib/win32/win32compat/fileio.c index 49da1ad5..7a6cc107 100644 --- a/contrib/win32/win32compat/fileio.c +++ b/contrib/win32/win32compat/fileio.c @@ -29,8 +29,8 @@ */ #include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> +#include "inc/sys/stat.h" +#include "inc/sys/types.h" #include <io.h> #include <errno.h> #include <stddef.h> @@ -55,8 +55,9 @@ struct createFile_flags { DWORD dwFlagsAndAttributes; }; -int termio_initiate_read(struct w32_io* pio); -int termio_initiate_write(struct w32_io* pio, DWORD num_bytes); +int syncio_initiate_read(struct w32_io* pio); +int syncio_initiate_write(struct w32_io* pio, DWORD num_bytes); +int syncio_close(struct w32_io* pio); /* maps Win32 error to errno */ int @@ -440,11 +441,10 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) } if (fileio_is_io_available(pio, TRUE) == FALSE) { - if (FILETYPE(pio) == FILE_TYPE_CHAR) { - if (-1 == termio_initiate_read(pio)) + if (pio->type == NONSOCK_SYNC_FD || FILETYPE(pio) == FILE_TYPE_CHAR) { + if (-1 == syncio_initiate_read(pio)) return -1; - } - else { + } else { if (-1 == fileio_ReadFileEx(pio, max)) { if ((FILETYPE(pio) == FILE_TYPE_PIPE) && (errno == ERROR_BROKEN_PIPE)) { @@ -571,46 +571,12 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) bytes_copied = min(max, pio->write_details.buf_size); memcpy(pio->write_details.buf, buf, bytes_copied); - if (FILETYPE(pio) == FILE_TYPE_CHAR) { - if (termio_initiate_write(pio, bytes_copied) == 0) { + if (pio->type == NONSOCK_SYNC_FD || FILETYPE(pio) == FILE_TYPE_CHAR) { + if (syncio_initiate_write(pio, bytes_copied) == 0) { pio->write_details.pending = TRUE; pio->write_details.remaining = bytes_copied; - } - else - return -1; - } else if ( FILETYPE(pio) == FILE_TYPE_PIPE && - GetNamedPipeInfo(WINHANDLE(pio), &pipe_flags, NULL, NULL, &pipe_instances) && - pipe_flags == PIPE_CLIENT_END && pipe_instances == 1) { - /* - * TODO - Figure out a better solution to this problem - * IO handle corresponding to this object (pio->handle) may be referring - * to something that isn't opened in overlapped mode. While all handles - * opened by this POSIX wrapper are opened in overlapped mode, other handles - * that are inherited (ex. via std i/o) are typically not. - * Ex. When we do this in Powershell - * $o = ssh.exe user@target hostname - * Powershell creates anonymous pipes (that do not support overlapped i.o) - * Calling asynchronous I/O APIs (WriteFileEx) for example will not work in - * those cases (the callback is never called and it typically manifests as a - * hang to end user - * - * This conditional logic is put in place to specifically handle Powershell - * redirection scenarios. Thinking behind these conditions - * - should be a pipe handle. console I/O is handled in termio.c, impacting file i/o - * scenarios not found yet. - * - pipe should be the client end. This is to skip pipes created internally in POSIX - * wrapper (by pipe() calls) - The write ends on these pipes are on server - * - pipe_instances == 1. This is to skip pipe handles created as part of Connect(AF_UNIX) - * sockets (that typically are created for unlimited instances). - * For such I/O we do a synchronous write. - */ - /* DebugBreak() */; - if (WriteFile(WINHANDLE(pio), pio->write_details.buf, bytes_copied, &bytes_copied, NULL) == FALSE) { - errno = errno_from_Win32LastError(); - debug3("write - WriteFile() ERROR:%d, io:%p", GetLastError(), pio); + } else return -1; - } - return bytes_copied; } else { if (WriteFileEx(WINHANDLE(pio), pio->write_details.buf, bytes_copied, &pio->write_overlapped, &WriteCompletionRoutine)) { @@ -753,8 +719,8 @@ fileio_on_select(struct w32_io* pio, BOOL rd) if (!pio->read_details.pending && !fileio_is_io_available(pio, rd)) /* initiate read, record any error so read() will pick up */ - if (FILETYPE(pio) == FILE_TYPE_CHAR) { - if (termio_initiate_read(pio) != 0) { + if (pio->type == NONSOCK_SYNC_FD || FILETYPE(pio) == FILE_TYPE_CHAR) { + if (syncio_initiate_read(pio) != 0) { pio->read_details.error = errno; errno = 0; return; @@ -773,6 +739,9 @@ fileio_close(struct w32_io* pio) { debug4("fileclose - pio:%p", pio); + if (pio->type == NONSOCK_SYNC_FD || FILETYPE(pio) == FILE_TYPE_CHAR) + return syncio_close(pio); + /* handle can be null on AF_UNIX sockets that are not yet connected */ if (WINHANDLE(pio) == 0 || WINHANDLE(pio) == INVALID_HANDLE_VALUE) { free(pio); @@ -782,15 +751,13 @@ fileio_close(struct w32_io* pio) CancelIo(WINHANDLE(pio)); /* let queued APCs (if any) drain */ SleepEx(0, TRUE); - if (pio->type != STD_IO_FD) { /* STD handles are never explicitly closed */ - CloseHandle(WINHANDLE(pio)); - + CloseHandle(WINHANDLE(pio)); + /* free up non stdio */ + if (!IS_STDIO(pio)) { if (pio->read_details.buf) free(pio->read_details.buf); - if (pio->write_details.buf) free(pio->write_details.buf); - free(pio); } return 0; diff --git a/contrib/win32/win32compat/inc/fcntl.h b/contrib/win32/win32compat/inc/fcntl.h index 3f651493..fba482ee 100644 --- a/contrib/win32/win32compat/inc/fcntl.h +++ b/contrib/win32/win32compat/inc/fcntl.h @@ -22,7 +22,6 @@ int w32_open(const char *pathname, int flags, ...); void* w32_fd_to_handle(int fd); int w32_allocate_fd_for_handle(void* h, int is_sock); -#define O_ACCMODE 0x0003 #define O_RDONLY _O_RDONLY #define O_WRONLY _O_WRONLY #define O_RDWR _O_RDWR @@ -37,4 +36,26 @@ int w32_allocate_fd_for_handle(void* h, int is_sock); #define O_NOINHERIT _O_NOINHERIT #define O_SEQUENTIAL _O_SEQUENTIAL #define O_RANDOM _O_RANDOM -#define O_U16TEXT _O_U16TEXT \ No newline at end of file +#define O_U16TEXT _O_U16TEXT + +/* +* open() POSIX specific modes and flags. +* Caution while making changes +* - cross check conflict with common macros in Windows headers +* - Ex. #define O_APPEND 0x8 +*/ +#define O_ACCMODE 0x0003 +#define O_NONBLOCK 0x0004 /*io operations wont block*/ +# define S_IXUSR 0000100 /* execute/search permission, */ +# define S_IXGRP 0000010 /* execute/search permission, */ +# define S_IXOTH 0000001 /* execute/search permission, */ +# define _S_IWUSR 0000200 /* write permission, */ +# define S_IWUSR _S_IWUSR /* write permission, owner */ +# define S_IWGRP 0000020 /* write permission, group */ +# define S_IWOTH 0000002 /* write permission, other */ +# define S_IRUSR 0000400 /* read permission, owner */ +# define S_IRGRP 0000040 /* read permission, group */ +# define S_IROTH 0000004 /* read permission, other */ +# define S_IRWXU 0000700 /* read, write, execute */ +# define S_IRWXG 0000070 /* read, write, execute */ +# define S_IRWXO 0000007 /* read, write, execute */ \ No newline at end of file diff --git a/contrib/win32/win32compat/misc.c b/contrib/win32/win32compat/misc.c index 93b1af39..99bbaf3b 100644 --- a/contrib/win32/win32compat/misc.c +++ b/contrib/win32/win32compat/misc.c @@ -404,123 +404,6 @@ w32_ioctl(int d, int request, ...) } } -/* - * spawn a child process - * - specified by cmd with agruments argv - * - with std handles set to in, out, err - * - flags are passed to CreateProcess call - * - * cmd will be internally decoarated with a set of '"' - * to account for any spaces within the commandline - * this decoration is done only when additional arguments are passed in argv - */ -int -spawn_child(char* cmd, char** argv, int in, int out, int err, DWORD flags) -{ - PROCESS_INFORMATION pi; - STARTUPINFOW si; - BOOL b; - char *cmdline, *t, **t1; - DWORD cmdline_len = 0; - wchar_t * cmdline_utf16; - int add_module_path = 0, ret = -1; - - /* should module path be added */ - do { - if (!cmd) - break; - t = cmd; - if (*t == '\"') - t++; - if (t[0] == '\0' || t[0] == '\\' || t[0] == '.' || t[1] == ':') - break; - add_module_path = 1; - } while (0); - - /* compute total cmdline len*/ - if (add_module_path) - cmdline_len += strlen(w32_programdir()) + 1 + strlen(cmd) + 1 + 2; - else - cmdline_len += strlen(cmd) + 1 + 2; - - if (argv) { - t1 = argv; - while (*t1) - cmdline_len += strlen(*t1++) + 1 + 2; - } - - if ((cmdline = malloc(cmdline_len)) == NULL) { - errno = ENOMEM; - goto cleanup; - } - - /* add current module path to start if needed */ - t = cmdline; - if (argv && argv[0]) - *t++ = '\"'; - if (add_module_path) { - memcpy(t, w32_programdir(), strlen(w32_programdir())); - t += strlen(w32_programdir()); - *t++ = '\\'; - } - - memcpy(t, cmd, strlen(cmd)); - t += strlen(cmd); - - if (argv && argv[0]) - *t++ = '\"'; - - if (argv) { - t1 = argv; - while (*t1) { - *t++ = ' '; - *t++ = '\"'; - memcpy(t, *t1, strlen(*t1)); - t += strlen(*t1); - *t++ = '\"'; - t1++; - } - } - - *t = '\0'; - - if ((cmdline_utf16 = utf8_to_utf16(cmdline)) == NULL) { - errno = ENOMEM; - goto cleanup; - } - - memset(&si, 0, sizeof(STARTUPINFOW)); - si.cb = sizeof(STARTUPINFOW); - si.hStdInput = w32_fd_to_handle(in); - si.hStdOutput = w32_fd_to_handle(out); - si.hStdError = w32_fd_to_handle(err); - si.dwFlags = STARTF_USESTDHANDLES; - - debug3("spawning %ls", cmdline_utf16); - b = CreateProcessW(NULL, cmdline_utf16, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi); - - if (b) { - if (register_child(pi.hProcess, pi.dwProcessId) == -1) { - TerminateProcess(pi.hProcess, 0); - CloseHandle(pi.hProcess); - goto cleanup; - } - CloseHandle(pi.hThread); - } else { - errno = GetLastError(); - goto cleanup; - } - - ret = pi.dwProcessId; -cleanup: - if (cmdline) - free(cmdline); - if (cmdline_utf16) - free(cmdline_utf16); - - return ret; -} - void strmode(mode_t mode, char *p) { diff --git a/contrib/win32/win32compat/misc_internal.h b/contrib/win32/win32compat/misc_internal.h index 6150de03..fa9a0d7b 100644 --- a/contrib/win32/win32compat/misc_internal.h +++ b/contrib/win32/win32compat/misc_internal.h @@ -1,5 +1,8 @@ #pragma once #define PATH_MAX MAX_PATH +#define SSH_ASYNC_STDIN "SSH_ASYNC_STDIN" +#define SSH_ASYNC_STDOUT "SSH_ASYNC_STDOUT" +#define SSH_ASYNC_STDERR "SSH_ASYNC_STDERR" /* removes first '/' for Windows paths that are unix styled. Ex: /c:/ab.cd */ char * sanitized_path(const char *); diff --git a/contrib/win32/win32compat/signal.c b/contrib/win32/win32compat/signal.c index 035f79ce..d0499031 100644 --- a/contrib/win32/win32compat/signal.c +++ b/contrib/win32/win32compat/signal.c @@ -78,7 +78,7 @@ sigtstp_APCProc(_In_ ULONG_PTR dwParam) BOOL WINAPI native_sig_handler(DWORD dwCtrlType) { - debug3("Native Ctrl+C handler, CtrlType %d", dwCtrlType); + debug4("Native Ctrl+C handler, CtrlType %d", dwCtrlType); switch (dwCtrlType) { case CTRL_C_EVENT: QueueUserAPC(sigint_APCProc, main_thread, (ULONG_PTR)NULL); @@ -154,7 +154,7 @@ w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) int w32_raise(int sig) { - debug3("raise sig:%d", sig); + debug4("raise sig:%d", sig); if (sig == W32_SIGSEGV) return raise(SIGSEGV); /* raise native exception handler*/ @@ -229,7 +229,7 @@ sw_process_pending_signals() DebugBreak(); if (sig_int) { - debug3("process_queued_signals: WARNING - A signal has interrupted and was processed"); + debug4("process_queued_signals: WARNING - A signal has interrupted and was processed"); errno = EINTR; return -1; } diff --git a/contrib/win32/win32compat/socketio.c b/contrib/win32/win32compat/socketio.c index f935fe35..5e9d6621 100644 --- a/contrib/win32/win32compat/socketio.c +++ b/contrib/win32/win32compat/socketio.c @@ -104,12 +104,20 @@ int socketio_acceptEx(struct w32_io* pio) { struct acceptEx_context *context; + struct sockaddr_storage addr; int addrlen = sizeof addr; + debug5("acceptEx - io:%p", pio); context = (struct acceptEx_context *)pio->internal.context; ResetEvent(pio->read_overlapped.hEvent); + if (getsockname(pio->sock, (struct sockaddr*)&addr, &addrlen) == SOCKET_ERROR) { + errno = errno_from_WSALastError(); + debug("acceptEx - getsockname() ERROR:%d, io:%p", errno, pio); + return -1; + } + /* create accepting socket */ - context->accept_socket = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); + context->accept_socket = socket(addr.ss_family, SOCK_STREAM, IPPROTO_TCP); if (context->accept_socket == INVALID_SOCKET) { errno = errno_from_WSALastError(); debug3("acceptEx - socket() ERROR:%d, io:%p", errno, pio); diff --git a/contrib/win32/win32compat/ssh-agent/authagent-request.c b/contrib/win32/win32compat/ssh-agent/authagent-request.c index 0fd765eb..291f332f 100644 --- a/contrib/win32/win32compat/ssh-agent/authagent-request.c +++ b/contrib/win32/win32compat/ssh-agent/authagent-request.c @@ -127,7 +127,7 @@ generate_user_token(wchar_t* user_cpn) { if (domain_user) InitLsaString(&auth_package_name, MICROSOFT_KERBEROS_NAME_A); else - InitLsaString(&auth_package_name, "SSH-LSA"); + InitLsaString(&auth_package_name, MSV1_0_PACKAGE_NAME); InitLsaString(&originName, "sshd"); if (ret = LsaRegisterLogonProcess(&logon_process_name, &lsa_handle, &mode) != STATUS_SUCCESS) @@ -154,11 +154,24 @@ generate_user_token(wchar_t* user_cpn) { s4u_logon->ClientRealm.MaximumLength = 0; s4u_logon->ClientRealm.Buffer = 0; } else { - logon_info_size = (wcslen(user_cpn) + 1)*sizeof(wchar_t); + MSV1_0_S4U_LOGON *s4u_logon; + logon_info_size = sizeof(MSV1_0_S4U_LOGON); + /* additional buffer size = size of user_cpn + size of "." and their null terminators */ + logon_info_size += (wcslen(user_cpn) * 2 + 2) + 4; logon_info = malloc(logon_info_size); if (logon_info == NULL) goto done; - memcpy(logon_info, user_cpn, logon_info_size); + s4u_logon = (MSV1_0_S4U_LOGON*)logon_info; + s4u_logon->MessageType = MsV1_0S4ULogon; + s4u_logon->Flags = 0; + s4u_logon->UserPrincipalName.Length = wcslen(user_cpn) * 2; + s4u_logon->UserPrincipalName.MaximumLength = s4u_logon->UserPrincipalName.Length; + s4u_logon->UserPrincipalName.Buffer = (WCHAR*)(s4u_logon + 1); + memcpy(s4u_logon->UserPrincipalName.Buffer, user_cpn, s4u_logon->UserPrincipalName.Length + 2); + s4u_logon->DomainName.Length = 2; + s4u_logon->DomainName.MaximumLength = 2; + s4u_logon->DomainName.Buffer = ((WCHAR*)s4u_logon->UserPrincipalName.Buffer) + wcslen(user_cpn) + 1; + memcpy(s4u_logon->DomainName.Buffer, L".", 4); } memcpy(sourceContext.SourceName,"sshagent", sizeof(sourceContext.SourceName)); @@ -180,7 +193,7 @@ generate_user_token(wchar_t* user_cpn) { &token, "as, &subStatus) != STATUS_SUCCESS) { - debug("LsaLogonUser failed %d", ret); + debug("LsaLogonUser failed NTSTATUS: %d", ret); goto done; } debug3("LsaLogonUser succeeded"); @@ -265,7 +278,7 @@ int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response, char *key_blob, *user, *sig, *blob; size_t key_blob_len, user_len, sig_len, blob_len; struct sshkey *key = NULL; - HANDLE token = NULL, restricted_token = NULL, dup_token = NULL, client_proc = NULL; + HANDLE token = NULL, dup_token = NULL, client_proc = NULL; wchar_t *user_utf16 = NULL, *udom_utf16 = NULL, *tmp; PWSTR wuser_home = NULL; ULONG client_pid; @@ -292,14 +305,8 @@ int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response, goto done; } - /* for key based auth, remove SeTakeOwnershipPrivilege */ - if (LookupPrivilegeValueW(NULL, L"SeTakeOwnershipPrivilege", &priv_to_delete[0].Luid) == FALSE || - CreateRestrictedToken(token, 0, 0, NULL, 1, priv_to_delete, 0, NULL, &restricted_token) == FALSE) { - debug("unable to remove SeTakeOwnershipPrivilege privilege"); - goto done; - } - if (SHGetKnownFolderPath(&FOLDERID_Profile, 0, restricted_token, &wuser_home) != S_OK || + if (SHGetKnownFolderPath(&FOLDERID_Profile, 0, token, &wuser_home) != S_OK || pubkey_allowed(key, user_utf16, wuser_home) != 1) { debug("unable to verify public key for user %ls (profile:%ls)", user_utf16, wuser_home); goto done; @@ -312,14 +319,14 @@ int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response, if ((FALSE == GetNamedPipeClientProcessId(con->connection, &client_pid)) || ( (client_proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL) || - (FALSE == DuplicateHandle(GetCurrentProcess(), restricted_token, client_proc, &dup_token, TOKEN_QUERY | TOKEN_IMPERSONATE, FALSE, DUPLICATE_SAME_ACCESS)) || + (FALSE == DuplicateHandle(GetCurrentProcess(), token, client_proc, &dup_token, TOKEN_QUERY | TOKEN_IMPERSONATE, FALSE, DUPLICATE_SAME_ACCESS)) || (sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)) { debug("failed to authorize user"); goto done; } - con->auth_token = restricted_token; - restricted_token = NULL; + con->auth_token = token; + token = NULL; if ((tmp = wcschr(user_utf16, L'@')) != NULL) { udom_utf16 = tmp + 1; *tmp = L'\0'; diff --git a/contrib/win32/win32compat/termio.c b/contrib/win32/win32compat/termio.c index 33ed14ef..945e227b 100644 --- a/contrib/win32/win32compat/termio.c +++ b/contrib/win32/win32compat/termio.c @@ -9,6 +9,10 @@ * Author: Balu <bagajjal@microsoft.com> * Misc fixes and code cleanup * + * Author: Manoj Ampalam <manojamp@microsoft.com> + * Extended support to other Windows IO that does not support + * overlapped IO. Ex. pipe handles returned by CreatePipe() + * * Copyright (c) 2017 Microsoft Corp. * All rights reserved * @@ -71,18 +75,26 @@ ReadAPCProc(_In_ ULONG_PTR dwParam) /* Read worker thread */ static DWORD WINAPI -ReadConsoleThread(_In_ LPVOID lpParameter) +ReadThread(_In_ LPVOID lpParameter) { int nBytesReturned = 0; struct w32_io* pio = (struct w32_io*)lpParameter; debug5("TermRead thread, io:%p", pio); memset(&read_status, 0, sizeof(read_status)); - while (nBytesReturned == 0) { - nBytesReturned = ReadConsoleForTermEmul(WINHANDLE(pio), - pio->read_details.buf, pio->read_details.buf_size); + if (FILETYPE(pio) == FILE_TYPE_CHAR) { + while (nBytesReturned == 0) { + nBytesReturned = ReadConsoleForTermEmul(WINHANDLE(pio), + pio->read_details.buf, pio->read_details.buf_size); + } + read_status.transferred = nBytesReturned; + } else { + if (!ReadFile(WINHANDLE(pio), pio->read_details.buf, + pio->read_details.buf_size, &read_status.transferred, NULL)) { + read_status.error = GetLastError(); + debug("ReadThread - ReadFile failed %d, io:%p", GetLastError(), pio); + } } - read_status.transferred = nBytesReturned; if (0 == QueueUserAPC(ReadAPCProc, main_thread, (ULONG_PTR)pio)) { debug3("TermRead thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio); pio->read_details.pending = FALSE; @@ -95,11 +107,11 @@ ReadConsoleThread(_In_ LPVOID lpParameter) /* Initiates read on tty */ int -termio_initiate_read(struct w32_io* pio) +syncio_initiate_read(struct w32_io* pio) { HANDLE read_thread; - debug5("TermRead initiate io:%p", pio); + debug5("syncio_initiate_read io:%p", pio); if (pio->read_details.buf_size == 0) { pio->read_details.buf = malloc(TERM_IO_BUF_SIZE); if (pio->read_details.buf == NULL) { @@ -109,7 +121,7 @@ termio_initiate_read(struct w32_io* pio) pio->read_details.buf_size = TERM_IO_BUF_SIZE; } - read_thread = CreateThread(NULL, 0, ReadConsoleThread, pio, 0, NULL); + read_thread = CreateThread(NULL, 0, ReadThread, pio, 0, NULL); if (read_thread == NULL) { errno = errno_from_Win32Error(GetLastError()); debug3("TermRead initiate - ERROR CreateThread %d, io:%p", GetLastError(), pio); @@ -148,19 +160,26 @@ WriteThread(_In_ LPVOID lpParameter) size_t resplen = 0; debug5("TermWrite thread, io:%p", pio); - pio->write_details.buf[write_status.to_transfer] = '\0'; - - if (0 == in_raw_mode) { - wchar_t* t = utf8_to_utf16(pio->write_details.buf); - WriteConsoleW(WINHANDLE(pio), t, wcslen(t), 0, 0); - free(t); + if (FILETYPE(pio) == FILE_TYPE_CHAR) { + pio->write_details.buf[write_status.to_transfer] = '\0'; + if (0 == in_raw_mode) { + wchar_t* t = utf8_to_utf16(pio->write_details.buf); + WriteConsoleW(WINHANDLE(pio), t, wcslen(t), 0, 0); + free(t); + } else { + processBuffer(WINHANDLE(pio), pio->write_details.buf, write_status.to_transfer, &respbuf, &resplen); + /* TODO - respbuf is not null in some cases, this needs to be returned back via read stream */ + } + write_status.transferred = write_status.to_transfer; } else { - processBuffer(WINHANDLE(pio), pio->write_details.buf, write_status.to_transfer, &respbuf, &resplen); - /* TODO - respbuf is not null in some cases, this needs to be returned back via read stream */ + if (!WriteFile(WINHANDLE(pio), pio->write_details.buf, write_status.to_transfer, + &write_status.transferred, NULL)) { + write_status.error = GetLastError(); + debug("WriteThread - ReadFile WriteFile %d, io:%p", GetLastError(), pio); + } } - write_status.transferred = write_status.to_transfer; - + if (0 == QueueUserAPC(WriteAPCProc, main_thread, (ULONG_PTR)pio)) { debug3("TermWrite thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio); pio->write_details.pending = FALSE; @@ -173,7 +192,7 @@ WriteThread(_In_ LPVOID lpParameter) /* Initiates write on tty */ int -termio_initiate_write(struct w32_io* pio, DWORD num_bytes) +syncio_initiate_write(struct w32_io* pio, DWORD num_bytes) { HANDLE write_thread; debug5("TermWrite initiate io:%p", pio); @@ -193,21 +212,27 @@ termio_initiate_write(struct w32_io* pio, DWORD num_bytes) /* tty close */ int -termio_close(struct w32_io* pio) +syncio_close(struct w32_io* pio) { - debug4("termio_close - pio:%p", pio); + debug4("syncio_close - pio:%p", pio); HANDLE h; CancelIoEx(WINHANDLE(pio), NULL); - /* If io is pending, let write worker threads exit. The read thread is blocked so terminate it.*/ - if (pio->read_details.pending) - TerminateThread(pio->read_overlapped.hEvent, 0); + + /* If io is pending, let worker threads exit. */ + if (pio->read_details.pending) { + /* For console - the read thread is blocked so terminate it. */ + if (FILETYPE(pio) == FILE_TYPE_CHAR) + TerminateThread(pio->read_overlapped.hEvent, 0); + else + WaitForSingleObject(pio->read_overlapped.hEvent, INFINITE); + } if (pio->write_details.pending) WaitForSingleObject(pio->write_overlapped.hEvent, INFINITE); /* drain queued APCs */ SleepEx(0, TRUE); - if (pio->type != STD_IO_FD) { - /* STD handles are never explicitly closed */ - CloseHandle(WINHANDLE(pio)); + CloseHandle(WINHANDLE(pio)); + /* free up if non stdio */ + if (!IS_STDIO(pio)) { if (pio->read_details.buf) free(pio->read_details.buf); if (pio->write_details.buf) diff --git a/contrib/win32/win32compat/ttymodes_windows.c b/contrib/win32/win32compat/ttymodes_windows.c index 6d8db1fd..4171d49c 100644 --- a/contrib/win32/win32compat/ttymodes_windows.c +++ b/contrib/win32/win32compat/ttymodes_windows.c @@ -24,7 +24,7 @@ #include "includes.h" -#include <sys/types.h> +#include "inc/sys/types.h" #include <errno.h> #include <string.h> diff --git a/contrib/win32/win32compat/w32fd.c b/contrib/win32/win32compat/w32fd.c index 4e48f964..3921fd44 100644 --- a/contrib/win32/win32compat/w32fd.c +++ b/contrib/win32/win32compat/w32fd.c @@ -36,6 +36,7 @@ #include "inc\unistd.h" #include "inc\fcntl.h" #include "inc\sys\un.h" +#include "inc\utf.h" #include "w32fd.h" #include "signal_internal.h" @@ -74,15 +75,24 @@ fd_table_initialize() memset(&fd_table, 0, sizeof(fd_table)); memset(&w32_io_stdin, 0, sizeof(w32_io_stdin)); w32_io_stdin.std_handle = STD_INPUT_HANDLE; - w32_io_stdin.type = STD_IO_FD; + w32_io_stdin.type = NONSOCK_SYNC_FD; + if (getenv(SSH_ASYNC_STDIN) && strcmp(getenv(SSH_ASYNC_STDIN), "1") == 0) + w32_io_stdin.type = NONSOCK_FD; + _putenv_s(SSH_ASYNC_STDIN, ""); fd_table_set(&w32_io_stdin, STDIN_FILENO); memset(&w32_io_stdout, 0, sizeof(w32_io_stdout)); w32_io_stdout.std_handle = STD_OUTPUT_HANDLE; - w32_io_stdout.type = STD_IO_FD; + w32_io_stdout.type = NONSOCK_SYNC_FD; + if (getenv(SSH_ASYNC_STDOUT) && strcmp(getenv(SSH_ASYNC_STDOUT), "1") == 0) + w32_io_stdout.type = NONSOCK_FD; + _putenv_s(SSH_ASYNC_STDOUT, ""); fd_table_set(&w32_io_stdout, STDOUT_FILENO); memset(&w32_io_stderr, 0, sizeof(w32_io_stderr)); w32_io_stderr.std_handle = STD_ERROR_HANDLE; - w32_io_stderr.type = STD_IO_FD; + w32_io_stderr.type = NONSOCK_SYNC_FD; + if (getenv(SSH_ASYNC_STDERR) && strcmp(getenv(SSH_ASYNC_STDERR), "1") == 0) + w32_io_stderr.type = NONSOCK_FD; + _putenv_s(SSH_ASYNC_STDERR, ""); fd_table_set(&w32_io_stderr, STDERR_FILENO); return 0; } @@ -128,7 +138,6 @@ fd_table_set(struct w32_io* pio, int index) static void fd_table_clear(int index) { - fd_table.w32_ios[index]->table_index = -1; fd_table.w32_ios[index] = NULL; FD_CLR(index, &(fd_table.occupied)); } @@ -483,6 +492,7 @@ int w32_close(int fd) { struct w32_io* pio; + int r; if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) { errno = EBADF; return -1; @@ -492,17 +502,14 @@ w32_close(int fd) debug3("close - io:%p, type:%d, fd:%d, table_index:%d", pio, pio->type, fd, pio->table_index); - fd_table_clear(pio->table_index); - + if (pio->type == SOCK_FD) - return socketio_close(pio); + r = socketio_close(pio); else - switch (FILETYPE(pio)) { - case FILE_TYPE_CHAR: - return termio_close(pio); - default: - return fileio_close(pio); - } + r = fileio_close(pio); + + fd_table_clear(fd); + return r; } static int @@ -798,7 +805,7 @@ w32_dup(int oldfd) memset(pio, 0, sizeof(struct w32_io)); pio->handle = target; - pio->type = NONSOCK_FD; + pio->type = fd_table.w32_ios[oldfd]->type; fd_table_set(pio, min_index); return min_index; } @@ -866,3 +873,131 @@ w32_fsync(int fd) CHECK_FD(fd); return FlushFileBuffers(w32_fd_to_handle(fd)); } + + +/* +* spawn a child process +* - specified by cmd with agruments argv +* - with std handles set to in, out, err +* - flags are passed to CreateProcess call +* +* cmd will be internally decoarated with a set of '"' +* to account for any spaces within the commandline +* this decoration is done only when additional arguments are passed in argv +*/ +int +spawn_child(char* cmd, char** argv, int in, int out, int err, DWORD flags) +{ + PROCESS_INFORMATION pi; + STARTUPINFOW si; + BOOL b; + char *cmdline, *t, **t1; + DWORD cmdline_len = 0; + wchar_t * cmdline_utf16; + int add_module_path = 0, ret = -1; + + /* should module path be added */ + do { + if (!cmd) + break; + t = cmd; + if (*t == '\"') + t++; + if (t[0] == '\0' || t[0] == '\\' || t[0] == '.' || t[1] == ':') + break; + add_module_path = 1; + } while (0); + + /* compute total cmdline len*/ + if (add_module_path) + cmdline_len += strlen(w32_programdir()) + 1 + strlen(cmd) + 1 + 2; + else + cmdline_len += strlen(cmd) + 1 + 2; + + if (argv) { + t1 = argv; + while (*t1) + cmdline_len += strlen(*t1++) + 1 + 2; + } + + if ((cmdline = malloc(cmdline_len)) == NULL) { + errno = ENOMEM; + goto cleanup; + } + + /* add current module path to start if needed */ + t = cmdline; + if (argv && argv[0]) + *t++ = '\"'; + if (add_module_path) { + memcpy(t, w32_programdir(), strlen(w32_programdir())); + t += strlen(w32_programdir()); + *t++ = '\\'; + } + + memcpy(t, cmd, strlen(cmd)); + t += strlen(cmd); + + if (argv && argv[0]) + *t++ = '\"'; + + if (argv) { + t1 = argv; + while (*t1) { + *t++ = ' '; + *t++ = '\"'; + memcpy(t, *t1, strlen(*t1)); + t += strlen(*t1); + *t++ = '\"'; + t1++; + } + } + + *t = '\0'; + + if ((cmdline_utf16 = utf8_to_utf16(cmdline)) == NULL) { + errno = ENOMEM; + goto cleanup; + } + + memset(&si, 0, sizeof(STARTUPINFOW)); + si.cb = sizeof(STARTUPINFOW); + si.hStdInput = w32_fd_to_handle(in); + si.hStdOutput = w32_fd_to_handle(out); + si.hStdError = w32_fd_to_handle(err); + si.dwFlags = STARTF_USESTDHANDLES; + + debug3("spawning %ls", cmdline_utf16); + if (fd_table.w32_ios[in]->type != NONSOCK_SYNC_FD) + _putenv_s(SSH_ASYNC_STDIN, "1"); + if (fd_table.w32_ios[out]->type != NONSOCK_SYNC_FD) + _putenv_s(SSH_ASYNC_STDOUT, "1"); + if (fd_table.w32_ios[err]->type != NONSOCK_SYNC_FD) + _putenv_s(SSH_ASYNC_STDERR, "1"); + b = CreateProcessW(NULL, cmdline_utf16, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi); + _putenv_s(SSH_ASYNC_STDIN, ""); + _putenv_s(SSH_ASYNC_STDOUT, ""); + _putenv_s(SSH_ASYNC_STDERR, ""); + + if (b) { + if (register_child(pi.hProcess, pi.dwProcessId) == -1) { + TerminateProcess(pi.hProcess, 0); + CloseHandle(pi.hProcess); + goto cleanup; + } + CloseHandle(pi.hThread); + } + else { + errno = GetLastError(); + goto cleanup; + } + + ret = pi.dwProcessId; +cleanup: + if (cmdline) + free(cmdline); + if (cmdline_utf16) + free(cmdline_utf16); + + return ret; +} diff --git a/contrib/win32/win32compat/w32fd.h b/contrib/win32/win32compat/w32fd.h index 0387a00f..22f23592 100644 --- a/contrib/win32/win32compat/w32fd.h +++ b/contrib/win32/win32compat/w32fd.h @@ -39,7 +39,22 @@ enum w32_io_type { UNKNOWN_FD = 0, SOCK_FD = 1, /*maps a socket fd*/ NONSOCK_FD = 2, /*maps a file fd, pipe fd or a tty fd*/ - STD_IO_FD = 5 /*maps a std fd - ex. STDIN_FILE*/ + /* + * maps a NONSOCK_FD that doesnt support async or overlapped io + * these are typically used for stdio on ssh client side + * executables (ssh, sftp and scp). + * Ex. ssh ... > output.txt + * In the above case, stdout passed to ssh.exe is a handle to + * output.txt that is opened in non-overlapped mode + * Ex. sample.exe | ssh ... + * In the above case, stdin passed to ssh.exe is a handle to + * a pipe opened in non-overlapped mode + * Ex. in Powershell + * $o = ssh ... + * In the above case, stdout passed to ssh.exe is a handle to + * a pipe opened in non-overlapped mode + */ + NONSOCK_SYNC_FD = 3 }; enum w32_io_sock_state { @@ -51,7 +66,7 @@ enum w32_io_sock_state { }; /* -* This structure encapsulates the state info needed to map a File Descriptor +* This structure encapsulates the I/O state info needed to map a File Descriptor * to Win32 Handle */ struct w32_io { @@ -94,7 +109,8 @@ struct w32_io { }internal; }; -#define WINHANDLE(pio) (((pio)->type == STD_IO_FD)? GetStdHandle((pio)->std_handle):(pio)->handle) +#define IS_STDIO(pio) ((pio)->table_index <= 2) +#define WINHANDLE(pio) (IS_STDIO(pio)? GetStdHandle((pio)->std_handle):(pio)->handle) #define FILETYPE(pio) (GetFileType(WINHANDLE(pio))) extern HANDLE main_thread; @@ -102,7 +118,7 @@ BOOL w32_io_is_blocking(struct w32_io*); BOOL w32_io_is_io_available(struct w32_io* pio, BOOL rd); int wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds); -/*POSIX mimic'ing socket API*/ +/*POSIX mimic'ing socket API and socket helper API*/ int socketio_initialize(); int socketio_done(); BOOL socketio_is_io_available(struct w32_io* pio, BOOL rd); @@ -122,7 +138,7 @@ int socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags); int socketio_shutdown(struct w32_io* pio, int how); int socketio_close(struct w32_io* pio); -/*POSIX mimic'ing file API*/ +/*POSIX mimic'ing file API and file helper API*/ BOOL fileio_is_io_available(struct w32_io* pio, BOOL rd); void fileio_on_select(struct w32_io* pio, BOOL rd); int fileio_close(struct w32_io* pio); @@ -136,45 +152,3 @@ int fileio_fstat(struct w32_io* pio, struct _stat64 *buf); int fileio_stat(const char *path, struct _stat64 *buf); long fileio_lseek(struct w32_io* pio, long offset, int origin); FILE* fileio_fdopen(struct w32_io* pio, const char *mode); - -/* terminal io specific versions */ -int termio_close(struct w32_io* pio); - -/* -* open() flags and modes -* all commented out macros are defined in fcntl.h -* they are listed here so as to cross check any conflicts with macros explicitly -* defined below. -*/ -/*open access modes. only one of these can be specified*/ -/* #define O_RDONLY 0x0 */ -/* #define O_WRONLY 0x1 */ -/* #define O_RDWR 0x2 */ -/* open file creation and file status flags can be bitwise-or'd*/ -/* #define O_APPEND 0x8 /*file is opened in append mode*/ -#ifndef O_NONBLOCK -#define O_NONBLOCK 0x0004 /*io operations wont block*/ -#endif -/* #define O_CREAT 0x100 /*If the file does not exist it will be created*/ -/* -* If the file exists and is a regular file, and the file is successfully -* opened O_RDWR or O_WRONLY, its length shall be truncated to 0, and the mode -* and owner shall be unchanged -*/ -/* #define O_TRUNC 0x200 */ -/* If O_CREAT and O_EXCL are set, open() shall fail if the file exists */ -/* #define O_EXCL 0x400 */ -/* #define O_BINARY 0x8000 //Gives raw data (while O_TEXT normalises line endings */ -/* open modes */ -#ifndef S_IRUSR -#define S_IRUSR 00400 /* user has read permission */ -#endif /* ! S_IRUSR */ -#ifndef S_IWUSR -#define S_IWUSR 00200 /* user has write permission */ -#endif -#ifndef S_IRGRP -#define S_IRGRP 00040 /* group has read permission */ -#endif -#ifndef S_IROTH -#define S_IROTH 00004 /* others have read permission */ -#endif \ No newline at end of file diff --git a/contrib/win32/win32compat/w32log.c b/contrib/win32/win32compat/w32log.c index 1df65d5b..327b366c 100644 --- a/contrib/win32/win32compat/w32log.c +++ b/contrib/win32/win32compat/w32log.c @@ -30,7 +30,7 @@ #include <Windows.h> #include <io.h> #include <fcntl.h> -#include <sys/stat.h> +#include "inc/sys/stat.h" #include "inc\syslog.h" #include "misc_internal.h" diff --git a/contrib/win32/win32compat/wmain_common.c b/contrib/win32/win32compat/wmain_common.c index 3d09ceea..fb6ca8f1 100644 --- a/contrib/win32/win32compat/wmain_common.c +++ b/contrib/win32/win32compat/wmain_common.c @@ -52,8 +52,9 @@ wmain(int argc, wchar_t **wargv) { if (getenv("SSH_AUTH_SOCK") == NULL) _putenv("SSH_AUTH_SOCK=ssh-agent"); - w32posix_initialize(); - r = main(argc, argv); - w32posix_done(); - return r; + w32posix_initialize(); + + r = main(argc, argv); + w32posix_done(); + return r; } diff --git a/kex.c b/kex.c index cf4ac0dc..98c0597a 100644 --- a/kex.c +++ b/kex.c @@ -54,14 +54,6 @@ #include "sshbuf.h" #include "digest.h" -#if OPENSSL_VERSION_NUMBER >= 0x00907000L -# if defined(HAVE_EVP_SHA256) -# define evp_ssh_sha256 EVP_sha256 -# else -extern const EVP_MD *evp_ssh_sha256(void); -# endif -#endif - /* prototype */ static int kex_choose_conf(struct ssh *); static int kex_input_newkeys(int, u_int32_t, void *); diff --git a/openbsd-compat/fmt_scaled.c b/openbsd-compat/fmt_scaled.c index e5533b2d..7c5193e2 100644 --- a/openbsd-compat/fmt_scaled.c +++ b/openbsd-compat/fmt_scaled.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fmt_scaled.c,v 1.13 2017/03/11 23:37:23 djm Exp $ */ +/* $OpenBSD: fmt_scaled.c,v 1.16 2017/03/16 02:40:46 dtucker Exp $ */ /* * Copyright (c) 2001, 2002, 2003 Ian F. Darwin. All rights reserved. @@ -125,22 +125,30 @@ scan_scaled(char *scaled, long long *result) /* ignore extra fractional digits */ continue; fract_digits++; /* for later scaling */ - if (fpart >= LLONG_MAX / 10) { + if (fpart > LLONG_MAX / 10) { errno = ERANGE; return -1; } fpart *= 10; + if (i > LLONG_MAX - fpart) { + errno = ERANGE; + return -1; + } fpart += i; } else { /* normal digit */ if (++ndigits >= MAX_DIGITS) { errno = ERANGE; return -1; } - if (whole >= LLONG_MAX / 10) { + if (whole > LLONG_MAX / 10) { errno = ERANGE; return -1; } whole *= 10; + if (i > LLONG_MAX - whole) { + errno = ERANGE; + return -1; + } whole += i; } } @@ -170,7 +178,9 @@ scan_scaled(char *scaled, long long *result) } scale_fact = scale_factors[i]; - if (whole >= LLONG_MAX / scale_fact) { + /* check for overflow and underflow after scaling */ + if (whole > LLONG_MAX / scale_fact || + whole < LLONG_MIN / scale_fact) { errno = ERANGE; return -1; } diff --git a/regress/pesterTests/SSH.Tests.ps1 b/regress/pesterTests/SSH.Tests.ps1 index 58cb7a6e..74223bca 100644 --- a/regress/pesterTests/SSH.Tests.ps1 +++ b/regress/pesterTests/SSH.Tests.ps1 @@ -1,14 +1,30 @@ -#covered -i -q -v -l -c -C +#todo: -i -q -v -l -c -C #todo: -S -F -V -e -Describe "Tests for ssh command" -Tags "Scenario" { +$tB = 1 +$tI = 0 + +Describe "ssh client tests" -Tags "CI" { BeforeAll { - $fileName = "test.txt" - $filePath = Join-Path ${TestDrive} $fileName + if($OpenSSHTestInfo -eq $null) + { + Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment." + } + + if(-not (Test-Path $OpenSSHTestInfo["TestDataPath"])) + { + $null = New-Item $OpenSSHTestInfo["TestDataPath"] -ItemType directory -Force -ErrorAction SilentlyContinue + } - [Machine] $client = [Machine]::new([MachineRole]::Client) - [Machine] $server = [Machine]::new([MachineRole]::Server) - $client.SetupClient($server) - $server.SetupServer($client) + $server = $OpenSSHTestInfo["Target"] + $port = $OpenSSHTestInfo["Port"] + $ssouser = $OpenSSHTestInfo["SSOUser"] + $sshCmdDefault = "ssh -p $port $($ssouser)@$($server)" + + $testDir = Join-Path $OpenSSHTestInfo["TestDataPath"] "ssh" + if(-not (Test-Path $testDir)) + { + $null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue + } $testData = @( @{ @@ -55,12 +71,71 @@ Describe "Tests for ssh command" -Tags "Scenario" { } - AfterAll { - $client.CleanupClient() - $server.CleanupServer() + BeforeEach { + $tI++; + $tFile=Join-Path $testDir "$tB.$tI.txt" + } + + Context "$tB - Basic Scenarios" { + + BeforeAll {$tI=1} + AfterAll{$tB++} + + <# these 2 tests dont work on AppVeyor that sniffs stderr channel + It "$tB.$tI - test version" { + iex "ssh -V 2> $tFile" + $tFile | Should Contain "OpenSSH_" + } + + It "$tB.$tI - test help" { + iex "ssh -? 2> $tFile" + $tFile | Should Contain "usage: ssh" + } + #> + + It "$tB.$tI - remote echo command" { + iex "$sshDefaultCmd echo 1234" | Should Be "1234" + } + } + + Context "$tB - Redirection Scenarios" { + + BeforeAll {$tI=1} + AfterAll{$tB++} + + It "$tB.$tI - stdout to file" { + iex "$sshDefaultCmd powershell get-process > $tFile" + $tFile | Should Contain "ProcessName" + } + + It "$tB.$tI - stdout to PS object" { + $o = iex "$sshDefaultCmd echo 1234" + $o | Should Be "1234" + } + + <#It "$tB.$tI - stdin from PS object" { + #if input redirection doesn't work, this would hang + 0 | ssh -p $port $ssouser@$server pause + $true | Should Be $true + }#> } - Context "Key is not secured in ssh-agent on server" { + Context "$tB - cmdline parameters" { + + BeforeAll {$tI=1} + AfterAll{$tB++} + + It "$tB.$tI - verbose to file" { + $logFile = Join-Path $testDir "$tB.$tI.log.txt" + $o = ssh -p $port -v -E $logFile $ssouser@$server echo 1234 + $o | Should Be "1234" + #TODO - checks below are very inefficient (time taking). + $logFile | Should Contain "OpenSSH_" + $logFile | Should Contain "Exit Status 0" + } + + } + <#Context "Key is not secured in ssh-agent on server" { BeforeAll { $identifyFile = $client.clientPrivateKeyPaths[0] Remove-Item -Path $filePath -Force -ea silentlycontinue @@ -156,5 +231,5 @@ Describe "Tests for ssh command" -Tags "Scenario" { #validate file content. Get-Content $filePath | Should be $server.MachineName } - } + }#> } diff --git a/session.c b/session.c index 523acf4f..a689b27a 100644 --- a/session.c +++ b/session.c @@ -559,6 +559,10 @@ int do_exec_windows(Session *s, const char *command, int pty) { debug("Executing command: %s", exec_command); UTF8_TO_UTF16_FATAL(exec_command_w, exec_command); + _putenv_s("SSH_ASYNC_STDIN", "1"); + _putenv_s("SSH_ASYNC_STDOUT", "1"); + _putenv_s("SSH_ASYNC_STDERR", "1"); + /* in debug mode launch using sshd.exe user context */ if (debug_flag) b = CreateProcessW(NULL, exec_command_w, NULL, NULL, TRUE, @@ -569,6 +573,10 @@ int do_exec_windows(Session *s, const char *command, int pty) { DETACHED_PROCESS , NULL, pw_dir_w, &si, &pi); + _putenv_s("SSH_ASYNC_STDIN", ""); + _putenv_s("SSH_ASYNC_STDOUT", ""); + _putenv_s("SSH_ASYNC_STDERR", ""); + if (!b) fatal("ERROR. Cannot create process (%u).\n", GetLastError()); else if (pty) { /*attach to shell console */ diff --git a/sshd.c b/sshd.c index 8f80bb58..b52ef567 100644 --- a/sshd.c +++ b/sshd.c @@ -233,6 +233,12 @@ int use_privsep = -1; #endif struct monitor *pmonitor = NULL; int privsep_is_preauth = 1; +#ifdef WINDOWS +/* Windows does not use Unix privilege separation model */ +static int privsep_chroot = 0; +#else +static int privsep_chroot = 1; +#endif /* global authentication context */ Authctxt *the_authctxt = NULL; @@ -577,7 +583,7 @@ privsep_preauth_child(void) demote_sensitive_data(); /* Demote the child */ - if (getuid() == 0 || geteuid() == 0) { + if (privsep_chroot) { /* Change our root directory */ if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, @@ -1314,6 +1320,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) * automatically be cleaned up on next iteration */ close(startup_p[1]); + free(path_utf8); continue; } @@ -1717,8 +1724,9 @@ main(int ac, char **av) #ifndef WINDOWS /* not applicable in Windows */ /* Store privilege separation user for later use if required. */ + privsep_chroot = use_privsep && (getuid() == 0 || geteuid() == 0); if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { - if (use_privsep || options.kerberos_authentication) + if (privsep_chroot || options.kerberos_authentication) fatal("Privilege separation user %s does not exist", SSH_PRIVSEP_USER); } else { @@ -1847,7 +1855,7 @@ main(int ac, char **av) key_type(key)); } - if (use_privsep) { + if (privsep_chroot) { struct stat st; if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) || diff --git a/sshkey.c b/sshkey.c index 53a7674b..3c487849 100644 --- a/sshkey.c +++ b/sshkey.c @@ -3513,11 +3513,7 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob, int success, r; int blen, len = strlen(_passphrase); u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; -#if (OPENSSL_VERSION_NUMBER < 0x00907000L) - const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL; -#else - const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; -#endif + const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; const u_char *bptr; BIO *bio = NULL;