From a4b577b5a088186c9fb41786da73ccd8318a0529 Mon Sep 17 00:00:00 2001 From: Manoj Ampalam Date: Tue, 3 Jan 2017 14:46:33 -0800 Subject: [PATCH] Source snapshot from Powershell/openssh-portable:latestw_cwb --- README | 2 +- appveyor.yml | 6 +- auth.c | 8 +- auth2-pubkey.c | 7 +- channels.c | 1 + clientloop.c | 1 + contrib/redhat/openssh.spec | 2 +- contrib/suse/openssh.spec | 2 +- contrib/win32/openssh/build.psm1 | 36 +- contrib/win32/openssh/config.h.vs | 2 +- contrib/win32/openssh/install-sshd.ps1 | 16 +- contrib/win32/openssh/libssh.vcxproj | 6 +- contrib/win32/openssh/version.rc | Bin 4046 -> 4046 bytes contrib/win32/openssh/win32iocompat.vcxproj | 11 +- .../openssh/win32iocompat.vcxproj.filters | 1 + contrib/win32/win32compat/fileio.c | 9 +- contrib/win32/win32compat/inc/w32posix.h | 3 + contrib/win32/win32compat/misc.c | 152 ++--- contrib/win32/win32compat/misc_internal.h | 3 + contrib/win32/win32compat/pwd.c | 26 - contrib/win32/win32compat/w32fd.c | 11 +- contrib/win32/win32compat/win32_dirent.c | 9 +- dh.c | 4 +- log.c | 1 - misc.c | 2 +- openbsd-compat/arc4random.c | 13 + readconf.c | 2 + readpass.c | 19 +- regress/Makefile | 5 +- regress/allow-deny-users.sh | 40 ++ regress/cert-file.sh | 2 +- regress/login-timeout.sh | 4 +- regress/pesterTests/SCP.Tests.ps1 | 82 ++- regress/reexec.sh | 11 +- regress/test-exec.sh | 25 +- regress/unittests/utf8/tests.c | 3 +- sandbox-darwin.c | 1 + scp.c | 120 ++-- servconf.c | 2 +- session.c | 552 +++++++++--------- sftp-client.c | 4 +- sftp-common.c | 3 +- sftp-common.c.orig | 533 ----------------- sftp-glob.c | 1 - sftp-server.c | 63 +- sftp.c | 246 ++++---- ssh.c | 2 +- sshd.c | 82 +-- sshtty.c | 7 +- utf8.c | 11 +- version.h | 4 +- 51 files changed, 785 insertions(+), 1373 deletions(-) create mode 100644 contrib/win32/win32compat/misc_internal.h create mode 100644 regress/allow-deny-users.sh delete mode 100644 sftp-common.c.orig diff --git a/README b/README index bea648d..60594ee 100644 --- a/README +++ b/README @@ -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 instructions and note that we do not use Github for bug reporting or diff --git a/appveyor.yml b/appveyor.yml index 727d98c..0d2d454 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,10 +1,10 @@ -version: 0.0.4.0.{build} +version: 0.0.6.0.{build} image: Visual Studio 2015 branches: only: - - V_7_3w - - latestw_cwb + - latestw_all + - latestw_all_openssl init: - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) diff --git a/auth.c b/auth.c index 57692a4..a6ba4d4 100644 --- a/auth.c +++ b/auth.c @@ -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. * @@ -192,7 +192,7 @@ allowed_user(struct passwd * pw) /* Return false if user is listed in DenyUsers */ 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, options.deny_users[i]); if (r < 0) { @@ -204,6 +204,7 @@ allowed_user(struct passwd * pw) pw->pw_name, hostname); return 0; } + } } /* Return false if AllowUsers isn't empty and user isn't listed there */ if (options.num_allow_users > 0) { @@ -576,7 +577,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes, struct stat st; int fd; FILE *f; - + #ifdef WINDOWS /* Windows POSIX adpater does not support fdopen() on open(file)*/ if ((f = fopen(file, "r")) == NULL) { @@ -616,6 +617,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes, return NULL; } #endif /* !WINDOWS */ + return f; } diff --git a/auth2-pubkey.c b/auth2-pubkey.c index d794bc9..949a864 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -245,10 +245,11 @@ userauth_pubkey(Authctxt *authctxt) * if a user is not allowed to login. is this an * issue? -markus */ -#ifndef WINDOWS - if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) -#endif /* !WINDOWS */ +#ifdef WINDOWS /* key validation in done in agent for Windows */ { +#else /* !WINDOWS */ + if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) { +#endif /* !WINDOWS */ packet_start(SSH2_MSG_USERAUTH_PK_OK); packet_put_string(pkalg, alen); packet_put_string(pkblob, blen); diff --git a/channels.c b/channels.c index 7fa8683..ef4018b 100644 --- a/channels.c +++ b/channels.c @@ -2049,6 +2049,7 @@ channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset) c->notbefore = monotime() + 1; return; } + #ifndef WINDOWS /*TODO - implement user check for Windows*/ if (getpeereid(newsock, &euid, &egid) < 0) { error("%s getpeereid failed: %s", __func__, diff --git a/clientloop.c b/clientloop.c index 9350e26..5bec8c0 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1273,6 +1273,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, } continue; #endif /* !WINDOWS */ + case '?': print_escape_help(berr, escape_char, compat20, (c && c->ctl_chan != -1), diff --git a/contrib/redhat/openssh.spec b/contrib/redhat/openssh.spec index 34bbc46..666097c 100644 --- a/contrib/redhat/openssh.spec +++ b/contrib/redhat/openssh.spec @@ -1,4 +1,4 @@ -%define ver 7.3p1 +%define ver 7.4p1 %define rel 1 # OpenSSH privilege separation requires a user & group ID diff --git a/contrib/suse/openssh.spec b/contrib/suse/openssh.spec index 5b64c15..4c4bbb6 100644 --- a/contrib/suse/openssh.spec +++ b/contrib/suse/openssh.spec @@ -13,7 +13,7 @@ Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation Name: openssh -Version: 7.3p1 +Version: 7.4p1 URL: https://www.openssh.com/ Release: 1 Source0: openssh-%{version}.tar.gz diff --git a/contrib/win32/openssh/build.psm1 b/contrib/win32/openssh/build.psm1 index 0eeff8f..ed5ec5a 100644 --- a/contrib/win32/openssh/build.psm1 +++ b/contrib/win32/openssh/build.psm1 @@ -3,6 +3,7 @@ Set-StrictMode -Version Latest [string] $script:platform = $env:PROCESSOR_ARCHITECTURE [string] $script:vcPath = $null [System.IO.DirectoryInfo] $script:OpenSSHRoot = $null +[System.IO.DirectoryInfo] $script:gitRoot = $null [bool] $script:Verbose = $false [string] $script:BuildLogFile = $null @@ -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 { [CmdletBinding(SupportsShouldProcess=$false)] @@ -286,6 +315,8 @@ function Start-SSHBuild # Get openssh-portable root $script:OpenSSHRoot = Get-Item -Path $repositoryRoot.FullName + $script:gitRoot = split-path $script:OpenSSHRoot + if($PSBoundParameters.ContainsKey("Verbose")) { @@ -302,6 +333,9 @@ function Start-SSHBuild Write-BuildMsg -AsInfo -Message "Build Log: $($script:BuildLogFile)" Start-SSHBootstrap + + Clone-Win32OpenSSH + Copy-OpenSSLSDK $msbuildCmd = "msbuild.exe" $solutionFile = Get-SolutionFile -root $repositoryRoot.FullName $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") } -Export-ModuleMember -Function Start-SSHBuild, Get-RepositoryRoot, Get-BuildLogFile \ No newline at end of file +Export-ModuleMember -Function Start-SSHBuild, Get-RepositoryRoot, Get-BuildLogFile, Clone-Win32OpenSSH, Copy-OpenSSLSDK \ No newline at end of file diff --git a/contrib/win32/openssh/config.h.vs b/contrib/win32/openssh/config.h.vs index e798289..f7a8f00 100644 --- a/contrib/win32/openssh/config.h.vs +++ b/contrib/win32/openssh/config.h.vs @@ -876,7 +876,7 @@ /* #undef HAVE_SET_ID */ /* 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 header file. */ /* #undef HAVE_SHA2_H */ diff --git a/contrib/win32/openssh/install-sshd.ps1 b/contrib/win32/openssh/install-sshd.ps1 index d9c08cc..d16a63e 100644 --- a/contrib/win32/openssh/install-sshd.ps1 +++ b/contrib/win32/openssh/install-sshd.ps1 @@ -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 $sshdpath = Join-Path $scriptdir "sshd.exe" $sshagentpath = Join-Path $scriptdir "ssh-agent.exe" $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)) { 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)' 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 cd $scriptdir @@ -35,9 +39,9 @@ cmd.exe /c $ntrights Pop-Location 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.SetSecurityDescriptorSddlForm($sddl) +$Acl.SetAccessRule($accessRule) Set-Acl -Path $logsdir -AclObject $acl Write-Host -ForegroundColor Green "sshd and ssh-agent services successfully installed" - diff --git a/contrib/win32/openssh/libssh.vcxproj b/contrib/win32/openssh/libssh.vcxproj index deffb3d..1205b58 100644 --- a/contrib/win32/openssh/libssh.vcxproj +++ b/contrib/win32/openssh/libssh.vcxproj @@ -194,7 +194,7 @@ true - true + true @@ -285,7 +285,9 @@ - + + true + diff --git a/contrib/win32/openssh/version.rc b/contrib/win32/openssh/version.rc index 6242ddcbf8c816c083478cc6f6b1485c2dfabfe2..88c54b0faf5f2d19c0a0bf4d685eff0d1eb6ebed 100644 GIT binary patch delta 45 zcmX>ne@=eGBo0Qi$&)z@8O=5y<&b0oau#w+PhP;qG1-8JZ?XXQ1fax1Ze11tP9P0M delta 45 zcmX>ne@=eGBo0Q?$&)z@8BI4I<&b0oau#w+PhP;qG1-8JZ?XXQ1fax1Ze11tO}-65 diff --git a/contrib/win32/openssh/win32iocompat.vcxproj b/contrib/win32/openssh/win32iocompat.vcxproj index 7849190..549e52c 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj +++ b/contrib/win32/openssh/win32iocompat.vcxproj @@ -155,11 +155,11 @@ - - - - - + + + + + @@ -198,6 +198,7 @@ + diff --git a/contrib/win32/openssh/win32iocompat.vcxproj.filters b/contrib/win32/openssh/win32iocompat.vcxproj.filters index ee2675f..21cc7aa 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj.filters +++ b/contrib/win32/openssh/win32iocompat.vcxproj.filters @@ -117,6 +117,7 @@ inc + diff --git a/contrib/win32/win32compat/fileio.c b/contrib/win32/win32compat/fileio.c index 466c7df..8d7ed26 100644 --- a/contrib/win32/win32compat/fileio.c +++ b/contrib/win32/win32compat/fileio.c @@ -199,9 +199,14 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) { return -1; } + cf_flags->dwShareMode = 0; + switch (rwflags) { case O_RDONLY: 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; case O_WRONLY: cf_flags->dwDesiredAccess = GENERIC_WRITE; @@ -211,8 +216,6 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) { break; } - cf_flags->dwShareMode = 0; - cf_flags->securityAttributes.lpSecurityDescriptor = NULL; cf_flags->securityAttributes.bInheritHandle = TRUE; 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) 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 */ diff --git a/contrib/win32/win32compat/inc/w32posix.h b/contrib/win32/win32compat/inc/w32posix.h index 0236b3c..7e7beed 100644 --- a/contrib/win32/win32compat/inc/w32posix.h +++ b/contrib/win32/win32compat/inc/w32posix.h @@ -159,3 +159,6 @@ explicit_bzero(void *b, size_t len); #define fopen w32_fopen_utf8 #define popen _popen #define pclose _pclose + +void convertToBackslash(char *str); +void convertToForwardslash(char *str); diff --git a/contrib/win32/win32compat/misc.c b/contrib/win32/win32compat/misc.c index 722a881..32b2ddc 100644 --- a/contrib/win32/win32compat/misc.c +++ b/contrib/win32/win32compat/misc.c @@ -36,6 +36,7 @@ #include "inc\sys\time.h" #include #include +#include "misc_internal.h" int usleep(unsigned int useconds) { @@ -302,11 +303,25 @@ spawn_child(char* cmd, int in, int out, int err, DWORD flags) { PROCESS_INFORMATION pi; STARTUPINFOW si; BOOL b; - char* abs_cmd; + char *abs_cmd, *t; wchar_t * cmd_utf16; + int add_module_path = 0; - /* relative ? if so, add current module path to start */ - if (!(cmd && cmd[0] != '\0' && (cmd[1] == ':' || cmd[0] == '\\' || cmd[0] == '.'))) { + /* should module path be added */ + do{ + if(!cmd) + break; + t = cmd; + if (*t == '\"') + t++; + if (t[0] == '\0' || t[0] == '\\' || t[0] == '.' || t[1] == ':') + break; + add_module_path = 1; + + } while (0); + + /* add current module path to start if needed */ + if (add_module_path) { char* ctr; abs_cmd = malloc(strlen(w32_programdir()) + 1 + strlen(cmd) + 1); if (abs_cmd == NULL) { @@ -478,8 +493,6 @@ w32_chown(const char *pathname, unsigned int owner, unsigned int group) { return -1; } -char *realpath_win(const char *path, char resolved[MAX_PATH]); - int w32_utimes(const char *filename, struct timeval *tvp) { struct utimbuf ub; @@ -487,10 +500,7 @@ w32_utimes(const char *filename, struct timeval *tvp) { ub.modtime = tvp[1].tv_sec; int ret; - // Skip the first '/' in the pathname - char resolvedPathName[MAX_PATH]; - realpath_win(filename, resolvedPathName); - wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolvedPathName); + wchar_t *resolvedPathName_utf16 = utf8_to_utf16(sanitized_path(filename)); if (resolvedPathName_utf16 == NULL) { errno = ENOMEM; return -1; @@ -517,16 +527,9 @@ link(const char *oldpath, const char *newpath) { int w32_rename(const char *old_name, const char *new_name) { - // Skip the first '/' in the pathname - char resolvedOldPathName[MAX_PATH]; - 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); + wchar_t *resolvedOldPathName_utf16 = utf8_to_utf16(sanitized_path(old_name)); + wchar_t *resolvedNewPathName_utf16 = utf8_to_utf16(sanitized_path(new_name)); + if (NULL == resolvedOldPathName_utf16 || NULL == resolvedNewPathName_utf16) { errno = ENOMEM; return -1; @@ -541,11 +544,8 @@ w32_rename(const char *old_name, const char *new_name) { int w32_unlink(const char *path) { - // Skip the first '/' in the pathname - char resolvedPathName[MAX_PATH]; - realpath_win(path, resolvedPathName); - - wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolvedPathName); + + wchar_t *resolvedPathName_utf16 = utf8_to_utf16(sanitized_path(path)); if (NULL == resolvedPathName_utf16) { errno = ENOMEM; return -1; @@ -559,11 +559,7 @@ w32_unlink(const char *path) { int w32_rmdir(const char *path) { - // Skip the first '/' in the pathname - char resolvedPathName[MAX_PATH]; - realpath_win(path, resolvedPathName); - - wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolvedPathName); + wchar_t *resolvedPathName_utf16 = utf8_to_utf16(sanitized_path(path)); if (NULL == resolvedPathName_utf16) { errno = ENOMEM; return -1; @@ -606,11 +602,8 @@ w32_getcwd(char *buffer, int maxlen) { int w32_mkdir(const char *path_utf8, unsigned short mode) { - // Skip the first '/' in the pathname - char resolvedPathName[MAX_PATH]; - realpath_win(path_utf8, resolvedPathName); - - wchar_t *path_utf16 = utf8_to_utf16(resolvedPathName); + + wchar_t *path_utf16 = utf8_to_utf16(sanitized_path(path_utf8)); if (path_utf16 == NULL) { errno = ENOMEM; return -1; @@ -621,86 +614,62 @@ w32_mkdir(const char *path_utf8, unsigned short mode) { 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 w32_stat(const char *path, struct w32_stat *buf) { - // Skip the first '/' in the pathname - char resolvedPathName[MAX_PATH]; - realpath_win(path, resolvedPathName); - - return fileio_stat(resolvedPathName, (struct _stat64*)buf); + return fileio_stat(sanitized_path(path), (struct _stat64*)buf); } // if file is symbolic link, copy its link into "link" . int readlink(const char *path, char *link, int linklen) { - // Skip the first '/' in the pathname - char resolvedPathName[MAX_PATH]; - realpath_win(path, resolvedPathName); - - strcpy_s(link, linklen, resolvedPathName); + strcpy_s(link, linklen, sanitized_path(path)); 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 /./, -* /../ and extra '/' characters in the null-terminated string named by +* This method will resolves references to /./, /../ and extra '/' characters in the null-terminated string named by * path to produce a canonicalized absolute pathname. */ char * -realpath(const char *path, char resolved[MAX_PATH]) -{ +realpath(const char *path, char resolved[MAX_PATH]) { char tempPath[MAX_PATH]; - - if ((0 == strcmp(path, "./")) || (0 == strcmp(path, "."))) { - tempPath[0] = '/'; - _getcwd(&tempPath[1], sizeof(tempPath) - 1); - slashconvert(tempPath); - - strncpy(resolved, tempPath, strlen(tempPath) + 1); - return resolved; - } - - if (path[0] != '/') - strlcpy(resolved, path, sizeof(tempPath)); + + if (*path == '/' && *(path + 2) == ':') + strncpy(resolved, path + 1, strlen(path)); // skip the first '/' else - strlcpy(resolved, path + 1, sizeof(tempPath)); + strncpy(resolved, path, strlen(path) + 1); - backslashconvert(resolved); - PathCanonicalizeA(tempPath, resolved); - slashconvert(tempPath); - - // Store terminating slash in 'X:/' on Windows. - if (tempPath[1] == ':' && tempPath[2] == 0) { - tempPath[2] = '/'; - tempPath[3] = 0; - } + if (_fullpath(tempPath, resolved, MAX_PATH) == NULL) + return NULL; + + convertToForwardslash(tempPath); resolved[0] = '/'; // will be our first slash in /x:/users/test1 format strncpy(resolved + 1, tempPath, sizeof(tempPath) - 1); 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 // data is 16KB, plus there's a header. #define MAX_REPARSE_SIZE 17000 @@ -737,8 +706,7 @@ typedef struct _REPARSE_DATA_BUFFER { } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; 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; BYTE reparseBuffer[MAX_REPARSE_SIZE]; PBYTE reparseData; diff --git a/contrib/win32/win32compat/misc_internal.h b/contrib/win32/win32compat/misc_internal.h new file mode 100644 index 0000000..0cd2369 --- /dev/null +++ b/contrib/win32/win32compat/misc_internal.h @@ -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)) \ No newline at end of file diff --git a/contrib/win32/win32compat/pwd.c b/contrib/win32/win32compat/pwd.c index b779f55..9d0a4a7 100644 --- a/contrib/win32/win32compat/pwd.c +++ b/contrib/win32/win32compat/pwd.c @@ -231,32 +231,6 @@ char *user_from_uid(uid_t uid, int nouser) { return "-"; } - -/* TODO - this is moved from realpath.c in openbsdcompat. Review and finalize its position*/ - -#include - -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 getuid(void) { return 0; diff --git a/contrib/win32/win32compat/w32fd.c b/contrib/win32/win32compat/w32fd.c index 9353f8c..ab6281b 100644 --- a/contrib/win32/win32compat/w32fd.c +++ b/contrib/win32/win32compat/w32fd.c @@ -40,6 +40,7 @@ #include #include "Shlwapi.h" #include +#include "misc_internal.h" /* internal table that stores the fd to w32_io mapping*/ 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); return 0; } -char *realpath_win(const char *path, char resolved[MAX_PATH]); + int w32_open(const char *pathname, int flags, ...) { int min_index = fd_table_get_min_index(); @@ -357,18 +358,14 @@ w32_open(const char *pathname, int flags, ...) { if (min_index == -1) return -1; - // Skip the first '/' in the pathname - char resolvedPathName[MAX_PATH]; - realpath_win(pathname, resolvedPathName); - - pio = fileio_open(resolvedPathName, flags, 0); + pio = fileio_open(sanitized_path(pathname), flags, 0); if (pio == NULL) return -1; pio->type = NONSOCK_FD; fd_table_set(pio, min_index); debug("open - handle:%p, io:%p, fd:%d", pio->handle, pio, min_index); - debug3("open - path:%s", resolvedPathName); + debug3("open - path:%s", pathname); return min_index; } diff --git a/contrib/win32/win32compat/win32_dirent.c b/contrib/win32/win32compat/win32_dirent.c index e009375..2418e13 100644 --- a/contrib/win32/win32compat/win32_dirent.c +++ b/contrib/win32/win32compat/win32_dirent.c @@ -11,6 +11,7 @@ #include "inc\dirent.h" #include "inc\libgen.h" +#include "misc_internal.h" struct DIR_ { @@ -19,8 +20,6 @@ struct DIR_ { int first; }; -char * realpath_win(const char *path, char resolved[MAX_PATH]); - /* Open a directory stream on NAME. Return a DIR stream on the directory, or NULL if it could not be opened. */ DIR * opendir(const char *name) @@ -32,11 +31,7 @@ DIR * opendir(const char *name) wchar_t* wname = NULL; int needed; - // Skip the first '/' in the pathname - char resolvedPathName[MAX_PATH]; - realpath_win(name, resolvedPathName); - - if ((wname = utf8_to_utf16(resolvedPathName)) == NULL) { + if ((wname = utf8_to_utf16(sanitized_path(name))) == NULL) { errno = ENOMEM; return NULL; } diff --git a/dh.c b/dh.c index 194f29b..4753124 100644 --- a/dh.c +++ b/dh.c @@ -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. * @@ -152,7 +152,7 @@ choose_dh(int min, int wantbits, int max) struct dhgroup dhg; 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)); return (dh_new_group_fallback(max)); } diff --git a/log.c b/log.c index 6f603e5..53721f3 100644 --- a/log.c +++ b/log.c @@ -446,7 +446,6 @@ do_log(LogLevel level, const char *fmt, va_list args) } strnvis(fmtbuf, msgbuf, sizeof(fmtbuf), log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS); - if (log_handler != NULL) { /* Avoid recursion */ tmp_handler = log_handler; diff --git a/misc.c b/misc.c index 5e87503..3dfcef6 100644 --- a/misc.c +++ b/misc.c @@ -432,7 +432,6 @@ char * colon(char *cp) { int flag = 0; - int len = 0; if (*cp == ':') /* Leading colon is part of file name. */ 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) fatal("tilde_expand_filename: Path too long"); + return (ret); } diff --git a/openbsd-compat/arc4random.c b/openbsd-compat/arc4random.c index b6256b4..128f9b6 100644 --- a/openbsd-compat/arc4random.c +++ b/openbsd-compat/arc4random.c @@ -78,6 +78,18 @@ _rs_init(u_char *buf, size_t n) } #ifndef WITH_OPENSSL +#ifdef WINDOWS +#include +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" /* XXX use getrandom() if supported on Linux */ static void @@ -101,6 +113,7 @@ getrnd(u_char *s, size_t len) } close(fd); } +#endif /* !WINDOWS */ #endif static void diff --git a/readconf.c b/readconf.c index d44b804..bf52589 100644 --- a/readconf.c +++ b/readconf.c @@ -469,6 +469,7 @@ default_ssh_port(void) static int execute_in_shell(const char *cmd) { + char *shell; #ifdef WINDOWS fatal("LocalCommand execution is not supported on Windows yet"); return 0; @@ -1725,6 +1726,7 @@ read_config_file_depth(const char *filename, struct passwd *pw, fatal("Bad owner or permissions on %s", filename); } #endif /* !WINDOWS */ + debug("Reading configuration data %.200s", filename); /* diff --git a/readpass.c b/readpass.c index 12f433c..78f8f07 100644 --- a/readpass.c +++ b/readpass.c @@ -145,6 +145,8 @@ read_passphrase(const char *prompt, int flags) /* prompt user */ wchar_t* wtmp = utf8_to_utf16(prompt); + if (wtmp == NULL) + fatal("unable to alloc memory"); _cputws(wtmp); free(wtmp); @@ -158,28 +160,28 @@ read_passphrase(const char *prompt, int flags) buf[len] = (unsigned char)_getch(); if (buf[len] == '\r') { - if (_kbhit()) - _getch(); // read linefeed if its there + if (_kbhit()) /* read linefeed if its there */ + _getch(); break; } else if (buf[len] == '\n') { break; } - else if (buf[len] == '\b') { // backspace + else if (buf[len] == '\b') { /* backspace */ if (len > 0) - len--; // overwrite last character + len--; /* overwrite last character */ } else if (buf[len] == '\003') { /* exit on Ctrl+C */ fatal(""); } else { - len++; // keep reading in the loop + len++; /* keep reading in the loop */ } } - buf[len] = '\0'; // get rid of the cr/lf - _cputs("\n"); // show a newline as we do not echo password or the line + buf[len] = '\0'; /* get rid of the cr/lf */ + _cputs("\n"); /*show a newline as we do not echo password or the line */ ret = xstrdup(buf); @@ -188,7 +190,6 @@ read_passphrase(const char *prompt, int flags) return ret; #else /* !WINDOWS */ - char *askpass = NULL, *ret, buf[1024]; int rppflags, use_askpass = 0, ttyfd; @@ -235,9 +236,7 @@ read_passphrase(const char *prompt, int flags) ret = xstrdup(buf); explicit_bzero(buf, sizeof(buf)); return ret; - #endif /* !WINDOWS */ - } int diff --git a/regress/Makefile b/regress/Makefile index bb88068..c2dba4f 100644 --- a/regress/Makefile +++ b/regress/Makefile @@ -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 tests: prep $(REGRESS_TARGETS) @@ -78,7 +78,8 @@ LTESTS= connect \ hostkey-rotate \ principals-command \ cert-file \ - cfginclude + cfginclude \ + allow-deny-users # dhgex \ diff --git a/regress/allow-deny-users.sh b/regress/allow-deny-users.sh new file mode 100644 index 0000000..86805e1 --- /dev/null +++ b/regress/allow-deny-users.sh @@ -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" diff --git a/regress/cert-file.sh b/regress/cert-file.sh index bad923a..b184e7f 100644 --- a/regress/cert-file.sh +++ b/regress/cert-file.sh @@ -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. tid="ssh with certificates" diff --git a/regress/login-timeout.sh b/regress/login-timeout.sh index eb76f55..12207fd 100644 --- a/regress/login-timeout.sh +++ b/regress/login-timeout.sh @@ -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. tid="connect after login grace timeout" @@ -17,7 +17,7 @@ if [ $? -ne 0 ]; then fail "ssh connect after login grace timeout failed with privsep" fi -$SUDO kill `$SUDO cat $PIDFILE` +stop_sshd trace "test login grace without privsep" echo "UsePrivilegeSeparation no" >> $OBJ/sshd_config diff --git a/regress/pesterTests/SCP.Tests.ps1 b/regress/pesterTests/SCP.Tests.ps1 index b510df8..7e9a4d6 100644 --- a/regress/pesterTests/SCP.Tests.ps1 +++ b/regress/pesterTests/SCP.Tests.ps1 @@ -26,13 +26,12 @@ Describe "Tests for scp command" -Tags "CI" { $client.SetupClient($server) $server.SetupServer($client) - $testData = @( - <# known issue 340 + $testData = @( @{ Title = 'Simple copy local file to local file' Source = $SourceFilePath Destination = $DestinationFilePath - },#> + }, @{ Title = 'Simple copy local file to remote file' Source = $SourceFilePath @@ -42,13 +41,12 @@ Describe "Tests for scp command" -Tags "CI" { Title = 'Simple copy remote file to local file' Source = "$($server.localAdminUserName)@$($server.MachineName):$SourceFilePath" Destination = $DestinationFilePath - }, - <# known issue 340 + }, @{ Title = 'Simple copy local file to local dir' Source = $SourceFilePath Destination = $DestinationDir - },#> + }, @{ Title = 'simple copy local file to remote dir' Source = $SourceFilePath @@ -66,7 +64,7 @@ Describe "Tests for scp command" -Tags "CI" { Title = 'copy from local dir to remote dir' Source = $sourceDir Destination = "$($server.localAdminUserName)@$($server.MachineName):$DestinationDir" - }, + }, @{ Title = 'copy from local dir to local dir' Source = $sourceDir @@ -84,16 +82,16 @@ Describe "Tests for scp command" -Tags "CI" { $client.CleanupClient() $server.CleanupServer() - Get-Item $SourceDir | Remove-Item -Recurse -Force -ea silentlycontinue - Get-Item $DestinationDir | Remove-Item -Recurse -Force -ea silentlycontinue + Get-Item $SourceDir | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue + Get-Item $DestinationDir | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue } - BeforeEach { + BeforeAll { $null = New-Item $DestinationDir -ItemType directory -Force } 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" { @@ -121,7 +119,7 @@ Describe "Tests for scp command" -Tags "CI" { $equal | Should Be $true } - <#It 'Directory recursive Copy with -i option: ' -TestCases:$testData1 { + It 'Directory recursive Copy with -i option: <Title> ' -TestCases:$testData1 { param([string]$Title, $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 | 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 | Should Be $true - }#> + + $equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0 + $equal | Should Be $true + } } #this context only run on windows @@ -149,37 +147,34 @@ Describe "Tests for scp command" -Tags "CI" { #cleanup single signon .\ssh-add.exe -D - } + } It 'File Copy with -S option (positive)' { .\scp -S .\ssh.exe $SourceFilePath "$($server.localAdminUserName)@$($server.MachineName):$DestinationFilePath" #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 } - <#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) - .\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. - $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 | Should Be $true - }#> - - <# known issue 369 - It 'Directory recursive Copy with -v option: <Title> ' -TestCases:$testData1 { - param([string]$Title, $Source, $Destination) - - .\scp -r -p $Source $Destination + $equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length, LastWriteTime.DateTime).Length -eq 0 + $equal | Should Be $true + } + + It 'Directory recursive Copy with -r -p -v option: <Title> ' -TestCases:$testData1 { + param([string]$Title, $Source, $Destination) + .\scp -r -p -c aes128-ctr -v $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 - - #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" { @@ -192,23 +187,20 @@ Describe "Tests for scp command" -Tags "CI" { .\scp -i $identifyFile -C -q $Source $Destination #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 } - <#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) .\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 | 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 | Should Be $true - }#> - } - + + $equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0 + $equal | Should Be $true + } + } } - diff --git a/regress/reexec.sh b/regress/reexec.sh index 5c0a7b4..72957d4 100644 --- a/regress/reexec.sh +++ b/regress/reexec.sh @@ -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. tid="reexec tests" @@ -39,8 +39,7 @@ echo "InvalidXXX=no" >> $OBJ/sshd_config copy_tests -$SUDO kill `$SUDO cat $PIDFILE` -rm -f $PIDFILE +stop_sshd cp $OBJ/sshd_config.orig $OBJ/sshd_config @@ -54,8 +53,7 @@ rm -f $SSHD_COPY copy_tests -$SUDO kill `$SUDO cat $PIDFILE` -rm -f $PIDFILE +stop_sshd verbose "test reexec fallback without privsep" @@ -67,7 +65,6 @@ rm -f $SSHD_COPY copy_tests -$SUDO kill `$SUDO cat $PIDFILE` -rm -f $PIDFILE +stop_sshd fi diff --git a/regress/test-exec.sh b/regress/test-exec.sh index 5d48706..bfa4880 100644 --- a/regress/test-exec.sh +++ b/regress/test-exec.sh @@ -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. #SUDO=sudo @@ -293,16 +293,8 @@ md5 () { } # End of portable specific functions -# helper -cleanup () +stop_sshd () { - 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 pid=`$SUDO cat $PIDFILE` if [ "X$pid" = "X" ]; then @@ -325,6 +317,19 @@ cleanup () 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 () { echo "trace: $@" >$TEST_REGRESS_LOGFILE diff --git a/regress/unittests/utf8/tests.c b/regress/unittests/utf8/tests.c index 304b73d..32c6171 100644 --- a/regress/unittests/utf8/tests.c +++ b/regress/unittests/utf8/tests.c @@ -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 * @@ -69,7 +69,6 @@ tests(void) TEST_DONE(); badarg(); - one("null", NULL, 8, 6, 6, "(null)"); one("empty", "", 2, 0, 0, ""); one("ascii", "x", -2, -2, -2, "x"); one("newline", "a\nb", -2, -2, -2, "a\nb"); diff --git a/sandbox-darwin.c b/sandbox-darwin.c index 35f0c4d..a61de74 100644 --- a/sandbox-darwin.c +++ b/sandbox-darwin.c @@ -31,6 +31,7 @@ #include "log.h" #include "sandbox.h" +#include "monitor.h" #include "xmalloc.h" /* Darwin/OS X sandbox */ diff --git a/scp.c b/scp.c index 097f51d..e65b466 100644 --- a/scp.c +++ b/scp.c @@ -214,7 +214,7 @@ do_local_cmd(arglist *a) return 0; } -#else +#else /* !WINDOWS */ if ((pid = fork()) == -1) fatal("do_local_cmd: fork: %s", strerror(errno)); @@ -239,7 +239,7 @@ do_local_cmd(arglist *a) return (-1); 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. */ #ifdef WINDOWS + /* generate command line and spawn_child */ replacearg(&args, 0, "%s", ssh_program); if (remuser != NULL) { 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); free(full_cmd); } - - -#else +#else /* !WINDOWS */ do_cmd_pid = fork(); -#endif +#endif /* !WINDOWS */ if (do_cmd_pid == 0) { /* Child. */ 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. */ #ifdef WINDOWS + /* generate command line and spawn_child */ replacearg(&args, 0, "%s", ssh_program); if (remuser != NULL) { 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); free(full_cmd); -} -#else + } +#else /* !WINDOWS */ pid = fork(); -#endif +#endif /* !WINDOWS */ if (pid == 0) { dup2(fdin, 0); dup2(fdout, 1); @@ -592,6 +592,18 @@ main(int argc, char **argv) remin = STDIN_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) { /* Follow "protocol", send data. */ (void) response(); @@ -807,6 +819,41 @@ tolocal(int argc, char **argv) for (i = 0; i < argc - 1; i++) { if (!(src = colon(argv[i]))) { /* Local to local. */ 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); if (iamrecursive) addargs(&alist, "-r"); @@ -815,6 +862,7 @@ tolocal(int argc, char **argv) addargs(&alist, "--"); addargs(&alist, "%s", argv[i]); addargs(&alist, "%s", argv[argc-1]); +#endif /* !WINDOWS */ if (do_local_cmd(&alist)) ++errs; continue; @@ -892,26 +940,10 @@ syserr: run_err("%s: %s", name, strerror(errno)); run_err("%s: not a regular file", name); 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) last = name; else ++last; -#endif curfile = last; if (pflag) { 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); if (verbose_mode) #ifdef WINDOWS - /* TODO - make fmprintf work for Windows */ - { - printf("Entering directory: "); - wchar_t* wtmp = utf8_to_utf16(path); - WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), wtmp, wcslen(wtmp), 0, 0); - free(wtmp); - } -#else + /* TODO - make fmprintf work for Windows */ + { + printf("Entering directory: "); + wchar_t* wtmp = utf8_to_utf16(path); + WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), wtmp, wcslen(wtmp), 0, 0); + free(wtmp); + } +#else /* !WINDOWS */ fmprintf(stderr, "Entering directory: %s", path); -#endif +#endif /* !WINDOWS */ (void) atomicio(vwrite, remout, path, strlen(path)); if (response() < 0) { closedir(dirp); @@ -1085,16 +1117,17 @@ sink(int argc, char **argv) *cp = 0; if (verbose_mode) #ifdef WINDOWS - /* TODO - make fmprintf work for Windows */ - { - printf("Sink: "); - wchar_t* wtmp = utf8_to_utf16(buf); - WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), wtmp, wcslen(wtmp), 0, 0); - free(wtmp); - } -#else + /* TODO - make fmprintf work for Windows */ + { + printf("Sink: "); + wchar_t* wtmp = utf8_to_utf16(buf); + WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), wtmp, wcslen(wtmp), 0, 0); + free(wtmp); + } +#else /* !WINDOWS */ fmprintf(stderr, "Sink: %s", buf); -#endif +#endif /* !WINDOWS */ + if (buf[0] == '\01' || buf[0] == '\02') { if (iamremote == 0) { (void) snmprintf(visbuf, sizeof(visbuf), @@ -1496,3 +1529,4 @@ lostconn(int signo) else exit(1); } + diff --git a/servconf.c b/servconf.c index 5c7d58d..3b82322 100644 --- a/servconf.c +++ b/servconf.c @@ -606,7 +606,7 @@ derelativise_path(const char *path) expanded = tilde_expand_filename(path, getuid()); #ifdef WINDOWS /* Windows absolute paths have a drive letter followed by :*/ - if (expanded[1] == ':') + if (*expanded != '\0' && expanded[1] == ':') #else /* !WINDOWS */ if (*expanded == '/') #endif /* !WINDOWS */ diff --git a/session.c b/session.c index 44e8bdd..c0fb6d7 100644 --- a/session.c +++ b/session.c @@ -183,8 +183,8 @@ static int auth_input_request_forwarding(struct passwd * pw) { #ifdef WINDOWS - packet_send_debug("Agent forwarding not supported yet in Windows"); - return 0; + packet_send_debug("Agent forwarding not supported yet in Windows"); + return 0; #else /* !WINDOWS */ Channel *nc; int sock = -1; @@ -296,7 +296,7 @@ xauth_valid_string(const char *s) * do_exec* on Windows * - Read and set user environment variables from registry * - 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 */ #include <Shlobj.h> @@ -312,360 +312,336 @@ xauth_valid_string(const char *s) void setup_session_vars(Session* s) { - wchar_t* pw_dir_w; - wchar_t* tmp; - char buf[128]; - char* laddr; + wchar_t* pw_dir_w; + wchar_t* tmp; + char buf[128]; + 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) - 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 ((pw_dir_w = utf8_to_utf16(s->pw->pw_dir)) == NULL) + fatal("%s: out of memory"); - if (s->display) - SetEnvironmentVariableA("DISPLAY", s->display); + if ((tmp = utf8_to_utf16(s->pw->pw_name)) == NULL) + 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"USERPROFILE", pw_dir_w); + SetEnvironmentVariableW(L"HOMEPATH", pw_dir_w); + SetEnvironmentVariableW(L"USERPROFILE", pw_dir_w); - if (pw_dir_w[1] == L':') { - wchar_t wc = pw_dir_w[2]; - pw_dir_w[2] = L'\0'; - SetEnvironmentVariableW(L"HOMEDRIVE", pw_dir_w); - pw_dir_w[2] = wc; - } + if (pw_dir_w[1] == L':') { + wchar_t wc = pw_dir_w[2]; + pw_dir_w[2] = L'\0'; + SetEnvironmentVariableW(L"HOMEDRIVE", pw_dir_w); + pw_dir_w[2] = wc; + } - snprintf(buf, sizeof buf, "%.50s %d %d", - ssh->remote_ipaddr, ssh->remote_port, ssh->local_port); + snprintf(buf, sizeof buf, "%.50s %d %d", + 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", - ssh->remote_ipaddr, ssh->remote_port, laddr, ssh->local_port); + snprintf(buf, sizeof buf, "%.50s %d %.50s %d", + 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) - SetEnvironmentVariableA("SSH_ORIGINAL_COMMAND", original_command); + if (original_command) + SetEnvironmentVariableA("SSH_ORIGINAL_COMMAND", original_command); - if ((s->term) && (s->term[0])) - SetEnvironmentVariable("TERM", s->term); + if ((s->term) && (s->term[0])) + SetEnvironmentVariable("TERM", s->term); - if (!s->is_subsystem) { - snprintf(buf, sizeof buf, "%s@%s $P$G", s->pw->pw_name, getenv("COMPUTERNAME")); - SetEnvironmentVariableA("PROMPT", buf); - } + if (!s->is_subsystem) { + snprintf(buf, sizeof buf, "%s@%s $P$G", s->pw->pw_name, getenv("COMPUTERNAME")); + SetEnvironmentVariableA("PROMPT", buf); + } - /*set user environment variables*/ - { - UCHAR InfoBuffer[1000]; - PTOKEN_USER pTokenUser = (PTOKEN_USER)InfoBuffer; - DWORD dwInfoBufferSize, tmp_len; - LPWSTR sid_str = NULL; - wchar_t reg_path[MAX_PATH]; - HKEY reg_key = 0; - HANDLE token = s->authctxt->methoddata; - - tmp_len = MAX_PATH; - if (GetTokenInformation(token, TokenUser, InfoBuffer, - 1000, &dwInfoBufferSize) == 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 || - RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY, ®_key) != 0 || - RegQueryValueExW(reg_key, L"ProfileImagePath", 0, NULL, (LPBYTE)pw_dir_w, &tmp_len) != 0) { - /* one of the above failed */ - debug("cannot retirve profile path - perhaps user profile is not created yet"); - } + /*set user environment variables*/ + { + UCHAR InfoBuffer[1000]; + PTOKEN_USER pTokenUser = (PTOKEN_USER)InfoBuffer; + DWORD dwInfoBufferSize, tmp_len; + LPWSTR sid_str = NULL; + wchar_t reg_path[MAX_PATH]; + HKEY reg_key = 0; + HANDLE token = s->authctxt->methoddata; + + tmp_len = MAX_PATH; + if (GetTokenInformation(token, TokenUser, InfoBuffer, + 1000, &dwInfoBufferSize) == 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 || + RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY, ®_key) != 0 || + RegQueryValueExW(reg_key, L"ProfileImagePath", 0, NULL, (LPBYTE)pw_dir_w, &tmp_len) != 0) { + /* one of the above failed */ + debug("cannot retirve profile path - perhaps user profile is not created yet"); + } - if (sid_str) - LocalFree(sid_str); + if (sid_str) + LocalFree(sid_str); - if (reg_key) - RegCloseKey(reg_key); - - { /* retrieve and set env variables. */ - /* TODO - Get away with fixed limits and dynamically allocate required memory, cleanup this logic*/ + if (reg_key) + RegCloseKey(reg_key); + + /* retrieve and set env variables. */ + { #define MAX_VALUE_LEN 1000 #define MAX_DATA_LEN 2000 #define MAX_EXPANDED_DATA_LEN 5000 - wchar_t *path; - wchar_t value_name[MAX_VALUE_LEN]; - wchar_t value_data[MAX_DATA_LEN], value_data_expanded[MAX_EXPANDED_DATA_LEN], *to_apply; - DWORD value_type, name_len, data_len; - int i; - LONG ret; + /* TODO - Get away with fixed limits and dynamically allocate required memory, cleanup this logic*/ + wchar_t *path; + wchar_t value_name[MAX_VALUE_LEN]; + wchar_t value_data[MAX_DATA_LEN], value_data_expanded[MAX_EXPANDED_DATA_LEN], *to_apply; + DWORD value_type, name_len, data_len; + int i; + LONG ret; - if (ImpersonateLoggedOnUser(token) == FALSE) - debug("Failed to impersonate user token, %d", GetLastError()); - SET_USER_ENV(FOLDERID_LocalAppData, L"LOCALAPPDATA"); - SET_USER_ENV(FOLDERID_Profile, L"USERPROFILE"); - SET_USER_ENV(FOLDERID_RoamingAppData, L"APPDATA"); - reg_key = 0; - if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Environment", 0, KEY_QUERY_VALUE, ®_key) == ERROR_SUCCESS) { - i = 0; - while (1) { - name_len = MAX_VALUE_LEN * 2; - data_len = MAX_DATA_LEN * 2; - to_apply = NULL; - if (RegEnumValueW(reg_key, i++, value_name, &name_len, 0, &value_type, (LPBYTE)&value_data, &data_len) != ERROR_SUCCESS) - break; - if (value_type == REG_SZ) - to_apply = value_data; - else if (value_type == REG_EXPAND_SZ) { - ExpandEnvironmentStringsW(value_data, value_data_expanded, MAX_EXPANDED_DATA_LEN); - to_apply = value_data_expanded; - } + if (ImpersonateLoggedOnUser(token) == FALSE) + debug("Failed to impersonate user token, %d", GetLastError()); + SET_USER_ENV(FOLDERID_LocalAppData, L"LOCALAPPDATA"); + SET_USER_ENV(FOLDERID_Profile, L"USERPROFILE"); + SET_USER_ENV(FOLDERID_RoamingAppData, L"APPDATA"); + reg_key = 0; + if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Environment", 0, KEY_QUERY_VALUE, ®_key) == ERROR_SUCCESS) { + i = 0; + while (1) { + name_len = MAX_VALUE_LEN * 2; + data_len = MAX_DATA_LEN * 2; + to_apply = NULL; + if (RegEnumValueW(reg_key, i++, value_name, &name_len, 0, &value_type, (LPBYTE)&value_data, &data_len) != ERROR_SUCCESS) + break; + if (value_type == REG_SZ) + to_apply = value_data; + else if (value_type == REG_EXPAND_SZ) { + ExpandEnvironmentStringsW(value_data, value_data_expanded, MAX_EXPANDED_DATA_LEN); + to_apply = value_data_expanded; + } - if (wcsicmp(value_name, L"PATH") == 0) { - DWORD size; - if ((size = GetEnvironmentVariableW(L"PATH", NULL, 0)) != ERROR_ENVVAR_NOT_FOUND) { - memcpy(value_data_expanded + size, to_apply, (wcslen(to_apply) + 1) * 2); - GetEnvironmentVariableW(L"PATH", value_data_expanded, MAX_EXPANDED_DATA_LEN); - value_data_expanded[size - 1] = L';'; - to_apply = value_data_expanded; - } + if (wcsicmp(value_name, L"PATH") == 0) { + DWORD size; + if ((size = GetEnvironmentVariableW(L"PATH", NULL, 0)) != ERROR_ENVVAR_NOT_FOUND) { + memcpy(value_data_expanded + size, to_apply, (wcslen(to_apply) + 1) * 2); + GetEnvironmentVariableW(L"PATH", value_data_expanded, MAX_EXPANDED_DATA_LEN); + value_data_expanded[size - 1] = L';'; + to_apply = value_data_expanded; + } - } - if (to_apply) - SetEnvironmentVariableW(value_name, to_apply); + } + if (to_apply) + SetEnvironmentVariableW(value_name, to_apply); + } + RegCloseKey(reg_key); + } + RevertToSelf(); + } + } - - } - RegCloseKey(reg_key); - } - - - RevertToSelf(); - } - } - - free(pw_dir_w); + free(pw_dir_w); } int do_exec_windows(Session *s, const char *command, int pty) { - int pipein[2], pipeout[2], pipeerr[2], r; - char *exec_command = NULL, *progdir = w32_programdir(); - wchar_t *exec_command_w = NULL, *pw_dir_w; + int pipein[2], pipeout[2], pipeerr[2], r; + char *exec_command = NULL, *progdir = w32_programdir(); + wchar_t *exec_command_w = NULL, *pw_dir_w; - if (s->is_subsystem >= SUBSYSTEM_INT_SFTP_ERROR) - { - error("sub system not supported, exiting\n"); - fflush(NULL); - exit(1); - } + if (s->is_subsystem >= SUBSYSTEM_INT_SFTP_ERROR) { + error("sub system not supported, exiting\n"); + fflush(NULL); + 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 (pipe(pipein) == -1 || pipe(pipeout) == -1 || pipe(pipeerr) == -1) - 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"); + if ((pw_dir_w = utf8_to_utf16(s->pw->pw_dir)) == NULL) + fatal("%s: out of memory"); - set_nonblock(pipein[0]); - set_nonblock(pipein[1]); - set_nonblock(pipeout[0]); - set_nonblock(pipeout[1]); - set_nonblock(pipeerr[0]); - set_nonblock(pipeerr[1]); + set_nonblock(pipein[0]); + set_nonblock(pipein[1]); + set_nonblock(pipeout[0]); + set_nonblock(pipeout[1]); + set_nonblock(pipeerr[0]); + set_nonblock(pipeerr[1]); - fcntl(pipein[1], F_SETFD, FD_CLOEXEC); - fcntl(pipeout[0], F_SETFD, FD_CLOEXEC); - fcntl(pipeerr[0], F_SETFD, FD_CLOEXEC); + fcntl(pipein[1], F_SETFD, FD_CLOEXEC); + fcntl(pipeout[0], F_SETFD, FD_CLOEXEC); + fcntl(pipeerr[0], F_SETFD, FD_CLOEXEC); - /* prepare exec - path used with CreateProcess() */ - if (s->is_subsystem || (command && memcmp(command, "scp", 3) == 0)) { - /* relative or absolute */ - if (command == NULL || command[0] == '\0') - fatal("expecting command for a subsystem"); + /* prepare exec - path used with CreateProcess() */ + if (s->is_subsystem || (command && memcmp(command, "scp", 3) == 0)) { + /* relative or absolute */ + if (command == NULL || command[0] == '\0') + fatal("expecting command for a subsystem"); - if (command[1] == ':') /* absolute */ - exec_command = xstrdup(command); - else {/*relative*/ - exec_command = malloc(strlen(progdir) + 1 + strlen(command)); - if (exec_command == NULL) - fatal("%s, out of memory"); - memcpy(exec_command, progdir, strlen(progdir)); - exec_command[strlen(progdir)] = '\\'; - memcpy(exec_command + strlen(progdir) + 1, command, strlen(command) + 1); - } - } else { - 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); - if (exec_command == NULL) - fatal("%s, out of memory"); - c = exec_command; - memcpy(c, progdir, strlen(progdir)); - c += strlen(progdir); - *c++ = '\\'; - memcpy(c, shell_host, strlen(shell_host)); - c += strlen(shell_host); - if (command) { - memcpy(c, command, strlen(command)); - c += strlen(command); - } - *c = '\0'; - } + if (command[1] == ':') /* absolute */ + exec_command = xstrdup(command); + else {/*relative*/ + exec_command = malloc(strlen(progdir) + 1 + strlen(command)); + if (exec_command == NULL) + fatal("%s, out of memory"); + memcpy(exec_command, progdir, strlen(progdir)); + exec_command[strlen(progdir)] = '\\'; + memcpy(exec_command + strlen(progdir) + 1, command, strlen(command) + 1); + } + } else { + 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); + if (exec_command == NULL) + fatal("%s, out of memory"); + c = exec_command; + memcpy(c, progdir, strlen(progdir)); + c += strlen(progdir); + *c++ = '\\'; + memcpy(c, shell_host, strlen(shell_host)); + c += strlen(shell_host); + if (command) { + memcpy(c, command, strlen(command)); + c += strlen(command); + } + *c = '\0'; + } - /* setup Environment varibles */ - setup_session_vars(s); - - extern int debug_flag; + /* setup Environment varibles */ + setup_session_vars(s); + 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.lpReserved = 0; - si.lpTitle = NULL; /* NULL means use exe name as title */ - si.dwX = 0; - si.dwY = 0; - si.dwXSize = 5; - si.dwYSize = 5; - si.dwXCountChars = s->col; - si.dwYCountChars = s->row; - si.dwFillAttribute = 0; - si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESIZE | STARTF_USECOUNTCHARS; - si.wShowWindow = 0; // FALSE ; - si.cbReserved2 = 0; - si.lpReserved2 = 0; + si.cb = sizeof(STARTUPINFO); + si.lpReserved = 0; + si.lpTitle = NULL; /* NULL means use exe name as title */ + si.dwX = 0; + si.dwY = 0; + si.dwXSize = 5; + si.dwYSize = 5; + si.dwXCountChars = s->col; + si.dwYCountChars = s->row; + si.dwFillAttribute = 0; + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESIZE | STARTF_USECOUNTCHARS; + si.wShowWindow = 0; // FALSE ; + si.cbReserved2 = 0; + si.lpReserved2 = 0; - si.hStdInput = (HANDLE)sfd_to_handle(pipein[0]); - si.hStdOutput = (HANDLE)sfd_to_handle(pipeout[1]); - si.hStdError = (HANDLE)sfd_to_handle(pipeerr[1]); - si.lpDesktop = NULL; + si.hStdInput = (HANDLE)sfd_to_handle(pipein[0]); + si.hStdOutput = (HANDLE)sfd_to_handle(pipeout[1]); + si.hStdError = (HANDLE)sfd_to_handle(pipeerr[1]); + 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) - b = CreateProcessW(NULL, exec_command_w, NULL, NULL, TRUE, - DETACHED_PROCESS, NULL, pw_dir_w, - &si, &pi); - else - b = CreateProcessAsUserW(hToken, NULL, exec_command_w, NULL, NULL, TRUE, - DETACHED_PROCESS , NULL, pw_dir_w, - &si, &pi); + if (debug_flag) + b = CreateProcessW(NULL, exec_command_w, NULL, NULL, TRUE, + DETACHED_PROCESS, NULL, pw_dir_w, + &si, &pi); + else + b = CreateProcessAsUserW(hToken, NULL, exec_command_w, NULL, NULL, TRUE, + DETACHED_PROCESS , NULL, pw_dir_w, + &si, &pi); - if (!b) - { - debug("ERROR. Cannot create process (%u).\n", GetLastError()); - free(pw_dir_w); - free(exec_command_w); - CloseHandle(hToken); + if (!b) + { + debug("ERROR. Cannot create process (%u).\n", GetLastError()); + free(pw_dir_w); + free(exec_command_w); + CloseHandle(hToken); - exit(1); - } - else if (pty) { /*attach to shell console */ - FreeConsole(); - if (!debug_flag) - ImpersonateLoggedOnUser(hToken); - Sleep(20); - while (AttachConsole(pi.dwProcessId) == FALSE) { - DWORD exit_code; - if (GetExitCodeProcess(pi.hProcess, &exit_code) && exit_code != STILL_ACTIVE) - break; - Sleep(100); - } - if (!debug_flag) - RevertToSelf(); - { - /* TODO - check this - Create Process above is not respecting x# and y# chars, so we are doing this explicity on the - * attached console agein */ + exit(1); + } + else if (pty) { /*attach to shell console */ + FreeConsole(); + if (!debug_flag) + ImpersonateLoggedOnUser(hToken); + Sleep(20); + while (AttachConsole(pi.dwProcessId) == FALSE) { + DWORD exit_code; + if (GetExitCodeProcess(pi.hProcess, &exit_code) && exit_code != STILL_ACTIVE) + break; + Sleep(100); + } + if (!debug_flag) + RevertToSelf(); + { + /* TODO - check this - Create Process above is not respecting x# and y# chars, so we are doing this explicity on the + * attached console agein */ - COORD coord; - coord.X = s->col; - coord.Y = 9999;; - SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coord); - } - } + COORD coord; + coord.X = s->col; + coord.Y = 9999;; + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coord); + } + } - s->pid = pi.dwProcessId; - sw_add_child(pi.hProcess, pi.dwProcessId); + CloseHandle(pi.hThread); + 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); - /* - * Set interactive/non-interactive mode. - */ + /* Close the child sides of the socket pairs. */ + 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. + */ - /* - * We are the parent. Close the child sides of the socket pairs. - */ - - 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 + 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(exec_command_w); - return 0; + return 0; } int do_exec_no_pty(Session *s, const char *command) { - return do_exec_windows(s, command, 0); + return do_exec_windows(s, command, 0); } int do_exec_pty(Session *s, const char *command) { - return do_exec_windows(s, command, 1); + return do_exec_windows(s, command, 1); } #else /* !WINDOWS */ diff --git a/sftp-client.c b/sftp-client.c index f1a047b..e65c15c 100644 --- a/sftp-client.c +++ b/sftp-client.c @@ -1384,11 +1384,9 @@ do_download(struct sftp_conn *conn, const char *remote_path, "server reordered requests", local_path); } debug("truncating at %llu", (unsigned long long)highwater); - #ifndef WIN32_VS if (ftruncate(local_fd, highwater) == -1) error("ftruncate \"%s\": %s", local_path, strerror(errno)); - #endif } if (read_error) { 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) error("Couldn't sync file \"%s\": %s", local_path, strerror(errno)); - } + } } close(local_fd); sshbuf_free(msg); diff --git a/sftp-common.c b/sftp-common.c index 3f96a75..3a70c52 100644 --- a/sftp-common.c +++ b/sftp-common.c @@ -222,7 +222,7 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units) strmode(st->st_mode, mode); if (!remote) { - user = user_from_uid(st->st_uid, 0); + user = user_from_uid(st->st_uid, 0); } else { snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid); 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); group = gbuf; } - if (ltime != NULL) { now = time(NULL); if (now - (365*24*60*60)/2 < st->st_mtime && diff --git a/sftp-common.c.orig b/sftp-common.c.orig deleted file mode 100644 index 40ae9fb..0000000 --- a/sftp-common.c.orig +++ /dev/null @@ -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 diff --git a/sftp-glob.c b/sftp-glob.c index b7aa618..43a1beb 100644 --- a/sftp-glob.c +++ b/sftp-glob.c @@ -67,7 +67,6 @@ fudge_readdir(struct SFTP_OPENDIR *od) /* Solaris needs sizeof(dirent) + path length (see below) */ static char buf[sizeof(struct dirent) + MAXPATHLEN]; struct dirent *ret = (struct dirent *)buf; - #ifdef __GNU_LIBRARY__ static int inum = 1; #endif /* __GNU_LIBRARY__ */ diff --git a/sftp-server.c b/sftp-server.c index b6a770e..3619cdf 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -688,7 +688,6 @@ process_open(u_int32_t id) debug3("request %u: open flags %d", id, pflags); flags = flags_from_portable(pflags); mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666; - logit("open \"%s\" flags %s mode 0%o", name, string_from_portable(pflags), mode); if (readonly && @@ -821,15 +820,13 @@ process_do_stat(u_int32_t id, int do_lstat) struct stat st; char *name; int r, status = SSH2_FX_FAILURE; - + if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) 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" : ""); verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name); - + r = do_lstat ? lstat(name, &st) : stat(name, &st); if (r < 0) { status = errno_to_portable(errno); } else { @@ -899,9 +896,8 @@ process_setstat(u_int32_t id) char *name; int r, status = SSH2_FX_OK; - // sshbuf_get_cstring() is called twice.. is this correct? 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)); debug("request %u: setstat name \"%s\"", id, name); @@ -936,7 +932,6 @@ process_setstat(u_int32_t id) if (r == -1) status = errno_to_portable(errno); } - send_status(id, status); free(name); } @@ -962,7 +957,6 @@ process_fsetstat(u_int32_t id) if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { logit("set \"%s\" size %llu", name, (unsigned long long)a.size); - r = ftruncate(fd, a.size); if (r == -1) status = errno_to_portable(errno); @@ -995,7 +989,6 @@ process_fsetstat(u_int32_t id) if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { logit("set \"%s\" owner %lu group %lu", name, (u_long)a.uid, (u_long)a.gid); - #ifdef HAVE_FCHOWN r = fchown(fd, a.uid, a.gid); #else @@ -1018,11 +1011,9 @@ process_opendir(u_int32_t id) if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); - dirp = opendir(path); - debug3("request %u: opendir", id); logit("opendir \"%s\"", path); - + dirp = opendir(path); if (dirp == NULL) { status = errno_to_portable(errno); } else { @@ -1064,7 +1055,6 @@ process_readdir(u_int32_t id) int nstats = 10, count = 0, i; stats = xcalloc(nstats, sizeof(Stat)); - while ((dp = readdir(dirp)) != NULL) { if (count >= nstats) { nstats *= 2; @@ -1078,7 +1068,7 @@ process_readdir(u_int32_t id) stat_to_attrib(&st, &(stats[count].attrib)); stats[count].name = xstrdup(dp->d_name); stats[count].long_name = ls_file(dp->d_name, &st, 0, 0); - count++; + count++; /* send up to 100 entries in one message */ /* XXX check packet size instead */ if (count == 100) @@ -1108,7 +1098,6 @@ process_remove(u_int32_t id) debug3("request %u: remove", id); logit("remove name \"%s\"", name); - r = unlink(name); status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); @@ -1130,8 +1119,6 @@ process_mkdir(u_int32_t id) a.perm & 07777 : 0777; debug3("request %u: mkdir", id); logit("mkdir name \"%s\" mode 0%o", name, mode); - - r = mkdir(name, mode); status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); @@ -1149,7 +1136,6 @@ process_rmdir(u_int32_t id) debug3("request %u: rmdir", id); logit("rmdir name \"%s\"", name); - r = rmdir(name); status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); @@ -1170,7 +1156,6 @@ process_realpath(u_int32_t id) free(path); path = xstrdup("."); } - debug3("request %u: realpath", id); verbose("realpath \"%s\"", path); if (realpath(path, resolvedname) == NULL) { @@ -1233,8 +1218,7 @@ process_rename(u_int32_t id) unlink(newpath); } else status = SSH2_FX_OK; - } - else if (stat(newpath, &sb) == -1) { + } else if (stat(newpath, &sb) == -1) { if (rename(oldpath, newpath) == -1) status = errno_to_portable(errno); else @@ -1257,7 +1241,6 @@ process_readlink(u_int32_t id) debug3("request %u: readlink", id); verbose("readlink \"%s\"", path); - if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) send_status(id, errno_to_portable(errno)); else { @@ -1275,7 +1258,7 @@ static void process_symlink(u_int32_t id) { char *oldpath, *newpath; - int r, status= SSH2_FX_OP_UNSUPPORTED; + int r, status; if ((r = sshbuf_get_cstring(iqueue, &oldpath, 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); logit("symlink old \"%s\" new \"%s\"", oldpath, newpath); - /* this will fail if 'newpath' exists */ r = symlink(oldpath, newpath); status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); - free(oldpath); free(newpath); } @@ -1317,7 +1298,6 @@ process_extended_statvfs(u_int32_t id) { char *path; struct statvfs st; - int r; 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); return; } - - if (statvfs(handle_to_name(handle), &st) != 0) - if (fstatvfs(fd, &st) != 0) - send_status(id, errno_to_portable(errno)); - else - send_statvfs(id, &st); + if (fstatvfs(fd, &st) != 0) + send_status(id, errno_to_portable(errno)); + else + send_statvfs(id, &st); } static void process_extended_hardlink(u_int32_t id) { char *oldpath, *newpath; - int r, status = SSH2_FX_OP_UNSUPPORTED; + int r, status; if ((r = sshbuf_get_cstring(iqueue, &oldpath, 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); logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath); - r = link(oldpath, newpath); status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; - send_status(id, status); free(oldpath); free(newpath); @@ -1429,11 +1405,10 @@ process(void) const u_char *cp; int i, r; u_int32_t id; - + buf_len = sshbuf_len(iqueue); - if (buf_len < 5) { + if (buf_len < 5) return; /* Incomplete message. */ - } cp = sshbuf_ptr(iqueue); msg_len = get_u32(cp); if (msg_len > SFTP_MAX_MSG_LENGTH) { @@ -1441,9 +1416,8 @@ process(void) client_addr, pw->pw_name); sftp_server_cleanup_exit(11); } - if (buf_len < msg_len + 4) { + if (buf_len < msg_len + 4) return; - } if ((r = sshbuf_consume(iqueue, 4)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); 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; ssize_t len, olen, set_size; SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; - - char *cp, *homedir = NULL, buf[4*4096]; + char *cp, *homedir = NULL, buf[4*4096]; long mask; extern char *optarg; @@ -1608,7 +1581,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) sftp_server_usage(); } } - + 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", __func__, ssh_err(r)); } -//#endif /* else WIN32 */ } - diff --git a/sftp.c b/sftp.c index 3e03016..9910fda 100644 --- a/sftp.c +++ b/sftp.c @@ -73,7 +73,6 @@ typedef void EditLine; #define DEFAULT_COPY_BUFLEN 32768 /* Size of buffer for up/download */ #define DEFAULT_NUM_REQUESTS 64 /* # concurrent outstanding requests */ -#define MAX_COMMAND_LINE 2048 /* File to read commands from */ FILE* infile; @@ -295,6 +294,7 @@ help(void) #ifdef WINDOWS /* printf version to account for utf-8 input */ +/* TODO - merge this with vfmprint */ static void printf_utf8(char *fmt, ... ) { /* TODO - is 1024 sufficient */ char buf[1024]; @@ -311,6 +311,8 @@ static void printf_utf8(char *fmt, ... ) { free(wtmp); } +/* override mprintf */ +#define mprintf(a,...) printf_utf8((a), __VA_ARGS__) #define printf(a,...) printf_utf8((a), __VA_ARGS__) #endif /* WINDOWS */ @@ -324,7 +326,7 @@ local_do_shell(const char *args) args = (char *) getenv("ComSpec"); // get name of Windows cmd shell } system(args); // execute the shell or cmd given - #else + #else /* !WINDOWS */ int status; char *shell; pid_t pid; @@ -358,7 +360,7 @@ local_do_shell(const char *args) error("Shell exited abnormally"); else if (WEXITSTATUS(status)) error("Shell exited with status %d", WEXITSTATUS(status)); - #endif + #endif /* !WINDOWS */ } static void @@ -418,11 +420,7 @@ make_absolute(char *p, const char *pwd) } /* convert '\\' tp '/' */ - s1 = p; - while ((s2 = strchr(s1, '\\')) != NULL) { - *s2 = '/'; - s1 = s2 + 1; - } + convertToForwardslash(p); /* Append "/" if needed to the absolute windows path */ if (p && p[0] != '\0' && p[1] == ':') { @@ -431,13 +429,14 @@ make_absolute(char *p, const char *pwd) p = s1; } -#else +#else /* !WINDOWS */ if (p && p[0] != '/') { abs_str = path_append(pwd, p); free(p); return(abs_str); - } -#endif + } else + return(p); +#endif /* !WINDOWS */ return(p); } @@ -672,7 +671,6 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst, abs_src = xstrdup(src); abs_src = make_absolute(abs_src, pwd); - memset(&g, 0, sizeof(g)); debug3("Looking up %s", abs_src); @@ -712,7 +710,7 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst, } else { abs_dst = xstrdup(dst); } - } else if (dst) { + } else if (dst) { abs_dst = path_append(dst, filename); } else { abs_dst = xstrdup(filename); @@ -720,10 +718,12 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst, free(tmp); resume |= global_aflag; - if (!quiet && resume) - printf("Resuming %s to %s\n", g.gl_pathv[i], abs_dst); - else if (!quiet && !resume) - printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); + if (!quiet && resume) + mprintf("Resuming %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 (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, 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 (tmp_dst != NULL) { + if (tmp_dst != NULL) dst_is_dir = remote_is_dir(conn, tmp_dst); - } - /* If multiple matches, dst may be directory or unspecified */ 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); else abs_dst = xstrdup(tmp_dst); - } else if (tmp_dst) { + } else if (tmp_dst) { abs_dst = path_append(tmp_dst, filename); } else { 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; if (!quiet && resume) - printf("Resuming upload of %s to %s\n", g.gl_pathv[i], - abs_dst); + mprintf("Resuming upload of %s to %s\n", + g.gl_pathv[i], abs_dst); 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 (upload_dir(conn, g.gl_pathv[i], abs_dst, 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) width = ws.ws_col; + columns = width / (m + 2); columns = MAXIMUM(columns, 1); colspace = width / columns; @@ -919,24 +919,21 @@ do_ls_dir(struct sftp_conn *conn, const char *path, attrib_to_stat(&d[n]->a, &sb); lname = ls_file(fname, &sb, 1, (lflag & LS_SI_UNITS)); - printf("%s\n", lname); + mprintf("%s\n", lname); free(lname); - } - else { - printf("%s\n", d[n]->longname); - } - } - else { + } else + mprintf("%s\n", d[n]->longname); + } else { #ifdef WINDOWS - /* cannot use printf_utf8 becuase of width specification */ - /* printf_utf8 does not account for utf-16 based argument widths */ - wchar_t buf[1024]; - wchar_t* wtmp = utf8_to_utf16(fname); - swprintf(buf, 1024, L"%-*s", colspace, wtmp); - WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), buf, wcslen(buf), 0, 0); - free(wtmp); + /* cannot use printf_utf8 becuase of width specification */ + /* printf_utf8 does not account for utf-16 based argument widths */ + wchar_t buf[1024]; + wchar_t* wtmp = utf8_to_utf16(fname); + swprintf(buf, 1024, L"%-*s", colspace, wtmp); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), buf, wcslen(buf), 0, 0); + free(wtmp); #else - printf("%-*s", colspace, fname); + mprintf("%-*s", colspace, fname); #endif if (c >= columns) { printf("\n"); @@ -995,7 +992,7 @@ do_globbed_ls(struct sftp_conn *conn, const char *path, globfree(&g); return err; } - + if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) 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, (lflag & LS_SI_UNITS)); - printf("%s\n", lname); - free(lname); + mprintf("%s\n", lname); + free(lname); } else { #ifdef WINDOWS - /* cannot use printf_utf8 becuase of width specification */ - /* printf_utf8 does not account for utf-16 based argument widths */ - wchar_t buf[1024]; - wchar_t* wtmp = utf8_to_utf16(fname); - swprintf(buf, 1024, L"%-*s", colspace, wtmp); - WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), buf, wcslen(buf), 0, 0); - free(wtmp); + /* cannot use printf_utf8 becuase of width specification */ + /* printf_utf8 does not account for utf-16 based argument widths */ + wchar_t buf[1024]; + wchar_t* wtmp = utf8_to_utf16(fname); + swprintf(buf, 1024, L"%-*s", colspace, wtmp); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), buf, wcslen(buf), 0, 0); + free(wtmp); #else - printf("%-*s", colspace, fname); + mprintf("%-*s", colspace, fname); #endif - if (c >= columns) { + if (c >= columns) { printf("\n"); c = 1; } else @@ -1513,23 +1510,17 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, path1 = path2 = NULL; #ifdef WINDOWS /* - * convert '/' to '\' in Windows styled paths. + * convert '\\' to '/' in Windows styled paths. * else they get treated as escape sequence in makeargv */ - { - char *s1 = cmd, *s2; - while ((s2 = strchr(s1, '\\')) != NULL) { - *s2 = '/'; - s1 = s2 + 1; - } - } + convertToForwardslash(cmd); #endif cmdnum = parse_args(&cmd, &ignore_errors, &aflag, &fflag, &hflag, &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg, &path1, &path2); if (ignore_errors != 0) err_abort = 0; - memset(&g, 0, sizeof(g)); + memset(&g, 0, sizeof(g)); /* Perform command */ switch (cmdnum) { @@ -1570,10 +1561,9 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, case I_RM: path1 = make_absolute(path1, *pwd); remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); - - for (i = 0; g.gl_pathv[i] && !interrupted; i++) { - if (!quiet) - printf("Removing %s\n", g.gl_pathv[i]); + for (i = 0; g.gl_pathv[i] && !interrupted; i++) { + if (!quiet) + mprintf("Removing %s\n", g.gl_pathv[i]); err = do_rm(conn, g.gl_pathv[i]); if (err != 0 && err_abort) 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); for (i = 0; g.gl_pathv[i] && !interrupted; i++) { 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); if (err != 0 && err_abort) break; @@ -1703,13 +1694,13 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; if (cmdnum == I_CHOWN) { if (!quiet) - printf("Changing owner on %s\n", - g.gl_pathv[i]); + mprintf("Changing owner on %s\n", + g.gl_pathv[i]); aa->uid = n_arg; } else { if (!quiet) - printf("Changing group on %s\n", - g.gl_pathv[i]); + mprintf("Changing group on %s\n", + g.gl_pathv[i]); aa->gid = n_arg; } 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; case I_PWD: - printf("Remote working directory: %s\n", *pwd); + mprintf("Remote working directory: %s\n", *pwd); break; case I_LPWD: 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; break; } - printf("Local working directory: %s\n", path_buf); + mprintf("Local working directory: %s\n", path_buf); break; case I_QUIT: /* Processed below */ @@ -2129,7 +2120,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) { char *remote_path; char *dir = NULL; - char cmd[MAX_COMMAND_LINE]; + char cmd[2048]; int err, interactive; EditLine *el = NULL; #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 (!quiet) - printf("Changing to: %s\n", dir); + mprintf("Changing to: %s\n", dir); snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); if (parse_dispatch_command(conn, cmd, &remote_path, 1) != 0) { @@ -2205,13 +2196,13 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) } #ifdef WINDOWS - /* Min buffer size allowed in Windows is 2*/ - setvbuf(stdout, NULL, _IOLBF, 2); - setvbuf(infile, NULL, _IOLBF, 2); -#else - setvbuf(stdout, NULL, _IOLBF, 0); + /* Min buffer size allowed in Windows is 2*/ + setvbuf(stdout, NULL, _IOLBF, 2); + setvbuf(infile, NULL, _IOLBF, 2); +#else /* !WINDOWS */ + setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(infile, NULL, _IOLBF, 0); -#endif +#endif /* !WINDOWS */ interactive = !batchmode && isatty(STDIN_FILENO); err = 0; @@ -2222,35 +2213,32 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) if (el == NULL) { #ifdef WINDOWS - if (interactive) { - wchar_t wcmd[MAX_COMMAND_LINE]; - printf("sftp> "); - if (fgetws(wcmd, sizeof(cmd)/sizeof(wchar_t), infile) == NULL) { - printf("\n"); - break; - } - else { - char *pcmd = NULL; - if ((pcmd = utf16_to_utf8(wcmd)) == NULL) - fatal("failed to convert input arguments"); - strcpy(cmd, pcmd); - free(pcmd); - } - } - else { - if (fgets(cmd, sizeof(cmd), infile) == NULL) { - break; - } - } -#else - if (interactive) { - printf("sftp> "); - if (fgets(cmd, sizeof(cmd), infile) == NULL) { - if (interactive) - printf("\n"); - break; - } -#endif + /* fgets on Windows does not support Unicode input*/ + if (interactive) { + wchar_t wcmd[2048]; + printf("sftp> "); + if (fgetws(wcmd, sizeof(cmd)/sizeof(wchar_t), infile) == NULL) { + printf("\n"); + break; + } + else { + char *pcmd = NULL; + if ((pcmd = utf16_to_utf8(wcmd)) == NULL) + fatal("failed to convert input arguments"); + strcpy(cmd, pcmd); + free(pcmd); + } + } else if (fgets(cmd, sizeof(cmd), infile) == NULL) + break; +#else /* !WINDOWS */ + if (interactive) + printf("sftp> "); + if (fgets(cmd, sizeof(cmd), infile) == NULL) { + if (interactive) + printf("\n"); + break; + } +#endif/* !WINDOWS */ if (!interactive) { /* Echo command */ mprintf("sftp> %s", cmd); if (strlen(cmd) > 0 && @@ -2324,6 +2312,7 @@ connect_to_server(char *path, char **args, int *in, int *out) #endif /* USE_PIPES */ #ifdef WINDOWS + /* fork replacement on Windows */ { size_t cmdlen = 0; int i = 0; @@ -2331,14 +2320,15 @@ connect_to_server(char *path, char **args, int *in, int *out) cmdlen = strlen(path) + 1; for (i = 1; args[i]; i++) - cmdlen += strlen(args[i]) + 1; + cmdlen += strlen(args[i]) + 1 + 2; full_cmd = xmalloc(cmdlen); full_cmd[0] = '\0'; strcat(full_cmd, path); for (i = 1; args[i]; i++) { - strcat(full_cmd, " "); + strcat(full_cmd, " \""); strcat(full_cmd, args[i]); + strcat(full_cmd, "\""); } /* disable inheritance on local pipe ends*/ @@ -2350,9 +2340,9 @@ connect_to_server(char *path, char **args, int *in, int *out) } if (sshpid == -1) -#else +#else /* !WINDOWS */ if ((sshpid = fork()) == -1) -#endif +#endif /* !WINDOWS */ fatal("fork: %s", strerror(errno)); else if (sshpid == 0) { if ((dup2(c_in, STDIN_FILENO) == -1) || @@ -2426,11 +2416,7 @@ main(int argc, char **argv) size_t num_requests = DEFAULT_NUM_REQUESTS; long long limit_kbps = 0; -#ifdef WINDOWS - /*TODO - is this really needed ???*/ - setvbuf(stdout, NULL, _IONBF, 0); - #endif - + ssh_malloc_init(); /* must be called before any mallocs */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); msetlocale(); @@ -2439,17 +2425,18 @@ main(int argc, char **argv) memset(&args, '\0', sizeof(args)); args.list = NULL; addargs(&args, "%s", ssh_program); - - addargs(&args, "\"-oForwardX11 no\""); - addargs(&args, "\"-oForwardAgent no\""); - addargs(&args, "\"-oPermitLocalCommand no\""); - addargs(&args, "\"-oClearAllForwardings yes\""); + addargs(&args, "-oForwardX11 no"); + addargs(&args, "-oForwardAgent no"); + addargs(&args, "-oPermitLocalCommand no"); + addargs(&args, "-oClearAllForwardings yes"); ll = SYSLOG_LEVEL_INFO; + #ifdef WINDOWS - _setmode(_fileno(stdin), O_U16TEXT); + /* prepare for Unicode input */ + _setmode(_fileno(stdin), O_U16TEXT); #endif - infile = stdin; + infile = stdin; while ((ch = getopt(argc, argv, "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); break; case 'P': - addargs(&args, "\"-oPort %s\"", optarg); - break; + addargs(&args, "-oPort %s", optarg); + break; case 'v': if (debug_level < 3) { addargs(&args, "-v"); @@ -2510,8 +2497,8 @@ main(int argc, char **argv) fatal("%s (%s).", strerror(errno), optarg); showprogress = 0; quiet = batchmode = 1; - addargs(&args, "\"-obatchmode yes\""); - break; + addargs(&args, "-obatchmode yes"); + break; case 'f': global_fflag = 1; break; @@ -2584,7 +2571,8 @@ main(int argc, char **argv) fprintf(stderr, "Missing hostname\n"); usage(); } - addargs(&args, "\"-oProtocol %d\"", sshver); + + addargs(&args, "-oProtocol %d", sshver); /* no subsystem if the server-spec contains a '/' */ if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) diff --git a/ssh.c b/ssh.c index 3447008..f718e42 100644 --- a/ssh.c +++ b/ssh.c @@ -1475,7 +1475,7 @@ control_persist_detach(void) */ fatal("ControlMaster is not supported in Windows yet"); #else /* !WINDOWS */ - pid_t pid; + pid_t pid; int devnull, keep_stderr; debug("%s: backgrounding master process", __func__); diff --git a/sshd.c b/sshd.c index 236962a..16f3206 100644 --- a/sshd.c +++ b/sshd.c @@ -164,11 +164,11 @@ int saved_argc; /* re-exec */ int rexeced_flag = 0; #ifdef WINDOWS -/* rexec is not supported in Windows */ +/* rexec is not applicable in Windows */ int rexec_flag = 0; -#else +#else /* !WINDOWS */ int rexec_flag = 1; -#endif +#endif /* !WINDOWS */ int rexec_argc = 0; char **rexec_argv; @@ -254,59 +254,6 @@ void destroy_sensitive_data(void); void demote_sensitive_data(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 */ @@ -591,7 +538,7 @@ reseed_prngs(void) /* * No-OP defs for preauth routines for Windows * 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 privsep_preauth_child(void) { @@ -608,7 +555,7 @@ privsep_postauth(Authctxt *authctxt) { return; } -#else +#else /* !WINDOWS */ /* Unix privilege separation routines */ static void privsep_preauth_child(void) @@ -645,6 +592,7 @@ privsep_preauth_child(void) if (setgroups(1, gidset) < 0) fatal("setgroups: %.100s", strerror(errno)); permanently_set_uid(privsep_pw); + } } static int @@ -768,7 +716,7 @@ privsep_postauth(Authctxt *authctxt) packet_set_authenticated(); } -#endif +#endif /* !WINDOWS */ static char * list_hostkey_types(void) @@ -1143,7 +1091,7 @@ server_listen(void) close(listen_sock); continue; } -#endif +#endif /* WINDOWS */ /* * Set socket options. * 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); close(*newsock); } -#else +#else /* !WINDOWS */ 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]); break; } -#endif +#endif /* !WINDOWS */ /* Parent. Stay in the loop. */ platform_post_fork_parent(pid); if (pid < 0) @@ -1764,7 +1712,7 @@ main(int ac, char **av) #endif ); -#ifndef WINDOWS +#ifndef WINDOWS /* not applicable in Windows */ /* Store privilege separation user for later use if required. */ if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { if (use_privsep || options.kerberos_authentication) @@ -1778,7 +1726,7 @@ main(int ac, char **av) privsep_pw->pw_passwd = xstrdup("*"); } endpwent(); -#endif +#endif /* !WINDOWS */ /* load host keys */ 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", options.host_key_agent, ssh_err(r)); } -#ifdef WIN32_FIXME +#ifdef WINDOWS /* Windows version always needs and has agent running */ have_agent = 1; #endif for (i = 0; i < options.num_host_key_files; i++) { @@ -1977,7 +1925,7 @@ main(int ac, char **av) #ifdef WINDOWS /* For Windows child sshd, skip listener */ if (is_child == 0) -#endif +#endif /* WINDOWS */ server_listen(); signal(SIGHUP, sighup_handler); @@ -2020,7 +1968,7 @@ main(int ac, char **av) fcntl(startup_pipe, F_SETFD, FD_CLOEXEC); } else /* Windows and Unix sshd parent */ -#endif +#endif /* WINDOWS */ /* Accept a connection and return in a forked child */ server_accept_loop(&sock_in, &sock_out, diff --git a/sshtty.c b/sshtty.c index b9012c2..b971bbc 100644 --- a/sshtty.c +++ b/sshtty.c @@ -74,9 +74,7 @@ void enter_raw_mode(int quiet) { ConInit(STD_OUTPUT_HANDLE, TRUE); } - #else /* !WINDOWS */ - struct termios * get_saved_tio(void) { @@ -124,7 +122,4 @@ enter_raw_mode(int quiet) } else _in_raw_mode = 1; } - -#endif /* !WINDOWS */ - - +#endif /* !WINDOWS */ \ No newline at end of file diff --git a/utf8.c b/utf8.c index 5d3e6e4..00a0a73 100644 --- a/utf8.c +++ b/utf8.c @@ -57,16 +57,15 @@ static int vasnmprintf(char **, size_t, int *, const char *, va_list); static int dangerous_locale(void) { - -#ifndef WINDOWS +#ifdef 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; loc = nl_langinfo(CODESET); 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 */ } diff --git a/version.h b/version.h index 617ab62..269ebcd 100644 --- a/version.h +++ b/version.h @@ -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_RELEASE SSH_VERSION SSH_PORTABLE