Source snapshot from Powershell/openssh-portable:latestw_cwb

This commit is contained in:
Manoj Ampalam 2017-01-03 14:46:33 -08:00
parent 15c6a77338
commit a4b577b5a0
51 changed files with 785 additions and 1373 deletions

2
README
View File

@ -1,4 +1,4 @@
See https://www.openssh.com/releasenotes.html#7.3p1 for the release notes. See https://www.openssh.com/releasenotes.html#7.4p1 for the release notes.
Please read https://www.openssh.com/report.html for bug reporting Please read https://www.openssh.com/report.html for bug reporting
instructions and note that we do not use Github for bug reporting or instructions and note that we do not use Github for bug reporting or

View File

@ -1,10 +1,10 @@
version: 0.0.4.0.{build} version: 0.0.6.0.{build}
image: Visual Studio 2015 image: Visual Studio 2015
branches: branches:
only: only:
- V_7_3w - latestw_all
- latestw_cwb - latestw_all_openssl
init: init:
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))

8
auth.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth.c,v 1.118 2016/11/08 22:04:34 djm Exp $ */ /* $OpenBSD: auth.c,v 1.119 2016/12/15 21:29:05 dtucker Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* *
@ -192,7 +192,7 @@ allowed_user(struct passwd * pw)
/* Return false if user is listed in DenyUsers */ /* Return false if user is listed in DenyUsers */
if (options.num_deny_users > 0) { if (options.num_deny_users > 0) {
for (i = 0; i < options.num_deny_users; i++) for (i = 0; i < options.num_deny_users; i++) {
r = match_user(pw->pw_name, hostname, ipaddr, r = match_user(pw->pw_name, hostname, ipaddr,
options.deny_users[i]); options.deny_users[i]);
if (r < 0) { if (r < 0) {
@ -204,6 +204,7 @@ allowed_user(struct passwd * pw)
pw->pw_name, hostname); pw->pw_name, hostname);
return 0; return 0;
} }
}
} }
/* Return false if AllowUsers isn't empty and user isn't listed there */ /* Return false if AllowUsers isn't empty and user isn't listed there */
if (options.num_allow_users > 0) { if (options.num_allow_users > 0) {
@ -576,7 +577,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
struct stat st; struct stat st;
int fd; int fd;
FILE *f; FILE *f;
#ifdef WINDOWS #ifdef WINDOWS
/* Windows POSIX adpater does not support fdopen() on open(file)*/ /* Windows POSIX adpater does not support fdopen() on open(file)*/
if ((f = fopen(file, "r")) == NULL) { if ((f = fopen(file, "r")) == NULL) {
@ -616,6 +617,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
return NULL; return NULL;
} }
#endif /* !WINDOWS */ #endif /* !WINDOWS */
return f; return f;
} }

View File

