Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

600 lines
17 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996.
//
// File: desktop.cxx
//
// Contents: Creation/initialization of the Scheduling Agent windowstation
// and its desktop, "SAWinSta\SADesktop". This windowstation
// needs to exist to run tasks when no user is logged on, or the
// logged on user is different than the task-specific account.
//
// Classes: None.
//
// Functions: None.
//
// History: 26-Jun-96 MarkBl Created
//
//----------------------------------------------------------------------------
#include "..\pch\headers.hxx"
#pragma hdrstop
#include "debug.hxx"
#include "..\inc\security.hxx"
#define SA_WINDOW_STATION L"SAWinSta"
#define SA_DESKTOP L"SADesktop"
//
// Define all access to windows objects
//
// From windows\gina\winlogon\secutil.c
//
#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 WINSTA_ATOMS (WINSTA_ACCESSGLOBALATOMS | \
WINSTA_ACCESSCLIPBOARD )
HDESK CreateSADesktop(HWINSTA hWinSta);
HWINSTA CreateSAWindowStation(void);
PSID GetProcessSid(void);
BOOL InitializeSAWindow(void);
BOOL SetSADesktopSecurity(
HDESK hDesktop,
PSID pSchedAgentSid,
PSID pBatchSid);
BOOL SetSAWindowStationSecurity(
HWINSTA hWinSta,
PSID pSchedAgentSid,
PSID pBatchSid);
void UninitializeSAWindow(void);
// Globals used in this module exclusively.
// Initialized in InitializeSAWindow, closed in UnitializeSAWindow.
//
HWINSTA ghSAWinsta = NULL; // Handle to window station, "SAWinSta".
HDESK ghSADesktop = NULL; // Handle to desktop, "SADesktop"
//+---------------------------------------------------------------------------
//
// Function: InitializeSAWindow
//
// Synopsis: Create and set security info on the windowstation\desktop,
// "SAWinSta\SADesktop". This desktop exists for tasks which
// run under an account different than the currently logged
// on user, or when no user is logged on. Note, these tasks will
// never appear on the interactive desktop.
//
// Arguments: None.
//
// Returns: TRUE -- Everything succeeded.
// FALSE -- Encountered an error.
//
// Notes: None.
//
//----------------------------------------------------------------------------
BOOL
InitializeSAWindow(void)
{
BOOL fRet = TRUE;
PSID pBatchSid;
PSID pSchedAgentSid;
HWINSTA hWinSta = NULL;
HWINSTA hServiceWinSta = NULL;
HDESK hDesktop = NULL;
BOOL fChangedWinSta = FALSE;
//
// Retrieve local system and batch account SIDs.
//
SID_IDENTIFIER_AUTHORITY SidAuth = SECURITY_NT_AUTHORITY;
if (!AllocateAndInitializeSid(&SidAuth,
1,
SECURITY_BATCH_RID,
0, 0, 0, 0, 0, 0, 0,
&pBatchSid))
{
schDebugOut((DEB_ERROR,
"InitializeSAWindow, AllocateAndInitializeSid failed, " \
"status = 0x%lx\n",
GetLastError()));
return(FALSE);
}
if ((pSchedAgentSid = GetProcessSid()) == NULL)
{
fRet = FALSE;
goto CleanExit;
}
//
// Get current service window station.
//
hServiceWinSta = GetProcessWindowStation();
if (hServiceWinSta == NULL) {
fRet = FALSE;
goto CleanExit;
}
//
// Create the window station & desktop.
//
if ((hWinSta = CreateSAWindowStation()) == NULL)
{
fRet = FALSE;
goto CleanExit;
}
if (!SetProcessWindowStation(hWinSta))
{
schDebugOut((DEB_ERROR,
"InitializeSAWindow, SetProcessWindowStation failed, " \
"status = 0x%lx\n",
GetLastError()));
fRet = FALSE;
goto CleanExit;
}
fChangedWinSta = TRUE;
if ((hDesktop = CreateSADesktop(hWinSta)) == NULL)
{
fRet = FALSE;
goto CleanExit;
}
//
// Set security on the window station & desktop.
//
if (!SetSAWindowStationSecurity(hWinSta, pSchedAgentSid, pBatchSid))
{
fRet = FALSE;
goto CleanExit;
}
if (!SetSADesktopSecurity(hDesktop, pSchedAgentSid, pBatchSid))
{
fRet = FALSE;
goto CleanExit;
}
CleanExit:
//
// If we have changed the window station, switch back to service window
// station.
//
if (fChangedWinSta) {
schAssert(hServiceWinSta);
if (!SetProcessWindowStation(hServiceWinSta))
{
schDebugOut((DEB_ERROR,
"InitializeSAWindow, SetProcessWindowStation failed, status = 0x%lx\n",
GetLastError()));
fRet = FALSE;
}
}
if (pBatchSid != NULL) FreeSid(pBatchSid);
if (pSchedAgentSid != NULL) LocalFree(pSchedAgentSid);
if (fRet)
{
ghSAWinsta = hWinSta;
ghSADesktop = hDesktop;
}
else
{
if (hWinSta != NULL) CloseHandle(hWinSta);
if (hDesktop != NULL) CloseHandle(hDesktop);
//
// even though the initial NULL values should still be untouched,
// we'll be extra paranoid here and pretend that gremlins may have fiddled with them
//
ghSAWinsta = NULL;
ghSADesktop = NULL;
}
return(fRet);
}
//+---------------------------------------------------------------------------
//
// Function: UninitializeSAWindow
//
// Synopsis: Close the global window station & desktop handles.
//
// Arguments: None.
//
// Returns: None.
//
// Notes: None.
//
//----------------------------------------------------------------------------
void
UninitializeSAWindow(void)
{
if (ghSADesktop != NULL)
{
CloseDesktop(ghSADesktop);
ghSADesktop = NULL;
}
if (ghSAWinsta != NULL)
{
CloseWindowStation(ghSAWinsta);
ghSAWinsta = NULL;
}
}
//+---------------------------------------------------------------------------
//
// Function: GetProcessSid
//
// Synopsis: Obtain the SID of this process.
//
// Arguments: None.
//
// Returns: This process' sid.
// NULL on failure.
//
// Notes: None.
//
//----------------------------------------------------------------------------
PSID
GetProcessSid(void)
{
PSECURITY_DESCRIPTOR psdProcessSD = NULL;
PSID pProcessSid = NULL;
PSID pProcessSidTmp;
DWORD cbSize;
HANDLE hProcess;
BOOL fOwnerDefaulted;
hProcess = GetCurrentProcess();
if (hProcess == NULL)
{
schDebugOut((DEB_ERROR,
"GetProcessSid, GetCurrentProcess failed, status = 0x%lx\n",
GetLastError()));
return(NULL);
}
//
// Retrieve the buffer size necessary to retrieve this process' SD.
//
if (!GetKernelObjectSecurity(hProcess,
OWNER_SECURITY_INFORMATION,
NULL,
0,
&cbSize) &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
psdProcessSD = LocalAlloc(LMEM_FIXED, cbSize);
if (psdProcessSD == NULL)
{
schDebugOut((DEB_ERROR,
"GetProcessSid, process security descriptor allocation " \
"failure\n"));
return(NULL);
}
//
// Actually retrieve this process' SD.
//
if (!GetKernelObjectSecurity(hProcess,
OWNER_SECURITY_INFORMATION,
psdProcessSD,
cbSize,
&cbSize))
{
schDebugOut((DEB_ERROR,
"GetProcessSid, GetKernelObjectSecurity failed, " \
"status = 0x%lx\n",
GetLastError()));
goto ErrorExit;
}
}
else
{
schAssert(0 && "GetKernelObjectSecurity() succeeded!");
return(NULL);
}
//
// Retrieve the owner SID from the SD.
//
if (!GetSecurityDescriptorOwner(psdProcessSD,
&pProcessSidTmp,
&fOwnerDefaulted))
{
schDebugOut((DEB_ERROR,
"GetProcessSid, GetSecurityDescriptorOwner failed, " \
"status = 0x%lx\n",
GetLastError()));
goto ErrorExit;
}
//
// An unnecessary check, maybe, but safe.
//
if (!IsValidSid(pProcessSidTmp))
{
schDebugOut((DEB_ERROR,
"GetProcessSid, IsValidSid failed, status = 0x%lx\n",
GetLastError()));
goto ErrorExit;
}
//
// Make a copy of the SID since that returned from GetSecuritySD refers
// within the security descriptor allocated above.
//
cbSize = GetLengthSid(pProcessSidTmp);
pProcessSid = LocalAlloc(LMEM_FIXED, cbSize);
if (pProcessSid == NULL)
{
schDebugOut((DEB_ERROR,
"GetProcessSid, process SID allocation failure\n"));
goto ErrorExit;
}
if (!CopySid(cbSize, pProcessSid, pProcessSidTmp))
{
LocalFree(pProcessSid);
pProcessSid = NULL;
schDebugOut((DEB_ERROR,
"GetProcessSid, CopySid failed, status = 0x%lx\n",
GetLastError()));
}
ErrorExit:
if (psdProcessSD != NULL) LocalFree(psdProcessSD);
return(pProcessSid);
}
//+---------------------------------------------------------------------------
//
// Function: CreateSAWindowStation
//
// Synopsis: Create the window station named "SAWinSta".
//
// Arguments: None.
//
// Returns: Window station handle on success.
// NULL on failure.
//
// Notes: None.
//
//----------------------------------------------------------------------------
HWINSTA
CreateSAWindowStation(void)
{
HWINSTA hWinSta;
if ((hWinSta = CreateWindowStation(SA_WINDOW_STATION,
NULL,
MAXIMUM_ALLOWED,
NULL)) == NULL)
{
schDebugOut((DEB_ERROR,
"CreateSAWindowStation, CreateWindowStation failed, " \
"status = 0x%lx\n",
GetLastError()));
return(NULL);
}
return(hWinSta);
}
//+---------------------------------------------------------------------------
//
// Function: CreateSADesktop
//
// Synopsis: Create the desktop, "SADesktop", on the window station
// indicated.
//
// Arguments: [hWinSta] -- Window station.
//
// Returns: Desktop handle on success.
// NULL on failure.
//
// Notes: None.
//
//----------------------------------------------------------------------------
HDESK
CreateSADesktop(HWINSTA hWinSta)
{
HDESK hDesktop;
if ((hDesktop = CreateDesktop(SA_DESKTOP,
NULL,
NULL,
0,
MAXIMUM_ALLOWED,
NULL)) == NULL)
{
schDebugOut((DEB_ERROR,
"CreateSADesktop, CreateDesktop failed, status = 0x%lx\n",
GetLastError()));
return(NULL);
}
return(hDesktop);
}
//+---------------------------------------------------------------------------
//
// Function: SetSAWindowStationSecurity
//
// Synopsis: Set permissions on the scheduling agent window station for
// this process and batch users.
//
// Arguments: [hWinSta] -- Window station.
// [pSchedAgentSid] -- Scheduling Agent process SID.
// [pBatchSid] -- Batch SID.
//
// Returns: TRUE -- Function succeeded,
// FALSE -- Otherwise.
//
// Notes: None.
//
//----------------------------------------------------------------------------
BOOL
SetSAWindowStationSecurity(
HWINSTA hWinSta,
PSID pSchedAgentSid,
PSID pBatchSid)
{
#define WS_ACE_COUNT 4
PACCESS_ALLOWED_ACE rgAce[WS_ACE_COUNT] = {
NULL, NULL, NULL, NULL }; // Supply this to CreateSD so we
// don't have to allocate memory.
MYACE rgMyAce[WS_ACE_COUNT] = {
{ WINSTA_ALL, // Acess mask.
NO_PROPAGATE_INHERIT_ACE, // Inherit flags.
pSchedAgentSid }, // SID.
{ GENERIC_ALL,
OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE,
pSchedAgentSid },
{ WINSTA_ALL & ~(DELETE | WRITE_DAC | WRITE_OWNER), // need to leave READ_CONTROL in this or jobs can't run
NO_PROPAGATE_INHERIT_ACE,
pBatchSid },
{ GENERIC_READ | GENERIC_EXECUTE,
INHERIT_ONLY_ACE,
pBatchSid }
};
schAssert(WS_ACE_COUNT == (sizeof(rgAce)/sizeof(PACCESS_ALLOWED_ACE)) &&
WS_ACE_COUNT == (sizeof(rgMyAce) / sizeof(MYACE)));
PSECURITY_DESCRIPTOR pSecurityDescriptor;
SECURITY_INFORMATION si;
DWORD Status = 0;
if ((pSecurityDescriptor = CreateSecurityDescriptor(WS_ACE_COUNT,
rgMyAce,
rgAce)) == NULL)
{
return(FALSE);
}
si = DACL_SECURITY_INFORMATION;
if (!SetUserObjectSecurity(hWinSta, &si, pSecurityDescriptor))
{
Status = GetLastError();
}
DeleteSecurityDescriptor(pSecurityDescriptor);
if (Status)
{
schDebugOut((DEB_ERROR,
"SetSASetWindowStationSecurity, SetUserObjectSecurity failed, " \
"status = 0x%lx\n",
Status));
return(FALSE);
}
return(TRUE);
}
//+---------------------------------------------------------------------------
//
// Function: SetSADesktopSecurity
//
// Synopsis: Set permissions on the scheduling agent desktop for this
// process and batch users.
//
// Arguments: [hDesktop] -- Desktop.
// [pSchedAgentSid] -- Scheduling Agent process SID.
// [pBatchSid] -- Batch SID.
//
// Returns: TRUE -- Function succeeded,
// FALSE -- Otherwise.
//
// Notes: None.
//
//----------------------------------------------------------------------------
BOOL
SetSADesktopSecurity(
HDESK hDesktop,
PSID pSchedAgentSid,
PSID pBatchSid)
{
#define DT_ACE_COUNT 2
PACCESS_ALLOWED_ACE rgAce[DT_ACE_COUNT] = {
NULL, NULL }; // Supply this to CreateSD so we
// don't have to allocate memory.
MYACE rgMyAce[DT_ACE_COUNT] = {
{ DESKTOP_ALL, // Acess mask.
0, // Inherit flags.
pSchedAgentSid }, // SID.
{ DESKTOP_ALL & ~STANDARD_RIGHTS_REQUIRED,
0,
pBatchSid }
};
schAssert(DT_ACE_COUNT == (sizeof(rgAce)/sizeof(PACCESS_ALLOWED_ACE)) &&
DT_ACE_COUNT == (sizeof(rgMyAce) / sizeof(MYACE)));
PSECURITY_DESCRIPTOR pSecurityDescriptor;
SECURITY_INFORMATION si;
DWORD Status = 0;
if ((pSecurityDescriptor = CreateSecurityDescriptor(DT_ACE_COUNT,
rgMyAce,
rgAce)) == NULL)
{
return(FALSE);
}
si = DACL_SECURITY_INFORMATION;
if (!SetUserObjectSecurity(hDesktop, &si, pSecurityDescriptor))
{
Status = GetLastError();
}
DeleteSecurityDescriptor(pSecurityDescriptor);
if (Status)
{
schDebugOut((DEB_ERROR,
"SetSADesktopSecurity, SetUserObjectSecurity failed, " \
"status = 0x%lx\n",
Status));
return(FALSE);
}
return(TRUE);
}