diff --git a/auth.c b/auth.c index 680dffc..405371c 100644 --- a/auth.c +++ b/auth.c @@ -385,29 +385,20 @@ auth_root_allowed(const char *method) #ifdef WIN32_FIXME -wchar_t *expand_authorized_keys(const wchar_t *filename, struct passwd *pw) +char *expand_authorized_keys(const char *filename, struct passwd *pw) { - wchar_t *file_w, ret[MAXPATHLEN], pw_name_w[MAXPATHLEN], filename_w[MAXPATHLEN]; - + wchar_t *file_w, ret[MAXPATHLEN], pw_name_w[MAXPATHLEN], filename_w[MAXPATHLEN], pw_dir_w[MAXPATHLEN]; + char* expanded_utf8[MAXPATHLEN]; int i; wchar_t *slash; - i = MultiByteToWideChar(CP_UTF8, 0, filename, -1, filename_w, MAXPATHLEN); - - if (i == 0) - { - fatal("expand_authorized_keys: unable to convert path to UTF-16"); - } - - MultiByteToWideChar(CP_UTF8, 0, pw -> pw_name, -1, pw_name_w, MAXPATHLEN); - - if (i == 0) - { - fatal("expand_authorized_keys: unable to convert path to UTF-16"); - } - - file_w = percent_expand_w(filename_w, L"h", pw -> pw_dir, + if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, filename_w, MAXPATHLEN) == 0 || + MultiByteToWideChar(CP_UTF8, 0, pw->pw_name, -1, pw_name_w, MAXPATHLEN) == 0 || + MultiByteToWideChar(CP_UTF8, 0, pw->pw_dir, -1, pw_dir_w, MAXPATHLEN) == 0) + fatal("expand_authorized_keys -MultiByteToWideChar failed" ); + + file_w = percent_expand_w(filename_w, L"h", pw_dir_w, L"u", pw_name_w, (char *) NULL); /* @@ -444,9 +435,12 @@ wchar_t *expand_authorized_keys(const wchar_t *filename, struct passwd *pw) fatal("expand_authorized_keys: path too long"); } + if (WideCharToMultiByte(CP_UTF8, 0, ret, -1, expanded_utf8, MAXPATHLEN, NULL, NULL) == 0) + fatal("expand_authorized_keys: WideCharToMultiByte failed"); + free(file_w); - return (_wcsdup(ret)); + return (xstrdup(expanded_utf8)); } #else /* WIN32_FIXME */ @@ -639,23 +633,15 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes, FILE *f; #ifdef WIN32_FIXME - if ((fd = _wopen(file, O_RDONLY|O_NONBLOCK)) == -1) { + if ((f = fopen(file, "r")) == NULL) + return NULL; #else if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) { -#endif if (log_missing || errno != ENOENT) debug("Could not open %s '%s': %s", file_type, file, strerror(errno)); return NULL; } - -#ifdef WIN32_FIXME - if ((f = _fdopen(fd, "r")) == NULL) { - _close(fd); - return NULL; - } - -#else if (fstat(fd, &st) < 0) { close(fd); return NULL; diff --git a/auth.h b/auth.h index c65b747..edc2d68 100644 --- a/auth.h +++ b/auth.h @@ -196,11 +196,7 @@ char *get_challenge(Authctxt *); int verify_response(Authctxt *, const char *); void abandon_challenge_response(Authctxt *); -#ifndef WIN32_FIXME char *expand_authorized_keys(const char *, struct passwd *pw); -#else -wchar_t *expand_authorized_keys(const wchar_t *filename, struct passwd *pw); -#endif char *authorized_principals_file(struct passwd *); diff --git a/authfile.c b/authfile.c index 601fab4..6955ae0 100644 --- a/authfile.c +++ b/authfile.c @@ -183,7 +183,7 @@ sshkey_perm_ok(int fd, const char *filename) if (check_ntsec(filename)) #endif -#ifndef WIN32_FIXME//R +#ifndef WINDOWS /*TODO - implement permission checks on Windows*/ if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) { error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); diff --git a/channels.c b/channels.c index bc1c6c4..e0bfb2b 100644 --- a/channels.c +++ b/channels.c @@ -1997,7 +1997,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__, strerror(errno)); @@ -2010,6 +2010,7 @@ channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset) close(newsock); return; } +#endif nc = channel_new("multiplex client", SSH_CHANNEL_MUX_CLIENT, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, "mux-control", 1); diff --git a/contrib/win32/openssh/config.h.vs b/contrib/win32/openssh/config.h.vs index 1236341..51e9445 100644 --- a/contrib/win32/openssh/config.h.vs +++ b/contrib/win32/openssh/config.h.vs @@ -1581,6 +1581,7 @@ #define _CRT_SECURE_NO_DEPRECATE 1 #define _CRT_NONSTDC_NO_DEPRECATE 1 #define WIN32_FIXME 1 +#define WINDOWS 1 /* Define if you must implement a startup_needs function for your platform */ #define HAVE_STARTUP_NEEDS 1 diff --git a/contrib/win32/openssh/win32compat.vcxproj b/contrib/win32/openssh/win32compat.vcxproj index 4cc6522..c1383d7 100644 --- a/contrib/win32/openssh/win32compat.vcxproj +++ b/contrib/win32/openssh/win32compat.vcxproj @@ -151,7 +151,6 @@ - diff --git a/contrib/win32/openssh/win32compat.vcxproj.filters b/contrib/win32/openssh/win32compat.vcxproj.filters index 90ee82c..ba02e95 100644 --- a/contrib/win32/openssh/win32compat.vcxproj.filters +++ b/contrib/win32/openssh/win32compat.vcxproj.filters @@ -57,9 +57,6 @@ Source Files - - Source Files - Source Files diff --git a/contrib/win32/openssh/win32iocompat.vcxproj b/contrib/win32/openssh/win32iocompat.vcxproj index 43bedc5..8a7d53f 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj +++ b/contrib/win32/openssh/win32iocompat.vcxproj @@ -150,6 +150,7 @@ + @@ -168,6 +169,8 @@ + + diff --git a/contrib/win32/openssh/win32iocompat.vcxproj.filters b/contrib/win32/openssh/win32iocompat.vcxproj.filters index 31d0e0d..1df6fe6 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj.filters +++ b/contrib/win32/openssh/win32iocompat.vcxproj.filters @@ -7,9 +7,10 @@ - - - + + + + @@ -49,13 +50,15 @@ inc\sys - + + + + inc - - inc + + inc\sys - diff --git a/contrib/win32/win32compat/fileio.c b/contrib/win32/win32compat/fileio.c index c460575..17fe2a2 100644 --- a/contrib/win32/win32compat/fileio.c +++ b/contrib/win32/win32compat/fileio.c @@ -557,6 +557,7 @@ fileio_fstat(struct w32_io* pio, struct _stat64 *buf) { int fileio_stat(const char *path, struct _stat64 *buf) { + /* TODO - path is UTD -8, support unicode*/ return _stat64(path, buf); } diff --git a/contrib/win32/win32compat/inc/pwd.h b/contrib/win32/win32compat/inc/pwd.h new file mode 100644 index 0000000..da81734 --- /dev/null +++ b/contrib/win32/win32compat/inc/pwd.h @@ -0,0 +1,42 @@ +/* +* Author: Manoj Ampalam +* +* Compatibility header to give us pwd-like functionality on Win32 +* A lot of passwd fields are not applicable in Windows, neither are some API calls based on this structure +* Ideally, usage of this structure needs to be replaced in core SSH code to an ssh_user interface, +* that each platform can extend and implement. +*/ + +#ifndef COMPAT_PWD_H +#define COMPAT_PWD_H 1 + +#include "sys\param.h" + +struct passwd { + char *pw_name; /* user's login name */ + char *pw_passwd; /* password? */ + char *pw_gecos; /* ??? */ + uid_t pw_uid; /* numerical user ID */ + gid_t pw_gid; /* numerical group ID */ + char *pw_dir; /* initial working directory */ + char *pw_shell; /* path to shell */ +}; + +/*start - declarations not applicable in Windows */ +uid_t getuid(void); +gid_t getgid(void); +uid_t geteuid(void); +gid_t getegid(void); +int setuid(uid_t uid); +int setgid(gid_t gid); +int seteuid(uid_t uid); +int setegid(gid_t gid); +/*end - declarations not applicable in Windows */ + +struct passwd *w32_getpwuid(uid_t uid); +struct passwd *w32_getpwnam(const char *username); + +#define getpwuid w32_getpwuid +#define getpwnam w32_getpwnam + +#endif diff --git a/contrib/win32/win32compat/inc/sys/param.h b/contrib/win32/win32compat/inc/sys/param.h new file mode 100644 index 0000000..bfc2d46 --- /dev/null +++ b/contrib/win32/win32compat/inc/sys/param.h @@ -0,0 +1,10 @@ +#ifndef COMPAT_PARAM_H +#define COMPAT_PARAM_H 1 + +typedef unsigned int uid_t; +typedef unsigned int gid_t; +typedef long off_t; +typedef unsigned int dev_t; + + +#endif diff --git a/contrib/win32/win32compat/inc/unistd.h b/contrib/win32/win32compat/inc/unistd.h index d65150c..f4831a8 100644 --- a/contrib/win32/win32compat/inc/unistd.h +++ b/contrib/win32/win32compat/inc/unistd.h @@ -34,6 +34,7 @@ #define lseek w32_lseek #define getdtablesize() MAX_FDS +#define gethostname w32_gethostname #define fopen w32_fopen_utf8 diff --git a/contrib/win32/win32compat/inc/w32posix.h b/contrib/win32/win32compat/inc/w32posix.h index 78a31fd..67ca87a 100644 --- a/contrib/win32/win32compat/inc/w32posix.h +++ b/contrib/win32/win32compat/inc/w32posix.h @@ -69,6 +69,7 @@ sighandler_t w32_signal(int signum, sighandler_t handler); int w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset); int w32_raise(int sig); int w32_kill(int pid, int sig); +int w32_gethostname(char *, size_t); FILE* w32_fopen_utf8(const char *, const char *); diff --git a/contrib/win32/win32compat/includes/pwd.h b/contrib/win32/win32compat/includes/pwd.h deleted file mode 100644 index 7a0d13c..0000000 --- a/contrib/win32/win32compat/includes/pwd.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef COMPAT_PWD_H -#define COMPAT_PWD_H 1 - -/* Compatibility header to give us pwd-like functionality on Win32 */ - -struct passwd -{ - char *pw_name; /* user's login name */ - char *pw_passwd; /* password? */ - char *pw_gecos; /* ??? */ - uid_t pw_uid; /* numerical user ID */ - gid_t pw_gid; /* numerical group ID */ - char *pw_dir; /* initial working directory */ - char *pw_shell; /* path to shell */ -}; - -uid_t getuid(void); -gid_t getgid(void); -uid_t geteuid(void); -gid_t getegid(void); -int setuid(uid_t uid); -int setgid(gid_t gid); -int seteuid(uid_t uid); -int setegid(gid_t gid); -struct passwd *getpwuid(uid_t uid); -struct passwd *getpwnam(const char *username); -void endpwent(void); - -char *realpathWin32(const char *path, char resolved[PATH_MAX]); - -const char * -user_from_uid(uid_t uid, int nouser); - -#endif diff --git a/contrib/win32/win32compat/includes/sys/param.h b/contrib/win32/win32compat/includes/sys/param.h deleted file mode 100644 index 2607d96..0000000 --- a/contrib/win32/win32compat/includes/sys/param.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef COMPAT_PARAM_H -#define COMPAT_PARAM_H 1 - -/* Compatibility header to avoid lots of #ifdef _WIN32's in includes.h */ -typedef unsigned int uid_t; -typedef unsigned int gid_t; -//typedef size_t _off_t; -typedef size_t off_t; -typedef _dev_t dev_t; - - -#endif diff --git a/contrib/win32/win32compat/misc.c b/contrib/win32/win32compat/misc.c index ec6c109..6f68830 100644 --- a/contrib/win32/win32compat/misc.c +++ b/contrib/win32/win32compat/misc.c @@ -117,4 +117,10 @@ w32_fopen_utf8(const char *path, const char *mode) { } return f; +} + +/*TODO implement Unicode host name support in Windows*/ +int +w32_gethostname(char *name, size_t len) { + return gethostname(name, len); } \ No newline at end of file diff --git a/contrib/win32/win32compat/pwd.c b/contrib/win32/win32compat/pwd.c index e311d0f..b775ef3 100644 --- a/contrib/win32/win32compat/pwd.c +++ b/contrib/win32/win32compat/pwd.c @@ -29,76 +29,132 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "includes.h" - -#include -#include -#include -#include -#include -#include -#include +#include +#include #include - -#include "win32auth.h" -#include "homedirhelp.h" - - -char *GetHomeDirFromToken(char *userName, HANDLE token); - -uid_t getuid(void) -{ - return 0; -} - -gid_t getgid(void) -{ - return 0; -} - -uid_t geteuid(void) -{ - return 0; -} - -gid_t getegid(void) -{ - return 0; -} - -int setuid(uid_t uid) -{ - return 0; -} - -int setgid(gid_t gid) -{ - return 0; -} - -int seteuid(uid_t uid) -{ - return 0; -} - -int setegid(gid_t gid) -{ - return 0; -} - -/* - * Global pw variables - */ +#define SECURITY_WIN32 +#include +#include "inc\pwd.h" static struct passwd pw; +static char* pw_shellpath = "ssh-shellhost.exe"; + +int +initialize_pw() { + if (pw.pw_shell != pw_shellpath) { + memset(&pw, 0, sizeof(pw)); + pw.pw_shell = pw_shellpath; + } + return 0; +} + +void +reset_pw() { + if (pw.pw_name) + free(pw.pw_name); + if (pw.pw_dir) + free(pw.pw_dir); +} + +wchar_t* +utf8_to_utf16(const char *utf8) { + int needed = 0; + wchar_t* utf16 = NULL; + if ((needed = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0)) == 0 || + (utf16 = malloc(needed*sizeof(wchar_t))) == NULL || + MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, needed) == 0) + return NULL; + return utf16; +} + +char* +utf16_to_utf8(const wchar_t* utf16) { + int needed = 0; + char* utf8 = NULL; + if ((needed = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, NULL, NULL)) == 0 || + (utf8 = malloc(needed)) == NULL || + WideCharToMultiByte(CP_UTF8, 0, utf16, -1, utf8, needed, NULL, NULL) == 0) + return NULL; + return utf8; +} + +struct passwd* +w32_getpwnam(const char *user_utf8) { + struct passwd *ret = NULL; + wchar_t *user_utf16 = NULL, *uname_utf16, *udom_utf16, *tmp; + char *uname_utf8 = NULL, *pw_home_utf8 = NULL; + LPBYTE *user_info = NULL; + LPWSTR user_sid = NULL; + wchar_t reg_path[MAX_PATH], profile_home[MAX_PATH]; + HKEY reg_key = 0; + int tmp_len = MAX_PATH; + + errno = 0; + + if (initialize_pw() != 0) + goto done; + + if ((user_utf16 = utf8_to_utf16(user_utf8) ) == NULL) { + errno = ENOMEM; + goto done; + } + + /*find domain part if any*/ + if ((tmp = wcschr(user_utf16, L'\\')) != NULL) { + udom_utf16 = user_utf16; + uname_utf16 = tmp + 1; + *tmp = L'\0'; + + } + else if ((tmp = wcschr(user_utf16, L'@')) != NULL) { + udom_utf16 = tmp + 1; + uname_utf16 = user_utf16; + *tmp = L'\0'; + } + else { + uname_utf16 = user_utf16; + udom_utf16 = NULL; + } + + if (NetUserGetInfo(udom_utf16, uname_utf16, 23, user_info) != NERR_Success || + ConvertSidToStringSidW(((LPUSER_INFO_23)user_info)->usri23_user_sid, &user_sid) == FALSE) { + errno = ENOMEM; //?? + goto done; + } + + if (swprintf(reg_path, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%ls", user_sid) == 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)profile_home, &tmp_len) != 0) + GetWindowsDirectoryW(profile_home, MAX_PATH); + + if ((uname_utf8 = utf16_to_utf8(uname_utf16)) == NULL || + (pw_home_utf8 = utf16_to_utf8(profile_home)) == NULL) { + errno = ENOMEM; + goto done; + } + + pw.pw_name = uname_utf8; + uname_utf8 = NULL; + pw.pw_dir = pw_home_utf8; + pw_home_utf8 = NULL; + ret = &pw; +done: + if (user_utf16) + free(user_utf16); + if (uname_utf8) + free(uname_utf8); + if (pw_home_utf8) + free(pw_home_utf8); + if (user_info) + NetApiBufferFree(user_info); + if (user_sid) + LocalFree(user_sid); + if (reg_key) + RegCloseKey(reg_key); + return ret; +} + -static char pw_gecos[UNLEN + 1] = {'\0'}; -static char pw_username[UNLEN + 1] = {'\0'}; -static char pw_passwd[UNLEN + 1] = {'\0'}; -static wchar_t pw_homedir[MAX_PATH] = {L'\0'}; -static char pw_homedir_ascii[MAX_PATH] = {'\0'}; -static char pw_password[MAX_PATH] = {'\0'}; -static char pw_shellpath[MAX_PATH] = {'\0'}; /* given a access token, find the domain name of user account of the access token */ int GetDomainFromToken ( HANDLE *hAccessToken, UCHAR *domain, DWORD dwSize) @@ -135,315 +191,39 @@ int GetDomainFromToken ( HANDLE *hAccessToken, UCHAR *domain, DWORD dwSize) } \ } while (0) -char *GetHomeDirFromToken(char *userName, HANDLE token) -{ - 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; - - /* set home dir to Windows if any of below fair*/ - GetWindowsDirectoryW(pw_homedir, MAX_PATH); - - 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, pw_homedir, &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 (reg_key) - RegCloseKey(reg_key); - - { /* retrieve and set env variables. */ - /* TODO - Get away with fixed limits and dynamically allocate required memory, cleanup this logic*/ -#define MAX_VALUE_LEN 1000 -#define MAX_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; - - 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, &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 (to_apply) - SetEnvironmentVariableW(value_name, to_apply); - - - } - RegCloseKey(reg_key); - } - - - RevertToSelf(); - } - - - - debug("<- GetHomeDirFromToken()..."); - - return pw_homedir; -} - /* - * Not thread safe, would need to use thread local - * storage instead of a static. + * Temporary getpwuid implementaion of Windows. This should be replaced with getpw_currentuser */ -struct passwd *getpwuid(uid_t uid) -{ - static struct passwd pw; +struct passwd* +w32_getpwuid(uid_t uid) { + wchar_t* wuser = NULL; + char* user_utf8 = NULL; + ULONG needed = 0; + struct passwd *ret = NULL; - static char username[UNLEN + 1]; - - DWORD usernamelen = UNLEN + 1; - - wchar_t *homedir_w; + errno = 0; - /* - * Clear errno. - */ - - errno = 0; + if (GetUserNameExW(NameSamCompatible, NULL, &needed) != 0 || + (wuser = malloc(needed*sizeof(wchar_t))) == NULL || + GetUserNameExW(NameSamCompatible, wuser, &needed) == 0 || + (user_utf8 = utf16_to_utf8(wuser) )== NULL ) { + errno = ENOMEM; + goto done; + } - /* - * Zero out the structure. - */ - - memset(&pw, 0, sizeof(pw)); - - memset(pw_username, 0, sizeof(pw_username)); - memset(pw_homedir, 0, sizeof(pw_homedir)); - memset(pw_password, 0, sizeof(pw_password)); - memset(pw_shellpath, 0, sizeof(pw_shellpath)); + ret = w32_getpwnam(user_utf8); - /* - * Point to the static string variables. - */ - - pw.pw_name = pw_username; - pw.pw_passwd = pw_password; - pw.pw_gecos = pw_gecos; - pw.pw_shell = pw_shellpath; - pw.pw_dir = pw_homedir_ascii; +done: + if (wuser) + free(wuser); + if (user_utf8) + free(user_utf8); - /* - * Get the current user's name. - */ - - GetUserName(username, &usernamelen); - - debug3("getpwuid: username [%s]", username); - - strncpy(pw_username, username, sizeof(pw_username)); - - /* - * ssh need path to 'known_hosts' file, so we don't - * comment it here (see -> getpwnam() function). - */ - - /* - * Get default shell path. - */ - - //GetSystemDirectory(pw_shellpath, MAX_PATH); - - //debug3("getpwuid: system dir [%s]", pw_shellpath); - pw_shellpath[0] = '\0'; - strcat(pw_shellpath, "ssh-shellhost.exe"); - - //debug3("getpwuid: shell path [%s]", pw_shellpath); - - /* - * Get home directory path (if this fails, - * the user is invalid, bail) - */ - - homedir_w = gethomedir_w(username, NULL); - - if (!homedir_w || homedir_w[0] == '\0') - { - /* - * Bail out. - */ - - errno = ENOENT; - - return &pw; - } - - debug3("getpwuid: homedir [%ls]", homedir_w); - - //wcsncpy(pw_homedir, homedir_w, sizeof(pw_homedir)); - // convert to ascii from widechar(unicode) - int rc = WideCharToMultiByte( CP_UTF8, // UTF8/ANSI Code Page - 0, // No special handling of unmapped chars - homedir_w, // wide-character string to be converted - -1, // Unicode src str len, -1 means calc it - pw_homedir_ascii, - sizeof(pw_homedir_ascii), - NULL, NULL ); // Unrepresented char replacement - Use Default - - free(homedir_w); - - if ( rc == 0 ) { - debug3("Could not convert homedirectory [%ls]from unicode to utf8", homedir_w); - } - - /* - * Point to the username static variable. - */ - - //pw.pw_name = pw_username; - //pw.pw_passwd = pw_passwd; - //pw.pw_gecos = pw_gecos; - //pw.pw_shell = pw_shellpath; - //pw.pw_dir = pw_homedir; - - return &pw; + return ret; } -struct passwd *getpwnam(const char *userin) -{ - char *homedir; - - debug3("getpwnam: username [%s]", userin); - - /* - * Clear errno. - */ - - errno = 0; - - /* - * Zero out the structure. - */ - - memset(&pw, 0, sizeof(pw)); - - memset(pw_username, 0, sizeof(pw_username)); - memset(pw_homedir, 0, sizeof(pw_homedir)); - memset(pw_password, 0, sizeof(pw_password)); - memset(pw_shellpath, 0, sizeof(pw_shellpath)); - - /* - * Point to the static string variables. - */ - - pw.pw_name = pw_username; - pw.pw_passwd = pw_password; - pw.pw_gecos = pw_gecos; - pw.pw_shell = pw_shellpath; - pw.pw_dir = pw_homedir; - - /* - * Get default shell path. - */ - - //GetSystemDirectory(pw_shellpath, MAX_PATH); - - //debug3("getpwuid: system dir [%s]", pw_shellpath); - - pw_shellpath[0] = '\0'; - strcat(pw_shellpath, "ssh-shellhost.exe"); - - //debug3("getpwuid: shell path [%s]", pw_shellpath); - - /* - * Copy user name to static structure. - */ - - strncpy(pw_username, userin, UNLEN + 1); - - /* - * Get a token for this user. - */ - - return &pw; -} - -void endpwent(void) -{ - /* - * This normally cleans up access to the passwd file, - * which we don't have, thus no cleanup. - */ -} - -#define NCACHE 64 /* power of 2 */ -#define MASK (NCACHE - 1) /* bits to store with */ - -const char * -user_from_uid(uid_t uid, int nouser) -{ - static struct ncache { - uid_t uid; - char *name; - } c_uid[NCACHE]; - static int pwopen; - static char nbuf[15]; /* 32 bits == 10 digits */ - struct passwd *pw; - struct ncache *cp; - - cp = c_uid + (uid & MASK); - if (cp->uid != uid || cp->name == NULL) { - if (pwopen == 0) { - pwopen = 1; - } - if ((pw = getpwuid(uid)) == NULL) { - if (nouser) - return (NULL); - (void)snprintf(nbuf, sizeof(nbuf), "%u", uid); - } - cp->uid = uid; - if (cp->name != NULL) - free(cp->name); - cp->name = strdup(pw ? pw->pw_name : nbuf); - } - return (cp->name); -} /* TODO - this is moved from realpath.c in openbsdcompat. Review and finalize its position*/ @@ -469,56 +249,43 @@ void slashconvert(char *str) } } -char *realpathWin32(const char *path, char resolved[PATH_MAX]) -{ - char realpath[PATH_MAX]; - strlcpy(resolved, path + 1, sizeof(realpath)); - backslashconvert(resolved); - PathCanonicalizeA(realpath, resolved); - slashconvert(realpath); - - /* - * Store terminating slash in 'X:/' on Windows. - */ - - if (realpath[1] == ':' && realpath[2] == 0) - { - realpath[2] = '/'; - realpath[3] = 0; - } - - resolved[0] = *path; // will be our first slash in /x:/users/test1 format - strncpy(resolved + 1, realpath, sizeof(realpath)); - return resolved; +uid_t +getuid(void) { + return 0; } -// like realpathWin32() but takes out the first slash so that windows systems can work on the actual file or directory -char *realpathWin32i(const char *path, char resolved[PATH_MAX]) -{ - char realpath[PATH_MAX]; - - if (path[0] != '/') { - // absolute form x:/abc/def given, no first slash to take out - strlcpy(resolved, path, sizeof(realpath)); - } - else - strlcpy(resolved, path + 1, sizeof(realpath)); - - backslashconvert(resolved); - PathCanonicalizeA(realpath, resolved); - slashconvert(realpath); - - /* - * Store terminating slash in 'X:/' on Windows. - */ - - if (realpath[1] == ':' && realpath[2] == 0) - { - realpath[2] = '/'; - realpath[3] = 0; - } - - strncpy(resolved, realpath, sizeof(realpath)); - return resolved; +gid_t +getgid(void) { + return 0; +} + +uid_t +geteuid(void) { + return 0; +} + +gid_t +getegid(void) { + return 0; +} + +int +setuid(uid_t uid) { + return 0; +} + +int +setgid(gid_t gid) { + return 0; +} + +int +seteuid(uid_t uid) { + return 0; +} + +int +setegid(gid_t gid) { + return 0; } diff --git a/contrib/win32/win32compat/ssh-agent/agentconfig.c b/contrib/win32/win32compat/ssh-agent/agentconfig.c index 2df29b1..7f6da6f 100644 --- a/contrib/win32/win32compat/ssh-agent/agentconfig.c +++ b/contrib/win32/win32compat/ssh-agent/agentconfig.c @@ -116,9 +116,8 @@ int pubkey_allowed(struct sshkey* pubkey, wchar_t* wuser, wchar_t* wuser_home) { if (WideCharToMultiByte(CP_UTF8, 0, wuser, -1, user, 256, NULL, NULL) == 0) return 0; - /* BUG - pw structure is assumed to be filled with unicode strings by expand_authorized_keys()*/ - //WideCharToMultiByte(CP_UTF8, 0, wuser_home, -1, user_home, MAX_PATH, NULL, NULL); - pw.pw_dir = wuser_home; + WideCharToMultiByte(CP_UTF8, 0, wuser_home, -1, user_home, MAX_PATH, NULL, NULL); + pw.pw_dir = user_home; pw.pw_name = user; return user_key_allowed(&pw, pubkey, 1); } \ No newline at end of file diff --git a/loginrec.c b/loginrec.c index 94ae81d..7e361bb 100644 --- a/loginrec.c +++ b/loginrec.c @@ -527,6 +527,7 @@ getlast_entry(struct logininfo *li) /* If wtmp isn't available, try wtmpx */ return (wtmpx_get_entry(li)); # else + /* TODO - implement last_login_entry in Windows*/ /* Give up: No means of retrieving last login time */ return (0); # endif /* DISABLE_LASTLOG */ diff --git a/misc.c b/misc.c index 0d2b2ea..2c7b100 100644 --- a/misc.c +++ b/misc.c @@ -222,12 +222,7 @@ pwcopy(struct passwd *pw) #ifdef HAVE_STRUCT_PASSWD_PW_CLASS copy->pw_class = xstrdup(pw->pw_class); #endif - -#ifdef WIN32_FIXME//N - copy -> pw_dir = (char*)_wcsdup((wchar_t*)pw->pw_dir); -#else copy->pw_dir = xstrdup(pw->pw_dir); -#endif copy->pw_shell = xstrdup(pw->pw_shell); return copy; } diff --git a/readconf.c b/readconf.c index 84da4cc..0894cd3 100644 --- a/readconf.c +++ b/readconf.c @@ -1564,7 +1564,7 @@ read_config_file(const char *filename, struct passwd *pw, const char *host, if ((f = fopen(filename, "r")) == NULL) return 0; -#ifndef WIN32_FIXME +#ifndef WINDOWS /* TODO - implement permission checks for Windows */ if (flags & SSHCONF_CHECKPERM) { struct stat sb; diff --git a/session.c b/session.c index f12e164..82e3c62 100644 --- a/session.c +++ b/session.c @@ -103,7 +103,6 @@ #ifdef WIN32_FIXME -char *GetHomeDirFromToken(char *userName, HANDLE token); /* FIXME: GFPZR: Function stat() may be undeclared. */ @@ -702,20 +701,13 @@ do_exec_no_pty(Session *s, const char *command) SetEnvironmentVariable("DISPLAY", s -> display); } - /* - * Get user homedir if needed. - */ - - if (1) // (s -> pw -> pw_dir == NULL || s -> pw -> pw_dir[0] == '\0') - { - s -> pw -> pw_dir = GetHomeDirFromToken(s -> pw -> pw_name, hToken); - } - /* * Change to users home directory + * TODO - pw_dir is utf-8, convert it to utf-16 and call _wchdir + * also change subsequent calls to SetEnvironmentVariable */ - _wchdir(s -> pw -> pw_dir); + _chdir(s->pw->pw_dir); SetEnvironmentVariableW(L"HOME", s -> pw -> pw_dir); wchar_t *wstr, wchr; diff --git a/sftp-common.c b/sftp-common.c index 277c14a..42e74fa 100644 --- a/sftp-common.c +++ b/sftp-common.c @@ -232,11 +232,13 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units) strmode_from_attrib(remote, mode); #endif if (!remote) { +#ifndef WIN#2_FIXME user = user_from_uid(st->st_uid, 0); - #ifdef WIN32_FIXME +#else + user = "\0"; snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid); group = gbuf; - #endif +#endif } else { snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid); user = ubuf; diff --git a/sftp-server.c b/sftp-server.c index e6dd029..9930f57 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -74,7 +74,8 @@ * stat requires paths * without slash at the end). */ - + char *realpathWin32(const char *path, char resolved[PATH_MAX]); + char *realpathWin32i(const char *path, char resolved[PATH_MAX]); #define realpath realpathWin32 #endif /* WIN32_FIXME */ @@ -2160,3 +2161,59 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) } //#endif /* else WIN32 */ } + +#ifdef WIN32_FIXME +char *realpathWin32(const char *path, char resolved[PATH_MAX]) +{ + char realpath[PATH_MAX]; + + strlcpy(resolved, path + 1, sizeof(realpath)); + backslashconvert(resolved); + PathCanonicalizeA(realpath, resolved); + slashconvert(realpath); + + /* + * Store terminating slash in 'X:/' on Windows. + */ + + if (realpath[1] == ':' && realpath[2] == 0) + { + realpath[2] = '/'; + realpath[3] = 0; + } + + resolved[0] = *path; // will be our first slash in /x:/users/test1 format + strncpy(resolved + 1, realpath, sizeof(realpath)); + return resolved; +} + +// like realpathWin32() but takes out the first slash so that windows systems can work on the actual file or directory +char *realpathWin32i(const char *path, char resolved[PATH_MAX]) +{ + char realpath[PATH_MAX]; + + if (path[0] != '/') { + // absolute form x:/abc/def given, no first slash to take out + strlcpy(resolved, path, sizeof(realpath)); + } + else + strlcpy(resolved, path + 1, sizeof(realpath)); + + backslashconvert(resolved); + PathCanonicalizeA(realpath, resolved); + slashconvert(realpath); + + /* + * Store terminating slash in 'X:/' on Windows. + */ + + if (realpath[1] == ':' && realpath[2] == 0) + { + realpath[2] = '/'; + realpath[3] = 0; + } + + strncpy(resolved, realpath, sizeof(realpath)); + return resolved; +} +#endif diff --git a/ssh.c b/ssh.c index 8ab2220..1848623 100644 --- a/ssh.c +++ b/ssh.c @@ -560,6 +560,7 @@ main(int ac, char **av) */ closefrom(STDERR_FILENO + 1); +#ifndef WINDOWS /* * Save the original real uid. It will be needed later (uid-swapping * may clobber the real uid). @@ -575,6 +576,7 @@ main(int ac, char **av) * has been made, as we may need to create the port several times). */ PRIV_END; +#endif #ifdef HAVE_SETRLIMIT /* If we are installed setuid root be careful to not drop core. */ @@ -2081,16 +2083,8 @@ load_public_identity_files(void) if ((pw = getpwuid(original_real_uid)) == NULL) fatal("load_public_identity_files: getpwuid failed"); pwname = xstrdup(pw->pw_name); -#ifdef WIN32_FIXME - pwdir = _wcsdup(pw -> pw_dir); - - if (pwdir) - { - sprintf(pwdir, "%ls", pw -> pw_dir); - } -#else pwdir = xstrdup(pw->pw_dir); -#endif + if (gethostname(thishost, sizeof(thishost)) == -1) fatal("load_public_identity_files: gethostname: %s", strerror(errno)); diff --git a/sshd.c b/sshd.c index f17ef23..b57f167 100644 --- a/sshd.c +++ b/sshd.c @@ -2213,6 +2213,7 @@ main(int ac, char **av) logit("[Build " __DATE__ " " __TIME__ "]"); #endif +#ifndef WINDOWS /* Store privilege separation user for later use if required. */ if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { if (use_privsep || options.kerberos_authentication) @@ -2226,6 +2227,7 @@ main(int ac, char **av) privsep_pw->pw_passwd = xstrdup("*"); } endpwent(); +#endif /* load host keys */ sensitive_data.host_keys = xcalloc(options.num_host_key_files,