Skip to content

Commit

Permalink
Fixes for #648 and #718
Browse files Browse the repository at this point in the history
  • Loading branch information
bingbing8 authored and manojampalam committed May 18, 2017
1 parent 79662b9 commit afc6ca9
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 32 deletions.
10 changes: 7 additions & 3 deletions contrib/win32/openssh/OpenSSHBuildHelper.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ function Package-OpenSSH

if ($DestinationPath -ne "") {
if (Test-Path $DestinationPath) {
Remove-Item $DestinationPath\* -Force -Recurse
Remove-Item $DestinationPath\* -Force -Recurse -ErrorAction SilentlyContinue
}
else {
New-Item -ItemType Directory $DestinationPath -Force | Out-Null
Expand Down Expand Up @@ -542,18 +542,22 @@ function UnInstall-OpenSSH
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
)

if (-not (Test-Path $OpenSSHDir))
{
return
}

Push-Location $OpenSSHDir
if((Get-Service ssh-agent -ErrorAction Ignore) -ne $null) {
Stop-Service ssh-agent -Force
}
&( "$OpenSSHDir\uninstall-sshd.ps1")
&( "$OpenSSHDir\uninstall-sshlsa.ps1")

$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
$newMachineEnvironmentPath = $machinePath
if ($machinePath.ToLower().Contains($OpenSSHDir.ToLower()))
{
$newMachineEnvironmentPath.Replace("$OpenSSHDir;", '')
$newMachineEnvironmentPath = $newMachineEnvironmentPath.Replace("$OpenSSHDir;", '')
$env:Path = $env:Path.Replace("$OpenSSHDir;", '')
}

Expand Down
58 changes: 45 additions & 13 deletions contrib/win32/win32compat/fileio.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <io.h>
#include <errno.h>
#include <stddef.h>
#include <direct.h>

#include "w32fd.h"
#include "inc\utf.h"
Expand Down Expand Up @@ -638,22 +639,53 @@ int
fileio_stat(const char *path, struct _stat64 *buf)
{
wchar_t* wpath = NULL;
int r = -1;

if ((wpath = utf8_to_utf16(path)) == NULL)
fatal("failed to covert input arguments");

r = _wstat64(wpath, buf);

/*
* If we doesn't have sufficient permissions then _wstat64() is returning "file not found"
* TODO - Replace the above call with GetFileAttributesEx
*/
WIN32_FILE_ATTRIBUTE_DATA attributes = { 0 };
int ret = -1, len = 0;
if ((wpath = utf8_to_utf16(path)) == NULL) {
errno = errno_from_Win32LastError();
debug3("utf8_to_utf16 failed for file:%s error:%d", path, GetLastError());
return -1;
}
memset(buf, 0, sizeof(struct _stat64));

if (GetFileAttributesExW(wpath, GetFileExInfoStandard, &attributes) == FALSE) {
errno = errno_from_Win32LastError();
debug3("GetFileAttributesExW with last error %d", GetLastError());
goto cleanup;
}

len = wcslen(wpath);

buf->st_ino = 0; /* Has no meaning in the FAT, HPFS, or NTFS file systems*/
buf->st_gid = 0; /* UNIX - specific; has no meaning on windows */
buf->st_uid = 0; /* UNIX - specific; has no meaning on windows */
buf->st_nlink = 1; /* number of hard links. Always 1 on non - NTFS file systems.*/
buf->st_mode |= file_attr_to_st_mode(wpath, attributes.dwFileAttributes);
buf->st_size = attributes.nFileSizeLow | (((off_t)attributes.nFileSizeHigh) << 32);
if (len > 1 && __ascii_iswalpha(*wpath) && (*(wpath + 1) == ':'))
buf->st_dev = buf->st_rdev = towupper(*wpath) - L'A'; /* drive num */
else
buf->st_dev = buf->st_rdev = _getdrive() - 1;
file_time_to_unix_time(&(attributes.ftLastAccessTime), &(buf->st_atime));
file_time_to_unix_time(&(attributes.ftLastWriteTime), &(buf->st_mtime));
file_time_to_unix_time(&(attributes.ftCreationTime), &(buf->st_ctime));

if (attributes.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
WIN32_FIND_DATAW findbuf = { 0 };
HANDLE handle = FindFirstFileW(wpath, &findbuf);
if (handle != INVALID_HANDLE_VALUE) {
if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
(findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
buf->st_mode |= S_IFLNK;
}
FindClose(handle);
}
}
ret = 0;
cleanup:
if (wpath)
free(wpath);
return r;
free(wpath);
return ret;
}

long
Expand Down
6 changes: 3 additions & 3 deletions contrib/win32/win32compat/inc/sys/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
#define utimes w32_utimes

int usleep(unsigned int);
int gettimeofday(struct timeval *tv, void *tz);
int nanosleep(const struct timespec *req, struct timespec *rem);
int w32_utimes(const char *filename, struct timeval *tvp);
int gettimeofday(struct timeval *, void *);
int nanosleep(const struct timespec *, struct timespec *);
int w32_utimes(const char *, struct timeval *);
89 changes: 77 additions & 12 deletions contrib/win32/win32compat/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ static char* s_programdir = NULL;
#define IO_REPARSE_TAG_SIS (0x80000007L) /* winnt ntifs */
#define REPARSE_MOUNTPOINT_HEADER_SIZE 8

/* Difference in us between UNIX Epoch and Win32 Epoch */
#define EPOCH_DELTA_US 116444736000000000ULL
#define RATE_DIFF 10000000ULL /* 1000 nsecs */

typedef struct _REPARSE_DATA_BUFFER {
ULONG ReparseTag;
USHORT ReparseDataLength;
Expand Down Expand Up @@ -174,9 +178,6 @@ nanosleep(const struct timespec *req, struct timespec *rem)
}
}

