mirror of https://github.com/tongzx/nt5src
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
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);
|
|
}
|