From 9ff97f6106e4d869052e0dbc489b86ad7ee96bef Mon Sep 17 00:00:00 2001 From: Manoj Ampalam Date: Mon, 28 May 2018 22:03:33 -0700 Subject: [PATCH] Fixed issue with virtual token generation (#314) On certain machines, virtual tokens were not getting generated due to lack of required privileges. Fixed it by assigning them before doing LogonUserExExW. Consolidated runtime dll loading logic. PowerShell/Win32-OpenSSH#1162 --- auth-passwd.c | 26 +- contrib/win32/openssh/win32iocompat.vcxproj | 716 +++++++++--------- .../openssh/win32iocompat.vcxproj.filters | 340 ++++----- contrib/win32/win32compat/logonuser.c | 82 -- contrib/win32/win32compat/logonuser.h | 14 - contrib/win32/win32compat/w32api_proxies.c | 199 +++++ contrib/win32/win32compat/w32api_proxies.h | 21 + .../win32/win32compat/win32_usertoken_utils.c | 55 +- 8 files changed, 782 insertions(+), 671 deletions(-) delete mode 100644 contrib/win32/win32compat/logonuser.c delete mode 100644 contrib/win32/win32compat/logonuser.h create mode 100644 contrib/win32/win32compat/w32api_proxies.c create mode 100644 contrib/win32/win32compat/w32api_proxies.h diff --git a/auth-passwd.c b/auth-passwd.c index 700bed195..fa4c0ecb5 100644 --- a/auth-passwd.c +++ b/auth-passwd.c @@ -57,11 +57,8 @@ #include "authfd.h" #ifdef WINDOWS -#define SECURITY_WIN32 -#include -#include "logonuser.h" +#include "w32api_proxies.h" #include "misc_internal.h" -#include "monitor_wrap.h" #endif extern Buffer loginmsg; @@ -297,25 +294,8 @@ sys_auth_passwd(struct ssh *ssh, const char *password) /* translate to domain user if format contains a backslash */ wchar_t * backslash = wcschr(user_utf16, L'\\'); if (backslash != NULL) { - - /* assemble the path to the name translation library */ - wchar_t library_path[MAX_PATH + 1]; - if (GetSystemDirectoryW(library_path, ARRAYSIZE(library_path)) == 0) { - debug3("%s: GetSystemDirectoryW() failed name translation: %d", __FUNCTION__, GetLastError()); - goto done; - } - wcscat_s(library_path, ARRAYSIZE(library_path), L"\\secur32.dll"); - - /* dynamically load name translation function to support static linking to onecore */ - typedef (*TranslateNameWFunc)(_In_ LPCWSTR lpAccountName, - _In_ EXTENDED_NAME_FORMAT AccountNameFormat, _In_ EXTENDED_NAME_FORMAT DesiredNameFormat, - _Out_writes_to_opt_(*nSize, *nSize) LPWSTR lpTranslatedName, _Inout_ PULONG nSize); - HMODULE library = LoadLibraryW(library_path); - TranslateNameWFunc LocalTranslateNameW = NULL; - /* attempt to format into upn format as this is preferred for login */ - if (library != NULL && (LocalTranslateNameW = (TranslateNameWFunc) GetProcAddress(library, "TranslateNameW")) != NULL && - LocalTranslateNameW(user_utf16, NameSamCompatible, NameUserPrincipal, domain_upn, &domain_upn_len) != 0) { + if (pTranslateNameW(user_utf16, NameSamCompatible, NameUserPrincipal, domain_upn, &domain_upn_len) != 0) { unam_utf16 = domain_upn; udom_utf16 = NULL; } @@ -330,7 +310,7 @@ sys_auth_passwd(struct ssh *ssh, const char *password) } } - if (LogonUserExExWHelper(unam_utf16, udom_utf16, pwd_utf16, LOGON32_LOGON_NETWORK_CLEARTEXT, + if (pLogonUserExExW(unam_utf16, udom_utf16, pwd_utf16, LOGON32_LOGON_NETWORK_CLEARTEXT, LOGON32_PROVIDER_DEFAULT, NULL, &token, NULL, NULL, NULL, NULL) == TRUE) password_auth_token = token; else { diff --git a/contrib/win32/openssh/win32iocompat.vcxproj b/contrib/win32/openssh/win32iocompat.vcxproj index d58a121d0..d4b351321 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj +++ b/contrib/win32/openssh/win32iocompat.vcxproj @@ -1,359 +1,359 @@ - - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - {0D02F0F0-013B-4EE3-906D-86517F3822C0} - win32iocompat - Win32Proj - $(WindowsSDKVersion) - posix_compat - - - - StaticLibrary - v140 - MultiByte - true - - - StaticLibrary - v140 - MultiByte - true - - - StaticLibrary - v141 - MultiByte - true - - - StaticLibrary - v141 - MultiByte - true - - - StaticLibrary - v140 - MultiByte - - - StaticLibrary - v140 - MultiByte - - - StaticLibrary - v141 - MultiByte - - - StaticLibrary - v141 - MultiByte - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>14.0.23107.0 - - - $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\$(TargetName)\ - - - $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\$(TargetName)\ - - - $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\$(TargetName)\ - - - $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\$(TargetName)\ - - - $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\$(TargetName)\ - - - $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\$(TargetName)\ - - - $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\$(TargetName)\ - - - $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\$(TargetName)\ - - - - Disabled - - - USE_MSCNG;_WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - NotUsing - Level1 - ProgramDatabase - false - false - Guard - /Gy %(AdditionalOptions) - - - - - Disabled - - - USE_MSCNG;_WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebug - NotUsing - Level3 - ProgramDatabase - false - Guard - /Gy %(AdditionalOptions) - - - - - Disabled - - - USE_MSCNG;_WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebug - NotUsing - Level3 - ProgramDatabase - false - Guard - /Gy %(AdditionalOptions) - - - - - Disabled - - - USE_MSCNG;_WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebug - NotUsing - Level3 - ProgramDatabase - false - Guard - /Gy %(AdditionalOptions) - - - - - - - _LIB;USE_MSCNG;_WIN32_WINNT=0x600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreaded - NotUsing - Level1 - ProgramDatabase - false - Guard - /Gy %(AdditionalOptions) - - - - - - - _LIB;USE_MSCNG;_WIN32_WINNT=0x600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreaded - NotUsing - Level1 - ProgramDatabase - false - Disabled - false - true - Guard - /Gy %(AdditionalOptions) - - - - - - - _LIB;USE_MSCNG;_WIN32_WINNT=0x600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreaded - NotUsing - Level1 - ProgramDatabase - false - Disabled - false - true - Guard - /Gy %(AdditionalOptions) - - - - - - - _LIB;USE_MSCNG;_WIN32_WINNT=0x600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - MultiThreaded - NotUsing - Level1 - ProgramDatabase - false - Disabled - false - true - Guard - /Gy %(AdditionalOptions) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {0D02F0F0-013B-4EE3-906D-86517F3822C0} + win32iocompat + Win32Proj + $(WindowsSDKVersion) + posix_compat + + + + StaticLibrary + v140 + MultiByte + true + + + StaticLibrary + v140 + MultiByte + true + + + StaticLibrary + v141 + MultiByte + true + + + StaticLibrary + v141 + MultiByte + true + + + StaticLibrary + v140 + MultiByte + + + StaticLibrary + v140 + MultiByte + + + StaticLibrary + v141 + MultiByte + + + StaticLibrary + v141 + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.23107.0 + + + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\$(TargetName)\ + + + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\$(TargetName)\ + + + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\$(TargetName)\ + + + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\$(TargetName)\ + + + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\$(TargetName)\ + + + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\$(TargetName)\ + + + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\$(TargetName)\ + + + $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\$(TargetName)\ + + + + Disabled + + + USE_MSCNG;_WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + NotUsing + Level3 + ProgramDatabase + false + false + Guard + /Gy %(AdditionalOptions) + + + + + Disabled + + + USE_MSCNG;_WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + NotUsing + Level3 + ProgramDatabase + false + Guard + /Gy %(AdditionalOptions) + + + + + Disabled + + + USE_MSCNG;_WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + NotUsing + Level3 + ProgramDatabase + false + Guard + /Gy %(AdditionalOptions) + + + + + Disabled + + + USE_MSCNG;_WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + NotUsing + Level3 + ProgramDatabase + false + Guard + /Gy %(AdditionalOptions) + + + + + + + _LIB;USE_MSCNG;_WIN32_WINNT=0x600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreaded + NotUsing + Level3 + ProgramDatabase + false + Guard + /Gy %(AdditionalOptions) + + + + + + + _LIB;USE_MSCNG;_WIN32_WINNT=0x600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreaded + NotUsing + Level3 + ProgramDatabase + false + Disabled + false + true + Guard + /Gy %(AdditionalOptions) + + + + + + + _LIB;USE_MSCNG;_WIN32_WINNT=0x600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreaded + NotUsing + Level3 + ProgramDatabase + false + Disabled + false + true + Guard + /Gy %(AdditionalOptions) + + + + + + + _LIB;USE_MSCNG;_WIN32_WINNT=0x600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreaded + NotUsing + Level3 + ProgramDatabase + false + Disabled + false + true + Guard + /Gy %(AdditionalOptions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contrib/win32/openssh/win32iocompat.vcxproj.filters b/contrib/win32/openssh/win32iocompat.vcxproj.filters index af443af01..f2ce0776f 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj.filters +++ b/contrib/win32/openssh/win32iocompat.vcxproj.filters @@ -1,170 +1,172 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - inc\sys - - - inc\sys - - - inc\sys - - - inc\sys - - - inc - - - inc - - - inc - - - inc - - - inc\sys - - - inc\sys - - - - inc - - - inc\sys - - - inc\sys - - - inc\sys - - - inc\sys - - - inc\arpa - - - inc\arpa - - - inc\netinet - - - inc\netinet - - - inc\netinet - - - inc\netinet - - - inc - - - inc - - - inc - - - inc - - - inc - - - inc - - - - inc - - - inc - - - inc - - - inc - - - inc - - - inc\sys - - - inc - - - inc - - - inc - - - inc - - - - - - inc - - - inc - - - inc\net - - - - - {b70431df-c3b2-46ee-a825-aeb9df643f7f} - - - {9fd6aa70-2efb-4577-87eb-d285a9cbbaa0} - - - {6e4a035d-0b38-4507-9eec-19097d4ac16f} - - - {d943f1aa-2df9-4df3-b499-4403a899fe8d} - - - {b16bbf61-e602-4b0f-832b-190085cbfd5c} - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + inc\sys + + + inc\sys + + + inc\sys + + + inc\sys + + + inc + + + inc + + + inc + + + inc + + + inc\sys + + + inc\sys + + + + inc + + + inc\sys + + + inc\sys + + + inc\sys + + + inc\sys + + + inc\arpa + + + inc\arpa + + + inc\netinet + + + inc\netinet + + + inc\netinet + + + inc\netinet + + + inc + + + inc + + + inc + + + inc + + + inc + + + inc + + + + inc + + + inc + + + inc + + + inc + + + inc + + + inc\sys + + + inc + + + inc + + + inc + + + inc + + + + + + inc + + + inc + + + inc\net + + + + + {b70431df-c3b2-46ee-a825-aeb9df643f7f} + + + {9fd6aa70-2efb-4577-87eb-d285a9cbbaa0} + + + {6e4a035d-0b38-4507-9eec-19097d4ac16f} + + + {d943f1aa-2df9-4df3-b499-4403a899fe8d} + + + {b16bbf61-e602-4b0f-832b-190085cbfd5c} + + \ No newline at end of file diff --git a/contrib/win32/win32compat/logonuser.c b/contrib/win32/win32compat/logonuser.c deleted file mode 100644 index 783e47800..000000000 --- a/contrib/win32/win32compat/logonuser.c +++ /dev/null @@ -1,82 +0,0 @@ -/* -* Author: Yanbing Wang -* -* Support logon user call on Win32 based operating systems. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include -#include "debug.h" - -/* Define the function prototype */ -typedef BOOL(WINAPI *LogonUserExExWType)(wchar_t*, wchar_t*, wchar_t*, DWORD, DWORD, PTOKEN_GROUPS, PHANDLE, PSID, PVOID, LPDWORD, PQUOTA_LIMITS); -static HMODULE hMod = NULL; -static LogonUserExExWType func = NULL; - -/* -* The function uses LoadLibrary and GetProcAddress to access -* LogonUserExExW function from sspicli.dll. -*/ -BOOL -LogonUserExExWHelper(wchar_t *user_name, wchar_t *domain, wchar_t *password, DWORD logon_type, - DWORD logon_provider, PTOKEN_GROUPS token_groups, PHANDLE token, PSID *logon_sid, - PVOID *profile_buffer, LPDWORD profile_length, PQUOTA_LIMITS quota_limits) -{ - wchar_t sspicli_dll_path[MAX_PATH + 1] = { 0, }; - wchar_t advapi32_dll_path[MAX_PATH + 1] = { 0, }; - wchar_t system32_path[MAX_PATH + 1] = { 0, }; - - if (!GetSystemDirectoryW(system32_path, _countof(system32_path))) { - debug3("GetSystemDirectory failed with error %d", GetLastError()); - return FALSE; - } - wcsncpy_s(sspicli_dll_path, _countof(sspicli_dll_path), system32_path, wcsnlen(system32_path, _countof(system32_path)) + 1); - wcscat_s(sspicli_dll_path, _countof(sspicli_dll_path), L"\\sspicli.dll"); - wcsncpy_s(advapi32_dll_path, _countof(advapi32_dll_path), system32_path, wcsnlen(system32_path, _countof(system32_path)) + 1); - wcscat_s(advapi32_dll_path, _countof(advapi32_dll_path), L"\\advapi32.dll"); - - if (hMod == NULL) { - hMod = LoadLibraryW(sspicli_dll_path); - if (hMod == NULL) - debug3("Failed to retrieve the module handle of sspicli.dll with error %d", GetLastError()); - } - - if (hMod == NULL) - hMod = LoadLibraryW(advapi32_dll_path); - - if (hMod == NULL) { - debug3("Failed to retrieve the module handle of advapi32.dll with error %d", GetLastError()); - return FALSE; - } - - if (func == NULL) - func = (LogonUserExExWType)GetProcAddress(hMod, "LogonUserExExW"); - - if (func == NULL) { - debug3("GetProcAddress of LogonUserExExW failed with error $d.", GetLastError()); - return FALSE; - } - - return func(user_name, domain, password, logon_type, logon_provider, - token_groups, token, logon_sid, profile_buffer, profile_length, quota_limits); -} \ No newline at end of file diff --git a/contrib/win32/win32compat/logonuser.h b/contrib/win32/win32compat/logonuser.h deleted file mode 100644 index 64e54c43a..000000000 --- a/contrib/win32/win32compat/logonuser.h +++ /dev/null @@ -1,14 +0,0 @@ -/* -* Author: Yanbing Wang -* -* Support logon user call on Win32 based operating systems. -* -*/ - -#ifndef LOGONUSER_H -#define LOGONUSER_H - -BOOL -LogonUserExExWHelper(wchar_t *, wchar_t *, wchar_t *, DWORD, DWORD, PTOKEN_GROUPS, PHANDLE, PSID *, PVOID *, LPDWORD, PQUOTA_LIMITS); - -#endif diff --git a/contrib/win32/win32compat/w32api_proxies.c b/contrib/win32/win32compat/w32api_proxies.c new file mode 100644 index 000000000..952facf06 --- /dev/null +++ b/contrib/win32/win32compat/w32api_proxies.c @@ -0,0 +1,199 @@ +/* +* Author: Yanbing Wang +* Support logon user call on Win32 based operating systems. +* +* Author: Manoj Ampalam +* Added generalized wrappers for run time dll loading +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "w32api_proxies.h" +#include "debug.h" + +static wchar_t* +system32_dir() +{ + static wchar_t* s_system32_dir = NULL; + static wchar_t s_system32_path[MAX_PATH + 1] = { 0, }; + + if (s_system32_dir) + return s_system32_dir; + + if (!GetSystemDirectoryW(s_system32_path, _countof(s_system32_path))) { + debug3("GetSystemDirectory failed with error %d", GetLastError()); + return NULL; + } + s_system32_dir = s_system32_path; + + return s_system32_dir; +} + +static HMODULE +load_module(wchar_t* name) +{ + wchar_t module_path[MAX_PATH + 1]; + wchar_t *system32_path, *p; + HMODULE hm; + + if ((system32_path = system32_dir()) == NULL) + return NULL; + + module_path[0] = L'\0'; + if (wcscat_s(module_path, _countof(module_path), system32_path) != 0 || + wcscat_s(module_path, _countof(module_path), L"\\") != 0 || + wcscat_s(module_path, _countof(module_path), name) != 0) + return NULL; + + if ((hm = LoadLibraryW(module_path)) == NULL) + debug3("unable to load module %ls at run time, error: %d", name, GetLastError()); + + return hm; +} + +static HMODULE +load_sspicli() +{ + static HMODULE s_hm_sspicli = NULL; + + if (!s_hm_sspicli) + s_hm_sspicli = load_module(L"sspicli.dll"); + + return s_hm_sspicli; +} + +static HMODULE +load_advapi32() +{ + static HMODULE s_hm_advapi32 = NULL; + + if (!s_hm_advapi32) + s_hm_advapi32 = load_module(L"advapi32.dll"); + + return s_hm_advapi32; +} + +static HMODULE +load_secur32() +{ + static HMODULE s_hm_secur32 = NULL; + + if (!s_hm_secur32) + s_hm_secur32 = load_module(L"secur32.dll"); + + return s_hm_secur32; +} + +FARPROC get_proc_address(HMODULE hm, char* fn) +{ + FARPROC ret = GetProcAddress(hm, fn); + if (!ret) + debug3("GetProcAddress of %s failed with error $d.", fn, GetLastError()); + + return ret; +} + +BOOL +pLogonUserExExW(wchar_t *user_name, wchar_t *domain, wchar_t *password, DWORD logon_type, + DWORD logon_provider, PTOKEN_GROUPS token_groups, PHANDLE token, PSID *logon_sid, + PVOID *profile_buffer, LPDWORD profile_length, PQUOTA_LIMITS quota_limits) +{ + HMODULE hm; + typedef BOOL(WINAPI *LogonUserExExWType)(wchar_t*, wchar_t*, wchar_t*, DWORD, DWORD, PTOKEN_GROUPS, PHANDLE, PSID, PVOID, LPDWORD, PQUOTA_LIMITS); + static LogonUserExExWType s_pLogonUserExExW = NULL; + + if (!s_pLogonUserExExW) { + /* this API is typically found in sspicli, but this dll doesn't exist on some downlevel machines - we fallback to advapi32 then */ + if ((hm = load_sspicli()) == NULL && + (hm = load_advapi32()) == NULL) + return FALSE; + + if ((s_pLogonUserExExW = (LogonUserExExWType)get_proc_address(hm, "LogonUserExExW")) == NULL) + return FALSE; + } + + return s_pLogonUserExExW(user_name, domain, password, logon_type, logon_provider, + token_groups, token, logon_sid, profile_buffer, profile_length, quota_limits); +} + + +BOOLEAN pTranslateNameW(LPCWSTR name, + EXTENDED_NAME_FORMAT account_format, + EXTENDED_NAME_FORMAT desired_name_format, + LPWSTR translated_name, + PULONG psize) +{ + HMODULE hm; + typedef BOOLEAN(WINAPI *TranslateNameWType)(LPCWSTR, EXTENDED_NAME_FORMAT, EXTENDED_NAME_FORMAT, LPWSTR, PULONG); + static TranslateNameWType s_pTranslateNameW = NULL; + + if (!s_pTranslateNameW) { + if ((hm = load_secur32()) == NULL) + return FALSE; + + if ((s_pTranslateNameW = (TranslateNameWType)get_proc_address(hm, "TranslateNameW")) == NULL) + return FALSE; + } + + return s_pTranslateNameW(name, account_format, desired_name_format, translated_name, psize); +} + +NTSTATUS pLsaOpenPolicy(PLSA_UNICODE_STRING system_name, + PLSA_OBJECT_ATTRIBUTES attrib, + ACCESS_MASK access, + PLSA_HANDLE handle) +{ + HMODULE hm; + typedef NTSTATUS(*LsaOpenPolicyType)(PLSA_UNICODE_STRING, PLSA_OBJECT_ATTRIBUTES, ACCESS_MASK, PLSA_HANDLE); + static LsaOpenPolicyType s_pLsaOpenPolicy = NULL; + + if (!s_pLsaOpenPolicy) { + if ((hm = load_advapi32()) == NULL) + return STATUS_ASSERTION_FAILURE; + + if ((s_pLsaOpenPolicy = (LsaOpenPolicyType)get_proc_address(hm, "LsaOpenPolicy")) == NULL) + return STATUS_ASSERTION_FAILURE; + } + + return s_pLsaOpenPolicy(system_name, attrib, access, handle); +} + + +NTSTATUS pLsaAddAccountRights(LSA_HANDLE lsa_h, + PSID psid, + PLSA_UNICODE_STRING rights, + ULONG num_rights) +{ + HMODULE hm; + typedef NTSTATUS(*LsaAddAccountRightsType)(LSA_HANDLE, PSID, PLSA_UNICODE_STRING, ULONG); + static LsaAddAccountRightsType s_pLsaAddAccountRights = NULL; + + if (!s_pLsaAddAccountRights) { + if ((hm = load_advapi32()) == NULL) + return STATUS_ASSERTION_FAILURE; + + if ((s_pLsaAddAccountRights = (LsaAddAccountRightsType)get_proc_address(hm, "LsaAddAccountRights")) == NULL) + return STATUS_ASSERTION_FAILURE; + } + + return s_pLsaAddAccountRights(lsa_h, psid, rights, num_rights); +} diff --git a/contrib/win32/win32compat/w32api_proxies.h b/contrib/win32/win32compat/w32api_proxies.h new file mode 100644 index 000000000..b7f69099e --- /dev/null +++ b/contrib/win32/win32compat/w32api_proxies.h @@ -0,0 +1,21 @@ +/* +* Author: Yanbing Wang +* +* Support logon user call on Win32 based operating systems. +* +*/ + +#pragma once + +#include +#define SECURITY_WIN32 +#include +#include + +BOOL pLogonUserExExW(wchar_t *, wchar_t *, wchar_t *, DWORD, DWORD, PTOKEN_GROUPS, PHANDLE, PSID *, PVOID *, LPDWORD, PQUOTA_LIMITS); +BOOLEAN pTranslateNameW(LPCWSTR, EXTENDED_NAME_FORMAT, EXTENDED_NAME_FORMAT, LPWSTR, PULONG); +NTSTATUS pLsaOpenPolicy(PLSA_UNICODE_STRING, PLSA_OBJECT_ATTRIBUTES, ACCESS_MASK, PLSA_HANDLE); +NTSTATUS pLsaAddAccountRights(LSA_HANDLE, PSID, PLSA_UNICODE_STRING, ULONG); + + + diff --git a/contrib/win32/win32compat/win32_usertoken_utils.c b/contrib/win32/win32compat/win32_usertoken_utils.c index 61fbf3ef2..b854534e2 100644 --- a/contrib/win32/win32compat/win32_usertoken_utils.c +++ b/contrib/win32/win32compat/win32_usertoken_utils.c @@ -43,7 +43,7 @@ #include #include "inc\utf.h" -#include "logonuser.h" +#include "w32api_proxies.h" #include #include #include @@ -134,26 +134,9 @@ generate_s4u_user_token(wchar_t* user_cpn, int impersonation) { if (domain_user) { /* assemble the path to the name translation library */ - wchar_t library_path[MAX_PATH + 1]; - if (GetSystemDirectoryW(library_path, ARRAYSIZE(library_path)) == 0) { - debug3("%s: GetSystemDirectoryW() failed name translation: %d", __FUNCTION__, GetLastError()); - goto done; - } - wcscat_s(library_path, ARRAYSIZE(library_path), L"\\secur32.dll"); - - /* dynamically load name translation function to support static linking to onecore */ - typedef (*TranslateNameWFunc)(_In_ LPCWSTR lpAccountName, - _In_ EXTENDED_NAME_FORMAT AccountNameFormat, _In_ EXTENDED_NAME_FORMAT DesiredNameFormat, - _Out_writes_to_opt_(*nSize, *nSize) LPWSTR lpTranslatedName, _Inout_ PULONG nSize); - HMODULE library = LoadLibraryW(library_path); - TranslateNameWFunc LocalTranslateNameW = NULL; - - /* lookup the upn for the user */ WCHAR domain_upn[MAX_UPN_LEN + 1]; ULONG domain_upn_len = ARRAYSIZE(domain_upn); - if (library == NULL || (LocalTranslateNameW = (TranslateNameWFunc) GetProcAddress(library, "TranslateNameW")) == NULL || - LocalTranslateNameW(user_cpn, NameSamCompatible, - NameUserPrincipal, domain_upn, &domain_upn_len) == 0) { + if (pTranslateNameW(user_cpn, NameSamCompatible, NameUserPrincipal, domain_upn, &domain_upn_len) == 0) { /* upn lookup failed so resort to attempting samcompatiblename */ debug3("%s: Unable to discover upn for user '%s': %d", @@ -360,7 +343,7 @@ get_user_token(char* user, int impersonation) { if ((token = generate_s4u_user_token(user_utf16, impersonation)) == 0) { debug3("unable to generate token for user %ls", user_utf16); /* work around for https://github.com/PowerShell/Win32-OpenSSH/issues/727 by doing a fake login */ - LogonUserExExWHelper(L"FakeUser", L"FakeDomain", L"FakePasswd", + pLogonUserExExW(L"FakeUser", L"FakeDomain", L"FakePasswd", LOGON32_LOGON_NETWORK_CLEARTEXT, LOGON32_PROVIDER_DEFAULT, NULL, &token, NULL, NULL, NULL, NULL); if ((token = generate_s4u_user_token(user_utf16, impersonation)) == 0) { error("unable to generate token on 2nd attempt for user %ls", user_utf16); @@ -473,9 +456,8 @@ AddSidMappingToLsa(PUNICODE_STRING domain_name, error("LsaManageSidNameMapping failed with ntstatus: %d \n", status); } - /* TODO - Free p_output */ - /*if (p_output) - LsaFreeMemory(p_output);*/ + if (p_output) + LsaFreeMemory(p_output); return ret; } @@ -547,6 +529,7 @@ HANDLE generate_sshd_virtual_token() SID_IDENTIFIER_AUTHORITY nt_authority = SECURITY_NT_AUTHORITY; UNICODE_STRING domain, group, account; WCHAR va_name[32]; /* enough to accomodate sshd_123457890 */ + LSA_HANDLE lsa_policy = NULL; PSID sid_domain = NULL, sid_group = NULL, sid_user = NULL; HANDLE va_token = 0, va_token_restricted = 0; @@ -617,12 +600,32 @@ HANDLE generate_sshd_virtual_token() if (AddSidMappingToLsa(&domain, &account, sid_user) != 0) goto cleanup; + /* assign service logon privilege to virtual account */ + { + LSA_OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING svcLogonRight; + NTSTATUS lsa_ret; + + ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); + if ((lsa_ret = LsaOpenPolicy(NULL, &ObjectAttributes, + POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, + &lsa_policy )) != STATUS_SUCCESS) { + error("%s: unable to open policy handle, error: %d", __FUNCTION__, LsaNtStatusToWinError(lsa_ret)); + goto cleanup; + } + InitUnicodeString(&svcLogonRight, L"SeServiceLogonRight"); + if ((lsa_ret = LsaAddAccountRights(lsa_policy, sid_user, &svcLogonRight, 1)) != STATUS_SUCCESS) { + error("%s: unable to assign SE_SERVICE_LOGON_NAME privilege, error: %d", __FUNCTION__, LsaNtStatusToWinError(lsa_ret)); + goto cleanup; + } + } + /* Logon virtual and create token */ - if (!LogonUserExExWHelper( + if (!pLogonUserExExW( va_name, VIRTUALUSER_DOMAIN, L"", - LOGON32_LOGON_INTERACTIVE, + LOGON32_LOGON_SERVICE, LOGON32_PROVIDER_VIRTUAL, NULL, &va_token, @@ -649,6 +652,8 @@ cleanup: FreeSid(sid_user); if (sid_group) FreeSid(sid_group); + if (lsa_policy) + LsaClose(lsa_policy); return va_token_restricted; }