/* Difference in us between UNIX Epoch and Win32 Epoch */
#define EPOCH_DELTA_US 11644473600000000ULL

/* This routine is contributed by * Author: NoMachine <[email protected]>
* Copyright (c) 2009, 2010 NoMachine
* All rights reserved
Expand All @@ -191,17 +192,14 @@ gettimeofday(struct timeval *tv, void *tz)
unsigned long long us;

/* Fetch time since Jan 1, 1601 in 100ns increments */
GetSystemTimeAsFileTime(&timehelper.ft);

/* Convert to microseconds from 100 ns units */
us = timehelper.ns / 10;
GetSystemTimeAsFileTime(&timehelper.ft);

/* Remove the epoch difference */
us -= EPOCH_DELTA_US;
us = timehelper.ns - EPOCH_DELTA_US;

/* Stuff result into the timeval */
tv->tv_sec = (long)(us / 1000000ULL);
tv->tv_usec = (long)(us % 1000000ULL);
tv->tv_sec = (long)(us / RATE_DIFF);
tv->tv_usec = (long)(us % RATE_DIFF);

return 0;
}
Expand Down Expand Up @@ -550,16 +548,83 @@ w32_chown(const char *pathname, unsigned int owner, unsigned int group)
return -1;
}

static void
/* Convert a UNIX time into a Windows file time */
void
unix_time_to_file_time(ULONG t, LPFILETIME pft)
{
ULONGLONG ull;
ull = UInt32x32To64(t, 10000000) + 116444736000000000;
ull = UInt32x32To64(t, RATE_DIFF) + EPOCH_DELTA_US;

pft->dwLowDateTime = (DWORD)ull;
pft->dwHighDateTime = (DWORD)(ull >> 32);
}

/* Convert a Windows file time into a UNIX time_t */
void
file_time_to_unix_time(const LPFILETIME pft, time_t * winTime)
{
*winTime = ((long long)pft->dwHighDateTime << 32) + pft->dwLowDateTime;
*winTime -= EPOCH_DELTA_US;
*winTime /= RATE_DIFF; /* Nano to seconds resolution */
}

static BOOL
is_root_or_empty(wchar_t * path)
{
wchar_t * path_start;
BOOL has_drive_letter_and_colon;
int len;
if (!path)
return FALSE;
len = wcslen(path);
if((len > 1) && __ascii_iswalpha(path[0]) && path[1] == L':')
path_start = path + 2;
else
path_start = path;
/*path like c:\, /, \ are root directory*/
if ((*path_start == L'\0') || ((*path_start == L'\\' || *path_start == L'/' ) && path_start[1] == L'\0'))
return TRUE;
return FALSE;
}