@ -245,10 +245,11 @@ userauth_pubkey(Authctxt *authctxt)
* if a user is not allowed to login. is this an * if a user is not allowed to login. is this an
* issue? -markus * issue? -markus
*/ */
#ifndef WINDOWS #ifdef WINDOWS /* key validation in done in agent for Windows */
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0)))
#endif /* !WINDOWS */
{ {
#else /* !WINDOWS */
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) {
#endif /* !WINDOWS */
packet_start(SSH2_MSG_USERAUTH_PK_OK); packet_start(SSH2_MSG_USERAUTH_PK_OK);
packet_put_string(pkalg, alen); packet_put_string(pkalg, alen);
packet_put_string(pkblob, blen); packet_put_string(pkblob, blen);

View File

@ -2049,6 +2049,7 @@ channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset)
c->notbefore = monotime() + 1; c->notbefore = monotime() + 1;
return; return;
} }
#ifndef WINDOWS /*TODO - implement user check for Windows*/ #ifndef WINDOWS /*TODO - implement user check for Windows*/
if (getpeereid(newsock, &euid, &egid) < 0) { if (getpeereid(newsock, &euid, &egid) < 0) {
error("%s getpeereid failed: %s", __func__, error("%s getpeereid failed: %s", __func__,

View File

@ -1273,6 +1273,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
} }
continue; continue;
#endif /* !WINDOWS */ #endif /* !WINDOWS */
case '?': case '?':
print_escape_help(berr, escape_char, compat20, print_escape_help(berr, escape_char, compat20,
(c && c->ctl_chan != -1), (c && c->ctl_chan != -1),

View File

@ -1,4 +1,4 @@
%define ver 7.3p1 %define ver 7.4p1
%define rel 1 %define rel 1
# OpenSSH privilege separation requires a user & group ID # OpenSSH privilege separation requires a user & group ID

View File

@ -13,7 +13,7 @@
Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation
Name: openssh Name: openssh
Version: 7.3p1 Version: 7.4p1
URL: https://www.openssh.com/ URL: https://www.openssh.com/
Release: 1 Release: 1
Source0: openssh-%{version}.tar.gz Source0: openssh-%{version}.tar.gz

View File

@ -3,6 +3,7 @@ Set-StrictMode -Version Latest
[string] $script:platform = $env:PROCESSOR_ARCHITECTURE [string] $script:platform = $env:PROCESSOR_ARCHITECTURE
[string] $script:vcPath = $null [string] $script:vcPath = $null
[System.IO.DirectoryInfo] $script:OpenSSHRoot = $null [System.IO.DirectoryInfo] $script:OpenSSHRoot = $null
[System.IO.DirectoryInfo] $script:gitRoot = $null
[bool] $script:Verbose = $false [bool] $script:Verbose = $false
[string] $script:BuildLogFile = $null [string] $script:BuildLogFile = $null
@ -268,6 +269,34 @@ function Start-SSHBootstrap
} }
} }
function Clone-Win32OpenSSH
{
$win32OpenSSHPath = join-path $script:gitRoot "Win32-OpenSSH"
if (-not (Test-Path -Path $win32OpenSSHPath -PathType Container))
{
Write-BuildMsg -AsInfo -Message "clone repo Win32-OpenSSH"
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"
Push-Location $win32OpenSSHPath
git fetch -q origin
git checkout -qf L1-Prod
Pop-Location
}
function Copy-OpenSSLSDK
{
$sourcePath = Join-Path $script:gitRoot "Win32-OpenSSH\contrib\win32\openssh\OpenSSLSDK"
Write-BuildMsg -AsInfo -Message "copying $sourcePath"
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 Start-SSHBuild function Start-SSHBuild
{ {
[CmdletBinding(SupportsShouldProcess=$false)] [CmdletBinding(SupportsShouldProcess=$false)]
@ -286,6 +315,8 @@ function Start-SSHBuild
# Get openssh-portable root # Get openssh-portable root
$script:OpenSSHRoot = Get-Item -Path $repositoryRoot.FullName $script:OpenSSHRoot = Get-Item -Path $repositoryRoot.FullName
$script:gitRoot = split-path $script:OpenSSHRoot
if($PSBoundParameters.ContainsKey("Verbose")) if($PSBoundParameters.ContainsKey("Verbose"))
{ {
@ -302,6 +333,9 @@ function Start-SSHBuild
Write-BuildMsg -AsInfo -Message "Build Log: $($script:BuildLogFile)" Write-BuildMsg -AsInfo -Message "Build Log: $($script:BuildLogFile)"
Start-SSHBootstrap Start-SSHBootstrap
Clone-Win32OpenSSH
Copy-OpenSSLSDK
$msbuildCmd = "msbuild.exe" $msbuildCmd = "msbuild.exe"
$solutionFile = Get-SolutionFile -root $repositoryRoot.FullName $solutionFile = Get-SolutionFile -root $repositoryRoot.FullName
$cmdMsg = @("${solutionFile}", "/p:Platform=${NativeHostArch}", "/p:Configuration=${Configuration}", "/fl", "/flp:LogFile=${script:BuildLogFile}`;Append`;Verbosity=diagnostic") $cmdMsg = @("${solutionFile}", "/p:Platform=${NativeHostArch}", "/p:Configuration=${Configuration}", "/fl", "/flp:LogFile=${script:BuildLogFile}`;Append`;Verbosity=diagnostic")
@ -380,4 +414,4 @@ function Get-RepositoryRoot
throw new-object System.IO.DirectoryNotFoundException("Could not find the root of the GIT repository") throw new-object System.IO.DirectoryNotFoundException("Could not find the root of the GIT repository")
} }
Export-ModuleMember -Function Start-SSHBuild, Get-RepositoryRoot, Get-BuildLogFile Export-ModuleMember -Function Start-SSHBuild, Get-RepositoryRoot, Get-BuildLogFile, Clone-Win32OpenSSH, Copy-OpenSSLSDK

View File

@ -876,7 +876,7 @@
/* #undef HAVE_SET_ID */ /* #undef HAVE_SET_ID */
/* Define to 1 if you have the `SHA256_Update' function. */ /* Define to 1 if you have the `SHA256_Update' function. */
#define HAVE_SHA256_UPDATE 1 /* #undef HAVE_SHA256_UPDATE */
/* Define to 1 if you have the <sha2.h> header file. */ /* Define to 1 if you have the <sha2.h> header file. */
/* #undef HAVE_SHA2_H */ /* #undef HAVE_SHA2_H */

View File

@ -1,11 +1,15 @@
$scriptpath = $MyInvocation.MyCommand.Path # @manojampalam - authored initial script
# @friism - Fixed issue with invalid SDDL on Set-Acl
$scriptpath = $MyInvocation.MyCommand.Path
$scriptdir = Split-Path $scriptpath $scriptdir = Split-Path $scriptpath
$sshdpath = Join-Path $scriptdir "sshd.exe" $sshdpath = Join-Path $scriptdir "sshd.exe"
$sshagentpath = Join-Path $scriptdir "ssh-agent.exe" $sshagentpath = Join-Path $scriptdir "ssh-agent.exe"
$logsdir = Join-Path $scriptdir "logs" $logsdir = Join-Path $scriptdir "logs"
$ntrights = "ntrights.exe -u `"NT SERVICE\SSHD`" +r SeAssignPrimaryTokenPrivilege" $account = "NT SERVICE\SSHD"
$ntrights = "ntrights.exe -u `"{0}`" +r SeAssignPrimaryTokenPrivilege" -f $account
if (-not (Test-Path $sshdpath)) { if (-not (Test-Path $sshdpath)) {
throw "sshd.exe is not present in script path" throw "sshd.exe is not present in script path"
@ -27,7 +31,7 @@ New-Service -Name ssh-agent -BinaryPathName $sshagentpath -Description "SSH Agen
cmd.exe /c 'sc.exe sdset ssh-agent D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;RP;;;AU)' 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 New-Service -Name sshd -BinaryPathName $sshdpath -Description "SSH Deamon" -StartupType Manual -DependsOn ssh-agent | Out-Null
sc.exe config sshd obj= "NT SERVICE\SSHD" sc.exe config sshd obj= $account
Push-Location Push-Location
cd $scriptdir cd $scriptdir
@ -35,9 +39,9 @@ cmd.exe /c $ntrights
Pop-Location Pop-Location
mkdir $logsdir > $null mkdir $logsdir > $null
$sddl = "O:SYG:DUD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x12019f;;;S-1-5-80-3847866527-469524349-687026318-516638107-1125189541)" $rights = [System.Security.AccessControl.FileSystemRights]"Read, Write"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($account, $rights, "ContainerInherit,ObjectInherit", "None", "Allow")
$acl = Get-Acl -Path $logsdir $acl = Get-Acl -Path $logsdir
$acl.SetSecurityDescriptorSddlForm($sddl) $Acl.SetAccessRule($accessRule)
Set-Acl -Path $logsdir -AclObject $acl Set-Acl -Path $logsdir -AclObject $acl
Write-Host -ForegroundColor Green "sshd and ssh-agent services successfully installed" Write-Host -ForegroundColor Green "sshd and ssh-agent services successfully installed"

View File

@ -194,7 +194,7 @@
<ExcludedFromBuild Condition="$(UseOpenSSL)==false">true</ExcludedFromBuild> <ExcludedFromBuild Condition="$(UseOpenSSL)==false">true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="$(OpenSSH-Src-Path)digest-libc.c"> <ClCompile Include="$(OpenSSH-Src-Path)digest-libc.c">
<ExcludedFromBuild Condition="$(UseOpenSSL)==false">true</ExcludedFromBuild> <ExcludedFromBuild Condition="$(UseOpenSSL)==true">true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="$(OpenSSH-Src-Path)dispatch.c" /> <ClCompile Include="$(OpenSSH-Src-Path)dispatch.c" />
<ClCompile Include="$(OpenSSH-Src-Path)dns.c" /> <ClCompile Include="$(OpenSSH-Src-Path)dns.c" />
@ -285,7 +285,9 @@
<ClCompile Include="$(OpenSSH-Src-Path)sandbox-pledge.c" /> <ClCompile Include="$(OpenSSH-Src-Path)sandbox-pledge.c" />
<ClCompile Include="$(OpenSSH-Src-Path)utf8.c" /> <ClCompile Include="$(OpenSSH-Src-Path)utf8.c" />
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\ttymodes_windows.c" /> <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\ttymodes_windows.c" />
<ClCompile Include="..\..\..\digest-openssl.c" /> <ClCompile Include="$(OpenSSH-Src-Path)digest-openssl.c">
<ExcludedFromBuild Condition="$(UseOpenSSL)==false">true</ExcludedFromBuild>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="$(OpenSSH-Src-Path)crypto-wrap.h" /> <ClInclude Include="$(OpenSSH-Src-Path)crypto-wrap.h" />

Binary file not shown.

View File

@ -155,11 +155,11 @@
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\win32_dirent.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\win32_dirent.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\no-ops.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\no-ops.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\win32_zlib.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\win32_zlib.c" />
<ClCompile Include="..\win32compat\ansiprsr.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ansiprsr.c" />
<ClCompile Include="..\win32compat\conio.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\conio.c" />
<ClCompile Include="..\win32compat\console.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\console.c" />
<ClCompile Include="..\win32compat\tncon.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tncon.c" />
<ClCompile Include="..\win32compat\tnnet.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tnnet.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" /> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />
@ -198,6 +198,7 @@
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\termios.h" /> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\termios.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\dirent.h" /> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\dirent.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\pwd.h" /> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\pwd.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\misc_internal.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View File

@ -117,6 +117,7 @@
<Filter>inc</Filter> <Filter>inc</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\pwd.h" /> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\pwd.h" />
<ClInclude Include="..\win32compat\misc_internal.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="inc"> <Filter Include="inc">

View File

@ -199,9 +199,14 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
return -1; return -1;
} }
cf_flags->dwShareMode = 0;
switch (rwflags) { switch (rwflags) {
case O_RDONLY: case O_RDONLY:
cf_flags->dwDesiredAccess = GENERIC_READ; cf_flags->dwDesiredAccess = GENERIC_READ;
/*todo: need to review to make sure all flags are correct*/
if (flags & O_NONBLOCK)
cf_flags->dwShareMode = FILE_SHARE_READ;
break; break;
case O_WRONLY: case O_WRONLY:
cf_flags->dwDesiredAccess = GENERIC_WRITE; cf_flags->dwDesiredAccess = GENERIC_WRITE;
@ -211,8 +216,6 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
break; break;
} }
cf_flags->dwShareMode = 0;
cf_flags->securityAttributes.lpSecurityDescriptor = NULL; cf_flags->securityAttributes.lpSecurityDescriptor = NULL;
cf_flags->securityAttributes.bInheritHandle = TRUE; cf_flags->securityAttributes.bInheritHandle = TRUE;
cf_flags->securityAttributes.nLength = 0; cf_flags->securityAttributes.nLength = 0;
@ -230,7 +233,7 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
if (c_s_flags & O_APPEND) if (c_s_flags & O_APPEND)
cf_flags->dwDesiredAccess = FILE_APPEND_DATA; cf_flags->dwDesiredAccess = FILE_APPEND_DATA;
cf_flags->dwFlagsAndAttributes = FILE_FLAG_OVERLAPPED | SECURITY_IMPERSONATION; cf_flags->dwFlagsAndAttributes = FILE_FLAG_OVERLAPPED | SECURITY_IMPERSONATION | FILE_FLAG_BACKUP_SEMANTICS;
/*TODO - map mode */ /*TODO - map mode */

View File

@ -159,3 +159,6 @@ explicit_bzero(void *b, size_t len);
#define fopen w32_fopen_utf8 #define fopen w32_fopen_utf8
#define popen _popen #define popen _popen
#define pclose _pclose #define pclose _pclose
void convertToBackslash(char *str);
void convertToForwardslash(char *str);

View File

@ -36,6 +36,7 @@
#include "inc\sys\time.h" #include "inc\sys\time.h"
#include <time.h> #include <time.h>
#include <Shlwapi.h> #include <Shlwapi.h>
#include "misc_internal.h"
int usleep(unsigned int useconds) int usleep(unsigned int useconds)
{ {
@ -302,11 +303,25 @@ spawn_child(char* cmd, int in, int out, int err, DWORD flags) {
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
STARTUPINFOW si; STARTUPINFOW si;
BOOL b; BOOL b;
char* abs_cmd; char *abs_cmd, *t;
wchar_t * cmd_utf16; wchar_t * cmd_utf16;
int add_module_path = 0;
/* relative ? if so, add current module path to start */ /* should module path be added */
if (!(cmd && cmd[0] != '\0' && (cmd[1] == ':' || cmd[0] == '\\' || cmd[0] == '.'))) { do{
if(!cmd)
break;
t = cmd;
if (*t == '\"')
t++;
if (t[0] == '\0' || t[0] == '\\' || t[0] == '.' || t[1] == ':')
break;
add_module_path = 1;
} while (0);
/* add current module path to start if needed */
if (add_module_path) {
char* ctr; char* ctr;
abs_cmd = malloc(strlen(w32_programdir()) + 1 + strlen(cmd) + 1); abs_cmd = malloc(strlen(w32_programdir()) + 1 + strlen(cmd) + 1);
if (abs_cmd == NULL) { if (abs_cmd == NULL) {
@ -478,8 +493,6 @@ w32_chown(const char *pathname, unsigned int owner, unsigned int group) {
return -1; return -1;
} }
char *realpath_win(const char *path, char resolved[MAX_PATH]);
int int
w32_utimes(const char *filename, struct timeval *tvp) { w32_utimes(const char *filename, struct timeval *tvp) {
struct utimbuf ub; struct utimbuf ub;
@ -487,10 +500,7 @@ w32_utimes(const char *filename, struct timeval *tvp) {
ub.modtime = tvp[1].tv_sec; ub.modtime = tvp[1].tv_sec;
int ret; int ret;
// Skip the first '/' in the pathname wchar_t *resolvedPathName_utf16 = utf8_to_utf16(sanitized_path(filename));
char resolvedPathName[MAX_PATH];
realpath_win(filename, resolvedPathName);
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolvedPathName);
if (resolvedPathName_utf16 == NULL) { if (resolvedPathName_utf16 == NULL) {
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
@ -517,16 +527,9 @@ link(const char *oldpath, const char *newpath) {
int int
w32_rename(const char *old_name, const char *new_name) { w32_rename(const char *old_name, const char *new_name) {
// Skip the first '/' in the pathname wchar_t *resolvedOldPathName_utf16 = utf8_to_utf16(sanitized_path(old_name));
char resolvedOldPathName[MAX_PATH]; wchar_t *resolvedNewPathName_utf16 = utf8_to_utf16(sanitized_path(new_name));
realpath_win(old_name, resolvedOldPathName);
// Skip the first '/' in the pathname
char resolvedNewPathName[MAX_PATH];
realpath_win(new_name, resolvedNewPathName);
wchar_t *resolvedOldPathName_utf16 = utf8_to_utf16(resolvedOldPathName);
wchar_t *resolvedNewPathName_utf16 = utf8_to_utf16(resolvedNewPathName);
if (NULL == resolvedOldPathName_utf16 || NULL == resolvedNewPathName_utf16) { if (NULL == resolvedOldPathName_utf16 || NULL == resolvedNewPathName_utf16) {
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
@ -541,11 +544,8 @@ w32_rename(const char *old_name, const char *new_name) {
int int
w32_unlink(const char *path) { w32_unlink(const char *path) {
// Skip the first '/' in the pathname
char resolvedPathName[MAX_PATH]; wchar_t *resolvedPathName_utf16 = utf8_to_utf16(sanitized_path(path));
realpath_win(path, resolvedPathName);
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolvedPathName);
if (NULL == resolvedPathName_utf16) { if (NULL == resolvedPathName_utf16) {
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
@ -559,11 +559,7 @@ w32_unlink(const char *path) {
int int
w32_rmdir(const char *path) { w32_rmdir(const char *path) {
// Skip the first '/' in the pathname wchar_t *resolvedPathName_utf16 = utf8_to_utf16(sanitized_path(path));
char resolvedPathName[MAX_PATH];
realpath_win(path, resolvedPathName);
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolvedPathName);
if (NULL == resolvedPathName_utf16) { if (NULL == resolvedPathName_utf16) {
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
@ -606,11 +602,8 @@ w32_getcwd(char *buffer, int maxlen) {
int int
w32_mkdir(const char *path_utf8, unsigned short mode) { w32_mkdir(const char *path_utf8, unsigned short mode) {
// Skip the first '/' in the pathname
char resolvedPathName[MAX_PATH]; wchar_t *path_utf16 = utf8_to_utf16(sanitized_path(path_utf8));
realpath_win(path_utf8, resolvedPathName);
wchar_t *path_utf16 = utf8_to_utf16(resolvedPathName);
if (path_utf16 == NULL) { if (path_utf16 == NULL) {
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
@ -621,86 +614,62 @@ w32_mkdir(const char *path_utf8, unsigned short mode) {
return returnStatus; return returnStatus;
} }
void
getrnd(u_char *s, size_t len) {
HCRYPTPROV hProvider;
if (CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT) == FALSE ||
CryptGenRandom(hProvider, len, s) == FALSE ||
CryptReleaseContext(hProvider, 0) == FALSE)
DebugBreak();
}
int int
w32_stat(const char *path, struct w32_stat *buf) { w32_stat(const char *path, struct w32_stat *buf) {
// Skip the first '/' in the pathname return fileio_stat(sanitized_path(path), (struct _stat64*)buf);
char resolvedPathName[MAX_PATH];
realpath_win(path, resolvedPathName);
return fileio_stat(resolvedPathName, (struct _stat64*)buf);
} }
// if file is symbolic link, copy its link into "link" . // if file is symbolic link, copy its link into "link" .
int int
readlink(const char *path, char *link, int linklen) readlink(const char *path, char *link, int linklen)
{ {
// Skip the first '/' in the pathname strcpy_s(link, linklen, sanitized_path(path));
char resolvedPathName[MAX_PATH];
realpath_win(path, resolvedPathName);
strcpy_s(link, linklen, resolvedPathName);
return 0; return 0;
} }
// convert forward slash to back slash
void
convertToBackslash(char *str) {
while (*str) {
if (*str == '/')
*str = '\\';
str++;
}
}
// convert back slash to forward slash
void
convertToForwardslash(char *str) {
while (*str) {
if (*str == '\\')
*str = '/';
str++;
}
}
/* /*
* This method will expands all symbolic links and resolves references to /./, * This method will resolves references to /./, /../ and extra '/' characters in the null-terminated string named by
* /../ and extra '/' characters in the null-terminated string named by
* path to produce a canonicalized absolute pathname. * path to produce a canonicalized absolute pathname.
*/ */
char * char *
realpath(const char *path, char resolved[MAX_PATH]) realpath(const char *path, char resolved[MAX_PATH]) {
{
char tempPath[MAX_PATH]; char tempPath[MAX_PATH];
if ((0 == strcmp(path, "./")) || (0 == strcmp(path, "."))) { if (*path == '/' && *(path + 2) == ':')
tempPath[0] = '/'; strncpy(resolved, path + 1, strlen(path)); // skip the first '/'
_getcwd(&tempPath[1], sizeof(tempPath) - 1);
slashconvert(tempPath);
strncpy(resolved, tempPath, strlen(tempPath) + 1);
return resolved;
}
if (path[0] != '/')
strlcpy(resolved, path, sizeof(tempPath));
else else
strlcpy(resolved, path + 1, sizeof(tempPath)); strncpy(resolved, path, strlen(path) + 1);
backslashconvert(resolved); if (_fullpath(tempPath, resolved, MAX_PATH) == NULL)
PathCanonicalizeA(tempPath, resolved); return NULL;
slashconvert(tempPath);
convertToForwardslash(tempPath);
// Store terminating slash in 'X:/' on Windows.
if (tempPath[1] == ':' && tempPath[2] == 0) {
tempPath[2] = '/';
tempPath[3] = 0;
}
resolved[0] = '/'; // will be our first slash in /x:/users/test1 format resolved[0] = '/'; // will be our first slash in /x:/users/test1 format
strncpy(resolved + 1, tempPath, sizeof(tempPath) - 1); strncpy(resolved + 1, tempPath, sizeof(tempPath) - 1);
return resolved; return resolved;
} }
// like realpathWin32() but takes out the first slash so that windows systems can work on the actual file or directory
char *
realpath_win(const char *path, char resolved[MAX_PATH])
{
char tempPath[MAX_PATH];
realpath(path, tempPath);
strncpy(resolved, &tempPath[1], sizeof(tempPath) - 1);
return resolved;
}
// Maximum reparse buffer info size. The max user defined reparse // Maximum reparse buffer info size. The max user defined reparse
// data is 16KB, plus there's a header. // data is 16KB, plus there's a header.
#define MAX_REPARSE_SIZE 17000 #define MAX_REPARSE_SIZE 17000
@ -737,8 +706,7 @@ typedef struct _REPARSE_DATA_BUFFER {
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
BOOL BOOL
ResolveLink(wchar_t * tLink, wchar_t *ret, DWORD * plen, DWORD Flags) ResolveLink(wchar_t * tLink, wchar_t *ret, DWORD * plen, DWORD Flags) {
{
HANDLE fileHandle; HANDLE fileHandle;
BYTE reparseBuffer[MAX_REPARSE_SIZE]; BYTE reparseBuffer[MAX_REPARSE_SIZE];
PBYTE reparseData; PBYTE reparseData;

View File

@ -0,0 +1,3 @@
/* removes first '/' for Windows paths that are unix styled. Ex: /c:/ab.cd */
#define sanitized_path(p) (((p)[0] == '/' && (p)[1] != '\0' && (p)[2] == ':')? (p)+1 : (p))

View File

@ -231,32 +231,6 @@ char *user_from_uid(uid_t uid, int nouser) {
return "-"; return "-";
} }
/* TODO - this is moved from realpath.c in openbsdcompat. Review and finalize its position*/
#include <Shlwapi.h>
void backslashconvert(char *str)
{
while (*str) {
if (*str == '/')
*str = '\\'; // convert forward slash to back slash
str++;
}
}
// convert back slash to forward slash
void slashconvert(char *str)
{
while (*str) {
if (*str == '\\')
*str = '/'; // convert back slash to forward slash
str++;
}
}
uid_t uid_t
getuid(void) { getuid(void) {
return 0; return 0;

View File

@ -40,6 +40,7 @@
#include <winioctl.h> #include <winioctl.h>
#include "Shlwapi.h" #include "Shlwapi.h"
#include <sys\utime.h> #include <sys\utime.h>
#include "misc_internal.h"
/* internal table that stores the fd to w32_io mapping*/ /* internal table that stores the fd to w32_io mapping*/
struct w32fd_table { struct w32fd_table {
@ -347,7 +348,7 @@ w32_pipe(int *pfds) {
pio[0]->handle, pio[0], read_index, pio[1]->handle, pio[1], write_index); pio[0]->handle, pio[0], read_index, pio[1]->handle, pio[1], write_index);
return 0; return 0;
} }
char *realpath_win(const char *path, char resolved[MAX_PATH]);
int int
w32_open(const char *pathname, int flags, ...) { w32_open(const char *pathname, int flags, ...) {
int min_index = fd_table_get_min_index(); int min_index = fd_table_get_min_index();
@ -357,18 +358,14 @@ w32_open(const char *pathname, int flags, ...) {
if (min_index == -1) if (min_index == -1)
return -1; return -1;
// Skip the first '/' in the pathname pio = fileio_open(sanitized_path(pathname), flags, 0);
char resolvedPathName[MAX_PATH];
realpath_win(pathname, resolvedPathName);
pio = fileio_open(resolvedPathName, flags, 0);
if (pio == NULL) if (pio == NULL)
return -1; return -1;
pio->type = NONSOCK_FD; pio->type = NONSOCK_FD;
fd_table_set(pio, min_index); fd_table_set(pio, min_index);
debug("open - handle:%p, io:%p, fd:%d", pio->handle, pio, min_index); debug("open - handle:%p, io:%p, fd:%d", pio->handle, pio, min_index);
debug3("open - path:%s", resolvedPathName); debug3("open - path:%s", pathname);
return min_index; return min_index;
} }

View File

@ -11,6 +11,7 @@
#include "inc\dirent.h" #include "inc\dirent.h"
#include "inc\libgen.h" #include "inc\libgen.h"
#include "misc_internal.h"
struct DIR_ { struct DIR_ {
@ -19,8 +20,6 @@ struct DIR_ {
int first; int first;
}; };
char * realpath_win(const char *path, char resolved[MAX_PATH]);
/* Open a directory stream on NAME. /* Open a directory stream on NAME.
Return a DIR stream on the directory, or NULL if it could not be opened. */ Return a DIR stream on the directory, or NULL if it could not be opened. */
DIR * opendir(const char *name) DIR * opendir(const char *name)
@ -32,11 +31,7 @@ DIR * opendir(const char *name)
wchar_t* wname = NULL; wchar_t* wname = NULL;
int needed; int needed;
// Skip the first '/' in the pathname if ((wname = utf8_to_utf16(sanitized_path(name))) == NULL) {
char resolvedPathName[MAX_PATH];
realpath_win(name, resolvedPathName);
if ((wname = utf8_to_utf16(resolvedPathName)) == NULL) {
errno = ENOMEM; errno = ENOMEM;
return NULL; return NULL;
} }

4
dh.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: dh.c,v 1.61 2016/09/12 01:22:38 deraadt Exp $ */ /* $OpenBSD: dh.c,v 1.62 2016/12/15 21:20:41 dtucker Exp $ */
/* /*
* Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2000 Niels Provos. All rights reserved.
* *
@ -152,7 +152,7 @@ choose_dh(int min, int wantbits, int max)
struct dhgroup dhg; struct dhgroup dhg;
if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL) { if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL) {
logit("WARNING: could open open %s (%s), using fixed modulus", logit("WARNING: could not open %s (%s), using fixed modulus",
_PATH_DH_MODULI, strerror(errno)); _PATH_DH_MODULI, strerror(errno));
return (dh_new_group_fallback(max)); return (dh_new_group_fallback(max));
} }

1
log.c
View File

@ -446,7 +446,6 @@ do_log(LogLevel level, const char *fmt, va_list args)
} }
strnvis(fmtbuf, msgbuf, sizeof(fmtbuf), strnvis(fmtbuf, msgbuf, sizeof(fmtbuf),
log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS); log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS);
if (log_handler != NULL) { if (log_handler != NULL) {
/* Avoid recursion */ /* Avoid recursion */
tmp_handler = log_handler; tmp_handler = log_handler;

2
misc.c
View File

@ -432,7 +432,6 @@ char *
colon(char *cp) colon(char *cp)
{ {
int flag = 0; int flag = 0;
int len = 0;
if (*cp == ':') /* Leading colon is part of file name. */ if (*cp == ':') /* Leading colon is part of file name. */
return NULL; return NULL;
@ -627,6 +626,7 @@ tilde_expand_filename(const char *filename, uid_t uid)
if (xasprintf(&ret, "%s%s%s", pw->pw_dir, sep, filename) >= PATH_MAX) if (xasprintf(&ret, "%s%s%s", pw->pw_dir, sep, filename) >= PATH_MAX)
fatal("tilde_expand_filename: Path too long"); fatal("tilde_expand_filename: Path too long");
return (ret); return (ret);
} }

View File

@ -78,6 +78,18 @@ _rs_init(u_char *buf, size_t n)
} }
#ifndef WITH_OPENSSL #ifndef WITH_OPENSSL
#ifdef WINDOWS
#include <Wincrypt.h>
static void
getrnd(u_char *s, size_t len) {
HCRYPTPROV hProvider;
if (CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT) == FALSE ||
CryptGenRandom(hProvider, len, s) == FALSE ||
CryptReleaseContext(hProvider, 0) == FALSE)
DebugBreak();
}
#else /* !WINDOWS */
#define SSH_RANDOM_DEV "/dev/urandom" #define SSH_RANDOM_DEV "/dev/urandom"
/* XXX use getrandom() if supported on Linux */ /* XXX use getrandom() if supported on Linux */
static void static void
@ -101,6 +113,7 @@ getrnd(u_char *s, size_t len)
} }
close(fd); close(fd);
} }
#endif /* !WINDOWS */
#endif #endif
static void static void

View File

@ -469,6 +469,7 @@ default_ssh_port(void)
static int static int
execute_in_shell(const char *cmd) execute_in_shell(const char *cmd)
{ {
char *shell;
#ifdef WINDOWS #ifdef WINDOWS
fatal("LocalCommand execution is not supported on Windows yet"); fatal("LocalCommand execution is not supported on Windows yet");
return 0; return 0;
@ -1725,6 +1726,7 @@ read_config_file_depth(const char *filename, struct passwd *pw,
fatal("Bad owner or permissions on %s", filename); fatal("Bad owner or permissions on %s", filename);
} }
#endif /* !WINDOWS */ #endif /* !WINDOWS */
debug("Reading configuration data %.200s", filename); debug("Reading configuration data %.200s", filename);
/* /*

View File

@ -145,6 +145,8 @@ read_passphrase(const char *prompt, int flags)
/* prompt user */ /* prompt user */
wchar_t* wtmp = utf8_to_utf16(prompt); wchar_t* wtmp = utf8_to_utf16(prompt);
if (wtmp == NULL)
fatal("unable to alloc memory");
_cputws(wtmp); _cputws(wtmp);
free(wtmp); free(wtmp);
@ -158,28 +160,28 @@ read_passphrase(const char *prompt, int flags)
buf[len] = (unsigned char)_getch(); buf[len] = (unsigned char)_getch();
if (buf[len] == '\r') { if (buf[len] == '\r') {
if (_kbhit()) if (_kbhit()) /* read linefeed if its there */
_getch(); // read linefeed if its there _getch();
break; break;
} }
else if (buf[len] == '\n') { else if (buf[len] == '\n') {
break; break;
} }
else if (buf[len] == '\b') { // backspace else if (buf[len] == '\b') { /* backspace */
if (len > 0) if (len > 0)
len--; // overwrite last character len--; /* overwrite last character */
} }
else if (buf[len] == '\003') { else if (buf[len] == '\003') {
/* exit on Ctrl+C */ /* exit on Ctrl+C */
fatal(""); fatal("");
} }
else { else {
len++; // keep reading in the loop len++; /* keep reading in the loop */
} }
} }
buf[len] = '\0'; // get rid of the cr/lf buf[len] = '\0'; /* get rid of the cr/lf */
_cputs("\n"); // show a newline as we do not echo password or the line _cputs("\n"); /*show a newline as we do not echo password or the line */
ret = xstrdup(buf); ret = xstrdup(buf);
@ -188,7 +190,6 @@ read_passphrase(const char *prompt, int flags)
return ret; return ret;
#else /* !WINDOWS */ #else /* !WINDOWS */
char *askpass = NULL, *ret, buf[1024]; char *askpass = NULL, *ret, buf[1024];
int rppflags, use_askpass = 0, ttyfd; int rppflags, use_askpass = 0, ttyfd;
@ -235,9 +236,7 @@ read_passphrase(const char *prompt, int flags)
ret = xstrdup(buf); ret = xstrdup(buf);
explicit_bzero(buf, sizeof(buf)); explicit_bzero(buf, sizeof(buf));
return ret; return ret;
#endif /* !WINDOWS */ #endif /* !WINDOWS */
} }
int int

View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.93 2016/11/01 13:43:27 tb Exp $ # $OpenBSD: Makefile,v 1.94 2016/12/16 03:51:19 dtucker Exp $
REGRESS_TARGETS= unit t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t-exec REGRESS_TARGETS= unit t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t-exec
tests: prep $(REGRESS_TARGETS) tests: prep $(REGRESS_TARGETS)
@ -78,7 +78,8 @@ LTESTS= connect \
hostkey-rotate \ hostkey-rotate \
principals-command \ principals-command \
cert-file \ cert-file \
cfginclude cfginclude \
allow-deny-users
# dhgex \ # dhgex \

View File

@ -0,0 +1,40 @@
# Public Domain
# Zev Weiss, 2016
tid="AllowUsers/DenyUsers"
me="$LOGNAME"
if [ "x$me" = "x" ]; then
me=`whoami`
fi
other="nobody"
test_auth()
{
deny="$1"
allow="$2"
should_succeed="$3"
failmsg="$4"
start_sshd -oDenyUsers="$deny" -oAllowUsers="$allow"
${SSH} -F $OBJ/ssh_config "$me@somehost" true
status=$?
if (test $status -eq 0 && ! $should_succeed) \
|| (test $status -ne 0 && $should_succeed); then
fail "$failmsg"
fi
stop_sshd
}
# DenyUsers AllowUsers should_succeed failure_message
test_auth "" "" true "user in neither DenyUsers nor AllowUsers denied"
test_auth "$other $me" "" false "user in DenyUsers allowed"
test_auth "$me $other" "" false "user in DenyUsers allowed"
test_auth "" "$other" false "user not in AllowUsers allowed"
test_auth "" "$other $me" true "user in AllowUsers denied"
test_auth "" "$me $other" true "user in AllowUsers denied"
test_auth "$me $other" "$me $other" false "user in both DenyUsers and AllowUsers allowed"
test_auth "$other $me" "$other $me" false "user in both DenyUsers and AllowUsers allowed"

View File

@ -1,4 +1,4 @@
# $OpenBSD: cert-file.sh,v 1.2 2015/09/24 07:15:39 djm Exp $ # $OpenBSD: cert-file.sh,v 1.4 2016/12/16 02:48:55 djm Exp $
# Placed in the Public Domain. # Placed in the Public Domain.
tid="ssh with certificates" tid="ssh with certificates"

View File

@ -1,4 +1,4 @@
# $OpenBSD: login-timeout.sh,v 1.7 2014/03/13 20:44:49 djm Exp $ # $OpenBSD: login-timeout.sh,v 1.8 2016/12/16 01:06:27 dtucker Exp $
# Placed in the Public Domain. # Placed in the Public Domain.
tid="connect after login grace timeout" tid="connect after login grace timeout"
@ -17,7 +17,7 @@ if [ $? -ne 0 ]; then
fail "ssh connect after login grace timeout failed with privsep" fail "ssh connect after login grace timeout failed with privsep"
fi fi
$SUDO kill `$SUDO cat $PIDFILE` stop_sshd
trace "test login grace without privsep" trace "test login grace without privsep"
echo "UsePrivilegeSeparation no" >> $OBJ/sshd_config echo "UsePrivilegeSeparation no" >> $OBJ/sshd_config

View File

@ -26,13 +26,12 @@ Describe "Tests for scp command" -Tags "CI" {
$client.SetupClient($server) $client.SetupClient($server)
$server.SetupServer($client) $server.SetupServer($client)
$testData = @( $testData = @(
<# known issue 340
@{ @{
Title = 'Simple copy local file to local file' Title = 'Simple copy local file to local file'
Source = $SourceFilePath Source = $SourceFilePath
Destination = $DestinationFilePath Destination = $DestinationFilePath
},#> },
@{ @{
Title = 'Simple copy local file to remote file' Title = 'Simple copy local file to remote file'
Source = $SourceFilePath Source = $SourceFilePath
@ -42,13 +41,12 @@ Describe "Tests for scp command" -Tags "CI" {
Title = 'Simple copy remote file to local file' Title = 'Simple copy remote file to local file'
Source = "$($server.localAdminUserName)@$($server.MachineName):$SourceFilePath" Source = "$($server.localAdminUserName)@$($server.MachineName):$SourceFilePath"
Destination = $DestinationFilePath Destination = $DestinationFilePath
}, },
<# known issue 340
@{ @{
Title = 'Simple copy local file to local dir' Title = 'Simple copy local file to local dir'
Source = $SourceFilePath Source = $SourceFilePath
Destination = $DestinationDir Destination = $DestinationDir
},#> },
@{ @{
Title = 'simple copy local file to remote dir' Title = 'simple copy local file to remote dir'
Source = $SourceFilePath Source = $SourceFilePath
@ -66,7 +64,7 @@ Describe "Tests for scp command" -Tags "CI" {
Title = 'copy from local dir to remote dir' Title = 'copy from local dir to remote dir'
Source = $sourceDir Source = $sourceDir
Destination = "$($server.localAdminUserName)@$($server.MachineName):$DestinationDir" Destination = "$($server.localAdminUserName)@$($server.MachineName):$DestinationDir"
}, },
@{ @{
Title = 'copy from local dir to local dir' Title = 'copy from local dir to local dir'
Source = $sourceDir Source = $sourceDir
@ -84,16 +82,16 @@ Describe "Tests for scp command" -Tags "CI" {
$client.CleanupClient() $client.CleanupClient()
$server.CleanupServer() $server.CleanupServer()
Get-Item $SourceDir | Remove-Item -Recurse -Force -ea silentlycontinue Get-Item $SourceDir | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
Get-Item $DestinationDir | Remove-Item -Recurse -Force -ea silentlycontinue Get-Item $DestinationDir | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
} }
BeforeEach { BeforeAll {
$null = New-Item $DestinationDir -ItemType directory -Force $null = New-Item $DestinationDir -ItemType directory -Force
} }
AfterEach { AfterEach {
Get-ChildItem $DestinationDir -Recurse -Directory | Remove-Item -Recurse -Force -ea silentlycontinue Get-ChildItem $DestinationDir -Recurse | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
} }
<#Context "SCP usage" { <#Context "SCP usage" {
@ -121,7 +119,7 @@ Describe "Tests for scp command" -Tags "CI" {
$equal | Should Be $true $equal | Should Be $true
} }
<#It 'Directory recursive Copy with -i option: <Title> ' -TestCases:$testData1 { It 'Directory recursive Copy with -i option: <Title> ' -TestCases:$testData1 {
param([string]$Title, $Source, $Destination) param([string]$Title, $Source, $Destination)
.\scp -r -i $identifyFile $Source $Destination .\scp -r -i $identifyFile $Source $Destination
@ -129,10 +127,10 @@ Describe "Tests for scp command" -Tags "CI" {
$equal = @(Compare-Object (Get-Item -path $SourceDir ) (Get-Item -path (join-path $DestinationDir $SourceDirName) ) -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 $equal | Should Be $true
#known issue 364
#$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0 $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 $equal | Should Be $true
}#> }
} }
#this context only run on windows #this context only run on windows
@ -149,37 +147,34 @@ Describe "Tests for scp command" -Tags "CI" {
#cleanup single signon #cleanup single signon
.\ssh-add.exe -D .\ssh-add.exe -D
} }
It 'File Copy with -S option (positive)' { It 'File Copy with -S option (positive)' {
.\scp -S .\ssh.exe $SourceFilePath "$($server.localAdminUserName)@$($server.MachineName):$DestinationFilePath" .\scp -S .\ssh.exe $SourceFilePath "$($server.localAdminUserName)@$($server.MachineName):$DestinationFilePath"
#validate file content. DestPath is the path to the file. #validate file content. DestPath is the path to the file.
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length).Length -eq 0 #todo: add LastWriteTime in comparison when issue is fixed $equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length).Length -eq 0
$equal | Should Be $true $equal | Should Be $true
} }
<#It 'File Copy with -p -c -v option: <Title> ' -TestCases:$testData { It 'File Copy with -p -c -v option: <Title> ' -TestCases:$testData {
param([string]$Title, $Source, $Destination) param([string]$Title, $Source, $Destination)
.\scp -p -c aes128-ctr -C $Source $Destination #Todo: add -v after it is supported. .\scp -p -c aes128-ctr -v -C $Source $Destination
#validate file content. DestPath is the path to the file. #validate file content. DestPath is the path to the file.
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length).Length -eq 0 #todo: add LastWriteTime in comparison when issue is fixed $equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length, LastWriteTime.DateTime).Length -eq 0
$equal | Should Be $true $equal | Should Be $true
}#> }
<# known issue 369 It 'Directory recursive Copy with -r -p -v option: <Title> ' -TestCases:$testData1 {
It 'Directory recursive Copy with -v option: <Title> ' -TestCases:$testData1 { param([string]$Title, $Source, $Destination)
param([string]$Title, $Source, $Destination) .\scp -r -p -c aes128-ctr -v $Source $Destination
.\scp -r -p $Source $Destination
$equal = @(Compare-Object (Get-Item -path $SourceDir ) (Get-Item -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length, LastWriteTime).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
$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 $equal | Should Be $true
}
#known issue 364
#$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length, LastWriteTime).Length -eq 0
#$equal | Should Be $true
}#>
} }
Context "Key based authentication with -i -C -q options. host keys are not secured on server" { Context "Key based authentication with -i -C -q options. host keys are not secured on server" {
@ -192,23 +187,20 @@ Describe "Tests for scp command" -Tags "CI" {
.\scp -i $identifyFile -C -q $Source $Destination .\scp -i $identifyFile -C -q $Source $Destination
#validate file content. DestPath is the path to the file. #validate file content. DestPath is the path to the file.
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length).Length -eq 0 # need to validate LastWriteTime after issue 356 is fixed. $equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length).Length -eq 0
$equal | Should Be $true $equal | Should Be $true
} }
<#It 'Directory recursive Copy with -i and -q options: <Title> ' -TestCases:$testData1 { It 'Directory recursive Copy with -i and -q options: <Title> ' -TestCases:$testData1 {
param([string]$Title, $Source, $Destination) param([string]$Title, $Source, $Destination)
.\scp -i $identifyFile -r -q $Source $Destination .\scp -i $identifyFile -r -q $Source $Destination
$equal = @(Compare-Object (Get-Item -path $SourceDir ) (Get-Item -path (join-path $DestinationDir $SourceDirName) ) -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 $equal | Should Be $true
#known issue 364 $equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
#$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
#$equal | Should Be $true }
}#> }
}
} }

View File

@ -1,4 +1,4 @@
# $OpenBSD: reexec.sh,v 1.8 2015/03/03 22:35:19 markus Exp $ # $OpenBSD: reexec.sh,v 1.10 2016/12/16 01:06:27 dtucker Exp $
# Placed in the Public Domain. # Placed in the Public Domain.
tid="reexec tests" tid="reexec tests"
@ -39,8 +39,7 @@ echo "InvalidXXX=no" >> $OBJ/sshd_config
copy_tests copy_tests
$SUDO kill `$SUDO cat $PIDFILE` stop_sshd
rm -f $PIDFILE
cp $OBJ/sshd_config.orig $OBJ/sshd_config cp $OBJ/sshd_config.orig $OBJ/sshd_config
@ -54,8 +53,7 @@ rm -f $SSHD_COPY
copy_tests copy_tests
$SUDO kill `$SUDO cat $PIDFILE` stop_sshd
rm -f $PIDFILE
verbose "test reexec fallback without privsep" verbose "test reexec fallback without privsep"
@ -67,7 +65,6 @@ rm -f $SSHD_COPY
copy_tests copy_tests
$SUDO kill `$SUDO cat $PIDFILE` stop_sshd
rm -f $PIDFILE
fi fi

View File

@ -1,4 +1,4 @@
# $OpenBSD: test-exec.sh,v 1.57 2016/11/25 03:02:01 dtucker Exp $ # $OpenBSD: test-exec.sh,v 1.58 2016/12/16 01:06:27 dtucker Exp $
# Placed in the Public Domain. # Placed in the Public Domain.
#SUDO=sudo #SUDO=sudo
@ -293,16 +293,8 @@ md5 () {
} }
# End of portable specific functions # End of portable specific functions
# helper stop_sshd ()
cleanup ()
{ {
if [ "x$SSH_PID" != "x" ]; then
if [ $SSH_PID -lt 2 ]; then
echo bad pid for ssh: $SSH_PID
else
kill $SSH_PID
fi
fi
if [ -f $PIDFILE ]; then if [ -f $PIDFILE ]; then
pid=`$SUDO cat $PIDFILE` pid=`$SUDO cat $PIDFILE`
if [ "X$pid" = "X" ]; then if [ "X$pid" = "X" ]; then
@ -325,6 +317,19 @@ cleanup ()
fi fi
} }
# helper
cleanup ()
{
if [ "x$SSH_PID" != "x" ]; then
if [ $SSH_PID -lt 2 ]; then
echo bad pid for ssh: $SSH_PID
else
kill $SSH_PID
fi
fi
stop_sshd
}
start_debug_log () start_debug_log ()
{ {
echo "trace: $@" >$TEST_REGRESS_LOGFILE echo "trace: $@" >$TEST_REGRESS_LOGFILE

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tests.c,v 1.2 2016/05/30 12:05:56 schwarze Exp $ */ /* $OpenBSD: tests.c,v 1.3 2016/12/19 04:55:18 djm Exp $ */
/* /*
* Regress test for the utf8.h *mprintf() API * Regress test for the utf8.h *mprintf() API
* *
@ -69,7 +69,6 @@ tests(void)
TEST_DONE(); TEST_DONE();
badarg(); badarg();
one("null", NULL, 8, 6, 6, "(null)");
one("empty", "", 2, 0, 0, ""); one("empty", "", 2, 0, 0, "");
one("ascii", "x", -2, -2, -2, "x"); one("ascii", "x", -2, -2, -2, "x");
one("newline", "a\nb", -2, -2, -2, "a\nb"); one("newline", "a\nb", -2, -2, -2, "a\nb");

View File

@ -31,6 +31,7 @@
#include "log.h" #include "log.h"
#include "sandbox.h" #include "sandbox.h"
#include "monitor.h"
#include "xmalloc.h" #include "xmalloc.h"
/* Darwin/OS X sandbox */ /* Darwin/OS X sandbox */

120
scp.c
View File

@ -214,7 +214,7 @@ do_local_cmd(arglist *a)
return 0; return 0;
} }
#else #else /* !WINDOWS */
if ((pid = fork()) == -1) if ((pid = fork()) == -1)
fatal("do_local_cmd: fork: %s", strerror(errno)); fatal("do_local_cmd: fork: %s", strerror(errno));
@ -239,7 +239,7 @@ do_local_cmd(arglist *a)
return (-1); return (-1);
return (0); return (0);
#endif #endif /* !WINDOWS */
} }
/* /*
@ -282,6 +282,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
/* Fork a child to execute the command on the remote host using ssh. */ /* Fork a child to execute the command on the remote host using ssh. */
#ifdef WINDOWS #ifdef WINDOWS
/* generate command line and spawn_child */
replacearg(&args, 0, "%s", ssh_program); replacearg(&args, 0, "%s", ssh_program);
if (remuser != NULL) { if (remuser != NULL) {
addargs(&args, "-l"); addargs(&args, "-l");
@ -314,11 +315,9 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
do_cmd_pid = spawn_child(full_cmd, pin[0], pout[1], STDERR_FILENO, 0); do_cmd_pid = spawn_child(full_cmd, pin[0], pout[1], STDERR_FILENO, 0);
free(full_cmd); free(full_cmd);
} }
#else /* !WINDOWS */
#else
do_cmd_pid = fork(); do_cmd_pid = fork();
#endif #endif /* !WINDOWS */
if (do_cmd_pid == 0) { if (do_cmd_pid == 0) {
/* Child. */ /* Child. */
close(pin[1]); close(pin[1]);
@ -373,6 +372,7 @@ do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout)
/* Fork a child to execute the command on the remote host using ssh. */ /* Fork a child to execute the command on the remote host using ssh. */
#ifdef WINDOWS #ifdef WINDOWS
/* generate command line and spawn_child */
replacearg(&args, 0, "%s", ssh_program); replacearg(&args, 0, "%s", ssh_program);
if (remuser != NULL) { if (remuser != NULL) {
addargs(&args, "-l"); addargs(&args, "-l");
@ -403,10 +403,10 @@ do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout)
pid = spawn_child(full_cmd, fdin, fdout, STDERR_FILENO, 0); pid = spawn_child(full_cmd, fdin, fdout, STDERR_FILENO, 0);
free(full_cmd); free(full_cmd);
} }
#else #else /* !WINDOWS */
pid = fork(); pid = fork();
#endif #endif /* !WINDOWS */
if (pid == 0) { if (pid == 0) {
dup2(fdin, 0); dup2(fdin, 0);
dup2(fdout, 1); dup2(fdout, 1);
@ -592,6 +592,18 @@ main(int argc, char **argv)
remin = STDIN_FILENO; remin = STDIN_FILENO;
remout = STDOUT_FILENO; remout = STDOUT_FILENO;
#ifdef WINDOWS
/*
* To support both Windows and Unix style paths
* convert '\\' to '/' in rest of arguments
*/
{
int i;
for (i = 0; i < argc; i++)
convertToForwardslash(argv[i]);
}
#endif /* WINDOWS */
if (fflag) { if (fflag) {
/* Follow "protocol", send data. */ /* Follow "protocol", send data. */
(void) response(); (void) response();
@ -807,6 +819,41 @@ tolocal(int argc, char **argv)
for (i = 0; i < argc - 1; i++) { for (i = 0; i < argc - 1; i++) {
if (!(src = colon(argv[i]))) { /* Local to local. */ if (!(src = colon(argv[i]))) { /* Local to local. */
freeargs(&alist); freeargs(&alist);
#ifdef WINDOWS
#define _PATH_XCOPY "xcopy"
#define _PATH_COPY "copy"
/* local to local on windows - need to use local native copy command */
struct stat stb;
int exists;
char *last;
exists = stat(argv[i], &stb) == 0;
/* convert '/' to '\\' */
convertToBackslash(argv[i]);
convertToBackslash(argv[argc - 1]);
if (exists && (S_ISDIR(stb.st_mode))) {
addargs(&alist, "%s", _PATH_XCOPY);
if (iamrecursive)
addargs(&alist, "/S /E /H");
if (pflag)
addargs(&alist, "/K /X");
addargs(&alist, "/Y /F /I");
addargs(&alist, "%s", argv[i]);
if ((last = strrchr(argv[i], '\\')) == NULL)
last = argv[i];
else
++last;
addargs(&alist, "%s%s%s", argv[argc - 1],
strcmp(argv[argc - 1], "\\") ? "\\" : "", last);
} else {
addargs(&alist, "%s", _PATH_COPY);
addargs(&alist, "/Y");
addargs(&alist, "%s", argv[i]);
addargs(&alist, "%s", argv[argc - 1]);
}
#else /* !WINDOWS */
addargs(&alist, "%s", _PATH_CP); addargs(&alist, "%s", _PATH_CP);
if (iamrecursive) if (iamrecursive)
addargs(&alist, "-r"); addargs(&alist, "-r");
@ -815,6 +862,7 @@ tolocal(int argc, char **argv)
addargs(&alist, "--"); addargs(&alist, "--");
addargs(&alist, "%s", argv[i]); addargs(&alist, "%s", argv[i]);
addargs(&alist, "%s", argv[argc-1]); addargs(&alist, "%s", argv[argc-1]);
#endif /* !WINDOWS */
if (do_local_cmd(&alist)) if (do_local_cmd(&alist))
++errs; ++errs;
continue; continue;
@ -892,26 +940,10 @@ syserr: run_err("%s: %s", name, strerror(errno));
run_err("%s: not a regular file", name); run_err("%s: not a regular file", name);
goto next; goto next;
} }
#ifdef WINDOWS
/* account for both slashes on Windows */
{
char *lastf = NULL, *lastr = NULL;
if ((lastf = strrchr(name, '/')) == NULL && (lastr = strrchr(name, '\\')) == NULL)
last = name;
else {
if (lastf)
last = lastf;
if (lastr)
last = lastr;
++last;
}
}
#else
if ((last = strrchr(name, '/')) == NULL) if ((last = strrchr(name, '/')) == NULL)
last = name; last = name;
else else
++last; ++last;
#endif
curfile = last; curfile = last;
if (pflag) { if (pflag) {
if (do_times(remout, verbose_mode, &stb) < 0) if (do_times(remout, verbose_mode, &stb) < 0)
@ -1000,16 +1032,16 @@ rsource(char *name, struct stat *statp)
(u_int) (statp->st_mode & FILEMODEMASK), 0, last); (u_int) (statp->st_mode & FILEMODEMASK), 0, last);
if (verbose_mode) if (verbose_mode)
#ifdef WINDOWS #ifdef WINDOWS
/* TODO - make fmprintf work for Windows */ /* TODO - make fmprintf work for Windows */
{ {
printf("Entering directory: "); printf("Entering directory: ");
wchar_t* wtmp = utf8_to_utf16(path); wchar_t* wtmp = utf8_to_utf16(path);
WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), wtmp, wcslen(wtmp), 0, 0); WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), wtmp, wcslen(wtmp), 0, 0);
free(wtmp); free(wtmp);
} }
#else #else /* !WINDOWS */
fmprintf(stderr, "Entering directory: %s", path); fmprintf(stderr, "Entering directory: %s", path);
#endif #endif /* !WINDOWS */
(void) atomicio(vwrite, remout, path, strlen(path)); (void) atomicio(vwrite, remout, path, strlen(path));
if (response() < 0) { if (response() < 0) {
closedir(dirp); closedir(dirp);
@ -1085,16 +1117,17 @@ sink(int argc, char **argv)
*cp = 0; *cp = 0;
if (verbose_mode) if (verbose_mode)
#ifdef WINDOWS #ifdef WINDOWS
/* TODO - make fmprintf work for Windows */ /* TODO - make fmprintf work for Windows */
{ {
printf("Sink: "); printf("Sink: ");
wchar_t* wtmp = utf8_to_utf16(buf); wchar_t* wtmp = utf8_to_utf16(buf);
WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), wtmp, wcslen(wtmp), 0, 0); WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), wtmp, wcslen(wtmp), 0, 0);
free(wtmp); free(wtmp);
} }
#else #else /* !WINDOWS */
fmprintf(stderr, "Sink: %s", buf); fmprintf(stderr, "Sink: %s", buf);
#endif #endif /* !WINDOWS */
if (buf[0] == '\01' || buf[0] == '\02') { if (buf[0] == '\01' || buf[0] == '\02') {
if (iamremote == 0) { if (iamremote == 0) {
(void) snmprintf(visbuf, sizeof(visbuf), (void) snmprintf(visbuf, sizeof(visbuf),
@ -1496,3 +1529,4 @@ lostconn(int signo)
else else
exit(1); exit(1);
} }

View File

@ -606,7 +606,7 @@ derelativise_path(const char *path)
expanded = tilde_expand_filename(path, getuid()); expanded = tilde_expand_filename(path, getuid());
#ifdef WINDOWS #ifdef WINDOWS
/* Windows absolute paths have a drive letter followed by :*/ /* Windows absolute paths have a drive letter followed by :*/
if (expanded[1] == ':') if (*expanded != '\0' && expanded[1] == ':')
#else /* !WINDOWS */ #else /* !WINDOWS */
if (*expanded == '/') if (*expanded == '/')
#endif /* !WINDOWS */ #endif /* !WINDOWS */

552
session.c
View File

@ -183,8 +183,8 @@ static int
auth_input_request_forwarding(struct passwd * pw) auth_input_request_forwarding(struct passwd * pw)
{ {
#ifdef WINDOWS #ifdef WINDOWS
packet_send_debug("Agent forwarding not supported yet in Windows"); packet_send_debug("Agent forwarding not supported yet in Windows");
return 0; return 0;
#else /* !WINDOWS */ #else /* !WINDOWS */
Channel *nc; Channel *nc;
int sock = -1; int sock = -1;
@ -296,7 +296,7 @@ xauth_valid_string(const char *s)
* do_exec* on Windows * do_exec* on Windows
* - Read and set user environment variables from registry * - Read and set user environment variables from registry
* - Build subsystem cmdline path * - Build subsystem cmdline path
* - Interative shell/commands are executed using ssh-shellhost.exe * - Interactive shell/commands are executed using ssh-shellhost.exe
* - ssh-shellhost.exe implements server-side PTY for Windows * - ssh-shellhost.exe implements server-side PTY for Windows
*/ */
#include <Shlobj.h> #include <Shlobj.h>
@ -312,360 +312,336 @@ xauth_valid_string(const char *s)
void setup_session_vars(Session* s) void setup_session_vars(Session* s)
{ {
wchar_t* pw_dir_w; wchar_t* pw_dir_w;
wchar_t* tmp; wchar_t* tmp;
char buf[128]; char buf[128];
char* laddr; char* laddr;
struct ssh *ssh = active_state; /* XXX */ struct ssh *ssh = active_state; /* XXX */
if ((pw_dir_w = utf8_to_utf16(s->pw->pw_dir)) == NULL) if ((pw_dir_w = utf8_to_utf16(s->pw->pw_dir)) == NULL)
fatal("%s: out of memory"); fatal("%s: out of memory");
if ((tmp = utf8_to_utf16(s->pw->pw_name)) == NULL)
fatal("%s, out of memory");
SetEnvironmentVariableW(L"USERNAME", tmp);
free(tmp);
if (s->display) if ((tmp = utf8_to_utf16(s->pw->pw_name)) == NULL)
SetEnvironmentVariableA("DISPLAY", s->display); fatal("%s, out of memory");
SetEnvironmentVariableW(L"USERNAME", tmp);
free(tmp);
if (s->display)
SetEnvironmentVariableA("DISPLAY", s->display);
SetEnvironmentVariableW(L"HOMEPATH", pw_dir_w); SetEnvironmentVariableW(L"HOMEPATH", pw_dir_w);
SetEnvironmentVariableW(L"USERPROFILE", pw_dir_w); SetEnvironmentVariableW(L"USERPROFILE", pw_dir_w);
if (pw_dir_w[1] == L':') { if (pw_dir_w[1] == L':') {
wchar_t wc = pw_dir_w[2]; wchar_t wc = pw_dir_w[2];
pw_dir_w[2] = L'\0'; pw_dir_w[2] = L'\0';
SetEnvironmentVariableW(L"HOMEDRIVE", pw_dir_w); SetEnvironmentVariableW(L"HOMEDRIVE", pw_dir_w);
pw_dir_w[2] = wc; pw_dir_w[2] = wc;
} }
snprintf(buf, sizeof buf, "%.50s %d %d", snprintf(buf, sizeof buf, "%.50s %d %d",
ssh->remote_ipaddr, ssh->remote_port, ssh->local_port); ssh->remote_ipaddr, ssh->remote_port, ssh->local_port);
SetEnvironmentVariableA("SSH_CLIENT", buf); SetEnvironmentVariableA("SSH_CLIENT", buf);
laddr = get_local_ipaddr(packet_get_connection_in()); laddr = get_local_ipaddr(packet_get_connection_in());
snprintf(buf, sizeof buf, "%.50s %d %.50s %d", snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
ssh->remote_ipaddr, ssh->remote_port, laddr, ssh->local_port); ssh->remote_ipaddr, ssh->remote_port, laddr, ssh->local_port);
free(laddr); free(laddr);
SetEnvironmentVariableA("SSH_CONNECTION", buf); SetEnvironmentVariableA("SSH_CONNECTION", buf);
if (original_command) if (original_command)
SetEnvironmentVariableA("SSH_ORIGINAL_COMMAND", original_command); SetEnvironmentVariableA("SSH_ORIGINAL_COMMAND", original_command);
if ((s->term) && (s->term[0])) if ((s->term) && (s->term[0]))
SetEnvironmentVariable("TERM", s->term); SetEnvironmentVariable("TERM", s->term);
if (!s->is_subsystem) { if (!s->is_subsystem) {
snprintf(buf, sizeof buf, "%s@%s $P$G", s->pw->pw_name, getenv("COMPUTERNAME")); snprintf(buf, sizeof buf, "%s@%s $P$G", s->pw->pw_name, getenv("COMPUTERNAME"));
SetEnvironmentVariableA("PROMPT", buf); SetEnvironmentVariableA("PROMPT", buf);
} }
/*set user environment variables*/ /*set user environment variables*/
{ {
UCHAR InfoBuffer[1000]; UCHAR InfoBuffer[1000];
PTOKEN_USER pTokenUser = (PTOKEN_USER)InfoBuffer; PTOKEN_USER pTokenUser = (PTOKEN_USER)InfoBuffer;
DWORD dwInfoBufferSize, tmp_len; DWORD dwInfoBufferSize, tmp_len;
LPWSTR sid_str = NULL; LPWSTR sid_str = NULL;
wchar_t reg_path[MAX_PATH]; wchar_t reg_path[MAX_PATH];
HKEY reg_key = 0; HKEY reg_key = 0;
HANDLE token = s->authctxt->methoddata; HANDLE token = s->authctxt->methoddata;
tmp_len = MAX_PATH; tmp_len = MAX_PATH;
if (GetTokenInformation(token, TokenUser, InfoBuffer, if (GetTokenInformation(token, TokenUser, InfoBuffer,
1000, &dwInfoBufferSize) == FALSE || 1000, &dwInfoBufferSize) == FALSE ||
ConvertSidToStringSidW(pTokenUser->User.Sid, &sid_str) == FALSE || ConvertSidToStringSidW(pTokenUser->User.Sid, &sid_str) == FALSE ||
swprintf(reg_path, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%ls", sid_str) == MAX_PATH || swprintf(reg_path, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%ls", sid_str) == MAX_PATH ||
RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY, &reg_key) != 0 || RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY, &reg_key) != 0 ||
RegQueryValueExW(reg_key, L"ProfileImagePath", 0, NULL, (LPBYTE)pw_dir_w, &tmp_len) != 0) { RegQueryValueExW(reg_key, L"ProfileImagePath", 0, NULL, (LPBYTE)pw_dir_w, &tmp_len) != 0) {
/* one of the above failed */ /* one of the above failed */
debug("cannot retirve profile path - perhaps user profile is not created yet"); debug("cannot retirve profile path - perhaps user profile is not created yet");
} }
if (sid_str) if (sid_str)
LocalFree(sid_str); LocalFree(sid_str);
if (reg_key) if (reg_key)
RegCloseKey(reg_key); RegCloseKey(reg_key);
{ /* retrieve and set env variables. */ /* retrieve and set env variables. */
/* TODO - Get away with fixed limits and dynamically allocate required memory, cleanup this logic*/ {
#define MAX_VALUE_LEN 1000 #define MAX_VALUE_LEN 1000
#define MAX_DATA_LEN 2000 #define MAX_DATA_LEN 2000
#define MAX_EXPANDED_DATA_LEN 5000 #define MAX_EXPANDED_DATA_LEN 5000
wchar_t *path; /* TODO - Get away with fixed limits and dynamically allocate required memory, cleanup this logic*/
wchar_t value_name[MAX_VALUE_LEN]; wchar_t *path;
wchar_t value_data[MAX_DATA_LEN], value_data_expanded[MAX_EXPANDED_DATA_LEN], *to_apply; wchar_t value_name[MAX_VALUE_LEN];
DWORD value_type, name_len, data_len; wchar_t value_data[MAX_DATA_LEN], value_data_expanded[MAX_EXPANDED_DATA_LEN], *to_apply;
int i; DWORD value_type, name_len, data_len;
LONG ret; int i;
LONG ret;
if (ImpersonateLoggedOnUser(token) == FALSE) if (ImpersonateLoggedOnUser(token) == FALSE)
debug("Failed to impersonate user token, %d", GetLastError()); debug("Failed to impersonate user token, %d", GetLastError());
SET_USER_ENV(FOLDERID_LocalAppData, L"LOCALAPPDATA"); SET_USER_ENV(FOLDERID_LocalAppData, L"LOCALAPPDATA");
SET_USER_ENV(FOLDERID_Profile, L"USERPROFILE"); SET_USER_ENV(FOLDERID_Profile, L"USERPROFILE");
SET_USER_ENV(FOLDERID_RoamingAppData, L"APPDATA"); SET_USER_ENV(FOLDERID_RoamingAppData, L"APPDATA");
reg_key = 0; reg_key = 0;
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Environment", 0, KEY_QUERY_VALUE, &reg_key) == ERROR_SUCCESS) { if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Environment", 0, KEY_QUERY_VALUE, &reg_key) == ERROR_SUCCESS) {
i = 0; i = 0;
while (1) { while (1) {
name_len = MAX_VALUE_LEN * 2; name_len = MAX_VALUE_LEN * 2;
data_len = MAX_DATA_LEN * 2; data_len = MAX_DATA_LEN * 2;
to_apply = NULL; to_apply = NULL;
if (RegEnumValueW(reg_key, i++, value_name, &name_len, 0, &value_type, (LPBYTE)&value_data, &data_len) != ERROR_SUCCESS) if (RegEnumValueW(reg_key, i++, value_name, &name_len, 0, &value_type, (LPBYTE)&value_data, &data_len) != ERROR_SUCCESS)
break; break;
if (value_type == REG_SZ) if (value_type == REG_SZ)
to_apply = value_data; to_apply = value_data;
else if (value_type == REG_EXPAND_SZ) { else if (value_type == REG_EXPAND_SZ) {
ExpandEnvironmentStringsW(value_data, value_data_expanded, MAX_EXPANDED_DATA_LEN); ExpandEnvironmentStringsW(value_data, value_data_expanded, MAX_EXPANDED_DATA_LEN);
to_apply = value_data_expanded; to_apply = value_data_expanded;
} }
if (wcsicmp(value_name, L"PATH") == 0) { if (wcsicmp(value_name, L"PATH") == 0) {
DWORD size; DWORD size;
if ((size = GetEnvironmentVariableW(L"PATH", NULL, 0)) != ERROR_ENVVAR_NOT_FOUND) { if ((size = GetEnvironmentVariableW(L"PATH", NULL, 0)) != ERROR_ENVVAR_NOT_FOUND) {
memcpy(value_data_expanded + size, to_apply, (wcslen(to_apply) + 1) * 2); memcpy(value_data_expanded + size, to_apply, (wcslen(to_apply) + 1) * 2);
GetEnvironmentVariableW(L"PATH", value_data_expanded, MAX_EXPANDED_DATA_LEN); GetEnvironmentVariableW(L"PATH", value_data_expanded, MAX_EXPANDED_DATA_LEN);
value_data_expanded[size - 1] = L';'; value_data_expanded[size - 1] = L';';
to_apply = value_data_expanded; to_apply = value_data_expanded;
} }
} }
if (to_apply) if (to_apply)
SetEnvironmentVariableW(value_name, to_apply); SetEnvironmentVariableW(value_name, to_apply);
}
RegCloseKey(reg_key);
}
RevertToSelf();
}
}
free(pw_dir_w);
}
RegCloseKey(reg_key);
}
RevertToSelf();
}
}
free(pw_dir_w);
} }
int do_exec_windows(Session *s, const char *command, int pty) { int do_exec_windows(Session *s, const char *command, int pty) {
int pipein[2], pipeout[2], pipeerr[2], r; int pipein[2], pipeout[2], pipeerr[2], r;
char *exec_command = NULL, *progdir = w32_programdir(); char *exec_command = NULL, *progdir = w32_programdir();
wchar_t *exec_command_w = NULL, *pw_dir_w; wchar_t *exec_command_w = NULL, *pw_dir_w;
if (s->is_subsystem >= SUBSYSTEM_INT_SFTP_ERROR) if (s->is_subsystem >= SUBSYSTEM_INT_SFTP_ERROR) {
{ error("sub system not supported, exiting\n");
error("sub system not supported, exiting\n"); fflush(NULL);
fflush(NULL); exit(1);
exit(1); }
}
/* Create three pipes for stdin, stdout and stderr */
if (pipe(pipein) == -1 || pipe(pipeout) == -1 || pipe(pipeerr) == -1)
fatal("%s: cannot create pipe: %.100s", __func__, strerror(errno));
/* Create three pipes for stdin, stdout and stderr */ if ((pw_dir_w = utf8_to_utf16(s->pw->pw_dir)) == NULL)
if (pipe(pipein) == -1 || pipe(pipeout) == -1 || pipe(pipeerr) == -1) fatal("%s: out of memory");
fatal("%s: cannot create pipe: %.100s", __func__, strerror(errno));
if ((pw_dir_w = utf8_to_utf16(s->pw->pw_dir)) == NULL)
fatal("%s: out of memory");
set_nonblock(pipein[0]); set_nonblock(pipein[0]);
set_nonblock(pipein[1]); set_nonblock(pipein[1]);
set_nonblock(pipeout[0]); set_nonblock(pipeout[0]);
set_nonblock(pipeout[1]); set_nonblock(pipeout[1]);
set_nonblock(pipeerr[0]); set_nonblock(pipeerr[0]);
set_nonblock(pipeerr[1]); set_nonblock(pipeerr[1]);
fcntl(pipein[1], F_SETFD, FD_CLOEXEC); fcntl(pipein[1], F_SETFD, FD_CLOEXEC);
fcntl(pipeout[0], F_SETFD, FD_CLOEXEC); fcntl(pipeout[0], F_SETFD, FD_CLOEXEC);
fcntl(pipeerr[0], F_SETFD, FD_CLOEXEC); fcntl(pipeerr[0], F_SETFD, FD_CLOEXEC);
/* prepare exec - path used with CreateProcess() */ /* prepare exec - path used with CreateProcess() */
if (s->is_subsystem || (command && memcmp(command, "scp", 3) == 0)) { if (s->is_subsystem || (command && memcmp(command, "scp", 3) == 0)) {
/* relative or absolute */ /* relative or absolute */
if (command == NULL || command[0] == '\0') if (command == NULL || command[0] == '\0')
fatal("expecting command for a subsystem"); fatal("expecting command for a subsystem");
if (command[1] == ':') /* absolute */ if (command[1] == ':') /* absolute */
exec_command = xstrdup(command); exec_command = xstrdup(command);
else {/*relative*/ else {/*relative*/
exec_command = malloc(strlen(progdir) + 1 + strlen(command)); exec_command = malloc(strlen(progdir) + 1 + strlen(command));
if (exec_command == NULL) if (exec_command == NULL)
fatal("%s, out of memory"); fatal("%s, out of memory");
memcpy(exec_command, progdir, strlen(progdir)); memcpy(exec_command, progdir, strlen(progdir));
exec_command[strlen(progdir)] = '\\'; exec_command[strlen(progdir)] = '\\';
memcpy(exec_command + strlen(progdir) + 1, command, strlen(command) + 1); memcpy(exec_command + strlen(progdir) + 1, command, strlen(command) + 1);
} }
} else { } else {
char *shell_host = pty ? "ssh-shellhost.exe " : "ssh-shellhost.exe -nopty ", *c; char *shell_host = pty ? "ssh-shellhost.exe " : "ssh-shellhost.exe -nopty ", *c;
exec_command = malloc(strlen(progdir) + 1 + strlen(shell_host) + (command ? strlen(command) : 0) + 1); exec_command = malloc(strlen(progdir) + 1 + strlen(shell_host) + (command ? strlen(command) : 0) + 1);
if (exec_command == NULL) if (exec_command == NULL)
fatal("%s, out of memory"); fatal("%s, out of memory");
c = exec_command; c = exec_command;
memcpy(c, progdir, strlen(progdir)); memcpy(c, progdir, strlen(progdir));
c += strlen(progdir); c += strlen(progdir);
*c++ = '\\'; *c++ = '\\';
memcpy(c, shell_host, strlen(shell_host)); memcpy(c, shell_host, strlen(shell_host));
c += strlen(shell_host); c += strlen(shell_host);
if (command) { if (command) {
memcpy(c, command, strlen(command)); memcpy(c, command, strlen(command));
c += strlen(command); c += strlen(command);
} }
*c = '\0'; *c = '\0';
} }
/* setup Environment varibles */ /* setup Environment varibles */
setup_session_vars(s); setup_session_vars(s);
extern int debug_flag;
extern int debug_flag;
PROCESS_INFORMATION pi; {
STARTUPINFOW si; PROCESS_INFORMATION pi;
STARTUPINFOW si;
BOOL b; BOOL b;
HANDLE hToken = INVALID_HANDLE_VALUE; HANDLE hToken = INVALID_HANDLE_VALUE;
/* /*
* Assign sockets to StartupInfo * Assign sockets to StartupInfo
*/ */
memset(&si, 0, sizeof(STARTUPINFO)); memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO); si.cb = sizeof(STARTUPINFO);
si.lpReserved = 0; si.lpReserved = 0;
si.lpTitle = NULL; /* NULL means use exe name as title */ si.lpTitle = NULL; /* NULL means use exe name as title */
si.dwX = 0; si.dwX = 0;
si.dwY = 0; si.dwY = 0;
si.dwXSize = 5; si.dwXSize = 5;
si.dwYSize = 5; si.dwYSize = 5;
si.dwXCountChars = s->col; si.dwXCountChars = s->col;
si.dwYCountChars = s->row; si.dwYCountChars = s->row;
si.dwFillAttribute = 0; si.dwFillAttribute = 0;
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESIZE | STARTF_USECOUNTCHARS; si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESIZE | STARTF_USECOUNTCHARS;
si.wShowWindow = 0; // FALSE ; si.wShowWindow = 0; // FALSE ;
si.cbReserved2 = 0; si.cbReserved2 = 0;
si.lpReserved2 = 0; si.lpReserved2 = 0;
si.hStdInput = (HANDLE)sfd_to_handle(pipein[0]); si.hStdInput = (HANDLE)sfd_to_handle(pipein[0]);
si.hStdOutput = (HANDLE)sfd_to_handle(pipeout[1]); si.hStdOutput = (HANDLE)sfd_to_handle(pipeout[1]);
si.hStdError = (HANDLE)sfd_to_handle(pipeerr[1]); si.hStdError = (HANDLE)sfd_to_handle(pipeerr[1]);
si.lpDesktop = NULL; si.lpDesktop = NULL;
hToken = s->authctxt->methoddata; hToken = s->authctxt->methoddata;
debug("Executing command: %s", exec_command); debug("Executing command: %s", exec_command);
/* Create the child process */ /* Create the child process */
exec_command_w = utf8_to_utf16(exec_command); exec_command_w = utf8_to_utf16(exec_command);
if (debug_flag) if (debug_flag)
b = CreateProcessW(NULL, exec_command_w, NULL, NULL, TRUE, b = CreateProcessW(NULL, exec_command_w, NULL, NULL, TRUE,
DETACHED_PROCESS, NULL, pw_dir_w, DETACHED_PROCESS, NULL, pw_dir_w,
&si, &pi); &si, &pi);
else else
b = CreateProcessAsUserW(hToken, NULL, exec_command_w, NULL, NULL, TRUE, b = CreateProcessAsUserW(hToken, NULL, exec_command_w, NULL, NULL, TRUE,
DETACHED_PROCESS , NULL, pw_dir_w, DETACHED_PROCESS , NULL, pw_dir_w,
&si, &pi); &si, &pi);
if (!b) if (!b)
{ {
debug("ERROR. Cannot create process (%u).\n", GetLastError()); debug("ERROR. Cannot create process (%u).\n", GetLastError());
free(pw_dir_w); free(pw_dir_w);
free(exec_command_w); free(exec_command_w);
CloseHandle(hToken); CloseHandle(hToken);
exit(1); exit(1);
} }
else if (pty) { /*attach to shell console */ else if (pty) { /*attach to shell console */
FreeConsole(); FreeConsole();
if (!debug_flag) if (!debug_flag)
ImpersonateLoggedOnUser(hToken); ImpersonateLoggedOnUser(hToken);
Sleep(20); Sleep(20);
while (AttachConsole(pi.dwProcessId) == FALSE) { while (AttachConsole(pi.dwProcessId) == FALSE) {
DWORD exit_code; DWORD exit_code;
if (GetExitCodeProcess(pi.hProcess, &exit_code) && exit_code != STILL_ACTIVE) if (GetExitCodeProcess(pi.hProcess, &exit_code) && exit_code != STILL_ACTIVE)
break; break;
Sleep(100); Sleep(100);
} }
if (!debug_flag) if (!debug_flag)
RevertToSelf(); RevertToSelf();
{ {
/* TODO - check this - Create Process above is not respecting x# and y# chars, so we are doing this explicity on the /* TODO - check this - Create Process above is not respecting x# and y# chars, so we are doing this explicity on the
* attached console agein */ * attached console agein */
COORD coord; COORD coord;
coord.X = s->col; coord.X = s->col;
coord.Y = 9999;; coord.Y = 9999;;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coord); SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coord);
} }
} }
s->pid = pi.dwProcessId; CloseHandle(pi.hThread);
sw_add_child(pi.hProcess, pi.dwProcessId); s->pid = pi.dwProcessId;
sw_add_child(pi.hProcess, pi.dwProcessId);
}
/*
* Set interactive/non-interactive mode.
*/
packet_set_interactive(s->display != NULL, options.ip_qos_interactive,
options.ip_qos_bulk);
/* /* Close the child sides of the socket pairs. */
* Set interactive/non-interactive mode. close(pipein[0]);
*/ close(pipeout[1]);
close(pipeerr[1]);
packet_set_interactive(s->display != NULL, options.ip_qos_interactive, /*
options.ip_qos_bulk); * Enter the interactive session. Note: server_loop must be able to
* handle the case that fdin and fdout are the same.
*/
/* if (s->ttyfd == -1)
* We are the parent. Close the child sides of the socket pairs. session_set_fds(s, pipein[1], pipeout[0], pipeerr[0], s->is_subsystem, 0);
*/ else
session_set_fds(s, pipein[1], pipeout[0], pipeerr[0], s->is_subsystem, 1); // tty interactive session
close(pipein[0]);
close(pipeout[1]);
close(pipeerr[1]);
/*
* Close child thread handles as we do not need it. Process handle we keep so that we can know if it has died o not
*/
CloseHandle(pi.hThread);
// CloseHandle(pi.hProcess);
/*
* Clear loginmsg, since it's the child's responsibility to display
* it to the user, otherwise multiple sessions may accumulate
* multiple copies of the login messages.
*/
buffer_clear(&loginmsg);
/*
* Enter the interactive session. Note: server_loop must be able to
* handle the case that fdin and fdout are the same.
*/
if (s->ttyfd == -1)
session_set_fds(s, pipein[1], pipeout[0], pipeerr[0], s->is_subsystem, 0);
else
session_set_fds(s, pipein[1], pipeout[0], pipeerr[0], s->is_subsystem, 1); // tty interactive session
free(pw_dir_w); free(pw_dir_w);
free(exec_command_w); free(exec_command_w);
return 0; return 0;
} }
int int
do_exec_no_pty(Session *s, const char *command) { do_exec_no_pty(Session *s, const char *command) {
return do_exec_windows(s, command, 0); return do_exec_windows(s, command, 0);
} }
int int
do_exec_pty(Session *s, const char *command) { do_exec_pty(Session *s, const char *command) {
return do_exec_windows(s, command, 1); return do_exec_windows(s, command, 1);
} }
#else /* !WINDOWS */ #else /* !WINDOWS */

View File

@ -1384,11 +1384,9 @@ do_download(struct sftp_conn *conn, const char *remote_path,
"server reordered requests", local_path); "server reordered requests", local_path);
} }
debug("truncating at %llu", (unsigned long long)highwater); debug("truncating at %llu", (unsigned long long)highwater);
#ifndef WIN32_VS
if (ftruncate(local_fd, highwater) == -1) if (ftruncate(local_fd, highwater) == -1)
error("ftruncate \"%s\": %s", local_path, error("ftruncate \"%s\": %s", local_path,
strerror(errno)); strerror(errno));
#endif
} }
if (read_error) { if (read_error) {
error("Couldn't read from remote file \"%s\" : %s", error("Couldn't read from remote file \"%s\" : %s",
@ -1428,7 +1426,7 @@ do_download(struct sftp_conn *conn, const char *remote_path,
if (fsync(local_fd) == -1) if (fsync(local_fd) == -1)
error("Couldn't sync file \"%s\": %s", error("Couldn't sync file \"%s\": %s",
local_path, strerror(errno)); local_path, strerror(errno));
} }
} }
close(local_fd); close(local_fd);
sshbuf_free(msg); sshbuf_free(msg);

View File

@ -222,7 +222,7 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units)
strmode(st->st_mode, mode); strmode(st->st_mode, mode);
if (!remote) { if (!remote) {
user = user_from_uid(st->st_uid, 0); user = user_from_uid(st->st_uid, 0);
} else { } else {
snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid); snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid);
user = ubuf; user = ubuf;
@ -233,7 +233,6 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units)
snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid); snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid);
group = gbuf; group = gbuf;
} }
if (ltime != NULL) { if (ltime != NULL) {
now = time(NULL); now = time(NULL);
if (now - (365*24*60*60)/2 < st->st_mtime && if (now - (365*24*60*60)/2 < st->st_mtime &&

View File

@ -1,533 +0,0 @@
/* $OpenBSD: sftp-common.c,v 1.28 2015/01/20 23:14:00 deraadt Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2001 Damien Miller. All rights reserved.
*
* 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.
*/
#include "includes.h"
#include <sys/param.h> /* MAX */
#include <sys/types.h>
#include <sys/stat.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
#include "xmalloc.h"
#include "ssherr.h"
#include "sshbuf.h"
#include "log.h"
#include "sftp.h"
#include "sftp-common.h"
/* Clear contents of attributes structure */
void
attrib_clear(Attrib *a)
{
a->flags = 0;
a->size = 0;
a->uid = 0;
a->gid = 0;
a->perm = 0;
a->atime = 0;
a->mtime = 0;
}
/* Convert from struct stat to filexfer attribs */
void
stat_to_attrib(const struct stat *st, Attrib *a)
{
attrib_clear(a);
a->flags = 0;
a->flags |= SSH2_FILEXFER_ATTR_SIZE;
a->size = st->st_size;
a->flags |= SSH2_FILEXFER_ATTR_UIDGID;
a->uid = st->st_uid;
a->gid = st->st_gid;
a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
a->perm = st->st_mode;
a->flags |= SSH2_FILEXFER_ATTR_ACMODTIME;
a->atime = st->st_atime;
a->mtime = st->st_mtime;
}
/* Convert from filexfer attribs to struct stat */
void
attrib_to_stat(const Attrib *a, struct stat *st)
{
memset(st, 0, sizeof(*st));
if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
st->st_size = a->size;
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
st->st_uid = a->uid;
st->st_gid = a->gid;
}
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
st->st_mode = a->perm;
if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
st->st_atime = a->atime;
st->st_mtime = a->mtime;
}
}
/* Decode attributes in buffer */
int
decode_attrib(struct sshbuf *b, Attrib *a)
{
int r;
attrib_clear(a);
if ((r = sshbuf_get_u32(b, &a->flags)) != 0)
return r;
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
if ((r = sshbuf_get_u64(b, &a->size)) != 0)
return r;
}
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
if ((r = sshbuf_get_u32(b, &a->uid)) != 0 ||
(r = sshbuf_get_u32(b, &a->gid)) != 0)
return r;
}
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
if ((r = sshbuf_get_u32(b, &a->perm)) != 0)
return r;
}
if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
if ((r = sshbuf_get_u32(b, &a->atime)) != 0 ||
(r = sshbuf_get_u32(b, &a->mtime)) != 0)
return r;
}
/* vendor-specific extensions */
if (a->flags & SSH2_FILEXFER_ATTR_EXTENDED) {
char *type;
u_char *data;
size_t dlen;
u_int i, count;
if ((r = sshbuf_get_u32(b, &count)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
for (i = 0; i < count; i++) {
if ((r = sshbuf_get_cstring(b, &type, NULL)) != 0 ||
(r = sshbuf_get_string(b, &data, &dlen)) != 0)
return r;
debug3("Got file attribute \"%.100s\" len %zu",
type, dlen);
free(type);
free(data);
}
}
return 0;
}
/* Encode attributes to buffer */
int
encode_attrib(struct sshbuf *b, const Attrib *a)
{
int r;
if ((r = sshbuf_put_u32(b, a->flags)) != 0)
return r;
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
if ((r = sshbuf_put_u64(b, a->size)) != 0)
return r;
}
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
if ((r = sshbuf_put_u32(b, a->uid)) != 0 ||
(r = sshbuf_put_u32(b, a->gid)) != 0)
return r;
}
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
if ((r = sshbuf_put_u32(b, a->perm)) != 0)
return r;
}
if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
if ((r = sshbuf_put_u32(b, a->atime)) != 0 ||
(r = sshbuf_put_u32(b, a->mtime)) != 0)
return r;
}
return 0;
}
/* Convert from SSH2_FX_ status to text error message */
const char *
fx2txt(int status)
{
switch (status) {
case SSH2_FX_OK:
return("No error");
case SSH2_FX_EOF:
return("End of file");
case SSH2_FX_NO_SUCH_FILE:
return("No such file or directory");
case SSH2_FX_PERMISSION_DENIED:
return("Permission denied");
case SSH2_FX_FAILURE:
return("Failure");
case SSH2_FX_BAD_MESSAGE:
return("Bad message");
case SSH2_FX_NO_CONNECTION:
return("No connection");
case SSH2_FX_CONNECTION_LOST:
return("Connection lost");
case SSH2_FX_OP_UNSUPPORTED:
return("Operation unsupported");
default:
return("Unknown status");
}
/* NOTREACHED */
}
/*
* drwxr-xr-x 5 markus markus 1024 Jan 13 18:39 .ssh
*/
char *
ls_file(const char *name, const struct stat *st, int remote, int si_units)
{
int ulen, glen, sz = 0;
struct tm *ltime = localtime(&st->st_mtime);
char *user, *group;
char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1];
char sbuf[FMT_SCALED_STRSIZE];
time_t now;
strmode(st->st_mode, mode);
if (!remote) {
user = user_from_uid(st->st_uid, 0);
} else {
snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid);
user = ubuf;
}
if (!remote) {
group = group_from_gid(st->st_gid, 0);
} else {
snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid);
group = gbuf;
}
if (ltime != NULL) {
now = time(NULL);
if (now - (365*24*60*60)/2 < st->st_mtime &&
now >= st->st_mtime)
sz = strftime(tbuf, sizeof tbuf, "%b %e %H:%M", ltime);
else
sz = strftime(tbuf, sizeof tbuf, "%b %e %Y", ltime);
}
if (sz == 0)
tbuf[0] = '\0';
ulen = MAX(strlen(user), 8);
glen = MAX(strlen(group), 8);
if (si_units) {
fmt_scaled((long long)st->st_size, sbuf);
snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8s %s %s", mode,
(u_int)st->st_nlink, ulen, user, glen, group,
sbuf, tbuf, name);
} else {
snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8llu %s %s", mode,
(u_int)st->st_nlink, ulen, user, glen, group,
(unsigned long long)st->st_size, tbuf, name);
}
return xstrdup(buf);
}
<<<<<<< HEAD
=======
#ifdef WINDOWS
#include <sys/types.h>
#include <windows.h>
void
strmode(mode_t mode, char *p)
{
/* print type */
switch (mode & S_IFMT) {
case S_IFDIR: /* directory */
*p++ = 'd';
break;
case S_IFCHR: /* character special */
*p++ = 'c';
break;
//case S_IFBLK: /* block special */
// *p++ = 'b';
// break;
case S_IFREG: /* regular */
*p++ = '-';
break;
//case S_IFLNK: /* symbolic link */
// *p++ = 'l';
// break;
#ifdef S_IFSOCK
case S_IFSOCK: /* socket */
*p++ = 's';
break;
#endif
case _S_IFIFO: /* fifo */
*p++ = 'p';
break;
default: /* unknown */
*p++ = '?';
break;
}
/* usr */
if (mode & S_IRUSR)
*p++ = 'r';
else
*p++ = '-';
if (mode & S_IWUSR)
*p++ = 'w';
else
*p++ = '-';
switch (mode & (S_IXUSR)) {
case 0:
*p++ = '-';
break;
case S_IXUSR:
*p++ = 'x';
break;
//case S_ISUID:
// *p++ = 'S';
// break;
//case S_IXUSR | S_ISUID:
// *p++ = 's';
// break;
}
/* group */
if (mode & S_IRGRP)
*p++ = 'r';
else
*p++ = '-';
if (mode & S_IWGRP)
*p++ = 'w';
else
*p++ = '-';
switch (mode & (S_IXGRP)) {
case 0:
*p++ = '-';
break;
case S_IXGRP:
*p++ = 'x';
break;
//case S_ISGID:
// *p++ = 'S';
// break;
//case S_IXGRP | S_ISGID:
// *p++ = 's';
// break;
}
/* other */
if (mode & S_IROTH)
*p++ = 'r';
else
*p++ = '-';
if (mode & S_IWOTH)
*p++ = 'w';
else
*p++ = '-';
switch (mode & (S_IXOTH)) {
case 0:
*p++ = '-';
break;
case S_IXOTH:
*p++ = 'x';
break;
}
*p++ = ' '; /* will be a '+' if ACL's implemented */
*p = '\0';
}
#include <winioctl.h>
// Maximum reparse buffer info size. The max user defined reparse
// data is 16KB, plus there's a header.
//
#define MAX_REPARSE_SIZE 17000
#define IO_REPARSE_TAG_SYMBOLIC_LINK IO_REPARSE_TAG_RESERVED_ZERO
#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) // winnt ntifs
#define IO_REPARSE_TAG_HSM (0xC0000004L) // winnt ntifs
#define IO_REPARSE_TAG_SIS (0x80000007L) // winnt ntifs
//
// Undocumented FSCTL_SET_REPARSE_POINT structure definition
//
#define REPARSE_MOUNTPOINT_HEADER_SIZE 8
typedef struct {
DWORD ReparseTag;
DWORD ReparseDataLength;
WORD Reserved;
WORD ReparseTargetLength;
WORD ReparseTargetMaximumLength;
WORD Reserved1;
WCHAR ReparseTarget[1];
} REPARSE_MOUNTPOINT_DATA_BUFFER, *PREPARSE_MOUNTPOINT_DATA_BUFFER;
typedef struct _REPARSE_DATA_BUFFER {
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union {
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct {
UCHAR DataBuffer[1];
} GenericReparseBuffer;
};
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
BOOL ResolveLink(wchar_t * tLink, wchar_t *ret, DWORD * plen, DWORD Flags)
{
HANDLE fileHandle;
BYTE reparseBuffer[MAX_REPARSE_SIZE];
PBYTE reparseData;
PREPARSE_GUID_DATA_BUFFER reparseInfo = (PREPARSE_GUID_DATA_BUFFER)reparseBuffer;
PREPARSE_DATA_BUFFER msReparseInfo = (PREPARSE_DATA_BUFFER)reparseBuffer;
DWORD returnedLength;
if (Flags & FILE_ATTRIBUTE_DIRECTORY)
{
fileHandle = CreateFileW(tLink, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
}
else {
//
// Open the file
//
fileHandle = CreateFileW(tLink, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT, 0);
}
if (fileHandle == INVALID_HANDLE_VALUE)
{
swprintf_s(ret, *plen, L"%ls", tLink);
return TRUE;
}
if (GetFileAttributesW(tLink) & FILE_ATTRIBUTE_REPARSE_POINT) {
if (DeviceIoControl(fileHandle, FSCTL_GET_REPARSE_POINT,
NULL, 0, reparseInfo, sizeof(reparseBuffer),
&returnedLength, NULL)) {
if (IsReparseTagMicrosoft(reparseInfo->ReparseTag)) {
switch (reparseInfo->ReparseTag) {
case 0x80000000 | IO_REPARSE_TAG_SYMBOLIC_LINK:
case IO_REPARSE_TAG_MOUNT_POINT:
if (*plen >= msReparseInfo->MountPointReparseBuffer.SubstituteNameLength)
{
reparseData = (PBYTE)&msReparseInfo->SymbolicLinkReparseBuffer.PathBuffer;
WCHAR temp[1024];
wcsncpy_s(temp, 1024,
(PWCHAR)(reparseData + msReparseInfo->MountPointReparseBuffer.SubstituteNameOffset),
(size_t)msReparseInfo->MountPointReparseBuffer.SubstituteNameLength);
temp[msReparseInfo->MountPointReparseBuffer.SubstituteNameLength] = 0;
swprintf_s(ret, *plen, L"%ls", &temp[4]);
}
else
{
swprintf_s(ret, *plen, L"%ls", tLink);
return FALSE;
}
break;
default:
break;
}
}
}
}
else {
swprintf_s(ret, *plen, L"%ls", tLink);
}
CloseHandle(fileHandle);
return TRUE;
}
char * get_inside_path(char * opath, BOOL bResolve, BOOL bMustExist)
{
char * ipath;
char * temp_name;
wchar_t temp[1024];
DWORD templen = 1024;
WIN32_FILE_ATTRIBUTE_DATA FileInfo;
wchar_t* opath_w = utf8_to_utf16(opath);
if (!GetFileAttributesExW(opath_w, GetFileExInfoStandard, &FileInfo) && bMustExist)
{
free(opath_w);
return NULL;
}
if (bResolve)
{
ResolveLink(opath_w, temp, &templen, FileInfo.dwFileAttributes);
ipath = utf16_to_utf8(temp);
}
else
{
ipath = xstrdup(opath);
}
free(opath_w);
return ipath;
}
// if file is symbolic link, copy its link into "link" .
int readlink(const char *path, char *link, int linklen)
{
strcpy_s(link, linklen, path);
return 0;
}
#endif
>>>>>>> V_7_3w

View File

@ -67,7 +67,6 @@ fudge_readdir(struct SFTP_OPENDIR *od)
/* Solaris needs sizeof(dirent) + path length (see below) */ /* Solaris needs sizeof(dirent) + path length (see below) */
static char buf[sizeof(struct dirent) + MAXPATHLEN]; static char buf[sizeof(struct dirent) + MAXPATHLEN];
struct dirent *ret = (struct dirent *)buf; struct dirent *ret = (struct dirent *)buf;
#ifdef __GNU_LIBRARY__ #ifdef __GNU_LIBRARY__
static int inum = 1; static int inum = 1;
#endif /* __GNU_LIBRARY__ */ #endif /* __GNU_LIBRARY__ */

View File

@ -688,7 +688,6 @@ process_open(u_int32_t id)
debug3("request %u: open flags %d", id, pflags); debug3("request %u: open flags %d", id, pflags);
flags = flags_from_portable(pflags); flags = flags_from_portable(pflags);
mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666; mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666;
logit("open \"%s\" flags %s mode 0%o", logit("open \"%s\" flags %s mode 0%o",
name, string_from_portable(pflags), mode); name, string_from_portable(pflags), mode);
if (readonly && if (readonly &&
@ -821,15 +820,13 @@ process_do_stat(u_int32_t id, int do_lstat)
struct stat st; struct stat st;
char *name; char *name;
int r, status = SSH2_FX_FAILURE; int r, status = SSH2_FX_FAILURE;
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
r = do_lstat ? lstat(name, &st) : stat(name, &st);
debug3("request %u: %sstat", id, do_lstat ? "l" : ""); debug3("request %u: %sstat", id, do_lstat ? "l" : "");
verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name); verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name);
r = do_lstat ? lstat(name, &st) : stat(name, &st);
if (r < 0) { if (r < 0) {
status = errno_to_portable(errno); status = errno_to_portable(errno);
} else { } else {
@ -899,9 +896,8 @@ process_setstat(u_int32_t id)
char *name; char *name;
int r, status = SSH2_FX_OK; int r, status = SSH2_FX_OK;
// sshbuf_get_cstring() is called twice.. is this correct?
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
(r = decode_attrib(iqueue, &a)) != 0) (r = decode_attrib(iqueue, &a)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug("request %u: setstat name \"%s\"", id, name); debug("request %u: setstat name \"%s\"", id, name);
@ -936,7 +932,6 @@ process_setstat(u_int32_t id)
if (r == -1) if (r == -1)
status = errno_to_portable(errno); status = errno_to_portable(errno);
} }
send_status(id, status); send_status(id, status);
free(name); free(name);
} }
@ -962,7 +957,6 @@ process_fsetstat(u_int32_t id)
if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
logit("set \"%s\" size %llu", logit("set \"%s\" size %llu",
name, (unsigned long long)a.size); name, (unsigned long long)a.size);
r = ftruncate(fd, a.size); r = ftruncate(fd, a.size);
if (r == -1) if (r == -1)
status = errno_to_portable(errno); status = errno_to_portable(errno);
@ -995,7 +989,6 @@ process_fsetstat(u_int32_t id)
if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
logit("set \"%s\" owner %lu group %lu", name, logit("set \"%s\" owner %lu group %lu", name,
(u_long)a.uid, (u_long)a.gid); (u_long)a.uid, (u_long)a.gid);
#ifdef HAVE_FCHOWN #ifdef HAVE_FCHOWN
r = fchown(fd, a.uid, a.gid); r = fchown(fd, a.uid, a.gid);
#else #else
@ -1018,11 +1011,9 @@ process_opendir(u_int32_t id)
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
dirp = opendir(path);
debug3("request %u: opendir", id); debug3("request %u: opendir", id);
logit("opendir \"%s\"", path); logit("opendir \"%s\"", path);
dirp = opendir(path);
if (dirp == NULL) { if (dirp == NULL) {
status = errno_to_portable(errno); status = errno_to_portable(errno);
} else { } else {
@ -1064,7 +1055,6 @@ process_readdir(u_int32_t id)
int nstats = 10, count = 0, i; int nstats = 10, count = 0, i;
stats = xcalloc(nstats, sizeof(Stat)); stats = xcalloc(nstats, sizeof(Stat));
while ((dp = readdir(dirp)) != NULL) { while ((dp = readdir(dirp)) != NULL) {
if (count >= nstats) { if (count >= nstats) {
nstats *= 2; nstats *= 2;
@ -1078,7 +1068,7 @@ process_readdir(u_int32_t id)
stat_to_attrib(&st, &(stats[count].attrib)); stat_to_attrib(&st, &(stats[count].attrib));
stats[count].name = xstrdup(dp->d_name); stats[count].name = xstrdup(dp->d_name);
stats[count].long_name = ls_file(dp->d_name, &st, 0, 0); stats[count].long_name = ls_file(dp->d_name, &st, 0, 0);
count++; count++;
/* send up to 100 entries in one message */ /* send up to 100 entries in one message */
/* XXX check packet size instead */ /* XXX check packet size instead */
if (count == 100) if (count == 100)
@ -1108,7 +1098,6 @@ process_remove(u_int32_t id)
debug3("request %u: remove", id); debug3("request %u: remove", id);
logit("remove name \"%s\"", name); logit("remove name \"%s\"", name);
r = unlink(name); r = unlink(name);
status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status); send_status(id, status);
@ -1130,8 +1119,6 @@ process_mkdir(u_int32_t id)
a.perm & 07777 : 0777; a.perm & 07777 : 0777;
debug3("request %u: mkdir", id); debug3("request %u: mkdir", id);
logit("mkdir name \"%s\" mode 0%o", name, mode); logit("mkdir name \"%s\" mode 0%o", name, mode);
r = mkdir(name, mode); r = mkdir(name, mode);
status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status); send_status(id, status);
@ -1149,7 +1136,6 @@ process_rmdir(u_int32_t id)
debug3("request %u: rmdir", id); debug3("request %u: rmdir", id);
logit("rmdir name \"%s\"", name); logit("rmdir name \"%s\"", name);
r = rmdir(name); r = rmdir(name);
status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status); send_status(id, status);
@ -1170,7 +1156,6 @@ process_realpath(u_int32_t id)
free(path); free(path);
path = xstrdup("."); path = xstrdup(".");
} }
debug3("request %u: realpath", id); debug3("request %u: realpath", id);
verbose("realpath \"%s\"", path); verbose("realpath \"%s\"", path);
if (realpath(path, resolvedname) == NULL) { if (realpath(path, resolvedname) == NULL) {
@ -1233,8 +1218,7 @@ process_rename(u_int32_t id)
unlink(newpath); unlink(newpath);
} else } else
status = SSH2_FX_OK; status = SSH2_FX_OK;
} } else if (stat(newpath, &sb) == -1) {
else if (stat(newpath, &sb) == -1) {
if (rename(oldpath, newpath) == -1) if (rename(oldpath, newpath) == -1)
status = errno_to_portable(errno); status = errno_to_portable(errno);
else else
@ -1257,7 +1241,6 @@ process_readlink(u_int32_t id)
debug3("request %u: readlink", id); debug3("request %u: readlink", id);
verbose("readlink \"%s\"", path); verbose("readlink \"%s\"", path);
if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1)
send_status(id, errno_to_portable(errno)); send_status(id, errno_to_portable(errno));
else { else {
@ -1275,7 +1258,7 @@ static void
process_symlink(u_int32_t id) process_symlink(u_int32_t id)
{ {
char *oldpath, *newpath; char *oldpath, *newpath;
int r, status= SSH2_FX_OP_UNSUPPORTED; int r, status;
if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
@ -1283,12 +1266,10 @@ process_symlink(u_int32_t id)
debug3("request %u: symlink", id); debug3("request %u: symlink", id);
logit("symlink old \"%s\" new \"%s\"", oldpath, newpath); logit("symlink old \"%s\" new \"%s\"", oldpath, newpath);
/* this will fail if 'newpath' exists */ /* this will fail if 'newpath' exists */
r = symlink(oldpath, newpath); r = symlink(oldpath, newpath);
status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status); send_status(id, status);
free(oldpath); free(oldpath);
free(newpath); free(newpath);
} }
@ -1317,7 +1298,6 @@ process_extended_statvfs(u_int32_t id)
{ {
char *path; char *path;
struct statvfs st; struct statvfs st;
int r; int r;
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
@ -1346,19 +1326,17 @@ process_extended_fstatvfs(u_int32_t id)
send_status(id, SSH2_FX_FAILURE); send_status(id, SSH2_FX_FAILURE);
return; return;
} }
if (fstatvfs(fd, &st) != 0)
if (statvfs(handle_to_name(handle), &st) != 0) send_status(id, errno_to_portable(errno));
if (fstatvfs(fd, &st) != 0) else
send_status(id, errno_to_portable(errno)); send_statvfs(id, &st);
else
send_statvfs(id, &st);
} }
static void static void
process_extended_hardlink(u_int32_t id) process_extended_hardlink(u_int32_t id)
{ {
char *oldpath, *newpath; char *oldpath, *newpath;
int r, status = SSH2_FX_OP_UNSUPPORTED; int r, status;
if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
@ -1366,10 +1344,8 @@ process_extended_hardlink(u_int32_t id)
debug3("request %u: hardlink", id); debug3("request %u: hardlink", id);
logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath); logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath);
r = link(oldpath, newpath); r = link(oldpath, newpath);
status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status); send_status(id, status);
free(oldpath); free(oldpath);
free(newpath); free(newpath);
@ -1429,11 +1405,10 @@ process(void)
const u_char *cp; const u_char *cp;
int i, r; int i, r;
u_int32_t id; u_int32_t id;
buf_len = sshbuf_len(iqueue); buf_len = sshbuf_len(iqueue);
if (buf_len < 5) { if (buf_len < 5)
return; /* Incomplete message. */ return; /* Incomplete message. */
}
cp = sshbuf_ptr(iqueue); cp = sshbuf_ptr(iqueue);
msg_len = get_u32(cp); msg_len = get_u32(cp);
if (msg_len > SFTP_MAX_MSG_LENGTH) { if (msg_len > SFTP_MAX_MSG_LENGTH) {
@ -1441,9 +1416,8 @@ process(void)
client_addr, pw->pw_name); client_addr, pw->pw_name);
sftp_server_cleanup_exit(11); sftp_server_cleanup_exit(11);
} }
if (buf_len < msg_len + 4) { if (buf_len < msg_len + 4)
return; return;
}
if ((r = sshbuf_consume(iqueue, 4)) != 0) if ((r = sshbuf_consume(iqueue, 4)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
buf_len -= 4; buf_len -= 4;
@ -1529,8 +1503,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0; int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0;
ssize_t len, olen, set_size; ssize_t len, olen, set_size;
SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
char *cp, *homedir = NULL, buf[4*4096];
char *cp, *homedir = NULL, buf[4*4096];
long mask; long mask;
extern char *optarg; extern char *optarg;
@ -1608,7 +1581,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
sftp_server_usage(); sftp_server_usage();
} }
} }
log_init(__progname, log_level, log_facility, log_stderr); log_init(__progname, log_level, log_facility, log_stderr);
/* /*
@ -1732,6 +1705,4 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
fatal("%s: sshbuf_check_reserve: %s", fatal("%s: sshbuf_check_reserve: %s",
__func__, ssh_err(r)); __func__, ssh_err(r));
} }
//#endif /* else WIN32 */
} }

