diff --git a/contrib/win32/win32compat/fileio.c b/contrib/win32/win32compat/fileio.c index bb51a2bfd..5719691e4 100644 --- a/contrib/win32/win32compat/fileio.c +++ b/contrib/win32/win32compat/fileio.c @@ -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; diff --git a/contrib/win32/win32compat/misc.c b/contrib/win32/win32compat/misc.c index fce17b8b7..2c272af13 100644 --- a/contrib/win32/win32compat/misc.c +++ b/contrib/win32/win32compat/misc.c @@ -55,6 +55,8 @@ #include "inc\grp.h" #include "inc\time.h" +#include + 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; -} \ No newline at end of file +} diff --git a/contrib/win32/win32compat/misc_internal.h b/contrib/win32/win32compat/misc_internal.h index d3d1ef881..ef7a563d7 100644 --- a/contrib/win32/win32compat/misc_internal.h +++ b/contrib/win32/win32compat/misc_internal.h @@ -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 *); \ No newline at end of file diff --git a/contrib/win32/win32compat/signal.c b/contrib/win32/win32compat/signal.c index 01b6ee3fa..0776f2350 100644 --- a/contrib/win32/win32compat/signal.c +++ b/contrib/win32/win32compat/signal.c @@ -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 diff --git a/contrib/win32/win32compat/socketio.c b/contrib/win32/win32compat/socketio.c index 2211d6237..893a88413 100644 --- a/contrib/win32/win32compat/socketio.c +++ b/contrib/win32/win32compat/socketio.c @@ -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); diff --git a/contrib/win32/win32compat/termio.c b/contrib/win32/win32compat/termio.c index 35b8a1723..fa662149e 100644 --- a/contrib/win32/win32compat/termio.c +++ b/contrib/win32/win32compat/termio.c @@ -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; diff --git a/contrib/win32/win32compat/w32-sshfileperm.c b/contrib/win32/win32compat/w32-sshfileperm.c index 652063e6f..2dda4adf4 100644 --- a/contrib/win32/win32compat/w32-sshfileperm.c +++ b/contrib/win32/win32compat/w32-sshfileperm.c @@ -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; } } diff --git a/contrib/win32/win32compat/w32fd.c b/contrib/win32/win32compat/w32fd.c index 65757d542..371e58676 100644 --- a/contrib/win32/win32compat/w32fd.c +++ b/contrib/win32/win32compat/w32fd.c @@ -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; diff --git a/contrib/win32/win32compat/w32log.c b/contrib/win32/win32compat/w32log.c index acd0b9898..a45aad5f9 100644 --- a/contrib/win32/win32compat/w32log.c +++ b/contrib/win32/win32compat/w32log.c @@ -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)) diff --git a/contrib/win32/win32compat/win32_dirent.c b/contrib/win32/win32compat/win32_dirent.c index f2a5796bb..e04125311 100644 --- a/contrib/win32/win32compat/win32_dirent.c +++ b/contrib/win32/win32compat/win32_dirent.c @@ -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; } diff --git a/contrib/win32/win32compat/wmain_sshd.c b/contrib/win32/win32compat/wmain_sshd.c index 1072839c8..8a14c705d 100644 --- a/contrib/win32/win32compat/wmain_sshd.c +++ b/contrib/win32/win32compat/wmain_sshd.c @@ -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; diff --git a/regress/unittests/win32compat/miscellaneous_tests.c b/regress/unittests/win32compat/miscellaneous_tests.c index 27b61af95..746c1a5dd 100644 --- a/regress/unittests/win32compat/miscellaneous_tests.c +++ b/regress/unittests/win32compat/miscellaneous_tests.c @@ -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(); }