mirror of
https://github.com/PowerShell/Win32-OpenSSH.git
synced 2025-07-20 12:34:45 +02:00
Source snapshot from Powershell/openssh-portable:latestw_all
This commit is contained in:
parent
f0fd5e0099
commit
8c43479844
19
Makefile.in
19
Makefile.in
@ -236,6 +236,8 @@ clean: regressclean
|
||||
rm -f regress/unittests/sshkey/test_sshkey
|
||||
rm -f regress/unittests/bitmap/*.o
|
||||
rm -f regress/unittests/bitmap/test_bitmap
|
||||
rm -f regress/unittests/conversion/*.o
|
||||
rm -f regress/unittests/conversion/test_conversion
|
||||
rm -f regress/unittests/hostkeys/*.o
|
||||
rm -f regress/unittests/hostkeys/test_hostkeys
|
||||
rm -f regress/unittests/kex/*.o
|
||||
@ -262,6 +264,8 @@ distclean: regressclean
|
||||
rm -f regress/unittests/sshkey/test_sshkey
|
||||
rm -f regress/unittests/bitmap/*.o
|
||||
rm -f regress/unittests/bitmap/test_bitmap
|
||||
rm -f regress/unittests/conversion/*.o
|
||||
rm -f regress/unittests/conversion/test_conversion
|
||||
rm -f regress/unittests/hostkeys/*.o
|
||||
rm -f regress/unittests/hostkeys/test_hostkeys
|
||||
rm -f regress/unittests/kex/*.o
|
||||
@ -426,6 +430,8 @@ regress-prep:
|
||||
mkdir -p `pwd`/regress/unittests/sshkey
|
||||
[ -d `pwd`/regress/unittests/bitmap ] || \
|
||||
mkdir -p `pwd`/regress/unittests/bitmap
|
||||
[ -d `pwd`/regress/unittests/conversion ] || \
|
||||
mkdir -p `pwd`/regress/unittests/conversion
|
||||
[ -d `pwd`/regress/unittests/hostkeys ] || \
|
||||
mkdir -p `pwd`/regress/unittests/hostkeys
|
||||
[ -d `pwd`/regress/unittests/kex ] || \
|
||||
@ -503,6 +509,16 @@ regress/unittests/bitmap/test_bitmap$(EXEEXT): ${UNITTESTS_TEST_BITMAP_OBJS} \
|
||||
regress/unittests/test_helper/libtest_helper.a \
|
||||
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
|
||||
|
||||
UNITTESTS_TEST_CONVERSION_OBJS=\
|
||||
regress/unittests/conversion/tests.o
|
||||
|
||||
regress/unittests/conversion/test_conversion$(EXEEXT): \
|
||||
${UNITTESTS_TEST_CONVERSION_OBJS} \
|
||||
regress/unittests/test_helper/libtest_helper.a libssh.a
|
||||
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_CONVERSION_OBJS) \
|
||||
regress/unittests/test_helper/libtest_helper.a \
|
||||
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
|
||||
|
||||
UNITTESTS_TEST_KEX_OBJS=\
|
||||
regress/unittests/kex/tests.o \
|
||||
regress/unittests/kex/test_kex.o
|
||||
@ -558,13 +574,14 @@ regress-binaries: regress/modpipe$(EXEEXT) \
|
||||
regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \
|
||||
regress/unittests/sshkey/test_sshkey$(EXEEXT) \
|
||||
regress/unittests/bitmap/test_bitmap$(EXEEXT) \
|
||||
regress/unittests/conversion/test_conversion$(EXEEXT) \
|
||||
regress/unittests/hostkeys/test_hostkeys$(EXEEXT) \
|
||||
regress/unittests/kex/test_kex$(EXEEXT) \
|
||||
regress/unittests/match/test_match$(EXEEXT) \
|
||||
regress/unittests/utf8/test_utf8$(EXEEXT) \
|
||||
regress/misc/kexfuzz/kexfuzz$(EXEEXT)
|
||||
|
||||
tests interop-tests t-exec: regress-prep regress-binaries $(TARGETS)
|
||||
tests interop-tests t-exec unit: regress-prep regress-binaries $(TARGETS)
|
||||
BUILDDIR=`pwd`; \
|
||||
TEST_SSH_SCP="$${BUILDDIR}/scp"; \
|
||||
TEST_SSH_SSH="$${BUILDDIR}/ssh"; \
|
||||
|
2
README
2
README
@ -1,4 +1,4 @@
|
||||
See https://www.openssh.com/releasenotes.html#7.4p1 for the release notes.
|
||||
See https://www.openssh.com/releasenotes.html#7.5p1 for the release notes.
|
||||
|
||||
Please read https://www.openssh.com/report.html for bug reporting
|
||||
instructions and note that we do not use Github for bug reporting or
|
||||
|
21
appveyor.yml
21
appveyor.yml
@ -1,4 +1,4 @@
|
||||
version: 0.0.8.0.{build}
|
||||
version: 0.0.10.0.{build}
|
||||
image: Visual Studio 2015
|
||||
|
||||
branches:
|
||||
@ -11,12 +11,12 @@ init:
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppVeyor.psm1 -DisableNameChecking
|
||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
|
||||
Invoke-AppVeyorBuild
|
||||
|
||||
after_build:
|
||||
- ps: |
|
||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppVeyor.psm1 -DisableNameChecking
|
||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
|
||||
Install-OpenSSH
|
||||
- ps: Write-Verbose "Restart computer ..."
|
||||
- ps: Restart-Computer -Force
|
||||
@ -25,23 +25,20 @@ after_build:
|
||||
|
||||
before_test:
|
||||
- ps: |
|
||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppVeyor.psm1 -DisableNameChecking
|
||||
Install-TestDependencies
|
||||
Deploy-OpenSSHTests
|
||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
|
||||
Setup-OpenSSHTestEnvironment -Quiet
|
||||
|
||||
test_script:
|
||||
- cmd: |
|
||||
"%ProgramFiles%\PowerShell\6.0.0.14\powershell.exe" -Command "Import-Module \"%APPVEYOR_BUILD_FOLDER%\contrib\win32\openssh\AppVeyor.psm1\" -DisableNameChecking;Run-OpenSSHPesterTest"
|
||||
- ps: |
|
||||
Check-PesterTestResult
|
||||
Run-OpenSSHUnitTest
|
||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
|
||||
Run-OpenSSHTests
|
||||
|
||||
after_test:
|
||||
- ps: |
|
||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppVeyor.psm1 -DisableNameChecking
|
||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
|
||||
Upload-OpenSSHTestResults
|
||||
|
||||
on_finish:
|
||||
- ps: |
|
||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppVeyor.psm1 -DisableNameChecking
|
||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
|
||||
Publish-Artifact
|
||||
|
@ -227,15 +227,16 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
|
||||
#elif defined(WINDOWS)
|
||||
/*
|
||||
* Authenticate on Windows - Pass credentials to ssh-agent and retrieve token
|
||||
* upon succesful authentication
|
||||
* upon successful authentication
|
||||
* TODO - password is sent in plain text over IPC. Consider implications.
|
||||
*/
|
||||
extern int auth_sock;
|
||||
int sys_auth_passwd(Authctxt *authctxt, const char *password)
|
||||
{
|
||||
struct sshbuf *msg = NULL;
|
||||
size_t blen = 0;
|
||||
DWORD token = 0;
|
||||
struct sshbuf *msg = NULL;
|
||||
int r;
|
||||
extern int auth_sock;
|
||||
int r = 0;
|
||||
|
||||
msg = sshbuf_new();
|
||||
if (!msg)
|
||||
|
4
auth.c
4
auth.c
@ -490,7 +490,7 @@ auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
|
||||
uid_t uid, char *err, size_t errlen)
|
||||
{
|
||||
#ifdef WINDOWS
|
||||
error("auth_secure_path should not be called in Windows");
|
||||
error("auth_secure_path should not be called in Windows yet");
|
||||
return -1;
|
||||
#else /* !WINDOWS */
|
||||
char buf[PATH_MAX], homedir[PATH_MAX];
|
||||
@ -579,7 +579,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
|
||||
FILE *f;
|
||||
|
||||
#ifdef WINDOWS
|
||||
/* Windows POSIX adpater does not support fdopen() on open(file)*/
|
||||
/* Windows POSIX adapter does not support fdopen() on open(file)*/
|
||||
if ((f = fopen(file, "r")) == NULL) {
|
||||
debug("Could not open %s '%s': %s", file_type, file,
|
||||
strerror(errno));
|
||||
|
@ -178,14 +178,14 @@ userauth_pubkey(Authctxt *authctxt)
|
||||
authenticated = 0;
|
||||
|
||||
#ifdef WINDOWS
|
||||
/* Pass key challenge material to ssh-agent to retrieve token upon succesful authentication */
|
||||
/* Pass key challenge material to ssh-agent to retrieve token upon successful authentication */
|
||||
{
|
||||
extern int auth_sock;
|
||||
int r;
|
||||
struct sshbuf *msg = NULL;
|
||||
u_char *blob = NULL;
|
||||
size_t blen = 0;
|
||||
DWORD token = 0;
|
||||
struct sshbuf *msg = NULL;
|
||||
extern int auth_sock;
|
||||
int r = 0;
|
||||
|
||||
while (1) {
|
||||
msg = sshbuf_new();
|
||||
@ -246,11 +246,7 @@ userauth_pubkey(Authctxt *authctxt)
|
||||
* if a user is not allowed to login. is this an
|
||||
* issue? -markus
|
||||
*/
|
||||
#ifdef WINDOWS /* key validation in done in agent for Windows */
|
||||
{
|
||||
#else /* !WINDOWS */
|
||||
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) {
|
||||
#endif /* !WINDOWS */
|
||||
packet_start(SSH2_MSG_USERAUTH_PK_OK);
|
||||
packet_put_string(pkalg, alen);
|
||||
packet_put_string(pkblob, blen);
|
||||
|
1
authfd.c
1
authfd.c
@ -113,7 +113,6 @@ ssh_get_authentication_socket(int *fdp)
|
||||
errno = oerrno;
|
||||
return SSH_ERR_SYSTEM_ERROR;
|
||||
}
|
||||
|
||||
if (fdp != NULL)
|
||||
*fdp = sock;
|
||||
else
|
||||
|
@ -1486,6 +1486,7 @@ AC_ARG_WITH(ldns,
|
||||
else
|
||||
LIBS="$LIBS `$LDNSCONFIG --libs`"
|
||||
CPPFLAGS="$CPPFLAGS `$LDNSCONFIG --cflags`"
|
||||
ldns=yes
|
||||
fi
|
||||
elif test "x$withval" != "xno" ; then
|
||||
CPPFLAGS="$CPPFLAGS -I${withval}/include"
|
||||
@ -1717,6 +1718,7 @@ AC_CHECK_FUNCS([ \
|
||||
inet_ntoa \
|
||||
inet_ntop \
|
||||
innetgr \
|
||||
llabs \
|
||||
login_getcapbool \
|
||||
md5_crypt \
|
||||
memmove \
|
||||
@ -2531,8 +2533,8 @@ if test "x$openssl" = "xyes" ; then
|
||||
ssl_library_ver=`cat conftest.ssllibver`
|
||||
# Check version is supported.
|
||||
case "$ssl_library_ver" in
|
||||
0090[[0-7]]*|009080[[0-5]]*)
|
||||
AC_MSG_ERROR([OpenSSL >= 0.9.8f required (have "$ssl_library_ver")])
|
||||
10000*|0*)
|
||||
AC_MSG_ERROR([OpenSSL >= 1.0.1 required (have "$ssl_library_ver")])
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
|
@ -63,7 +63,6 @@ sshd_config_configured=no
|
||||
port_number=22
|
||||
service_name=sshd
|
||||
strictmodes=yes
|
||||
privsep_used=yes
|
||||
cygwin_value=""
|
||||
user_account=
|
||||
password_value=
|
||||
@ -140,33 +139,21 @@ sshd_strictmodes() {
|
||||
|
||||
# ======================================================================
|
||||
# Routine: sshd_privsep
|
||||
# MODIFIES: privsep_used
|
||||
# Try to create ssshd user account
|
||||
# ======================================================================
|
||||
sshd_privsep() {
|
||||
local ret=0
|
||||
|
||||
if [ "${sshd_config_configured}" != "yes" ]
|
||||
then
|
||||
echo
|
||||
csih_inform "Privilege separation is set to 'sandbox' by default since"
|
||||
csih_inform "OpenSSH 6.1. This is unsupported by Cygwin and has to be set"
|
||||
csih_inform "to 'yes' or 'no'."
|
||||
csih_inform "However, using privilege separation requires a non-privileged account"
|
||||
csih_inform "called 'sshd'."
|
||||
csih_inform "For more info on privilege separation read /usr/share/doc/openssh/README.privsep."
|
||||
if csih_request "Should privilege separation be used?"
|
||||
if ! csih_create_unprivileged_user sshd
|
||||
then
|
||||
privsep_used=yes
|
||||
if ! csih_create_unprivileged_user sshd
|
||||
then
|
||||
csih_error_recoverable "Couldn't create user 'sshd'!"
|
||||
csih_error_recoverable "Privilege separation set to 'no' again!"
|
||||
csih_error_recoverable "Check your ${SYSCONFDIR}/sshd_config file!"
|
||||
let ++ret
|
||||
privsep_used=no
|
||||
fi
|
||||
else
|
||||
privsep_used=no
|
||||
csih_error_recoverable "Could not create user 'sshd'!"
|
||||
csih_error_recoverable "You will not be able to run an sshd service"
|
||||
csih_error_recoverable "under a privileged account successfully."
|
||||
csih_error_recoverable "Make sure to create a non-privileged user 'sshd'"
|
||||
csih_error_recoverable "manually before trying to run the service!"
|
||||
let ++ret
|
||||
fi
|
||||
fi
|
||||
return $ret
|
||||
@ -202,18 +189,6 @@ sshd_config_tweak() {
|
||||
let ++ret
|
||||
fi
|
||||
fi
|
||||
if [ "${sshd_config_configured}" != "yes" ]
|
||||
then
|
||||
/usr/bin/sed -i -e "
|
||||
s/^#\?UsePrivilegeSeparation .*/UsePrivilegeSeparation ${privsep_used}/" \
|
||||
${SYSCONFDIR}/sshd_config
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
csih_warning "Setting privilege separation failed!"
|
||||
csih_warning "Check your ${SYSCONFDIR}/sshd_config file!"
|
||||
let ++ret
|
||||
fi
|
||||
fi
|
||||
return $ret
|
||||
} # --- End of sshd_config_tweak --- #
|
||||
|
||||
@ -693,7 +668,7 @@ then
|
||||
fi
|
||||
fi
|
||||
|
||||
# handle sshd_config (and privsep)
|
||||
# handle sshd_config
|
||||
csih_install_config "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults" || let ++warning_cnt
|
||||
if ! /usr/bin/cmp "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/sshd_config" >/dev/null 2>&1
|
||||
then
|
||||
|
@ -1,4 +1,4 @@
|
||||
%define ver 7.4p1
|
||||
%define ver 7.5p1
|
||||
%define rel 1
|
||||
|
||||
# OpenSSH privilege separation requires a user & group ID
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation
|
||||
Name: openssh
|
||||
Version: 7.4p1
|
||||
Version: 7.5p1
|
||||
URL: https://www.openssh.com/
|
||||
Release: 1
|
||||
Source0: openssh-%{version}.tar.gz
|
||||
|
269
contrib/win32/openssh/AppveyorHelper.psm1
Normal file
269
contrib/win32/openssh/AppveyorHelper.psm1
Normal file
@ -0,0 +1,269 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -Force -DisableNameChecking
|
||||
Import-Module $PSScriptRoot\OpenSSHBuildHelper.psm1 -Force -DisableNameChecking
|
||||
Import-Module $PSScriptRoot\OpenSSHTestHelper.psm1 -Force -DisableNameChecking
|
||||
|
||||
$repoRoot = Get-RepositoryRoot
|
||||
$script:messageFile = join-path $repoRoot.FullName "BuildMessage.log"
|
||||
|
||||
# Sets a build variable
|
||||
Function Write-BuildMessage
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string] $Message,
|
||||
$Category,
|
||||
[string] $Details)
|
||||
|
||||
if($env:AppVeyor)
|
||||
{
|
||||
Add-AppveyorMessage @PSBoundParameters
|
||||
}
|
||||
|
||||
# write it to the log file, if present.
|
||||
if (-not ([string]::IsNullOrEmpty($script:messageFile)))
|
||||
{
|
||||
Add-Content -Path $script:messageFile -Value "$Category--$Message"
|
||||
}
|
||||
}
|
||||
|
||||
# Sets a build variable
|
||||
Function Set-BuildVariable
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$Name,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$Value
|
||||
)
|
||||
|
||||
if($env:AppVeyor -and (Get-Command Set-AppveyorBuildVariable -ErrorAction Ignore) -ne $null)
|
||||
{
|
||||
Set-AppveyorBuildVariable @PSBoundParameters
|
||||
}
|
||||
elseif($env:AppVeyor)
|
||||
{
|
||||
appveyor SetVariable -Name $Name -Value $Value
|
||||
}
|
||||
else
|
||||
{
|
||||
Set-Item env:$Name -Value $Value
|
||||
}
|
||||
}
|
||||
|
||||
# Emulates running all of AppVeyor but locally
|
||||
# should not be used on AppVeyor
|
||||
function Invoke-AppVeyorFull
|
||||
{
|
||||
param(
|
||||
[switch] $APPVEYOR_SCHEDULED_BUILD,
|
||||
[switch] $CleanRepo
|
||||
)
|
||||
if($CleanRepo)
|
||||
{
|
||||
Clear-PSRepo
|
||||
}
|
||||
|
||||
if($env:APPVEYOR)
|
||||
{
|
||||
throw "This function is to simulate appveyor, but not to be run from appveyor!"
|
||||
}
|
||||
|
||||
if($APPVEYOR_SCHEDULED_BUILD)
|
||||
{
|
||||
$env:APPVEYOR_SCHEDULED_BUILD = 'True'
|
||||
}
|
||||
try {
|
||||
Set-OpenSSHTestParams
|
||||
Invoke-AppVeyorBuild
|
||||
Install-OpenSSH
|
||||
Install-OpenSSHTestDependencies
|
||||
Deploy-OpenSSHTests
|
||||
Setup-OpenSSHTestEnvironment
|
||||
Run-OpenSSHTests
|
||||
Publish-Artifact
|
||||
}
|
||||
finally {
|
||||
if($APPVEYOR_SCHEDULED_BUILD -and $env:APPVEYOR_SCHEDULED_BUILD)
|
||||
{
|
||||
Remove-Item env:APPVEYOR_SCHEDULED_BUILD
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Implements the AppVeyor 'build_script' step
|
||||
function Invoke-AppVeyorBuild
|
||||
{
|
||||
Set-BuildVariable TestPassed True
|
||||
Build-OpenSSH -Configuration Release -NativeHostArch x64
|
||||
Build-OpenSSH -Configuration Debug -NativeHostArch x86
|
||||
Write-BuildMessage -Message "OpenSSH binaries build success!" -Category Information
|
||||
}
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
Adds a build log to the list of published artifacts.
|
||||
.Description
|
||||
If a build log exists, it is renamed to reflect the associated CLR runtime then added to the list of
|
||||
artifacts to publish. If it doesn't exist, a warning is written and the file is skipped.
|
||||
The rename is needed since publishing overwrites the artifact if it already exists.
|
||||
.Parameter artifacts
|
||||
An array list to add the fully qualified build log path
|
||||
.Parameter buildLog
|
||||
The build log file produced by the build.
|
||||
#>
|
||||
function Add-BuildLog
|
||||
{
|
||||
param
|
||||
(
|
||||
[ValidateNotNull()]
|
||||
[System.Collections.ArrayList] $artifacts,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string] $buildLog
|
||||
)
|
||||
|
||||
if (Test-Path -Path $buildLog)
|
||||
{
|
||||
$null = $artifacts.Add($buildLog)
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Warning "Skip publishing build log. $buildLog does not exist"
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
Publishes package build artifacts.
|
||||
.Parameter artifacts
|
||||
An array list to add the fully qualified build log path
|
||||
.Parameter FileToAdd
|
||||
Path to the file
|
||||
#>
|
||||
function Add-Artifact
|
||||
{
|
||||
param
|
||||
(
|
||||
[ValidateNotNull()]
|
||||
[System.Collections.ArrayList] $artifacts,
|
||||
[string] $FileToAdd
|
||||
)
|
||||
|
||||
if ([string]::IsNullOrEmpty($FileToAdd) -or (-not (Test-Path $FileToAdd -PathType Leaf)) )
|
||||
{
|
||||
Write-Host "Skip publishing package artifacts. $FileToAdd does not exist"
|
||||
}
|
||||
else
|
||||
{
|
||||
$null = $artifacts.Add($FileToAdd)
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
After build and test run completes, upload all artifacts from the build machine.
|
||||
#>
|
||||
function Publish-Artifact
|
||||
{
|
||||
Write-Host -ForegroundColor Yellow "Publishing project artifacts"
|
||||
[System.Collections.ArrayList] $artifacts = [System.Collections.ArrayList]::new()
|
||||
|
||||
# Get the build.log file for each build configuration
|
||||
Add-BuildLog -artifacts $artifacts -buildLog (Get-BuildLogFile -root $repoRoot.FullName)
|
||||
|
||||
if($Global:OpenSSHTestInfo)
|
||||
{
|
||||
Add-Artifact -artifacts $artifacts -FileToAdd $Global:OpenSSHTestInfo["UnitTestResultsFile"]
|
||||
Add-Artifact -artifacts $artifacts -FileToAdd $Global:OpenSSHTestInfo["E2ETestResultsFile"]
|
||||
Add-Artifact -artifacts $artifacts -FileToAdd $Global:OpenSSHTestInfo["TestSetupLogFile"]
|
||||
}
|
||||
|
||||
foreach ($artifact in $artifacts)
|
||||
{
|
||||
Write-Host "Publishing $artifact as Appveyor artifact"
|
||||
# NOTE: attempt to publish subsequent artifacts even if the current one fails
|
||||
Push-AppveyorArtifact $artifact -ErrorAction Continue
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
Runs the tests for this repo
|
||||
#>
|
||||
function Run-OpenSSHTests
|
||||
{
|
||||
Write-Host "Start running unit tests"
|
||||
$unitTestFailed = Run-OpenSSHUnitTest
|
||||
|
||||
if($unitTestFailed)
|
||||
{
|
||||
Write-Host "At least one of the unit tests failed!" -ForegroundColor Yellow
|
||||
Write-BuildMessage "At least one of the unit tests failed!" -Category Error
|
||||
Set-BuildVariable TestPassed False
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "All Unit tests passed!"
|
||||
Write-BuildMessage -Message "All Unit tests passed!" -Category Information
|
||||
}
|
||||
# Run all E2E tests.
|
||||
Run-OpenSSHE2ETest
|
||||
if (($OpenSSHTestInfo -eq $null) -or (-not (Test-Path $OpenSSHTestInfo["E2ETestResultsFile"])))
|
||||
{
|
||||
Write-Warning "Test result file $OpenSSHTestInfo["E2ETestResultsFile"] not found after tests."
|
||||
Write-BuildMessage -Message "Test result file $OpenSSHTestInfo["E2ETestResultsFile"] not found after tests." -Category Error
|
||||
Set-BuildVariable TestPassed False
|
||||
}
|
||||
$xml = [xml](Get-Content -raw $OpenSSHTestInfo["E2ETestResultsFile"])
|
||||
if ([int]$xml.'test-results'.failures -gt 0)
|
||||
{
|
||||
$errorMessage = "$($xml.'test-results'.failures) tests in regress\pesterTests failed. Detail test log is at $($OpenSSHTestInfo["E2ETestResultsFile"])."
|
||||
Write-Warning $errorMessage
|
||||
Write-BuildMessage -Message $errorMessage -Category Error
|
||||
Set-BuildVariable TestPassed False
|
||||
}
|
||||
|
||||
# Writing out warning when the $Error.Count is non-zero. Tests Should clean $Error after success.
|
||||
if ($Error.Count -gt 0)
|
||||
{
|
||||
Write-BuildMessage -Message "Tests Should clean $Error after success." -Category Warning
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
upload OpenSSH pester test results.
|
||||
#>
|
||||
function Upload-OpenSSHTestResults
|
||||
{
|
||||
if ($env:APPVEYOR_JOB_ID)
|
||||
{
|
||||
$resultFile = Resolve-Path $Global:OpenSSHTestInfo["E2ETestResultsFile"] -ErrorAction Ignore
|
||||
if( (Test-Path $Global:OpenSSHTestInfo["E2ETestResultsFile"]) -and $resultFile)
|
||||
{
|
||||
(New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", $resultFile)
|
||||
Write-BuildMessage -Message "Test results uploaded!" -Category Information
|
||||
}
|
||||
}
|
||||
|
||||
if ($env:DebugMode)
|
||||
{
|
||||
Remove-Item $env:DebugMode
|
||||
}
|
||||
|
||||
if($env:TestPassed -ieq 'True')
|
||||
{
|
||||
Write-BuildMessage -Message "The checkin validation success!" -Category Information
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-BuildMessage -Message "The checkin validation failed!" -Category Error
|
||||
throw "The checkin validation failed!"
|
||||
}
|
||||
}
|
592
contrib/win32/openssh/OpenSSHBuildHelper.psm1
Normal file
592
contrib/win32/openssh/OpenSSHBuildHelper.psm1
Normal file
@ -0,0 +1,592 @@
|
||||
Set-StrictMode -Version Latest
|
||||
|
||||
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -force -DisableNameChecking
|
||||
[string] $script:platform = $env:PROCESSOR_ARCHITECTURE
|
||||
[string] $script:vcPath = $null
|
||||
[System.IO.DirectoryInfo] $script:OpenSSHRoot = $null
|
||||
[System.IO.DirectoryInfo] $script:gitRoot = $null
|
||||
[bool] $script:Verbose = $false
|
||||
[string] $script:BuildLogFile = $null
|
||||
|
||||
<#
|
||||
Called by Write-BuildMsg to write to the build log, if it exists.
|
||||
#>
|
||||
function Write-Log
|
||||
{
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string] $Message
|
||||
)
|
||||
# write it to the log file, if present.
|
||||
if (-not ([string]::IsNullOrEmpty($script:BuildLogFile)))
|
||||
{
|
||||
Add-Content -Path $script:BuildLogFile -Value $Message
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
Writes a build message.
|
||||
.Parameter Message
|
||||
The message to write.
|
||||
.Parameter AsInfo
|
||||
Writes a user message using Write-Information.
|
||||
.Parameter AsVerbose
|
||||
Writes a message using Write-Verbose and to the build log if -Verbose was specified to Start-DscBuild.
|
||||
.Parameter AsWarning
|
||||
Writes a message using Write-Warning and to the build log.
|
||||
.Parameter AsError
|
||||
Writes a message using Write-Error and to the build log.
|
||||
.Parameter Silent
|
||||
Writes the message only to the log.
|
||||
.Parameter ErrorAction
|
||||
Determines if the script is terminated when errors are written.
|
||||
This parameter is ignored when -Silent is specified.
|
||||
.Example
|
||||
Write-BuildMsg -AsInfo 'Starting the build'
|
||||
Writes an informational message to the log and to the user
|
||||
.Example
|
||||
Write-BuildMsg -AsError 'Terminating build' -Silent
|
||||
Writes an error message only to the log
|
||||
.Example
|
||||
Write-BuildMsg -AsError 'Terminating build' -ErrorAction Stop
|
||||
Writes an error message to the log and the user and terminates the build.
|
||||
.Example
|
||||
Write-BuildMsg -AsInfo 'Nuget is already installed' -Silent:(-not $script:Verbose)
|
||||
Writes an informational message to the log. If -Verbose was specified, also
|
||||
writes to message to the user.
|
||||
#>
|
||||
function Write-BuildMsg
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string] $Message,
|
||||
|
||||
[Parameter(ParameterSetName='Info')]
|
||||
[switch] $AsInfo,
|
||||
|
||||
[Parameter(ParameterSetName='Verbose')]
|
||||
[switch] $AsVerbose,
|
||||
|
||||
[Parameter(ParameterSetName='Warning')]
|
||||
[switch] $AsWarning,
|
||||
|
||||
[Parameter(ParameterSetName='Error')]
|
||||
[switch] $AsError,
|
||||
|
||||
[switch] $Silent
|
||||
)
|
||||
|
||||
if ($AsVerbose)
|
||||
{
|
||||
if ($script:Verbose)
|
||||
{
|
||||
Write-Log -Message "VERBOSE: $message"
|
||||
if (-not $Silent)
|
||||
{
|
||||
Write-Verbose -Message $message -Verbose
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if ($AsInfo)
|
||||
{
|
||||
Write-Log -Message "INFO: $message"
|
||||
if (-not $Silent)
|
||||
{
|
||||
Write-Information -MessageData $message -InformationAction Continue
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if ($AsWarning)
|
||||
{
|
||||
Write-Log -Message "WARNING: $message"
|
||||
if (-not $Silent)
|
||||
{
|
||||
Write-Warning -Message $message
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if ($AsError)
|
||||
{
|
||||
Write-Log -Message "ERROR: $message"
|
||||
if (-not $Silent)
|
||||
{
|
||||
Write-Error -Message $message
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
# if we reached here, no output type switch was specified.
|
||||
Write-BuildMsg -AsError -ErrorAction Stop -Message 'Write-BuildMsg was called without selecting an output type.'
|
||||
}
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
Verifies all tools and dependencies required for building Open SSH are installed on the machine.
|
||||
#>
|
||||
function Start-OpenSSHBootstrap
|
||||
{
|
||||
[bool] $silent = -not $script:Verbose
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
Write-BuildMsg -AsInfo -Message "Checking tools and dependencies" -Silent:$silent
|
||||
|
||||
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
|
||||
$newMachineEnvironmentPath = $machinePath
|
||||
|
||||
# Install chocolatey
|
||||
$chocolateyPath = "$env:AllUsersProfile\chocolatey\bin"
|
||||
if(Get-Command "choco" -ErrorAction SilentlyContinue)
|
||||
{
|
||||
Write-BuildMsg -AsVerbose -Message "Chocolatey is already installed. Skipping installation." -Silent:$silent
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-BuildMsg -AsInfo -Message "Chocolatey not present. Installing chocolatey." -Silent:$silent
|
||||
Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $script:BuildLogFile
|
||||
}
|
||||
|
||||
# Add git\cmd to the path
|
||||
$gitCmdPath = "$env:ProgramFiles\git\cmd"
|
||||
if (-not ($machinePath.ToLower().Contains($gitCmdPath.ToLower())))
|
||||
{
|
||||
Write-BuildMsg -AsVerbose -Message "Adding $gitCmdPath to Path environment variable" -Silent:$silent
|
||||
$newMachineEnvironmentPath = "$gitCmdPath;$newMachineEnvironmentPath"
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-BuildMsg -AsVerbose -Message "$gitCmdPath already present in Path environment variable" -Silent:$silent
|
||||
}
|
||||
|
||||
$nativeMSBuildPath = "${env:ProgramFiles(x86)}\MSBuild\14.0\bin"
|
||||
if($script:platform -ieq "AMD64")
|
||||
{
|
||||
$nativeMSBuildPath += "\amd64"
|
||||
}
|
||||
|
||||
if (-not ($machinePath.ToLower().Contains($nativeMSBuildPath.ToLower())))
|
||||
{
|
||||
Write-BuildMsg -AsVerbose -Message "Adding $nativeMSBuildPath to Path environment variable" -Silent:$silent
|
||||
$newMachineEnvironmentPath += ";$nativeMSBuildPath"
|
||||
$env:Path += ";$nativeMSBuildPath"
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-BuildMsg -AsVerbose -Message "$nativeMSBuildPath already present in Path environment variable" -Silent:$silent
|
||||
}
|
||||
|
||||
# Update machine environment path
|
||||
if ($newMachineEnvironmentPath -ne $machinePath)
|
||||
{
|
||||
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
|
||||
}
|
||||
|
||||
# install nasm
|
||||
$packageName = "nasm"
|
||||
$nasmPath = "${env:ProgramFiles(x86)}\NASM"
|
||||
|
||||
if (-not (Test-Path -Path $nasmPath -PathType Container))
|
||||
{
|
||||
Write-BuildMsg -AsInfo -Message "$packageName not present. Installing $packageName." -Silent:$silent
|
||||
choco install $packageName -y --force --limitoutput --execution-timeout 10000 2>&1 >> $script:BuildLogFile
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-BuildMsg -AsVerbose -Message "$packageName present. Skipping installation." -Silent:$silent
|
||||
}
|
||||
|
||||
# Install Visual Studio 2015 Community
|
||||
$packageName = "VisualStudio2015Community"
|
||||
$VSPackageInstalled = Get-ItemProperty "HKLM:\software\WOW6432Node\Microsoft\VisualStudio\14.0\setup\vs" -ErrorAction SilentlyContinue
|
||||
|
||||
if ($null -eq $VSPackageInstalled)
|
||||
{
|
||||
Write-BuildMsg -AsInfo -Message "$packageName not present. Installing $packageName."
|
||||
$adminFilePath = "$script:OpenSSHRoot\contrib\win32\openssh\VSWithBuildTools.xml"
|
||||
choco install $packageName -packageParameters "--AdminFile $adminFilePath" -y --force --limitoutput --execution-timeout 10000 2>&1 >> $script:BuildLogFile
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-BuildMsg -AsVerbose -Message "$packageName present. Skipping installation." -Silent:$silent
|
||||
}
|
||||
|
||||
# Install Windows 8.1 SDK
|
||||
$packageName = "windows-sdk-8.1"
|
||||
$sdkPath = "${env:ProgramFiles(x86)}\Windows Kits\8.1\bin\x86\register_app.vbs"
|
||||
|
||||
if (-not (Test-Path -Path $sdkPath))
|
||||
{
|
||||
Write-BuildMsg -AsInfo -Message "Windows 8.1 SDK not present. Installing $packageName."
|
||||
choco install $packageName -y --limitoutput --force 2>&1 >> $script:BuildLogFile
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-BuildMsg -AsInfo -Message "$packageName present. Skipping installation." -Silent:$silent
|
||||
}
|
||||
|
||||
# Require restarting PowerShell session
|
||||
if ($null -eq $VSPackageInstalled)
|
||||
{
|
||||
Write-Host "To apply changes, please close this PowerShell window, open a new one and call Start-SSHBuild or Start-DscBootstrap again." -ForegroundColor Black -BackgroundColor Yellow
|
||||
Write-Host -NoNewLine 'Press any key to close this PowerShell window...' -ForegroundColor Black -BackgroundColor Yellow
|
||||
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
|
||||
exit
|
||||
}
|
||||
|
||||
# Ensure the VS C toolset is installed
|
||||
if ($null -eq $env:VS140COMNTOOLS)
|
||||
{
|
||||
Write-BuildMsg -AsError -ErrorAction Stop -Message "Cannot find Visual Studio 2015 Environment variable VS140COMNTOOlS"
|
||||
}
|
||||
|
||||
$item = Get-Item(Join-Path -Path $env:VS140COMNTOOLS -ChildPath '../../vc')
|
||||
|
||||
$script:vcPath = $item.FullName
|
||||
Write-BuildMsg -AsVerbose -Message "vcPath: $script:vcPath" -Silent:$silent
|
||||
if ((Test-Path -Path "$script:vcPath\vcvarsall.bat") -eq $false)
|
||||
{
|
||||
Write-BuildMsg -AsError -ErrorAction Stop -Message "Could not find Visual Studio vcvarsall.bat at$script:vcPath, which means some required develop kits are missing on the machine."
|
||||
}
|
||||
}
|
||||
|
||||
function Clone-Win32OpenSSH
|
||||
{
|
||||
[bool] $silent = -not $script:Verbose
|
||||
|
||||
$win32OpenSSHPath = join-path $script:gitRoot "Win32-OpenSSH"
|
||||
if (-not (Test-Path -Path $win32OpenSSHPath -PathType Container))
|
||||
{
|
||||
Write-BuildMsg -AsInfo -Message "clone repo Win32-OpenSSH" -Silent:$silent
|
||||
Push-Location $gitRoot
|
||||
git clone -q --recursive https://github.com/PowerShell/Win32-OpenSSH.git $win32OpenSSHPath
|
||||
Pop-Location
|
||||
}
|
||||
Write-BuildMsg -AsInfo -Message "pull latest from repo Win32-OpenSSH" -Silent:$silent
|
||||
Push-Location $win32OpenSSHPath
|
||||
git fetch -q origin
|
||||
git checkout -qf L1-Prod
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
function Copy-OpenSSLSDK
|
||||
{
|
||||
[bool] $silent = -not $script:Verbose
|
||||
|
||||
$sourcePath = Join-Path $script:gitRoot "Win32-OpenSSH\contrib\win32\openssh\OpenSSLSDK"
|
||||
Write-BuildMsg -AsInfo -Message "copying $sourcePath" -Silent:$silent
|
||||
Copy-Item -Container -Path $sourcePath -Destination $PSScriptRoot -Recurse -Force -ErrorAction SilentlyContinue -ErrorVariable e
|
||||
if($e -ne $null)
|
||||
{
|
||||
Write-BuildMsg -AsError -ErrorAction Stop -Message "Copy OpenSSL from $sourcePath failed "
|
||||
}
|
||||
}
|
||||
|
||||
function Package-OpenSSH
|
||||
{
|
||||
[CmdletBinding(SupportsShouldProcess=$false)]
|
||||
param
|
||||
(
|
||||
[ValidateSet('x86', 'x64')]
|
||||
[string]$NativeHostArch = "x64",
|
||||
|
||||
[ValidateSet('Debug', 'Release', '')]
|
||||
[string]$Configuration = "Release"
|
||||
)
|
||||
|
||||
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
|
||||
$repositoryRoot = Get-Item -Path $repositoryRoot.FullName
|
||||
$folderName = $NativeHostArch
|
||||
if($NativeHostArch -ieq 'x86')
|
||||
{
|
||||
$folderName = "Win32"
|
||||
}
|
||||
$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 += "sshd_config", "install-sshd.ps1", "uninstall-sshd.ps1"
|
||||
$payload += "install-sshlsa.ps1", "uninstall-sshlsa.ps1"
|
||||
|
||||
$packageName = "OpenSSH-Win64"
|
||||
if ($NativeHostArch -eq 'x86') {
|
||||
$packageName = "OpenSSH-Win32"
|
||||
}
|
||||
|
||||
$packageDir = Join-Path $buildDir $packageName
|
||||
Remove-Item $packageDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
New-Item $packageDir -Type Directory | Out-Null
|
||||
|
||||
$symbolsDir = Join-Path $buildDir ($packageName + '_Symbols')
|
||||
Remove-Item $symbolsDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
New-Item $symbolsDir -Type Directory | Out-Null
|
||||
|
||||
foreach ($file in $payload) {
|
||||
if ((-not(Test-Path (Join-Path $buildDir $file)))) {
|
||||
Throw "Cannot find $file under $buildDir. Did you run Build-OpenSSH?"
|
||||
}
|
||||
Copy-Item (Join-Path $buildDir $file) $packageDir
|
||||
if ($file.EndsWith(".exe")) {
|
||||
$pdb = $file.Replace(".exe", ".pdb")
|
||||
Copy-Item (Join-Path $buildDir $pdb) $symbolsDir
|
||||
}
|
||||
if ($file.EndsWith(".dll")) {
|
||||
$pdb = $file.Replace(".dll", ".pdb")
|
||||
Copy-Item (Join-Path $buildDir $pdb) $symbolsDir
|
||||
}
|
||||
}
|
||||
|
||||
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')
|
||||
Remove-Item $symbolsDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
function Build-OpenSSH
|
||||
{
|
||||
[CmdletBinding(SupportsShouldProcess=$false)]
|
||||
param
|
||||
(
|
||||
[ValidateSet('x86', 'x64')]
|
||||
[string]$NativeHostArch = "x64",
|
||||
|
||||
[ValidateSet('Debug', 'Release', '')]
|
||||
[string]$Configuration = "Release"
|
||||
)
|
||||
Set-StrictMode -Version Latest
|
||||
$script:BuildLogFile = $null
|
||||
|
||||
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
|
||||
|
||||
# Get openssh-portable root
|
||||
$script:OpenSSHRoot = Get-Item -Path $repositoryRoot.FullName
|
||||
$script:gitRoot = split-path $script:OpenSSHRoot
|
||||
|
||||
if($PSBoundParameters.ContainsKey("Verbose"))
|
||||
{
|
||||
$script:Verbose = ($PSBoundParameters['Verbose']).IsPresent
|
||||
}
|
||||
[bool] $silent = -not $script:Verbose
|
||||
|
||||
$script:BuildLogFile = Get-BuildLogFile -root $repositoryRoot.FullName -Configuration $Configuration -NativeHostArch $NativeHostArch
|
||||
if (Test-Path -Path $script:BuildLogFile)
|
||||
{
|
||||
Remove-Item -Path $script:BuildLogFile -force
|
||||
}
|
||||
|
||||
Write-BuildMsg -AsInfo -Message "Starting Open SSH build; Build Log: $($script:BuildLogFile)"
|
||||
|
||||
Start-OpenSSHBootstrap
|
||||
|
||||
Clone-Win32OpenSSH
|
||||
Copy-OpenSSLSDK
|
||||
$msbuildCmd = "msbuild.exe"
|
||||
$solutionFile = Get-SolutionFile -root $repositoryRoot.FullName
|
||||
$cmdMsg = @("${solutionFile}", "/p:Platform=${NativeHostArch}", "/p:Configuration=${Configuration}", "/m", "/noconlog", "/nologo", "/fl", "/flp:LogFile=${script:BuildLogFile}`;Append`;Verbosity=diagnostic")
|
||||
|
||||
& $msbuildCmd $cmdMsg
|
||||
$errorCode = $LASTEXITCODE
|
||||
|
||||
if ($errorCode -ne 0)
|
||||
{
|
||||
Write-BuildMsg -AsError -ErrorAction Stop -Message "Build failed for OpenSSH.`nExitCode: $error."
|
||||
}
|
||||
|
||||
Write-BuildMsg -AsInfo -Message "SSH build passed." -Silent:$silent
|
||||
}
|
||||
|
||||
function Get-BuildLogFile
|
||||
{
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateNotNull()]
|
||||
[System.IO.DirectoryInfo] $root,
|
||||
|
||||
[ValidateSet('x86', 'x64')]
|
||||
[string]$NativeHostArch = "x64",
|
||||
|
||||
[ValidateSet('Debug', 'Release', '')]
|
||||
[string]$Configuration = "Release"
|
||||
|
||||
)
|
||||
return Join-Path -Path $root -ChildPath "contrib\win32\openssh\OpenSSH$($Configuration)$($NativeHostArch).log"
|
||||
}
|
||||
|
||||
function Get-SolutionFile
|
||||
{
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateNotNull()]
|
||||
[System.IO.DirectoryInfo] $root
|
||||
)
|
||||
return Join-Path -Path $root -ChildPath "contrib\win32\openssh\Win32-OpenSSH.sln"
|
||||
}
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
Deploy all required files to build a package and create zip file.
|
||||
#>
|
||||
function Deploy-Win32OpenSSHBinaries
|
||||
{
|
||||
[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))
|
||||
{
|
||||
$null = New-Item -Path $OpenSSHDir -ItemType Directory -Force -ErrorAction Stop
|
||||
}
|
||||
|
||||
[string] $platform = $env:PROCESSOR_ARCHITECTURE
|
||||
if(-not [String]::IsNullOrEmpty($NativeHostArch))
|
||||
{
|
||||
$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"
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
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')
|
||||
$newMachineEnvironmentPath = $machinePath
|
||||
if (-not ($machinePath.ToLower().Contains($OpenSSHDir.ToLower())))
|
||||
{
|
||||
$newMachineEnvironmentPath = "$OpenSSHDir;$newMachineEnvironmentPath"
|
||||
$env:Path = "$OpenSSHDir;$env:Path"
|
||||
}
|
||||
# Update machine environment path
|
||||
if ($newMachineEnvironmentPath -ne $machinePath)
|
||||
{
|
||||
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
|
||||
}
|
||||
|
||||
Set-Service sshd -StartupType Automatic
|
||||
Set-Service ssh-agent -StartupType Automatic
|
||||
Start-Service sshd
|
||||
|
||||
Pop-Location
|
||||
Write-Log -Message "OpenSSH installed!"
|
||||
}
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
uninstalled sshd and sshla
|
||||
#>
|
||||
function UnInstall-OpenSSH
|
||||
{
|
||||
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
|
||||
)
|
||||
|
||||
Push-Location $OpenSSHDir
|
||||
if((Get-Service ssh-agent -ErrorAction Ignore) -ne $null) {
|
||||
Stop-Service ssh-agent -Force
|
||||
}
|
||||
&( "$OpenSSHDir\uninstall-sshd.ps1")
|
||||
&( "$OpenSSHDir\uninstall-sshlsa.ps1")
|
||||
|
||||
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
|
||||
$newMachineEnvironmentPath = $machinePath
|
||||
if ($machinePath.ToLower().Contains($OpenSSHDir.ToLower()))
|
||||
{
|
||||
$newMachineEnvironmentPath.Replace("$OpenSSHDir;", '')
|
||||
$env:Path = $env:Path.Replace("$OpenSSHDir;", '')
|
||||
}
|
||||
|
||||
# Update machine environment path
|
||||
# machine will be reboot after Uninstall-OpenSSH
|
||||
if ($newMachineEnvironmentPath -ne $machinePath)
|
||||
{
|
||||
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
|
||||
}
|
||||
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
|
||||
Export-ModuleMember -Function Build-OpenSSH, Get-BuildLogFile, Install-OpenSSH, UnInstall-OpenSSH, Package-OpenSSH
|
31
contrib/win32/openssh/OpenSSHCommonUtils.psm1
Normal file
31
contrib/win32/openssh/OpenSSHCommonUtils.psm1
Normal file
@ -0,0 +1,31 @@
|
||||
<#
|
||||
.Synopsis
|
||||
Finds the root of the git repository
|
||||
|
||||
.Outputs
|
||||
A System.IO.DirectoryInfo for the location of the root.
|
||||
|
||||
.Inputs
|
||||
None
|
||||
|
||||
.Notes
|
||||
FileNotFoundException is thrown if the current directory does not contain a CMakeLists.txt file.
|
||||
#>
|
||||
function Get-RepositoryRoot
|
||||
{
|
||||
$currentDir = (Get-Item -Path $PSCommandPath).Directory
|
||||
|
||||
while ($null -ne $currentDir.Parent)
|
||||
{
|
||||
$path = Join-Path -Path $currentDir.FullName -ChildPath '.git'
|
||||
if (Test-Path -Path $path)
|
||||
{
|
||||
return $currentDir
|
||||
}
|
||||
$currentDir = $currentDir.Parent
|
||||
}
|
||||
|
||||
throw new-object System.IO.DirectoryNotFoundException("Could not find the root of the GIT repository")
|
||||
}
|
||||
|
||||
Export-ModuleMember -Function Get-RepositoryRoot
|
445
contrib/win32/openssh/OpenSSHTestHelper.psm1
Normal file
445
contrib/win32/openssh/OpenSSHTestHelper.psm1
Normal file
@ -0,0 +1,445 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -DisableNameChecking
|
||||
|
||||
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
|
||||
# test environment parameters initialized with defaults
|
||||
$E2ETestResultsFileName = "E2ETestResults.xml"
|
||||
$UnitTestResultsFileName = "UnitTestResults.txt"
|
||||
$TestSetupLogFileName = "TestSetupLog.txt"
|
||||
$SSOUser = "sshtest_ssouser"
|
||||
$PubKeyUser = "sshtest_pubkeyuser"
|
||||
$PasswdUser = "sshtest_passwduser"
|
||||
$OpenSSHTestAccountsPassword = "P@ssw0rd_1"
|
||||
$OpenSSHTestAccounts = $Script:SSOUser, $Script:PubKeyUser, $Script:PasswdUser
|
||||
|
||||
$Script:TestDataPath = "$env:SystemDrive\OpenSSHTests"
|
||||
$Script:E2ETestResultsFile = Join-Path $TestDataPath $E2ETestResultsFileName
|
||||
$Script:UnitTestResultsFile = Join-Path $TestDataPath $UnitTestResultsFileName
|
||||
$Script:TestSetupLogFile = Join-Path $TestDataPath $TestSetupLogFileName
|
||||
$Script:E2ETestDirectory = Join-Path $repositoryRoot.FullName -ChildPath "regress\pesterTests"
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
Setup-OpenSSHTestEnvironment
|
||||
TODO - split these steps into client and server side
|
||||
#>
|
||||
function Setup-OpenSSHTestEnvironment
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[switch] $Quiet,
|
||||
[string] $OpenSSHBinPath,
|
||||
[string] $TestDataPath = "$env:SystemDrive\OpenSSHTests",
|
||||
[Boolean] $DebugMode = $false
|
||||
)
|
||||
|
||||
if($Global:OpenSSHTestInfo -ne $null)
|
||||
{
|
||||
$Global:OpenSSHTestInfo.Clear()
|
||||
$Global:OpenSSHTestInfo = $null
|
||||
}
|
||||
$Script:TestDataPath = $TestDataPath;
|
||||
$Script:E2ETestResultsFile = Join-Path $TestDataPath "E2ETestResults.xml"
|
||||
$Script:UnitTestResultsFile = Join-Path $TestDataPath "UnitTestResults.txt"
|
||||
$Script:TestSetupLogFile = Join-Path $TestDataPath "TestSetupLog.txt"
|
||||
$Script:UnitTestDirectory = Get-UnitTestDirectory
|
||||
|
||||
|
||||
$Global:OpenSSHTestInfo = @{
|
||||
"Target"= "localhost"; # test listener name
|
||||
"Port"= "47002"; # test listener port
|
||||
"SSOUser"= $SSOUser; # test user with single sign on capability
|
||||
"PubKeyUser"= $PubKeyUser; # test user to be used with explicit key for key auth
|
||||
"PasswdUser"= $PasswdUser; # common password for all test accounts
|
||||
"TestAccountPW"= $OpenSSHTestAccountsPassword; # common password for all test accounts
|
||||
"TestDataPath" = $TestDataPath; # openssh tests path
|
||||
"TestSetupLogFile" = $Script:TestSetupLogFile; # openssh test setup log file
|
||||
"E2ETestResultsFile" = $Script:E2ETestResultsFile; # openssh E2E test results file
|
||||
"UnitTestResultsFile" = $Script:UnitTestResultsFile; # openssh unittest test results file
|
||||
"E2ETestDirectory" = $Script:E2ETestDirectory # the directory of E2E tests
|
||||
"UnitTestDirectory" = $Script:UnitTestDirectory # the directory of unit tests
|
||||
"DebugMode" = $DebugMode # run openssh E2E in debug mode
|
||||
}
|
||||
|
||||
#if user does not set path, pick it up
|
||||
if([string]::IsNullOrEmpty($OpenSSHBinPath))
|
||||
{
|
||||
$sshcmd = get-command ssh.exe -ErrorAction Ignore
|
||||
if($sshcmd -eq $null)
|
||||
{
|
||||
Throw "Cannot find ssh.exe. Please specify -OpenSSHBinPath to the OpenSSH installed location."
|
||||
}
|
||||
elseif($Quiet)
|
||||
{
|
||||
$dirToCheck = split-path $sshcmd.Path
|
||||
$script:OpenSSHBinPath = $dirToCheck
|
||||
}
|
||||
else
|
||||
{
|
||||
$dirToCheck = split-path $sshcmd.Path
|
||||
$message = "Do you want to test openssh installed at $($dirToCheck)? [Yes] Y; [No] N (default is `"Y`")"
|
||||
$response = Read-Host -Prompt $message
|
||||
if( ($response -eq "") -or ($response -ieq "Y") -or ($response -ieq "Yes") )
|
||||
{
|
||||
$script:OpenSSHBinPath = $dirToCheck
|
||||
}
|
||||
elseif( ($response -ieq "N") -or ($response -ieq "No") )
|
||||
{
|
||||
Write-Host "User decided not to pick up ssh.exe from $dirToCheck. Please specify -OpenSSHBinPath to the OpenSSH installed location."
|
||||
return
|
||||
}
|
||||
else
|
||||
{
|
||||
Throw "User entered invalid option ($response). Please specify -OpenSSHBinPath to the OpenSSH installed location"
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (-not (Test-Path (Join-Path $OpenSSHBinPath ssh.exe) -PathType Leaf))
|
||||
{
|
||||
Throw "Cannot find OpenSSH binaries under $OpenSSHBinPath. Please specify -OpenSSHBinPathto the OpenSSH installed location"
|
||||
}
|
||||
else
|
||||
{
|
||||
$script:OpenSSHBinPath = $OpenSSHBinPath
|
||||
}
|
||||
}
|
||||
|
||||
$Global:OpenSSHTestInfo.Add("OpenSSHBinPath", $script:OpenSSHBinPath)
|
||||
|
||||
$warning = @"
|
||||
WARNING: Following changes will be made to OpenSSH configuration
|
||||
- sshd_config will be backed up as sshd_config.ori
|
||||
- will be replaced with a test sshd_config
|
||||
- $HOME\.ssh\known_hosts will be backed up as known_hosts.ori
|
||||
- will be replaced with a test known_hosts
|
||||
- sshd test listener will be on port 47002
|
||||
- $HOME\.ssh\known_hosts will be modified with test host key entry
|
||||
- test accounts - ssouser, pubkeyuser, and passwduser will be added
|
||||
- Setup single signon for ssouser
|
||||
- To cleanup - Run Cleanup-OpenSSHTestEnvironment
|
||||
"@
|
||||
|
||||
if (-not $Quiet) {
|
||||
Write-Warning $warning
|
||||
$continue = Read-Host -Prompt "Do you want to continue with the above changes? [Yes] Y; [No] N (default is `"Y`")"
|
||||
if( ($continue -eq "") -or ($continue -ieq "Y") -or ($continue -ieq "Yes") )
|
||||
{
|
||||
}
|
||||
elseif( ($continue -ieq "N") -or ($continue -ieq "No") )
|
||||
{
|
||||
Write-Host "User decided not to make the changes."
|
||||
return
|
||||
}
|
||||
else
|
||||
{
|
||||
Throw "User entered invalid option ($continue). Exit now."
|
||||
}
|
||||
}
|
||||
|
||||
Install-OpenSSHTestDependencies
|
||||
|
||||
if(-not (Test-path $TestDataPath -PathType Container))
|
||||
{
|
||||
New-Item -ItemType Directory -Path $TestDataPath -Force -ErrorAction SilentlyContinue | out-null
|
||||
}
|
||||
|
||||
#Backup existing OpenSSH configuration
|
||||
$backupConfigPath = Join-Path $script:OpenSSHBinPath sshd_config.ori
|
||||
if (-not (Test-Path $backupConfigPath -PathType Leaf)) {
|
||||
Copy-Item (Join-Path $script:OpenSSHBinPath sshd_config) $backupConfigPath -Force
|
||||
}
|
||||
|
||||
# copy new sshd_config
|
||||
Copy-Item (Join-Path $Script:E2ETestDirectory sshd_config) (Join-Path $script:OpenSSHBinPath sshd_config) -Force
|
||||
Copy-Item "$($Script:E2ETestDirectory)\sshtest*hostkey*" $script:OpenSSHBinPath -Force
|
||||
Restart-Service sshd -Force
|
||||
|
||||
#Backup existing known_hosts and replace with test version
|
||||
#TODO - account for custom known_hosts locations
|
||||
$knowHostsDirectoryPath = Join-Path $home .ssh
|
||||
$knowHostsFilePath = Join-Path $knowHostsDirectoryPath known_hosts
|
||||
if(-not (Test-Path $knowHostsDirectoryPath -PathType Container))
|
||||
{
|
||||
New-Item -ItemType Directory -Path $knowHostsDirectoryPath -Force -ErrorAction SilentlyContinue | out-null
|
||||
}
|
||||
if ((Test-Path $knowHostsFilePath -PathType Leaf) -and (-not (Test-Path (Join-Path $knowHostsDirectoryPath known_hosts.ori) -PathType Leaf))) {
|
||||
Copy-Item $knowHostsFilePath (Join-Path $knowHostsDirectoryPath known_hosts.ori) -Force
|
||||
}
|
||||
Copy-Item (Join-Path $Script:E2ETestDirectory known_hosts) $knowHostsFilePath -Force
|
||||
|
||||
# create test accounts
|
||||
#TODO - this is Windows specific. Need to be in PAL
|
||||
foreach ($user in $OpenSSHTestAccounts)
|
||||
{
|
||||
try
|
||||
{
|
||||
$objUser = New-Object System.Security.Principal.NTAccount($user)
|
||||
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
|
||||
}
|
||||
catch
|
||||
{
|
||||
#only add the local user when it does not exists on the machine
|
||||
net user $user $Script:OpenSSHTestAccountsPassword /ADD 2>&1 >> $Script:TestSetupLogFile
|
||||
}
|
||||
}
|
||||
|
||||
#setup single sign on for ssouser
|
||||
#TODO - this is Windows specific. Need to be in PAL
|
||||
$ssousersid = Get-UserSID -User sshtest_ssouser
|
||||
$ssouserProfileRegistry = Join-Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" $ssousersid
|
||||
if (-not (Test-Path $ssouserProfileRegistry) ) {
|
||||
#create profile
|
||||
if (-not($env:DISPLAY)) { $env:DISPLAY = 1 }
|
||||
$env:SSH_ASKPASS="$($env:ComSpec) /c echo $($OpenSSHTestAccountsPassword)"
|
||||
cmd /c "ssh -p 47002 sshtest_ssouser@localhost echo %userprofile% > profile.txt"
|
||||
if ($env:DISPLAY -eq 1) { Remove-Item env:\DISPLAY }
|
||||
remove-item "env:SSH_ASKPASS" -ErrorAction SilentlyContinue
|
||||
}
|
||||
$ssouserProfile = (Get-ItemProperty -Path $ssouserProfileRegistry -Name 'ProfileImagePath').ProfileImagePath
|
||||
New-Item -ItemType Directory -Path (Join-Path $ssouserProfile .ssh) -Force -ErrorAction SilentlyContinue | out-null
|
||||
$authorizedKeyPath = Join-Path $ssouserProfile .ssh\authorized_keys
|
||||
$testPubKeyPath = Join-Path $Script:E2ETestDirectory sshtest_userssokey_ed25519.pub
|
||||
#workaround for the cariggage new line added by git
|
||||
(Get-Content $testPubKeyPath -Raw).Replace("`r`n","`n") | Set-Content $testPubKeyPath -Force
|
||||
Copy-Item $testPubKeyPath $authorizedKeyPath -Force -ErrorAction SilentlyContinue
|
||||
$acl = get-acl $authorizedKeyPath
|
||||
$ar = New-Object System.Security.AccessControl.FileSystemAccessRule("NT Service\sshd", "Read", "Allow")
|
||||
$acl.SetAccessRule($ar)
|
||||
Set-Acl $authorizedKeyPath $acl
|
||||
$testPriKeypath = Join-Path $Script:E2ETestDirectory sshtest_userssokey_ed25519
|
||||
(Get-Content $testPriKeypath -Raw).Replace("`r`n","`n") | Set-Content $testPriKeypath -Force
|
||||
cmd /c "ssh-add $testPriKeypath 2>&1 >> $Script:TestSetupLogFile"
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This function installs the tools required by our tests
|
||||
1) Pester for running the tests
|
||||
2) sysinternals required by the tests on windows.
|
||||
#>
|
||||
function Install-OpenSSHTestDependencies
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param ()
|
||||
|
||||
# Install chocolatey
|
||||
if(-not (Get-Command "choco" -ErrorAction SilentlyContinue))
|
||||
{
|
||||
Write-Log -Message "Chocolatey not present. Installing chocolatey."
|
||||
Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $Script:TestSetupLogFile
|
||||
}
|
||||
|
||||
$isModuleAvailable = Get-Module 'Pester' -ListAvailable
|
||||
if (-not ($isModuleAvailable))
|
||||
{
|
||||
Write-Log -Message "Installing Pester..."
|
||||
choco install Pester -y --force --limitoutput 2>&1 >> $Script:TestSetupLogFile
|
||||
}
|
||||
|
||||
if ( -not (Test-Path "$env:ProgramData\chocolatey\lib\sysinternals\tools" ) ) {
|
||||
Write-Log -Message "sysinternals not present. Installing sysinternals."
|
||||
choco install sysinternals -y --force --limitoutput 2>&1 >> $Script:TestSetupLogFile
|
||||
}
|
||||
}
|
||||
<#
|
||||
.Synopsis
|
||||
Get-UserSID
|
||||
#>
|
||||
function Get-UserSID
|
||||
{
|
||||
param
|
||||
(
|
||||
[string]$Domain,
|
||||
[string]$User
|
||||
)
|
||||
if([string]::IsNullOrEmpty($Domain))
|
||||
{
|
||||
$objUser = New-Object System.Security.Principal.NTAccount($User)
|
||||
}
|
||||
else
|
||||
{
|
||||
$objUser = New-Object System.Security.Principal.NTAccount($Domain, $User)
|
||||
}
|
||||
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
|
||||
$strSID.Value
|
||||
}
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
Cleanup-OpenSSHTestEnvironment
|
||||
#>
|
||||
function Cleanup-OpenSSHTestEnvironment
|
||||
{
|
||||
# .exe - Windows specific. TODO - PAL
|
||||
if (-not (Test-Path (Join-Path $script:OpenSSHBinPath ssh.exe) -PathType Leaf))
|
||||
{
|
||||
Throw "Cannot find OpenSSH binaries under $script:OpenSSHBinPath. "
|
||||
}
|
||||
|
||||
#Restore sshd_config
|
||||
$backupConfigPath = Join-Path $Script:OpenSSHBinPath sshd_config.ori
|
||||
if (Test-Path $backupConfigPath -PathType Leaf) {
|
||||
Copy-Item $backupConfigPath (Join-Path $Script:OpenSSHBinPath sshd_config) -Force -ErrorAction SilentlyContinue
|
||||
Remove-Item (Join-Path $Script:OpenSSHBinPath sshd_config.ori) -Force -ErrorAction SilentlyContinue
|
||||
Remove-Item $Script:OpenSSHBinPath\sshtest*hostkey* -Force -ErrorAction SilentlyContinue
|
||||
Restart-Service sshd
|
||||
}
|
||||
|
||||
#Restore known_hosts
|
||||
$originKnowHostsPath = Join-Path $home .ssh\known_hosts.ori
|
||||
if (Test-Path $originKnowHostsPath)
|
||||
{
|
||||
Copy-Item $originKnowHostsPath (Join-Path $home .ssh\known_hosts) -Force -ErrorAction SilentlyContinue
|
||||
Remove-Item $originKnowHostsPath -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
#Delete accounts
|
||||
foreach ($user in $OpenSSHTestAccounts)
|
||||
{
|
||||
net user $user /delete
|
||||
}
|
||||
|
||||
# remove registered keys
|
||||
cmd /c "ssh-add -d (Join-Path $Script:E2ETestDirectory sshtest_userssokey_ed25519) 2>&1 >> $Script:TestSetupLogFile"
|
||||
|
||||
if($Global:OpenSSHTestInfo -ne $null)
|
||||
{
|
||||
$Global:OpenSSHTestInfo.Clear()
|
||||
$Global:OpenSSHTestInfo = $null
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
Get-UnitTestDirectory.
|
||||
#>
|
||||
function Get-UnitTestDirectory
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[ValidateSet('Debug', 'Release')]
|
||||
[string]$Configuration = "Release",
|
||||
|
||||
[ValidateSet('x86', 'x64', '')]
|
||||
[string]$NativeHostArch = ""
|
||||
)
|
||||
|
||||
[string] $platform = $env:PROCESSOR_ARCHITECTURE
|
||||
if(-not [String]::IsNullOrEmpty($NativeHostArch))
|
||||
{
|
||||
$folderName = $NativeHostArch
|
||||
if($NativeHostArch -eq '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"
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$RealConfiguration = $Configuration
|
||||
}
|
||||
$unitTestdir = Join-Path $repositoryRoot.FullName -ChildPath "bin\$folderName\$RealConfiguration"
|
||||
$unitTestDir
|
||||
}
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
Run OpenSSH pester tests.
|
||||
#>
|
||||
function Run-OpenSSHE2ETest
|
||||
{
|
||||
# Discover all CI tests and run them.
|
||||
Push-Location $Script:E2ETestDirectory
|
||||
Write-Log -Message "Running OpenSSH E2E tests..."
|
||||
$testFolders = Get-ChildItem *.tests.ps1 -Recurse -Exclude SSHDConfig.tests.ps1, SSH.Tests.ps1 | ForEach-Object{ Split-Path $_.FullName} | Sort-Object -Unique
|
||||
Invoke-Pester $testFolders -OutputFormat NUnitXml -OutputFile $Script:E2ETestResultsFile -Tag 'CI'
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
Run openssh unit tests.
|
||||
#>
|
||||
function Run-OpenSSHUnitTest
|
||||
{
|
||||
# Discover all CI tests and run them.
|
||||
Push-Location $Script:UnitTestDirectory
|
||||
Write-Log -Message "Running OpenSSH unit tests..."
|
||||
if (Test-Path $Script:UnitTestResultsFile)
|
||||
{
|
||||
$null = Remove-Item -Path $Script:UnitTestResultsFile -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
$testFolders = Get-ChildItem unittest-*.exe -Recurse -Exclude unittest-sshkey.exe,unittest-kex.exe |
|
||||
ForEach-Object{ Split-Path $_.FullName} |
|
||||
Sort-Object -Unique
|
||||
$testfailed = $false
|
||||
if ($testFolders -ne $null)
|
||||
{
|
||||
$testFolders | % {
|
||||
Push-Location $_
|
||||
$unittestFile = "$(Split-Path $_ -Leaf).exe"
|
||||
Write-log "Running OpenSSH unit $unittestFile ..."
|
||||
& .\$unittestFile >> $Script:UnitTestResultsFile
|
||||
|
||||
$errorCode = $LASTEXITCODE
|
||||
if ($errorCode -ne 0)
|
||||
{
|
||||
$testfailed = $true
|
||||
$errorMessage = "$($_.FullName) test failed for OpenSSH.`nExitCode: $errorCode. Detail test log is at $($Script:UnitTestResultsFile)."
|
||||
Write-Warning $errorMessage
|
||||
}
|
||||
Pop-Location
|
||||
}
|
||||
}
|
||||
Pop-Location
|
||||
$testfailed
|
||||
}
|
||||
|
||||
<#
|
||||
Write-Log
|
||||
#>
|
||||
function Write-Log
|
||||
{
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string] $Message
|
||||
)
|
||||
if(-not (Test-Path (Split-Path $Script:TestSetupLogFile) -PathType Container))
|
||||
{
|
||||
$null = New-Item -ItemType Directory -Path (Split-Path $Script:TestSetupLogFile) -Force -ErrorAction SilentlyContinue | out-null
|
||||
}
|
||||
if (-not ([string]::IsNullOrEmpty($Script:TestSetupLogFile)))
|
||||
{
|
||||
Add-Content -Path $Script:TestSetupLogFile -Value $Message
|
||||
}
|
||||
}
|
||||
|
||||
Export-ModuleMember -Function Setup-OpenSSHTestEnvironment, Cleanup-OpenSSHTestEnvironment, Run-OpenSSHUnitTest, Run-OpenSSHE2ETest
|
@ -126,14 +126,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittest-win32compat", "uni
|
||||
{0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittest-utf8", "unittest-utf8.vcxproj", "{114CAA59-46C0-4B87-BA86-C1946A68101D}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
|
||||
{8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}
|
||||
{DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
|
||||
{0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittest-hostkeys", "unittest-hostkeys.vcxproj", "{890C6129-286F-4CD8-8252-FB8D3B4E6E1B}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
|
||||
@ -314,14 +306,6 @@ Global
|
||||
{BF295BA9-4BF8-43F8-8CBF-FAE84815466C}.Release|x64.Build.0 = Release|x64
|
||||
{BF295BA9-4BF8-43F8-8CBF-FAE84815466C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{BF295BA9-4BF8-43F8-8CBF-FAE84815466C}.Release|x86.Build.0 = Release|Win32
|
||||
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Debug|x64.Build.0 = Debug|x64
|
||||
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Debug|x86.Build.0 = Debug|Win32
|
||||
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Release|x64.ActiveCfg = Release|x64
|
||||
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Release|x64.Build.0 = Release|x64
|
||||
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Release|x86.ActiveCfg = Release|Win32
|
||||
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Release|x86.Build.0 = Release|Win32
|
||||
{890C6129-286F-4CD8-8252-FB8D3B4E6E1B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{890C6129-286F-4CD8-8252-FB8D3B4E6E1B}.Debug|x64.Build.0 = Debug|x64
|
||||
{890C6129-286F-4CD8-8252-FB8D3B4E6E1B}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
@ -369,7 +353,6 @@ Global
|
||||
{8EC56B06-5A9A-4D6D-804D-037FE26FD43E} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
|
||||
{CD9740CE-C96E-49B3-823F-012E09D17806} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
|
||||
{BF295BA9-4BF8-43F8-8CBF-FAE84815466C} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
|
||||
{114CAA59-46C0-4B87-BA86-C1946A68101D} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
|
||||
{890C6129-286F-4CD8-8252-FB8D3B4E6E1B} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
|
||||
{FC568FF0-60F2-4B2E-AF62-FD392EDBA1B9} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
|
||||
{484A8CDE-B949-4BDA-B447-74685C8E032F} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
|
||||
|
@ -1681,13 +1681,12 @@
|
||||
/* Windows specific macro added to workaround mysignal implementaion in bsd-misc.c */
|
||||
#define HAVE_MYSIGNAL 1
|
||||
|
||||
|
||||
#define PATH_MAX MAX_PATH
|
||||
|
||||
#define S_IFIFO 0x1000
|
||||
|
||||
#define HAVE_EXPLICIT_BZERO
|
||||
|
||||
#define HAVE_MBTOWC 1
|
||||
#define HAVE_LLABS 1
|
||||
|
||||
#include <signal.h>
|
||||
#include <io.h>
|
||||
|
@ -117,6 +117,10 @@
|
||||
<PreBuildEvent>
|
||||
<Message>Generate crtheaders.h and config.h</Message>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command>copy /Y $(SolutionDir)install-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & If NOT exist $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\sshd_config (copy $(SolutionDir)sshd_config $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\)</Command>
|
||||
<Message>Copy install-sshd.ps1, uninstall-sshd.ps1 and sshd_config (if not already present) to build directory</Message>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
@ -141,6 +145,10 @@
|
||||
<PreBuildEvent>
|
||||
<Message>Generate crtheaders.h and config.h</Message>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command>copy /Y $(SolutionDir)install-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & If NOT exist $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\sshd_config (copy $(SolutionDir)sshd_config $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\)</Command>
|
||||
<Message>Copy install-sshd.ps1, uninstall-sshd.ps1 and sshd_config (if not already present) to build directory</Message>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
@ -169,6 +177,10 @@
|
||||
<PreBuildEvent>
|
||||
<Message>Generate crtheaders.h and config.h</Message>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command>copy /Y $(SolutionDir)install-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & If NOT exist $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\sshd_config (copy $(SolutionDir)sshd_config $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\)</Command>
|
||||
<Message>Copy install-sshd.ps1, uninstall-sshd.ps1 and sshd_config (if not already present) to build directory</Message>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
@ -197,6 +209,10 @@
|
||||
<PreBuildEvent>
|
||||
<Message>Generate crtheaders.h and config.h</Message>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command>copy /Y $(SolutionDir)install-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & If NOT exist $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\sshd_config (copy $(SolutionDir)sshd_config $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\)</Command>
|
||||
<Message>Copy install-sshd.ps1, uninstall-sshd.ps1 and sshd_config (if not already present) to build directory</Message>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
@ -1,5 +1,6 @@
|
||||
# @manojampalam - authored initial script
|
||||
# @friism - Fixed issue with invalid SDDL on Set-Acl
|
||||
# @manojampalam - removed ntrights.exe dependency
|
||||
|
||||
$scriptpath = $MyInvocation.MyCommand.Path
|
||||
$scriptdir = Split-Path $scriptpath
|
||||
@ -8,8 +9,71 @@ $sshdpath = Join-Path $scriptdir "sshd.exe"
|
||||
$sshagentpath = Join-Path $scriptdir "ssh-agent.exe"
|
||||
$logsdir = Join-Path $scriptdir "logs"
|
||||
|
||||
$account = "NT SERVICE\SSHD"
|
||||
$ntrights = "ntrights.exe -u `"{0}`" +r SeAssignPrimaryTokenPrivilege" -f $account
|
||||
$sshdAccount = "NT SERVICE\SSHD"
|
||||
|
||||
#Idea borrowed from http://sqldbamusings.blogspot.com/2012/03/powershell-adding-accounts-to-local.html
|
||||
function Add-Privilege
|
||||
{
|
||||
param(
|
||||
[string] $Account,
|
||||
|
||||
[ValidateSet("SeAssignPrimaryTokenPrivilege", "SeServiceLogonRight")]
|
||||
[string] $Privilege
|
||||
)
|
||||
|
||||
#Get $Account SID
|
||||
$account_sid = $null
|
||||
try
|
||||
{
|
||||
$ntprincipal = new-object System.Security.Principal.NTAccount "$Account"
|
||||
$sid = $ntprincipal.Translate([System.Security.Principal.SecurityIdentifier])
|
||||
$account_sid = $sid.Value.ToString()
|
||||
}
|
||||
catch
|
||||
{
|
||||
Throw 'Unable to resolve '+ $Account
|
||||
}
|
||||
|
||||
#Prepare policy settings file to be applied
|
||||
$settings_to_export = [System.IO.Path]::GetTempFileName()
|
||||
"[Unicode]" | Set-Content $settings_to_export -Encoding Unicode
|
||||
"Unicode=yes" | Add-Content $settings_to_export -Force -WhatIf:$false
|
||||
"[Version]" | Add-Content $settings_to_export -Force -WhatIf:$false
|
||||
"signature=`"`$CHICAGO`$`"" | Add-Content $settings_to_export -Force -WhatIf:$false
|
||||
"Revision=1" | Add-Content $settings_to_export -Force -WhatIf:$false
|
||||
"[Privilege Rights]" | Add-Content $settings_to_export -Force -WhatIf:$false
|
||||
|
||||
#Get Current policy settings
|
||||
$imported_settings = [System.IO.Path]::GetTempFileName()
|
||||
secedit.exe /export /areas USER_RIGHTS /cfg "$($imported_settings)" > $null
|
||||
|
||||
if (-not(Test-Path $imported_settings)) {
|
||||
Throw "Unable to import current security policy settings"
|
||||
}
|
||||
|
||||
#find current assigned accounts to $Privilege and add it to $settings_to_export
|
||||
$current_settings = Get-Content $imported_settings -Encoding Unicode
|
||||
$existing_setting = $null
|
||||
foreach ($setting in $current_settings) {
|
||||
if ($setting -like "$Privilege`*") {
|
||||
$existing_setting = $setting
|
||||
}
|
||||
}
|
||||
|
||||
#Add $account_sid to list
|
||||
if ($existing_setting -eq $null) {
|
||||
$Privilege + " = *" + $account_sid | Add-Content $settings_to_export -Force -WhatIf:$false
|
||||
}
|
||||
else
|
||||
{
|
||||
$existing_setting + ",*" + $account_sid | Add-Content $settings_to_export -Force -WhatIf:$false
|
||||
}
|
||||
|
||||
#export
|
||||
secedit.exe /configure /db "secedit.sdb" /cfg "$($settings_to_export)" /areas USER_RIGHTS > $null
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (-not (Test-Path $sshdpath)) {
|
||||
throw "sshd.exe is not present in script path"
|
||||
@ -30,20 +94,18 @@ if (Get-Service ssh-agent -ErrorAction SilentlyContinue)
|
||||
New-Service -Name ssh-agent -BinaryPathName $sshagentpath -Description "SSH Agent" -StartupType Manual | Out-Null
|
||||
cmd.exe /c 'sc.exe sdset ssh-agent D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;RP;;;AU)'
|
||||
|
||||
New-Service -Name sshd -BinaryPathName $sshdpath -Description "SSH Deamon" -StartupType Manual -DependsOn ssh-agent | Out-Null
|
||||
sc.exe config sshd obj= $account
|
||||
New-Service -Name sshd -BinaryPathName $sshdpath -Description "SSH Daemon" -StartupType Manual -DependsOn ssh-agent | Out-Null
|
||||
sc.exe config sshd obj= $sshdAccount
|
||||
|
||||
Push-Location
|
||||
cd $scriptdir
|
||||
cmd.exe /c $ntrights
|
||||
Pop-Location
|
||||
Add-Privilege -Account $sshdAccount -Privilege SeAssignPrimaryTokenPrivilege
|
||||
Add-Privilege -Account $sshdAccount -Privilege SeServiceLogonRight
|
||||
|
||||
if(-not (test-path $logsdir -PathType Container))
|
||||
{
|
||||
$null = New-Item $logsdir -ItemType Directory -Force -ErrorAction Stop
|
||||
}
|
||||
$rights = [System.Security.AccessControl.FileSystemRights]"Read, Write"
|
||||
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($account, $rights, "ContainerInherit,ObjectInherit", "None", "Allow")
|
||||
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($sshdAccount, $rights, "ContainerInherit,ObjectInherit", "None", "Allow")
|
||||
$acl = Get-Acl -Path $logsdir
|
||||
$Acl.SetAccessRule($accessRule)
|
||||
Set-Acl -Path $logsdir -AclObject $acl
|
||||
|
@ -290,7 +290,6 @@
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)uuencode.h" />
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)version.h" />
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)xmalloc.h" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)clientloop.c" />
|
||||
@ -299,7 +298,8 @@
|
||||
<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)sshtty.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshtty.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="version.rc" />
|
||||
|
@ -305,10 +305,10 @@
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)sshconnect2.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)sshtty.c">
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c">
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshtty.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
@ -222,6 +222,7 @@
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)auth2-passwd.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)auth2-pubkey.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)auth2.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)groupaccess.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)gss-serv-krb5.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)gss-serv.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)kexdhs.c" />
|
||||
@ -244,9 +245,8 @@
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)sftp-common.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)sshd.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)sshlogin.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)sshpty.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshpty.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_sshd.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)groupaccess.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="version.rc" />
|
||||
|
@ -144,15 +144,15 @@
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)sshlogin.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)sshpty.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_sshd.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)groupaccess.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshpty.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="version.rc">
|
||||
|
@ -119,4 +119,4 @@ Subsystem sftp sftp-server.exe
|
||||
# X11Forwarding no
|
||||
# AllowTcpForwarding no
|
||||
# ForceCommand cvs server
|
||||
PubkeyAcceptedKeyTypes ssh-ed25519*
|
||||
# PubkeyAcceptedKeyTypes ssh-ed25519*
|
Binary file not shown.
@ -204,8 +204,9 @@
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\sys\types.h" />
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\ctype.h" />
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\stdlib.h" />
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\debug.h" />
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\console.h" />
|
||||
<ClInclude Include="..\win32compat\tnnet.h" />
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tnnet.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
@ -139,8 +139,9 @@
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\ctype.h">
|
||||
<Filter>inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\debug.h" />
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\console.h" />
|
||||
<ClInclude Include="..\win32compat\tnnet.h" />
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tnnet.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="inc">
|
||||
|
@ -1,39 +1,10 @@
|
||||
/*
|
||||
* Author: NoMachine <developers@nomachine.com>
|
||||
*
|
||||
* Copyright (c) 2009, 2011 NoMachine
|
||||
* All rights reserved
|
||||
*
|
||||
* Support functions and system calls' replacements needed to let the
|
||||
* software run on Win32 based operating systems.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef Debug_H
|
||||
#define Debug_H
|
||||
|
||||
#define FAIL(CONDITION) if (CONDITION) goto fail
|
||||
|
||||
#define NTFAIL(NTFUNC) if((ntStat = (NTFUNC))) goto fail
|
||||
|
||||
#endif
|
||||
/* Enable the following for verbose logging */
|
||||
#if (0)
|
||||
#define debug4 debug2
|
||||
#define debug5 debug3
|
||||
#else
|
||||
#define debug4(a,...)
|
||||
#define debug5(a,...)
|
||||
#endif
|
@ -38,10 +38,6 @@
|
||||
|
||||
#include "console.h"
|
||||
|
||||
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4
|
||||
#endif
|
||||
|
||||
HANDLE hOutputConsole = NULL;
|
||||
DWORD dwSavedAttributes = 0;
|
||||
WORD wStartingAttributes = 0;
|
||||
@ -140,7 +136,7 @@ ConEnterRawMode(DWORD OutputHandle, BOOL fSmartInit)
|
||||
SavedViewRect = csbi.srWindow;
|
||||
debug("console doesn't support the ansi parsing");
|
||||
} else {
|
||||
ConMoveCurosorTop(csbi);
|
||||
ConMoveCursorTop(csbi);
|
||||
debug("console supports the ansi parsing");
|
||||
}
|
||||
|
||||
@ -1075,16 +1071,27 @@ ConScrollUp(int topline, int botline)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
ConMoveVisibleWindow(int offset)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
|
||||
SMALL_RECT visibleWindowRect;
|
||||
|
||||
if (GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo)) {
|
||||
memcpy(&visibleWindowRect, &consoleInfo.srWindow, sizeof(visibleWindowRect));
|
||||
visibleWindowRect.Top += offset;
|
||||
visibleWindowRect.Bottom += offset;
|
||||
/* Check if applying the offset results in console buffer overflow.
|
||||
* if yes, then scrolldown the console buffer.
|
||||
*/
|
||||
if ((consoleInfo.srWindow.Bottom + offset) >= (consoleInfo.dwSize.Y - 1)) {
|
||||
for (int i = 0; i < offset; i++)
|
||||
ConScrollDown(0, consoleInfo.dwSize.Y - 1);
|
||||
|
||||
if (GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
|
||||
memcpy(&visibleWindowRect, &consoleInfo.srWindow, sizeof(visibleWindowRect));
|
||||
} else {
|
||||
memcpy(&visibleWindowRect, &consoleInfo.srWindow, sizeof(visibleWindowRect));
|
||||
visibleWindowRect.Top += offset;
|
||||
visibleWindowRect.Bottom += offset;
|
||||
}
|
||||
|
||||
SetConsoleWindowInfo(hOutputConsole, TRUE, &visibleWindowRect);
|
||||
}
|
||||
@ -1552,10 +1559,48 @@ ConSaveWindowsState()
|
||||
}
|
||||
|
||||
void
|
||||
ConMoveCurosorTop(CONSOLE_SCREEN_BUFFER_INFO csbi)
|
||||
ConMoveCursorTop(CONSOLE_SCREEN_BUFFER_INFO csbi)
|
||||
{
|
||||
/* Windows server at first sends the "cls" after the connection is established.
|
||||
* Since we don't want to loose any data on the console, we would like to scroll down
|
||||
* the visible window.
|
||||
*/
|
||||
int offset = csbi.dwCursorPosition.Y - csbi.srWindow.Top;
|
||||
ConMoveVisibleWindow(offset);
|
||||
|
||||
ConSaveViewRect();
|
||||
}
|
||||
|
||||
HANDLE
|
||||
get_console_handle(FILE *stream, DWORD * mode)
|
||||
{
|
||||
int file_num = 0, ret = 0;
|
||||
intptr_t lHandle = 0;
|
||||
HANDLE hFile = NULL;
|
||||
DWORD type = 0;
|
||||
|
||||
file_num = (_fileno)(stream);
|
||||
if (file_num == -1) {
|
||||
return -1;
|
||||
}
|
||||
lHandle = _get_osfhandle(file_num);
|
||||
if (lHandle == -1 && errno == EBADF) {
|
||||
return -1;
|
||||
}
|
||||
type = GetFileType((HANDLE)lHandle);
|
||||
if (type == FILE_TYPE_CHAR && file_num >= 0 && file_num <= 2) {
|
||||
if (file_num == 0)
|
||||
hFile = GetStdHandle(STD_INPUT_HANDLE);
|
||||
else if (file_num == 1)
|
||||
hFile = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
else if (file_num == 2)
|
||||
hFile = GetStdHandle(STD_ERROR_HANDLE);
|
||||
|
||||
if ((hFile != NULL) &&
|
||||
(hFile != INVALID_HANDLE_VALUE) &&
|
||||
(GetFileType(hFile) == FILE_TYPE_CHAR) &&
|
||||
GetConsoleMode(hFile, mode))
|
||||
return hFile;
|
||||
}
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
@ -79,6 +79,10 @@
|
||||
#define false FALSE
|
||||
#define bool BOOL
|
||||
|
||||
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4
|
||||
#endif
|
||||
|
||||
typedef void * SCREEN_HANDLE;
|
||||
|
||||
int ConEnterRawMode(DWORD OutputHandle, BOOL fSmartInit);
|
||||
@ -137,5 +141,6 @@ void ConSaveWindowsState();
|
||||
void ConMoveVisibleWindow(int offset);
|
||||
int is_cursor_at_lastline_of_visible_window();
|
||||
void ConGetCursorPosition(int *x, int *y);
|
||||
void ConMoveCurosorTop(CONSOLE_SCREEN_BUFFER_INFO csbi);
|
||||
void ConMoveCursorTop(CONSOLE_SCREEN_BUFFER_INFO csbi);
|
||||
HANDLE get_console_handle(FILE *, DWORD *);
|
||||
#endif
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "inc\utf.h"
|
||||
#include "inc\fcntl.h"
|
||||
#include "misc_internal.h"
|
||||
#include "debug.h"
|
||||
|
||||
/* internal read buffer size */
|
||||
#define READ_BUFFER_SIZE 100*1024
|
||||
@ -97,7 +98,7 @@ fileio_connect(struct w32_io* pio, char* name)
|
||||
int ret = 0;
|
||||
|
||||
if (pio->handle != 0 && pio->handle != INVALID_HANDLE_VALUE) {
|
||||
debug("fileio_connect called in unexpected state, pio = %p", pio);
|
||||
debug3("fileio_connect called in unexpected state, pio = %p", pio);
|
||||
errno = EOTHER;
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
@ -114,13 +115,13 @@ fileio_connect(struct w32_io* pio, char* name)
|
||||
/* TODO - support nonblocking connect */
|
||||
/* wait until we have a server pipe instance to connect */
|
||||
while (h == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY) {
|
||||
debug2("waiting for agent connection, retrying after 1 sec");
|
||||
debug4("waiting for agent connection, retrying after 1 sec");
|
||||
if ((ret = wait_for_any_event(NULL, 0, 1000) != 0) != 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
debug("unable to connect to pipe %ls, error: %d", name_w, GetLastError());
|
||||
debug3("unable to connect to pipe %ls, error: %d", name_w, GetLastError());
|
||||
errno = errno_from_Win32LastError();
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
@ -129,7 +130,7 @@ fileio_connect(struct w32_io* pio, char* name)
|
||||
if (SetHandleInformation(h, HANDLE_FLAG_INHERIT,
|
||||
pio->fd_flags & FD_CLOEXEC ? 0 : HANDLE_FLAG_INHERIT) == FALSE) {
|
||||
errno = errno_from_Win32LastError();
|
||||
debug("SetHandleInformation failed, error = %d, pio = %p", GetLastError(), pio);
|
||||
debug3("SetHandleInformation failed, error = %d, pio = %p", GetLastError(), pio);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -162,7 +163,7 @@ fileio_pipe(struct w32_io* pio[2])
|
||||
|
||||
if (pio == NULL) {
|
||||
errno = EINVAL;
|
||||
debug("pipe - ERROR invalid parameter");
|
||||
debug3("pipe - ERROR invalid parameter");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -170,7 +171,7 @@ fileio_pipe(struct w32_io* pio[2])
|
||||
if (-1 == sprintf_s(pipe_name, PATH_MAX, "\\\\.\\Pipe\\W32PosixPipe.%08x.%08x",
|
||||
GetCurrentProcessId(), pipe_counter++)) {
|
||||
errno = EOTHER;
|
||||
debug("pipe - ERROR sprintf_s %d", errno);
|
||||
debug3("pipe - ERROR sprintf_s %d", errno);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -179,31 +180,31 @@ fileio_pipe(struct w32_io* pio[2])
|
||||
sec_attributes.nLength = 0;
|
||||
|
||||
/* create named pipe */
|
||||
read_handle = CreateNamedPipeA(pipe_name,
|
||||
PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
|
||||
write_handle = CreateNamedPipeA(pipe_name,
|
||||
PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
|
||||
PIPE_TYPE_BYTE | PIPE_WAIT,
|
||||
1,
|
||||
4096,
|
||||
4096,
|
||||
0,
|
||||
&sec_attributes);
|
||||
if (read_handle == INVALID_HANDLE_VALUE) {
|
||||
if (write_handle == INVALID_HANDLE_VALUE) {
|
||||
errno = errno_from_Win32LastError();
|
||||
debug("pipe - CreateNamedPipe() ERROR:%d", errno);
|
||||
debug3("pipe - CreateNamedPipe() ERROR:%d", errno);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* connect to named pipe */
|
||||
write_handle = CreateFileA(pipe_name,
|
||||
GENERIC_WRITE,
|
||||
read_handle = CreateFileA(pipe_name,
|
||||
GENERIC_READ,
|
||||
0,
|
||||
&sec_attributes,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
||||
NULL);
|
||||
if (write_handle == INVALID_HANDLE_VALUE) {
|
||||
if (read_handle == INVALID_HANDLE_VALUE) {
|
||||
errno = errno_from_Win32LastError();
|
||||
debug("pipe - ERROR CreateFile() :%d", errno);
|
||||
debug3("pipe - ERROR CreateFile() :%d", errno);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -213,7 +214,7 @@ fileio_pipe(struct w32_io* pio[2])
|
||||
|
||||
if (!pio_read || !pio_write) {
|
||||
errno = ENOMEM;
|
||||
debug("pip - ERROR:%d", errno);
|
||||
debug3("pip - ERROR:%d", errno);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -252,21 +253,21 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags)
|
||||
* O_RDONLY, O_WRONLY, or O_RDWR
|
||||
*/
|
||||
if ((rwflags != O_RDONLY) && (rwflags != O_WRONLY) && (rwflags != O_RDWR)) {
|
||||
debug("open - flags ERROR: wrong rw flags: %d", flags);
|
||||
debug3("open - flags ERROR: wrong rw flags: %d", flags);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*only following create and status flags currently supported*/
|
||||
if (c_s_flags & ~(O_NONBLOCK | O_APPEND | O_CREAT | O_TRUNC | O_EXCL | O_BINARY)) {
|
||||
debug("open - ERROR: Unsupported flags: %d", flags);
|
||||
debug3("open - ERROR: Unsupported flags: %d", flags);
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*validate mode*/
|
||||
if (mode &~(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) {
|
||||
debug("open - ERROR: unsupported mode: %d", mode);
|
||||
debug3("open - ERROR: unsupported mode: %d", mode);
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
@ -310,6 +311,8 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define NULL_DEVICE "/dev/null"
|
||||
/* open() implementation. Uses CreateFile to open file, console, device, etc */
|
||||
struct w32_io*
|
||||
fileio_open(const char *path_utf8, int flags, int mode)
|
||||
@ -319,17 +322,21 @@ fileio_open(const char *path_utf8, int flags, int mode)
|
||||
HANDLE handle;
|
||||
wchar_t *path_utf16 = NULL;
|
||||
|
||||
debug2("open - pathname:%s, flags:%d, mode:%d", path_utf8, flags, mode);
|
||||
debug4("open - pathname:%s, flags:%d, mode:%d", path_utf8, flags, mode);
|
||||
/* check input params*/
|
||||
if (path_utf8 == NULL) {
|
||||
errno = EINVAL;
|
||||
debug("open - ERROR:%d", errno);
|
||||
debug3("open - ERROR:%d", errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* if opening null device, point to Windows equivalent */
|
||||
if (strncmp(path_utf8, NULL_DEVICE, strlen(NULL_DEVICE)) == 0)
|
||||
path_utf8 = "NUL";
|
||||
|
||||
if ((path_utf16 = utf8_to_utf16(path_utf8)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
debug("utf8_to_utf16 failed for file:%s error:%d", path_utf8, GetLastError());
|
||||
debug3("utf8_to_utf16 failed for file:%s error:%d", path_utf8, GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -342,7 +349,7 @@ fileio_open(const char *path_utf8, int flags, int mode)
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
errno = errno_from_Win32LastError();
|
||||
debug("failed to open file:%s error:%d", path_utf8, GetLastError());
|
||||
debug3("failed to open file:%s error:%d", path_utf8, GetLastError());
|
||||
free(path_utf16);
|
||||
return NULL;
|
||||
}
|
||||
@ -352,7 +359,7 @@ fileio_open(const char *path_utf8, int flags, int mode)
|
||||
if (pio == NULL) {
|
||||
CloseHandle(handle);
|
||||
errno = ENOMEM;
|
||||
debug("fileio_open(), failed to allocate memory error:%d", errno);
|
||||
debug3("fileio_open(), failed to allocate memory error:%d", errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -369,7 +376,7 @@ VOID CALLBACK
|
||||
ReadCompletionRoutine(_In_ DWORD dwErrorCode, _In_ DWORD dwNumberOfBytesTransfered, _Inout_ LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
struct w32_io* pio = (struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, read_overlapped));
|
||||
debug2("ReadCB pio:%p, pending_state:%d, error:%d, received:%d",
|
||||
debug4("ReadCB pio:%p, pending_state:%d, error:%d, received:%d",
|
||||
pio, pio->read_details.pending, dwErrorCode, dwNumberOfBytesTransfered);
|
||||
pio->read_details.error = dwErrorCode;
|
||||
pio->read_details.remaining = dwNumberOfBytesTransfered;
|
||||
@ -383,13 +390,13 @@ ReadCompletionRoutine(_In_ DWORD dwErrorCode, _In_ DWORD dwNumberOfBytesTransfer
|
||||
int
|
||||
fileio_ReadFileEx(struct w32_io* pio, unsigned int bytes_requested)
|
||||
{
|
||||
debug2("ReadFileEx io:%p", pio);
|
||||
debug4("ReadFileEx io:%p", pio);
|
||||
|
||||
if (pio->read_details.buf == NULL) {
|
||||
pio->read_details.buf = malloc(READ_BUFFER_SIZE);
|
||||
if (!pio->read_details.buf) {
|
||||
errno = ENOMEM;
|
||||
debug2("ReadFileEx - ERROR: %d, io:%p", errno, pio);
|
||||
debug4("ReadFileEx - ERROR: %d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -404,7 +411,7 @@ fileio_ReadFileEx(struct w32_io* pio, unsigned int bytes_requested)
|
||||
pio->read_details.pending = TRUE;
|
||||
else {
|
||||
errno = errno_from_Win32LastError();
|
||||
debug("ReadFileEx() ERROR:%d, io:%p", GetLastError(), pio);
|
||||
debug3("ReadFileEx() ERROR:%d, io:%p", GetLastError(), pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -417,18 +424,18 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max)
|
||||
{
|
||||
int bytes_copied;
|
||||
|
||||
debug3("read - io:%p remaining:%d", pio, pio->read_details.remaining);
|
||||
debug5("read - io:%p remaining:%d", pio, pio->read_details.remaining);
|
||||
/* if read is pending */
|
||||
if (pio->read_details.pending) {
|
||||
if (w32_io_is_blocking(pio)) {
|
||||
debug2("read - io is pending, blocking call made, io:%p", pio);
|
||||
debug4("read - io is pending, blocking call made, io:%p", pio);
|
||||
while (fileio_is_io_available(pio, TRUE) == FALSE) {
|
||||
if (-1 == wait_for_any_event(NULL, 0, INFINITE))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
errno = EAGAIN;
|
||||
debug2("read - io is already pending, io:%p", pio);
|
||||
debug4("read - io is already pending, io:%p", pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -442,14 +449,14 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max)
|
||||
if ((FILETYPE(pio) == FILE_TYPE_PIPE)
|
||||
&& (errno == ERROR_BROKEN_PIPE)) {
|
||||
/* write end of the pipe closed */
|
||||
debug("read - no more data, io:%p", pio);
|
||||
debug3("read - no more data, io:%p", pio);
|
||||
errno = 0;
|
||||
return 0;
|
||||
}
|
||||
/* on W2012, ReadFileEx on file throws a synchronous EOF error*/
|
||||
else if ((FILETYPE(pio) == FILE_TYPE_DISK)
|
||||
&& (errno == ERROR_HANDLE_EOF)) {
|
||||
debug("read - no more data, io:%p", pio);
|
||||
debug3("read - no more data, io:%p", pio);
|
||||
errno = 0;
|
||||
return 0;
|
||||
}
|
||||
@ -468,7 +475,7 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max)
|
||||
}
|
||||
else if (pio->read_details.pending) {
|
||||
errno = EAGAIN;
|
||||
debug2("read - IO is pending, io:%p", pio);
|
||||
debug4("read - IO is pending, io:%p", pio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -478,12 +485,12 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max)
|
||||
/*write end of the pipe is closed or pipe broken or eof reached*/
|
||||
if ((pio->read_details.error == ERROR_BROKEN_PIPE) ||
|
||||
(pio->read_details.error == ERROR_HANDLE_EOF)) {
|
||||
debug2("read - (2) no more data, io:%p", pio);
|
||||
debug4("read - (2) no more data, io:%p", pio);
|
||||
errno = 0;
|
||||
pio->read_details.error = 0;
|
||||
return 0;
|
||||
}
|
||||
debug("read - ERROR from cb :%d, io:%p", errno, pio);
|
||||
debug3("read - ERROR from cb :%d, io:%p", errno, pio);
|
||||
pio->read_details.error = 0;
|
||||
return -1;
|
||||
}
|
||||
@ -492,7 +499,7 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max)
|
||||
memcpy(dst, pio->read_details.buf + pio->read_details.completed, bytes_copied);
|
||||
pio->read_details.remaining -= bytes_copied;
|
||||
pio->read_details.completed += bytes_copied;
|
||||
debug2("read - io:%p read: %d remaining: %d", pio, bytes_copied,
|
||||
debug4("read - io:%p read: %d remaining: %d", pio, bytes_copied,
|
||||
pio->read_details.remaining);
|
||||
return bytes_copied;
|
||||
}
|
||||
@ -504,13 +511,13 @@ WriteCompletionRoutine(_In_ DWORD dwErrorCode,
|
||||
{
|
||||
struct w32_io* pio =
|
||||
(struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, write_overlapped));
|
||||
debug2("WriteCB - pio:%p, pending_state:%d, error:%d, transferred:%d of remaining: %d",
|
||||
debug4("WriteCB - pio:%p, pending_state:%d, error:%d, transferred:%d of remaining: %d",
|
||||
pio, pio->write_details.pending, dwErrorCode, dwNumberOfBytesTransfered,
|
||||
pio->write_details.remaining);
|
||||
pio->write_details.error = dwErrorCode;
|
||||
/* TODO - assert that remaining == dwNumberOfBytesTransfered */
|
||||
if ((dwErrorCode == 0) && (pio->write_details.remaining != dwNumberOfBytesTransfered)) {
|
||||
debug("WriteCB - ERROR: broken assumption, io:%p, wrote:%d, remaining:%d", pio,
|
||||
debug3("WriteCB - ERROR: broken assumption, io:%p, wrote:%d, remaining:%d", pio,
|
||||
dwNumberOfBytesTransfered, pio->write_details.remaining);
|
||||
DebugBreak();
|
||||
}
|
||||
@ -524,27 +531,28 @@ int
|
||||
fileio_write(struct w32_io* pio, const void *buf, unsigned int max)
|
||||
{
|
||||
int bytes_copied;
|
||||
DWORD pipe_flags = 0, pipe_instances = 0;
|
||||
|
||||
debug2("write - io:%p", pio);
|
||||
debug4("write - io:%p", pio);
|
||||
if (pio->write_details.pending) {
|
||||
if (w32_io_is_blocking(pio)) {
|
||||
debug2("write - io pending, blocking call made, io:%p", pio);
|
||||
debug4("write - io pending, blocking call made, io:%p", pio);
|
||||
while (pio->write_details.pending)
|
||||
if (wait_for_any_event(NULL, 0, INFINITE) == -1)
|
||||
return -1;
|
||||
} else {
|
||||
errno = EAGAIN;
|
||||
debug2("write - IO is already pending, io:%p", pio);
|
||||
debug4("write - IO is already pending, io:%p", pio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (pio->write_details.error) {
|
||||
errno = errno_from_Win32Error(pio->write_details.error);
|
||||
debug("write - ERROR:%d on prior unblocking write, io:%p", errno, pio);
|
||||
debug3("write - ERROR:%d on prior unblocking write, io:%p", errno, pio);
|
||||
pio->write_details.error = 0;
|
||||
if ((FILETYPE(pio) == FILE_TYPE_PIPE) && (errno == ERROR_BROKEN_PIPE)) {
|
||||
debug("write - ERROR:read end of the pipe closed, io:%p", pio);
|
||||
debug3("write - ERROR:read end of the pipe closed, io:%p", pio);
|
||||
errno = EPIPE;
|
||||
}
|
||||
return -1;
|
||||
@ -554,7 +562,7 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max)
|
||||
pio->write_details.buf = malloc(WRITE_BUFFER_SIZE);
|
||||
if (pio->write_details.buf == NULL) {
|
||||
errno = ENOMEM;
|
||||
debug("write - ERROR:%d, io:%p", errno, pio);
|
||||
debug3("write - ERROR:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
pio->write_details.buf_size = WRITE_BUFFER_SIZE;
|
||||
@ -570,6 +578,39 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max)
|
||||
}
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
return bytes_copied;
|
||||
} else {
|
||||
if (WriteFileEx(WINHANDLE(pio), pio->write_details.buf, bytes_copied,
|
||||
&pio->write_overlapped, &WriteCompletionRoutine)) {
|
||||
@ -579,10 +620,10 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max)
|
||||
errno = errno_from_Win32LastError();
|
||||
/* read end of the pipe closed ? */
|
||||
if ((FILETYPE(pio) == FILE_TYPE_PIPE) && (errno == ERROR_BROKEN_PIPE)) {
|
||||
debug("write - ERROR:read end of the pipe closed, io:%p", pio);
|
||||
debug3("write - ERROR:read end of the pipe closed, io:%p", pio);
|
||||
errno = EPIPE;
|
||||
}
|
||||
debug("write ERROR from cb(2):%d, io:%p", errno, pio);
|
||||
debug3("write ERROR from cb(2):%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -604,11 +645,11 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max)
|
||||
/* if write has completed, pick up any error reported*/
|
||||
if (!pio->write_details.pending && pio->write_details.error) {
|
||||
errno = errno_from_Win32Error(pio->write_details.error);
|
||||
debug("write - ERROR from cb:%d, io:%p", pio->write_details.error, pio);
|
||||
debug3("write - ERROR from cb:%d, io:%p", pio->write_details.error, pio);
|
||||
pio->write_details.error = 0;
|
||||
return -1;
|
||||
}
|
||||
debug2("write - reporting %d bytes written, io:%p", bytes_copied, pio);
|
||||
debug4("write - reporting %d bytes written, io:%p", bytes_copied, pio);
|
||||
return bytes_copied;
|
||||
|
||||
}
|
||||
@ -618,7 +659,7 @@ int
|
||||
fileio_fstat(struct w32_io* pio, struct _stat64 *buf)
|
||||
{
|
||||
int fd = _open_osfhandle((intptr_t)pio->handle, 0);
|
||||
debug2("fstat - pio:%p", pio);
|
||||
debug4("fstat - pio:%p", pio);
|
||||
if (fd == -1) {
|
||||
errno = EOTHER;
|
||||
return -1;
|
||||
@ -630,33 +671,31 @@ fileio_fstat(struct w32_io* pio, struct _stat64 *buf)
|
||||
int
|
||||
fileio_stat(const char *path, struct _stat64 *buf)
|
||||
{
|
||||
wchar_t wpath[PATH_MAX];
|
||||
wchar_t* wtmp = NULL;
|
||||
struct w32_io* pio;
|
||||
wchar_t* wpath = NULL;
|
||||
int r = -1;
|
||||
|
||||
if ((wtmp = utf8_to_utf16(path)) == NULL)
|
||||
if ((wpath = utf8_to_utf16(path)) == NULL)
|
||||
fatal("failed to covert input arguments");
|
||||
|
||||
/* If we doesn't have sufficient permissions then _wstat4() is returning
|
||||
* file not found so added fileio_open() which will set the errorno correctly (access denied)
|
||||
*/
|
||||
if (NULL == (pio = fileio_open(path, O_RDONLY, 0)))
|
||||
return -1;
|
||||
|
||||
fileio_close(pio);
|
||||
r = _wstat64(wpath, buf);
|
||||
|
||||
wcscpy(&wpath[0], wtmp);
|
||||
free(wtmp);
|
||||
/*
|
||||
* If we doesn't have sufficient permissions then _wstat64() is returning "file not found"
|
||||
* TODO - Replace the above call with GetFileAttributesEx
|
||||
*/
|
||||
|
||||
return _wstat64(wpath, buf);
|
||||
cleanup:
|
||||
if (wpath)
|
||||
free(wpath);
|
||||
return r;
|
||||
}
|
||||
|
||||
long
|
||||
fileio_lseek(struct w32_io* pio, long offset, int origin)
|
||||
{
|
||||
debug2("lseek - pio:%p", pio);
|
||||
debug4("lseek - pio:%p", pio);
|
||||
if (origin != SEEK_SET) {
|
||||
debug("lseek - ERROR, origin is not supported %d", origin);
|
||||
debug3("lseek - ERROR, origin is not supported %d", origin);
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
@ -671,7 +710,7 @@ FILE*
|
||||
fileio_fdopen(struct w32_io* pio, const char *mode)
|
||||
{
|
||||
int fd_flags = 0;
|
||||
debug2("fdopen - io:%p", pio);
|
||||
debug4("fdopen - io:%p", pio);
|
||||
|
||||
/* logic below doesn't work with overlapped file HANDLES */
|
||||
if (mode[1] == '\0') {
|
||||
@ -686,12 +725,12 @@ fileio_fdopen(struct w32_io* pio, const char *mode)
|
||||
break;
|
||||
default:
|
||||
errno = ENOTSUP;
|
||||
debug("fdopen - ERROR unsupported mode %s", mode);
|
||||
debug3("fdopen - ERROR unsupported mode %s", mode);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
errno = ENOTSUP;
|
||||
debug("fdopen - ERROR unsupported mode %s", mode);
|
||||
debug3("fdopen - ERROR unsupported mode %s", mode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -699,7 +738,7 @@ fileio_fdopen(struct w32_io* pio, const char *mode)
|
||||
|
||||
if (fd == -1) {
|
||||
errno = EOTHER;
|
||||
debug("fdopen - ERROR:%d _open_osfhandle()", errno);
|
||||
debug3("fdopen - ERROR:%d _open_osfhandle()", errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -732,7 +771,7 @@ fileio_on_select(struct w32_io* pio, BOOL rd)
|
||||
int
|
||||
fileio_close(struct w32_io* pio)
|
||||
{
|
||||
debug2("fileclose - pio:%p", pio);
|
||||
debug4("fileclose - pio:%p", pio);
|
||||
|
||||
/* handle can be null on AF_UNIX sockets that are not yet connected */
|
||||
if (WINHANDLE(pio) == 0 || WINHANDLE(pio) == INVALID_HANDLE_VALUE) {
|
||||
|
@ -81,4 +81,21 @@ char *crypt(const char *key, const char *salt);
|
||||
int link(const char *oldpath, const char *newpath);
|
||||
int readlink(const char *path, char *link, int linklen);
|
||||
|
||||
int spawn_child(char* cmd, int in, int out, int err, unsigned long flags);
|
||||
int spawn_child(char* cmd, char** argv, int in, int out, int err, unsigned long flags);
|
||||
|
||||
|
||||
/*
|
||||
* readpassphrase.h definitions
|
||||
* cannot create a separate header due to the way
|
||||
* its included in openbsdcompat.h
|
||||
*/
|
||||
|
||||
#define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */
|
||||
#define RPP_ECHO_ON 0x01 /* Leave echo on. */
|
||||
#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */
|
||||
#define RPP_FORCELOWER 0x04 /* Force input to lower case. */
|
||||
#define RPP_FORCEUPPER 0x08 /* Force input to upper case. */
|
||||
#define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */
|
||||
#define RPP_STDIN 0x20 /* Read from stdin, not /dev/tty */
|
||||
|
||||
char * readpassphrase(const char *, char *, size_t, int);
|
@ -33,6 +33,7 @@
|
||||
#include <time.h>
|
||||
#include <Shlwapi.h>
|
||||
|
||||
#include "inc\unistd.h"
|
||||
#include "inc\sys\stat.h"
|
||||
#include "inc\sys\statvfs.h"
|
||||
#include "inc\sys\time.h"
|
||||
@ -44,6 +45,7 @@
|
||||
#include "inc\fcntl.h"
|
||||
#include "inc\utf.h"
|
||||
#include "signal_internal.h"
|
||||
#include "debug.h"
|
||||
|
||||
static char* s_programdir = NULL;
|
||||
|
||||
@ -249,7 +251,7 @@ w32_fopen_utf8(const char *path, const char *mode)
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, PATH_MAX) == 0 ||
|
||||
MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, 5) == 0) {
|
||||
errno = EFAULT;
|
||||
debug("WideCharToMultiByte failed for %c - ERROR:%d", path, GetLastError());
|
||||
debug3("WideCharToMultiByte failed for %c - ERROR:%d", path, GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -402,15 +404,26 @@ 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, int in, int out, int err, DWORD flags)
|
||||
spawn_child(char* cmd, char** argv, int in, int out, int err, DWORD flags)
|
||||
{
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFOW si;
|
||||
BOOL b;
|
||||
char *abs_cmd, *t;
|
||||
wchar_t * cmd_utf16;
|
||||
int add_module_path = 0;
|
||||
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 {
|
||||
@ -424,31 +437,57 @@ spawn_child(char* cmd, int in, int out, int err, DWORD flags)
|
||||
add_module_path = 1;
|
||||
} while (0);
|
||||
|
||||
/* add current module path to start if needed */
|
||||
if (add_module_path) {
|
||||
char* ctr;
|
||||
abs_cmd = malloc(strlen(w32_programdir()) + 1 + strlen(cmd) + 1);
|
||||
if (abs_cmd == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
ctr = abs_cmd;
|
||||
memcpy(ctr, w32_programdir(), strlen(w32_programdir()));
|
||||
ctr += strlen(w32_programdir());
|
||||
*ctr++ = '\\';
|
||||
memcpy(ctr, cmd, strlen(cmd) + 1);
|
||||
} else
|
||||
abs_cmd = cmd;
|
||||
/* 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;
|
||||
|
||||
debug("spawning %s", abs_cmd);
|
||||
|
||||
if ((cmd_utf16 = utf8_to_utf16(abs_cmd)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
if (argv) {
|
||||
t1 = argv;
|
||||
while (*t1)
|
||||
cmdline_len += strlen(*t1++) + 1 + 2;
|
||||
}
|
||||
|
||||
if (abs_cmd != cmd)
|
||||
free(abs_cmd);
|
||||
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);
|
||||
@ -457,22 +496,29 @@ spawn_child(char* cmd, int in, int out, int err, DWORD flags)
|
||||
si.hStdError = w32_fd_to_handle(err);
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
|
||||
b = CreateProcessW(NULL, cmd_utf16, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi);
|
||||
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);
|
||||
pi.dwProcessId = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
CloseHandle(pi.hThread);
|
||||
} else {
|
||||
errno = GetLastError();
|
||||
pi.dwProcessId = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
free(cmd_utf16);
|
||||
return pi.dwProcessId;
|
||||
ret = pi.dwProcessId;
|
||||
cleanup:
|
||||
if (cmdline)
|
||||
free(cmdline);
|
||||
if (cmdline_utf16)
|
||||
free(cmdline_utf16);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
@ -618,13 +664,13 @@ settimes(wchar_t * path, FILETIME *cretime, FILETIME *acttime, FILETIME *modtime
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
/* TODO - convert Win32 error to errno */
|
||||
errno = GetLastError();
|
||||
debug("w32_settimes - CreateFileW ERROR:%d", errno);
|
||||
debug3("w32_settimes - CreateFileW ERROR:%d", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SetFileTime(handle, cretime, acttime, modtime) == 0) {
|
||||
errno = GetLastError();
|
||||
debug("w32_settimes - SetFileTime ERROR:%d", errno);
|
||||
debug3("w32_settimes - SetFileTime ERROR:%d", errno);
|
||||
CloseHandle(handle);
|
||||
return -1;
|
||||
}
|
||||
@ -953,12 +999,12 @@ statvfs(const char *path, struct statvfs *buf)
|
||||
wchar_t* path_utf16 = utf8_to_utf16(sanitized_path(path));
|
||||
if (GetDiskFreeSpaceW(path_utf16, §orsPerCluster, &bytesPerSector,
|
||||
&freeClusters, &totalClusters) == TRUE) {
|
||||
debug3("path : [%s]", path);
|
||||
debug3("sectorsPerCluster : [%lu]", sectorsPerCluster);
|
||||
debug3("bytesPerSector : [%lu]", bytesPerSector);
|
||||
debug3("bytesPerCluster : [%lu]", sectorsPerCluster * bytesPerSector);
|
||||
debug3("freeClusters : [%lu]", freeClusters);
|
||||
debug3("totalClusters : [%lu]", totalClusters);
|
||||
debug5("path : [%s]", path);
|
||||
debug5("sectorsPerCluster : [%lu]", sectorsPerCluster);
|
||||
debug5("bytesPerSector : [%lu]", bytesPerSector);
|
||||
debug5("bytesPerCluster : [%lu]", sectorsPerCluster * bytesPerSector);
|
||||
debug5("freeClusters : [%lu]", freeClusters);
|
||||
debug5("totalClusters : [%lu]", totalClusters);
|
||||
|
||||
buf->f_bsize = sectorsPerCluster * bytesPerSector;
|
||||
buf->f_frsize = sectorsPerCluster * bytesPerSector;
|
||||
@ -975,7 +1021,7 @@ statvfs(const char *path, struct statvfs *buf)
|
||||
free(path_utf16);
|
||||
return 0;
|
||||
} else {
|
||||
debug3("ERROR: Cannot get free space for [%s]. Error code is : %d.\n", path, GetLastError());
|
||||
debug5("ERROR: Cannot get free space for [%s]. Error code is : %d.\n", path, GetLastError());
|
||||
|
||||
free(path_utf16);
|
||||
return -1;
|
||||
@ -996,3 +1042,58 @@ w32_strerror(int errnum)
|
||||
return _sys_errlist_ext[errnum - EADDRINUSE];
|
||||
return strerror(errnum);
|
||||
}
|
||||
/*
|
||||
* Temporary implementation of readpassphrase.
|
||||
* TODO - this needs to be reimplemented as per
|
||||
* https://linux.die.net/man/3/readpassphrase
|
||||
*/
|
||||
char *
|
||||
readpassphrase(const char *prompt, char *out, size_t out_len, int flags) {
|
||||
char *askpass = NULL;
|
||||
char *ret = NULL;
|
||||
|
||||
DWORD mode;
|
||||
size_t len = 0;
|
||||
int retr = 0;
|
||||
|
||||
/* prompt user */
|
||||
wchar_t* wtmp = utf8_to_utf16(prompt);
|
||||
if (wtmp == NULL)
|
||||
fatal("unable to alloc memory");
|
||||
_cputws(wtmp);
|
||||
free(wtmp);
|
||||
|
||||
len = retr = 0;
|
||||
|
||||
while (_kbhit())
|
||||
_getch();
|
||||
|
||||
while (len < out_len) {
|
||||
out[len] = (unsigned char)_getch();
|
||||
|
||||
if (out[len] == '\r') {
|
||||
if (_kbhit()) /* read linefeed if its there */
|
||||
_getch();
|
||||
break;
|
||||
}
|
||||
else if (out[len] == '\n') {
|
||||
break;
|
||||
}
|
||||
else if (out[len] == '\b') { /* backspace */
|
||||
if (len > 0)
|
||||
len--; /* overwrite last character */
|
||||
}
|
||||
else if (out[len] == '\003') {
|
||||
/* exit on Ctrl+C */
|
||||
fatal("");
|
||||
}
|
||||
else {
|
||||
len++; /* keep reading in the loop */
|
||||
}
|
||||
}
|
||||
|
||||
out[len] = '\0'; /* get rid of the cr/lf */
|
||||
_cputs("\n"); /*show a newline as we do not echo password or the line */
|
||||
|
||||
return out;
|
||||
}
|
@ -41,6 +41,7 @@
|
||||
#include "inc\grp.h"
|
||||
#include "inc\utf.h"
|
||||
#include "misc_internal.h"
|
||||
#include "debug.h"
|
||||
|
||||
static struct passwd pw;
|
||||
static char* pw_shellpath = NULL;
|
||||
@ -128,7 +129,7 @@ get_passwd(const char *user_utf8, LPWSTR user_sid)
|
||||
if (user_sid == NULL) {
|
||||
NET_API_STATUS status;
|
||||
if ((status = NetUserGetInfo(udom_utf16, uname_utf16, 23, &user_info)) != NERR_Success) {
|
||||
debug("NetUserGetInfo() failed with error: %d for user: %ls and domain: %ls \n", status, uname_utf16, udom_utf16);
|
||||
debug3("NetUserGetInfo() failed with error: %d for user: %ls and domain: %ls \n", status, uname_utf16, udom_utf16);
|
||||
|
||||
if ((dsStatus = DsGetDcNameW(NULL, udom_utf16, NULL, NULL, DS_DIRECTORY_SERVICE_PREFERRED, &pdc)) != ERROR_SUCCESS) {
|
||||
error("DsGetDcNameW() failed with error: %d \n", dsStatus);
|
||||
@ -137,14 +138,14 @@ get_passwd(const char *user_utf8, LPWSTR user_sid)
|
||||
}
|
||||
|
||||
if ((status = NetUserGetInfo(pdc->DomainControllerName, uname_utf16, 23, &user_info)) != NERR_Success) {
|
||||
debug("NetUserGetInfo() with domainController: %ls failed with error: %d \n", pdc->DomainControllerName, status);
|
||||
debug3("NetUserGetInfo() with domainController: %ls failed with error: %d \n", pdc->DomainControllerName, status);
|
||||
errno = ENOENT;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (ConvertSidToStringSidW(((LPUSER_INFO_23)user_info)->usri23_user_sid, &user_sid_local) == FALSE) {
|
||||
debug("NetUserGetInfo() Succeded but ConvertSidToStringSidW() failed with error: %d\n", GetLastError());
|
||||
debug3("NetUserGetInfo() Succeded but ConvertSidToStringSidW() failed with error: %d\n", GetLastError());
|
||||
errno = ENOENT;
|
||||
goto done;
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "w32fd.h"
|
||||
#include "signal_internal.h"
|
||||
#include "inc\signal.h"
|
||||
#include "debug.h"
|
||||
|
||||
#undef signal
|
||||
#undef raise
|
||||
@ -56,28 +57,28 @@ extern struct _children children;
|
||||
static VOID CALLBACK
|
||||
sigint_APCProc(_In_ ULONG_PTR dwParam)
|
||||
{
|
||||
debug3("SIGINT APCProc()");
|
||||
debug5("SIGINT APCProc()");
|
||||
sigaddset(&pending_signals, W32_SIGINT);
|
||||
}
|
||||
|
||||
static VOID CALLBACK
|
||||
sigterm_APCProc(_In_ ULONG_PTR dwParam)
|
||||
{
|
||||
debug3("SIGTERM APCProc()");
|
||||
debug5("SIGTERM APCProc()");
|
||||
sigaddset(&pending_signals, W32_SIGTERM);
|
||||
}
|
||||
|
||||
static VOID CALLBACK
|
||||
sigtstp_APCProc(_In_ ULONG_PTR dwParam)
|
||||
{
|
||||
debug3("SIGTSTP APCProc()");
|
||||
debug5("SIGTSTP APCProc()");
|
||||
sigaddset(&pending_signals, W32_SIGTSTP);
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
native_sig_handler(DWORD dwCtrlType)
|
||||
{
|
||||
debug("Native Ctrl+C handler, CtrlType %d", dwCtrlType);
|
||||
debug3("Native Ctrl+C handler, CtrlType %d", dwCtrlType);
|
||||
switch (dwCtrlType) {
|
||||
case CTRL_C_EVENT:
|
||||
QueueUserAPC(sigint_APCProc, main_thread, (ULONG_PTR)NULL);
|
||||
@ -100,7 +101,7 @@ native_sig_handler(DWORD dwCtrlType)
|
||||
static VOID CALLBACK
|
||||
sigwinch_APCProc(_In_ ULONG_PTR dwParam)
|
||||
{
|
||||
debug3("SIGTERM APCProc()");
|
||||
debug5("SIGTERM APCProc()");
|
||||
sigaddset(&pending_signals, W32_SIGWINCH);
|
||||
}
|
||||
|
||||
@ -128,7 +129,7 @@ sighandler_t
|
||||
w32_signal(int signum, sighandler_t handler)
|
||||
{
|
||||
sighandler_t prev;
|
||||
debug2("signal() sig:%d, handler:%p", signum, handler);
|
||||
debug4("signal() sig:%d, handler:%p", signum, handler);
|
||||
if (signum >= W32_SIGMAX) {
|
||||
errno = EINVAL;
|
||||
return W32_SIG_ERR;
|
||||
@ -144,7 +145,7 @@ w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
|
||||
{
|
||||
/* this is only used by sshd to block SIGCHLD while doing waitpid() */
|
||||
/* our implementation of waidpid() is never interrupted, so no need to implement this for now*/
|
||||
debug3("sigprocmask() how:%d");
|
||||
debug5("sigprocmask() how:%d");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -153,7 +154,7 @@ w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
|
||||
int
|
||||
w32_raise(int sig)
|
||||
{
|
||||
debug("raise sig:%d", sig);
|
||||
debug3("raise sig:%d", sig);
|
||||
if (sig == W32_SIGSEGV)
|
||||
return raise(SIGSEGV); /* raise native exception handler*/
|
||||
|
||||
@ -191,7 +192,7 @@ sw_process_pending_signals()
|
||||
sigset_t pending_tmp = pending_signals;
|
||||
BOOL sig_int = FALSE; /* has any signal actually interrupted */
|
||||
|
||||
debug3("process_signals()");
|
||||
debug5("process_signals()");
|
||||
int i, exp[] = { W32_SIGCHLD , W32_SIGINT , W32_SIGALRM, W32_SIGTERM, W32_SIGTSTP, W32_SIGWINCH };
|
||||
|
||||
/* check for expected signals*/
|
||||
@ -199,7 +200,7 @@ sw_process_pending_signals()
|
||||
sigdelset(&pending_tmp, exp[i]);
|
||||
if (pending_tmp) {
|
||||
/* unexpected signals queued up */
|
||||
debug("process_signals() - ERROR unexpected signals in queue: %d", pending_tmp);
|
||||
debug3("process_signals() - ERROR unexpected signals in queue: %d", pending_tmp);
|
||||
errno = ENOTSUP;
|
||||
DebugBreak();
|
||||
return -1;
|
||||
@ -228,7 +229,7 @@ sw_process_pending_signals()
|
||||
DebugBreak();
|
||||
|
||||
if (sig_int) {
|
||||
debug("process_queued_signals: WARNING - A signal has interrupted and was processed");
|
||||
debug3("process_queued_signals: WARNING - A signal has interrupted and was processed");
|
||||
errno = EINTR;
|
||||
return -1;
|
||||
}
|
||||
@ -257,7 +258,7 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
|
||||
num_all_events = num_events + live_children;
|
||||
|
||||
if (num_all_events > MAXIMUM_WAIT_OBJECTS) {
|
||||
debug("wait() - ERROR max events reached");
|
||||
debug3("wait() - ERROR max events reached");
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
@ -265,7 +266,7 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
|
||||
memcpy(all_events, children.handles, live_children * sizeof(HANDLE));
|
||||
memcpy(all_events + live_children, events, num_events * sizeof(HANDLE));
|
||||
|
||||
debug3("wait() on %d events and %d children", num_events, live_children);
|
||||
debug5("wait() on %d events and %d children", num_events, live_children);
|
||||
/* TODO - implement signal catching and handling */
|
||||
if (num_all_events) {
|
||||
DWORD ret = WaitForMultipleObjectsEx(num_all_events, all_events, FALSE, milli_seconds, TRUE);
|
||||
@ -284,7 +285,7 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
|
||||
return 0;
|
||||
} else { /* some other error*/
|
||||
errno = EOTHER;
|
||||
debug("ERROR: unxpected wait end: %d", ret);
|
||||
debug3("ERROR: unxpected wait end: %d", ret);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
@ -296,7 +297,7 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
|
||||
return 0;
|
||||
} else { /* some other error */
|
||||
errno = EOTHER;
|
||||
debug("ERROR: unxpected SleepEx error: %d", ret);
|
||||
debug3("ERROR: unxpected SleepEx error: %d", ret);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include "signal_internal.h"
|
||||
#include "inc\signal.h"
|
||||
#include "debug.h"
|
||||
|
||||
struct _timer_info timer_info;
|
||||
extern sigset_t pending_signals;
|
||||
@ -49,7 +50,7 @@ w32_alarm(unsigned int sec)
|
||||
ULONGLONG sec_passed;
|
||||
int ret = 0;
|
||||
|
||||
debug3("alarm() %d secs", sec);
|
||||
debug5("alarm() %d secs", sec);
|
||||
errno = 0;
|
||||
/* cancel any live timer if seconds is 0*/
|
||||
if (sec == 0) {
|
||||
@ -63,7 +64,7 @@ w32_alarm(unsigned int sec)
|
||||
due.QuadPart *= sec;
|
||||
/* this call resets the timer if it is already active */
|
||||
if (!SetWaitableTimer(timer_info.timer, &due, 0, sigalrm_APC, NULL, FALSE)) {
|
||||
debug("alram() - ERROR SetWaitableTimer() %d", GetLastError());
|
||||
debug3("alram() - ERROR SetWaitableTimer() %d", GetLastError());
|
||||
return 0;;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include "signal_internal.h"
|
||||
#include "inc\sys\wait.h"
|
||||
#include "debug.h"
|
||||
|
||||
struct _children children;
|
||||
|
||||
@ -38,7 +39,7 @@ register_child(HANDLE child, DWORD pid)
|
||||
{
|
||||
DWORD first_zombie_index;
|
||||
|
||||
debug("Register child %p pid %d, %d zombies of %d", child, pid,
|
||||
debug3("Register child %p pid %d, %d zombies of %d", child, pid,
|
||||
children.num_zombies, children.num_children);
|
||||
if (children.num_children == MAX_CHILDREN) {
|
||||
errno = ENOMEM;
|
||||
@ -65,7 +66,7 @@ int
|
||||
sw_remove_child_at_index(DWORD index)
|
||||
{
|
||||
DWORD last_non_zombie;
|
||||
debug("Unregister child at index %d, %d zombies of %d", index,
|
||||
debug3("Unregister child at index %d, %d zombies of %d", index,
|
||||
children.num_zombies, children.num_children);
|
||||
|
||||
if ((index >= children.num_children) || (children.num_children == 0)) {
|
||||
@ -103,7 +104,7 @@ sw_child_to_zombie(DWORD index)
|
||||
DWORD last_non_zombie, zombie_pid;
|
||||
HANDLE zombie_handle;
|
||||
|
||||
debug("zombie'ing child at index %d, %d zombies of %d", index,
|
||||
debug3("zombie'ing child at index %d, %d zombies of %d", index,
|
||||
children.num_zombies, children.num_children);
|
||||
|
||||
if (index >= children.num_children) {
|
||||
@ -152,7 +153,7 @@ waitpid(int pid, int *status, int options)
|
||||
DWORD index, ret, ret_id, exit_code, timeout = 0;
|
||||
HANDLE process = NULL;
|
||||
|
||||
debug3("waitpid - pid:%d, options:%d", pid, options);
|
||||
debug5("waitpid - pid:%d, options:%d", pid, options);
|
||||
if (options & (~WNOHANG)) {
|
||||
errno = ENOTSUP;
|
||||
DebugBreak();
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <stddef.h>
|
||||
#include "w32fd.h"
|
||||
#include "inc\utf.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define INTERNAL_SEND_BUFFER_SIZE 70*1024 //70KB
|
||||
#define INTERNAL_RECV_BUFFER_SIZE 70*1024 //70KB
|
||||
@ -103,7 +104,7 @@ int
|
||||
socketio_acceptEx(struct w32_io* pio)
|
||||
{
|
||||
struct acceptEx_context *context;
|
||||
debug3("acceptEx - io:%p", pio);
|
||||
debug5("acceptEx - io:%p", pio);
|
||||
context = (struct acceptEx_context *)pio->internal.context;
|
||||
ResetEvent(pio->read_overlapped.hEvent);
|
||||
|
||||
@ -111,7 +112,7 @@ socketio_acceptEx(struct w32_io* pio)
|
||||
context->accept_socket = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (context->accept_socket == INVALID_SOCKET) {
|
||||
errno = errno_from_WSALastError();
|
||||
debug("acceptEx - socket() ERROR:%d, io:%p", errno, pio);
|
||||
debug3("acceptEx - socket() ERROR:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -130,7 +131,7 @@ socketio_acceptEx(struct w32_io* pio)
|
||||
/* if overlapped io is in progress, we are good */
|
||||
if (WSAGetLastError() != ERROR_IO_PENDING) {
|
||||
errno = errno_from_WSALastError();
|
||||
debug("acceptEx - AcceptEx() ERROR:%d, io:%p", errno, pio);
|
||||
debug3("acceptEx - AcceptEx() ERROR:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -147,7 +148,7 @@ CALLBACK WSARecvCompletionRoutine(IN DWORD dwError,
|
||||
{
|
||||
struct w32_io* pio =
|
||||
(struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, read_overlapped));
|
||||
debug2("WSARecvCompletionCB - io:%p, pending_state:%d, flags:%d, error:%d, received:%d",
|
||||
debug4("WSARecvCompletionCB - io:%p, pending_state:%d, flags:%d, error:%d, received:%d",
|
||||
pio, pio->read_details.pending, dwFlags, dwError, cbTransferred);
|
||||
if (!dwError && !cbTransferred)
|
||||
dwError = ERROR_GRACEFUL_DISCONNECT;
|
||||
@ -166,7 +167,7 @@ socketio_WSARecv(struct w32_io* pio, BOOL* completed)
|
||||
WSABUF wsabuf;
|
||||
DWORD recv_flags = 0;
|
||||
|
||||
debug3("WSARecv - pio: %p", pio);
|
||||
debug5("WSARecv - pio: %p", pio);
|
||||
if (completed)
|
||||
*completed = FALSE;
|
||||
|
||||
@ -176,7 +177,7 @@ socketio_WSARecv(struct w32_io* pio, BOOL* completed)
|
||||
wsabuf.buf = malloc(wsabuf.len);
|
||||
if (!wsabuf.buf) {
|
||||
errno = ENOMEM;
|
||||
debug("WSARecv - ERROR:%d, io:%p", errno, pio);
|
||||
debug3("WSARecv - ERROR:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -189,17 +190,17 @@ socketio_WSARecv(struct w32_io* pio, BOOL* completed)
|
||||
if (ret == 0) {
|
||||
pio->read_details.pending = TRUE;
|
||||
/* receive has completed but APC is pending to be scheduled */
|
||||
debug2("WSARecv - WSARecv() returned 0, io:%p", pio);
|
||||
debug4("WSARecv - WSARecv() returned 0, io:%p", pio);
|
||||
if (completed)
|
||||
*completed = TRUE;
|
||||
} else { /* (ret == SOCKET_ERROR) */
|
||||
if (WSAGetLastError() == WSA_IO_PENDING) {
|
||||
/* io is initiated and pending */
|
||||
debug2("WSARecv - reported IO pending");
|
||||
debug4("WSARecv - reported IO pending");
|
||||
pio->read_details.pending = TRUE;
|
||||
} else {
|
||||
errno = errno_from_WSALastError();
|
||||
debug("WSARecv - WSARecv() ERROR: io:%p %d", pio, errno);
|
||||
debug3("WSARecv - WSARecv() ERROR: io:%p %d", pio, errno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -214,7 +215,7 @@ socketio_socket(int domain, int type, int protocol)
|
||||
struct w32_io *pio = (struct w32_io*)malloc(sizeof(struct w32_io));
|
||||
if (!pio) {
|
||||
errno = ENOMEM;
|
||||
debug("socket - ERROR:%d, io:%p", errno, pio);
|
||||
debug3("socket - ERROR:%d, io:%p", errno, pio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -223,7 +224,7 @@ socketio_socket(int domain, int type, int protocol)
|
||||
if (pio->sock == INVALID_SOCKET) {
|
||||
errno = errno_from_WSALastError();
|
||||
free(pio);
|
||||
debug("socket - socket() ERROR:%d, io:%p", errno, pio);
|
||||
debug3("socket - socket() ERROR:%d, io:%p", errno, pio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -235,7 +236,7 @@ socketio_socket(int domain, int type, int protocol)
|
||||
int ret = (expr); \
|
||||
if (ret == SOCKET_ERROR) { \
|
||||
errno = errno_from_WSALastError(); \
|
||||
debug("%s - ERROR:%d", __FUNCTION__, errno); \
|
||||
debug3("%s - ERROR:%d", __FUNCTION__, errno); \
|
||||
} \
|
||||
return ret; \
|
||||
} while (0)
|
||||
@ -248,7 +249,7 @@ socketio_setsockopt(struct w32_io* pio, int level, int optname, const char* optv
|
||||
(optname == TCP_NODELAY) || (optname == IPV6_V6ONLY))
|
||||
SET_ERRNO_ON_ERROR(setsockopt(pio->sock, level, optname, optval, optlen));
|
||||
else {
|
||||
debug("setsockop - ERROR: unsupported optname:%d io:%p", optname, pio);
|
||||
debug3("setsockop - ERROR: unsupported optname:%d io:%p", optname, pio);
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
@ -283,7 +284,7 @@ socketio_listen(struct w32_io* pio, int backlog)
|
||||
|
||||
if (SOCKET_ERROR == listen(pio->sock, backlog)) {
|
||||
errno = errno_from_WSALastError();
|
||||
debug("listen - listen() ERROR:%d io:%p", errno, pio);
|
||||
debug3("listen - listen() ERROR:%d io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -296,7 +297,7 @@ socketio_listen(struct w32_io* pio, int backlog)
|
||||
context = (struct acceptEx_context*)malloc(sizeof(struct acceptEx_context));
|
||||
if (context == NULL) {
|
||||
errno = ENOMEM;
|
||||
debug("listen - ERROR:%d, io:%p", errno, pio);
|
||||
debug3("listen - ERROR:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
memset(context, 0, sizeof(struct acceptEx_context));
|
||||
@ -307,7 +308,7 @@ socketio_listen(struct w32_io* pio, int backlog)
|
||||
&dwBytes, NULL, NULL)) {
|
||||
free(context);
|
||||
errno = errno_from_WSALastError();
|
||||
debug("listen - Ioctl1 ERROR:%d, io:%p", errno, pio);
|
||||
debug3("listen - Ioctl1 ERROR:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -318,7 +319,7 @@ socketio_listen(struct w32_io* pio, int backlog)
|
||||
&dwBytes, NULL, NULL)) {
|
||||
free(context);
|
||||
errno = errno_from_WSALastError();
|
||||
debug("listen - Ioctl2 ERROR:%d, io:%p", errno, pio);
|
||||
debug3("listen - Ioctl2 ERROR:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -326,7 +327,7 @@ socketio_listen(struct w32_io* pio, int backlog)
|
||||
if ((pio->read_overlapped.hEvent) == NULL) {
|
||||
free(context);
|
||||
errno = ENOMEM;
|
||||
debug("listen - CreateEvent() ERROR:%d, io:%p", errno, pio);
|
||||
debug3("listen - CreateEvent() ERROR:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -350,16 +351,16 @@ int
|
||||
socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
|
||||
{
|
||||
BOOL completed = FALSE;
|
||||
debug3("recv - io:%p", pio);
|
||||
debug5("recv - io:%p", pio);
|
||||
if ((buf == NULL) || (len == 0)) {
|
||||
errno = EINVAL;
|
||||
debug("recv - ERROR: invalid arguments, buf:%p, len:%d, io:%p", buf, len, pio);
|
||||
debug3("recv - ERROR: invalid arguments, buf:%p, len:%d, io:%p", buf, len, pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags != 0) {
|
||||
errno = ENOTSUP;
|
||||
debug("recv - ERROR: flags are not currently supported, io:%p", pio);
|
||||
debug3("recv - ERROR: flags are not currently supported, io:%p", pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -368,14 +369,14 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
|
||||
if (pio->read_details.pending) {
|
||||
/* if recv is now in blocking mode, wait for data to be available */
|
||||
if (w32_io_is_blocking(pio)) {
|
||||
debug2("recv - io is pending, call is blocking, io:%p", pio);
|
||||
debug4("recv - io is pending, call is blocking, io:%p", pio);
|
||||
while (socketio_is_io_available(pio, TRUE) == FALSE) {
|
||||
if (0 != wait_for_any_event(NULL, 0, INFINITE))
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
errno = EAGAIN;
|
||||
debug2("recv - io is already pending, io:%p", pio);
|
||||
debug4("recv - io is already pending, io:%p", pio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -387,7 +388,7 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
|
||||
num_bytes_copied);
|
||||
pio->read_details.remaining -= num_bytes_copied;
|
||||
pio->read_details.completed += num_bytes_copied;
|
||||
debug2("recv - returning %d bytes from prior completed IO, remaining:%d, io:%p",
|
||||
debug4("recv - returning %d bytes from prior completed IO, remaining:%d, io:%p",
|
||||
num_bytes_copied, pio->read_details.remaining, pio);
|
||||
return num_bytes_copied;
|
||||
}
|
||||
@ -395,12 +396,12 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
|
||||
/* if there was an error on async call, return */
|
||||
if (pio->read_details.error) {
|
||||
if (pio->read_details.error == ERROR_GRACEFUL_DISCONNECT) {
|
||||
debug2("recv - connection closed, io:%p", pio);
|
||||
debug4("recv - connection closed, io:%p", pio);
|
||||
/* connection is closed */
|
||||
return 0;
|
||||
} else {
|
||||
errno = errno_from_WSAError(pio->read_details.error);
|
||||
debug("recv - from CB ERROR:%d, io:%p", pio->read_details.error, pio);
|
||||
debug3("recv - from CB ERROR:%d, io:%p", pio->read_details.error, pio);
|
||||
pio->read_details.error = 0;
|
||||
return -1;
|
||||
}
|
||||
@ -411,19 +412,19 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
|
||||
|
||||
if (completed) {
|
||||
/* Let APC be scheduled */
|
||||
debug2("recv - Letting APC to execute, io:%p", pio);
|
||||
debug4("recv - Letting APC to execute, io:%p", pio);
|
||||
SleepEx(0, TRUE);
|
||||
if (pio->read_details.pending) {
|
||||
/* this shouldn't be happening */
|
||||
errno = EOTHER;
|
||||
debug("recv - ERROR: Unexpected IO state, io:%p", pio);
|
||||
debug3("recv - ERROR: Unexpected IO state, io:%p", pio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (w32_io_is_blocking(pio)) {
|
||||
/* wait until io is done */
|
||||
debug3("recv - socket in blocking mode, io:%p", pio);
|
||||
debug5("recv - socket in blocking mode, io:%p", pio);
|
||||
while (socketio_is_io_available(pio, TRUE) == FALSE) {
|
||||
if (0 != wait_for_any_event(NULL, 0, INFINITE))
|
||||
return -1;
|
||||
@ -431,7 +432,7 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
|
||||
} else {
|
||||
if (socketio_is_io_available(pio, TRUE) == FALSE) {
|
||||
errno = EAGAIN;
|
||||
debug2("recv - IO is pending, io:%p", pio);
|
||||
debug4("recv - IO is pending, io:%p", pio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -443,12 +444,12 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
|
||||
if (pio->read_details.error) {
|
||||
if (pio->read_details.error == ERROR_GRACEFUL_DISCONNECT) {
|
||||
/* connection is closed */
|
||||
debug2("recv - connection closed(2), io:%p", pio);
|
||||
debug4("recv - connection closed(2), io:%p", pio);
|
||||
return 0;
|
||||
} else {
|
||||
errno = errno_from_WSAError(pio->read_details.error);
|
||||
pio->read_details.error = 0;
|
||||
debug("recv - from CB(2) ERROR:%d, io:%p", errno, pio);
|
||||
debug3("recv - from CB(2) ERROR:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -458,13 +459,13 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
|
||||
memcpy(buf, pio->read_details.buf, num_bytes_copied);
|
||||
pio->read_details.remaining -= num_bytes_copied;
|
||||
pio->read_details.completed = num_bytes_copied;
|
||||
debug2("recv - (2) returning %d bytes from completed IO, remaining:%d, io:%p",
|
||||
debug4("recv - (2) returning %d bytes from completed IO, remaining:%d, io:%p",
|
||||
num_bytes_copied, pio->read_details.remaining, pio);
|
||||
return num_bytes_copied;
|
||||
} else {
|
||||
/* this should not happen */
|
||||
errno = EOTHER;
|
||||
debug("recv - (2) ERROR:Unexpected IO state, io:%p", pio);
|
||||
debug3("recv - (2) ERROR:Unexpected IO state, io:%p", pio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -476,13 +477,13 @@ CALLBACK WSASendCompletionRoutine(IN DWORD dwError,
|
||||
IN DWORD dwFlags)
|
||||
{
|
||||
struct w32_io* pio = (struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, write_overlapped));
|
||||
debug2("WSASendCB - io:%p, pending_state:%d, error:%d, sent:%d of remaining:%d",
|
||||
debug4("WSASendCB - io:%p, pending_state:%d, error:%d, sent:%d of remaining:%d",
|
||||
pio, pio->write_details.pending, dwError, cbTransferred,
|
||||
pio->write_details.remaining);
|
||||
pio->write_details.error = dwError;
|
||||
/* TODO - assert that remaining == cbTransferred */
|
||||
if ((dwError == 0) && (pio->write_details.remaining != cbTransferred)) {
|
||||
debug("WSASendCB - ERROR: broken assumption, io:%p, sent:%d, remaining:%d", pio,
|
||||
debug3("WSASendCB - ERROR: broken assumption, io:%p, sent:%d, remaining:%d", pio,
|
||||
cbTransferred, pio->write_details.remaining);
|
||||
DebugBreak();
|
||||
}
|
||||
@ -497,16 +498,16 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags)
|
||||
int ret = 0;
|
||||
WSABUF wsabuf;
|
||||
|
||||
debug2("send - io:%p", pio);
|
||||
debug4("send - io:%p", pio);
|
||||
if ((buf == NULL) || (len == 0)) {
|
||||
errno = EINVAL;
|
||||
debug("send - ERROR invalid arguments, buf:%p, len:%d, io:%p", buf, len, pio);
|
||||
debug3("send - ERROR invalid arguments, buf:%p, len:%d, io:%p", buf, len, pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags != 0) {
|
||||
errno = ENOTSUP;
|
||||
debug("send - ERROR: flags are not currently supported, io:%p", pio);
|
||||
debug3("send - ERROR: flags are not currently supported, io:%p", pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -514,20 +515,20 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags)
|
||||
/* if io is already pending */
|
||||
if (pio->write_details.pending) {
|
||||
if (w32_io_is_blocking(pio)) {
|
||||
debug2("send - io is pending, call is blocking, io:%p", pio);
|
||||
debug4("send - io is pending, call is blocking, io:%p", pio);
|
||||
while (pio->write_details.pending)
|
||||
if (wait_for_any_event(NULL, 0, INFINITE) == -1)
|
||||
return -1;
|
||||
} else {
|
||||
errno = EAGAIN;
|
||||
debug2("send - IO currently pending, EAGAIN, io:%p", pio);
|
||||
debug4("send - IO currently pending, EAGAIN, io:%p", pio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (pio->write_details.error) {
|
||||
errno = errno_from_WSAError(pio->write_details.error);
|
||||
debug("ERROR:%d, io:%p", errno, pio);
|
||||
debug3("ERROR:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -537,7 +538,7 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags)
|
||||
wsabuf.buf = malloc(wsabuf.len);
|
||||
if (!wsabuf.buf) {
|
||||
errno = ENOMEM;
|
||||
debug("send - ERROR:%d, io:%p", errno, pio);
|
||||
debug3("send - ERROR:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -554,13 +555,13 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags)
|
||||
|
||||
if (ret == 0) {
|
||||
/* send has completed and APC is scheduled, let it run */
|
||||
debug2("send - WSASend() returned 0, APC scheduled io:%p", pio);
|
||||
debug4("send - WSASend() returned 0, APC scheduled io:%p", pio);
|
||||
pio->write_details.pending = TRUE;
|
||||
pio->write_details.remaining = wsabuf.len;
|
||||
SleepEx(0, TRUE);
|
||||
if ((pio->write_details.pending) || (pio->write_details.remaining != 0)) {
|
||||
errno = EOTHER;
|
||||
debug("send - ERROR: Unexpected IO state, io:%p", pio);
|
||||
debug3("send - ERROR: Unexpected IO state, io:%p", pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -569,12 +570,12 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags)
|
||||
} else {
|
||||
if (WSAGetLastError() == WSA_IO_PENDING) {
|
||||
/* io is initiated and pending */
|
||||
debug2("send - WSASend reported IO pending, io:%p", pio);
|
||||
debug4("send - WSASend reported IO pending, io:%p", pio);
|
||||
pio->write_details.pending = TRUE;
|
||||
pio->write_details.remaining = wsabuf.len;
|
||||
if (w32_io_is_blocking(pio)) {
|
||||
/* wait until io is done */
|
||||
debug3("send - waiting as socket is in blocking mode, io:%p", pio);
|
||||
debug5("send - waiting as socket is in blocking mode, io:%p", pio);
|
||||
while (pio->write_details.pending)
|
||||
if (wait_for_any_event(NULL, 0, INFINITE) == -1) {
|
||||
/* if interrupted but send has completed, we are good*/
|
||||
@ -584,11 +585,11 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
debug3("send - returning %d, io:%p", wsabuf.len, pio);
|
||||
debug5("send - returning %d, io:%p", wsabuf.len, pio);
|
||||
return wsabuf.len;
|
||||
} else {
|
||||
errno = errno_from_WSALastError();
|
||||
debug("send - WSASend() ERROR:%d, io:%p", errno, pio);
|
||||
debug3("send - WSASend() ERROR:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -605,13 +606,13 @@ socketio_shutdown(struct w32_io* pio, int how)
|
||||
int
|
||||
socketio_close(struct w32_io* pio)
|
||||
{
|
||||
debug2("close - io:%p", pio);
|
||||
debug4("close - io:%p", pio);
|
||||
closesocket(pio->sock);
|
||||
/* wait for pending io to abort */
|
||||
SleepEx(0, TRUE);
|
||||
if (((pio->internal.state == SOCK_CONNECTED) || (pio->internal.state == SOCK_ACCEPTED)) &&
|
||||
(pio->read_details.pending || pio->write_details.pending)) {
|
||||
debug2("close - IO is still pending on closed socket. read:%d, write:%d, io:%p",
|
||||
debug4("close - IO is still pending on closed socket. read:%d, write:%d, io:%p",
|
||||
pio->read_details.pending, pio->write_details.pending, pio);
|
||||
DebugBreak();
|
||||
}
|
||||
@ -649,7 +650,7 @@ socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen)
|
||||
struct sockaddr *local_address, *remote_address;
|
||||
int local_address_len, remote_address_len;
|
||||
|
||||
debug3("accept - io:%p", pio);
|
||||
debug5("accept - io:%p", pio);
|
||||
/* start io if not already started */
|
||||
if (pio->read_details.pending == FALSE) {
|
||||
if (socketio_acceptEx(pio) != 0)
|
||||
@ -666,7 +667,7 @@ socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen)
|
||||
/* if i/o is not ready */
|
||||
if (FALSE == socketio_is_io_available(pio, TRUE)) {
|
||||
errno = EAGAIN;
|
||||
debug2("accept is pending, io:%p", pio);
|
||||
debug4("accept is pending, io:%p", pio);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -677,21 +678,21 @@ socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen)
|
||||
|
||||
if (pio->read_details.error) {
|
||||
errno = errno_from_WSAError(pio->read_details.error);
|
||||
debug("accept - ERROR: async io completed with error: %d, io:%p", errno, pio);
|
||||
debug3("accept - ERROR: async io completed with error: %d, io:%p", errno, pio);
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
if (0 != setsockopt(context->accept_socket, SOL_SOCKET,
|
||||
SO_UPDATE_ACCEPT_CONTEXT, (char*)&pio->sock, sizeof(pio->sock))) {
|
||||
errno = errno_from_WSALastError();
|
||||
debug("accept - ERROR: setsockopt failed:%d, io:%p", errno, pio);
|
||||
debug3("accept - ERROR: setsockopt failed:%d, io:%p", errno, pio);
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
accept_io = (struct w32_io*)malloc(sizeof(struct w32_io));
|
||||
if (!accept_io) {
|
||||
errno = ENOMEM;
|
||||
debug("accept - ERROR:%d, io:%p", errno, pio);
|
||||
debug3("accept - ERROR:%d, io:%p", errno, pio);
|
||||
goto on_error;
|
||||
}
|
||||
memset(accept_io, 0, sizeof(struct w32_io));
|
||||
@ -699,7 +700,7 @@ socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen)
|
||||
accept_io->sock = context->accept_socket;
|
||||
accept_io->internal.state = SOCK_ACCEPTED;
|
||||
context->accept_socket = INVALID_SOCKET;
|
||||
debug2("accept io:%p", accept_io);
|
||||
debug4("accept io:%p", accept_io);
|
||||
|
||||
if ((addr != NULL) && (addrlen != NULL)) {
|
||||
context->lpfnGuidGetAcceptExSockaddrs(context->lpOutputBuf, 0,
|
||||
@ -735,7 +736,7 @@ socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen)
|
||||
GUID connectex_guid = WSAID_CONNECTEX;
|
||||
LPFN_CONNECTEX ConnectEx;
|
||||
|
||||
debug3("connectex - io:%p", pio);
|
||||
debug5("connectex - io:%p", pio);
|
||||
if (name->sa_family == AF_INET6) {
|
||||
ZeroMemory(&tmp_addr6, sizeof(tmp_addr6));
|
||||
tmp_addr6.sin6_family = AF_INET6;
|
||||
@ -750,13 +751,13 @@ socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen)
|
||||
tmp_addr_len = sizeof(tmp_addr4);
|
||||
} else {
|
||||
errno = ENOTSUP;
|
||||
debug("connectex - ERROR: unsuppored address family:%d, io:%p", name->sa_family, pio);
|
||||
debug3("connectex - ERROR: unsuppored address family:%d, io:%p", name->sa_family, pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SOCKET_ERROR == bind(pio->sock, tmp_addr, (int)tmp_addr_len)) {
|
||||
errno = errno_from_WSALastError();
|
||||
debug("connectex - ERROR: bind failed :%d, io:%p", WSAGetLastError(), pio);
|
||||
debug3("connectex - ERROR: bind failed :%d, io:%p", WSAGetLastError(), pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -765,14 +766,14 @@ socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen)
|
||||
&ConnectEx, sizeof(ConnectEx),
|
||||
&tmp_bytes, NULL, NULL)) {
|
||||
errno = errno_from_WSALastError();
|
||||
debug("connectex - ioctl ERROR:%d, io:%p", WSAGetLastError(), pio);
|
||||
debug3("connectex - ioctl ERROR:%d, io:%p", WSAGetLastError(), pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((!pio->write_overlapped.hEvent)
|
||||
&& ((pio->write_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)) {
|
||||
errno = ENOMEM;
|
||||
debug("connectex - ERROR CreateEvent failed:%d, io:%p", errno, pio);
|
||||
debug3("connectex - ERROR CreateEvent failed:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -786,7 +787,7 @@ socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen)
|
||||
CloseHandle(pio->write_overlapped.hEvent);
|
||||
pio->write_overlapped.hEvent = 0;
|
||||
errno = errno_from_WSALastError();
|
||||
debug("connectex - ERROR ConnectEx() :%d, io:%p", errno, pio);
|
||||
debug3("connectex - ERROR ConnectEx() :%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -801,7 +802,7 @@ int
|
||||
socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namelen)
|
||||
{
|
||||
|
||||
debug3("connect - io:%p", pio);
|
||||
debug5("connect - io:%p", pio);
|
||||
if (pio->write_details.pending == FALSE) {
|
||||
if (-1 == socketio_connectex(pio, name, namelen))
|
||||
return -1;
|
||||
@ -817,7 +818,7 @@ socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namelen)
|
||||
/* if i/o is not ready */
|
||||
if (FALSE == socketio_is_io_available(pio, TRUE)) {
|
||||
errno = EINPROGRESS;
|
||||
debug2("connect - in progress, io:%p", pio);
|
||||
debug4("connect - in progress, io:%p", pio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -828,16 +829,16 @@ socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namelen)
|
||||
int
|
||||
socketio_finish_connect(struct w32_io* pio)
|
||||
{
|
||||
debug3("finish_connect, io:%p", pio);
|
||||
debug5("finish_connect, io:%p", pio);
|
||||
if (pio->write_details.error) {
|
||||
errno = errno_from_WSAError(pio->write_details.error);
|
||||
debug("finish_connect - ERROR: async io completed with error: %d, io:%p", errno, pio);
|
||||
debug3("finish_connect - ERROR: async io completed with error: %d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 != setsockopt(pio->sock, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0)) {
|
||||
errno = errno_from_WSALastError();
|
||||
debug("finish_connect - ERROR: setsockopt failed:%d, io:%p", errno, pio);
|
||||
debug3("finish_connect - ERROR: setsockopt failed:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -896,7 +897,7 @@ void
|
||||
socketio_on_select(struct w32_io* pio, BOOL rd)
|
||||
{
|
||||
enum w32_io_sock_state sock_state = pio->internal.state;
|
||||
debug2("on_select - io:%p type:%d rd:%d", pio, pio->type, rd);
|
||||
debug4("on_select - io:%p type:%d rd:%d", pio, pio->type, rd);
|
||||
|
||||
/* nothing to do for writes (that includes connect) */
|
||||
if (!rd)
|
||||
|
@ -63,6 +63,12 @@ mm_is_monitor(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mm_user_key_allowed(struct passwd *pw, Key *k, int i)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kexgex_server(struct ssh * sh) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "w32fd.h"
|
||||
#include "tncon.h"
|
||||
#include "inc\utf.h"
|
||||
#include "debug.h"
|
||||
#include "tnnet.h"
|
||||
|
||||
#define TERM_IO_BUF_SIZE 2048
|
||||
@ -57,7 +58,7 @@ static VOID CALLBACK
|
||||
ReadAPCProc(_In_ ULONG_PTR dwParam)
|
||||
{
|
||||
struct w32_io* pio = (struct w32_io*)dwParam;
|
||||
debug3("TermRead CB - io:%p, bytes: %d, pending: %d, error: %d", pio, read_status.transferred,
|
||||
debug5("TermRead CB - io:%p, bytes: %d, pending: %d, error: %d", pio, read_status.transferred,
|
||||
pio->read_details.pending, read_status.error);
|
||||
pio->read_details.error = read_status.error;
|
||||
pio->read_details.remaining = read_status.transferred;
|
||||
@ -75,7 +76,7 @@ ReadConsoleThread(_In_ LPVOID lpParameter)
|
||||
int nBytesReturned = 0;
|
||||
struct w32_io* pio = (struct w32_io*)lpParameter;
|
||||
|
||||
debug3("TermRead thread, io:%p", pio);
|
||||
debug5("TermRead thread, io:%p", pio);
|
||||
memset(&read_status, 0, sizeof(read_status));
|
||||
while (nBytesReturned == 0) {
|
||||
nBytesReturned = ReadConsoleForTermEmul(WINHANDLE(pio),
|
||||
@ -83,7 +84,7 @@ ReadConsoleThread(_In_ LPVOID lpParameter)
|
||||
}
|
||||
read_status.transferred = nBytesReturned;
|
||||
if (0 == QueueUserAPC(ReadAPCProc, main_thread, (ULONG_PTR)pio)) {
|
||||
debug("TermRead thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio);
|
||||
debug3("TermRead thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio);
|
||||
pio->read_details.pending = FALSE;
|
||||
pio->read_details.error = GetLastError();
|
||||
DebugBreak();
|
||||
@ -98,7 +99,7 @@ termio_initiate_read(struct w32_io* pio)
|
||||
{
|
||||
HANDLE read_thread;
|
||||
|
||||
debug3("TermRead initiate io:%p", pio);
|
||||
debug5("TermRead initiate 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) {
|
||||
@ -111,7 +112,7 @@ termio_initiate_read(struct w32_io* pio)
|
||||
read_thread = CreateThread(NULL, 0, ReadConsoleThread, pio, 0, NULL);
|
||||
if (read_thread == NULL) {
|
||||
errno = errno_from_Win32Error(GetLastError());
|
||||
debug("TermRead initiate - ERROR CreateThread %d, io:%p", GetLastError(), pio);
|
||||
debug3("TermRead initiate - ERROR CreateThread %d, io:%p", GetLastError(), pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -125,7 +126,7 @@ static VOID CALLBACK
|
||||
WriteAPCProc(_In_ ULONG_PTR dwParam)
|
||||
{
|
||||
struct w32_io* pio = (struct w32_io*)dwParam;
|
||||
debug3("TermWrite CB - io:%p, bytes: %d, pending: %d, error: %d", pio, write_status.transferred,
|
||||
debug5("TermWrite CB - io:%p, bytes: %d, pending: %d, error: %d", pio, write_status.transferred,
|
||||
pio->write_details.pending, write_status.error);
|
||||
pio->write_details.error = write_status.error;
|
||||
pio->write_details.remaining -= write_status.transferred;
|
||||
@ -144,10 +145,9 @@ WriteThread(_In_ LPVOID lpParameter)
|
||||
{
|
||||
struct w32_io* pio = (struct w32_io*)lpParameter;
|
||||
char *respbuf = NULL;
|
||||
size_t resplen = 0;
|
||||
DWORD dwSavedAttributes = ENABLE_PROCESSED_INPUT;
|
||||
debug3("TermWrite thread, io:%p", pio);
|
||||
|
||||
size_t resplen = 0;
|
||||
debug5("TermWrite thread, io:%p", pio);
|
||||
|
||||
pio->write_details.buf[write_status.to_transfer] = '\0';
|
||||
|
||||
if (0 == in_raw_mode) {
|
||||
@ -162,7 +162,7 @@ WriteThread(_In_ LPVOID lpParameter)
|
||||
write_status.transferred = write_status.to_transfer;
|
||||
|
||||
if (0 == QueueUserAPC(WriteAPCProc, main_thread, (ULONG_PTR)pio)) {
|
||||
debug("TermWrite thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio);
|
||||
debug3("TermWrite thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio);
|
||||
pio->write_details.pending = FALSE;
|
||||
pio->write_details.error = GetLastError();
|
||||
DebugBreak();
|
||||
@ -176,13 +176,13 @@ int
|
||||
termio_initiate_write(struct w32_io* pio, DWORD num_bytes)
|
||||
{
|
||||
HANDLE write_thread;
|
||||
debug3("TermWrite initiate io:%p", pio);
|
||||
debug5("TermWrite initiate io:%p", pio);
|
||||
memset(&write_status, 0, sizeof(write_status));
|
||||
write_status.to_transfer = num_bytes;
|
||||
write_thread = CreateThread(NULL, 0, WriteThread, pio, 0, NULL);
|
||||
if (write_thread == NULL) {
|
||||
errno = errno_from_Win32Error(GetLastError());
|
||||
debug("TermWrite initiate - ERROR CreateThread %d, io:%p", GetLastError(), pio);
|
||||
debug3("TermWrite initiate - ERROR CreateThread %d, io:%p", GetLastError(), pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -195,7 +195,7 @@ termio_initiate_write(struct w32_io* pio, DWORD num_bytes)
|
||||
int
|
||||
termio_close(struct w32_io* pio)
|
||||
{
|
||||
debug2("termio_close - pio:%p", pio);
|
||||
debug4("termio_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.*/
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "Shlwapi.h"
|
||||
#include <sys\utime.h>
|
||||
#include "misc_internal.h"
|
||||
#include "debug.h"
|
||||
|
||||
/* internal table that stores the fd to w32_io mapping*/
|
||||
struct w32fd_table {
|
||||
@ -99,7 +100,7 @@ fd_table_get_min_index()
|
||||
min_index += 8;
|
||||
if (min_index >= MAX_FDS) {
|
||||
errno = EMFILE;
|
||||
debug("ERROR: MAX_FDS limit reached");
|
||||
debug3("ERROR: MAX_FDS limit reached");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -180,11 +181,10 @@ w32_io_on_select(struct w32_io* pio, BOOL rd)
|
||||
}
|
||||
|
||||
#define CHECK_FD(fd) do { \
|
||||
debug3("%s fd:%d", __FUNCTION__, fd); \
|
||||
errno = 0; \
|
||||
if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) { \
|
||||
errno = EBADF; \
|
||||
debug("%s ERROR: bad fd: %d", __FUNCTION__, fd); \
|
||||
debug3("%s ERROR: bad fd: %d", __FUNCTION__, fd); \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
@ -193,7 +193,7 @@ w32_io_on_select(struct w32_io* pio, BOOL rd)
|
||||
errno = 0; \
|
||||
if (pio->type != SOCK_FD) { \
|
||||
errno = ENOTSOCK; \
|
||||
debug("%s ERROR: not sock :%d", __FUNCTION__, pio->type); \
|
||||
debug3("%s ERROR: not sock :%d", __FUNCTION__, pio->type); \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
@ -221,7 +221,7 @@ w32_socket(int domain, int type, int protocol)
|
||||
}
|
||||
|
||||
fd_table_set(pio, min_index);
|
||||
debug("socket:%d, socktype:%d, io:%p, fd:%d ", pio->sock, type, pio, min_index);
|
||||
debug3("socket:%d, socktype:%d, io:%p, fd:%d ", pio->sock, type, pio, min_index);
|
||||
return min_index;
|
||||
}
|
||||
|
||||
@ -242,7 +242,7 @@ w32_accept(int fd, struct sockaddr* addr, int* addrlen)
|
||||
|
||||
pio->type = SOCK_FD;
|
||||
fd_table_set(pio, min_index);
|
||||
debug("socket:%d, io:%p, fd:%d ", pio->sock, pio, min_index);
|
||||
debug3("socket:%d, io:%p, fd:%d ", pio->sock, pio, min_index);
|
||||
return min_index;
|
||||
}
|
||||
|
||||
@ -329,7 +329,7 @@ w32_send(int fd, const void *buf, size_t len, int flags)
|
||||
int
|
||||
w32_shutdown(int fd, int how)
|
||||
{
|
||||
debug2("shutdown - fd:%d how:%d", fd, how);
|
||||
debug4("shutdown - fd:%d how:%d", fd, how);
|
||||
CHECK_FD(fd);
|
||||
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
|
||||
return socketio_shutdown(fd_table.w32_ios[fd], how);
|
||||
@ -339,7 +339,7 @@ int
|
||||
w32_socketpair(int domain, int type, int protocol, int sv[2])
|
||||
{
|
||||
errno = ENOTSUP;
|
||||
debug("socketpair - ERROR not supported");
|
||||
debug3("socketpair - ERROR not supported");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -371,7 +371,7 @@ w32_pipe(int *pfds)
|
||||
fd_table_set(pio[1], write_index);
|
||||
pfds[0] = read_index;
|
||||
pfds[1] = write_index;
|
||||
debug("pipe - r-h:%d,io:%p,fd:%d w-h:%d,io:%p,fd:%d",
|
||||
debug3("pipe - r-h:%d,io:%p,fd:%d w-h:%d,io:%p,fd:%d",
|
||||
pio[0]->handle, pio[0], read_index, pio[1]->handle, pio[1], write_index);
|
||||
|
||||
return 0;
|
||||
@ -393,8 +393,8 @@ w32_open(const char *pathname, int flags, ...)
|
||||
|
||||
pio->type = NONSOCK_FD;
|
||||
fd_table_set(pio, min_index);
|
||||
debug("open - handle:%p, io:%p, fd:%d", pio->handle, pio, min_index);
|
||||
debug3("open - path:%s", pathname);
|
||||
debug3("open - handle:%p, io:%p, fd:%d", pio->handle, pio, min_index);
|
||||
debug5("open - path:%s", pathname);
|
||||
return min_index;
|
||||
}
|
||||
|
||||
@ -473,7 +473,7 @@ w32_fdopen(int fd, const char *mode)
|
||||
errno = 0;
|
||||
if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) {
|
||||
errno = EBADF;
|
||||
debug("fdopen - ERROR bad fd: %d", fd);
|
||||
debug3("fdopen - ERROR bad fd: %d", fd);
|
||||
return NULL;
|
||||
}
|
||||
return fileio_fdopen(fd_table.w32_ios[fd], mode);
|
||||
@ -490,7 +490,7 @@ w32_close(int fd)
|
||||
|
||||
pio = fd_table.w32_ios[fd];
|
||||
|
||||
debug("close - io:%p, type:%d, fd:%d, table_index:%d", pio, pio->type, 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);
|
||||
|
||||
@ -510,7 +510,7 @@ w32_io_process_fd_flags(struct w32_io* pio, int flags)
|
||||
{
|
||||
DWORD shi_flags;
|
||||
if (flags & ~FD_CLOEXEC) {
|
||||
debug("fcntl - ERROR unsupported flags %d, io:%p", flags, pio);
|
||||
debug3("fcntl - ERROR unsupported flags %d, io:%p", flags, pio);
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
@ -523,7 +523,7 @@ w32_io_process_fd_flags(struct w32_io* pio, int flags)
|
||||
* UF_UNIX sockets that are not connected yet
|
||||
*/
|
||||
if (GetLastError() != ERROR_INVALID_HANDLE) {
|
||||
debug("fcntl - SetHandleInformation failed %d, io:%p",
|
||||
debug3("fcntl - SetHandleInformation failed %d, io:%p",
|
||||
GetLastError(), pio);
|
||||
errno = EOTHER;
|
||||
return -1;
|
||||
@ -559,7 +559,7 @@ w32_fcntl(int fd, int cmd, ... /* arg */)
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
debug("fcntl - ERROR not supported cmd:%d", cmd);
|
||||
debug3("fcntl - ERROR not supported cmd:%d", cmd);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
@ -589,20 +589,20 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
|
||||
|
||||
if (fds > MAX_FDS) {
|
||||
errno = EINVAL;
|
||||
debug("select - ERROR: invalid fds: %d", fds);
|
||||
debug3("select - ERROR: invalid fds: %d", fds);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!readfds && !writefds) {
|
||||
errno = EINVAL;
|
||||
debug("select - ERROR: null fd_sets");
|
||||
debug3("select - ERROR: null fd_sets");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO - see if this needs to be supported */
|
||||
/* if (exceptfds) {
|
||||
errno = EOPNOTSUPP;
|
||||
debug("select - ERROR: exceptfds not supported");
|
||||
debug3("select - ERROR: exceptfds not supported");
|
||||
DebugBreak();
|
||||
return -1;
|
||||
} */
|
||||
@ -626,11 +626,11 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
|
||||
/* if none of input fds are set return error */
|
||||
if (in_set_fds == 0) {
|
||||
errno = EINVAL;
|
||||
debug("select - ERROR: empty fd_sets");
|
||||
debug3("select - ERROR: empty fd_sets");
|
||||
return -1;
|
||||
}
|
||||
|
||||
debug3("Total in fds:%d", in_set_fds);
|
||||
debug5("Total in fds:%d", in_set_fds);
|
||||
/*
|
||||
* start async io on selected fds if needed and pick up any events
|
||||
* that select needs to listen on
|
||||
@ -641,7 +641,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
|
||||
if ((fd_table.w32_ios[i]->type == SOCK_FD) &&
|
||||
(fd_table.w32_ios[i]->internal.state == SOCK_LISTENING)) {
|
||||
if (num_events == SELECT_EVENT_LIMIT) {
|
||||
debug("select - ERROR: max #events breach");
|
||||
debug3("select - ERROR: max #events breach");
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
@ -654,7 +654,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
|
||||
if ((fd_table.w32_ios[i]->type == SOCK_FD) &&
|
||||
(fd_table.w32_ios[i]->internal.state == SOCK_CONNECTING)) {
|
||||
if (num_events == SELECT_EVENT_LIMIT) {
|
||||
debug("select - ERROR: max #events reached for select");
|
||||
debug3("select - ERROR: max #events reached for select");
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
@ -695,7 +695,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
|
||||
|
||||
if (timeout != NULL) {
|
||||
if (timeout_ms < ticks_spent) {
|
||||
debug("select - timing out");
|
||||
debug3("select - timing out");
|
||||
break;
|
||||
}
|
||||
time_rem = timeout_ms - (ticks_spent & 0xffffffff);
|
||||
@ -725,7 +725,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
|
||||
}
|
||||
|
||||
if (out_ready_fds == 0)
|
||||
debug3("select - wait ended without any IO completion, looping again");
|
||||
debug5("select - wait ended without any IO completion, looping again");
|
||||
}
|
||||
|
||||
/* clear out fds that are not ready yet */
|
||||
@ -754,7 +754,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
|
||||
FD_CLR(i, writefds);
|
||||
}
|
||||
|
||||
debug3("select - returning %d", out_ready_fds);
|
||||
debug5("select - returning %d", out_ready_fds);
|
||||
return out_ready_fds;
|
||||
|
||||
}
|
||||
@ -768,7 +768,7 @@ w32_dup(int oldfd)
|
||||
CHECK_FD(oldfd);
|
||||
if (oldfd > STDERR_FILENO) {
|
||||
errno = EOPNOTSUPP;
|
||||
debug("dup - ERROR: supports only std io, fd:%d", oldfd);
|
||||
debug3("dup - ERROR: supports only std io, fd:%d", oldfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -778,13 +778,13 @@ w32_dup(int oldfd)
|
||||
src = GetStdHandle(fd_table.w32_ios[oldfd]->std_handle);
|
||||
if (src == INVALID_HANDLE_VALUE) {
|
||||
errno = EINVAL;
|
||||
debug("dup - ERROR: unable to get underlying handle for std fd:%d", oldfd);
|
||||
debug3("dup - ERROR: unable to get underlying handle for std fd:%d", oldfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!DuplicateHandle(GetCurrentProcess(), src, GetCurrentProcess(), &target, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
|
||||
errno = EOTHER;
|
||||
debug("dup - ERROR: DuplicatedHandle() :%d", GetLastError());
|
||||
debug3("dup - ERROR: DuplicatedHandle() :%d", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -792,7 +792,7 @@ w32_dup(int oldfd)
|
||||
if (pio == NULL) {
|
||||
CloseHandle(target);
|
||||
errno = ENOMEM;
|
||||
debug("dup - ERROR: %d", errno);
|
||||
debug3("dup - ERROR: %d", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -808,7 +808,7 @@ w32_dup2(int oldfd, int newfd)
|
||||
{
|
||||
CHECK_FD(oldfd);
|
||||
errno = EOPNOTSUPP;
|
||||
debug("dup2 - ERROR: not implemented yet");
|
||||
debug3("dup2 - ERROR: not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1,34 +1,51 @@
|
||||
/*
|
||||
* Temporary Windows versions of functions implemented in utf8.c
|
||||
* Windows versions of functions implemented in utf8.c
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <Windows.h>
|
||||
|
||||
#include "console.h"
|
||||
|
||||
|
||||
int
|
||||
vfmprintf(FILE *f, const char *fmt, va_list list)
|
||||
vfmprintf(FILE *stream, const char *fmt, va_list ap)
|
||||
{
|
||||
return vfprintf(f, fmt, list);
|
||||
DWORD saved_mode = 0, new_mode = 0;
|
||||
int ret;
|
||||
HANDLE hFile;
|
||||
hFile = get_console_handle(stream, &saved_mode);
|
||||
if(hFile != INVALID_HANDLE_VALUE &&
|
||||
((saved_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {
|
||||
new_mode = saved_mode & (~ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
||||
SetConsoleMode(hFile, new_mode);
|
||||
}
|
||||
|
||||
ret = vfprintf(stream, fmt, ap);
|
||||
if (saved_mode != 0 && new_mode != saved_mode)
|
||||
SetConsoleMode(hFile, saved_mode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
mprintf(const char *fmt, ...)
|
||||
{
|
||||
int ret = 0;
|
||||
va_list valist;
|
||||
va_start(valist, fmt);
|
||||
ret = vfmprintf(stdout, fmt, valist);
|
||||
va_end(valist);
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
ret = vfmprintf(stdout, fmt, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
fmprintf(FILE *f, const char *fmt, ...)
|
||||
fmprintf(FILE *stream, const char *fmt, ...)
|
||||
{
|
||||
int ret = 0;
|
||||
va_list valist;
|
||||
va_start(valist, fmt);
|
||||
ret = vfmprintf(f, fmt, valist);
|
||||
va_end(valist);
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
ret = vfmprintf(stream, fmt, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -49,6 +66,5 @@ snmprintf(char *buf, size_t len, int *written, const char *fmt, ...)
|
||||
void
|
||||
msetlocale(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
58
contrib/win32/win32compat/win32_sshpty.c
Normal file
58
contrib/win32/win32compat/win32_sshpty.c
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Windows version of sshpty* routines in sshpty.c
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <Windows.h>
|
||||
#include "..\..\..\sshpty.h"
|
||||
|
||||
|
||||
/*
|
||||
* Windows versions of pty_*. Some of them are NO-OPs and should go
|
||||
* away when pty logic is refactored and abstracted out
|
||||
*
|
||||
*/
|
||||
int
|
||||
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
|
||||
{
|
||||
/*
|
||||
* Simple console screen implementation in Win32 to give a
|
||||
* Unix like pty for interactive sessions
|
||||
*/
|
||||
*ttyfd = 0;
|
||||
*ptyfd = 0;
|
||||
strlcpy(namebuf, "console", namebuflen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
pty_release(const char *tty) {
|
||||
/* NO-OP */
|
||||
}
|
||||
|
||||
void
|
||||
pty_make_controlling_tty(int *ttyfd, const char *tty) {
|
||||
/* NO-OP */
|
||||
}
|
||||
|
||||
void
|
||||
pty_change_window_size(int ptyfd, u_int row, u_int col,
|
||||
u_int xpixel, u_int ypixel) {
|
||||
COORD coord;
|
||||
coord.X = col;
|
||||
coord.Y = 9999;
|
||||
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coord);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pty_setowner(struct passwd *pw, const char *tty) {
|
||||
/* NO-OP */
|
||||
}
|
||||
|
||||
void
|
||||
disconnect_controlling_tty(void) {
|
||||
/* NO-OP */
|
||||
}
|
||||
|
40
contrib/win32/win32compat/win32_sshtty.c
Normal file
40
contrib/win32/win32compat/win32_sshtty.c
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Windows version of sshtty* routines implemented in sshtty.c
|
||||
*/
|
||||
|
||||
#include <Windows.h>
|
||||
#include "..\..\..\sshpty.h"
|
||||
|
||||
static struct termios _saved_tio;
|
||||
static int _in_raw_mode = 0;
|
||||
|
||||
|
||||
/*
|
||||
* TTY raw mode routines for Windows
|
||||
*/
|
||||
|
||||
int ConEnterRawMode(DWORD OutputHandle, BOOL fSmartInit);
|
||||
int ConExitRawMode(void);
|
||||
|
||||
struct termios term_settings;
|
||||
|
||||
/*
|
||||
* TODO - clean this up for Windows, ConInit should return previous terminal
|
||||
* settings that need to be stored in term_settings
|
||||
*/
|
||||
|
||||
struct termios *
|
||||
get_saved_tio(void) {
|
||||
memset(&term_settings, 0, sizeof(term_settings));
|
||||
return &term_settings;
|
||||
}
|
||||
|
||||
void
|
||||
leave_raw_mode(int quiet) {
|
||||
ConExitRawMode();
|
||||
}
|
||||
|
||||
void
|
||||
enter_raw_mode(int quiet) {
|
||||
ConEnterRawMode(STD_OUTPUT_HANDLE, TRUE);
|
||||
}
|
@ -53,21 +53,21 @@ int
|
||||
ga_init(const char *user, gid_t base)
|
||||
{
|
||||
#ifdef WINDOWS
|
||||
DWORD i = 0, j = 0;
|
||||
LPLOCALGROUP_USERS_INFO_0 local_groups_info = NULL, tmp_groups_info;
|
||||
wchar_t *user_utf16 = NULL, *full_name_utf16 = NULL, *udom_utf16 = NULL, *tmp;
|
||||
char *group_utf8 = NULL;
|
||||
DWORD i = 0, j = 0;
|
||||
DWORD entries_read = 0, total_entries = 0, full_name_len = 0, index = 0;
|
||||
NET_API_STATUS nStatus;
|
||||
|
||||
if (ngroups > 0)
|
||||
ga_free();
|
||||
|
||||
user_utf16 = utf8_to_utf16(user);
|
||||
if ((user_utf16 = utf8_to_utf16(user)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
full_name_len = wcslen(user_utf16) + 1;
|
||||
if ((full_name_utf16 = malloc(full_name_len * sizeof(wchar_t))) == NULL) {
|
||||
errno = ENOMEM;
|
||||
@ -151,7 +151,6 @@ done:
|
||||
free(groups_bygid);
|
||||
#endif /* !WINDOWS */
|
||||
return (ngroups = j);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
5
kex.c
5
kex.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kex.c,v 1.130 2017/03/10 04:07:20 djm Exp $ */
|
||||
/* $OpenBSD: kex.c,v 1.131 2017/03/15 07:07:39 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -341,7 +341,6 @@ kex_reset_dispatch(struct ssh *ssh)
|
||||
{
|
||||
ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN,
|
||||
SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -431,6 +430,7 @@ kex_input_newkeys(int type, u_int32_t seq, void *ctxt)
|
||||
|
||||
debug("SSH2_MSG_NEWKEYS received");
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
|
||||
if ((r = sshpkt_get_end(ssh)) != 0)
|
||||
return r;
|
||||
if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0)
|
||||
@ -545,6 +545,7 @@ kex_new(struct ssh *ssh, char *proposal[PROPOSAL_MAX], struct kex **kexp)
|
||||
goto out;
|
||||
kex->done = 0;
|
||||
kex_reset_dispatch(ssh);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
|
||||
r = 0;
|
||||
*kexp = kex;
|
||||
out:
|
||||
|
7
krl.c
7
krl.c
@ -14,7 +14,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $OpenBSD: krl.c,v 1.38 2016/09/12 01:22:38 deraadt Exp $ */
|
||||
/* $OpenBSD: krl.c,v 1.39 2017/03/10 07:18:32 dtucker Exp $ */
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
@ -1089,7 +1089,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
|
||||
break;
|
||||
case KRL_SECTION_SIGNATURE:
|
||||
/* Handled above, but still need to stay in synch */
|
||||
sshbuf_reset(sect);
|
||||
sshbuf_free(sect);
|
||||
sect = NULL;
|
||||
if ((r = sshbuf_skip_string(copy)) != 0)
|
||||
goto out;
|
||||
@ -1288,7 +1288,8 @@ ssh_krl_file_contains_key(const char *path, const struct sshkey *key)
|
||||
debug2("%s: checking KRL %s", __func__, path);
|
||||
r = ssh_krl_check_key(krl, key);
|
||||
out:
|
||||
close(fd);
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
sshbuf_free(krlbuf);
|
||||
ssh_krl_free(krl);
|
||||
if (r != 0)
|
||||
|
8
log.c
8
log.c
@ -455,15 +455,7 @@ do_log(LogLevel level, const char *fmt, va_list args)
|
||||
} else if (log_on_stderr) {
|
||||
snprintf(msgbuf, sizeof msgbuf, "%.*s\r\n",
|
||||
(int)sizeof msgbuf - 3, fmtbuf);
|
||||
#ifdef WINDOWS
|
||||
/*
|
||||
* In Windows, write is implemented as part of POSIX compat layer
|
||||
* that itself may "log" resulting in a infinite recursion loop
|
||||
*/
|
||||
_write(STDERR_FILENO, msgbuf, strlen(msgbuf));
|
||||
#else /* !WINDOWS */
|
||||
(void)write(log_stderr_fd, msgbuf, strlen(msgbuf));
|
||||
#endif /* !WINDOWS */
|
||||
} else {
|
||||
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
|
||||
openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
|
||||
|
17
misc.c
17
misc.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: misc.c,v 1.107 2016/11/30 00:28:31 dtucker Exp $ */
|
||||
/* $OpenBSD: misc.c,v 1.109 2017/03/14 00:55:37 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
|
||||
@ -310,7 +310,7 @@ a2tun(const char *s, int *remote)
|
||||
long
|
||||
convtime(const char *s)
|
||||
{
|
||||
long total, secs;
|
||||
long total, secs, multiplier = 1;
|
||||
const char *p;
|
||||
char *endp;
|
||||
|
||||
@ -337,23 +337,28 @@ convtime(const char *s)
|
||||
break;
|
||||
case 'm':
|
||||
case 'M':
|
||||
secs *= MINUTES;
|
||||
multiplier = MINUTES;
|
||||
break;
|
||||
case 'h':
|
||||
case 'H':
|
||||
secs *= HOURS;
|
||||
multiplier = HOURS;
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
secs *= DAYS;
|
||||
multiplier = DAYS;
|
||||
break;
|
||||
case 'w':
|
||||
case 'W':
|
||||
secs *= WEEKS;
|
||||
multiplier = WEEKS;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (secs >= LONG_MAX / multiplier)
|
||||
return -1;
|
||||
secs *= multiplier;
|
||||
if (total >= LONG_MAX - secs)
|
||||
return -1;
|
||||
total += secs;
|
||||
if (total < 0)
|
||||
return -1;
|
||||
|
@ -307,3 +307,11 @@ mbtowc(wchar_t *pwc, const char *s, size_t n)
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LLABS
|
||||
long long
|
||||
llabs(long long j)
|
||||
{
|
||||
return (j < 0 ? -j : j);
|
||||
}
|
||||
#endif
|
||||
|
@ -135,4 +135,8 @@ void errx(int, const char *, ...) __attribute__((format(printf, 2, 3)));
|
||||
void warn(const char *, ...) __attribute__((format(printf, 1, 2)));
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LLABS
|
||||
long long llabs(long long);
|
||||
#endif
|
||||
|
||||
#endif /* _BSD_MISC_H */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: fmt_scaled.c,v 1.9 2007/03/20 03:42:52 tedu Exp $ */
|
||||
/* $OpenBSD: fmt_scaled.c,v 1.13 2017/03/11 23:37:23 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001, 2002, 2003 Ian F. Darwin. All rights reserved.
|
||||
@ -69,7 +69,7 @@ static long long scale_factors[] = {
|
||||
|
||||
#define MAX_DIGITS (SCALE_LENGTH * 3) /* XXX strlen(sprintf("%lld", -1)? */
|
||||
|
||||
/** Convert the given input string "scaled" into numeric in "result".
|
||||
/* Convert the given input string "scaled" into numeric in "result".
|
||||
* Return 0 on success, -1 and errno set on error.
|
||||
*/
|
||||
int
|
||||
@ -81,7 +81,7 @@ scan_scaled(char *scaled, long long *result)
|
||||
long long scale_fact = 1, whole = 0, fpart = 0;
|
||||
|
||||
/* Skip leading whitespace */
|
||||
while (isascii(*p) && isspace(*p))
|
||||
while (isascii((unsigned char)*p) && isspace((unsigned char)*p))
|
||||
++p;
|
||||
|
||||
/* Then at most one leading + or - */
|
||||
@ -108,7 +108,8 @@ scan_scaled(char *scaled, long long *result)
|
||||
* (but note that E for Exa might look like e to some!).
|
||||
* Advance 'p' to end, to get scale factor.
|
||||
*/
|
||||
for (; isascii(*p) && (isdigit(*p) || *p=='.'); ++p) {
|
||||
for (; isascii((unsigned char)*p) &&
|
||||
(isdigit((unsigned char)*p) || *p=='.'); ++p) {
|
||||
if (*p == '.') {
|
||||
if (fract_digits > 0) { /* oops, more than one '.' */
|
||||
errno = EINVAL;
|
||||
@ -124,6 +125,10 @@ scan_scaled(char *scaled, long long *result)
|
||||
/* ignore extra fractional digits */
|
||||
continue;
|
||||
fract_digits++; /* for later scaling */
|
||||
if (fpart >= LLONG_MAX / 10) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
fpart *= 10;
|
||||
fpart += i;
|
||||
} else { /* normal digit */
|
||||
@ -131,6 +136,10 @@ scan_scaled(char *scaled, long long *result)
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
if (whole >= LLONG_MAX / 10) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
whole *= 10;
|
||||
whole += i;
|
||||
}
|
||||
@ -150,17 +159,22 @@ scan_scaled(char *scaled, long long *result)
|
||||
/* Validate scale factor, and scale whole and fraction by it. */
|
||||
for (i = 0; i < SCALE_LENGTH; i++) {
|
||||
|
||||
/** Are we there yet? */
|
||||
/* Are we there yet? */
|
||||
if (*p == scale_chars[i] ||
|
||||
*p == tolower(scale_chars[i])) {
|
||||
*p == tolower((unsigned char)scale_chars[i])) {
|
||||
|
||||
/* If it ends with alphanumerics after the scale char, bad. */
|
||||
if (isalnum(*(p+1))) {
|
||||
if (isalnum((unsigned char)*(p+1))) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
scale_fact = scale_factors[i];
|
||||
|
||||
if (whole >= LLONG_MAX / scale_fact) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* scale whole part */
|
||||
whole *= scale_fact;
|
||||
|
||||
@ -181,7 +195,9 @@ scan_scaled(char *scaled, long long *result)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
errno = ERANGE;
|
||||
|
||||
/* Invalid unit or character */
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -196,7 +212,7 @@ fmt_scaled(long long number, char *result)
|
||||
unsigned int i;
|
||||
unit_type unit = NONE;
|
||||
|
||||
abval = (number < 0LL) ? -number : number; /* no long long_abs yet */
|
||||
abval = llabs(number);
|
||||
|
||||
/* Not every negative long long has a positive representation.
|
||||
* Also check for numbers that are just too darned big to format
|
||||
|
6
packet.c
6
packet.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: packet.c,v 1.246 2017/02/28 06:10:08 djm Exp $ */
|
||||
/* $OpenBSD: packet.c,v 1.247 2017/03/11 13:07:35 markus Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -1850,11 +1850,11 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
|
||||
if (r != SSH_ERR_MAC_INVALID)
|
||||
goto out;
|
||||
logit("Corrupted MAC on input.");
|
||||
if (need > PACKET_MAX_SIZE)
|
||||
if (need + block_size > PACKET_MAX_SIZE)
|
||||
return SSH_ERR_INTERNAL_ERROR;
|
||||
return ssh_packet_start_discard(ssh, enc, mac,
|
||||
sshbuf_len(state->incoming_packet),
|
||||
PACKET_MAX_SIZE - need);
|
||||
PACKET_MAX_SIZE - need - block_size);
|
||||
}
|
||||
/* Remove MAC from input buffer */
|
||||
DBG(debug("MAC #%d ok", state->p_read.seqnr));
|
||||
|
68
readpass.c
68
readpass.c
@ -69,7 +69,7 @@ ssh_askpass(char *askpass, const char *msg)
|
||||
#ifdef WINDOWS
|
||||
/* spawd child for Windows */
|
||||
fcntl(p[0], F_SETFD, FD_CLOEXEC);
|
||||
pid = spawn_child(askpass, p[1], p[1], STDERR_FILENO, 0);
|
||||
pid = spawn_child(askpass, NULL, p[1], p[1], STDERR_FILENO, 0);
|
||||
if (pid < 0) {
|
||||
#else /* !WINDOWS */
|
||||
if ((pid = fork()) < 0) {
|
||||
@ -125,71 +125,6 @@ ssh_askpass(char *askpass, const char *msg)
|
||||
char *
|
||||
read_passphrase(const char *prompt, int flags)
|
||||
{
|
||||
|
||||
#ifdef WINDOWS
|
||||
/* TODO - do flags apply on Windows? */
|
||||
char *askpass = NULL;
|
||||
char *ret = NULL;
|
||||
char buf[1024] = { 0 };
|
||||
|
||||
DWORD mode;
|
||||
size_t len = 0;
|
||||
int retr = 0;
|
||||
|
||||
if (getenv(SSH_ASKPASS_ENV)) {
|
||||
askpass = getenv(SSH_ASKPASS_ENV);
|
||||
if ((ret = ssh_askpass(askpass, prompt)) == NULL)
|
||||
return xstrdup("");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* prompt user */
|
||||
wchar_t* wtmp = utf8_to_utf16(prompt);
|
||||
if (wtmp == NULL)
|
||||
fatal("unable to alloc memory");
|
||||
_cputws(wtmp);
|
||||
free(wtmp);
|
||||
|
||||
len = retr = 0;
|
||||
int bufsize = sizeof(buf);
|
||||
|
||||
while (_kbhit())
|
||||
_getch();
|
||||
|
||||
while (len < bufsize) {
|
||||
buf[len] = (unsigned char)_getch();
|
||||
|
||||
if (buf[len] == '\r') {
|
||||
if (_kbhit()) /* read linefeed if its there */
|
||||
_getch();
|
||||
break;
|
||||
}
|
||||
else if (buf[len] == '\n') {
|
||||
break;
|
||||
}
|
||||
else if (buf[len] == '\b') { /* backspace */
|
||||
if (len > 0)
|
||||
len--; /* overwrite last character */
|
||||
}
|
||||
else if (buf[len] == '\003') {
|
||||
/* exit on Ctrl+C */
|
||||
fatal("");
|
||||
}
|
||||
else {
|
||||
len++; /* keep reading in the loop */
|
||||
}
|
||||
}
|
||||
|
||||
buf[len] = '\0'; /* get rid of the cr/lf */
|
||||
_cputs("\n"); /*show a newline as we do not echo password or the line */
|
||||
|
||||
ret = xstrdup(buf);
|
||||
|
||||
memset(buf, 'x', sizeof(buf));
|
||||
|
||||
return ret;
|
||||
|
||||
#else /* !WINDOWS */
|
||||
char *askpass = NULL, *ret, buf[1024];
|
||||
int rppflags, use_askpass = 0, ttyfd;
|
||||
|
||||
@ -236,7 +171,6 @@ read_passphrase(const char *prompt, int flags)
|
||||
ret = xstrdup(buf);
|
||||
explicit_bzero(buf, sizeof(buf));
|
||||
return ret;
|
||||
#endif /* !WINDOWS */
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -222,6 +222,7 @@ unit:
|
||||
$$V ${.OBJDIR}/unittests/sshkey/test_sshkey \
|
||||
-d ${.CURDIR}/unittests/sshkey/testdata ; \
|
||||
$$V ${.OBJDIR}/unittests/bitmap/test_bitmap ; \
|
||||
$$V ${.OBJDIR}/unittests/conversion/test_conversion ; \
|
||||
$$V ${.OBJDIR}/unittests/kex/test_kex ; \
|
||||
$$V ${.OBJDIR}/unittests/hostkeys/test_hostkeys \
|
||||
-d ${.CURDIR}/unittests/hostkeys/testdata ; \
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $OpenBSD: cert-file.sh,v 1.4 2016/12/16 02:48:55 djm Exp $
|
||||
# $OpenBSD: cert-file.sh,v 1.5 2017/03/11 23:44:16 djm Exp $
|
||||
# Placed in the Public Domain.
|
||||
|
||||
tid="ssh with certificates"
|
||||
@ -17,24 +17,59 @@ ${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key1 || \
|
||||
fatal "ssh-keygen failed"
|
||||
${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key2 || \
|
||||
fatal "ssh-keygen failed"
|
||||
${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key3 || \
|
||||
fatal "ssh-keygen failed"
|
||||
${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key4 || \
|
||||
fatal "ssh-keygen failed"
|
||||
${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key5 || \
|
||||
fatal "ssh-keygen failed"
|
||||
|
||||
# Move the certificate to a different address to better control
|
||||
# when it is offered.
|
||||
${SSHKEYGEN} -q -s $OBJ/user_ca_key1 -I "regress user key for $USER" \
|
||||
-z $$ -n ${USER} $OBJ/user_key1 ||
|
||||
fail "couldn't sign user_key1 with user_ca_key1"
|
||||
fatal "couldn't sign user_key1 with user_ca_key1"
|
||||
mv $OBJ/user_key1-cert.pub $OBJ/cert_user_key1_1.pub
|
||||
${SSHKEYGEN} -q -s $OBJ/user_ca_key2 -I "regress user key for $USER" \
|
||||
-z $$ -n ${USER} $OBJ/user_key1 ||
|
||||
fail "couldn't sign user_key1 with user_ca_key2"
|
||||
fatal "couldn't sign user_key1 with user_ca_key2"
|
||||
mv $OBJ/user_key1-cert.pub $OBJ/cert_user_key1_2.pub
|
||||
${SSHKEYGEN} -q -s $OBJ/user_ca_key1 -I "regress user key for $USER" \
|
||||
-z $$ -n ${USER} $OBJ/user_key3 ||
|
||||
fatal "couldn't sign user_key3 with user_ca_key1"
|
||||
rm $OBJ/user_key3.pub # to test use of private key w/o public half.
|
||||
${SSHKEYGEN} -q -s $OBJ/user_ca_key1 -I "regress user key for $USER" \
|
||||
-z $$ -n ${USER} $OBJ/user_key4 ||
|
||||
fatal "couldn't sign user_key4 with user_ca_key1"
|
||||
rm $OBJ/user_key4 $OBJ/user_key4.pub # to test no matching pub/private key case.
|
||||
|
||||
trace 'try with identity files'
|
||||
opts="-F $OBJ/ssh_proxy -oIdentitiesOnly=yes"
|
||||
opts2="$opts -i $OBJ/user_key1 -i $OBJ/user_key2"
|
||||
echo "cert-authority $(cat $OBJ/user_ca_key1.pub)" > $OBJ/authorized_keys_$USER
|
||||
|
||||
# Make a clean config that doesn't have any pre-added identities.
|
||||
cat $OBJ/ssh_proxy | grep -v IdentityFile > $OBJ/no_identity_config
|
||||
|
||||
# XXX: verify that certificate used was what we expect. Needs exposure of
|
||||
# keys via enviornment variable or similar.
|
||||
|
||||
for p in ${SSH_PROTOCOLS}; do
|
||||
# Key with no .pub should work - finding the equivalent *-cert.pub.
|
||||
verbose "protocol $p: identity cert with no plain public file"
|
||||
${SSH} -F $OBJ/no_identity_config -oIdentitiesOnly=yes \
|
||||
-i $OBJ/user_key3 somehost exit 5$p
|
||||
[ $? -ne 5$p ] && fail "ssh failed"
|
||||
|
||||
# CertificateFile matching private key with no .pub file should work.
|
||||
verbose "protocol $p: CertificateFile with no plain public file"
|
||||
${SSH} -F $OBJ/no_identity_config -oIdentitiesOnly=yes \
|
||||
-oCertificateFile=$OBJ/user_key3-cert.pub \
|
||||
-i $OBJ/user_key3 somehost exit 5$p
|
||||
[ $? -ne 5$p ] && fail "ssh failed"
|
||||
|
||||
# Just keys should fail
|
||||
verbose "protocol $p: plain keys"
|
||||
${SSH} $opts2 somehost exit 5$p
|
||||
r=$?
|
||||
if [ $r -eq 5$p ]; then
|
||||
@ -42,6 +77,7 @@ for p in ${SSH_PROTOCOLS}; do
|
||||
fi
|
||||
|
||||
# Keys with untrusted cert should fail.
|
||||
verbose "protocol $p: untrusted cert"
|
||||
opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_2.pub"
|
||||
${SSH} $opts3 somehost exit 5$p
|
||||
r=$?
|
||||
@ -50,6 +86,7 @@ for p in ${SSH_PROTOCOLS}; do
|
||||
fi
|
||||
|
||||
# Good cert with bad key should fail.
|
||||
verbose "protocol $p: good cert, bad key"
|
||||
opts3="$opts -i $OBJ/user_key2"
|
||||
opts3="$opts3 -oCertificateFile=$OBJ/cert_user_key1_1.pub"
|
||||
${SSH} $opts3 somehost exit 5$p
|
||||
@ -59,6 +96,7 @@ for p in ${SSH_PROTOCOLS}; do
|
||||
fi
|
||||
|
||||
# Keys with one trusted cert, should succeed.
|
||||
verbose "protocol $p: single trusted"
|
||||
opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_1.pub"
|
||||
${SSH} $opts3 somehost exit 5$p
|
||||
r=$?
|
||||
@ -67,6 +105,7 @@ for p in ${SSH_PROTOCOLS}; do
|
||||
fi
|
||||
|
||||
# Multiple certs and keys, with one trusted cert, should succeed.
|
||||
verbose "protocol $p: multiple trusted"
|
||||
opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_2.pub"
|
||||
opts3="$opts3 -oCertificateFile=$OBJ/cert_user_key1_1.pub"
|
||||
${SSH} $opts3 somehost exit 5$p
|
||||
@ -74,14 +113,6 @@ for p in ${SSH_PROTOCOLS}; do
|
||||
if [ $r -ne 5$p ]; then
|
||||
fail "ssh failed with multiple certs in protocol $p"
|
||||
fi
|
||||
|
||||
#Keys with trusted certificate specified in config options, should succeed.
|
||||
opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_1.pub"
|
||||
${SSH} $opts3 somehost exit 5$p
|
||||
r=$?
|
||||
if [ $r -ne 5$p ]; then
|
||||
fail "ssh failed with trusted cert in config in protocol $p"
|
||||
fi
|
||||
done
|
||||
|
||||
#next, using an agent in combination with the keys
|
||||
|
@ -10,7 +10,7 @@ start_sshd
|
||||
base=33
|
||||
last=$PORT
|
||||
fwd=""
|
||||
CTL=$OBJ/ctl-sock
|
||||
CTL=/tmp/openssh.regress.ctl-sock.$$
|
||||
|
||||
for j in 0 1 2; do
|
||||
for i in 0 1 2; do
|
||||
|
@ -1,13 +1,8 @@
|
||||
# $OpenBSD: keytype.sh,v 1.4 2015/07/10 06:23:25 markus Exp $
|
||||
# $OpenBSD: keytype.sh,v 1.5 2017/03/20 22:08:06 djm Exp $
|
||||
# Placed in the Public Domain.
|
||||
|
||||
tid="login with different key types"
|
||||
|
||||
TIME=`which time 2>/dev/null`
|
||||
if test ! -x "$TIME"; then
|
||||
TIME=""
|
||||
fi
|
||||
|
||||
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
|
||||
cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
|
||||
|
||||
@ -26,8 +21,8 @@ for kt in $ktypes; do
|
||||
rm -f $OBJ/key.$kt
|
||||
bits=`echo ${kt} | awk -F- '{print $2}'`
|
||||
type=`echo ${kt} | awk -F- '{print $1}'`
|
||||
printf "keygen $type, $bits bits:\t"
|
||||
${TIME} ${SSHKEYGEN} -b $bits -q -N '' -t $type -f $OBJ/key.$kt ||\
|
||||
verbose "keygen $type, $bits bits"
|
||||
${SSHKEYGEN} -b $bits -q -N '' -t $type -f $OBJ/key.$kt ||\
|
||||
fail "ssh-keygen for type $type, $bits bits failed"
|
||||
done
|
||||
|
||||
@ -63,8 +58,8 @@ for ut in $ktypes; do
|
||||
) > $OBJ/known_hosts
|
||||
cat $OBJ/key.$ut.pub > $OBJ/authorized_keys_$USER
|
||||
for i in $tries; do
|
||||
printf "userkey $ut, hostkey ${ht}:\t"
|
||||
${TIME} ${SSH} -F $OBJ/ssh_proxy 999.999.999.999 true
|
||||
verbose "userkey $ut, hostkey ${ht}"
|
||||
${SSH} -F $OBJ/ssh_proxy 999.999.999.999 true
|
||||
if [ $? -ne 0 ]; then
|
||||
fail "ssh userkey $ut, hostkey $ht failed"
|
||||
fi
|
||||
|
@ -64,7 +64,7 @@ function Is-CoreCLR {
|
||||
|
||||
Class Machine
|
||||
{
|
||||
[string] $MachineName = $env:COMPUTERNAME
|
||||
[string] $MachineName = "localhost"
|
||||
[MachineRole] $Role = [MachineRole]::Client
|
||||
[PlatformType] $Platform
|
||||
[boolean] $IsCoreCLR
|
||||
@ -72,8 +72,9 @@ Class Machine
|
||||
#Members on server role
|
||||
[string []] $PublicHostKeyPaths
|
||||
[string []] $PrivateHostKeyPaths
|
||||
[string] $localAdminUserName = "localadmin"
|
||||
[string] $localAdminPassword = "Bull_dog1"
|
||||
[string] $ssouser = "sshtest_ssouser"
|
||||
[string] $passwduser = "sshtest_passwduser"
|
||||
[string] $passwduser_pw = "P@ssw0rd_1"
|
||||
[string] $localAdminAuthorizedKeyPath
|
||||
[string] $sshdConfigFile = (join-path $PSScriptRoot "sshd_config")
|
||||
[string] $backupFileName = (join-path $PSScriptRoot "sshd_backup")
|
||||
@ -92,19 +93,19 @@ Class Machine
|
||||
Machine() {
|
||||
$this.Platform = Set-Platform
|
||||
$this.IsCoreCLR = Is-CoreCLR
|
||||
$this.InitializeClient()
|
||||
$this.InitializeServer()
|
||||
#$this.InitializeClient()
|
||||
#$this.InitializeServer()
|
||||
}
|
||||
|
||||
Machine ([MachineRole] $r) {
|
||||
$this.Platform = Set-Platform
|
||||
$this.IsCoreCLR = Is-CoreCLR
|
||||
$this.Role = $r
|
||||
if($this.Role -eq [MachineRole]::Client) {
|
||||
$this.InitializeClient()
|
||||
} else {
|
||||
$this.InitializeServer()
|
||||
}
|
||||
#if($this.Role -eq [MachineRole]::Client) {
|
||||
# $this.InitializeClient()
|
||||
#} else {
|
||||
# $this.InitializeServer()
|
||||
#}
|
||||
}
|
||||
|
||||
[void] InitializeClient() {
|
||||
@ -127,14 +128,6 @@ Class Machine
|
||||
}
|
||||
}
|
||||
|
||||
foreach($key in @("ed25519")) #@("rsa","dsa","ecdsa","ed25519")
|
||||
{
|
||||
$keyPath = "$($this.ClientKeyDirectory)\id_$key"
|
||||
$this.clientPrivateKeyPaths += $keyPath
|
||||
$this.clientPublicKeyPaths += "$keyPath.pub"
|
||||
$str = ".\ssh-keygen -t $key -P """" -f $keyPath"
|
||||
$this.RunCmd($str)
|
||||
}
|
||||
}
|
||||
|
||||
[void] InitializeServer() {
|
||||
@ -157,13 +150,6 @@ Class Machine
|
||||
}
|
||||
$this.localAdminAuthorizedKeyPath = join-path $($this.localUserprofilePath) ".ssh/authorized_keys"
|
||||
Remove-Item -Path $($this.localAdminAuthorizedKeyPath) -Force -ea silentlycontinue
|
||||
|
||||
#Generate all host keys
|
||||
.\ssh-keygen -A
|
||||
$this.PublicHostKeyPaths = @("$psscriptroot\ssh_host_ed25519_key.pub")
|
||||
# @("$psscriptroot\ssh_host_rsa_key.pub","$psscriptroot\ssh_host_dsa_key.pub","$psscriptroot\ssh_host_ecdsa_key.pub","$psscriptroot\ssh_host_ed25519_key.pub")
|
||||
$this.PrivateHostKeyPaths = @("$psscriptroot\ssh_host_ed25519_key")
|
||||
# @("$psscriptroot\ssh_host_rsa_key","$psscriptroot\ssh_host_dsa_key","$psscriptroot\ssh_host_ecdsa_key","$psscriptroot\ssh_host_ed25519_key")
|
||||
}
|
||||
|
||||
[void] SetupClient([Machine] $server) {
|
||||
@ -251,6 +237,11 @@ Class Machine
|
||||
{
|
||||
$this.SetKeys($null, $publicKeyPath, $($this.localAdminAuthorizedKeyPath))
|
||||
}
|
||||
# Provide Read Access to NT Service\sshd
|
||||
$acl = get-acl $($this.localAdminAuthorizedKeyPath)
|
||||
$ar = New-Object System.Security.AccessControl.FileSystemAccessRule("NT Service\sshd", "Read", "Allow")
|
||||
$acl.SetAccessRule($ar)
|
||||
Set-Acl $($this.localAdminAuthorizedKeyPath) $acl
|
||||
}
|
||||
|
||||
[void] CleanupServer() {
|
||||
@ -351,7 +342,8 @@ Class Machine
|
||||
}
|
||||
|
||||
[void] AddPasswordSetting([string] $pass) {
|
||||
if ($this.Platform -eq [PlatformType]::Windows) {
|
||||
if ($this.Platform -eq [PlatformType]::Windows) {
|
||||
if (-not($env:DISPLAY)) {$env:DISPLAY=1}
|
||||
$env:SSH_ASKPASS="$($env:ComSpec) /c echo $pass"
|
||||
}
|
||||
}
|
||||
@ -359,6 +351,7 @@ Class Machine
|
||||
[void] CleanupPasswordSetting() {
|
||||
if ($this.Platform -eq [PlatformType]::Windows -and (Test-Path env:SSH_ASKPASS))
|
||||
{
|
||||
if ($env:DISPLAY -eq 1) {Remove-Item env:\DISPLAY}
|
||||
remove-item "env:SSH_ASKPASS" -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
@ -1,53 +1,45 @@
|
||||
using module .\PlatformAbstractLayer.psm1
|
||||
|
||||
|
||||
Describe "Tests for portforwarding" -Tags "CI" {
|
||||
BeforeAll {
|
||||
BeforeAll {
|
||||
|
||||
if($OpenSSHTestInfo -eq $null)
|
||||
{
|
||||
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment."
|
||||
}
|
||||
$fileName = "test.txt"
|
||||
$filePath = Join-Path ${TestDrive} $fileName
|
||||
|
||||
[Machine] $client = [Machine]::new([MachineRole]::Client)
|
||||
[Machine] $server = [Machine]::new([MachineRole]::Server)
|
||||
$client.SetupClient($server)
|
||||
$server.SetupServer($client)
|
||||
|
||||
$server.SecureHostKeys($server.PrivateHostKeyPaths)
|
||||
$server.SetupServerRemoting([Protocol]::WSMAN)
|
||||
#setup single signon
|
||||
.\ssh-add.exe $client.clientPrivateKeyPaths[0]
|
||||
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
||||
$logName = "log.txt"
|
||||
$logPath = Join-Path ${TestDrive} $logName
|
||||
$server = $OpenSSHTestInfo["Target"]
|
||||
$port = $OpenSSHTestInfo["Port"]
|
||||
$ssouser = $OpenSSHTestInfo["SSOUser"]
|
||||
|
||||
$testData = @(
|
||||
@{
|
||||
Title = "Local port forwarding"
|
||||
Options = "-L 5432:127.0.0.1:47001"
|
||||
Port = 5432
|
||||
FwdedPort = 5432
|
||||
|
||||
},
|
||||
@{
|
||||
Title = "Remote port forwarding"
|
||||
Options = "-R 5432:127.0.0.1:47001"
|
||||
Port = 5432
|
||||
FwdedPort = 5432
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
#cleanup single signon
|
||||
.\ssh-add.exe -D
|
||||
$Server.CleanupHostKeys()
|
||||
$client.CleanupClient()
|
||||
$server.CleanupServer()
|
||||
}
|
||||
|
||||
AfterEach {
|
||||
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
||||
Remove-Item -Path $logPath -Force -ea silentlycontinue
|
||||
}
|
||||
|
||||
It '<Title>' -TestCases:$testData {
|
||||
param([string]$Title, $Options, $port)
|
||||
|
||||
$str = ".\ssh $($Options) $($server.localAdminUserName)@$($server.MachineName) powershell.exe Test-WSMan -computer 127.0.0.1 -port $port > $filePath"
|
||||
$client.RunCmd($str)
|
||||
param([string]$Title, $Options, $FwdedPort)
|
||||
|
||||
$str = "ssh -p $($port) -E $logPath $($Options) $($ssouser)@$($server) powershell.exe Test-WSMan -computer 127.0.0.1 -port $FwdedPort > $filePath"
|
||||
# TODO - move this to PAL
|
||||
cmd /c $str
|
||||
#validate file content.
|
||||
$content = Get-Content $filePath
|
||||
$content -like "wsmid*" | Should Not Be $null
|
||||
|
@ -1,6 +1,4 @@
|
||||
using module .\PlatformAbstractLayer.psm1
|
||||
|
||||
Describe "Tests for powershell over ssh" -Tags "Scenario" {
|
||||
Describe "Tests for powershell over ssh" -Tags "Scenario" {
|
||||
BeforeAll {
|
||||
$defaultParamValues = $PSDefaultParameterValues.Clone()
|
||||
#Skip on windows powershell. this feature only supported in powershell core from git
|
||||
|
42
regress/pesterTests/README.md
Normal file
42
regress/pesterTests/README.md
Normal file
@ -0,0 +1,42 @@
|
||||
Run OpenSSH Pester Tests:
|
||||
==================================
|
||||
|
||||
#### To setup the test environment before test run:
|
||||
|
||||
```powershell
|
||||
Import-Module .\openssh-portable\contrib\win32\openssh\OpenSSHTestHelper.psm1 –Force
|
||||
Setup-OpenSSHTestEnvironment
|
||||
```
|
||||
|
||||
`Setup-OpenSSHTestEnvironment` contains below parameters:
|
||||
* `-OpenSSHBinPath`: Specify the location where ssh.exe should be picked up. If not specified, the function will prompt to user if he/she want to choose the first ssh.exe found in `$env:path` if exists.
|
||||
* `-TestDataPath`: Specify the location where the test binaries deploy to. The default is `$env:SystemDrive\OpenSSHTests` if it not specified.
|
||||
* `-Quiet`: If it is set, the function will do all the changes without prompting to user to confirm.
|
||||
* `-DebugMode`: If it is set, the subsequent tests will be running in debug mode. User can modify by setting $OpenSSHTestInfo["DebugMode"] .
|
||||
|
||||
#### To run the test suites:
|
||||
|
||||
```powershell
|
||||
Run-OpenSSHE2ETest
|
||||
Run-OpenSSHUnitTest
|
||||
```
|
||||
|
||||
#### To run a particular test, just run the script or the executatlbe directly
|
||||
|
||||
```powershell
|
||||
C:\git\openssh-portable\regress\pesterTests\SCP.Tests.ps1
|
||||
C:\git\openssh-portable\bin\x64\Release\unittest-bitmap\unittest-bitmap.exe
|
||||
```
|
||||
|
||||
#### To verify / modify (Ex- DebugMode) the Test setup environment
|
||||
|
||||
```powershell
|
||||
$OpenSSHTestInfo
|
||||
$OpenSSHTestInfo["DebugMode"] = $true
|
||||
```
|
||||
|
||||
#### To revert what's done in Setup-OpenSSHTestEnvironment:
|
||||
|
||||
```powershell
|
||||
Cleanup-OpenSSHTestEnvironment
|
||||
```
|
@ -1,30 +1,39 @@
|
||||
using module .\PlatformAbstractLayer.psm1
|
||||
|
||||
|
||||
#covered -i -p -q -r -v -c -S -C
|
||||
#todo: -F, -l and -P should be tested over the network
|
||||
Describe "Tests for scp command" -Tags "CI" {
|
||||
BeforeAll {
|
||||
BeforeAll {
|
||||
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
|
||||
}
|
||||
|
||||
$fileName1 = "test.txt"
|
||||
$fileName2 = "test2.txt"
|
||||
$SourceDirName = "SourceDir"
|
||||
$SourceDir = Join-Path ${TestDrive} $SourceDirName
|
||||
$SourceDir = Join-Path "$($OpenSSHTestInfo["TestDataPath"])\SCP" $SourceDirName
|
||||
$SourceFilePath = Join-Path $SourceDir $fileName1
|
||||
$DestinationDir = Join-Path ${TestDrive} "DestDir"
|
||||
$DestinationDir = Join-Path "$($OpenSSHTestInfo["TestDataPath"])\SCP" "DestDir"
|
||||
$DestinationFilePath = Join-Path $DestinationDir $fileName1
|
||||
$NestedSourceDir= Join-Path $SourceDir "nested"
|
||||
$NestedSourceFilePath = Join-Path $NestedSourceDir $fileName2
|
||||
$null = New-Item $SourceDir -ItemType directory -Force
|
||||
$null = New-Item $NestedSourceDir -ItemType directory -Force
|
||||
$null = New-item -path $SourceFilePath -force
|
||||
$null = New-item -path $NestedSourceFilePath -force
|
||||
$null = New-Item $SourceDir -ItemType directory -Force -ErrorAction SilentlyContinue
|
||||
$null = New-Item $NestedSourceDir -ItemType directory -Force -ErrorAction SilentlyContinue
|
||||
$null = New-item -path $SourceFilePath -force -ErrorAction SilentlyContinue
|
||||
$null = New-item -path $NestedSourceFilePath -force -ErrorAction SilentlyContinue
|
||||
"Test content111" | Set-content -Path $SourceFilePath
|
||||
"Test content in nested dir" | Set-content -Path $NestedSourceFilePath
|
||||
$null = New-Item $DestinationDir -ItemType directory -Force
|
||||
|
||||
[Machine] $client = [Machine]::new([MachineRole]::Client)
|
||||
[Machine] $server = [Machine]::new([MachineRole]::Server)
|
||||
$client.SetupClient($server)
|
||||
$server.SetupServer($client)
|
||||
$null = New-Item $DestinationDir -ItemType directory -Force -ErrorAction SilentlyContinue
|
||||
$sshcmd = (get-command ssh).Path
|
||||
|
||||
$server = $OpenSSHTestInfo["Target"]
|
||||
$port = $OpenSSHTestInfo["Port"]
|
||||
$ssouser = $OpenSSHTestInfo["SSOUser"]
|
||||
$script:logNum = 0
|
||||
|
||||
$testData = @(
|
||||
@ -32,31 +41,37 @@ Describe "Tests for scp command" -Tags "CI" {
|
||||
Title = 'Simple copy local file to local file'
|
||||
Source = $SourceFilePath
|
||||
Destination = $DestinationFilePath
|
||||
Options = "-P $port "
|
||||
},
|
||||
@{
|
||||
Title = 'Simple copy local file to remote file'
|
||||
Source = $SourceFilePath
|
||||
Destination = "$($server.localAdminUserName)@$($server.MachineName):$DestinationFilePath"
|
||||
Destination = "$($ssouser)@$($server):$DestinationFilePath"
|
||||
Options = "-P $port -S $sshcmd"
|
||||
},
|
||||
@{
|
||||
Title = 'Simple copy remote file to local file'
|
||||
Source = "$($server.localAdminUserName)@$($server.MachineName):$SourceFilePath"
|
||||
Destination = $DestinationFilePath
|
||||
Source = "$($ssouser)@$($server):$SourceFilePath"
|
||||
Destination = $DestinationFilePath
|
||||
Options = "-P $port -p -c aes128-ctr -C"
|
||||
},
|
||||
@{
|
||||
Title = 'Simple copy local file to local dir'
|
||||
Source = $SourceFilePath
|
||||
Destination = $DestinationDir
|
||||
Options = "-P $port "
|
||||
},
|
||||
@{
|
||||
Title = 'simple copy local file to remote dir'
|
||||
Source = $SourceFilePath
|
||||
Destination = "$($server.localAdminUserName)@$($server.MachineName):$DestinationDir"
|
||||
Destination = "$($ssouser)@$($server):$DestinationDir"
|
||||
Options = "-P $port -C -q"
|
||||
},
|
||||
@{
|
||||
Title = 'simple copy remote file to local dir'
|
||||
Source = "$($server.localAdminUserName)@$($server.MachineName):$SourceFilePath"
|
||||
Source = "$($ssouser)@$($server):$SourceFilePath"
|
||||
Destination = $DestinationDir
|
||||
Options = "-P $port "
|
||||
}
|
||||
)
|
||||
|
||||
@ -64,27 +79,45 @@ Describe "Tests for scp command" -Tags "CI" {
|
||||
@{
|
||||
Title = 'copy from local dir to remote dir'
|
||||
Source = $sourceDir
|
||||
Destination = "$($server.localAdminUserName)@$($server.MachineName):$DestinationDir"
|
||||
Destination = "$($ssouser)@$($server):$DestinationDir"
|
||||
Options = "-P $port -r -p -c aes128-ctr"
|
||||
},
|
||||
<# @{
|
||||
@{
|
||||
Title = 'copy from local dir to local dir'
|
||||
Source = $sourceDir
|
||||
Destination = $DestinationDir
|
||||
},#>
|
||||
Options = "-r "
|
||||
},
|
||||
@{
|
||||
Title = 'copy from remote dir to local dir'
|
||||
Source = "$($server.localAdminUserName)@$($server.MachineName):$sourceDir"
|
||||
Source = "$($ssouser)@$($server):$sourceDir"
|
||||
Destination = $DestinationDir
|
||||
Options = "-P $port -C -r -q"
|
||||
}
|
||||
)
|
||||
|
||||
# for the first time, delete the existing log files.
|
||||
if ($OpenSSHTestInfo['DebugMode'])
|
||||
{
|
||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore
|
||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore
|
||||
}
|
||||
|
||||
function CheckTarget {
|
||||
param([string]$target)
|
||||
if(-not (Test-path $target))
|
||||
{
|
||||
Copy-Item .\logs\ssh-agent.log ".\logs\failedagent$script:logNum.log" -Force
|
||||
Copy-Item .\logs\sshd.log ".\logs\failedsshd$script:logNum.log" -Force
|
||||
$script:logNum++
|
||||
{
|
||||
if( $OpenSSHTestInfo["DebugMode"])
|
||||
{
|
||||
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\failedagent$script:logNum.log" -Force
|
||||
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\failedsshd$script:logNum.log" -Force
|
||||
|
||||
$script:logNum++
|
||||
|
||||
# clear the ssh-agent, sshd logs so that next testcase will get fresh logs.
|
||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore
|
||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore
|
||||
}
|
||||
|
||||
return $false
|
||||
}
|
||||
@ -93,11 +126,21 @@ Describe "Tests for scp command" -Tags "CI" {
|
||||
}
|
||||
AfterAll {
|
||||
|
||||
$client.CleanupClient()
|
||||
$server.CleanupServer()
|
||||
|
||||
Get-Item $SourceDir | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
||||
Get-Item $DestinationDir | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
||||
if($OpenSSHTestInfo -eq $null)
|
||||
{
|
||||
#do nothing
|
||||
}
|
||||
elseif( -not $OpenSSHTestInfo['DebugMode'])
|
||||
{
|
||||
if(-not [string]::IsNullOrEmpty($SourceDir))
|
||||
{
|
||||
Get-Item $SourceDir | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
if(-not [string]::IsNullOrEmpty($DestinationDir))
|
||||
{
|
||||
Get-Item $DestinationDir | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BeforeAll {
|
||||
@ -106,170 +149,50 @@ Describe "Tests for scp command" -Tags "CI" {
|
||||
|
||||
AfterEach {
|
||||
Get-ChildItem $DestinationDir -Recurse | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
<#Context "SCP usage" {
|
||||
It 'SCP usage' {
|
||||
#TODO: usage output does not redirect to file
|
||||
}
|
||||
}#>
|
||||
}
|
||||
|
||||
Context "Key is Secured in ssh-agent on server" {
|
||||
BeforeAll {
|
||||
$Server.SecureHostKeys($server.PrivateHostKeyPaths)
|
||||
$privateKeyFile = $client.clientPrivateKeyPaths[0]
|
||||
}
|
||||
BeforeEach {
|
||||
if ($env:DebugMode)
|
||||
{
|
||||
Stop-Service ssh-agent -Force
|
||||
Start-Sleep 2
|
||||
Remove-Item .\logs\ssh-agent.log -Force -ErrorAction ignore
|
||||
Remove-Item .\logs\sshd.log -Force -ErrorAction ignore
|
||||
Start-Service sshd
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
$Server.CleanupHostKeys()
|
||||
}
|
||||
|
||||
It 'File copy with -i option and private key: <Title> ' -TestCases:$testData {
|
||||
param([string]$Title, $Source, $Destination)
|
||||
.\scp -i $privateKeyFile $Source $Destination
|
||||
$LASTEXITCODE | Should Be 0
|
||||
|
||||
#validate file content. DestPath is the path to the file.
|
||||
CheckTarget -target $DestinationFilePath | Should Be $true
|
||||
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
}
|
||||
|
||||
It 'Directory recursive copy with -i option and private key: <Title> ' -TestCases:$testData1 {
|
||||
param([string]$Title, $Source, $Destination)
|
||||
|
||||
.\scp -r -i $privateKeyFile $Source $Destination
|
||||
$LASTEXITCODE | Should Be 0
|
||||
CheckTarget -target (join-path $DestinationDir $SourceDirName) | Should Be $true
|
||||
It 'File copy: <Title> ' -TestCases:$testData {
|
||||
param([string]$Title, $Source, $Destination, $Options)
|
||||
|
||||
$equal = @(Compare-Object (Get-Item -path $SourceDir ) (Get-Item -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
|
||||
$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
}
|
||||
}
|
||||
|
||||
Context "Single signon with keys -p -v -c option Secured in ssh-agent" {
|
||||
BeforeAll {
|
||||
$Server.SecureHostKeys($server.PrivateHostKeyPaths)
|
||||
$identifyFile = $client.clientPrivateKeyPaths[0]
|
||||
#setup single signon
|
||||
.\ssh-add.exe $identifyFile
|
||||
}
|
||||
iex "scp $Options $Source $Destination"
|
||||
$LASTEXITCODE | Should Be 0
|
||||
#validate file content. DestPath is the path to the file.
|
||||
CheckTarget -target $DestinationFilePath | Should Be $true
|
||||
|
||||
AfterAll {
|
||||
$Server.CleanupHostKeys()
|
||||
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length ).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
|
||||
#cleanup single signon
|
||||
.\ssh-add.exe -D
|
||||
}
|
||||
|
||||
It 'File copy with -S -v option (positive)' {
|
||||
.\scp -S .\ssh.exe -v $SourceFilePath "$($server.localAdminUserName)@$($server.MachineName):$DestinationFilePath"
|
||||
$LASTEXITCODE | Should Be 0
|
||||
#validate file content. DestPath is the path to the file.
|
||||
CheckTarget -target $DestinationFilePath | Should Be $true
|
||||
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length).Length -eq 0
|
||||
if($Options.contains("-p"))
|
||||
{
|
||||
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath).LastWriteTime.DateTime (Get-ChildItem -path $DestinationFilePath).LastWriteTime.DateTime ).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
}
|
||||
|
||||
It 'File copy with -p -c option: <Title> ' -TestCases:$testData {
|
||||
param([string]$Title, $Source, $Destination)
|
||||
|
||||
.\scp -p -c aes128-ctr -C $Source $Destination
|
||||
$LASTEXITCODE | Should Be 0
|
||||
#validate file content. DestPath is the path to the file.
|
||||
CheckTarget -target $DestinationFilePath | Should Be $true
|
||||
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length, LastWriteTime.DateTime).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
}
|
||||
}
|
||||
|
||||
It 'Directory recursive copy with -r -p -c option: <Title> ' -TestCases:$testData1 {
|
||||
param([string]$Title, $Source, $Destination)
|
||||
It 'Directory recursive copy: <Title> ' -TestCases:$testData1 {
|
||||
param([string]$Title, $Source, $Destination, $Options)
|
||||
|
||||
.\scp -r -p -c aes128-ctr $Source $Destination
|
||||
$LASTEXITCODE | Should Be 0
|
||||
CheckTarget -target (join-path $DestinationDir $SourceDirName) | Should Be $true
|
||||
$equal = @(Compare-Object (Get-Item -path $SourceDir ) (Get-Item -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length, LastWriteTime.DateTime).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
|
||||
$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length, LastWriteTime.DateTime).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
}
|
||||
}
|
||||
|
||||
Context "Private key authentication with -i -C -q options. host keys are not secured on server" {
|
||||
BeforeAll {
|
||||
$identifyFile = $client.clientPrivateKeyPaths[0]
|
||||
}
|
||||
|
||||
It 'File copy with -i -C -q options: <Title> ' -TestCases:$testData{
|
||||
param([string]$Title, $Source, $Destination)
|
||||
iex "scp $Options $Source $Destination"
|
||||
$LASTEXITCODE | Should Be 0
|
||||
CheckTarget -target (join-path $DestinationDir $SourceDirName) | Should Be $true
|
||||
|
||||
.\scp -i $identifyFile -C -q $Source $Destination
|
||||
$LASTEXITCODE | Should Be 0
|
||||
#validate file content. DestPath is the path to the file.
|
||||
CheckTarget -target $DestinationFilePath | Should Be $true
|
||||
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length).Length -eq 0
|
||||
$equal = @(Compare-Object (Get-Item -path $SourceDir ) (Get-Item -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
|
||||
if($Options.contains("-p"))
|
||||
{
|
||||
$equal = @(Compare-Object (Get-Item -path $SourceDir).LastWriteTime.DateTime (Get-Item -path (join-path $DestinationDir $SourceDirName)).LastWriteTime.DateTime).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
}
|
||||
|
||||
It 'Directory recursive copy with -i -C -r and -q options: <Title> ' -TestCases:$testData1 {
|
||||
param([string]$Title, $Source, $Destination)
|
||||
$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
|
||||
.\scp -i $identifyFile -C -r -q $Source $Destination
|
||||
$LASTEXITCODE | Should Be 0
|
||||
CheckTarget -target (join-path $DestinationDir $SourceDirName) | Should Be $true
|
||||
$equal = @(Compare-Object (Get-Item -path $SourceDir ) (Get-Item -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
|
||||
if($Options.contains("-p"))
|
||||
{
|
||||
$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir).LastWriteTime.DateTime (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ).LastWriteTime.DateTime).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
|
||||
$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
}
|
||||
}
|
||||
|
||||
Context "Password authentication" {
|
||||
BeforeAll {
|
||||
$client.AddPasswordSetting($server.localAdminPassword)
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
$client.CleanupPasswordSetting()
|
||||
}
|
||||
|
||||
It 'File copy with -p options: <Title> ' -TestCases:$testData {
|
||||
param([string]$Title, $Source, $Destination)
|
||||
|
||||
.\scp -p $Source $Destination
|
||||
$LASTEXITCODE | Should Be 0
|
||||
#validate file content. DestPath is the path to the file.
|
||||
CheckTarget -target $DestinationFilePath | Should Be $true
|
||||
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length, LastWriteTime.DateTime).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
}
|
||||
|
||||
It 'Directory recursive copy with -p and -v options: <Title> ' -TestCases:$testData1 {
|
||||
param([string]$Title, $Source, $Destination)
|
||||
|
||||
.\scp -r -p $Source $Destination
|
||||
$LASTEXITCODE | Should Be 0
|
||||
CheckTarget -target (join-path $DestinationDir $SourceDirName) | Should Be $true
|
||||
$equal = @(Compare-Object (Get-Item -path $SourceDir ) (Get-Item -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length, LastWriteTime.DateTime).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
|
||||
$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length, LastWriteTime.DateTime).Length -eq 0
|
||||
$equal | Should Be $true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,75 +1,80 @@
|
||||
using module .\PlatformAbstractLayer.psm1
|
||||
|
||||
Describe "SFTP Testcases" -Tags "CI" {
|
||||
Describe "SFTP Test Cases" -Tags "CI" {
|
||||
BeforeAll {
|
||||
$rootDirectory = $TestDrive
|
||||
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
|
||||
}
|
||||
|
||||
$rootDirectory = "$($OpenSSHTestInfo["TestDataPath"])\SFTP"
|
||||
|
||||
$outputFileName = "output.txt"
|
||||
$batchFileName = "sftp-batchcmds.txt"
|
||||
$outputFilePath = Join-Path $rootDirectory $outputFileName
|
||||
$batchFilePath = Join-Path $rootDirectory $batchFileName
|
||||
|
||||
|
||||
$tempFileName = "tempFile.txt"
|
||||
$tempFilePath = Join-Path $rootDirectory $tempFileName
|
||||
|
||||
|
||||
$tempUnicodeFileName = "tempFile_язык.txt"
|
||||
$tempUnicodeFilePath = Join-Path $rootDirectory $tempUnicodeFileName
|
||||
|
||||
|
||||
$clientDirectory = Join-Path $rootDirectory 'client_dir'
|
||||
$serverDirectory = Join-Path $rootDirectory 'server_dir'
|
||||
|
||||
|
||||
$null = New-Item $clientDirectory -ItemType directory -Force
|
||||
$null = New-Item $serverDirectory -ItemType directory -Force
|
||||
$null = New-Item $batchFilePath -ItemType file -Force
|
||||
$null = New-Item $outputFilePath -ItemType file -Force
|
||||
$null = New-Item $tempFilePath -ItemType file -Force -value "temp file data"
|
||||
$null = New-Item $tempUnicodeFilePath -ItemType file -Force -value "temp file data"
|
||||
|
||||
$expectedOutputDelimiter = "#DL$"
|
||||
|
||||
[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"]
|
||||
$script:testId = 1
|
||||
|
||||
$testData1 = @(
|
||||
@{
|
||||
title = "put, ls for non-unicode file names"
|
||||
logonstr = "$($server.localadminusername)@$($server.machinename)"
|
||||
options = '-i $identifyfile'
|
||||
logonstr = "$($ssouser)@$($server)"
|
||||
options = ''
|
||||
commands = "put $tempFilePath $serverDirectory
|
||||
ls $serverDirectory"
|
||||
expectedoutput = (join-path $serverdirectory $tempFileName)
|
||||
|
||||
},
|
||||
@{
|
||||
title = "get, ls for non-unicode file names"
|
||||
logonstr = "$($server.localadminusername)@$($server.machinename)"
|
||||
options = '-i $identifyfile'
|
||||
logonstr = "$($ssouser)@$($server)"
|
||||
options = ''
|
||||
commands = "get $tempFilePath $clientDirectory
|
||||
ls $clientDirectory"
|
||||
expectedoutput = (join-path $clientDirectory $tempFileName)
|
||||
},
|
||||
@{
|
||||
title = "mput, ls for non-unicode file names"
|
||||
logonstr = "$($server.localadminusername)@$($server.machinename)"
|
||||
options = '-i $identifyfile'
|
||||
logonstr = "$($ssouser)@$($server)"
|
||||
options = ''
|
||||
commands = "mput $tempFilePath $serverDirectory
|
||||
ls $serverDirectory"
|
||||
expectedoutput = (join-path $serverdirectory $tempFileName)
|
||||
},
|
||||
@{
|
||||
title = "mget, ls for non-unicode file names"
|
||||
logonstr = "$($server.localadminusername)@$($server.machinename)"
|
||||
options = '-i $identifyfile'
|
||||
logonstr = "$($ssouser)@$($server)"
|
||||
options = ''
|
||||
commands = "mget $tempFilePath $clientDirectory
|
||||
ls $clientDirectory"
|
||||
expectedoutput = (join-path $clientDirectory $tempFileName)
|
||||
},
|
||||
@{
|
||||
title = "mkdir, cd, pwd for non-unicode directory names"
|
||||
logonstr = "$($server.localadminusername)@$($server.machinename)"
|
||||
options = '-i $identifyfile'
|
||||
logonstr = "$($ssouser)@$($server)"
|
||||
options = ''
|
||||
commands = "cd $serverdirectory
|
||||
mkdir server_test_dir
|
||||
cd server_test_dir
|
||||
@ -78,8 +83,8 @@ Describe "SFTP Testcases" -Tags "CI" {
|
||||
},
|
||||
@{
|
||||
Title = "lmkdir, lcd, lpwd for non-unicode directory names"
|
||||
LogonStr = "$($server.localAdminUserName)@$($server.MachineName)"
|
||||
Options = '-i $identifyFile'
|
||||
LogonStr = "$($ssouser)@$($server)"
|
||||
Options = ''
|
||||
Commands = "lcd $clientDirectory
|
||||
lmkdir client_test_dir
|
||||
lcd client_test_dir
|
||||
@ -88,40 +93,40 @@ Describe "SFTP Testcases" -Tags "CI" {
|
||||
},
|
||||
@{
|
||||
title = "put, ls for unicode file names"
|
||||
logonstr = "$($server.localadminusername)@$($server.machinename)"
|
||||
options = '-i $identifyfile'
|
||||
logonstr = "$($ssouser)@$($server)"
|
||||
options = ''
|
||||
commands = "put $tempUnicodeFilePath $serverDirectory
|
||||
ls $serverDirectory"
|
||||
expectedoutput = (join-path $serverdirectory $tempUnicodeFileName)
|
||||
},
|
||||
@{
|
||||
title = "get, ls for unicode file names"
|
||||
logonstr = "$($server.localadminusername)@$($server.machinename)"
|
||||
options = '-i $identifyfile'
|
||||
logonstr = "$($ssouser)@$($server)"
|
||||
options = ''
|
||||
commands = "get $tempUnicodeFilePath $clientDirectory
|
||||
ls $clientDirectory"
|
||||
expectedoutput = (join-path $clientDirectory $tempUnicodeFileName)
|
||||
},
|
||||
@{
|
||||
title = "mput, ls for unicode file names"
|
||||
logonstr = "$($server.localadminusername)@$($server.machinename)"
|
||||
options = '-i $identifyfile'
|
||||
logonstr = "$($ssouser)@$($server)"
|
||||
options = ''
|
||||
commands = "mput $tempUnicodeFilePath $serverDirectory
|
||||
ls $serverDirectory"
|
||||
expectedoutput = (join-path $serverdirectory $tempUnicodeFileName)
|
||||
},
|
||||
@{
|
||||
title = "mget, ls for unicode file names"
|
||||
logonstr = "$($server.localadminusername)@$($server.machinename)"
|
||||
options = '-i $identifyfile'
|
||||
logonstr = "$($ssouser)@$($server)"
|
||||
options = ''
|
||||
commands = "mget $tempUnicodeFilePath $clientDirectory
|
||||
ls $clientDirectory"
|
||||
expectedoutput = (join-path $clientDirectory $tempUnicodeFileName)
|
||||
},
|
||||
@{
|
||||
title = "mkdir, cd, pwd for unicode directory names"
|
||||
logonstr = "$($server.localadminusername)@$($server.machinename)"
|
||||
options = '-i $identifyfile'
|
||||
logonstr = "$($ssouser)@$($server)"
|
||||
options = ''
|
||||
commands = "cd $serverdirectory
|
||||
mkdir server_test_dir_язык
|
||||
cd server_test_dir_язык
|
||||
@ -130,8 +135,8 @@ Describe "SFTP Testcases" -Tags "CI" {
|
||||
},
|
||||
@{
|
||||
Title = "lmkdir, lcd, lpwd for unicode directory names"
|
||||
LogonStr = "$($server.localAdminUserName)@$($server.MachineName)"
|
||||
Options = '-i $identifyFile'
|
||||
LogonStr = "$($ssouser)@$($server)"
|
||||
Options = ''
|
||||
Commands = "lcd $clientDirectory
|
||||
lmkdir client_test_dir_язык
|
||||
lcd client_test_dir_язык
|
||||
@ -144,8 +149,8 @@ Describe "SFTP Testcases" -Tags "CI" {
|
||||
$testData2 = @(
|
||||
@{
|
||||
title = "rm, rmdir, rename for unicode file, directory"
|
||||
logonstr = "$($server.localadminusername)@$($server.machinename)"
|
||||
options = '-i $identifyfile -b $batchFilePath'
|
||||
logonstr = "$($ssouser)@$($server)"
|
||||
options = '-b $batchFilePath'
|
||||
|
||||
tmpFileName1 = $tempUnicodeFileName
|
||||
tmpFilePath1 = $tempUnicodeFilePath
|
||||
@ -159,8 +164,8 @@ Describe "SFTP Testcases" -Tags "CI" {
|
||||
},
|
||||
@{
|
||||
title = "rm, rmdir, rename for non-unicode file, directory"
|
||||
logonstr = "$($server.localadminusername)@$($server.machinename)"
|
||||
options = '-i $identifyfile -b $batchFilePath'
|
||||
logonstr = "$($ssouser)@$($server)"
|
||||
options = '-b $batchFilePath'
|
||||
|
||||
tmpFileName1 = $tempFileName
|
||||
tmpFilePath1 = $tempFilePath
|
||||
@ -173,96 +178,110 @@ Describe "SFTP Testcases" -Tags "CI" {
|
||||
tmpDirectoryPath2 = (join-path $serverDirectory "test_dir_2")
|
||||
}
|
||||
)
|
||||
|
||||
# for the first time, delete the existing log files.
|
||||
if ($OpenSSHTestInfo['DebugMode'])
|
||||
{
|
||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore
|
||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore
|
||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction ignore
|
||||
}
|
||||
|
||||
function CopyDebugLogs {
|
||||
if($OpenSSHTestInfo["DebugMode"])
|
||||
{
|
||||
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent_$script:testId.log" -Force
|
||||
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd_$script:testId.log" -Force
|
||||
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server_$script:testId.log" -Force
|
||||
|
||||
$script:testId++
|
||||
|
||||
# clear the ssh-agent, sshd logs so that next testcase will get fresh logs.
|
||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore
|
||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore
|
||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
$client.CleanupClient()
|
||||
$server.CleanupServer()
|
||||
}
|
||||
|
||||
Context "Single signon" {
|
||||
BeforeAll {
|
||||
$Server.SecureHostKeys($server.PrivateHostKeyPaths)
|
||||
$identifyFile = $client.clientPrivateKeyPaths[0]
|
||||
.\ssh-add.exe $identifyFile #setup single signon
|
||||
}
|
||||
AfterAll {
|
||||
$Server.CleanupHostKeys()
|
||||
.\ssh-add.exe -D #cleanup single signon
|
||||
|
||||
if(!$OpenSSHTestInfo["DebugMode"])
|
||||
{
|
||||
Get-Item $rootDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
BeforeEach {
|
||||
Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
||||
Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
||||
Remove-Item $batchFilePath
|
||||
Remove-Item $outputFilePath
|
||||
}
|
||||
|
||||
It '<Title>' -TestCases:$testData1 {
|
||||
param([string]$Title, $LogonStr, $Options, $Commands, $ExpectedOutput, $SkipVerification = $false)
|
||||
|
||||
Set-Content $batchFilePath -Encoding UTF8 -value $Commands
|
||||
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) -b $batchFilePath $($LogonStr) > $outputFilePath")
|
||||
$client.RunCmd($str)
|
||||
BeforeEach {
|
||||
Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
||||
Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
||||
Remove-Item $batchFilePath
|
||||
Remove-Item $outputFilePath
|
||||
}
|
||||
|
||||
#validate file content.
|
||||
$($ExpectedOutput).split($expectedOutputDelimiter) | foreach {
|
||||
Test-Path ($_) | Should be $true
|
||||
}
|
||||
}
|
||||
|
||||
It '<Title>' -TestCases:$testData2 {
|
||||
param([string]$Title, $LogonStr, $Options, $tmpFileName1, $tmpFilePath1, $tmpFileName2, $tmpFilePath2, $tmpDirectoryName1, $tmpDirectoryPath1, $tmpDirectoryName2, $tmpDirectoryPath2, $SkipVerification = $false)
|
||||
|
||||
#rm (remove file)
|
||||
$commands = "mkdir $tmpDirectoryPath1
|
||||
put $tmpFilePath1 $tmpDirectoryPath1
|
||||
ls $tmpDirectoryPath1"
|
||||
Set-Content $batchFilePath -Encoding UTF8 -value $commands
|
||||
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) $($LogonStr) > $outputFilePath")
|
||||
$client.RunCmd($str)
|
||||
Test-Path (join-path $tmpDirectoryPath1 $tmpFileName1) | Should be $true
|
||||
|
||||
$commands = "rm $tmpDirectoryPath1\*
|
||||
ls $tmpDirectoryPath1
|
||||
pwd
|
||||
"
|
||||
Set-Content $batchFilePath -Encoding UTF8 -value $commands
|
||||
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) $($LogonStr) > $outputFilePath")
|
||||
$client.RunCmd($str)
|
||||
Test-Path (join-path $tmpDirectoryPath1 $tmpFileName1) | Should be $false
|
||||
|
||||
#rename file
|
||||
Remove-Item $outputFilePath
|
||||
Copy-Item $tmpFilePath1 -destination $tmpDirectoryPath1
|
||||
$commands = "rename $tmpDirectoryPath1\$tmpFileName1 $tmpDirectoryPath1\$tmpFileName2
|
||||
ls $tmpDirectoryPath1
|
||||
pwd"
|
||||
Set-Content $batchFilePath -Encoding UTF8 -value $commands
|
||||
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) $($LogonStr) > $outputFilePath")
|
||||
$client.RunCmd($str)
|
||||
Test-Path (join-path $tmpDirectoryPath1 $tmpFileName2) | Should be $true
|
||||
|
||||
#rename directory
|
||||
Remove-Item $outputFilePath
|
||||
$commands = "rm $tmpDirectoryPath1\*
|
||||
rename $tmpDirectoryPath1 $tmpDirectoryPath2
|
||||
ls $serverDirectory"
|
||||
Set-Content $batchFilePath -Encoding UTF8 -value $commands
|
||||
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) $($LogonStr) > $outputFilePath")
|
||||
$client.RunCmd($str)
|
||||
Test-Path $tmpDirectoryPath2 | Should be $true
|
||||
|
||||
#rmdir (remove directory)
|
||||
Remove-Item $outputFilePath
|
||||
$commands = "rmdir $tmpDirectoryPath2
|
||||
ls $serverDirectory"
|
||||
Set-Content $batchFilePath -Encoding UTF8 -value $commands
|
||||
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) $($LogonStr) > $outputFilePath")
|
||||
$client.RunCmd($str)
|
||||
Test-Path $tmpDirectoryPath2 | Should be $false
|
||||
}
|
||||
AfterEach {
|
||||
CopyDebugLogs
|
||||
}
|
||||
|
||||
It '<Title>' -TestCases:$testData1 {
|
||||
param([string]$Title, $LogonStr, $Options, $Commands, $ExpectedOutput)
|
||||
|
||||
Set-Content $batchFilePath -Encoding UTF8 -value $Commands
|
||||
$str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) -b $batchFilePath $($LogonStr) > $outputFilePath")
|
||||
iex $str
|
||||
|
||||
#validate file content.
|
||||
Test-Path $ExpectedOutput | Should be $true
|
||||
}
|
||||
|
||||
It '<Title>' -TestCases:$testData2 {
|
||||
param([string]$Title, $LogonStr, $Options, $tmpFileName1, $tmpFilePath1, $tmpFileName2, $tmpFilePath2, $tmpDirectoryName1, $tmpDirectoryPath1, $tmpDirectoryName2, $tmpDirectoryPath2)
|
||||
|
||||
#rm (remove file)
|
||||
$commands = "mkdir $tmpDirectoryPath1
|
||||
put $tmpFilePath1 $tmpDirectoryPath1
|
||||
ls $tmpDirectoryPath1"
|
||||
Set-Content $batchFilePath -Encoding UTF8 -value $commands
|
||||
$str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) $($LogonStr) > $outputFilePath")
|
||||
iex $str
|
||||
Test-Path (join-path $tmpDirectoryPath1 $tmpFileName1) | Should be $true
|
||||
|
||||
$commands = "rm $tmpDirectoryPath1\*
|
||||
ls $tmpDirectoryPath1
|
||||
pwd
|
||||
"
|
||||
Set-Content $batchFilePath -Encoding UTF8 -value $commands
|
||||
$str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) $($LogonStr) > $outputFilePath")
|
||||
iex $str
|
||||
Test-Path (join-path $tmpDirectoryPath1 $tmpFileName1) | Should be $false
|
||||
|
||||
#rename file
|
||||
Remove-Item $outputFilePath
|
||||
Copy-Item $tmpFilePath1 -destination $tmpDirectoryPath1
|
||||
$commands = "rename $tmpDirectoryPath1\$tmpFileName1 $tmpDirectoryPath1\$tmpFileName2
|
||||
ls $tmpDirectoryPath1
|
||||
pwd"
|
||||
Set-Content $batchFilePath -Encoding UTF8 -value $commands
|
||||
$str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) $($LogonStr) > $outputFilePath")
|
||||
iex $str
|
||||
Test-Path (join-path $tmpDirectoryPath1 $tmpFileName2) | Should be $true
|
||||
|
||||
#rename directory
|
||||
Remove-Item $outputFilePath
|
||||
$commands = "rm $tmpDirectoryPath1\*
|
||||
rename $tmpDirectoryPath1 $tmpDirectoryPath2
|
||||
ls $serverDirectory"
|
||||
Set-Content $batchFilePath -Encoding UTF8 -value $commands
|
||||
$str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) $($LogonStr) > $outputFilePath")
|
||||
iex $str
|
||||
Test-Path $tmpDirectoryPath2 | Should be $true
|
||||
|
||||
#rmdir (remove directory)
|
||||
Remove-Item $outputFilePath
|
||||
$commands = "rmdir $tmpDirectoryPath2
|
||||
ls $serverDirectory"
|
||||
Set-Content $batchFilePath -Encoding UTF8 -value $commands
|
||||
$str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) $($LogonStr) > $outputFilePath")
|
||||
iex $str
|
||||
Test-Path $tmpDirectoryPath2 | Should be $false
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
using module .\PlatformAbstractLayer.psm1
|
||||
|
||||
#covered -i -q -v -l -c -C
|
||||
#covered -i -q -v -l -c -C
|
||||
#todo: -S -F -V -e
|
||||
Describe "Tests for ssh command" -Tags "CI" {
|
||||
Describe "Tests for ssh command" -Tags "Scenario" {
|
||||
BeforeAll {
|
||||
$fileName = "test.txt"
|
||||
$filePath = Join-Path ${TestDrive} $fileName
|
||||
|
@ -1,6 +1,4 @@
|
||||
using module .\PlatformAbstractLayer.psm1
|
||||
|
||||
Describe "Tests of sshd_config" -Tags "CI" {
|
||||
Describe "Tests of sshd_config" -Tags "Scenario" {
|
||||
BeforeAll {
|
||||
$fileName = "test.txt"
|
||||
$filePath = Join-Path ${TestDrive} $fileName
|
||||
|
@ -10,7 +10,7 @@
|
||||
# possible, but leave them commented. Uncommented options override the
|
||||
# default value.
|
||||
|
||||
#Port 22
|
||||
Port 47002
|
||||
#AddressFamily any
|
||||
#ListenAddress 0.0.0.0
|
||||
#ListenAddress ::
|
||||
@ -21,9 +21,10 @@
|
||||
# HostKey for protocol version 1
|
||||
#HostKey /etc/ssh/ssh_host_key
|
||||
# HostKeys for protocol version 2
|
||||
#HostKey /etc/ssh/ssh_host_rsa_key
|
||||
#HostKey /etc/ssh/ssh_host_dsa_key
|
||||
#HostKey /etc/ssh/ssh_host_ecdsa_key
|
||||
HostKey sshtest_hostkey_rsa
|
||||
HostKey sshtest_hostkey_dsa
|
||||
HostKey sshtest_hostkey_ecdsa
|
||||
HostKey sshtest_hostkey_ed25519
|
||||
|
||||
# Lifetime and size of ephemeral version 1 server key
|
||||
#KeyRegenerationInterval 1h
|
||||
@ -112,7 +113,7 @@ AuthorizedKeysFile .ssh/authorized_keys
|
||||
#Banner none
|
||||
|
||||
# override default of no subsystems
|
||||
Subsystem sftp sftp-server.exe
|
||||
Subsystem sftp sftp-server.exe -l DEBUG3
|
||||
|
||||
# Example of overriding settings on a per-user basis
|
||||
#Match User anoncvs
|
||||
@ -121,7 +122,7 @@ Subsystem sftp sftp-server.exe
|
||||
# ForceCommand cvs server
|
||||
PubkeyAcceptedKeyTypes ssh-ed25519*
|
||||
|
||||
DenyUsers denyuser1 deny*2 denyuse?3,
|
||||
AllowUsers allowuser1 allowu*r2 allow?se?3 allowuser4 localuser1 localu*r2 loc?lu?er3 localadmin
|
||||
DenyGroups denygroup1 denygr*p2 deny?rou?3
|
||||
AllowGroups allowgroup1 allowg*2 allowg?ou?3 Adm*
|
||||
#DenyUsers denyuser1 deny*2 denyuse?3,
|
||||
#AllowUsers allowuser1 allowu*r2 allow?se?3 allowuser4 localuser1 localu*r2 loc?lu?er3 localadmin
|
||||
#DenyGroups denygroup1 denygr*p2 deny?rou?3
|
||||
#AllowGroups allowgroup1 allowg*2 allowg?ou?3 Adm*
|
4
regress/pesterTests/known_hosts
Normal file
4
regress/pesterTests/known_hosts
Normal file
@ -0,0 +1,4 @@
|
||||
[localhost]:47002 ssh-dss AAAAB3NzaC1kc3MAAACBAIyVGPwSzaCedtroufmFrwXGVPzYUMHPePvlduORG2+1VmLkP2Yw+U6MHRnaDyDriCulhnmwIueGxhH+t0HKbGK0j7XpGnwgmFOBIg5gJwQTDJ+gX+qC2ju55WB0Gkkwl+xktnAFSqmj8ttSzUBhh1ksh5A6oW+NKjwEVH8tQExFAAAAFQC0YldxCDQbTuDO04EVgA0OMpDIvwAAAIBXWRzpoyQWNoB18DGbY9zupGhfwuKGmnlj2mY0aYxY3qu1+9ciQOBrwYJlf4dEJbirwp2XmKzHZ6LFrkLQptVcD1wDkG/a/wMRvh+tbxlq45S3Eh0oNj1cobhUlFm9m5PM2HW1LccbOAEBUG/L4Vcj1Ag4n639H0fwDRL+rwOpjgAAAIBh/fSBidBGsQITgg45wwDszk7AAhngNm+jbiea8dbgYP6wpT6dJdg3pYwKT0V/PdXTSDi16kkoMkbUsMZyxyFJf/TtmCtBnon55yL9+H5dtcOBF8BXR7KzQX1E1n0eIL9jZ0Q4BspkB4LKQXhxRnrNJlv/oopxXua/GCMW17xxuA== sshtest_hostkey_dsa
|
||||
[localhost]:47002 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHF2eWwgnaUSLNNN0ilxiT916uMa6lusMB31AxfkDGArh4xCWL0e3F/gRifRephM0cD2dSh8Ji6VnjkhvZptjEw= sshtest_hostkey_ecdsa
|
||||
[localhost]:47002 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMtJMxwn+iJU0X4+EC7PSj/cfcMbdP6ahhodtXx+6RHv sshtest_hostkey_ed25519
|
||||
[localhost]:47002 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDU+NcQ5NuRutQJoZVjDmP/vE6IYZOaE59FTUjaoZkuPl4prdOPgqAnCwSy9XtnfzPm/oe62SyYIHgj8wRzhqjMU8g8aGqfv9ryF+hpNXZrFYXIdkdxnubzfb4e70RRRoTH8P5vuY8sAn0FIRlV/3EDkSKBFy2W3InMTO6l8gbkzzkgbn1GLvH06QJVdb2PcHksSn7dJBVHWASYi3TJWWu4muI+ZNfothujxAHqjKTJuJ9apDZIc0tnkPmlifRmolSUS4OAH2KWZ+5Gwaj7gsB8bk4QuA+QCT60OCcuzCcy4FBuXvvXkM9MBe/P2KZjVLAn86SriRtoE4RI+9R9S7DV sshtest_hostkey_rsa
|
12
regress/pesterTests/sshtest_hostkey_dsa
Normal file
12
regress/pesterTests/sshtest_hostkey_dsa
Normal file
@ -0,0 +1,12 @@
|
||||
-----BEGIN DSA PRIVATE KEY-----
|
||||
MIIBuwIBAAKBgQCMlRj8Es2gnnba6Ln5ha8FxlT82FDBz3j75XbjkRtvtVZi5D9m
|
||||
MPlOjB0Z2g8g64grpYZ5sCLnhsYR/rdBymxitI+16Rp8IJhTgSIOYCcEEwyfoF/q
|
||||
gto7ueVgdBpJMJfsZLZwBUqpo/LbUs1AYYdZLIeQOqFvjSo8BFR/LUBMRQIVALRi
|
||||
V3EINBtO4M7TgRWADQ4ykMi/AoGAV1kc6aMkFjaAdfAxm2Pc7qRoX8Lihpp5Y9pm
|
||||
NGmMWN6rtfvXIkDga8GCZX+HRCW4q8Kdl5isx2eixa5C0KbVXA9cA5Bv2v8DEb4f
|
||||
rW8ZauOUtxIdKDY9XKG4VJRZvZuTzNh1tS3HGzgBAVBvy+FXI9QIOJ+t/R9H8A0S
|
||||
/q8DqY4CgYBh/fSBidBGsQITgg45wwDszk7AAhngNm+jbiea8dbgYP6wpT6dJdg3
|
||||
pYwKT0V/PdXTSDi16kkoMkbUsMZyxyFJf/TtmCtBnon55yL9+H5dtcOBF8BXR7Kz
|
||||
QX1E1n0eIL9jZ0Q4BspkB4LKQXhxRnrNJlv/oopxXua/GCMW17xxuAIVAIy08ce7
|
||||
877PESiaI4iDWj36uuWV
|
||||
-----END DSA PRIVATE KEY-----
|
1
regress/pesterTests/sshtest_hostkey_dsa.pub
Normal file
1
regress/pesterTests/sshtest_hostkey_dsa.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-dss AAAAB3NzaC1kc3MAAACBAIyVGPwSzaCedtroufmFrwXGVPzYUMHPePvlduORG2+1VmLkP2Yw+U6MHRnaDyDriCulhnmwIueGxhH+t0HKbGK0j7XpGnwgmFOBIg5gJwQTDJ+gX+qC2ju55WB0Gkkwl+xktnAFSqmj8ttSzUBhh1ksh5A6oW+NKjwEVH8tQExFAAAAFQC0YldxCDQbTuDO04EVgA0OMpDIvwAAAIBXWRzpoyQWNoB18DGbY9zupGhfwuKGmnlj2mY0aYxY3qu1+9ciQOBrwYJlf4dEJbirwp2XmKzHZ6LFrkLQptVcD1wDkG/a/wMRvh+tbxlq45S3Eh0oNj1cobhUlFm9m5PM2HW1LccbOAEBUG/L4Vcj1Ag4n639H0fwDRL+rwOpjgAAAIBh/fSBidBGsQITgg45wwDszk7AAhngNm+jbiea8dbgYP6wpT6dJdg3pYwKT0V/PdXTSDi16kkoMkbUsMZyxyFJf/TtmCtBnon55yL9+H5dtcOBF8BXR7KzQX1E1n0eIL9jZ0Q4BspkB4LKQXhxRnrNJlv/oopxXua/GCMW17xxuA== sshtest_hostkey_dsa
|
5
regress/pesterTests/sshtest_hostkey_ecdsa
Normal file
5
regress/pesterTests/sshtest_hostkey_ecdsa
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEICAT5BC1AJpeOsRQaettNtqw6rzKlHDgtGvqnYZuU8YOoAoGCCqGSM49
|
||||
AwEHoUQDQgAEcXZ5bCCdpRIs003SKXGJP3Xq4xrqW6wwHfUDF+QMYCuHjEJYvR7c
|
||||
X+BGJ9F6mEzRwPZ1KHwmLpWeOSG9mm2MTA==
|
||||
-----END EC PRIVATE KEY-----
|
1
regress/pesterTests/sshtest_hostkey_ecdsa.pub
Normal file
1
regress/pesterTests/sshtest_hostkey_ecdsa.pub
Normal file
@ -0,0 +1 @@
|
||||
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHF2eWwgnaUSLNNN0ilxiT916uMa6lusMB31AxfkDGArh4xCWL0e3F/gRifRephM0cD2dSh8Ji6VnjkhvZptjEw= sshtest_hostkey_ecdsa
|
7
regress/pesterTests/sshtest_hostkey_ed25519
Normal file
7
regress/pesterTests/sshtest_hostkey_ed25519
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACDLSTMcJ/oiVNF+PhAuz0o/3H3DG3T+moYaHbV8fukR7wAAAKACW4cWAluH
|
||||
FgAAAAtzc2gtZWQyNTUxOQAAACDLSTMcJ/oiVNF+PhAuz0o/3H3DG3T+moYaHbV8fukR7w
|
||||
AAAEDIU6PKvxw+6hgpQmTOOFeUasWnsYU3gricJCNrEHu2FstJMxwn+iJU0X4+EC7PSj/c
|
||||
fcMbdP6ahhodtXx+6RHvAAAAF3NzaHRlc3RfaG9zdGtleV9lZDI1NTE5AQIDBAUG
|
||||
-----END OPENSSH PRIVATE KEY-----
|
1
regress/pesterTests/sshtest_hostkey_ed25519.pub
Normal file
1
regress/pesterTests/sshtest_hostkey_ed25519.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMtJMxwn+iJU0X4+EC7PSj/cfcMbdP6ahhodtXx+6RHv sshtest_hostkey_ed25519
|
27
regress/pesterTests/sshtest_hostkey_rsa
Normal file
27
regress/pesterTests/sshtest_hostkey_rsa
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEA1PjXEOTbkbrUCaGVYw5j/7xOiGGTmhOfRU1I2qGZLj5eKa3T
|
||||
j4KgJwsEsvV7Z38z5v6HutksmCB4I/MEc4aozFPIPGhqn7/a8hfoaTV2axWFyHZH
|
||||
cZ7m832+Hu9EUUaEx/D+b7mPLAJ9BSEZVf9xA5EigRctltyJzEzupfIG5M85IG59
|
||||
Ri7x9OkCVXW9j3B5LEp+3SQVR1gEmIt0yVlruJriPmTX6LYbo8QB6oykybifWqQ2
|
||||
SHNLZ5D5pYn0ZqJUlEuDgB9ilmfuRsGo+4LAfG5OELgPkAk+tDgnLswnMuBQbl77
|
||||
15DPTAXvz9imY1SwJ/Okq4kbaBOESPvUfUuw1QIDAQABAoIBAGdEafRVJGqbbulk
|
||||
om0vsyl0A5h5x/pz/Uy7VtI8fWxA7aPEF8uEiWelHhgwlC/xLBeb3/CoEcmKJPc5
|
||||
hTUHXJ4HGhbAgsMHYoD1OsqZE9yEySQUxju/0zjKBgA2AKhwSz4wCw/dqCCs7DYq
|
||||
gICEpiYWn+Z8eKyoL2ETBL0OiG01c4oZ8Qd1WrNPNAOA8uX2avCIawiGqfI5hRR2
|
||||
UIpmTNsh8SbA7hMqI47JlLvmfAdKOvug09f36Yhx63RuXWy0AHqz3HcTe4K4tzlP
|
||||
M+DnKDgHQkx8R5j/Q9Dv6ZlKn85FatIWftjd9e4Zsjx2lCKXBFIyn3EM1aiCaRAS
|
||||
iIFJh4ECgYEA6nBShG3z6bLbBNEWPq2xqmq6uJDD7dg6glK5alDDKwCmurfQYxyY
|
||||
HD/1YcIlf+kC4qUCrREgYlheH3xRbzT0yomtci015iC8R8ZZgGNqZO52HxhQVWdN
|
||||
i08vsJmUnrq0WFyXS0OysnPCEPLbHBoFVbJWEDTgKxLOwbYMEyp7IHECgYEA6I8Z
|
||||
tRE3AMbdYvN8+hjq5fcrsRZvkbddYa3DLYImii09s84p82MEskFd+dcTs6ViX2Qn
|
||||
wFgdASCi0FBblKca6ZxgwMHoEEiWgx6zndayeU2wDGWCbHlVXkpnCPb7O+YoMKhy
|
||||
XtDDfVZ0n0Cu+W6dlbVxWyP0uQ8RrE25Po/QSKUCgYAGCrkFsrO7jSF54U2ade2D
|
||||
P9bqFMkH4y+21hzzMXumKxEg9MXJGB6Pc9KGH3PJ9R5e6vPDtBJKlo5ub0zF+e5p
|
||||
Hd07eRDPin5vtxvtZCKE0WR37q97U/s6oOLQwVSENrmZIWHAzdDYKoWQ3EFrWvxS
|
||||
NhNjvYkdcxGjCmcLQ2gC8QKBgD4IFZpXmi1J3jmLqxVm2hk3Id9dlarvlyf72mjk
|
||||
I3WN9bxlTIlQKyuFBhUjSm0Luz6oj3XdyvbHBsa7+IGhRSt0+9XOoyDcy9DzuoNq
|
||||
hjaXA1N7LBvVDXFWNT+N6Zujm6rG86LY2pwvGHJ2JXYBDGWnfTILWDaYj2U/Yh8O
|
||||
60bFAoGAVnm3EVlak5mbDpSpyzqnglVKgZ+mz+4ODcF+qK4415QtAua8Je8Frcje
|
||||
3dYJtP5c5Xm+wE5Lmr+yZUAxup5oC5NAmtvLwK8DLPjfZIBtF7qBf08am8e8HnZw
|
||||
PzFks7iwv86eqgvTwBdE6QmaBzvEPLSmSI93uRz3q/S+16j50Pk=
|
||||
-----END RSA PRIVATE KEY-----
|
1
regress/pesterTests/sshtest_hostkey_rsa.pub
Normal file
1
regress/pesterTests/sshtest_hostkey_rsa.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDU+NcQ5NuRutQJoZVjDmP/vE6IYZOaE59FTUjaoZkuPl4prdOPgqAnCwSy9XtnfzPm/oe62SyYIHgj8wRzhqjMU8g8aGqfv9ryF+hpNXZrFYXIdkdxnubzfb4e70RRRoTH8P5vuY8sAn0FIRlV/3EDkSKBFy2W3InMTO6l8gbkzzkgbn1GLvH06QJVdb2PcHksSn7dJBVHWASYi3TJWWu4muI+ZNfothujxAHqjKTJuJ9apDZIc0tnkPmlifRmolSUS4OAH2KWZ+5Gwaj7gsB8bk4QuA+QCT60OCcuzCcy4FBuXvvXkM9MBe/P2KZjVLAn86SriRtoE4RI+9R9S7DV sshtest_hostkey_rsa
|
7
regress/pesterTests/sshtest_userssokey_ed25519
Normal file
7
regress/pesterTests/sshtest_userssokey_ed25519
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACArxdmtP2DtTFvNp+4N4vlEP2tBmG7QtG4qfNUKlYmxRQAAAKAX+9lZF/vZ
|
||||
WQAAAAtzc2gtZWQyNTUxOQAAACArxdmtP2DtTFvNp+4N4vlEP2tBmG7QtG4qfNUKlYmxRQ
|
||||
AAAEBkZYPXRU9wu7OCcBia+eKvWOtDKpZRibjGQMTdBlCn5CvF2a0/YO1MW82n7g3i+UQ/
|
||||
a0GYbtC0bip81QqVibFFAAAAGnNzaHRlc3RfdXNlcnNzb2tleV9lZDI1NTE5AQID
|
||||
-----END OPENSSH PRIVATE KEY-----
|
1
regress/pesterTests/sshtest_userssokey_ed25519.pub
Normal file
1
regress/pesterTests/sshtest_userssokey_ed25519.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICvF2a0/YO1MW82n7g3i+UQ/a0GYbtC0bip81QqVibFF sshtest_userssokey_ed25519
|
@ -1,5 +1,6 @@
|
||||
# $OpenBSD: Makefile,v 1.7 2016/08/19 06:44:13 djm Exp $
|
||||
REGRESS_FAIL_EARLY= yes
|
||||
SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys utf8 match
|
||||
# $OpenBSD: Makefile,v 1.9 2017/03/14 01:20:29 dtucker Exp $
|
||||
|
||||
REGRESS_FAIL_EARLY?= yes
|
||||
SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys utf8 match conversion
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
10
regress/unittests/conversion/Makefile
Normal file
10
regress/unittests/conversion/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
# $OpenBSD: Makefile,v 1.1 2017/03/14 01:20:29 dtucker Exp $
|
||||
|
||||
PROG=test_conversion
|
||||
SRCS=tests.c
|
||||
REGRESS_TARGETS=run-regress-${PROG}
|
||||
|
||||
run-regress-${PROG}: ${PROG}
|
||||
env ${TEST_ENV} ./${PROG}
|
||||
|
||||
.include <bsd.regress.mk>
|
51
regress/unittests/conversion/tests.c
Normal file
51
regress/unittests/conversion/tests.c
Normal file
@ -0,0 +1,51 @@
|
||||
/* $OpenBSD: tests.c,v 1.1 2017/03/14 01:20:29 dtucker Exp $ */
|
||||
/*
|
||||
* Regress test for conversions
|
||||
*
|
||||
* Placed in the public domain
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../test_helper/test_helper.h"
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
void
|
||||
tests(void)
|
||||
{
|
||||
char buf[1024];
|
||||
|
||||
TEST_START("conversion_convtime");
|
||||
ASSERT_LONG_EQ(convtime("0"), 0);
|
||||
ASSERT_LONG_EQ(convtime("1"), 1);
|
||||
ASSERT_LONG_EQ(convtime("1S"), 1);
|
||||
/* from the examples in the comment above the function */
|
||||
ASSERT_LONG_EQ(convtime("90m"), 5400);
|
||||
ASSERT_LONG_EQ(convtime("1h30m"), 5400);
|
||||
ASSERT_LONG_EQ(convtime("2d"), 172800);
|
||||
ASSERT_LONG_EQ(convtime("1w"), 604800);
|
||||
|
||||
/* negative time is not allowed */
|
||||
ASSERT_LONG_EQ(convtime("-7"), -1);
|
||||
ASSERT_LONG_EQ(convtime("-9d"), -1);
|
||||
|
||||
/* overflow */
|
||||
snprintf(buf, sizeof buf, "%llu", (unsigned long long)LONG_MAX + 1);
|
||||
ASSERT_LONG_EQ(convtime(buf), -1);
|
||||
|
||||
/* overflow with multiplier */
|
||||
snprintf(buf, sizeof buf, "%lluM", (unsigned long long)LONG_MAX/60 + 1);
|
||||
ASSERT_LONG_EQ(convtime(buf), -1);
|
||||
ASSERT_LONG_EQ(convtime("1000000000000000000000w"), -1);
|
||||
TEST_DONE();
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: test_helper.c,v 1.6 2015/03/03 20:42:49 djm Exp $ */
|
||||
/* $OpenBSD: test_helper.c,v 1.7 2017/03/14 01:10:07 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
|
||||
*
|
||||
@ -441,6 +441,17 @@ assert_u_int(const char *file, int line, const char *a1, const char *a2,
|
||||
test_die();
|
||||
}
|
||||
|
||||
void
|
||||
assert_long(const char *file, int line, const char *a1, const char *a2,
|
||||
long aa1, long aa2, enum test_predicate pred)
|
||||
{
|
||||
TEST_CHECK(aa1, aa2, pred);
|
||||
test_header(file, line, a1, a2, "LONG", pred);
|
||||
fprintf(stderr, "%12s = %ld / 0x%lx\n", a1, aa1, aa1);
|
||||
fprintf(stderr, "%12s = %ld / 0x%lx\n", a2, aa2, aa2);
|
||||
test_die();
|
||||
}
|
||||
|
||||
void
|
||||
assert_long_long(const char *file, int line, const char *a1, const char *a2,
|
||||
long long aa1, long long aa2, enum test_predicate pred)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: test_helper.h,v 1.6 2015/01/18 19:52:44 djm Exp $ */
|
||||
/* $OpenBSD: test_helper.h,v 1.7 2017/03/14 01:10:07 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
|
||||
*
|
||||
@ -67,6 +67,9 @@ void assert_size_t(const char *file, int line,
|
||||
void assert_u_int(const char *file, int line,
|
||||
const char *a1, const char *a2,
|
||||
u_int aa1, u_int aa2, enum test_predicate pred);
|
||||
void assert_long(const char *file, int line,
|
||||
const char *a1, const char *a2,
|
||||
long aa1, long aa2, enum test_predicate pred);
|
||||
void assert_long_long(const char *file, int line,
|
||||
const char *a1, const char *a2,
|
||||
long long aa1, long long aa2, enum test_predicate pred);
|
||||
@ -110,6 +113,8 @@ void assert_u64(const char *file, int line,
|
||||
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
|
||||
#define ASSERT_U_INT_EQ(a1, a2) \
|
||||
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
|
||||
#define ASSERT_LONG_EQ(a1, a2) \
|
||||
assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
|
||||
#define ASSERT_LONG_LONG_EQ(a1, a2) \
|
||||
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
|
||||
#define ASSERT_CHAR_EQ(a1, a2) \
|
||||
@ -139,6 +144,8 @@ void assert_u64(const char *file, int line,
|
||||
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
|
||||
#define ASSERT_U_INT_NE(a1, a2) \
|
||||
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
|
||||
#define ASSERT_LONG_NE(a1, a2) \
|
||||
assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
|
||||
#define ASSERT_LONG_LONG_NE(a1, a2) \
|
||||
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
|
||||
#define ASSERT_CHAR_NE(a1, a2) \
|
||||
@ -166,6 +173,8 @@ void assert_u64(const char *file, int line,
|
||||
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
|
||||
#define ASSERT_U_INT_LT(a1, a2) \
|
||||
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
|
||||
#define ASSERT_LONG_LT(a1, a2) \
|
||||
assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
|
||||
#define ASSERT_LONG_LONG_LT(a1, a2) \
|
||||
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
|
||||
#define ASSERT_CHAR_LT(a1, a2) \
|
||||
@ -193,6 +202,8 @@ void assert_u64(const char *file, int line,
|
||||
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
|
||||
#define ASSERT_U_INT_LE(a1, a2) \
|
||||
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
|
||||
#define ASSERT_LONG_LE(a1, a2) \
|
||||
assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
|
||||
#define ASSERT_LONG_LONG_LE(a1, a2) \
|
||||
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
|
||||
#define ASSERT_CHAR_LE(a1, a2) \
|
||||
@ -220,6 +231,8 @@ void assert_u64(const char *file, int line,
|
||||
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
|
||||
#define ASSERT_U_INT_GT(a1, a2) \
|
||||
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
|
||||
#define ASSERT_LONG_GT(a1, a2) \
|
||||
assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
|
||||
#define ASSERT_LONG_LONG_GT(a1, a2) \
|
||||
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
|
||||
#define ASSERT_CHAR_GT(a1, a2) \
|
||||
@ -247,6 +260,8 @@ void assert_u64(const char *file, int line,
|
||||
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
|
||||
#define ASSERT_U_INT_GE(a1, a2) \
|
||||
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
|
||||
#define ASSERT_LONG_GE(a1, a2) \
|
||||
assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
|
||||
#define ASSERT_LONG_LONG_GE(a1, a2) \
|
||||
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
|
||||
#define ASSERT_CHAR_GE(a1, a2) \
|
||||
|
@ -56,11 +56,6 @@ tests(void)
|
||||
{
|
||||
char *loc;
|
||||
|
||||
#ifdef WINDOWS
|
||||
TEST_START("not applicable to Windows yet");
|
||||
TEST_DONE();
|
||||
return;
|
||||
#endif
|
||||
TEST_START("utf8_setlocale");
|
||||
loc = setlocale(LC_CTYPE, "en_US.UTF-8");
|
||||
ASSERT_PTR_NE(loc, NULL);
|
||||
|
@ -50,6 +50,9 @@
|
||||
#include <elf.h>
|
||||
|
||||
#include <asm/unistd.h>
|
||||
#ifdef __s390__
|
||||
#include <asm/zcrypt.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
@ -73,19 +76,35 @@
|
||||
# define SECCOMP_FILTER_FAIL SECCOMP_RET_TRAP
|
||||
#endif /* SANDBOX_SECCOMP_FILTER_DEBUG */
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# define ARG_LO_OFFSET 0
|
||||
# define ARG_HI_OFFSET sizeof(uint32_t)
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
# define ARG_LO_OFFSET sizeof(uint32_t)
|
||||
# define ARG_HI_OFFSET 0
|
||||
#else
|
||||
#error "Unknown endianness"
|
||||
#endif
|
||||
|
||||
/* Simple helpers to avoid manual errors (but larger BPF programs). */
|
||||
#define SC_DENY(_nr, _errno) \
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 1), \
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 1), \
|
||||
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO|(_errno))
|
||||
#define SC_ALLOW(_nr) \
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 1), \
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 1), \
|
||||
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
|
||||
#define SC_ALLOW_ARG(_nr, _arg_nr, _arg_val) \
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 4), \
|
||||
/* load first syscall argument */ \
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 6), \
|
||||
/* load and test first syscall argument, low word */ \
|
||||
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
|
||||
offsetof(struct seccomp_data, args[(_arg_nr)])), \
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_arg_val), 0, 1), \
|
||||
offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_LO_OFFSET), \
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, \
|
||||
((_arg_val) & 0xFFFFFFFF), 0, 3), \
|
||||
/* load and test first syscall argument, high word */ \
|
||||
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
|
||||
offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_HI_OFFSET), \
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, \
|
||||
(((uint32_t)((uint64_t)(_arg_val) >> 32)) & 0xFFFFFFFF), 0, 1), \
|
||||
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), \
|
||||
/* reload syscall number; all rules expect it in accumulator */ \
|
||||
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
|
||||
@ -104,108 +123,122 @@ static const struct sock_filter preauth_insns[] = {
|
||||
|
||||
/* Syscalls to non-fatally deny */
|
||||
#ifdef __NR_lstat
|
||||
SC_DENY(lstat, EACCES),
|
||||
SC_DENY(__NR_lstat, EACCES),
|
||||
#endif
|
||||
#ifdef __NR_lstat64
|
||||
SC_DENY(lstat64, EACCES),
|
||||
SC_DENY(__NR_lstat64, EACCES),
|
||||
#endif
|
||||
#ifdef __NR_fstat
|
||||
SC_DENY(fstat, EACCES),
|
||||
SC_DENY(__NR_fstat, EACCES),
|
||||
#endif
|
||||
#ifdef __NR_fstat64
|
||||
SC_DENY(fstat64, EACCES),
|
||||
SC_DENY(__NR_fstat64, EACCES),
|
||||
#endif
|
||||
#ifdef __NR_open
|
||||
SC_DENY(open, EACCES),
|
||||
SC_DENY(__NR_open, EACCES),
|
||||
#endif
|
||||
#ifdef __NR_openat
|
||||
SC_DENY(openat, EACCES),
|
||||
SC_DENY(__NR_openat, EACCES),
|
||||
#endif
|
||||
#ifdef __NR_newfstatat
|
||||
SC_DENY(newfstatat, EACCES),
|
||||
SC_DENY(__NR_newfstatat, EACCES),
|
||||
#endif
|
||||
#ifdef __NR_stat
|
||||
SC_DENY(stat, EACCES),
|
||||
SC_DENY(__NR_stat, EACCES),
|
||||
#endif
|
||||
#ifdef __NR_stat64
|
||||
SC_DENY(stat64, EACCES),
|
||||
SC_DENY(__NR_stat64, EACCES),
|
||||
#endif
|
||||
|
||||
/* Syscalls to permit */
|
||||
#ifdef __NR_brk
|
||||
SC_ALLOW(brk),
|
||||
SC_ALLOW(__NR_brk),
|
||||
#endif
|
||||
#ifdef __NR_clock_gettime
|
||||
SC_ALLOW(clock_gettime),
|
||||
SC_ALLOW(__NR_clock_gettime),
|
||||
#endif
|
||||
#ifdef __NR_close
|
||||
SC_ALLOW(close),
|
||||
SC_ALLOW(__NR_close),
|
||||
#endif
|
||||
#ifdef __NR_exit
|
||||
SC_ALLOW(exit),
|
||||
SC_ALLOW(__NR_exit),
|
||||
#endif
|
||||
#ifdef __NR_exit_group
|
||||
SC_ALLOW(exit_group),
|
||||
SC_ALLOW(__NR_exit_group),
|
||||
#endif
|
||||
#ifdef __NR_getpgid
|
||||
SC_ALLOW(getpgid),
|
||||
SC_ALLOW(__NR_getpgid),
|
||||
#endif
|
||||
#ifdef __NR_getpid
|
||||
SC_ALLOW(getpid),
|
||||
SC_ALLOW(__NR_getpid),
|
||||
#endif
|
||||
#ifdef __NR_getrandom
|
||||
SC_ALLOW(getrandom),
|
||||
SC_ALLOW(__NR_getrandom),
|
||||
#endif
|
||||
#ifdef __NR_gettimeofday
|
||||
SC_ALLOW(gettimeofday),
|
||||
SC_ALLOW(__NR_gettimeofday),
|
||||
#endif
|
||||
#ifdef __NR_madvise
|
||||
SC_ALLOW(madvise),
|
||||
SC_ALLOW(__NR_madvise),
|
||||
#endif
|
||||
#ifdef __NR_mmap
|
||||
SC_ALLOW(mmap),
|
||||
SC_ALLOW(__NR_mmap),
|
||||
#endif
|
||||
#ifdef __NR_mmap2
|
||||
SC_ALLOW(mmap2),
|
||||
SC_ALLOW(__NR_mmap2),
|
||||
#endif
|
||||
#ifdef __NR_mremap
|
||||
SC_ALLOW(mremap),
|
||||
SC_ALLOW(__NR_mremap),
|
||||
#endif
|
||||
#ifdef __NR_munmap
|
||||
SC_ALLOW(munmap),
|
||||
SC_ALLOW(__NR_munmap),
|
||||
#endif
|
||||
#ifdef __NR__newselect
|
||||
SC_ALLOW(_newselect),
|
||||
SC_ALLOW(__NR__newselect),
|
||||
#endif
|
||||
#ifdef __NR_poll
|
||||
SC_ALLOW(poll),
|
||||
SC_ALLOW(__NR_poll),
|
||||
#endif
|
||||
#ifdef __NR_pselect6
|
||||
SC_ALLOW(pselect6),
|
||||
SC_ALLOW(__NR_pselect6),
|
||||
#endif
|
||||
#ifdef __NR_read
|
||||
SC_ALLOW(read),
|
||||
SC_ALLOW(__NR_read),
|
||||
#endif
|
||||
#ifdef __NR_rt_sigprocmask
|
||||
SC_ALLOW(rt_sigprocmask),
|
||||
SC_ALLOW(__NR_rt_sigprocmask),
|
||||
#endif
|
||||
#ifdef __NR_select
|
||||
SC_ALLOW(select),
|
||||
SC_ALLOW(__NR_select),
|
||||
#endif
|
||||
#ifdef __NR_shutdown
|
||||
SC_ALLOW(shutdown),
|
||||
SC_ALLOW(__NR_shutdown),
|
||||
#endif
|
||||
#ifdef __NR_sigprocmask
|
||||
SC_ALLOW(sigprocmask),
|
||||
SC_ALLOW(__NR_sigprocmask),
|
||||
#endif
|
||||
#ifdef __NR_time
|
||||
SC_ALLOW(time),
|
||||
SC_ALLOW(__NR_time),
|
||||
#endif
|
||||
#ifdef __NR_write
|
||||
SC_ALLOW(write),
|
||||
SC_ALLOW(__NR_write),
|
||||
#endif
|
||||
#ifdef __NR_socketcall
|
||||
SC_ALLOW_ARG(socketcall, 0, SYS_SHUTDOWN),
|
||||
SC_ALLOW_ARG(__NR_socketcall, 0, SYS_SHUTDOWN),
|
||||
#endif
|
||||
#if defined(__NR_ioctl) && defined(__s390__)
|
||||
/* Allow ioctls for ICA crypto card on s390 */
|
||||
SC_ALLOW_ARG(__NR_ioctl, 1, Z90STAT_STATUS_MASK),
|
||||
SC_ALLOW_ARG(__NR_ioctl, 1, ICARSAMODEXPO),
|
||||
SC_ALLOW_ARG(__NR_ioctl, 1, ICARSACRT),
|
||||
#endif
|
||||
#if defined(__x86_64__) && defined(__ILP32__) && defined(__X32_SYSCALL_BIT)
|
||||
/*
|
||||
* On Linux x32, the clock_gettime VDSO falls back to the
|
||||
* x86-64 syscall under some circumstances, e.g.
|
||||
* https://bugs.debian.org/849923
|
||||
*/
|
||||
SC_ALLOW(__NR_clock_gettime & ~__X32_SYSCALL_BIT),
|
||||
#endif
|
||||
|
||||
/* Default deny */
|
||||
|
47
scp.c
47
scp.c
@ -292,29 +292,11 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
|
||||
addargs(&args, "%s", host);
|
||||
addargs(&args, "%s", cmd);
|
||||
|
||||
{
|
||||
char* full_cmd;
|
||||
size_t cmdlen = 0;
|
||||
char** list = args.list;
|
||||
fcntl(pout[0], F_SETFD, FD_CLOEXEC);
|
||||
fcntl(pin[1], F_SETFD, FD_CLOEXEC);
|
||||
|
||||
cmdlen = 1; /* null term */
|
||||
while (*list)
|
||||
cmdlen += strlen(*list++) + 1;
|
||||
do_cmd_pid = spawn_child(args.list[0], args.list + 1, pin[0], pout[1], STDERR_FILENO, 0);
|
||||
|
||||
full_cmd = xmalloc(cmdlen);
|
||||
full_cmd[0] = '\0';
|
||||
list = args.list;
|
||||
while (*list) {
|
||||
strcat(full_cmd, *list++);
|
||||
strcat(full_cmd, " ");
|
||||
}
|
||||
|
||||
fcntl(pout[0], F_SETFD, FD_CLOEXEC);
|
||||
fcntl(pin[1], F_SETFD, FD_CLOEXEC);
|
||||
|
||||
do_cmd_pid = spawn_child(full_cmd, pin[0], pout[1], STDERR_FILENO, 0);
|
||||
free(full_cmd);
|
||||
}
|
||||
#else /* !WINDOWS */
|
||||
do_cmd_pid = fork();
|
||||
#endif /* !WINDOWS */
|
||||
@ -382,26 +364,8 @@ do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout)
|
||||
addargs(&args, "%s", host);
|
||||
addargs(&args, "%s", cmd);
|
||||
|
||||
{
|
||||
char* full_cmd;
|
||||
size_t cmdlen = 0;
|
||||
char** list = args.list;
|
||||
|
||||
cmdlen = 1; /* null term */
|
||||
while (*list)
|
||||
cmdlen += strlen(*list++) + 1;
|
||||
|
||||
full_cmd = xmalloc(cmdlen);
|
||||
full_cmd[0] = '\0';
|
||||
list = args.list;
|
||||
while (*list) {
|
||||
strcat(full_cmd, *list++);
|
||||
strcat(full_cmd, " ");
|
||||
}
|
||||
|
||||
pid = spawn_child(full_cmd, fdin, fdout, STDERR_FILENO, 0);
|
||||
free(full_cmd);
|
||||
}
|
||||
pid = spawn_child(args.list[0], args.list + 1, fdin, fdout, STDERR_FILENO, 0);
|
||||
|
||||
#else /* !WINDOWS */
|
||||
pid = fork();
|
||||
#endif /* !WINDOWS */
|
||||
@ -1512,4 +1476,3 @@ lostconn(int signo)
|
||||
else
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
12
servconf.c
12
servconf.c
@ -1,5 +1,5 @@
|
||||
|
||||
/* $OpenBSD: servconf.c,v 1.305 2017/03/10 04:11:00 dtucker Exp $ */
|
||||
/* $OpenBSD: servconf.c,v 1.306 2017/03/14 07:19:07 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
@ -535,7 +535,7 @@ static struct {
|
||||
{ "clientalivecountmax", sClientAliveCountMax, SSHCFG_ALL },
|
||||
{ "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
|
||||
{ "authorizedkeysfile2", sDeprecated, SSHCFG_ALL },
|
||||
{ "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
|
||||
{ "useprivilegeseparation", sDeprecated, SSHCFG_GLOBAL},
|
||||
{ "acceptenv", sAcceptEnv, SSHCFG_ALL },
|
||||
{ "permittunnel", sPermitTunnel, SSHCFG_ALL },
|
||||
{ "permittty", sPermitTTY, SSHCFG_ALL },
|
||||
@ -1379,11 +1379,6 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||
intptr = &options->disable_forwarding;
|
||||
goto parse_flag;
|
||||
|
||||
case sUsePrivilegeSeparation:
|
||||
intptr = &use_privsep;
|
||||
multistate_ptr = multistate_privsep;
|
||||
goto parse_multistate;
|
||||
|
||||
case sAllowUsers:
|
||||
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
||||
if (options->num_allow_users >= MAX_ALLOW_USERS)
|
||||
@ -2112,8 +2107,6 @@ fmt_intarg(ServerOpCodes code, int val)
|
||||
return fmt_multistate_int(val, multistate_gatewayports);
|
||||
case sCompression:
|
||||
return fmt_multistate_int(val, multistate_compression);
|
||||
case sUsePrivilegeSeparation:
|
||||
return fmt_multistate_int(val, multistate_privsep);
|
||||
case sAllowTcpForwarding:
|
||||
return fmt_multistate_int(val, multistate_tcpfwd);
|
||||
case sAllowStreamLocalForwarding:
|
||||
@ -2289,7 +2282,6 @@ dump_config(ServerOptions *o)
|
||||
dump_cfg_fmtint(sDisableForwarding, o->disable_forwarding);
|
||||
dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
|
||||
dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
|
||||
dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
|
||||
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
|
||||
|
||||
/* string arguments */
|
||||
|
@ -183,7 +183,7 @@ static int
|
||||
auth_input_request_forwarding(struct passwd * pw)
|
||||
{
|
||||
#ifdef WINDOWS
|
||||
packet_send_debug("Agent forwarding not supported yet in Windows");
|
||||
packet_send_debug("Agent forwarding not supported in Windows yet");
|
||||
return 0;
|
||||
#else /* !WINDOWS */
|
||||
Channel *nc;
|
||||
@ -2377,9 +2377,9 @@ static int
|
||||
session_env_req(Session *s)
|
||||
{
|
||||
char *name, *val;
|
||||
u_int name_chars, val_len, i;
|
||||
u_int name_len, val_len, i;
|
||||
|
||||
name = packet_get_cstring(&name_chars);
|
||||
name = packet_get_cstring(&name_len);
|
||||
val = packet_get_cstring(&val_len);
|
||||
packet_check_eom();
|
||||
|
||||
|
@ -67,6 +67,13 @@ extern int showprogress;
|
||||
/* Maximum depth to descend in directory trees */
|
||||
#define MAX_DIR_DEPTH 64
|
||||
|
||||
/* Directory separator characters */
|
||||
#ifdef HAVE_CYGWIN
|
||||
# define SFTP_DIRECTORY_CHARS "/\\"
|
||||
#else /* HAVE_CYGWIN */
|
||||
# define SFTP_DIRECTORY_CHARS "/"
|
||||
#endif /* HAVE_CYGWIN */
|
||||
|
||||
struct sftp_conn {
|
||||
int fd_in;
|
||||
int fd_out;
|
||||
@ -619,7 +626,7 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
|
||||
* These can be used to attack recursive ops
|
||||
* (e.g. send '../../../../etc/passwd')
|
||||
*/
|
||||
if (strchr(filename, '/') != NULL) {
|
||||
if (strpbrk(filename, SFTP_DIRECTORY_CHARS) != NULL) {
|
||||
error("Server sent suspect path \"%s\" "
|
||||
"during readdir of \"%s\"", filename, path);
|
||||
} else if (dir) {
|
||||
|
34
sftp.c
34
sftp.c
@ -2163,12 +2163,11 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
|
||||
free(dir);
|
||||
}
|
||||
|
||||
interactive = !batchmode && isatty(STDIN_FILENO);
|
||||
err = 0;
|
||||
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
setvbuf(infile, NULL, _IOLBF, 0);
|
||||
|
||||
interactive = !batchmode && isatty(STDIN_FILENO);
|
||||
err = 0;
|
||||
for (;;) {
|
||||
char *cp;
|
||||
|
||||
@ -2256,32 +2255,11 @@ connect_to_server(char *path, char **args, int *in, int *out)
|
||||
|
||||
#ifdef WINDOWS
|
||||
/* fork replacement on Windows */
|
||||
{
|
||||
size_t cmdlen = 0;
|
||||
int i = 0;
|
||||
char* full_cmd;
|
||||
|
||||
cmdlen = strlen(path) + 1;
|
||||
for (i = 1; args[i]; i++)
|
||||
cmdlen += strlen(args[i]) + 1 + 2;
|
||||
|
||||
full_cmd = xmalloc(cmdlen);
|
||||
full_cmd[0] = '\0';
|
||||
strcat(full_cmd, path);
|
||||
for (i = 1; args[i]; i++) {
|
||||
strcat(full_cmd, " \"");
|
||||
strcat(full_cmd, args[i]);
|
||||
strcat(full_cmd, "\"");
|
||||
}
|
||||
|
||||
/* disable inheritance on local pipe ends*/
|
||||
fcntl(pout[1], F_SETFD, FD_CLOEXEC);
|
||||
fcntl(pin[0], F_SETFD, FD_CLOEXEC);
|
||||
|
||||
sshpid = spawn_child(full_cmd, c_in, c_out, STDERR_FILENO, 0);
|
||||
free(full_cmd);
|
||||
}
|
||||
/* disable inheritance on local pipe ends*/
|
||||
fcntl(pout[1], F_SETFD, FD_CLOEXEC);
|
||||
fcntl(pin[0], F_SETFD, FD_CLOEXEC);
|
||||
|
||||
sshpid = spawn_child(path, args + 1, c_in, c_out, STDERR_FILENO, 0);
|
||||
if (sshpid == -1)
|
||||
#else /* !WINDOWS */
|
||||
if ((sshpid = fork()) == -1)
|
||||
|
@ -492,12 +492,7 @@ main(int argc, char **argv)
|
||||
OpenSSL_add_all_algorithms();
|
||||
#endif
|
||||
|
||||
#ifdef WINDOWS
|
||||
/* Min buffer size allowed in Windows is 2*/
|
||||
setvbuf(stdout, NULL, _IOLBF, 2);
|
||||
#else
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
#endif
|
||||
|
||||
/* First, get a connection to the authentication agent. */
|
||||
switch (r = ssh_get_authentication_socket(&agent_fd)) {
|
||||
|
16
ssh-agent.c
16
ssh-agent.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-agent.c,v 1.216 2017/01/04 02:21:43 djm Exp $ */
|
||||
/* $OpenBSD: ssh-agent.c,v 1.218 2017/03/15 03:52:30 deraadt Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -821,7 +821,7 @@ send:
|
||||
static void
|
||||
process_remove_smartcard_key(SocketEntry *e)
|
||||
{
|
||||
char *provider = NULL, *pin = NULL;
|
||||
char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX];
|
||||
int r, version, success = 0;
|
||||
Identity *id, *nxt;
|
||||
Idtab *tab;
|
||||
@ -831,6 +831,13 @@ process_remove_smartcard_key(SocketEntry *e)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
free(pin);
|
||||
|
||||
if (realpath(provider, canonical_provider) == NULL) {
|
||||
verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
|
||||
provider, strerror(errno));
|
||||
goto send;
|
||||
}
|
||||
|
||||
debug("%s: remove %.100s", __func__, canonical_provider);
|
||||
for (version = 1; version < 3; version++) {
|
||||
tab = idtab_lookup(version);
|
||||
for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
|
||||
@ -838,18 +845,19 @@ process_remove_smartcard_key(SocketEntry *e)
|
||||
/* Skip file--based keys */
|
||||
if (id->provider == NULL)
|
||||
continue;
|
||||
if (!strcmp(provider, id->provider)) {
|
||||
if (!strcmp(canonical_provider, id->provider)) {
|
||||
TAILQ_REMOVE(&tab->idlist, id, next);
|
||||
free_identity(id);
|
||||
tab->nentries--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pkcs11_del_provider(provider) == 0)
|
||||
if (pkcs11_del_provider(canonical_provider) == 0)
|
||||
success = 1;
|
||||
else
|
||||
error("process_remove_smartcard_key:"
|
||||
" pkcs11_del_provider failed");
|
||||
send:
|
||||
free(provider);
|
||||
send_status(e, success);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sshconnect2.c,v 1.254 2017/02/03 02:56:00 dtucker Exp $ */
|
||||
/* $OpenBSD: sshconnect2.c,v 1.255 2017/03/11 23:40:26 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2008 Damien Miller. All rights reserved.
|
||||
@ -1001,11 +1001,11 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
|
||||
}
|
||||
|
||||
static const char *
|
||||
identity_sign_encode(struct identity *id)
|
||||
key_sign_encode(const struct sshkey *key)
|
||||
{
|
||||
struct ssh *ssh = active_state;
|
||||
|
||||
if (id->key->type == KEY_RSA) {
|
||||
if (key->type == KEY_RSA) {
|
||||
switch (ssh->kex->rsa_sha2) {
|
||||
case 256:
|
||||
return "rsa-sha2-256";
|
||||
@ -1013,7 +1013,7 @@ identity_sign_encode(struct identity *id)
|
||||
return "rsa-sha2-512";
|
||||
}
|
||||
}
|
||||
return key_ssh_name(id->key);
|
||||
return key_ssh_name(key);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1022,30 +1022,49 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
|
||||
{
|
||||
Key *prv;
|
||||
int ret;
|
||||
const char *alg;
|
||||
|
||||
alg = identity_sign_encode(id);
|
||||
|
||||
/* the agent supports this key */
|
||||
if (id->agent_fd != -1)
|
||||
if (id->key != NULL && id->agent_fd != -1)
|
||||
return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp,
|
||||
data, datalen, alg, compat);
|
||||
data, datalen, key_sign_encode(id->key), compat);
|
||||
|
||||
/*
|
||||
* we have already loaded the private key or
|
||||
* the private key is stored in external hardware
|
||||
*/
|
||||
if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))
|
||||
return (sshkey_sign(id->key, sigp, lenp, data, datalen, alg,
|
||||
compat));
|
||||
if (id->key != NULL &&
|
||||
(id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT)))
|
||||
return (sshkey_sign(id->key, sigp, lenp, data, datalen,
|
||||
key_sign_encode(id->key), compat));
|
||||
|
||||
/* load the private key from the file */
|
||||
if ((prv = load_identity_file(id)) == NULL)
|
||||
return SSH_ERR_KEY_NOT_FOUND;
|
||||
ret = sshkey_sign(prv, sigp, lenp, data, datalen, alg, compat);
|
||||
ret = sshkey_sign(prv, sigp, lenp, data, datalen,
|
||||
key_sign_encode(prv), compat);
|
||||
sshkey_free(prv);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
id_filename_matches(Identity *id, Identity *private_id)
|
||||
{
|
||||
const char *suffixes[] = { ".pub", "-cert.pub", NULL };
|
||||
size_t len = strlen(id->filename), plen = strlen(private_id->filename);
|
||||
size_t i, slen;
|
||||
|
||||
if (strcmp(id->filename, private_id->filename) == 0)
|
||||
return 1;
|
||||
for (i = 0; suffixes[i]; i++) {
|
||||
slen = strlen(suffixes[i]);
|
||||
if (len > slen && plen == len - slen &&
|
||||
strcmp(id->filename + (len - slen), suffixes[i]) == 0 &&
|
||||
memcmp(id->filename, private_id->filename, plen) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
|
||||
{
|
||||
@ -1088,7 +1107,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
|
||||
} else {
|
||||
buffer_put_cstring(&b, authctxt->method->name);
|
||||
buffer_put_char(&b, have_sig);
|
||||
buffer_put_cstring(&b, identity_sign_encode(id));
|
||||
buffer_put_cstring(&b, key_sign_encode(id->key));
|
||||
}
|
||||
buffer_put_string(&b, blob, bloblen);
|
||||
|
||||
@ -1108,6 +1127,24 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Exact key matches are preferred, but also allow
|
||||
* filename matches for non-PKCS#11/agent keys that
|
||||
* didn't load public keys. This supports the case
|
||||
* of keeping just a private key file and public
|
||||
* certificate on disk.
|
||||
*/
|
||||
if (!matched && !id->isprivate && id->agent_fd == -1 &&
|
||||
(id->key->flags & SSHKEY_FLAG_EXT) == 0) {
|
||||
TAILQ_FOREACH(private_id, &authctxt->keys, next) {
|
||||
if (private_id->key == NULL &&
|
||||
id_filename_matches(id, private_id)) {
|
||||
id = private_id;
|
||||
matched = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matched) {
|
||||
debug2("%s: using private key \"%s\"%s for "
|
||||
"certificate", __func__, id->filename,
|
||||
@ -1186,7 +1223,7 @@ send_pubkey_test(Authctxt *authctxt, Identity *id)
|
||||
packet_put_cstring(authctxt->method->name);
|
||||
packet_put_char(have_sig);
|
||||
if (!(datafellows & SSH_BUG_PKAUTH))
|
||||
packet_put_cstring(identity_sign_encode(id));
|
||||
packet_put_cstring(key_sign_encode(id->key));
|
||||
packet_put_string(blob, bloblen);
|
||||
free(blob);
|
||||
packet_send();
|
||||
|
17
sshd.c
17
sshd.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sshd.c,v 1.483 2017/02/24 03:16:34 djm Exp $ */
|
||||
/* $OpenBSD: sshd.c,v 1.485 2017/03/15 03:52:30 deraadt Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -1317,7 +1317,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
|
||||
continue;
|
||||
}
|
||||
|
||||
pid = spawn_child(path_utf8, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, CREATE_NEW_PROCESS_GROUP);
|
||||
pid = spawn_child(path_utf8, NULL, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, CREATE_NEW_PROCESS_GROUP);
|
||||
free(path_utf8);
|
||||
close(*newsock);
|
||||
}
|
||||
@ -1747,14 +1747,23 @@ main(int ac, char **av)
|
||||
error("Could not connect to agent \"%s\": %s",
|
||||
options.host_key_agent, ssh_err(r));
|
||||
}
|
||||
#ifdef WINDOWS /* Windows version always needs and has agent running */
|
||||
#ifdef WINDOWS /* Windows version always needs and has agent running */
|
||||
have_agent = 1;
|
||||
#endif
|
||||
#endif
|
||||
for (i = 0; i < options.num_host_key_files; i++) {
|
||||
if (options.host_key_files[i] == NULL)
|
||||
continue;
|
||||
key = key_load_private(options.host_key_files[i], "", NULL);
|
||||
pubkey = key_load_public(options.host_key_files[i], NULL);
|
||||
|
||||
if ((pubkey != NULL && pubkey->type == KEY_RSA1) ||
|
||||
(key != NULL && key->type == KEY_RSA1)) {
|
||||
verbose("Ignoring RSA1 key %s",
|
||||
options.host_key_files[i]);
|
||||
key_free(key);
|
||||
key_free(pubkey);
|
||||
continue;
|
||||
}
|
||||
if (pubkey == NULL && key != NULL)
|
||||
pubkey = key_demote(key);
|
||||
sensitive_data.host_keys[i] = key;
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $OpenBSD: sshd_config,v 1.100 2016/08/15 12:32:04 naddy Exp $
|
||||
# $OpenBSD: sshd_config,v 1.101 2017/03/14 07:19:07 djm Exp $
|
||||
|
||||
# This is the sshd server system-wide configuration file. See
|
||||
# sshd_config(5) for more information.
|
||||
@ -93,7 +93,6 @@ AuthorizedKeysFile .ssh/authorized_keys
|
||||
#PrintLastLog yes
|
||||
#TCPKeepAlive yes
|
||||
#UseLogin no
|
||||
#UsePrivilegeSeparation sandbox
|
||||
#PermitUserEnvironment no
|
||||
#Compression delayed
|
||||
#ClientAliveInterval 0
|
||||
|
@ -33,8 +33,8 @@
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $OpenBSD: sshd_config.5,v 1.242 2017/02/03 23:01:19 djm Exp $
|
||||
.Dd $Mdocdate: February 3 2017 $
|
||||
.\" $OpenBSD: sshd_config.5,v 1.243 2017/03/14 07:19:07 djm Exp $
|
||||
.Dd $Mdocdate: March 14 2017 $
|
||||
.Dt SSHD_CONFIG 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -1494,28 +1494,6 @@ is enabled, you will not be able to run
|
||||
as a non-root user.
|
||||
The default is
|
||||
.Cm no .
|
||||
.It Cm UsePrivilegeSeparation
|
||||
Specifies whether
|
||||
.Xr sshd 8
|
||||
separates privileges by creating an unprivileged child process
|
||||
to deal with incoming network traffic.
|
||||
After successful authentication, another process will be created that has
|
||||
the privilege of the authenticated user.
|
||||
The goal of privilege separation is to prevent privilege
|
||||
escalation by containing any corruption within the unprivileged processes.
|
||||
The argument must be
|
||||
.Cm yes ,
|
||||
.Cm no ,
|
||||
or
|
||||
.Cm sandbox .
|
||||
If
|
||||
.Cm UsePrivilegeSeparation
|
||||
is set to
|
||||
.Cm sandbox
|
||||
then the pre-authentication unprivileged process is subject to additional
|
||||
restrictions.
|
||||
The default is
|
||||
.Cm sandbox .
|
||||
.It Cm VersionAddendum
|
||||
Optionally specifies additional text to append to the SSH protocol banner
|
||||
sent by the server upon connection.
|
||||
|
52
sshpty.c
52
sshpty.c
@ -53,57 +53,6 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef WINDOWS
|
||||
/*
|
||||
* Windows versions of pty_*. Some of them are NO-OPs and should go
|
||||
* away when pty logic is refactored and abstracted out
|
||||
*
|
||||
*/
|
||||
int
|
||||
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
|
||||
{
|
||||
/*
|
||||
* Simple console screen implementation in Win32 to give a
|
||||
* Unix like pty for interactive sessions
|
||||
*/
|
||||
*ttyfd = 0;
|
||||
*ptyfd = 0;
|
||||
strlcpy(namebuf, "console", namebuflen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
pty_release(const char *tty) {
|
||||
/* NO-OP */
|
||||
}
|
||||
|
||||
void
|
||||
pty_make_controlling_tty(int *ttyfd, const char *tty) {
|
||||
/* NO-OP */
|
||||
}
|
||||
|
||||
void
|
||||
pty_change_window_size(int ptyfd, u_int row, u_int col,
|
||||
u_int xpixel, u_int ypixel) {
|
||||
COORD coord;
|
||||
coord.X = col;
|
||||
coord.Y = 9999;
|
||||
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coord);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pty_setowner(struct passwd *pw, const char *tty) {
|
||||
/* NO-OP */
|
||||
}
|
||||
|
||||
void
|
||||
disconnect_controlling_tty(void) {
|
||||
/* NO-OP */
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Allocates and opens a pty. Returns 0 if no pty could be allocated, or
|
||||
* nonzero if a pty was successfully allocated. On success, open file
|
||||
@ -303,4 +252,3 @@ disconnect_controlling_tty(void)
|
||||
}
|
||||
#endif /* TIOCNOTTY */
|
||||
}
|
||||
#endif
|
||||
|
32
sshtty.c
32
sshtty.c
@ -47,37 +47,6 @@
|
||||
static struct termios _saved_tio;
|
||||
static int _in_raw_mode = 0;
|
||||
|
||||
#ifdef WINDOWS
|
||||
/*
|
||||
* TTY raw mode routines for Windows
|
||||
*/
|
||||
|
||||
int ConEnterRawMode(DWORD OutputHandle, BOOL fSmartInit);
|
||||
int ConExitRawMode(void);
|
||||
|
||||
struct termios term_settings;
|
||||
|
||||
/*
|
||||
* TODO - clean this up for Windows, ConInit should return previous terminal
|
||||
* settings that need to be stored in term_settings
|
||||
*/
|
||||
|
||||
struct termios *
|
||||
get_saved_tio(void) {
|
||||
memset(&term_settings, 0, sizeof(term_settings));
|
||||
return &term_settings;
|
||||
}
|
||||
|
||||
void
|
||||
leave_raw_mode(int quiet) {
|
||||
ConExitRawMode();
|
||||
}
|
||||
|
||||
void
|
||||
enter_raw_mode(int quiet) {
|
||||
ConEnterRawMode(STD_OUTPUT_HANDLE, TRUE);
|
||||
}
|
||||
#else /* !WINDOWS */
|
||||
struct termios *
|
||||
get_saved_tio(void)
|
||||
{
|
||||
@ -125,4 +94,3 @@ enter_raw_mode(int quiet)
|
||||
} else
|
||||
_in_raw_mode = 1;
|
||||
}
|
||||
#endif /* !WINDOWS */
|
3
utf8.c
3
utf8.c
@ -61,7 +61,7 @@ dangerous_locale(void) {
|
||||
|
||||
loc = nl_langinfo(CODESET);
|
||||
return strcmp(loc, "US-ASCII") != 0 && strcmp(loc, "UTF-8") != 0 &&
|
||||
strcmp(loc, "ANSI_X3.4-1968") != 0;
|
||||
strcmp(loc, "ANSI_X3.4-1968") != 0 && strcmp(loc, "646") != 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -332,4 +332,3 @@ msetlocale(void)
|
||||
/* We can handle this locale */
|
||||
setlocale(LC_CTYPE, "");
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* $OpenBSD: version.h,v 1.78 2016/12/19 04:55:51 djm Exp $ */
|
||||
/* $OpenBSD: version.h,v 1.79 2017/03/20 01:18:59 djm Exp $ */
|
||||
|
||||
#define SSH_VERSION "OpenSSH_7.4"
|
||||
#define SSH_VERSION "OpenSSH_7.5"
|
||||
|
||||
#define SSH_PORTABLE "p1"
|
||||
#define SSH_RELEASE SSH_VERSION SSH_PORTABLE
|
||||
|
Loading…
x
Reference in New Issue
Block a user