static BOOL
has_executable_extension(wchar_t * path)
{
wchar_t * last_dot;
if (!path)
return FALSE;

last_dot = wcsrchr(path, L'.');
if (!last_dot)
return FALSE;
if (_wcsnicmp(last_dot, L".exe", 4) != 0 && _wcsnicmp(last_dot, L".cmd", 4) != 0 &&
_wcsnicmp(last_dot, L".bat", 4) != 0 && _wcsnicmp(last_dot, L".com", 4) != 0)
return FALSE;
return TRUE;
}

int
file_attr_to_st_mode(wchar_t * path, DWORD attributes)
{
int mode = S_IREAD;
if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 || is_root_or_empty(path))
mode |= S_IFDIR | _S_IEXEC;
else {
mode |= S_IFREG;
/* See if file appears to be an executable by checking its extension */
if (has_executable_extension(path))
mode |= _S_IEXEC;

}
if (!(attributes & FILE_ATTRIBUTE_READONLY))
mode |= S_IWRITE;

// propagate owner read/write/execute bits to group/other fields.
mode |= (mode & 0700) >> 3;
mode |= (mode & 0700) >> 6;
return mode;
}

static int
settimes(wchar_t * path, FILETIME *cretime, FILETIME *acttime, FILETIME *modtime)
{
Expand Down
3 changes: 3 additions & 0 deletions contrib/win32/win32compat/misc_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ char* w32_programdir();

void convertToBackslash(char *str);
void convertToForwardslash(char *str);

void unix_time_to_file_time(ULONG, LPFILETIME);
void file_time_unix_time(const LPFILETIME, time_t *);
9 changes: 9 additions & 0 deletions regress/pesterTests/Hostkey_fileperm.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ Describe "Tests for host keys file permission" -Tags "Scenario" {
Remove-Item -Path $filePath -Force -ErrorAction ignore
}

AfterAll {
if(Test-path $hostKeyFilePath -PathType Leaf){
Set-SecureFileACL -filepath $hostKeyFilePath
}
if(Test-path "$hostKeyFilePath.pub" -PathType Leaf){
Set-SecureFileACL -filepath "$hostKeyFilePath.pub"
}
}

It 'Host keys -- positive (Secured private key and sshd can access to public key file)' {
#setup to have current user as owner and grant it full control
Set-SecureFileACL -filepath $hostKeyFilePath
Expand Down
44 changes: 43 additions & 1 deletion regress/unittests/win32compat/file_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,49 @@ void file_simple_fileio()
ASSERT_INT_EQ(ret, 0);
close(f);
TEST_DONE();
}

void file_simple_fileio_mode()
{
char * small_write_buf = "sample payload", *c, small_read_buf[SMALL_RECV_BUF_SIZE];
int ret;
FILE* f;
struct stat st;

TEST_START("file mode");
f = fopen("tmp.txt", "w");
ASSERT_PTR_NE(f, NULL);
fclose(f);
f = fopen("tmp.txt", "r");
ASSERT_PTR_NE(f, NULL);
c = fgets(small_read_buf, sizeof(small_read_buf), f);
ASSERT_PTR_EQ(c, NULL);
fclose(f);

ret = stat("tmp.txt", &st);
ASSERT_INT_EQ(ret, 0);
ASSERT_INT_EQ(st.st_size, 0);

f = fopen("tmp.txt", "w");
ASSERT_PTR_NE(f, NULL);
ret = fputs(small_write_buf, f);
ASSERT_INT_EQ(ret, 0);
fclose(f);

ret = stat("tmp.txt", &st);
ASSERT_INT_EQ(ret, 0);
ASSERT_INT_EQ(st.st_size, strlen(small_write_buf));

f = fopen("tmp.txt", "r");
ASSERT_PTR_NE(f, NULL);
c = fgets(small_read_buf, sizeof(small_read_buf), f);
ASSERT_PTR_NE(c, NULL);
ASSERT_STRING_EQ(small_write_buf, small_read_buf);

c = fgets(small_read_buf, sizeof(small_read_buf), f);
ASSERT_PTR_EQ(c, NULL);
fclose(f);
TEST_DONE();
}

void
Expand Down Expand Up @@ -240,7 +281,8 @@ void
file_tests()
{
//console_io_test();
//file_simple_fileio();
file_simple_fileio();
file_simple_fileio_mode();
file_blocking_io_tests();
file_nonblocking_io_tests();
file_select_tests();
Expand Down

0 comments on commit afc6ca9

Please sign in to comment.