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:
Manoj Ampalam 2018-05-28 22:03:33 -07:00 committed by GitHub
parent 471b76dbd5
commit 9ff97f6106
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 782 additions and 671 deletions

View File

@ -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 {

View File

@ -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" />

View File

@ -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" />

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}