246
sftp.c
View File

@ -73,7 +73,6 @@ typedef void EditLine;
#define DEFAULT_COPY_BUFLEN 32768 /* Size of buffer for up/download */ #define DEFAULT_COPY_BUFLEN 32768 /* Size of buffer for up/download */
#define DEFAULT_NUM_REQUESTS 64 /* # concurrent outstanding requests */ #define DEFAULT_NUM_REQUESTS 64 /* # concurrent outstanding requests */
#define MAX_COMMAND_LINE 2048
/* File to read commands from */ /* File to read commands from */
FILE* infile; FILE* infile;
@ -295,6 +294,7 @@ help(void)
#ifdef WINDOWS #ifdef WINDOWS
/* printf version to account for utf-8 input */ /* printf version to account for utf-8 input */
/* TODO - merge this with vfmprint */
static void printf_utf8(char *fmt, ... ) { static void printf_utf8(char *fmt, ... ) {
/* TODO - is 1024 sufficient */ /* TODO - is 1024 sufficient */
char buf[1024]; char buf[1024];
@ -311,6 +311,8 @@ static void printf_utf8(char *fmt, ... ) {
free(wtmp); free(wtmp);
} }
/* override mprintf */
#define mprintf(a,...) printf_utf8((a), __VA_ARGS__)
#define printf(a,...) printf_utf8((a), __VA_ARGS__) #define printf(a,...) printf_utf8((a), __VA_ARGS__)
#endif /* WINDOWS */ #endif /* WINDOWS */
@ -324,7 +326,7 @@ local_do_shell(const char *args)
args = (char *) getenv("ComSpec"); // get name of Windows cmd shell args = (char *) getenv("ComSpec"); // get name of Windows cmd shell
} }
system(args); // execute the shell or cmd given system(args); // execute the shell or cmd given
#else #else /* !WINDOWS */
int status; int status;
char *shell; char *shell;
pid_t pid; pid_t pid;
@ -358,7 +360,7 @@ local_do_shell(const char *args)
error("Shell exited abnormally"); error("Shell exited abnormally");
else if (WEXITSTATUS(status)) else if (WEXITSTATUS(status))
error("Shell exited with status %d", WEXITSTATUS(status)); error("Shell exited with status %d", WEXITSTATUS(status));
#endif #endif /* !WINDOWS */
} }
static void static void
@ -418,11 +420,7 @@ make_absolute(char *p, const char *pwd)
} }
/* convert '\\' tp '/' */ /* convert '\\' tp '/' */
s1 = p; convertToForwardslash(p);
while ((s2 = strchr(s1, '\\')) != NULL) {
*s2 = '/';
s1 = s2 + 1;
}
/* Append "/" if needed to the absolute windows path */ /* Append "/" if needed to the absolute windows path */
if (p && p[0] != '\0' && p[1] == ':') { if (p && p[0] != '\0' && p[1] == ':') {
@ -431,13 +429,14 @@ make_absolute(char *p, const char *pwd)
p = s1; p = s1;
} }
#else #else /* !WINDOWS */
if (p && p[0] != '/') { if (p && p[0] != '/') {
abs_str = path_append(pwd, p); abs_str = path_append(pwd, p);
free(p); free(p);
return(abs_str); return(abs_str);
} } else
#endif return(p);
#endif /* !WINDOWS */
return(p); return(p);
} }
@ -672,7 +671,6 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst,
abs_src = xstrdup(src); abs_src = xstrdup(src);
abs_src = make_absolute(abs_src, pwd); abs_src = make_absolute(abs_src, pwd);
memset(&g, 0, sizeof(g)); memset(&g, 0, sizeof(g));
debug3("Looking up %s", abs_src); debug3("Looking up %s", abs_src);
@ -712,7 +710,7 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst,
} else { } else {
abs_dst = xstrdup(dst); abs_dst = xstrdup(dst);
} }
} else if (dst) { } else if (dst) {
abs_dst = path_append(dst, filename); abs_dst = path_append(dst, filename);
} else { } else {
abs_dst = xstrdup(filename); abs_dst = xstrdup(filename);
@ -720,10 +718,12 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst,
free(tmp); free(tmp);
resume |= global_aflag; resume |= global_aflag;
if (!quiet && resume) if (!quiet && resume)
printf("Resuming %s to %s\n", g.gl_pathv[i], abs_dst); mprintf("Resuming %s to %s\n",
else if (!quiet && !resume) g.gl_pathv[i], abs_dst);
printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); else if (!quiet && !resume)
mprintf("Fetching %s to %s\n",
g.gl_pathv[i], abs_dst);
if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
pflag || global_pflag, 1, resume, pflag || global_pflag, 1, resume,
@ -771,10 +771,8 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst,
} }
/* If we aren't fetching to pwd then stash this status for later */ /* If we aren't fetching to pwd then stash this status for later */
if (tmp_dst != NULL) { if (tmp_dst != NULL)
dst_is_dir = remote_is_dir(conn, tmp_dst); dst_is_dir = remote_is_dir(conn, tmp_dst);
}
/* If multiple matches, dst may be directory or unspecified */ /* If multiple matches, dst may be directory or unspecified */
if (g.gl_matchc > 1 && tmp_dst && !dst_is_dir) { if (g.gl_matchc > 1 && tmp_dst && !dst_is_dir) {
@ -805,7 +803,7 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst,
abs_dst = path_append(tmp_dst, filename); abs_dst = path_append(tmp_dst, filename);
else else
abs_dst = xstrdup(tmp_dst); abs_dst = xstrdup(tmp_dst);
} else if (tmp_dst) { } else if (tmp_dst) {
abs_dst = path_append(tmp_dst, filename); abs_dst = path_append(tmp_dst, filename);
} else { } else {
abs_dst = make_absolute(xstrdup(filename), pwd); abs_dst = make_absolute(xstrdup(filename), pwd);
@ -814,10 +812,11 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst,
resume |= global_aflag; resume |= global_aflag;
if (!quiet && resume) if (!quiet && resume)
printf("Resuming upload of %s to %s\n", g.gl_pathv[i], mprintf("Resuming upload of %s to %s\n",
abs_dst); g.gl_pathv[i], abs_dst);
else if (!quiet && !resume) else if (!quiet && !resume)
printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); mprintf("Uploading %s to %s\n",
g.gl_pathv[i], abs_dst);
if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
if (upload_dir(conn, g.gl_pathv[i], abs_dst, if (upload_dir(conn, g.gl_pathv[i], abs_dst,
pflag || global_pflag, 1, resume, pflag || global_pflag, 1, resume,
@ -887,6 +886,7 @@ do_ls_dir(struct sftp_conn *conn, const char *path,
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
width = ws.ws_col; width = ws.ws_col;
columns = width / (m + 2); columns = width / (m + 2);
columns = MAXIMUM(columns, 1); columns = MAXIMUM(columns, 1);
colspace = width / columns; colspace = width / columns;
@ -919,24 +919,21 @@ do_ls_dir(struct sftp_conn *conn, const char *path,
attrib_to_stat(&d[n]->a, &sb); attrib_to_stat(&d[n]->a, &sb);
lname = ls_file(fname, &sb, 1, lname = ls_file(fname, &sb, 1,
(lflag & LS_SI_UNITS)); (lflag & LS_SI_UNITS));
printf("%s\n", lname); mprintf("%s\n", lname);
free(lname); free(lname);
} } else
else { mprintf("%s\n", d[n]->longname);
printf("%s\n", d[n]->longname); } else {
}
}
else {
#ifdef WINDOWS #ifdef WINDOWS
/* cannot use printf_utf8 becuase of width specification */ /* cannot use printf_utf8 becuase of width specification */
/* printf_utf8 does not account for utf-16 based argument widths */ /* printf_utf8 does not account for utf-16 based argument widths */
wchar_t buf[1024]; wchar_t buf[1024];
wchar_t* wtmp = utf8_to_utf16(fname); wchar_t* wtmp = utf8_to_utf16(fname);
swprintf(buf, 1024, L"%-*s", colspace, wtmp); swprintf(buf, 1024, L"%-*s", colspace, wtmp);
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), buf, wcslen(buf), 0, 0); WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), buf, wcslen(buf), 0, 0);
free(wtmp); free(wtmp);
#else #else
printf("%-*s", colspace, fname); mprintf("%-*s", colspace, fname);
#endif #endif
if (c >= columns) { if (c >= columns) {
printf("\n"); printf("\n");
@ -995,7 +992,7 @@ do_globbed_ls(struct sftp_conn *conn, const char *path,
globfree(&g); globfree(&g);
return err; return err;
} }
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
width = ws.ws_col; width = ws.ws_col;
@ -1018,21 +1015,21 @@ do_globbed_ls(struct sftp_conn *conn, const char *path,
} }
lname = ls_file(fname, g.gl_statv[i], 1, lname = ls_file(fname, g.gl_statv[i], 1,
(lflag & LS_SI_UNITS)); (lflag & LS_SI_UNITS));
printf("%s\n", lname); mprintf("%s\n", lname);
free(lname); free(lname);
} else { } else {
#ifdef WINDOWS #ifdef WINDOWS
/* cannot use printf_utf8 becuase of width specification */ /* cannot use printf_utf8 becuase of width specification */
/* printf_utf8 does not account for utf-16 based argument widths */ /* printf_utf8 does not account for utf-16 based argument widths */
wchar_t buf[1024]; wchar_t buf[1024];
wchar_t* wtmp = utf8_to_utf16(fname); wchar_t* wtmp = utf8_to_utf16(fname);
swprintf(buf, 1024, L"%-*s", colspace, wtmp); swprintf(buf, 1024, L"%-*s", colspace, wtmp);
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), buf, wcslen(buf), 0, 0); WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), buf, wcslen(buf), 0, 0);
free(wtmp); free(wtmp);
#else #else
printf("%-*s", colspace, fname); mprintf("%-*s", colspace, fname);
#endif #endif
if (c >= columns) { if (c >= columns) {
printf("\n"); printf("\n");
c = 1; c = 1;
} else } else
@ -1513,23 +1510,17 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
path1 = path2 = NULL; path1 = path2 = NULL;
#ifdef WINDOWS #ifdef WINDOWS
/* /*
* convert '/' to '\' in Windows styled paths. * convert '\\' to '/' in Windows styled paths.
* else they get treated as escape sequence in makeargv * else they get treated as escape sequence in makeargv
*/ */
{ convertToForwardslash(cmd);
char *s1 = cmd, *s2;
while ((s2 = strchr(s1, '\\')) != NULL) {
*s2 = '/';
s1 = s2 + 1;
}
}
#endif #endif
cmdnum = parse_args(&cmd, &ignore_errors, &aflag, &fflag, &hflag, cmdnum = parse_args(&cmd, &ignore_errors, &aflag, &fflag, &hflag,
&iflag, &lflag, &pflag, &rflag, &sflag, &n_arg, &path1, &path2); &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg, &path1, &path2);
if (ignore_errors != 0) if (ignore_errors != 0)
err_abort = 0; err_abort = 0;
memset(&g, 0, sizeof(g)); memset(&g, 0, sizeof(g));
/* Perform command */ /* Perform command */
switch (cmdnum) { switch (cmdnum) {
@ -1570,10 +1561,9 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
case I_RM: case I_RM:
path1 = make_absolute(path1, *pwd); path1 = make_absolute(path1, *pwd);
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
for (i = 0; g.gl_pathv[i] && !interrupted; i++) { if (!quiet)
if (!quiet) mprintf("Removing %s\n", g.gl_pathv[i]);
printf("Removing %s\n", g.gl_pathv[i]);
err = do_rm(conn, g.gl_pathv[i]); err = do_rm(conn, g.gl_pathv[i]);
if (err != 0 && err_abort) if (err != 0 && err_abort)
break; break;
@ -1673,7 +1663,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
for (i = 0; g.gl_pathv[i] && !interrupted; i++) { for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
if (!quiet) if (!quiet)
printf("Changing mode on %s\n", g.gl_pathv[i]); mprintf("Changing mode on %s\n",
g.gl_pathv[i]);
err = do_setstat(conn, g.gl_pathv[i], &a); err = do_setstat(conn, g.gl_pathv[i], &a);
if (err != 0 && err_abort) if (err != 0 && err_abort)
break; break;
@ -1703,13 +1694,13 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
if (cmdnum == I_CHOWN) { if (cmdnum == I_CHOWN) {
if (!quiet) if (!quiet)
printf("Changing owner on %s\n", mprintf("Changing owner on %s\n",
g.gl_pathv[i]); g.gl_pathv[i]);
aa->uid = n_arg; aa->uid = n_arg;
} else { } else {
if (!quiet) if (!quiet)
printf("Changing group on %s\n", mprintf("Changing group on %s\n",
g.gl_pathv[i]); g.gl_pathv[i]);
aa->gid = n_arg; aa->gid = n_arg;
} }
err = do_setstat(conn, g.gl_pathv[i], aa); err = do_setstat(conn, g.gl_pathv[i], aa);
@ -1718,7 +1709,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
} }
break; break;
case I_PWD: case I_PWD:
printf("Remote working directory: %s\n", *pwd); mprintf("Remote working directory: %s\n", *pwd);
break; break;
case I_LPWD: case I_LPWD:
if (!getcwd(path_buf, sizeof(path_buf))) { if (!getcwd(path_buf, sizeof(path_buf))) {
@ -1726,7 +1717,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
err = -1; err = -1;
break; break;
} }
printf("Local working directory: %s\n", path_buf); mprintf("Local working directory: %s\n", path_buf);
break; break;
case I_QUIT: case I_QUIT:
/* Processed below */ /* Processed below */
@ -2129,7 +2120,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
{ {
char *remote_path; char *remote_path;
char *dir = NULL; char *dir = NULL;
char cmd[MAX_COMMAND_LINE]; char cmd[2048];
int err, interactive; int err, interactive;
EditLine *el = NULL; EditLine *el = NULL;
#ifdef USE_LIBEDIT #ifdef USE_LIBEDIT
@ -2179,7 +2170,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
if (remote_is_dir(conn, dir) && file2 == NULL) { if (remote_is_dir(conn, dir) && file2 == NULL) {
if (!quiet) if (!quiet)
printf("Changing to: %s\n", dir); mprintf("Changing to: %s\n", dir);
snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
if (parse_dispatch_command(conn, cmd, if (parse_dispatch_command(conn, cmd,
&remote_path, 1) != 0) { &remote_path, 1) != 0) {
@ -2205,13 +2196,13 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
} }
#ifdef WINDOWS #ifdef WINDOWS
/* Min buffer size allowed in Windows is 2*/ /* Min buffer size allowed in Windows is 2*/
setvbuf(stdout, NULL, _IOLBF, 2); setvbuf(stdout, NULL, _IOLBF, 2);
setvbuf(infile, NULL, _IOLBF, 2); setvbuf(infile, NULL, _IOLBF, 2);
#else #else /* !WINDOWS */
setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(infile, NULL, _IOLBF, 0); setvbuf(infile, NULL, _IOLBF, 0);
#endif #endif /* !WINDOWS */
interactive = !batchmode && isatty(STDIN_FILENO); interactive = !batchmode && isatty(STDIN_FILENO);
err = 0; err = 0;
@ -2222,35 +2213,32 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
if (el == NULL) { if (el == NULL) {
#ifdef WINDOWS #ifdef WINDOWS
if (interactive) { /* fgets on Windows does not support Unicode input*/
wchar_t wcmd[MAX_COMMAND_LINE]; if (interactive) {
printf("sftp> "); wchar_t wcmd[2048];
if (fgetws(wcmd, sizeof(cmd)/sizeof(wchar_t), infile) == NULL) { printf("sftp> ");
printf("\n"); if (fgetws(wcmd, sizeof(cmd)/sizeof(wchar_t), infile) == NULL) {
break; printf("\n");
} break;
else { }
char *pcmd = NULL; else {
if ((pcmd = utf16_to_utf8(wcmd)) == NULL) char *pcmd = NULL;
fatal("failed to convert input arguments"); if ((pcmd = utf16_to_utf8(wcmd)) == NULL)
strcpy(cmd, pcmd); fatal("failed to convert input arguments");
free(pcmd); strcpy(cmd, pcmd);
} free(pcmd);
} }
else { } else if (fgets(cmd, sizeof(cmd), infile) == NULL)
if (fgets(cmd, sizeof(cmd), infile) == NULL) { break;
break; #else /* !WINDOWS */
} if (interactive)
} printf("sftp> ");
#else if (fgets(cmd, sizeof(cmd), infile) == NULL) {
if (interactive) { if (interactive)
printf("sftp> "); printf("\n");
if (fgets(cmd, sizeof(cmd), infile) == NULL) { break;
if (interactive) }
printf("\n"); #endif/* !WINDOWS */
break;
}
#endif
if (!interactive) { /* Echo command */ if (!interactive) { /* Echo command */
mprintf("sftp> %s", cmd); mprintf("sftp> %s", cmd);
if (strlen(cmd) > 0 && if (strlen(cmd) > 0 &&
@ -2324,6 +2312,7 @@ connect_to_server(char *path, char **args, int *in, int *out)
#endif /* USE_PIPES */ #endif /* USE_PIPES */
#ifdef WINDOWS #ifdef WINDOWS
/* fork replacement on Windows */
{ {
size_t cmdlen = 0; size_t cmdlen = 0;
int i = 0; int i = 0;
@ -2331,14 +2320,15 @@ connect_to_server(char *path, char **args, int *in, int *out)
cmdlen = strlen(path) + 1; cmdlen = strlen(path) + 1;
for (i = 1; args[i]; i++) for (i = 1; args[i]; i++)
cmdlen += strlen(args[i]) + 1; cmdlen += strlen(args[i]) + 1 + 2;
full_cmd = xmalloc(cmdlen); full_cmd = xmalloc(cmdlen);
full_cmd[0] = '\0'; full_cmd[0] = '\0';
strcat(full_cmd, path); strcat(full_cmd, path);
for (i = 1; args[i]; i++) { for (i = 1; args[i]; i++) {
strcat(full_cmd, " "); strcat(full_cmd, " \"");
strcat(full_cmd, args[i]); strcat(full_cmd, args[i]);
strcat(full_cmd, "\"");
} }
/* disable inheritance on local pipe ends*/ /* disable inheritance on local pipe ends*/
@ -2350,9 +2340,9 @@ connect_to_server(char *path, char **args, int *in, int *out)
} }
if (sshpid == -1) if (sshpid == -1)
#else #else /* !WINDOWS */
if ((sshpid = fork()) == -1) if ((sshpid = fork()) == -1)
#endif #endif /* !WINDOWS */
fatal("fork: %s", strerror(errno)); fatal("fork: %s", strerror(errno));
else if (sshpid == 0) { else if (sshpid == 0) {
if ((dup2(c_in, STDIN_FILENO) == -1) || if ((dup2(c_in, STDIN_FILENO) == -1) ||
@ -2426,11 +2416,7 @@ main(int argc, char **argv)
size_t num_requests = DEFAULT_NUM_REQUESTS; size_t num_requests = DEFAULT_NUM_REQUESTS;
long long limit_kbps = 0; long long limit_kbps = 0;
#ifdef WINDOWS ssh_malloc_init(); /* must be called before any mallocs */
/*TODO - is this really needed ???*/
setvbuf(stdout, NULL, _IONBF, 0);
#endif
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd(); sanitise_stdfd();
msetlocale(); msetlocale();
@ -2439,17 +2425,18 @@ main(int argc, char **argv)
memset(&args, '\0', sizeof(args)); memset(&args, '\0', sizeof(args));
args.list = NULL; args.list = NULL;
addargs(&args, "%s", ssh_program); addargs(&args, "%s", ssh_program);
addargs(&args, "-oForwardX11 no");
addargs(&args, "\"-oForwardX11 no\""); addargs(&args, "-oForwardAgent no");
addargs(&args, "\"-oForwardAgent no\""); addargs(&args, "-oPermitLocalCommand no");
addargs(&args, "\"-oPermitLocalCommand no\""); addargs(&args, "-oClearAllForwardings yes");
addargs(&args, "\"-oClearAllForwardings yes\"");
ll = SYSLOG_LEVEL_INFO; ll = SYSLOG_LEVEL_INFO;
#ifdef WINDOWS #ifdef WINDOWS
_setmode(_fileno(stdin), O_U16TEXT); /* prepare for Unicode input */
_setmode(_fileno(stdin), O_U16TEXT);
#endif #endif
infile = stdin; infile = stdin;
while ((ch = getopt(argc, argv, while ((ch = getopt(argc, argv,
"1246afhpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) { "1246afhpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
@ -2475,8 +2462,8 @@ main(int argc, char **argv)
addargs(&args, "-%c", ch); addargs(&args, "-%c", ch);
break; break;
case 'P': case 'P':
addargs(&args, "\"-oPort %s\"", optarg); addargs(&args, "-oPort %s", optarg);
break; break;
case 'v': case 'v':
if (debug_level < 3) { if (debug_level < 3) {
addargs(&args, "-v"); addargs(&args, "-v");
@ -2510,8 +2497,8 @@ main(int argc, char **argv)
fatal("%s (%s).", strerror(errno), optarg); fatal("%s (%s).", strerror(errno), optarg);
showprogress = 0; showprogress = 0;
quiet = batchmode = 1; quiet = batchmode = 1;
addargs(&args, "\"-obatchmode yes\""); addargs(&args, "-obatchmode yes");
break; break;
case 'f': case 'f':
global_fflag = 1; global_fflag = 1;
break; break;
@ -2584,7 +2571,8 @@ main(int argc, char **argv)
fprintf(stderr, "Missing hostname\n"); fprintf(stderr, "Missing hostname\n");
usage(); usage();
} }
addargs(&args, "\"-oProtocol %d\"", sshver);
addargs(&args, "-oProtocol %d", sshver);
/* no subsystem if the server-spec contains a '/' */ /* no subsystem if the server-spec contains a '/' */
if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) if (sftp_server == NULL || strchr(sftp_server, '/') == NULL)

2
ssh.c
View File

@ -1475,7 +1475,7 @@ control_persist_detach(void)
*/ */
fatal("ControlMaster is not supported in Windows yet"); fatal("ControlMaster is not supported in Windows yet");
#else /* !WINDOWS */ #else /* !WINDOWS */
pid_t pid; pid_t pid;
int devnull, keep_stderr; int devnull, keep_stderr;
debug("%s: backgrounding master process", __func__); debug("%s: backgrounding master process", __func__);

82
sshd.c
View File

@ -164,11 +164,11 @@ int saved_argc;
/* re-exec */ /* re-exec */
int rexeced_flag = 0; int rexeced_flag = 0;
#ifdef WINDOWS #ifdef WINDOWS
/* rexec is not supported in Windows */ /* rexec is not applicable in Windows */
int rexec_flag = 0; int rexec_flag = 0;
#else #else /* !WINDOWS */
int rexec_flag = 1; int rexec_flag = 1;
#endif #endif /* !WINDOWS */
int rexec_argc = 0; int rexec_argc = 0;
char **rexec_argv; char **rexec_argv;
@ -254,59 +254,6 @@ void destroy_sensitive_data(void);
void demote_sensitive_data(void); void demote_sensitive_data(void);
static void do_ssh2_kex(void); static void do_ssh2_kex(void);
/*
* Retrieve path to current running module.
*
* path - buffer, where to store path (OUT).
* pathSize - size of path buffer in bytes (IN).
*
* RETURNS: 0 if OK.
*/
int GetCurrentModulePath(char *path, int pathSize)
{
int exitCode = -1;
#ifdef WINDOWS
char* dir = w32_programdir();
if (strnlen(dir, pathSize) == pathSize)
error("program directory path size exceeded provided pathSize %d", pathSize);
else {
memcpy(path, dir, strnlen(dir, pathSize) + 1);
exitCode = 0;
}
#endif
//
// Linux.
//
#ifdef __linux__
if (readlink ("/proc/self/exe", path, pathSize) != -1)
{
dirname(path);
strcat(path, "/");
exitCode = 0;
}
#endif
//
// MacOS.
//
#ifdef __APPLE__
#endif
return exitCode;
}
/* /*
* Close all listening sockets * Close all listening sockets
*/ */
@ -591,7 +538,7 @@ reseed_prngs(void)
/* /*
* No-OP defs for preauth routines for Windows * No-OP defs for preauth routines for Windows
* these should go away once the privilege separation * these should go away once the privilege separation
* related is refactored to be invoked only when applicable * related code is refactored to be invoked only when applicable
*/ */
static void static void
privsep_preauth_child(void) { privsep_preauth_child(void) {
@ -608,7 +555,7 @@ privsep_postauth(Authctxt *authctxt) {
return; return;
} }
#else #else /* !WINDOWS */
/* Unix privilege separation routines */ /* Unix privilege separation routines */
static void static void
privsep_preauth_child(void) privsep_preauth_child(void)
@ -645,6 +592,7 @@ privsep_preauth_child(void)
if (setgroups(1, gidset) < 0) if (setgroups(1, gidset) < 0)
fatal("setgroups: %.100s", strerror(errno)); fatal("setgroups: %.100s", strerror(errno));
permanently_set_uid(privsep_pw); permanently_set_uid(privsep_pw);
}
} }
static int static int
@ -768,7 +716,7 @@ privsep_postauth(Authctxt *authctxt)
packet_set_authenticated(); packet_set_authenticated();
} }
#endif #endif /* !WINDOWS */
static char * static char *
list_hostkey_types(void) list_hostkey_types(void)
@ -1143,7 +1091,7 @@ server_listen(void)
close(listen_sock); close(listen_sock);
continue; continue;
} }
#endif #endif /* WINDOWS */
/* /*
* Set socket options. * Set socket options.
* Allow local port reuse in TIME_WAIT. * Allow local port reuse in TIME_WAIT.
@ -1370,7 +1318,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
free(path_utf8); free(path_utf8);
close(*newsock); close(*newsock);
} }
#else #else /* !WINDOWS */
if ((pid = fork()) == 0) { if ((pid = fork()) == 0) {
/* /*
@ -1395,7 +1343,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
close(config_s[0]); close(config_s[0]);
break; break;
} }
#endif #endif /* !WINDOWS */
/* Parent. Stay in the loop. */ /* Parent. Stay in the loop. */
platform_post_fork_parent(pid); platform_post_fork_parent(pid);
if (pid < 0) if (pid < 0)
@ -1764,7 +1712,7 @@ main(int ac, char **av)
#endif #endif
); );
#ifndef WINDOWS #ifndef WINDOWS /* not applicable in Windows */
/* Store privilege separation user for later use if required. */ /* Store privilege separation user for later use if required. */
if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) {
if (use_privsep || options.kerberos_authentication) if (use_privsep || options.kerberos_authentication)
@ -1778,7 +1726,7 @@ main(int ac, char **av)
privsep_pw->pw_passwd = xstrdup("*"); privsep_pw->pw_passwd = xstrdup("*");
} }
endpwent(); endpwent();
#endif #endif /* !WINDOWS */
/* load host keys */ /* load host keys */
sensitive_data.host_keys = xcalloc(options.num_host_key_files, sensitive_data.host_keys = xcalloc(options.num_host_key_files,
@ -1796,7 +1744,7 @@ main(int ac, char **av)
error("Could not connect to agent \"%s\": %s", error("Could not connect to agent \"%s\": %s",
options.host_key_agent, ssh_err(r)); options.host_key_agent, ssh_err(r));
} }
#ifdef WIN32_FIXME #ifdef WINDOWS /* Windows version always needs and has agent running */
have_agent = 1; have_agent = 1;
#endif #endif
for (i = 0; i < options.num_host_key_files; i++) { for (i = 0; i < options.num_host_key_files; i++) {
@ -1977,7 +1925,7 @@ main(int ac, char **av)
#ifdef WINDOWS #ifdef WINDOWS
/* For Windows child sshd, skip listener */ /* For Windows child sshd, skip listener */
if (is_child == 0) if (is_child == 0)
#endif #endif /* WINDOWS */
server_listen(); server_listen();
signal(SIGHUP, sighup_handler); signal(SIGHUP, sighup_handler);
@ -2020,7 +1968,7 @@ main(int ac, char **av)
fcntl(startup_pipe, F_SETFD, FD_CLOEXEC); fcntl(startup_pipe, F_SETFD, FD_CLOEXEC);
} }
else /* Windows and Unix sshd parent */ else /* Windows and Unix sshd parent */
#endif #endif /* WINDOWS */
/* Accept a connection and return in a forked child */ /* Accept a connection and return in a forked child */
server_accept_loop(&sock_in, &sock_out, server_accept_loop(&sock_in, &sock_out,

View File

@ -74,9 +74,7 @@ void
enter_raw_mode(int quiet) { enter_raw_mode(int quiet) {
ConInit(STD_OUTPUT_HANDLE, TRUE); ConInit(STD_OUTPUT_HANDLE, TRUE);
} }
#else /* !WINDOWS */ #else /* !WINDOWS */
struct termios * struct termios *
get_saved_tio(void) get_saved_tio(void)
{ {
@ -124,7 +122,4 @@ enter_raw_mode(int quiet)
} else } else
_in_raw_mode = 1; _in_raw_mode = 1;
} }
#endif /* !WINDOWS */
#endif /* !WINDOWS */

11
utf8.c
View File

@ -57,16 +57,15 @@ static int vasnmprintf(char **, size_t, int *, const char *, va_list);
static int static int
dangerous_locale(void) { dangerous_locale(void) {
#ifdef WINDOWS
#ifndef WINDOWS wchar_t loc[LOCALE_NAME_MAX_LENGTH];
GetSystemDefaultLocaleName(loc, LOCALE_NAME_MAX_LENGTH);
return wcscmp(loc, L"US-ASCII") && wcscmp(loc, L"UTF-8");
#else /* !WINDOWS */
char *loc; char *loc;
loc = nl_langinfo(CODESET); loc = nl_langinfo(CODESET);
return strcmp(loc, "US-ASCII") && strcmp(loc, "UTF-8"); return strcmp(loc, "US-ASCII") && strcmp(loc, "UTF-8");
#else /* !WINDOWS */
wchar_t loc[LOCALE_NAME_MAX_LENGTH];
GetSystemDefaultLocaleName(loc, LOCALE_NAME_MAX_LENGTH);
return wcscmp(loc, L"US-ASCII") && wcscmp(loc, L"UTF-8");
#endif /* !WINDOWS */ #endif /* !WINDOWS */
} }

View File

@ -1,6 +1,6 @@
/* $OpenBSD: version.h,v 1.77 2016/07/24 11:45:36 djm Exp $ */ /* $OpenBSD: version.h,v 1.78 2016/12/19 04:55:51 djm Exp $ */
#define SSH_VERSION "OpenSSH_7.3" #define SSH_VERSION "OpenSSH_7.4"
#define SSH_PORTABLE "p1" #define SSH_PORTABLE "p1"
#define SSH_RELEASE SSH_VERSION SSH_PORTABLE #define SSH_RELEASE SSH_VERSION SSH_PORTABLE