diff --git a/base/system/winlogon/CMakeLists.txt b/base/system/winlogon/CMakeLists.txt index 64d3fef8b57..06ff9241c91 100644 --- a/base/system/winlogon/CMakeLists.txt +++ b/base/system/winlogon/CMakeLists.txt @@ -11,6 +11,7 @@ list(APPEND SOURCE rpcserver.c sas.c screensaver.c + security.c setup.c shutdown.c winlogon.c diff --git a/base/system/winlogon/sas.c b/base/system/winlogon/sas.c index 20298e84b90..a78733b7771 100644 --- a/base/system/winlogon/sas.c +++ b/base/system/winlogon/sas.c @@ -428,87 +428,6 @@ PlayLogonSound( CloseHandle(hThread); } -static BOOL -AllowWinstaAccess(PWLSESSION Session) -{ - BOOL bSuccess = FALSE; - DWORD dwIndex; - DWORD dwLength = 0; - PTOKEN_GROUPS ptg = NULL; - PSID psid; - TOKEN_STATISTICS Stats; - DWORD cbStats; - DWORD ret; - - // Get required buffer size and allocate the TOKEN_GROUPS buffer. - - if (!GetTokenInformation(Session->UserToken, - TokenGroups, - ptg, - 0, - &dwLength)) - { - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) - return FALSE; - - ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength); - if (ptg == NULL) - return FALSE; - } - - // Get the token group information from the access token. - if (!GetTokenInformation(Session->UserToken, - TokenGroups, - ptg, - dwLength, - &dwLength)) - { - goto Cleanup; - } - - // Loop through the groups to find the logon SID. - - for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++) - { - if ((ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) - == SE_GROUP_LOGON_ID) - { - psid = ptg->Groups[dwIndex].Sid; - break; - } - } - - dwLength = GetLengthSid(psid); - - if (!GetTokenInformation(Session->UserToken, - TokenStatistics, - &Stats, - sizeof(TOKEN_STATISTICS), - &cbStats)) - { - WARN("Couldn't get Authentication id from user token!\n"); - goto Cleanup; - } - - AddAceToWindowStation(Session->InteractiveWindowStation, psid); - - ret = SetWindowStationUser(Session->InteractiveWindowStation, - &Stats.AuthenticationId, - psid, - dwLength); - TRACE("SetWindowStationUser returned 0x%x\n", ret); - - bSuccess = TRUE; - -Cleanup: - - // Free the buffer for the token groups. - if (ptg != NULL) - HeapFree(GetProcessHeap(), 0, (LPVOID)ptg); - - return bSuccess; -} - static VOID RestoreAllConnections(PWLSESSION Session) @@ -633,7 +552,12 @@ HandleLogon( goto cleanup; } - AllowWinstaAccess(Session); + /* Allow winsta and desktop access for this session */ + if (!AllowAccessOnSession(Session)) + { + WARN("WL: AllowAccessOnSession() failed to give winsta & desktop access for this session\n"); + goto cleanup; + } /* Connect remote resources */ RestoreAllConnections(Session); diff --git a/base/system/winlogon/security.c b/base/system/winlogon/security.c new file mode 100644 index 00000000000..26d3935fe2e --- /dev/null +++ b/base/system/winlogon/security.c @@ -0,0 +1,1314 @@ +/* + * PROJECT: ReactOS Winlogon + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Security utility infrastructure implementation of Winlogon + * COPYRIGHT: Copyright 2022 George Bișoc + */ + +/* INCLUDES *****************************************************************/ + +#include "winlogon.h" + +/* DEFINES ******************************************************************/ + +#define DESKTOP_ALL (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | \ + DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | \ + DESKTOP_JOURNALPLAYBACK | DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | \ + DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_REQUIRED) + +#define DESKTOP_ADMINS_LIMITED (DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | \ + DESKTOP_CREATEWINDOW | DESKTOP_CREATEMENU | DESKTOP_ENUMERATE) + +#define DESKTOP_INTERACTIVE_LIMITED (STANDARD_RIGHTS_READ | DESKTOP_ENUMERATE | \ + DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW) + +#define DESKTOP_WINLOGON_ADMINS_LIMITED (STANDARD_RIGHTS_REQUIRED | DESKTOP_ENUMERATE) + +#define WINSTA_ALL (WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | \ + WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | \ + WINSTA_WRITEATTRIBUTES | WINSTA_ACCESSGLOBALATOMS | \ + WINSTA_EXITWINDOWS | WINSTA_ENUMERATE | WINSTA_READSCREEN | \ + STANDARD_RIGHTS_REQUIRED) + +#define WINSTA_ADMINS_LIMITED (WINSTA_READATTRIBUTES | WINSTA_ENUMERATE) + +#define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | \ + GENERIC_EXECUTE | GENERIC_ALL) + +/* GLOBALS ******************************************************************/ + +static SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; + +/* FUNCTIONS ****************************************************************/ + +/** + * @brief + * Converts an absolute security descriptor to a self-relative + * format. + * + * @param[in] AbsoluteSd + * A pointer to an absolute security descriptor to be + * converted. + * + * @return + * Returns a pointer to a converted security descriptor in + * self-relative format. If the function fails, NULL is returned + * otherwise. + * + * @remarks + * The function allocates the security descriptor buffer in memory + * heap, the caller is entirely responsible for freeing such buffer + * from when it's no longer needed. + */ +PSECURITY_DESCRIPTOR +ConvertToSelfRelative( + _In_ PSECURITY_DESCRIPTOR AbsoluteSd) +{ + PSECURITY_DESCRIPTOR RelativeSd; + DWORD DescriptorLength = 0; + + /* Determine the size for our buffer to allocate */ + if (!MakeSelfRelativeSD(AbsoluteSd, NULL, &DescriptorLength) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + ERR("ConvertToSelfRelative(): Unexpected error code (error code %lu -- must be ERROR_INSUFFICIENT_BUFFER)\n", GetLastError()); + return NULL; + } + + /* Allocate the buffer now */ + RelativeSd = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + DescriptorLength); + if (RelativeSd == NULL) + { + ERR("ConvertToSelfRelative(): Failed to allocate buffer for relative SD!\n"); + return NULL; + } + + /* Convert the security descriptor now */ + if (!MakeSelfRelativeSD(AbsoluteSd, RelativeSd, &DescriptorLength)) + { + ERR("ConvertToSelfRelative(): Failed to convert the security descriptor to a self relative format (error code %lu)\n", GetLastError()); + RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd); + return NULL; + } + + return RelativeSd; +} + +/** + * @brief + * Creates a security descriptor for the default + * window station upon its creation. + * + * @param[out] WinstaSd + * A pointer to a created security descriptor for + * the window station. + * + * @return + * Returns TRUE if the function has successfully + * created the security descriptor, FALSE otherwise. + */ +BOOL +CreateWinstaSecurity( + _Out_ PSECURITY_DESCRIPTOR *WinstaSd) +{ + BOOL Success = FALSE; + SECURITY_DESCRIPTOR AbsoluteSd; + PSECURITY_DESCRIPTOR RelativeSd = NULL; + PSID WinlogonSid = NULL, AdminsSid = NULL; + DWORD DaclSize; + PACL Dacl; + + /* Create the Winlogon SID */ + if (!AllocateAndInitializeSid(&NtAuthority, + 1, + SECURITY_LOCAL_SYSTEM_RID, + 0, 0, 0, 0, 0, 0, 0, + &WinlogonSid)) + { + ERR("CreateWinstaSecurity(): Failed to create the Winlogon SID (error code %lu)\n", GetLastError()); + return FALSE; + } + + /* Create the admins SID */ + if (!AllocateAndInitializeSid(&NtAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &AdminsSid)) + { + ERR("CreateWinstaSecurity(): Failed to create the admins SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* + * Build up the DACL size. This includes a number + * of four ACEs of two different SIDs. The first two + * ACEs give both window station and generic access + * to Winlogon, the last two give limited window station + * and desktop access to admins. + */ + DaclSize = sizeof(ACL) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid); + + /* Allocate the DACL now */ + Dacl = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + DaclSize); + if (Dacl == NULL) + { + ERR("CreateWinstaSecurity(): Failed to allocate memory buffer for DACL!\n"); + goto Quit; + } + + /* Initialize it */ + if (!InitializeAcl(Dacl, DaclSize, ACL_REVISION)) + { + ERR("CreateWinstaSecurity(): Failed to initialize DACL (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* First ACE -- give full winsta access to Winlogon */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + NO_PROPAGATE_INHERIT_ACE, + WINSTA_ALL, + WinlogonSid)) + { + ERR("CreateWinstaSecurity(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Second ACE -- give full generic access to Winlogon */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, + GENERIC_ACCESS, + WinlogonSid)) + { + ERR("CreateWinstaSecurity(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Third ACE -- give limited winsta access to admins */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + NO_PROPAGATE_INHERIT_ACE, + WINSTA_ADMINS_LIMITED, + AdminsSid)) + { + ERR("CreateWinstaSecurity(): Failed to set ACE for admins (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Fourth ACE -- give limited desktop access to admins */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, + DESKTOP_ADMINS_LIMITED, + AdminsSid)) + { + ERR("CreateWinstaSecurity(): Failed to set ACE for admins (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Initialize the security descriptor */ + if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION)) + { + ERR("CreateWinstaSecurity(): Failed to initialize absolute security descriptor (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Set the DACL to the descriptor */ + if (!SetSecurityDescriptorDacl(&AbsoluteSd, TRUE, Dacl, FALSE)) + { + ERR("CreateWinstaSecurity(): Failed to set up DACL to absolute security descriptor (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Convert it to self-relative format */ + RelativeSd = ConvertToSelfRelative(&AbsoluteSd); + if (RelativeSd == NULL) + { + ERR("CreateWinstaSecurity(): Failed to convert security descriptor to self relative format!\n"); + goto Quit; + } + + /* Give the descriptor to the caller */ + *WinstaSd = RelativeSd; + Success = TRUE; + +Quit: + if (WinlogonSid != NULL) + { + FreeSid(WinlogonSid); + } + + if (AdminsSid != NULL) + { + FreeSid(AdminsSid); + } + + if (Dacl != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl); + } + + if (Success == FALSE) + { + if (RelativeSd != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd); + } + } + + return Success; +} + +/** + * @brief + * Creates a security descriptor for the default + * application desktop upon its creation. + * + * @param[out] ApplicationDesktopSd + * A pointer to a created security descriptor for + * the application desktop. + * + * @return + * Returns TRUE if the function has successfully + * created the security descriptor, FALSE otherwise. + */ +BOOL +CreateApplicationDesktopSecurity( + _Out_ PSECURITY_DESCRIPTOR *ApplicationDesktopSd) +{ + BOOL Success = FALSE; + SECURITY_DESCRIPTOR AbsoluteSd; + PSECURITY_DESCRIPTOR RelativeSd = NULL; + PSID WinlogonSid = NULL, AdminsSid = NULL; + DWORD DaclSize; + PACL Dacl; + + /* Create the Winlogon SID */ + if (!AllocateAndInitializeSid(&NtAuthority, + 1, + SECURITY_LOCAL_SYSTEM_RID, + 0, 0, 0, 0, 0, 0, 0, + &WinlogonSid)) + { + ERR("CreateApplicationDesktopSecurity(): Failed to create the Winlogon SID (error code %lu)\n", GetLastError()); + return FALSE; + } + + /* Create the admins SID */ + if (!AllocateAndInitializeSid(&NtAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &AdminsSid)) + { + ERR("CreateApplicationDesktopSecurity(): Failed to create the admins SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* + * Build up the DACL size. This includes a number + * of two ACEs of two different SIDs. The first ACE + * gives full access to Winlogon, the last one gives + * limited desktop access to admins. + */ + DaclSize = sizeof(ACL) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid); + + /* Allocate the DACL now */ + Dacl = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + DaclSize); + if (Dacl == NULL) + { + ERR("CreateApplicationDesktopSecurity(): Failed to allocate memory buffer for DACL!\n"); + goto Quit; + } + + /* Initialize it */ + if (!InitializeAcl(Dacl, DaclSize, ACL_REVISION)) + { + ERR("CreateApplicationDesktopSecurity(): Failed to initialize DACL (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* First ACE -- Give full desktop power to Winlogon */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + 0, + DESKTOP_ALL, + WinlogonSid)) + { + ERR("CreateApplicationDesktopSecurity(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Second ACE -- Give limited desktop power to admins */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + 0, + DESKTOP_ADMINS_LIMITED, + AdminsSid)) + { + ERR("CreateApplicationDesktopSecurity(): Failed to set ACE for admins (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Initialize the security descriptor */ + if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION)) + { + ERR("CreateApplicationDesktopSecurity(): Failed to initialize absolute security descriptor (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Set the DACL to the descriptor */ + if (!SetSecurityDescriptorDacl(&AbsoluteSd, TRUE, Dacl, FALSE)) + { + ERR("CreateApplicationDesktopSecurity(): Failed to set up DACL to absolute security descriptor (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Conver it to self-relative format */ + RelativeSd = ConvertToSelfRelative(&AbsoluteSd); + if (RelativeSd == NULL) + { + ERR("CreateApplicationDesktopSecurity(): Failed to convert security descriptor to self relative format!\n"); + goto Quit; + } + + /* Give the descriptor to the caller */ + *ApplicationDesktopSd = RelativeSd; + Success = TRUE; + +Quit: + if (WinlogonSid != NULL) + { + FreeSid(WinlogonSid); + } + + if (AdminsSid != NULL) + { + FreeSid(AdminsSid); + } + + if (Dacl != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl); + } + + if (Success == FALSE) + { + if (RelativeSd != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd); + } + } + + return Success; +} + +/** + * @brief + * Creates a security descriptor for the default + * Winlogon desktop. This descriptor serves as a + * security measure for the winlogon desktop so + * that only Winlogon itself (and admins) can + * interact with it. + * + * @param[out] WinlogonDesktopSd + * A pointer to a created security descriptor for + * the Winlogon desktop. + * + * @return + * Returns TRUE if the function has successfully + * created the security descriptor, FALSE otherwise. + */ +BOOL +CreateWinlogonDesktopSecurity( + _Out_ PSECURITY_DESCRIPTOR *WinlogonDesktopSd) +{ + BOOL Success = FALSE; + SECURITY_DESCRIPTOR AbsoluteSd; + PSECURITY_DESCRIPTOR RelativeSd = NULL; + PSID WinlogonSid = NULL, AdminsSid = NULL; + DWORD DaclSize; + PACL Dacl; + + /* Create the Winlogon SID */ + if (!AllocateAndInitializeSid(&NtAuthority, + 1, + SECURITY_LOCAL_SYSTEM_RID, + 0, 0, 0, 0, 0, 0, 0, + &WinlogonSid)) + { + ERR("CreateWinlogonDesktopSecurity(): Failed to create the Winlogon SID (error code %lu)\n", GetLastError()); + return FALSE; + } + + /* Create the admins SID */ + if (!AllocateAndInitializeSid(&NtAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &AdminsSid)) + { + ERR("CreateWinlogonDesktopSecurity(): Failed to create the admins SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* + * Build up the DACL size. This includes a number + * of two ACEs of two different SIDs. The first ACE + * gives full access to Winlogon, the last one gives + * limited desktop access to admins. + */ + DaclSize = sizeof(ACL) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid); + + /* Allocate the DACL now */ + Dacl = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + DaclSize); + if (Dacl == NULL) + { + ERR("CreateWinlogonDesktopSecurity(): Failed to allocate memory buffer for DACL!\n"); + goto Quit; + } + + /* Initialize it */ + if (!InitializeAcl(Dacl, DaclSize, ACL_REVISION)) + { + ERR("CreateWinlogonDesktopSecurity(): Failed to initialize DACL (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* First ACE -- Give full desktop access to Winlogon */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + 0, + DESKTOP_ALL, + WinlogonSid)) + { + ERR("CreateWinlogonDesktopSecurity(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Second ACE -- Give limited desktop access to admins */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + 0, + DESKTOP_WINLOGON_ADMINS_LIMITED, + AdminsSid)) + { + ERR("CreateWinlogonDesktopSecurity(): Failed to set ACE for admins (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Initialize the security descriptor */ + if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION)) + { + ERR("CreateWinlogonDesktopSecurity(): Failed to initialize absolute security descriptor (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Set the DACL to the descriptor */ + if (!SetSecurityDescriptorDacl(&AbsoluteSd, TRUE, Dacl, FALSE)) + { + ERR("CreateWinlogonDesktopSecurity(): Failed to set up DACL to absolute security descriptor (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Conver it to self-relative format */ + RelativeSd = ConvertToSelfRelative(&AbsoluteSd); + if (RelativeSd == NULL) + { + ERR("CreateWinlogonDesktopSecurity(): Failed to convert security descriptor to self relative format!\n"); + goto Quit; + } + + /* Give the descriptor to the caller */ + *WinlogonDesktopSd = RelativeSd; + Success = TRUE; + +Quit: + if (WinlogonSid != NULL) + { + FreeSid(WinlogonSid); + } + + if (AdminsSid != NULL) + { + FreeSid(AdminsSid); + } + + if (Dacl != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl); + } + + if (Success == FALSE) + { + if (RelativeSd != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd); + } + } + + return Success; +} + +/** + * @brief + * Creates a security descriptor for the screen + * saver desktop. + * + * @param[out] ScreenSaverDesktopSd + * A pointer to a created security descriptor for + * the screen-saver desktop. + * + * @return + * Returns TRUE if the function has successfully + * created the security descriptor, FALSE otherwise. + */ +BOOL +CreateScreenSaverSecurity( + _Out_ PSECURITY_DESCRIPTOR *ScreenSaverDesktopSd) +{ + BOOL Success = FALSE; + SECURITY_DESCRIPTOR AbsoluteSd; + PSECURITY_DESCRIPTOR RelativeSd = NULL; + PSID WinlogonSid = NULL, AdminsSid = NULL, InteractiveSid = NULL; + DWORD DaclSize; + PACL Dacl; + + /* Create the Winlogon SID */ + if (!AllocateAndInitializeSid(&NtAuthority, + 1, + SECURITY_LOCAL_SYSTEM_RID, + 0, 0, 0, 0, 0, 0, 0, + &WinlogonSid)) + { + ERR("CreateScreenSaverSecurity(): Failed to create the Winlogon SID (error code %lu)\n", GetLastError()); + return FALSE; + } + + /* Create the admins SID */ + if (!AllocateAndInitializeSid(&NtAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &AdminsSid)) + { + ERR("CreateScreenSaverSecurity(): Failed to create the admins SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Create the interactive logon SID */ + if (!AllocateAndInitializeSid(&NtAuthority, + 1, + SECURITY_INTERACTIVE_RID, + 0, 0, 0, 0, 0, 0, 0, + &InteractiveSid)) + { + ERR("CreateScreenSaverSecurity(): Failed to create the interactive SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* + * Build up the DACL size. This includes a number + * of three ACEs of three different SIDs. The first ACE + * gives full access to Winlogon, the second one gives + * limited desktop access to admins and the last one + * gives full desktop access to users who have logged in + * interactively. + */ + DaclSize = sizeof(ACL) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(InteractiveSid); + + /* Allocate the DACL now */ + Dacl = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + DaclSize); + if (Dacl == NULL) + { + ERR("CreateScreenSaverSecurity(): Failed to allocate memory buffer for DACL!\n"); + goto Quit; + } + + /* Initialize it */ + if (!InitializeAcl(Dacl, DaclSize, ACL_REVISION)) + { + ERR("CreateScreenSaverSecurity(): Failed to initialize DACL (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* First ACE -- Give full desktop access to Winlogon */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + 0, + DESKTOP_ALL, + WinlogonSid)) + { + ERR("CreateScreenSaverSecurity(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Second ACE -- Give limited desktop access to admins */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + NO_PROPAGATE_INHERIT_ACE, + DESKTOP_ADMINS_LIMITED, + AdminsSid)) + { + ERR("CreateScreenSaverSecurity(): Failed to set ACE for admins (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Third ACE -- Give full desktop access to interactive logon users */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + NO_PROPAGATE_INHERIT_ACE, + DESKTOP_INTERACTIVE_LIMITED, + InteractiveSid)) + { + ERR("CreateScreenSaverSecurity(): Failed to set ACE for interactive SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Initialize the security descriptor */ + if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION)) + { + ERR("CreateScreenSaverSecurity(): Failed to initialize absolute security descriptor (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Set the DACL to the descriptor */ + if (!SetSecurityDescriptorDacl(&AbsoluteSd, TRUE, Dacl, FALSE)) + { + ERR("CreateScreenSaverSecurity(): Failed to set up DACL to absolute security descriptor (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Conver it to self-relative format */ + RelativeSd = ConvertToSelfRelative(&AbsoluteSd); + if (RelativeSd == NULL) + { + ERR("CreateScreenSaverSecurity(): Failed to convert security descriptor to self relative format!\n"); + goto Quit; + } + + /* Give the descriptor to the caller */ + *ScreenSaverDesktopSd = RelativeSd; + Success = TRUE; + +Quit: + if (WinlogonSid != NULL) + { + FreeSid(WinlogonSid); + } + + if (AdminsSid != NULL) + { + FreeSid(AdminsSid); + } + + if (InteractiveSid != NULL) + { + FreeSid(InteractiveSid); + } + + if (Dacl != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl); + } + + if (Success == FALSE) + { + if (RelativeSd != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd); + } + } + + return Success; +} + +/** + * @brief + * Assigns access to the specific logon user to + * the default window station. Such access is + * given to the user when it has logged in. + * + * @param[in] WinSta + * A handle to a window station where the + * user is given access to it. + * + * @param[in] LogonSid + * A pointer to a logon SID that represents + * the logged in user in question. + * + * @return + * Returns TRUE if the function has successfully + * assigned access to the user, FALSE otherwise. + */ +BOOL +AllowWinstaAccessToUser( + _In_ HWINSTA WinSta, + _In_ PSID LogonSid) +{ + BOOL Success = FALSE; + SECURITY_DESCRIPTOR AbsoluteSd; + PSECURITY_DESCRIPTOR RelativeSd = NULL; + PSID WinlogonSid = NULL, AdminsSid = NULL, InteractiveSid = NULL; + SECURITY_INFORMATION SecurityInformation; + DWORD DaclSize; + PACL Dacl; + + /* Create the Winlogon SID */ + if (!AllocateAndInitializeSid(&NtAuthority, + 1, + SECURITY_LOCAL_SYSTEM_RID, + 0, 0, 0, 0, 0, 0, 0, + &WinlogonSid)) + { + ERR("AllowWinstaAccessToUser(): Failed to create the Winlogon SID (error code %lu)\n", GetLastError()); + return FALSE; + } + + /* Create the admins SID */ + if (!AllocateAndInitializeSid(&NtAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &AdminsSid)) + { + ERR("AllowWinstaAccessToUser(): Failed to create the admins SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Create the interactive logon SID */ + if (!AllocateAndInitializeSid(&NtAuthority, + 1, + SECURITY_INTERACTIVE_RID, + 0, 0, 0, 0, 0, 0, 0, + &InteractiveSid)) + { + ERR("AllowWinstaAccessToUser(): Failed to create the interactive SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* + * Build up the DACL size. This includes a number + * of eight ACEs of four different SIDs. The first ACE + * gives full winsta access to Winlogon, the second one gives + * generic access to Winlogon. Such approach is the same + * for both interactive logon users and logon user as well. + * Only admins are given limited powers. + */ + DaclSize = sizeof(ACL) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(InteractiveSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(InteractiveSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(LogonSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(LogonSid); + + /* Allocate the DACL now */ + Dacl = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + DaclSize); + if (Dacl == NULL) + { + ERR("AllowWinstaAccessToUser(): Failed to allocate memory buffer for DACL!\n"); + goto Quit; + } + + /* Initialize it */ + if (!InitializeAcl(Dacl, DaclSize, ACL_REVISION)) + { + ERR("AllowWinstaAccessToUser(): Failed to initialize DACL (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* First ACE -- Give full winsta access to Winlogon */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + NO_PROPAGATE_INHERIT_ACE, + WINSTA_ALL, + WinlogonSid)) + { + ERR("AllowWinstaAccessToUser(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Second ACE -- Give generic access to Winlogon */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, + GENERIC_ACCESS, + WinlogonSid)) + { + ERR("AllowWinstaAccessToUser(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Third ACE -- Give limited winsta access to admins */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + NO_PROPAGATE_INHERIT_ACE, + WINSTA_ADMINS_LIMITED, + AdminsSid)) + { + ERR("AllowWinstaAccessToUser(): Failed to set ACE for admins (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Fourth ACE -- Give limited desktop access to admins */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, + DESKTOP_ADMINS_LIMITED, + AdminsSid)) + { + ERR("AllowWinstaAccessToUser(): Failed to set ACE for admins (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Fifth ACE -- Give full winsta access to interactive logon users */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + NO_PROPAGATE_INHERIT_ACE, + WINSTA_ALL, + InteractiveSid)) + { + ERR("AllowWinstaAccessToUser(): Failed to set ACE for interactive SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Sixth ACE -- Give generic access to interactive logon users */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, + GENERIC_ACCESS, + InteractiveSid)) + { + ERR("AllowWinstaAccessToUser(): Failed to set ACE for interactive SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Seventh ACE -- Give full winsta access to logon user */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + NO_PROPAGATE_INHERIT_ACE, + WINSTA_ALL, + LogonSid)) + { + ERR("AllowWinstaAccessToUser(): Failed to set ACE for logon user SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Eighth ACE -- Give generic access to logon user */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, + GENERIC_ACCESS, + LogonSid)) + { + ERR("AllowWinstaAccessToUser(): Failed to set ACE for logon user SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Initialize the security descriptor */ + if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION)) + { + ERR("AllowWinstaAccessToUser(): Failed to initialize absolute security descriptor (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Set the DACL to descriptor */ + if (!SetSecurityDescriptorDacl(&AbsoluteSd, TRUE, Dacl, FALSE)) + { + ERR("AllowWinstaAccessToUser(): Failed to set up DACL to absolute security descriptor (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Convert it to self-relative format */ + RelativeSd = ConvertToSelfRelative(&AbsoluteSd); + if (RelativeSd == NULL) + { + ERR("AllowWinstaAccessToUser(): Failed to convert security descriptor to self relative format!\n"); + goto Quit; + } + + /* Set new winsta security based on this descriptor */ + SecurityInformation = DACL_SECURITY_INFORMATION; + if (!SetUserObjectSecurity(WinSta, &SecurityInformation, RelativeSd)) + { + ERR("AllowWinstaAccessToUser(): Failed to set window station security descriptor (error code %lu)\n", GetLastError()); + goto Quit; + } + + Success = TRUE; + +Quit: + if (WinlogonSid != NULL) + { + FreeSid(WinlogonSid); + } + + if (AdminsSid != NULL) + { + FreeSid(AdminsSid); + } + + if (InteractiveSid != NULL) + { + FreeSid(InteractiveSid); + } + + if (Dacl != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl); + } + + if (RelativeSd != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd); + } + + return Success; +} + +/** + * @brief + * Assigns access to the specific logon user to + * the default desktop. Such access is given to + * the user when it has logged in. + * + * @param[in] Desktop + * A handle to a desktop where the user + * is given access to it. + * + * @param[in] LogonSid + * A pointer to a logon SID that represents + * the logged in user in question. + * + * @return + * Returns TRUE if the function has successfully + * assigned access to the user, FALSE otherwise. + */ +BOOL +AllowDesktopAccessToUser( + _In_ HDESK Desktop, + _In_ PSID LogonSid) +{ + BOOL Success = FALSE; + SECURITY_DESCRIPTOR AbsoluteSd; + PSECURITY_DESCRIPTOR RelativeSd = NULL; + PSID WinlogonSid = NULL, AdminsSid = NULL, InteractiveSid = NULL; + SECURITY_INFORMATION SecurityInformation; + DWORD DaclSize; + PACL Dacl; + + /* Create the Winlogon SID */ + if (!AllocateAndInitializeSid(&NtAuthority, + 1, + SECURITY_LOCAL_SYSTEM_RID, + 0, 0, 0, 0, 0, 0, 0, + &WinlogonSid)) + { + ERR("AllowDesktopAccessToUser(): Failed to create the Winlogon SID (error code %lu)\n", GetLastError()); + return FALSE; + } + + /* Create the admins SID */ + if (!AllocateAndInitializeSid(&NtAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &AdminsSid)) + { + ERR("AllowDesktopAccessToUser(): Failed to create the admins SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Create the interactive logon SID */ + if (!AllocateAndInitializeSid(&NtAuthority, + 1, + SECURITY_INTERACTIVE_RID, + 0, 0, 0, 0, 0, 0, 0, + &InteractiveSid)) + { + ERR("AllowDesktopAccessToUser(): Failed to create the interactive SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* + * Build up the DACL size. This includes a number + * of four ACEs of four different SIDs. The first ACE + * gives full desktop access to Winlogon, the second one gives + * generic limited desktop access to admins. The last two give + * full power to both interactive logon users and logon user as + * well. + */ + DaclSize = sizeof(ACL) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(WinlogonSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(AdminsSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(InteractiveSid) + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(LogonSid); + + /* Allocate the DACL now */ + Dacl = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + DaclSize); + if (Dacl == NULL) + { + ERR("AllowDesktopAccessToUser(): Failed to allocate memory buffer for DACL!\n"); + goto Quit; + } + + /* Initialize it */ + if (!InitializeAcl(Dacl, DaclSize, ACL_REVISION)) + { + ERR("AllowDesktopAccessToUser(): Failed to initialize DACL (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* First ACE -- Give full desktop access to Winlogon */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + 0, + DESKTOP_ALL, + WinlogonSid)) + { + ERR("AllowDesktopAccessToUser(): Failed to set ACE for Winlogon (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Second ACE -- Give limited desktop access to admins */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + 0, + DESKTOP_ADMINS_LIMITED, + AdminsSid)) + { + ERR("AllowDesktopAccessToUser(): Failed to set ACE for admins (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Third ACE -- Give full desktop access to interactive logon users */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + 0, + DESKTOP_ALL, + InteractiveSid)) + { + ERR("AllowDesktopAccessToUser(): Failed to set ACE for interactive SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Fourth ACE -- Give full desktop access to logon user */ + if (!AddAccessAllowedAceEx(Dacl, + ACL_REVISION, + 0, + DESKTOP_ALL, + LogonSid)) + { + ERR("AllowDesktopAccessToUser(): Failed to set ACE for logon user SID (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Initialize the security descriptor */ + if (!InitializeSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION)) + { + ERR("AllowDesktopAccessToUser(): Failed to initialize absolute security descriptor (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Set the DACL to the descriptor */ + if (!SetSecurityDescriptorDacl(&AbsoluteSd, TRUE, Dacl, FALSE)) + { + ERR("AllowDesktopAccessToUser(): Failed to set up DACL to absolute security descriptor (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Conver it to self-relative format */ + RelativeSd = ConvertToSelfRelative(&AbsoluteSd); + if (RelativeSd == NULL) + { + ERR("AllowDesktopAccessToUser(): Failed to convert security descriptor to self relative format!\n"); + goto Quit; + } + + /* Assign new security to desktop based on this descriptor */ + SecurityInformation = DACL_SECURITY_INFORMATION; + if (!SetUserObjectSecurity(Desktop, &SecurityInformation, RelativeSd)) + { + ERR("AllowDesktopAccessToUser(): Failed to set desktop security descriptor (error code %lu)\n", GetLastError()); + goto Quit; + } + + Success = TRUE; + +Quit: + if (WinlogonSid != NULL) + { + FreeSid(WinlogonSid); + } + + if (AdminsSid != NULL) + { + FreeSid(AdminsSid); + } + + if (InteractiveSid != NULL) + { + FreeSid(InteractiveSid); + } + + if (Dacl != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl); + } + + if (RelativeSd != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd); + } + + return Success; +} + +/** + * @brief + * Assigns both window station and desktop access + * to the specific session currently active on the + * system. + * + * @param[in] Session + * A pointer to an active session. + * + * @return + * Returns TRUE if the function has successfully + * assigned access to the current session, FALSE otherwise. + */ +BOOL +AllowAccessOnSession( + _In_ PWLSESSION Session) +{ + BOOL Success = FALSE; + DWORD Index, SidLength, GroupsLength = 0; + PTOKEN_GROUPS TokenGroup = NULL; + PSID LogonSid; + + /* Get required buffer size and allocate the TOKEN_GROUPS buffer */ + if (!GetTokenInformation(Session->UserToken, + TokenGroups, + TokenGroup, + 0, + &GroupsLength)) + { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + ERR("AllowAccessOnSession(): Unexpected error code returned, must be ERROR_INSUFFICIENT_BUFFER (error code %lu)\n", GetLastError()); + return FALSE; + } + + TokenGroup = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, GroupsLength); + if (TokenGroup == NULL) + { + ERR("AllowAccessOnSession(): Failed to allocate memory buffer for token group!\n"); + return FALSE; + } + } + + /* Get the token group information from the access token */ + if (!GetTokenInformation(Session->UserToken, + TokenGroups, + TokenGroup, + GroupsLength, + &GroupsLength)) + { + ERR("AllowAccessOnSession(): Failed to retrieve the token group information (error code %lu)\n", GetLastError()); + goto Quit; + } + + /* Loop through the groups to find the logon SID */ + for (Index = 0; Index < TokenGroup->GroupCount; Index++) + { + if ((TokenGroup->Groups[Index].Attributes & SE_GROUP_LOGON_ID) + == SE_GROUP_LOGON_ID) + { + LogonSid = TokenGroup->Groups[Index].Sid; + break; + } + } + + /* Allow window station access to this user within this session */ + if (!AllowWinstaAccessToUser(Session->InteractiveWindowStation, LogonSid)) + { + ERR("AllowAccessOnSession(): Failed to allow winsta access to the logon user!\n"); + goto Quit; + } + +/* + * FIXME: Desktop security management is broken. The application desktop gets created + * with CreateDesktopW() API call with an initial and defined security descriptor for it yet + * when we are giving access to the logged in user, SetUserObjectSecurity() API call fails to set + * new security because the desktop in question has no prior security descriptor (when it's + * been assigned even before!!!). This chunk of code must be enabled when this gets fixed. + */ +#if 0 + /* Allow application desktop access to this user within this session */ + if (!AllowDesktopAccessToUser(Session->ApplicationDesktop, LogonSid)) + { + ERR("AllowAccessOnSession(): Failed to allow application desktop access to the logon user!\n"); + goto Quit; + } +#endif + + /* Get the length of this logon SID */ + SidLength = GetLengthSid(LogonSid); + + /* Assign the window station to this logged in user */ + if (!SetWindowStationUser(Session->InteractiveWindowStation, + &Session->LogonId, + LogonSid, + SidLength)) + { + ERR("AllowAccessOnSession(): Failed to assign the window station to the logon user!\n"); + goto Quit; + } + + Success = TRUE; + +Quit: + if (TokenGroup != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, TokenGroup); + } + + return Success; +} + +/* EOF */ diff --git a/base/system/winlogon/winlogon.h b/base/system/winlogon/winlogon.h index 07f803a20d8..668fd3e0ad2 100644 --- a/base/system/winlogon/winlogon.h +++ b/base/system/winlogon/winlogon.h @@ -320,6 +320,41 @@ InitializeScreenSaver(IN OUT PWLSESSION Session); VOID StartScreenSaver(IN PWLSESSION Session); +/* security.c */ +PSECURITY_DESCRIPTOR +ConvertToSelfRelative( + _In_ PSECURITY_DESCRIPTOR AbsoluteSd); + +BOOL +CreateWinstaSecurity( + _Out_ PSECURITY_DESCRIPTOR *WinstaSd); + +BOOL +CreateApplicationDesktopSecurity( + _Out_ PSECURITY_DESCRIPTOR *ApplicationDesktopSd); + +BOOL +CreateWinlogonDesktopSecurity( + _Out_ PSECURITY_DESCRIPTOR *WinlogonDesktopSd); + +BOOL +CreateScreenSaverSecurity( + _Out_ PSECURITY_DESCRIPTOR *ScreenSaverDesktopSd); + +BOOL +AllowWinstaAccessToUser( + _In_ HWINSTA WinSta, + _In_ PSID LogonSid); + +BOOL +AllowDesktopAccessToUser( + _In_ HDESK Desktop, + _In_ PSID LogonSid); + +BOOL +AllowAccessOnSession( + _In_ PWLSESSION Session); + /* setup.c */ DWORD GetSetupType(VOID); @@ -364,12 +399,8 @@ BOOL GinaInit(IN OUT PWLSESSION Session); BOOL -AddAceToWindowStation( - IN HWINSTA WinSta, - IN PSID Sid); - -BOOL -CreateWindowStationAndDesktops(IN OUT PWLSESSION Session); +CreateWindowStationAndDesktops( + _Inout_ PWLSESSION Session); VOID WINAPI WlxUseCtrlAltDel(HANDLE hWlx); diff --git a/base/system/winlogon/wlx.c b/base/system/winlogon/wlx.c index 89289c08a99..5b719e0c70f 100644 --- a/base/system/winlogon/wlx.c +++ b/base/system/winlogon/wlx.c @@ -12,20 +12,6 @@ #include "winlogon.h" -#define DESKTOP_ALL (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | \ - DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | \ - DESKTOP_JOURNALPLAYBACK | DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | \ - DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_REQUIRED) - -#define WINSTA_ALL (WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | \ - WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | \ - WINSTA_WRITEATTRIBUTES | WINSTA_ACCESSGLOBALATOMS | \ - WINSTA_EXITWINDOWS | WINSTA_ENUMERATE | WINSTA_READSCREEN | \ - STANDARD_RIGHTS_REQUIRED) - -#define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | \ - GENERIC_EXECUTE | GENERIC_ALL) - typedef struct _DIALOG_LIST_ENTRY { LIST_ENTRY Entry; @@ -938,293 +924,59 @@ GinaInit( &Session->Gina.Context); } -BOOL -AddAceToWindowStation( - IN HWINSTA WinSta, - IN PSID Sid) -{ - DWORD AclSize; - SECURITY_INFORMATION SecurityInformation; - PACL pDefaultAcl = NULL; - PSECURITY_DESCRIPTOR WinstaSd = NULL; - PACCESS_ALLOWED_ACE Ace = NULL; - BOOL Ret = FALSE; - - /* Allocate space for an ACL */ - AclSize = sizeof(ACL) - + 2 * (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(Sid)); - pDefaultAcl = HeapAlloc(GetProcessHeap(), 0, AclSize); - if (!pDefaultAcl) - { - ERR("WL: HeapAlloc() failed\n"); - goto cleanup; - } - - /* Initialize it */ - if (!InitializeAcl(pDefaultAcl, AclSize, ACL_REVISION)) - { - ERR("WL: InitializeAcl() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - /* Initialize new security descriptor */ - WinstaSd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH); - if (!InitializeSecurityDescriptor(WinstaSd, SECURITY_DESCRIPTOR_REVISION)) - { - ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - /* Allocate memory for access allowed ACE */ - Ace = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACCESS_ALLOWED_ACE)+ - GetLengthSid(Sid) - sizeof(DWORD)); - - /* Create the first ACE for the window station */ - Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; - Ace->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE; - Ace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(Sid) - sizeof(DWORD); - Ace->Mask = GENERIC_ACCESS; - - /* Copy the sid */ - if (!CopySid(GetLengthSid(Sid), &Ace->SidStart, Sid)) - { - ERR("WL: CopySid() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - /* Add the first ACE */ - if (!AddAce(pDefaultAcl, ACL_REVISION, MAXDWORD, (LPVOID)Ace, Ace->Header.AceSize)) - { - ERR("WL: AddAce() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - /* Add the second ACE to the end of ACL */ - Ace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE; - Ace->Mask = WINSTA_ALL; - if (!AddAce(pDefaultAcl, ACL_REVISION, MAXDWORD, (LPVOID)Ace, Ace->Header.AceSize)) - { - ERR("WL: AddAce() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - /* Add ACL to winsta's security descriptor */ - if (!SetSecurityDescriptorDacl(WinstaSd, TRUE, pDefaultAcl, FALSE)) - { - ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - /* Apply security to the window station */ - SecurityInformation = DACL_SECURITY_INFORMATION; - if (!SetUserObjectSecurity(WinSta, &SecurityInformation, WinstaSd)) - { - ERR("WL: SetUserObjectSecurity() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - /* Indicate success */ - Ret = TRUE; - -cleanup: - /* Free allocated stuff */ - if (pDefaultAcl) HeapFree(GetProcessHeap(), 0, pDefaultAcl); - if (WinstaSd) HeapFree(GetProcessHeap(), 0, WinstaSd); - if (Ace) HeapFree(GetProcessHeap(), 0, Ace); - - return Ret; -} - -BOOL -AddAceToDesktop( - IN HDESK Desktop, - IN PSID WinlogonSid, - IN PSID UserSid) -{ - DWORD AclSize; - SECURITY_INFORMATION SecurityInformation; - PACL Acl = NULL; - PSECURITY_DESCRIPTOR DesktopSd = NULL; - BOOL Ret = FALSE; - - /* Allocate ACL */ - AclSize = sizeof(ACL) - + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(WinlogonSid); - - /* Take user's sid into account */ - if (UserSid) - AclSize += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(UserSid); - - Acl = HeapAlloc(GetProcessHeap(), 0, AclSize); - if (!Acl) - { - ERR("WL: HeapAlloc() failed\n"); - goto cleanup; - } - - /* Initialize ACL */ - if (!InitializeAcl(Acl, AclSize, ACL_REVISION)) - { - ERR("WL: InitializeAcl() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - /* Add full desktop access ACE for winlogon */ - if (!AddAccessAllowedAce(Acl, ACL_REVISION, DESKTOP_ALL, WinlogonSid)) - { - ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - /* Add full desktop access ACE for a user (if provided) */ - if (UserSid && !AddAccessAllowedAce(Acl, ACL_REVISION, DESKTOP_ALL, UserSid)) - { - ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - /* Initialize new security descriptor */ - DesktopSd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH); - if (!InitializeSecurityDescriptor(DesktopSd, SECURITY_DESCRIPTOR_REVISION)) - { - ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - /* Add ACL to the security descriptor */ - if (!SetSecurityDescriptorDacl(DesktopSd, TRUE, Acl, FALSE)) - { - ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - /* Apply security to the window station */ - SecurityInformation = DACL_SECURITY_INFORMATION; - if (!SetUserObjectSecurity(Desktop, &SecurityInformation, DesktopSd)) - { - ERR("WL: SetUserObjectSecurity() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - /* Indicate success */ - Ret = TRUE; - -cleanup: - /* Free allocated stuff */ - if (Acl) HeapFree(GetProcessHeap(), 0, Acl); - if (DesktopSd) HeapFree(GetProcessHeap(), 0, DesktopSd); - - return Ret; -} - BOOL CreateWindowStationAndDesktops( - IN OUT PWLSESSION Session) + _Inout_ PWLSESSION Session) { - BYTE LocalSystemBuffer[SECURITY_MAX_SID_SIZE]; - BYTE InteractiveBuffer[SECURITY_MAX_SID_SIZE]; - PSID pLocalSystemSid = (PSID)&LocalSystemBuffer; - PSID pInteractiveSid = (PSID)InteractiveBuffer; - DWORD SidSize, AclSize; - PACL pDefaultAcl = NULL; - PACL pUserDesktopAcl = NULL; - SECURITY_DESCRIPTOR DefaultSecurityDescriptor; - SECURITY_ATTRIBUTES DefaultSecurity; - SECURITY_DESCRIPTOR UserDesktopSecurityDescriptor; - SECURITY_ATTRIBUTES UserDesktopSecurity; + SECURITY_ATTRIBUTES WinstaSecurity; + SECURITY_ATTRIBUTES ApplicationDesktopSecurity; + SECURITY_ATTRIBUTES WinlogonDesktopSecurity; + SECURITY_ATTRIBUTES ScreenSaverDesktopSecurity; + PSECURITY_DESCRIPTOR WlWinstaSecurityDescriptor; + PSECURITY_DESCRIPTOR WlApplicationDesktopSecurityDescriptor; + PSECURITY_DESCRIPTOR WlWinlogonDesktopSecurityDescriptor; + PSECURITY_DESCRIPTOR WlScreenSaverDesktopSecurityDescriptor; BOOL ret = FALSE; - /* - * Prepare information for ACLs we will apply - */ - SidSize = SECURITY_MAX_SID_SIZE; - if (!CreateWellKnownSid(WinLocalSystemSid, NULL, pLocalSystemSid, &SidSize)) + if (!CreateWinstaSecurity(&WlWinstaSecurityDescriptor)) { - ERR("WL: CreateWellKnownSid() failed (error %lu)\n", GetLastError()); - goto cleanup; + ERR("WL: Failed to create winsta security!\n"); + return ret; } - SidSize = SECURITY_MAX_SID_SIZE; - if (!CreateWellKnownSid(WinInteractiveSid, NULL, pInteractiveSid, &SidSize)) + + WinstaSecurity.nLength = sizeof(SECURITY_ATTRIBUTES); + WinstaSecurity.lpSecurityDescriptor = WlWinstaSecurityDescriptor; + WinstaSecurity.bInheritHandle = TRUE; + + if (!CreateApplicationDesktopSecurity(&WlApplicationDesktopSecurityDescriptor)) { - ERR("WL: CreateWellKnownSid() failed (error %lu)\n", GetLastError()); + ERR("WL: Failed to create application desktop security!\n"); goto cleanup; } - AclSize = sizeof(ACL) - + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(pLocalSystemSid) - + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(pInteractiveSid); - pDefaultAcl = HeapAlloc(GetProcessHeap(), 0, AclSize); - pUserDesktopAcl = HeapAlloc(GetProcessHeap(), 0, AclSize); - if (!pDefaultAcl || !pUserDesktopAcl) + ApplicationDesktopSecurity.nLength = sizeof(SECURITY_ATTRIBUTES); + ApplicationDesktopSecurity.lpSecurityDescriptor = WlApplicationDesktopSecurityDescriptor; + ApplicationDesktopSecurity.bInheritHandle = TRUE; + + if (!CreateWinlogonDesktopSecurity(&WlWinlogonDesktopSecurityDescriptor)) { - ERR("WL: HeapAlloc() failed\n"); + ERR("WL: Failed to create winlogon desktop security!\n"); goto cleanup; } - if (!InitializeAcl(pDefaultAcl, AclSize, ACL_REVISION) - || !InitializeAcl(pUserDesktopAcl, AclSize, ACL_REVISION)) + WinlogonDesktopSecurity.nLength = sizeof(SECURITY_ATTRIBUTES); + WinlogonDesktopSecurity.lpSecurityDescriptor = WlWinlogonDesktopSecurityDescriptor; + WinlogonDesktopSecurity.bInheritHandle = FALSE; + + if (!CreateScreenSaverSecurity(&WlScreenSaverDesktopSecurityDescriptor)) { - ERR("WL: InitializeAcl() failed (error %lu)\n", GetLastError()); + ERR("WL: Failed to create winlogon desktop security!\n"); goto cleanup; } - /* - * Create default ACL (window station, winlogon desktop, screen saver desktop) - */ - if (!AddAccessAllowedAce(pDefaultAcl, ACL_REVISION, GENERIC_ALL, pLocalSystemSid) - || !AddAccessAllowedAce(pDefaultAcl, ACL_REVISION, GENERIC_READ, pInteractiveSid)) - { - ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - /* - * Create the default security descriptor - */ - if (!InitializeSecurityDescriptor(&DefaultSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION)) - { - ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - if (!SetSecurityDescriptorDacl(&DefaultSecurityDescriptor, TRUE, pDefaultAcl, FALSE)) - { - ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - DefaultSecurity.nLength = sizeof(SECURITY_ATTRIBUTES); - DefaultSecurity.lpSecurityDescriptor = &DefaultSecurityDescriptor; - DefaultSecurity.bInheritHandle = TRUE; - - /* - * Create user desktop ACL - */ - if (!AddAccessAllowedAce(pUserDesktopAcl, ACL_REVISION, GENERIC_ALL, pLocalSystemSid) - || !AddAccessAllowedAce(pUserDesktopAcl, ACL_REVISION, GENERIC_ALL, pInteractiveSid)) - { - ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - /* - * Create the user desktop security descriptor - */ - if (!InitializeSecurityDescriptor(&UserDesktopSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION)) - { - ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - if (!SetSecurityDescriptorDacl(&UserDesktopSecurityDescriptor, TRUE, pUserDesktopAcl, FALSE)) - { - ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError()); - goto cleanup; - } - - UserDesktopSecurity.nLength = sizeof(SECURITY_ATTRIBUTES); - UserDesktopSecurity.lpSecurityDescriptor = &UserDesktopSecurityDescriptor; - UserDesktopSecurity.bInheritHandle = TRUE; + ScreenSaverDesktopSecurity.nLength = sizeof(SECURITY_ATTRIBUTES); + ScreenSaverDesktopSecurity.lpSecurityDescriptor = WlScreenSaverDesktopSecurityDescriptor; + ScreenSaverDesktopSecurity.bInheritHandle = TRUE; /* * Create the interactive window station @@ -1234,12 +986,13 @@ CreateWindowStationAndDesktops( Session->InteractiveWindowStationName, 0, MAXIMUM_ALLOWED, - &DefaultSecurity); + &WinstaSecurity); if (!Session->InteractiveWindowStation) { ERR("WL: Failed to create window station (%lu)\n", GetLastError()); goto cleanup; } + if (!SetProcessWindowStation(Session->InteractiveWindowStation)) { ERR("WL: SetProcessWindowStation() failed (error %lu)\n", GetLastError()); @@ -1255,7 +1008,7 @@ CreateWindowStationAndDesktops( NULL, 0, /* FIXME: Add DF_ALLOWOTHERACCOUNTHOOK flag? */ MAXIMUM_ALLOWED, - &UserDesktopSecurity); + &ApplicationDesktopSecurity); if (!Session->ApplicationDesktop) { ERR("WL: Failed to create Default desktop (%lu)\n", GetLastError()); @@ -1271,7 +1024,7 @@ CreateWindowStationAndDesktops( NULL, 0, MAXIMUM_ALLOWED, - &DefaultSecurity); // FIXME: Must use restricted Winlogon-only security!! + &WinlogonDesktopSecurity); if (!Session->WinlogonDesktop) { ERR("WL: Failed to create Winlogon desktop (%lu)\n", GetLastError()); @@ -1287,7 +1040,7 @@ CreateWindowStationAndDesktops( NULL, 0, MAXIMUM_ALLOWED, - &DefaultSecurity); + &ScreenSaverDesktopSecurity); if(!Session->ScreenSaverDesktop) { ERR("WL: Failed to create Screen-Saver desktop (%lu)\n", GetLastError()); @@ -1332,8 +1085,23 @@ cleanup: CloseWindowStation(Session->InteractiveWindowStation); Session->InteractiveWindowStation = NULL; } + if (WlWinstaSecurityDescriptor) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, WlWinstaSecurityDescriptor); + } + if (WlApplicationDesktopSecurityDescriptor) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, WlApplicationDesktopSecurityDescriptor); + } + if (WlWinlogonDesktopSecurityDescriptor) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, WlWinlogonDesktopSecurityDescriptor); + } + if (WlScreenSaverDesktopSecurityDescriptor) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, WlScreenSaverDesktopSecurityDescriptor); + } } - HeapFree(GetProcessHeap(), 0, pDefaultAcl); - HeapFree(GetProcessHeap(), 0, pUserDesktopAcl); + return ret; }