Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

466 lines
12 KiB

//+----------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996.
//
// File: security.cxx
//
// Contents:
//
// Classes:
//
// Interfaces:
//
// History: 06-Jul-96 MarkBl Created.
// 03-Mar-01 JBenton Prefix Bug 350196
// invalid pointer could be dereferenced on cleanup
//
//-----------------------------------------------------------------------------
#include "..\pch\headers.hxx"
#pragma hdrstop
#include "common.hxx"
#include "debug.hxx"
#include "security.hxx"
#include "proto.hxx"
typedef struct _MYSIDINFO {
PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority;
DWORD dwSubAuthority;
PSID pSid;
} MYSIDINFO;
#define TASK_ALL (GENERIC_READ | GENERIC_WRITE | \
GENERIC_EXECUTE | GENERIC_ALL)
#define TASK_READ (GENERIC_READ)
DWORD AllocateAndInitializeDomainSid(
PSID pDomainSid,
MYSIDINFO * pDomainSidInfo);
HRESULT GetFileOwnerSid(
LPCWSTR pwszFileName,
PSID * ppSid);
//+---------------------------------------------------------------------------
//
// Function: SetTaskFileSecurity
//
// Synopsis: Grant the following permissions to the task object:
//
// LocalSystem All Access.
// Creator All Access.
// Domain Admininstrators All Access.
//
// Arguments: [fIsATTask] -- TRUE if the task is an AT-submitted task;
// FALSE otherwise.
// [pwszTaskPath] -- Task object path.
//
// Notes: None.
//
//----------------------------------------------------------------------------
HRESULT
SetTaskFileSecurity(LPCWSTR pwszTaskPath, BOOL fIsATTask)
{
#define BASE_SID_COUNT 2
#define DOMAIN_SID_COUNT 1
#define TASK_ACE_COUNT 3
FILESYSTEMTYPE FileSystemType;
HRESULT hr;
hr = GetFileSystemTypeFromPath(pwszTaskPath, &FileSystemType);
if (FAILED(hr))
{
return(hr);
}
if (FileSystemType == FILESYSTEM_FAT)
{
//
// No security on FAT. This isn't an error. Let the caller
// think everything went fine.
//
return(S_OK);
}
//
// Retrieve the SID of the file owner.
//
PSID pOwnerSid = NULL;
hr = GetFileOwnerSid(pwszTaskPath, &pOwnerSid);
if (FAILED(hr))
{
return(hr);
}
//
// OK, the fun begins. Build a security descriptor and set file security.
//
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
DWORD Status;
SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY;
SID_IDENTIFIER_AUTHORITY CreatorSidAuth = SECURITY_CREATOR_SID_AUTHORITY;
MYSIDINFO rgBaseSidInfo[BASE_SID_COUNT] = {
{ &NtAuth, // Local System.
SECURITY_LOCAL_SYSTEM_RID,
NULL },
{ &NtAuth, // Built in domain.
SECURITY_BUILTIN_DOMAIN_RID,
NULL }
};
MYSIDINFO rgDomainSidInfo[DOMAIN_SID_COUNT] = {
{ NULL, // Domain administrators.
DOMAIN_ALIAS_RID_ADMINS,
NULL }
};
SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
//
// Make sure we didn't goof.
//
schAssert(BASE_SID_COUNT == (sizeof(rgBaseSidInfo) / sizeof(MYSIDINFO)));
schAssert(DOMAIN_SID_COUNT == (sizeof(rgDomainSidInfo) /
sizeof(MYSIDINFO)));
//
// Create the base SIDs.
//
DWORD i;
for (i = 0; i < BASE_SID_COUNT; i++)
{
if (!AllocateAndInitializeSid(rgBaseSidInfo[i].pIdentifierAuthority,
1,
rgBaseSidInfo[i].dwSubAuthority,
0, 0, 0, 0, 0, 0, 0,
&rgBaseSidInfo[i].pSid))
{
hr = HRESULT_FROM_WIN32(GetLastError());
CHECK_HRESULT(hr);
break;
}
if (!IsValidSid(rgBaseSidInfo[i].pSid))
{
hr = HRESULT_FROM_WIN32(GetLastError());
CHECK_HRESULT(hr);
break;
}
}
if (SUCCEEDED(hr))
{
//
// Create the domain SIDs.
//
for (i = 0; i < DOMAIN_SID_COUNT; i++)
{
DWORD dwError = AllocateAndInitializeDomainSid(
rgBaseSidInfo[1].pSid,
&rgDomainSidInfo[i]);
if (dwError != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(dwError);
CHECK_HRESULT(hr);
break;
}
}
}
//
// Create the security descriptor.
//
// Possibly adjust the array size to account for two special cases:
// 1. If this job is an AT job, only local system and administrators
// are to have access; don't grant users access. This case
// also encompasses case (2).
// 2. The owner sid and the domain administrator SID will be equal
// if the user is an admin. If the user is an admin, ignore the
// administrator setting.
//
DWORD ActualTaskAceCount;
if (fIsATTask)
{
ActualTaskAceCount = TASK_ACE_COUNT - 1;
}
else if (EqualSid(pOwnerSid, rgDomainSidInfo[0].pSid))
{
ActualTaskAceCount = TASK_ACE_COUNT - 1;
}
else
{
ActualTaskAceCount = TASK_ACE_COUNT;
}
PACCESS_ALLOWED_ACE rgAce[TASK_ACE_COUNT] = {
NULL, NULL, NULL // Supply this to CreateSD so we
}; // so we don't have to allocate
// memory.
MYACE rgMyAce[TASK_ACE_COUNT] = {
{ TASK_ALL, // Acess mask.
NO_PROPAGATE_INHERIT_ACE, // Inherit flags.
rgBaseSidInfo[0].pSid }, // SID.
{ TASK_ALL,
NO_PROPAGATE_INHERIT_ACE,
rgDomainSidInfo[0].pSid },
{ TASK_ALL,
NO_PROPAGATE_INHERIT_ACE,
pOwnerSid }
};
schAssert(TASK_ACE_COUNT == (sizeof(rgAce)/sizeof(PACCESS_ALLOWED_ACE)) &&
TASK_ACE_COUNT == (sizeof(rgMyAce) / sizeof(MYACE)));
if (FAILED(hr))
{
goto CleanExit;
}
if ((pSecurityDescriptor = CreateSecurityDescriptor(ActualTaskAceCount,
rgMyAce,
rgAce,
&Status)) == NULL)
{
hr = HRESULT_FROM_WIN32(Status);
goto CleanExit;
}
//
// Finally, set permissions.
//
if (!SetFileSecurity(pwszTaskPath, si, pSecurityDescriptor))
{
hr = HRESULT_FROM_WIN32(GetLastError());
CHECK_HRESULT(hr);
goto CleanExit;
}
CleanExit:
delete pOwnerSid;
for (i = 0; i < BASE_SID_COUNT; i++)
{
if (rgBaseSidInfo[i].pSid != NULL)
{
FreeSid(rgBaseSidInfo[i].pSid);
}
}
for (i = 0; i < DOMAIN_SID_COUNT; i++)
{
if (rgDomainSidInfo[i].pSid != NULL)
{
delete rgDomainSidInfo[i].pSid;
}
}
if (pSecurityDescriptor != NULL)
{
DeleteSecurityDescriptor(pSecurityDescriptor);
}
return(hr);
}
//+---------------------------------------------------------------------------
//
// Function: AllocateAndInitializeDomainSid
//
// Synopsis:
//
// Arguments: [pDomainSid] --
// [pDomainSidInfo] --
//
// Notes: None.
//
//----------------------------------------------------------------------------
DWORD
AllocateAndInitializeDomainSid(
PSID pDomainSid,
MYSIDINFO * pDomainSidInfo)
{
UCHAR DomainIdSubAuthorityCount;
DWORD SidLength;
//
// Allocate a Sid which has one more sub-authority than the domain ID.
//
DomainIdSubAuthorityCount = *(GetSidSubAuthorityCount(pDomainSid));
SidLength = GetSidLengthRequired(DomainIdSubAuthorityCount + 1);
pDomainSidInfo->pSid = new BYTE[SidLength];
if (pDomainSidInfo->pSid == NULL)
{
CHECK_HRESULT(E_OUTOFMEMORY);
return(ERROR_NOT_ENOUGH_MEMORY);
}
//
// Initialize the new SID to have the same inital value as the
// domain ID.
//
if (!CopySid(SidLength, pDomainSidInfo->pSid, pDomainSid))
{
delete pDomainSidInfo->pSid;
pDomainSidInfo->pSid = NULL;
CHECK_HRESULT(HRESULT_FROM_WIN32(GetLastError()));
return(GetLastError());
}
//
// Adjust the sub-authority count and add the relative Id unique
// to the newly allocated SID
//
(*(GetSidSubAuthorityCount(pDomainSidInfo->pSid)))++;
*(GetSidSubAuthority(pDomainSidInfo->pSid,
DomainIdSubAuthorityCount)) =
pDomainSidInfo->dwSubAuthority;
return(ERROR_SUCCESS);
}
//+---------------------------------------------------------------------------
//
// Function: GetFileOwnerSid
//
// Synopsis:
//
// Arguments: [pwszFileName] --
// [ppSid] --
//
// Notes: None.
//
//----------------------------------------------------------------------------
HRESULT
GetFileOwnerSid(LPCWSTR pwszFileName, PSID * ppSid)
{
DWORD cbSizeNeeded;
//
// Retrieve the file owner. Call GetFileSecurity twice - first to get
// the buffer size, then the actual information retrieval.
//
if (GetFileSecurity(pwszFileName,
OWNER_SECURITY_INFORMATION,
NULL,
0,
&cbSizeNeeded))
{
//
// Didn't expect this to succeed!
//
CHECK_HRESULT(E_UNEXPECTED);
return(E_UNEXPECTED);
}
DWORD Status = GetLastError();
PSECURITY_DESCRIPTOR pOwnerSecDescr = NULL;
HRESULT hr = S_OK;
if ((Status == ERROR_INSUFFICIENT_BUFFER) && (cbSizeNeeded > 0))
{
//
// Allocate the buffer space necessary and retrieve the info.
//
pOwnerSecDescr = (SECURITY_DESCRIPTOR *)new BYTE[cbSizeNeeded];
if (pOwnerSecDescr == NULL)
{
CHECK_HRESULT(E_OUTOFMEMORY);
return(E_OUTOFMEMORY);
}
if (!GetFileSecurity(pwszFileName,
OWNER_SECURITY_INFORMATION,
pOwnerSecDescr,
cbSizeNeeded,
&cbSizeNeeded))
{
delete pOwnerSecDescr;
hr = HRESULT_FROM_WIN32(GetLastError());
CHECK_HRESULT(hr);
return(hr);
}
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
CHECK_HRESULT(hr);
return(hr);
}
//
// Retrieve & validate the owner sid.
//
// NB : After this, pOwnerSid will point into the security descriptor,
// pOwnerSecDescr; hence, the descriptor must exist for the
// lifetime of pOwnerSid.
//
DWORD cbOwnerSid;
PSID pOwnerSid;
BOOL fOwnerDefaulted;
if (GetSecurityDescriptorOwner(pOwnerSecDescr,
&pOwnerSid,
&fOwnerDefaulted))
{
if (IsValidSid(pOwnerSid))
{
*ppSid = new BYTE[cbOwnerSid = GetLengthSid(pOwnerSid)];
if (*ppSid != NULL)
{
if (!CopySid(cbOwnerSid, *ppSid, pOwnerSid))
{
delete *ppSid;
*ppSid = NULL;
hr = HRESULT_FROM_WIN32(GetLastError());
CHECK_HRESULT(hr);
}
}
else
{
hr = E_OUTOFMEMORY;
CHECK_HRESULT(hr);
}
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
CHECK_HRESULT(hr);
}
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
CHECK_HRESULT(hr);
}
delete pOwnerSecDescr;
return(hr);
}