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
This commit is contained in:
parent
471b76dbd5
commit
9ff97f6106
|
@ -57,11 +57,8 @@
|
|||
#include "authfd.h"
|
||||
|
||||
#ifdef WINDOWS
|
||||
#define SECURITY_WIN32
|
||||
#include <security.h>
|
||||
#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 {
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level1</WarningLevel>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
|
@ -223,7 +223,7 @@
|
|||
<PreprocessorDefinitions>_LIB;USE_MSCNG;_WIN32_WINNT=0x600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level1</WarningLevel>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<ControlFlowGuard>Guard</ControlFlowGuard>
|
||||
|
@ -237,7 +237,7 @@
|
|||
<PreprocessorDefinitions>_LIB;USE_MSCNG;_WIN32_WINNT=0x600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level1</WarningLevel>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<Optimization>Disabled</Optimization>
|
||||
|
@ -254,7 +254,7 @@
|
|||
<PreprocessorDefinitions>_LIB;USE_MSCNG;_WIN32_WINNT=0x600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level1</WarningLevel>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<Optimization>Disabled</Optimization>
|
||||
|
@ -271,7 +271,7 @@
|
|||
<PreprocessorDefinitions>_LIB;USE_MSCNG;_WIN32_WINNT=0x600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level1</WarningLevel>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<Optimization>Disabled</Optimization>
|
||||
|
@ -290,7 +290,7 @@
|
|||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\misc.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\signal_sigalrm.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\signal_sigchld.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\logonuser.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32api_proxies.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\win32_usertoken_utils.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32log.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\pwd.c" />
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tnnet.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\utf.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\spawn.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32api_proxies.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\win32_usertoken_utils.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* Author: Yanbing Wang <yawang@microsoft.com>
|
||||
*
|
||||
* 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 <Windows.h>
|
||||
#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);
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
/*
|
||||
* Author: Yanbing Wang <yawang@microsoft.com>
|
||||
*
|
||||
* 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
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Author: Yanbing Wang <yawang@microsoft.com>
|
||||
* Support logon user call on Win32 based operating systems.
|
||||
*
|
||||
* Author: Manoj Ampalam <manojamp@microsoft.com>
|
||||
* 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);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Author: Yanbing Wang <yawang@microsoft.com>
|
||||
*
|
||||
* Support logon user call on Win32 based operating systems.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#define SECURITY_WIN32
|
||||
#include <security.h>
|
||||
#include <Ntsecapi.h>
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
|
@ -43,7 +43,7 @@
|
|||
#include <security.h>
|
||||
|
||||
#include "inc\utf.h"
|
||||
#include "logonuser.h"
|
||||
#include "w32api_proxies.h"
|
||||
#include <Ntsecapi.h>
|
||||
#include <Strsafe.h>
|
||||
#include <sddl.h>
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue