Merge pull request #303 from NoMoreFood/path_fixes
Reworked resolved_path() into resolved_path_utf16() that combined utf16 conversion and path conditioning into a single function. This eliminated the previously non-threadsafe resolved_path() function that used a static buffer. Changed some functions to use unicode to eliminate use of previous resolve_path function. Adjusted functions to use resolved_path_utf16(). Collapsed copy_file() function that was only used once. Corrected compilation errors when debug4() and debug5() are enabled. Removed debug statements that were interfering with APC wakeup due to the way that logging works in atomicio6(). Filled in a missing parameter in a debug statement. Changed test helper so test name is displayed when running release build. Corrected permissions check for whether to run symbolic links in test cases. Removed TEST_RESOURCES() in unit tests calls due to inconsistent ability to sample handles in Windows 8.1 / Server 2012 R2.
This commit is contained in:
commit
77999d2f4d
|
@ -439,10 +439,10 @@ fileio_open(const char *path_utf8, int flags, mode_t mode)
|
|||
}
|
||||
|
||||
/* if opening null device, point to Windows equivalent */
|
||||
if (strncmp(path_utf8, NULL_DEVICE, strlen(NULL_DEVICE)+1) == 0)
|
||||
path_utf8 = "NUL";
|
||||
if (strncmp(path_utf8, NULL_DEVICE, sizeof(NULL_DEVICE)) == 0)
|
||||
path_utf8 = NULL_DEVICE_WIN;
|
||||
|
||||
if ((path_utf16 = utf8_to_utf16(path_utf8)) == NULL) {
|
||||
if ((path_utf16 = resolved_path_utf16(path_utf8)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
debug3("utf8_to_utf16 failed for file:%s error:%d", path_utf8, GetLastError());
|
||||
return NULL;
|
||||
|
@ -774,7 +774,7 @@ fileio_stat_or_lstat_internal(const char *path, struct _stat64 *buf, int do_lsta
|
|||
return 0;
|
||||
}
|
||||
|
||||
if ((wpath = utf8_to_utf16(path)) == NULL) {
|
||||
if ((wpath = resolved_path_utf16(path)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
debug3("utf8_to_utf16 failed for file:%s error:%d", path, GetLastError());
|
||||
return -1;
|
||||
|
@ -1013,8 +1013,6 @@ fileio_readlink(const char *path, char *buf, size_t bufsiz)
|
|||
* for more info: https://msdn.microsoft.com/en-us/library/cc232006.aspx
|
||||
*/
|
||||
|
||||
debug4("readlink - io:%p", pio);
|
||||
|
||||
typedef struct _REPARSE_DATA_BUFFER_SYMLINK {
|
||||
ULONG ReparseTag;
|
||||
USHORT ReparseDataLength;
|
||||
|
@ -1041,7 +1039,7 @@ fileio_readlink(const char *path, char *buf, size_t bufsiz)
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((wpath = utf8_to_utf16(path)) == NULL) {
|
||||
if ((wpath = resolved_path_utf16(path)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -1131,8 +1129,8 @@ fileio_symlink(const char *target, const char *linkpath)
|
|||
}
|
||||
|
||||
DWORD ret = 0;
|
||||
wchar_t *target_utf16 = utf8_to_utf16(resolved_path(target));
|
||||
wchar_t *linkpath_utf16 = utf8_to_utf16(resolved_path(linkpath));
|
||||
wchar_t *target_utf16 = resolved_path_utf16(target);
|
||||
wchar_t *linkpath_utf16 = resolved_path_utf16(linkpath);
|
||||
wchar_t *resolved_utf16 = _wcsdup(target_utf16);
|
||||
if (target_utf16 == NULL || linkpath_utf16 == NULL || resolved_utf16 == NULL) {
|
||||
errno = ENOMEM;
|
||||
|
@ -1214,8 +1212,10 @@ fileio_link(const char *oldpath, const char *newpath)
|
|||
}
|
||||
|
||||
DWORD ret = 0;
|
||||
wchar_t *oldpath_utf16 = utf8_to_utf16(resolved_path(oldpath));
|
||||
wchar_t *newpath_utf16 = utf8_to_utf16(resolved_path(newpath));
|
||||
|
||||
wchar_t *oldpath_utf16 = resolved_path_utf16(oldpath);
|
||||
wchar_t *newpath_utf16 = resolved_path_utf16(newpath);
|
||||
|
||||
if (oldpath_utf16 == NULL || newpath_utf16 == NULL) {
|
||||
errno = ENOMEM;
|
||||
ret = -1;
|
||||
|
|
|
@ -55,6 +55,8 @@
|
|||
#include "inc\grp.h"
|
||||
#include "inc\time.h"
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
static char* s_programdir = NULL;
|
||||
|
||||
/* Maximum reparse buffer info size. The max user defined reparse
|
||||
|
@ -230,15 +232,14 @@ dlsym(HMODULE handle, const char *symbol)
|
|||
FILE *
|
||||
w32_fopen_utf8(const char *input_path, const char *mode)
|
||||
{
|
||||
wchar_t wpath[PATH_MAX], wmode[5];
|
||||
FILE* f;
|
||||
wchar_t *wmode = NULL, *wpath = NULL;
|
||||
FILE* f = NULL;
|
||||
char utf8_bom[] = { 0xEF,0xBB,0xBF };
|
||||
char first3_bytes[3];
|
||||
int status = 1;
|
||||
errno_t r = 0;
|
||||
char *path = NULL;
|
||||
errno_t r = 0;
|
||||
|
||||
if (mode[1] != '\0') {
|
||||
if (mode == NULL || mode[1] != '\0') {
|
||||
errno = ENOTSUP;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -249,28 +250,21 @@ w32_fopen_utf8(const char *input_path, const char *mode)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
path = resolved_path(input_path);
|
||||
|
||||
/* if opening null device, point to Windows equivalent */
|
||||
if (0 == strncmp(path, NULL_DEVICE, strlen(NULL_DEVICE)+1)) {
|
||||
if ((r = wcsncpy_s(wpath, PATH_MAX, L"NUL", 3)) != 0) {
|
||||
debug3("wcsncpy_s failed with error: %d.", r);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
status = MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, PATH_MAX);
|
||||
if (strncmp(input_path, NULL_DEVICE, sizeof(NULL_DEVICE)) == 0)
|
||||
input_path = NULL_DEVICE_WIN;
|
||||
|
||||
if ((0 == status) ||
|
||||
(0 == MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, 5))) {
|
||||
errno = EFAULT;
|
||||
debug3("WideCharToMultiByte failed for %c - ERROR:%d", path, GetLastError());
|
||||
return NULL;
|
||||
wpath = resolved_path_utf16(input_path);
|
||||
wmode = utf8_to_utf16(mode);
|
||||
if (wpath == NULL || wmode == NULL)
|
||||
{
|
||||
errno = ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((_wfopen_s(&f, wpath, wmode) != 0) || (f == NULL)) {
|
||||
debug3("Failed to open file:%s error:%d", path, errno);
|
||||
return NULL;
|
||||
debug3("Failed to open file:%s error:%d", input_path, errno);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* BOM adjustments for file streams*/
|
||||
|
@ -278,7 +272,7 @@ w32_fopen_utf8(const char *input_path, const char *mode)
|
|||
/* write UTF-8 BOM - should we ?*/
|
||||
/*if (fwrite(utf8_bom, sizeof(utf8_bom), 1, f) != 1) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
goto cleanup;
|
||||
}*/
|
||||
|
||||
} else if (mode[0] == 'r' && fseek(f, 0, SEEK_SET) != EBADF) {
|
||||
|
@ -289,6 +283,13 @@ w32_fopen_utf8(const char *input_path, const char *mode)
|
|||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
if (wpath)
|
||||
free(wpath);
|
||||
if (wmode)
|
||||
free(wmode);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
@ -512,7 +513,7 @@ int
|
|||
w32_chmod(const char *pathname, mode_t mode)
|
||||
{
|
||||
int ret;
|
||||
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolved_path(pathname));
|
||||
wchar_t *resolvedPathName_utf16 = resolved_path_utf16(pathname);
|
||||
if (resolvedPathName_utf16 == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
|
@ -640,7 +641,7 @@ w32_utimes(const char *filename, struct timeval *tvp)
|
|||
{
|
||||
int ret;
|
||||
FILETIME acttime, modtime;
|
||||
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolved_path(filename));
|
||||
wchar_t *resolvedPathName_utf16 = resolved_path_utf16(filename);
|
||||
if (resolvedPathName_utf16 == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
|
@ -670,19 +671,13 @@ w32_link(const char *oldpath, const char *newpath)
|
|||
int
|
||||
w32_rename(const char *old_name, const char *new_name)
|
||||
{
|
||||
char old_name_resolved[PATH_MAX] = {0, };
|
||||
char new_name_resolved[PATH_MAX] = {0, };
|
||||
|
||||
if (old_name == NULL || new_name == NULL) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy_s(old_name_resolved, _countof(old_name_resolved), resolved_path(old_name));
|
||||
strcpy_s(new_name_resolved, _countof(new_name_resolved), resolved_path(new_name));
|
||||
|
||||
wchar_t *resolvedOldPathName_utf16 = utf8_to_utf16(old_name_resolved);
|
||||
wchar_t *resolvedNewPathName_utf16 = utf8_to_utf16(new_name_resolved);
|
||||
wchar_t *resolvedOldPathName_utf16 = resolved_path_utf16(old_name);
|
||||
wchar_t *resolvedNewPathName_utf16 = resolved_path_utf16(new_name);
|
||||
|
||||
if (NULL == resolvedOldPathName_utf16 || NULL == resolvedNewPathName_utf16) {
|
||||
errno = ENOMEM;
|
||||
|
@ -694,18 +689,18 @@ w32_rename(const char *old_name, const char *new_name)
|
|||
* 1) if the new_name is file, then delete it so that _wrename will succeed.
|
||||
* 2) if the new_name is directory and it is empty then delete it so that _wrename will succeed.
|
||||
*/
|
||||
struct _stat64 st;
|
||||
if (fileio_stat(resolved_path(new_name_resolved), &st) != -1) {
|
||||
struct w32_stat st;
|
||||
if (w32_stat(new_name, &st) != -1) {
|
||||
if (((st.st_mode & _S_IFMT) == _S_IFREG))
|
||||
w32_unlink(new_name_resolved);
|
||||
w32_unlink(new_name);
|
||||
else {
|
||||
DIR *dirp = opendir(new_name_resolved);
|
||||
DIR *dirp = opendir(new_name);
|
||||
if (NULL != dirp) {
|
||||
struct dirent *dp = readdir(dirp);
|
||||
closedir(dirp);
|
||||
|
||||
if (dp == NULL)
|
||||
w32_rmdir(new_name_resolved);
|
||||
w32_rmdir(new_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -720,7 +715,7 @@ w32_rename(const char *old_name, const char *new_name)
|
|||
int
|
||||
w32_unlink(const char *path)
|
||||
{
|
||||
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolved_path(path));
|
||||
wchar_t *resolvedPathName_utf16 = resolved_path_utf16(path);
|
||||
if (NULL == resolvedPathName_utf16) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
|
@ -735,7 +730,7 @@ w32_unlink(const char *path)
|
|||
int
|
||||
w32_rmdir(const char *path)
|
||||
{
|
||||
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolved_path(path));
|
||||
wchar_t *resolvedPathName_utf16 = resolved_path_utf16(path);
|
||||
if (NULL == resolvedPathName_utf16) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
|
@ -795,7 +790,7 @@ int
|
|||
w32_mkdir(const char *path_utf8, unsigned short mode)
|
||||
{
|
||||
int curmask;
|
||||
wchar_t *path_utf16 = utf8_to_utf16(resolved_path(path_utf8));
|
||||
wchar_t *path_utf16 = resolved_path_utf16(path_utf8);
|
||||
if (path_utf16 == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
|
@ -819,20 +814,20 @@ w32_mkdir(const char *path_utf8, unsigned short mode)
|
|||
int
|
||||
w32_stat(const char *input_path, struct w32_stat *buf)
|
||||
{
|
||||
return fileio_stat(resolved_path(input_path), (struct _stat64*)buf);
|
||||
return fileio_stat(input_path, (struct _stat64*)buf);
|
||||
}
|
||||
|
||||
int
|
||||
w32_lstat(const char *input_path, struct w32_stat *buf)
|
||||
{
|
||||
return fileio_lstat(resolved_path(input_path), (struct _stat64*)buf);
|
||||
return fileio_lstat(input_path, (struct _stat64*)buf);
|
||||
}
|
||||
|
||||
/* if file is symbolic link, copy its link into "link" */
|
||||
int
|
||||
w32_readlink(const char *path, char *link, int linklen)
|
||||
{
|
||||
return fileio_readlink(resolved_path(path), link, linklen);
|
||||
return fileio_readlink(path, link, linklen);
|
||||
}
|
||||
|
||||
/* convert forward slash to back slash */
|
||||
|
@ -914,44 +909,56 @@ realpath(const char *path, char resolved[PATH_MAX])
|
|||
return resolved;
|
||||
}
|
||||
|
||||
/* This function is not thread safe.
|
||||
* TODO - It uses static memory. Is this a good design?
|
||||
*/
|
||||
char*
|
||||
resolved_path(const char *input_path)
|
||||
wchar_t*
|
||||
resolved_path_utf16(const char *input_path)
|
||||
{
|
||||
static char resolved_path[PATH_MAX] = {0,};
|
||||
static char newPath[PATH_MAX] = { '\0', };
|
||||
errno_t r = 0;
|
||||
|
||||
if (!input_path) return NULL;
|
||||
|
||||
/* If filename contains __PROGRAMDATA__ then expand it to %programData% and return the resolved path */
|
||||
if ((strlen(input_path) >= strlen(PROGRAM_DATA)) && (memcmp(input_path, PROGRAM_DATA, strlen(PROGRAM_DATA)) == 0)) {
|
||||
resolved_path[0] = '\0';
|
||||
strcat_s(resolved_path, _countof(resolved_path), get_program_data_path());
|
||||
strcat_s(resolved_path, _countof(resolved_path), &input_path[strlen(PROGRAM_DATA)]);
|
||||
wchar_t * resolved_path = utf8_to_utf16(input_path);
|
||||
if (resolved_path == NULL)
|
||||
return NULL;
|
||||
|
||||
return resolved_path; /* return here as its doesn't start with "/" */
|
||||
int resolved_len = (int) wcslen(resolved_path);
|
||||
const int variable_len = (int) wcslen(PROGRAM_DATAW);
|
||||
|
||||
/* search for program data flag and switch it with the real path */
|
||||
if (_wcsnicmp(resolved_path, PROGRAM_DATAW, variable_len) == 0) {
|
||||
wchar_t * program_data = get_program_data_path();
|
||||
const int programdata_len = (int) wcslen(program_data);
|
||||
const int changed_req = programdata_len - variable_len;
|
||||
|
||||
/* allocate more memory if required */
|
||||
if (changed_req > 0) {
|
||||
wchar_t * resolved_path_new = realloc(resolved_path,
|
||||
(resolved_len + changed_req + 1) * sizeof(wchar_t));
|
||||
if (resolved_path == NULL) {
|
||||
debug3("%s: memory allocation failed.", __FUNCTION__);
|
||||
free(resolved_path);
|
||||
return NULL;
|
||||
}
|
||||
else resolved_path = resolved_path_new;
|
||||
}
|
||||
|
||||
/* shift memory contents over based on side of the new string */
|
||||
wmemmove_s(&resolved_path[variable_len + changed_req], resolved_len - variable_len + 1,
|
||||
&resolved_path[variable_len], resolved_len - variable_len + 1);
|
||||
resolved_len += changed_req;
|
||||
wmemcpy_s(resolved_path, resolved_len + 1, program_data, programdata_len);
|
||||
}
|
||||
|
||||
strcpy_s(resolved_path, _countof(resolved_path), input_path);
|
||||
if (resolved_path[0] == '/' && resolved_path[1]) {
|
||||
if (resolved_path[2] == ':') {
|
||||
if (resolved_path[3] == '\0') {
|
||||
/* make "/x:" as "x:\\" */
|
||||
resolved_path[0] = resolved_path[1];
|
||||
resolved_path[1] = resolved_path[2];
|
||||
resolved_path[2] = '\\';
|
||||
resolved_path[3] = '\0';
|
||||
if (resolved_path[0] == L'/' && iswalpha(resolved_path[1]) && resolved_path[2] == L':') {
|
||||
|
||||
return resolved_path;
|
||||
} else
|
||||
return (char *)(resolved_path + 1); /* skip the first "/" */
|
||||
/* shift memory to remove forward slash including null terminator */
|
||||
wmemmove_s(resolved_path, resolved_len + 1, resolved_path + 1, (resolved_len + 1 - 1));
|
||||
|
||||
/* if just a drive letter path, make x: into x:\ */
|
||||
if (resolved_path[2] == L'\0') {
|
||||
resolved_path[2] = L'\\';
|
||||
resolved_path[3] = L'\0';
|
||||
}
|
||||
}
|
||||
|
||||
return (char *)resolved_path;
|
||||
return resolved_path;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -962,7 +969,7 @@ statvfs(const char *path, struct statvfs *buf)
|
|||
DWORD freeClusters;
|
||||
DWORD totalClusters;
|
||||
|
||||
wchar_t* path_utf16 = utf8_to_utf16(resolved_path(path));
|
||||
wchar_t* path_utf16 = resolved_path_utf16(path);
|
||||
if (path_utf16 && (GetDiskFreeSpaceW(path_utf16, §orsPerCluster, &bytesPerSector,
|
||||
&freeClusters, &totalClusters) == TRUE)) {
|
||||
debug5("path : [%s]", path);
|
||||
|
@ -1432,23 +1439,19 @@ cleanup:
|
|||
return ret;
|
||||
}
|
||||
|
||||
char*
|
||||
wchar_t*
|
||||
get_program_data_path()
|
||||
{
|
||||
if (ssh_cfg_dir_path) return ssh_cfg_dir_path;
|
||||
static wchar_t ssh_cfg_dir_path_w[PATH_MAX] = L"";
|
||||
if (wcslen(ssh_cfg_dir_path_w) > 0) return ssh_cfg_dir_path_w;
|
||||
|
||||
wchar_t ssh_cfg_dir_path_w[PATH_MAX] = {0, };
|
||||
int return_val = ExpandEnvironmentStringsW(L"%programData%", ssh_cfg_dir_path_w, PATH_MAX);
|
||||
int return_val = ExpandEnvironmentStringsW(L"%ProgramData%", ssh_cfg_dir_path_w, PATH_MAX);
|
||||
if (return_val > PATH_MAX)
|
||||
fatal("%s, buffer too small to expand:%s", __func__, "%programData%");
|
||||
fatal("%s, buffer too small to expand:%s", __func__, "%ProgramData%");
|
||||
else if (!return_val)
|
||||
fatal("%s, failed to expand:%s error:%s", __func__, "%programData%", GetLastError());
|
||||
|
||||
ssh_cfg_dir_path = utf16_to_utf8(ssh_cfg_dir_path_w);
|
||||
if(!ssh_cfg_dir_path)
|
||||
fatal("%s utf16_to_utf8 failed", __func__);
|
||||
fatal("%s, failed to expand:%s error:%s", __func__, "%ProgramData%", GetLastError());
|
||||
|
||||
return ssh_cfg_dir_path;
|
||||
return ssh_cfg_dir_path_w;
|
||||
}
|
||||
|
||||
/* Windows absolute paths - \abc, /abc, c:\abc, c:/abc, __PROGRAMDATA__\openssh\sshd_config */
|
||||
|
@ -1468,28 +1471,15 @@ is_absolute_path(const char *path)
|
|||
|
||||
/* return -1 - in case of failure, 0 - success */
|
||||
int
|
||||
create_directory_withsddl(char *path, char *sddl)
|
||||
create_directory_withsddl(wchar_t *path_w, wchar_t *sddl_w)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(path, &st) < 0) {
|
||||
if (GetFileAttributesW(path_w) == INVALID_FILE_ATTRIBUTES) {
|
||||
PSECURITY_DESCRIPTOR pSD = NULL;
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.bInheritHandle = FALSE;
|
||||
|
||||
wchar_t *path_w = utf8_to_utf16(path);
|
||||
if (!path_w) {
|
||||
error("%s utf8_to_utf16() has failed to convert string:%s", __func__, path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wchar_t *sddl_w = utf8_to_utf16(sddl);
|
||||
if (!sddl_w) {
|
||||
error("%s utf8_to_utf16() has failed to convert string:%s", __func__, sddl);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ConvertStringSecurityDescriptorToSecurityDescriptorW(sddl_w, SDDL_REVISION, &pSD, NULL) == FALSE) {
|
||||
error("ConvertStringSecurityDescriptorToSecurityDescriptorW failed with error code %d", GetLastError());
|
||||
return -1;
|
||||
|
@ -1545,4 +1535,4 @@ localtime_r(const time_t *timep, struct tm *result)
|
|||
struct tm *t = localtime(timep);
|
||||
memcpy(result, t, sizeof(struct tm));
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,21 +9,23 @@
|
|||
goto cleanup; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define NULL_DEVICE "/dev/null"
|
||||
#define NULL_DEVICE_WIN "NUL"
|
||||
|
||||
#define IsWin7OrLess() (!IsWindows8OrGreater())
|
||||
|
||||
#define IS_INVALID_HANDLE(h) ( ((NULL == h) || (INVALID_HANDLE_VALUE == h)) ? 1 : 0 )
|
||||
#define IS_VALID_HANDLE(h) (!IS_INVALID_HANDLE(h))
|
||||
#define PROGRAM_DATA "__PROGRAMDATA__"
|
||||
#define PROGRAM_DATAW L"__PROGRAMDATA__"
|
||||
|
||||
#define errno_from_Win32LastError() errno_from_Win32Error(GetLastError())
|
||||
|
||||
static char *machine_domain_name;
|
||||
static char *ssh_cfg_dir_path = NULL;
|
||||
|
||||
/* removes first '/' for Windows paths that are unix styled. Ex: /c:/ab.cd */
|
||||
char * resolved_path(const char *);
|
||||
wchar_t * resolved_path_utf16(const char *);
|
||||
void w32posix_initialize();
|
||||
void w32posix_done();
|
||||
char* w32_programdir();
|
||||
|
@ -37,9 +39,8 @@ int file_attr_to_st_mode(wchar_t * path, DWORD attributes);
|
|||
void invalid_parameter_handler(const wchar_t *, const wchar_t *, const wchar_t *, unsigned int, uintptr_t);
|
||||
void to_lower_case(char *s);
|
||||
int get_machine_domain_name(wchar_t *domain, int size);
|
||||
char* get_program_data_path();
|
||||
wchar_t* get_program_data_path();
|
||||
HANDLE get_user_token(char* user);
|
||||
int load_user_profile(HANDLE user_token, char* user);
|
||||
int copy_file(char *source, char *destination);
|
||||
int create_directory_withsddl(char *path, char *sddl);
|
||||
int create_directory_withsddl(wchar_t *path, wchar_t *sddl);
|
||||
int is_absolute_path(const char *);
|
|
@ -159,7 +159,7 @@ w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
|
|||
{
|
||||
/* this is only used by sshd to block SIGCHLD while doing waitpid() */
|
||||
/* our implementation of waidpid() is never interrupted, so no need to implement this for now*/
|
||||
debug5("sigprocmask() how:%d");
|
||||
debug5("sigprocmask() how:%d", how);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -286,7 +286,6 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
|
|||
return -1;
|
||||
}
|
||||
|
||||
debug5("wait() on %d events and %d children", num_events, live_children);
|
||||
DWORD ret = wait_for_multiple_objects_enhanced(num_all_events, all_events, milli_seconds, TRUE);
|
||||
if ((ret >= WAIT_OBJECT_0_ENHANCED) && (ret <= WAIT_OBJECT_0_ENHANCED + num_all_events - 1)) {
|
||||
/* woken up by event signaled
|
||||
|
|
|
@ -579,7 +579,6 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags)
|
|||
|
||||
if (ret == 0) {
|
||||
/* send has completed and APC is scheduled, let it run */
|
||||
debug4("send - WSASend() returned 0, APC scheduled io:%p", pio);
|
||||
pio->write_details.pending = TRUE;
|
||||
pio->write_details.remaining = wsabuf.len;
|
||||
SleepEx(0, TRUE);
|
||||
|
|
|
@ -57,7 +57,7 @@ static VOID CALLBACK
|
|||
ReadAPCProc(_In_ ULONG_PTR dwParam)
|
||||
{
|
||||
struct w32_io* pio = (struct w32_io*)dwParam;
|
||||
debug5("TermRead CB - io:%p, bytes: %d, pending: %d, error: %d", pio, read_status.transferred,
|
||||
debug5("TermRead CB - io:%p, bytes: %d, pending: %d, error: %d", pio, pio->read_details.completed,
|
||||
pio->read_details.pending, pio->sync_read_status.error);
|
||||
pio->read_details.error = pio->sync_read_status.error;
|
||||
pio->read_details.remaining = pio->sync_read_status.transferred;
|
||||
|
@ -171,7 +171,7 @@ static VOID CALLBACK
|
|||
WriteAPCProc(_In_ ULONG_PTR dwParam)
|
||||
{
|
||||
struct w32_io* pio = (struct w32_io*)dwParam;
|
||||
debug5("TermWrite CB - io:%p, bytes: %d, pending: %d, error: %d", pio, write_status.transferred,
|
||||
debug5("TermWrite CB - io:%p, bytes: %d, pending: %d, error: %d", pio, pio->write_details.completed,
|
||||
pio->write_details.pending, pio->sync_write_status.error);
|
||||
pio->write_details.error = pio->sync_write_status.error;
|
||||
pio->write_details.remaining -= pio->sync_write_status.transferred;
|
||||
|
|
|
@ -57,7 +57,6 @@ check_secure_file_permission(const char *input_path, struct passwd * pw)
|
|||
struct passwd * pwd = pw;
|
||||
char *bad_user = NULL;
|
||||
int ret = 0;
|
||||
char *path = NULL;
|
||||
|
||||
if (pwd == NULL)
|
||||
if ((pwd = getpwuid(0)) == NULL)
|
||||
|
@ -70,8 +69,7 @@ check_secure_file_permission(const char *input_path, struct passwd * pw)
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
path = resolved_path(input_path);
|
||||
if ((path_utf16 = utf8_to_utf16(path)) == NULL) {
|
||||
if ((path_utf16 = resolved_path_utf16(input_path)) == NULL) {
|
||||
ret = -1;
|
||||
errno = ENOMEM;
|
||||
goto cleanup;
|
||||
|
@ -81,7 +79,7 @@ check_secure_file_permission(const char *input_path, struct passwd * pw)
|
|||
if ((error_code = GetNamedSecurityInfoW(path_utf16, SE_FILE_OBJECT,
|
||||
OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
|
||||
&owner_sid, NULL, &dacl, NULL, &pSD)) != ERROR_SUCCESS) {
|
||||
debug3("failed to retrieve the owner sid and dacl of file %s with error code: %d", path, error_code);
|
||||
debug3("failed to retrieve the owner sid and dacl of file %S with error code: %d", path_utf16, error_code);
|
||||
errno = EOTHER;
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
|
@ -94,7 +92,7 @@ check_secure_file_permission(const char *input_path, struct passwd * pw)
|
|||
if (!IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) &&
|
||||
!IsWellKnownSid(owner_sid, WinLocalSystemSid) &&
|
||||
!EqualSid(owner_sid, user_sid)) {
|
||||
debug3("Bad owner on %s", path);
|
||||
debug3("Bad owner on %S", path_utf16);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -136,7 +134,7 @@ check_secure_file_permission(const char *input_path, struct passwd * pw)
|
|||
debug3("ConvertSidToSidString failed with %d. ", GetLastError());
|
||||
break;
|
||||
}
|
||||
debug3("Bad permissions. Try removing permissions for user: %s on file %s.", bad_user, path);
|
||||
debug3("Bad permissions. Try removing permissions for user: %s on file %S.", bad_user, path_utf16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -474,7 +474,7 @@ w32_open(const char *pathname, int flags, ... /* arg */)
|
|||
va_end(valist);
|
||||
}
|
||||
|
||||
pio = fileio_open(resolved_path(pathname), flags, mode);
|
||||
pio = fileio_open(pathname, flags, mode);
|
||||
|
||||
if (pio == NULL)
|
||||
return -1;
|
||||
|
|
|
@ -110,13 +110,11 @@ openlog_file()
|
|||
while (tail > module_path && *tail != L'\\' && *tail != L'/')
|
||||
tail--;
|
||||
|
||||
char ssh_cfg_path[PATH_MAX] = {0 ,};
|
||||
strcat_s(ssh_cfg_path, _countof(ssh_cfg_path), get_program_data_path()); /* "%programData%" */
|
||||
strcat_s(ssh_cfg_path, _countof(ssh_cfg_path), "\\ssh"); /* "%programData%\\ssh" */
|
||||
wchar_t ssh_cfg_path[PATH_MAX] = {0 ,};
|
||||
wcscat_s(ssh_cfg_path, _countof(ssh_cfg_path), get_program_data_path()); /* "%programData%" */
|
||||
wcscat_s(ssh_cfg_path, _countof(ssh_cfg_path), L"\\ssh"); /* "%programData%\\ssh" */
|
||||
|
||||
wchar_t* ssh_root_path_w = utf8_to_utf16(ssh_cfg_path); /* "%programData%\\ssh" */
|
||||
|
||||
if ((wcsncat_s(log_file, PATH_MAX + 12, ssh_root_path_w, wcslen(ssh_root_path_w)) != 0) ||
|
||||
if ((wcsncat_s(log_file, PATH_MAX + 12, ssh_cfg_path, wcslen(ssh_cfg_path)) != 0) ||
|
||||
(wcsncat_s(log_file, PATH_MAX + 12, logs_dir, 6) != 0) ||
|
||||
(wcsncat_s(log_file, PATH_MAX + 12, tail + 1, wcslen(tail + 1) - 3) != 0 ) ||
|
||||
(wcsncat_s(log_file, PATH_MAX + 12, L"log", 3) != 0))
|
||||
|
|
|
@ -108,7 +108,7 @@ opendir(const char *name)
|
|||
if (name && strcmp(name, "/") == 0)
|
||||
return openrootdir(name);
|
||||
|
||||
if ((wname = utf8_to_utf16(resolved_path(name))) == NULL) {
|
||||
if ((wname = resolved_path_utf16(name)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -162,34 +162,32 @@ static void
|
|||
create_prgdata_ssh_folder()
|
||||
{
|
||||
/* create ssh cfg folder */
|
||||
char ssh_cfg_dir[PATH_MAX] = { 0, };
|
||||
strcpy_s(ssh_cfg_dir, _countof(ssh_cfg_dir), get_program_data_path());
|
||||
strcat_s(ssh_cfg_dir, _countof(ssh_cfg_dir), "\\ssh");
|
||||
if (create_directory_withsddl(ssh_cfg_dir, "O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;AU)") < 0) {
|
||||
wchar_t ssh_cfg_dir[PATH_MAX] = { 0, };
|
||||
wcscpy_s(ssh_cfg_dir, _countof(ssh_cfg_dir), get_program_data_path());
|
||||
wcscat_s(ssh_cfg_dir, _countof(ssh_cfg_dir), L"\\ssh");
|
||||
if (create_directory_withsddl(ssh_cfg_dir, L"O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;AU)") < 0) {
|
||||
printf("failed to create %s", ssh_cfg_dir);
|
||||
exit(255);
|
||||
}
|
||||
|
||||
/* create logs folder */
|
||||
char logs_dir[PATH_MAX] = { 0, };
|
||||
strcat_s(logs_dir, _countof(logs_dir), ssh_cfg_dir);
|
||||
strcat_s(logs_dir, _countof(logs_dir), "\\logs");
|
||||
if (create_directory_withsddl(logs_dir, "O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)") < 0) {
|
||||
wchar_t logs_dir[PATH_MAX] = { 0, };
|
||||
wcscat_s(logs_dir, _countof(logs_dir), ssh_cfg_dir);
|
||||
wcscat_s(logs_dir, _countof(logs_dir), L"\\logs");
|
||||
if (create_directory_withsddl(logs_dir, L"O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)") < 0) {
|
||||
printf("failed to create %s", logs_dir);
|
||||
exit(255);
|
||||
}
|
||||
|
||||
/* COPY sshd_config_default to %programData%\openssh\sshd_config */
|
||||
char sshd_config_path[PATH_MAX] = { 0, };
|
||||
strcat_s(sshd_config_path, _countof(sshd_config_path), ssh_cfg_dir);
|
||||
strcat_s(sshd_config_path, _countof(sshd_config_path), "\\sshd_config");
|
||||
struct stat st;
|
||||
if (stat(sshd_config_path, &st) < 0) {
|
||||
char sshd_config_default_path[PATH_MAX] = { 0, };
|
||||
strcat_s(sshd_config_default_path, _countof(sshd_config_default_path), w32_programdir());
|
||||
strcat_s(sshd_config_default_path, _countof(sshd_config_default_path), "\\sshd_config_default");
|
||||
/* copy sshd_config_default to %programData%\ssh\sshd_config */
|
||||
wchar_t sshd_config_path[PATH_MAX] = { 0, };
|
||||
wcscat_s(sshd_config_path, _countof(sshd_config_path), ssh_cfg_dir);
|
||||
wcscat_s(sshd_config_path, _countof(sshd_config_path), L"\\sshd_config");
|
||||
if (GetFileAttributesW(sshd_config_path) == INVALID_FILE_ATTRIBUTES) {
|
||||
wchar_t sshd_config_default_path[PATH_MAX] = { 0, };
|
||||
swprintf_s(sshd_config_default_path, PATH_MAX, L"%S\\%s", w32_programdir(), L"sshd_config_default");
|
||||
|
||||
if (copy_file(sshd_config_default_path, sshd_config_path) < 0) {
|
||||
if (CopyFileW(sshd_config_default_path, sshd_config_path, TRUE) == 0) {
|
||||
printf("Failed to copy %s to %s, error:%d", sshd_config_default_path, sshd_config_path, GetLastError());
|
||||
exit(255);
|
||||
}
|
||||
|
@ -261,7 +259,7 @@ int wmain(int argc, wchar_t **wargv) {
|
|||
wchar_t* path_utf16;
|
||||
argc_original = argc;
|
||||
wargv_original = wargv;
|
||||
|
||||
|
||||
/* change current directory to sshd.exe root */
|
||||
if ( (path_utf16 = utf8_to_utf16(w32_programdir())) == NULL)
|
||||
return -1;
|
||||
|
|
|
@ -64,31 +64,38 @@ test_sanitizedpath()
|
|||
{
|
||||
TEST_START("win32 program dir");
|
||||
|
||||
char *win32prgdir = w32_programdir();
|
||||
ASSERT_PTR_NE(win32prgdir, NULL);
|
||||
char *win32prgdir_utf8 = w32_programdir();
|
||||
ASSERT_PTR_NE(win32prgdir_utf8, NULL);
|
||||
|
||||
ASSERT_PTR_EQ(resolved_path(NULL), NULL);
|
||||
ASSERT_PTR_EQ(resolved_path_utf16(NULL), NULL);
|
||||
|
||||
char *ret = resolved_path(win32prgdir);
|
||||
retValue = strcmp(win32prgdir, ret);
|
||||
wchar_t *win32prgdir = utf8_to_utf16(win32prgdir_utf8);
|
||||
wchar_t *ret = resolved_path_utf16(win32prgdir_utf8);
|
||||
retValue = wcscmp(win32prgdir, ret);
|
||||
ASSERT_INT_EQ(retValue, 0);
|
||||
free(ret);
|
||||
|
||||
char win32prgdir_len = strlen(win32prgdir);
|
||||
char win32prgdir_len = strlen(win32prgdir_utf8);
|
||||
char *tmp_path = malloc(win32prgdir_len + 2); /* 1-NULL and 1-adding "/" */
|
||||
tmp_path[0] = '/';
|
||||
strncpy(tmp_path+1, win32prgdir, win32prgdir_len);
|
||||
strcpy(tmp_path+1, win32prgdir_utf8);
|
||||
tmp_path[win32prgdir_len+1] = '\0';
|
||||
|
||||
ret = resolved_path(tmp_path);
|
||||
retValue = strcmp(win32prgdir, ret);
|
||||
ret = resolved_path_utf16(tmp_path);
|
||||
retValue = wcscmp(win32prgdir, ret);
|
||||
ASSERT_INT_EQ(retValue, 0);
|
||||
free(ret);
|
||||
|
||||
char *s1 = malloc(4), *s2 = malloc(4);
|
||||
char s1[4];
|
||||
wchar_t s2[4];
|
||||
s1[0] = '/', s1[1] = win32prgdir[0], s1[2] = ':', s1[3] = '\0';
|
||||
s2[0] = win32prgdir[0], s2[1] = ':', s2[2] = '\\', s2[3] = '\0';
|
||||
ret = resolved_path(s1);
|
||||
retValue = strcmp(ret, s2);
|
||||
s2[0] = win32prgdir[0], s2[1] = ':', s2[2] = '\\', s2[3] = '\0';
|
||||
ret = resolved_path_utf16(s1);
|
||||
retValue = wcscmp(ret, s2);
|
||||
ASSERT_INT_EQ(retValue, 0);
|
||||
free(ret);
|
||||
|
||||
free(win32prgdir);
|
||||
|
||||
TEST_DONE();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue