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.
1113 lines
31 KiB
1113 lines
31 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
|
|
Module Name:
|
|
|
|
NTacls
|
|
|
|
Abstract:
|
|
|
|
This module implements the CSecurityAttribute class. It's job is to
|
|
encapsulate the NT security descriptors as needed by Calais.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 1/24/1997
|
|
|
|
Environment:
|
|
|
|
Windows NT, Win32, C++ w/ Exceptions
|
|
|
|
Notes:
|
|
|
|
?Notes?
|
|
|
|
--*/
|
|
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#include <windows.h>
|
|
#include "cspUtils.h"
|
|
|
|
|
|
const CSecurityDescriptor::SecurityId
|
|
CSecurityDescriptor::SID_Null = { SECURITY_NULL_SID_AUTHORITY, 1, SECURITY_NULL_RID, 0 },
|
|
CSecurityDescriptor::SID_World = { SECURITY_WORLD_SID_AUTHORITY, 1, SECURITY_WORLD_RID, 0 },
|
|
CSecurityDescriptor::SID_Local = { SECURITY_LOCAL_SID_AUTHORITY, 1, SECURITY_LOCAL_RID, 0 },
|
|
CSecurityDescriptor::SID_Owner = { SECURITY_CREATOR_SID_AUTHORITY, 1, SECURITY_CREATOR_OWNER_RID, 0 },
|
|
CSecurityDescriptor::SID_Group = { SECURITY_CREATOR_SID_AUTHORITY, 1, SECURITY_CREATOR_GROUP_RID, 0 },
|
|
CSecurityDescriptor::SID_Admins = { SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS },
|
|
CSecurityDescriptor::SID_DialUp = { SECURITY_NT_AUTHORITY, 1, SECURITY_DIALUP_RID, 0 },
|
|
CSecurityDescriptor::SID_Network = { SECURITY_NT_AUTHORITY, 1, SECURITY_NETWORK_RID, 0 },
|
|
CSecurityDescriptor::SID_Batch = { SECURITY_NT_AUTHORITY, 1, SECURITY_BATCH_RID, 0 },
|
|
CSecurityDescriptor::SID_Interactive = { SECURITY_NT_AUTHORITY, 1, SECURITY_INTERACTIVE_RID, 0 },
|
|
CSecurityDescriptor::SID_Service = { SECURITY_NT_AUTHORITY, 1, SECURITY_SERVICE_RID, 0 },
|
|
CSecurityDescriptor::SID_System = { SECURITY_NT_AUTHORITY, 1, SECURITY_LOCAL_SYSTEM_RID, 0 },
|
|
CSecurityDescriptor::SID_SysDomain = { SECURITY_NT_AUTHORITY, 1, SECURITY_BUILTIN_DOMAIN_RID, 0 };
|
|
|
|
CSecurityDescriptor::CSecurityDescriptor()
|
|
{
|
|
m_pSD = NULL;
|
|
m_pOwner = NULL;
|
|
m_pGroup = NULL;
|
|
m_pDACL = NULL;
|
|
m_pSACL= NULL;
|
|
m_fInheritance = FALSE;
|
|
}
|
|
|
|
CSecurityDescriptor::~CSecurityDescriptor()
|
|
{
|
|
if (m_pSD)
|
|
delete m_pSD;
|
|
if (m_pOwner)
|
|
delete[] (LPBYTE)m_pOwner;
|
|
if (m_pGroup)
|
|
delete[] (LPBYTE)m_pGroup;
|
|
if (m_pDACL)
|
|
delete[] (LPBYTE)m_pDACL;
|
|
if (m_pSACL)
|
|
delete[] (LPBYTE)m_pSACL;
|
|
}
|
|
|
|
HRESULT CSecurityDescriptor::Initialize()
|
|
{
|
|
if (m_pSD)
|
|
{
|
|
delete m_pSD;
|
|
m_pSD = NULL;
|
|
}
|
|
if (m_pOwner)
|
|
{
|
|
delete[] (LPBYTE)(m_pOwner);
|
|
m_pOwner = NULL;
|
|
}
|
|
if (m_pGroup)
|
|
{
|
|
delete[] (LPBYTE)(m_pGroup);
|
|
m_pGroup = NULL;
|
|
}
|
|
if (m_pDACL)
|
|
{
|
|
delete[] (LPBYTE)(m_pDACL);
|
|
m_pDACL = NULL;
|
|
}
|
|
if (m_pSACL)
|
|
{
|
|
delete[] (LPBYTE)(m_pSACL);
|
|
m_pSACL = NULL;
|
|
}
|
|
|
|
m_pSD = new SECURITY_DESCRIPTOR;
|
|
if (!m_pSD)
|
|
return E_OUTOFMEMORY;
|
|
if (!InitializeSecurityDescriptor(m_pSD, SECURITY_DESCRIPTOR_REVISION))
|
|
{
|
|
HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
|
|
delete m_pSD;
|
|
m_pSD = NULL;
|
|
_ASSERTE(FALSE);
|
|
return hr;
|
|
}
|
|
// Set the DACL to allow EVERYONE
|
|
SetSecurityDescriptorDacl(m_pSD, TRUE, NULL, FALSE);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CSecurityDescriptor::InitializeFromProcessToken(BOOL bDefaulted)
|
|
{
|
|
PSID pUserSid;
|
|
PSID pGroupSid;
|
|
HRESULT hr;
|
|
|
|
Initialize();
|
|
hr = GetProcessSids(&pUserSid, &pGroupSid);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
hr = SetOwner(pUserSid, bDefaulted);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
hr = SetGroup(pGroupSid, bDefaulted);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CSecurityDescriptor::InitializeFromThreadToken(BOOL bDefaulted, BOOL bRevertToProcessToken)
|
|
{
|
|
PSID pUserSid;
|
|
PSID pGroupSid;
|
|
HRESULT hr;
|
|
|
|
Initialize();
|
|
hr = GetThreadSids(&pUserSid, &pGroupSid);
|
|
if (HRESULT_CODE(hr) == ERROR_NO_TOKEN && bRevertToProcessToken)
|
|
hr = GetProcessSids(&pUserSid, &pGroupSid);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
hr = SetOwner(pUserSid, bDefaulted);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
hr = SetGroup(pGroupSid, bDefaulted);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CSecurityDescriptor::SetOwner(PSID pOwnerSid, BOOL bDefaulted)
|
|
{
|
|
_ASSERTE(m_pSD);
|
|
|
|
// Mark the SD as having no owner
|
|
if (!SetSecurityDescriptorOwner(m_pSD, NULL, bDefaulted))
|
|
{
|
|
HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
|
|
_ASSERTE(FALSE);
|
|
return hr;
|
|
}
|
|
|
|
if (m_pOwner)
|
|
{
|
|
delete[] (LPBYTE)(m_pOwner);
|
|
m_pOwner = NULL;
|
|
}
|
|
|
|
// If they asked for no owner don't do the copy
|
|
if (pOwnerSid == NULL)
|
|
return S_OK;
|
|
|
|
// Make a copy of the Sid for the return value
|
|
DWORD dwSize = GetLengthSid(pOwnerSid);
|
|
|
|
m_pOwner = (PSID) new BYTE[dwSize];
|
|
if (!m_pOwner)
|
|
{
|
|
// Insufficient memory to allocate Sid
|
|
_ASSERTE(FALSE);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
if (!CopySid(dwSize, m_pOwner, pOwnerSid))
|
|
{
|
|
HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
|
|
_ASSERTE(FALSE);
|
|
delete[] (LPBYTE)(m_pOwner);
|
|
m_pOwner = NULL;
|
|
return hr;
|
|
}
|
|
|
|
_ASSERTE(IsValidSid(m_pOwner));
|
|
|
|
if (!SetSecurityDescriptorOwner(m_pSD, m_pOwner, bDefaulted))
|
|
{
|
|
HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
|
|
_ASSERTE(FALSE);
|
|
delete[] (LPBYTE)(m_pOwner);
|
|
m_pOwner = NULL;
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CSecurityDescriptor::SetGroup(PSID pGroupSid, BOOL bDefaulted)
|
|
{
|
|
_ASSERTE(m_pSD);
|
|
|
|
// Mark the SD as having no Group
|
|
if (!SetSecurityDescriptorGroup(m_pSD, NULL, bDefaulted))
|
|
{
|
|
HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
|
|
_ASSERTE(FALSE);
|
|
return hr;
|
|
}
|
|
|
|
if (m_pGroup)
|
|
{
|
|
delete[] (LPBYTE)(m_pGroup);
|
|
m_pGroup = NULL;
|
|
}
|
|
|
|
// If they asked for no Group don't do the copy
|
|
if (pGroupSid == NULL)
|
|
return S_OK;
|
|
|
|
// Make a copy of the Sid for the return value
|
|
DWORD dwSize = GetLengthSid(pGroupSid);
|
|
|
|
m_pGroup = (PSID) new BYTE[dwSize];
|
|
if (!m_pGroup)
|
|
{
|
|
// Insufficient memory to allocate Sid
|
|
_ASSERTE(FALSE);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
if (!CopySid(dwSize, m_pGroup, pGroupSid))
|
|
{
|
|
HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
|
|
_ASSERTE(FALSE);
|
|
delete[] (LPBYTE)(m_pGroup);
|
|
m_pGroup = NULL;
|
|
return hr;
|
|
}
|
|
|
|
_ASSERTE(IsValidSid(m_pGroup));
|
|
|
|
if (!SetSecurityDescriptorGroup(m_pSD, m_pGroup, bDefaulted))
|
|
{
|
|
HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
|
|
_ASSERTE(FALSE);
|
|
delete[] (LPBYTE)(m_pGroup);
|
|
m_pGroup = NULL;
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CSecurityDescriptor::Allow(const SecurityId *psidPrincipal, DWORD dwAccessMask)
|
|
{
|
|
HRESULT hr = AddAccessAllowedACEToACL(&m_pDACL, psidPrincipal, dwAccessMask);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE))
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CSecurityDescriptor::Allow(LPCTSTR pszPrincipal, DWORD dwAccessMask)
|
|
{
|
|
HRESULT hr = AddAccessAllowedACEToACL(&m_pDACL, pszPrincipal, dwAccessMask);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE))
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CSecurityDescriptor::Deny(const SecurityId *psidPrincipal, DWORD dwAccessMask)
|
|
{
|
|
HRESULT hr = AddAccessDeniedACEToACL(&m_pDACL, psidPrincipal, dwAccessMask);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE))
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CSecurityDescriptor::Deny(LPCTSTR pszPrincipal, DWORD dwAccessMask)
|
|
{
|
|
HRESULT hr = AddAccessDeniedACEToACL(&m_pDACL, pszPrincipal, dwAccessMask);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE))
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CSecurityDescriptor::Revoke(LPCTSTR pszPrincipal)
|
|
{
|
|
HRESULT hr = RemovePrincipalFromACL(m_pDACL, pszPrincipal);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE))
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CSecurityDescriptor::GetProcessSids(PSID* ppUserSid, PSID* ppGroupSid)
|
|
{
|
|
BOOL bRes;
|
|
HRESULT hr;
|
|
HANDLE hToken = NULL;
|
|
if (ppUserSid)
|
|
*ppUserSid = NULL;
|
|
if (ppGroupSid)
|
|
*ppGroupSid = NULL;
|
|
bRes = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
|
|
if (!bRes)
|
|
{
|
|
// Couldn't open process token
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
_ASSERTE(FALSE);
|
|
return hr;
|
|
}
|
|
hr = GetTokenSids(hToken, ppUserSid, ppGroupSid);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CSecurityDescriptor::GetThreadSids(PSID* ppUserSid, PSID* ppGroupSid, BOOL bOpenAsSelf)
|
|
{
|
|
BOOL bRes;
|
|
HRESULT hr;
|
|
HANDLE hToken = NULL;
|
|
if (ppUserSid)
|
|
*ppUserSid = NULL;
|
|
if (ppGroupSid)
|
|
*ppGroupSid = NULL;
|
|
bRes = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, bOpenAsSelf, &hToken);
|
|
if (!bRes)
|
|
{
|
|
// Couldn't open thread token
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
return hr;
|
|
}
|
|
hr = GetTokenSids(hToken, ppUserSid, ppGroupSid);
|
|
CloseHandle(hToken);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CSecurityDescriptor::GetTokenSids(HANDLE hToken, PSID* ppUserSid, PSID* ppGroupSid)
|
|
{
|
|
DWORD dwSize;
|
|
HRESULT hr;
|
|
PTOKEN_USER ptkUser = NULL;
|
|
PTOKEN_PRIMARY_GROUP ptkGroup = NULL;
|
|
|
|
if (ppUserSid)
|
|
*ppUserSid = NULL;
|
|
if (ppGroupSid)
|
|
*ppGroupSid = NULL;
|
|
|
|
if (ppUserSid)
|
|
{
|
|
// Get length required for TokenUser by specifying buffer length of 0
|
|
GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
|
|
hr = GetLastError();
|
|
if (hr != ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
// Expected ERROR_INSUFFICIENT_BUFFER
|
|
_ASSERTE(FALSE);
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
goto failed;
|
|
}
|
|
|
|
ptkUser = (TOKEN_USER*) new BYTE[dwSize];
|
|
if (!ptkUser)
|
|
{
|
|
// Insufficient memory to allocate TOKEN_USER
|
|
_ASSERTE(FALSE);
|
|
hr = E_OUTOFMEMORY;
|
|
goto failed;
|
|
}
|
|
// Get Sid of process token.
|
|
if (!GetTokenInformation(hToken, TokenUser, ptkUser, dwSize, &dwSize))
|
|
{
|
|
// Couldn't get user info
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
_ASSERTE(FALSE);
|
|
goto failed;
|
|
}
|
|
|
|
// Make a copy of the Sid for the return value
|
|
dwSize = GetLengthSid(ptkUser->User.Sid);
|
|
|
|
PSID pSid = (PSID) new BYTE[dwSize];
|
|
if (!pSid)
|
|
{
|
|
// Insufficient memory to allocate Sid
|
|
_ASSERTE(FALSE);
|
|
hr = E_OUTOFMEMORY;
|
|
goto failed;
|
|
}
|
|
if (!CopySid(dwSize, pSid, ptkUser->User.Sid))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
_ASSERTE(FALSE);
|
|
goto failed;
|
|
}
|
|
|
|
_ASSERTE(IsValidSid(pSid));
|
|
*ppUserSid = pSid;
|
|
delete[] (LPBYTE)(ptkUser);
|
|
ptkUser = NULL;
|
|
}
|
|
if (ppGroupSid)
|
|
{
|
|
// Get length required for TokenPrimaryGroup by specifying buffer length of 0
|
|
GetTokenInformation(hToken, TokenPrimaryGroup, NULL, 0, &dwSize);
|
|
hr = GetLastError();
|
|
if (hr != ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
// Expected ERROR_INSUFFICIENT_BUFFER
|
|
_ASSERTE(FALSE);
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
goto failed;
|
|
}
|
|
|
|
ptkGroup = (TOKEN_PRIMARY_GROUP*) new BYTE[dwSize];
|
|
if (!ptkGroup)
|
|
{
|
|
// Insufficient memory to allocate TOKEN_USER
|
|
_ASSERTE(FALSE);
|
|
hr = E_OUTOFMEMORY;
|
|
goto failed;
|
|
}
|
|
// Get Sid of process token.
|
|
if (!GetTokenInformation(hToken, TokenPrimaryGroup, ptkGroup, dwSize, &dwSize))
|
|
{
|
|
// Couldn't get user info
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
_ASSERTE(FALSE);
|
|
goto failed;
|
|
}
|
|
|
|
// Make a copy of the Sid for the return value
|
|
dwSize = GetLengthSid(ptkGroup->PrimaryGroup);
|
|
|
|
PSID pSid = (PSID) new BYTE[dwSize];
|
|
if (!pSid)
|
|
{
|
|
// Insufficient memory to allocate Sid
|
|
_ASSERTE(FALSE);
|
|
hr = E_OUTOFMEMORY;
|
|
goto failed;
|
|
}
|
|
if (!CopySid(dwSize, pSid, ptkGroup->PrimaryGroup))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
_ASSERTE(FALSE);
|
|
goto failed;
|
|
}
|
|
|
|
_ASSERTE(IsValidSid(pSid));
|
|
|
|
*ppGroupSid = pSid;
|
|
delete[] (LPBYTE)(ptkGroup);
|
|
ptkGroup = NULL;
|
|
}
|
|
|
|
return S_OK;
|
|
|
|
failed:
|
|
if (ptkUser)
|
|
delete[] (LPBYTE)(ptkUser);
|
|
if (ptkGroup)
|
|
delete[] (LPBYTE)(ptkGroup);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CSecurityDescriptor::GetCurrentUserSID(PSID *ppSid)
|
|
{
|
|
HANDLE tkHandle;
|
|
|
|
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tkHandle))
|
|
{
|
|
TOKEN_USER *tkUser;
|
|
DWORD tkSize;
|
|
DWORD sidLength;
|
|
|
|
// Call to get size information for alloc
|
|
GetTokenInformation(tkHandle, TokenUser, NULL, 0, &tkSize);
|
|
tkUser = (TOKEN_USER *) new BYTE[tkSize];
|
|
if (NULL == tkUser)
|
|
{
|
|
CloseHandle(tkHandle);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Now make the real call
|
|
if (GetTokenInformation(tkHandle, TokenUser, tkUser, tkSize, &tkSize))
|
|
{
|
|
sidLength = GetLengthSid(tkUser->User.Sid);
|
|
*ppSid = (PSID) new BYTE[sidLength];
|
|
if (NULL != *ppSid)
|
|
{
|
|
memcpy(*ppSid, tkUser->User.Sid, sidLength);
|
|
CloseHandle(tkHandle);
|
|
|
|
delete[] (LPBYTE)(tkUser);
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
CloseHandle(tkHandle);
|
|
delete[] (LPBYTE)(tkUser);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delete[] (LPBYTE)(tkUser);
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
|
|
HRESULT CSecurityDescriptor::GetPrincipalSID(LPCTSTR pszPrincipal, PSID *ppSid)
|
|
{
|
|
HRESULT hr;
|
|
LPTSTR pszRefDomain = NULL;
|
|
DWORD dwDomainSize = 0;
|
|
DWORD dwSidSize = 0;
|
|
SID_NAME_USE snu;
|
|
|
|
// Call to get size info for alloc
|
|
LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu);
|
|
|
|
hr = GetLastError();
|
|
if (hr != ERROR_INSUFFICIENT_BUFFER)
|
|
return HRESULT_FROM_WIN32(hr);
|
|
|
|
pszRefDomain = new TCHAR[dwDomainSize];
|
|
if (pszRefDomain == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
*ppSid = (PSID) new BYTE[dwSidSize];
|
|
if (*ppSid != NULL)
|
|
{
|
|
if (!LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu))
|
|
{
|
|
delete[] (LPBYTE)(*ppSid);
|
|
*ppSid = NULL;
|
|
delete[] pszRefDomain;
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
delete[] pszRefDomain;
|
|
return S_OK;
|
|
}
|
|
delete[] pszRefDomain;
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
HRESULT CSecurityDescriptor::Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD)
|
|
{
|
|
PACL pDACL = NULL;
|
|
PACL pSACL = NULL;
|
|
BOOL bDACLPresent, bSACLPresent;
|
|
BOOL bDefaulted;
|
|
PACL m_pDACL = NULL;
|
|
ACCESS_ALLOWED_ACE* pACE;
|
|
HRESULT hr;
|
|
PSID pUserSid;
|
|
PSID pGroupSid;
|
|
|
|
hr = Initialize();
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
// get the existing DACL.
|
|
if (!GetSecurityDescriptorDacl(pSelfRelativeSD, &bDACLPresent, &pDACL, &bDefaulted))
|
|
goto failed;
|
|
|
|
if (bDACLPresent)
|
|
{
|
|
if (pDACL)
|
|
{
|
|
// allocate new DACL.
|
|
if (NULL == (m_pDACL = (PACL) new BYTE[pDACL->AclSize]))
|
|
goto failed;
|
|
|
|
// initialize the DACL
|
|
if (!InitializeAcl(m_pDACL, pDACL->AclSize, ACL_REVISION))
|
|
goto failed;
|
|
|
|
// copy the ACES
|
|
for (int i = 0; i < pDACL->AceCount; i++)
|
|
{
|
|
if (!GetAce(pDACL, i, (void **)&pACE))
|
|
goto failed;
|
|
|
|
if (!AddAccessAllowedAce(m_pDACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart)))
|
|
goto failed;
|
|
}
|
|
|
|
if (!IsValidAcl(m_pDACL))
|
|
goto failed;
|
|
}
|
|
|
|
// set the DACL
|
|
if (!SetSecurityDescriptorDacl(m_pSD, m_pDACL ? TRUE : FALSE, m_pDACL, bDefaulted))
|
|
goto failed;
|
|
}
|
|
|
|
// get the existing SACL.
|
|
if (!GetSecurityDescriptorSacl(pSelfRelativeSD, &bSACLPresent, &pSACL, &bDefaulted))
|
|
goto failed;
|
|
|
|
if (bSACLPresent)
|
|
{
|
|
if (pSACL)
|
|
{
|
|
// allocate new SACL.
|
|
if (NULL == (m_pSACL = (PACL) new BYTE[pSACL->AclSize]))
|
|
goto failed;
|
|
|
|
// initialize the SACL
|
|
if (!InitializeAcl(m_pSACL, pSACL->AclSize, ACL_REVISION))
|
|
goto failed;
|
|
|
|
// copy the ACES
|
|
for (int i = 0; i < pSACL->AceCount; i++)
|
|
{
|
|
if (!GetAce(pSACL, i, (void **)&pACE))
|
|
goto failed;
|
|
|
|
if (!AddAccessAllowedAce(m_pSACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart)))
|
|
goto failed;
|
|
}
|
|
|
|
if (!IsValidAcl(m_pSACL))
|
|
goto failed;
|
|
}
|
|
|
|
// set the SACL
|
|
if (!SetSecurityDescriptorSacl(m_pSD, m_pSACL ? TRUE : FALSE, m_pSACL, bDefaulted))
|
|
goto failed;
|
|
}
|
|
|
|
if (!GetSecurityDescriptorOwner(m_pSD, &pUserSid, &bDefaulted))
|
|
goto failed;
|
|
|
|
if (FAILED(SetOwner(pUserSid, bDefaulted)))
|
|
goto failed;
|
|
|
|
if (!GetSecurityDescriptorGroup(m_pSD, &pGroupSid, &bDefaulted))
|
|
goto failed;
|
|
|
|
if (FAILED(SetGroup(pGroupSid, bDefaulted)))
|
|
goto failed;
|
|
|
|
if (!IsValidSecurityDescriptor(m_pSD))
|
|
goto failed;
|
|
|
|
return hr;
|
|
|
|
failed:
|
|
if (m_pDACL)
|
|
delete[] (LPBYTE)(m_pDACL);
|
|
if (m_pSD)
|
|
delete[] (LPBYTE)(m_pSD);
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
HRESULT CSecurityDescriptor::AttachObject(HANDLE hObject)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwSize = 0;
|
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
|
|
|
GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
|
DACL_SECURITY_INFORMATION, pSD, 0, &dwSize);
|
|
|
|
hr = GetLastError();
|
|
if (hr != ERROR_INSUFFICIENT_BUFFER)
|
|
return HRESULT_FROM_WIN32(hr);
|
|
|
|
pSD = (PSECURITY_DESCRIPTOR) new BYTE[dwSize];
|
|
|
|
if (!GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
|
DACL_SECURITY_INFORMATION, pSD, dwSize, &dwSize))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
delete[] (LPBYTE)(pSD);
|
|
return hr;
|
|
}
|
|
|
|
hr = Attach(pSD);
|
|
delete[] (LPBYTE)(pSD);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CSecurityDescriptor::CopyACL(PACL pDest, PACL pSrc)
|
|
{
|
|
ACL_SIZE_INFORMATION aclSizeInfo;
|
|
LPVOID pAce;
|
|
ACE_HEADER *aceHeader;
|
|
|
|
if (pSrc == NULL)
|
|
return S_OK;
|
|
|
|
if (!GetAclInformation(pSrc, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
// Copy all of the ACEs to the new ACL
|
|
for (UINT i = 0; i < aclSizeInfo.AceCount; i++)
|
|
{
|
|
if (!GetAce(pSrc, i, &pAce))
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
aceHeader = (ACE_HEADER *) pAce;
|
|
|
|
if (!AddAce(pDest, ACL_REVISION, 0xffffffff, pAce, aceHeader->AceSize))
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CSecurityDescriptor::AddAccessDeniedACEToACL(PACL *ppAcl, LPCTSTR pszPrincipal, DWORD dwAccessMask)
|
|
{
|
|
ACL_SIZE_INFORMATION aclSizeInfo;
|
|
int aclSize;
|
|
DWORD returnValue;
|
|
PSID principalSID;
|
|
PACL oldACL, newACL;
|
|
|
|
oldACL = *ppAcl;
|
|
|
|
returnValue = GetPrincipalSID(pszPrincipal, &principalSID);
|
|
if (FAILED(returnValue))
|
|
return returnValue;
|
|
|
|
aclSizeInfo.AclBytesInUse = 0;
|
|
if (*ppAcl != NULL)
|
|
GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
|
|
|
|
aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
|
|
|
|
newACL = (PACL) new BYTE[aclSize];
|
|
|
|
if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
|
|
{
|
|
delete[] (LPBYTE)(principalSID);
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
if (!AddAccessDeniedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID))
|
|
{
|
|
delete[] (LPBYTE)(principalSID);
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
returnValue = CopyACL(newACL, oldACL);
|
|
if (FAILED(returnValue))
|
|
{
|
|
delete[] (LPBYTE)(principalSID);
|
|
return returnValue;
|
|
}
|
|
|
|
*ppAcl = newACL;
|
|
|
|
if (oldACL != NULL)
|
|
delete[] (LPBYTE)(oldACL);
|
|
delete[] (LPBYTE)(principalSID);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CSecurityDescriptor::AddAccessDeniedACEToACL(PACL *ppAcl, const SecurityId *psidPrincipal, DWORD dwAccessMask)
|
|
{
|
|
ACL_SIZE_INFORMATION aclSizeInfo;
|
|
int aclSize;
|
|
DWORD returnValue;
|
|
PSID principalSID;
|
|
PACL oldACL, newACL;
|
|
DWORD dwLen, dwIx;
|
|
|
|
oldACL = *ppAcl;
|
|
|
|
ASSERT(255 >= psidPrincipal->dwRidCount);
|
|
dwLen = GetSidLengthRequired((UCHAR)psidPrincipal->dwRidCount);
|
|
principalSID = (PSID)(new BYTE[dwLen]);
|
|
if (!InitializeSid(
|
|
principalSID,
|
|
(PSID_IDENTIFIER_AUTHORITY)&psidPrincipal->sid,
|
|
(UCHAR)psidPrincipal->dwRidCount))
|
|
{
|
|
delete[] (LPBYTE)principalSID;
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
for (dwIx = 0; dwIx < psidPrincipal->dwRidCount; dwIx += 1)
|
|
*GetSidSubAuthority(principalSID, dwIx) = psidPrincipal->rgRids[dwIx];
|
|
if (!IsValidSid(principalSID))
|
|
{
|
|
delete[] (LPBYTE)principalSID;
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
aclSizeInfo.AclBytesInUse = 0;
|
|
if (*ppAcl != NULL)
|
|
GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
|
|
|
|
aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
|
|
|
|
newACL = (PACL) new BYTE[aclSize];
|
|
|
|
if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
|
|
{
|
|
delete[] (LPBYTE)(principalSID);
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
if (!AddAccessDeniedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID))
|
|
{
|
|
delete[] (LPBYTE)(principalSID);
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
returnValue = CopyACL(newACL, oldACL);
|
|
if (FAILED(returnValue))
|
|
{
|
|
delete[] (LPBYTE)(principalSID);
|
|
return returnValue;
|
|
}
|
|
|
|
*ppAcl = newACL;
|
|
|
|
if (oldACL != NULL)
|
|
delete[] (LPBYTE)(oldACL);
|
|
delete[] (LPBYTE)(principalSID);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CSecurityDescriptor::AddAccessAllowedACEToACL(PACL *ppAcl, const SecurityId *psidPrincipal, DWORD dwAccessMask)
|
|
{
|
|
ACL_SIZE_INFORMATION aclSizeInfo;
|
|
int aclSize;
|
|
DWORD returnValue;
|
|
PSID principalSID = NULL;
|
|
PACL oldACL, newACL;
|
|
DWORD dwLen, dwIx;
|
|
|
|
oldACL = *ppAcl;
|
|
|
|
ASSERT(255 >= psidPrincipal->dwRidCount);
|
|
dwLen = GetSidLengthRequired((UCHAR)psidPrincipal->dwRidCount);
|
|
principalSID = (PSID)(new BYTE[dwLen]);
|
|
if (!InitializeSid(
|
|
principalSID,
|
|
(PSID_IDENTIFIER_AUTHORITY)&psidPrincipal->sid,
|
|
(UCHAR)psidPrincipal->dwRidCount))
|
|
{
|
|
delete[] (LPBYTE)principalSID;
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
for (dwIx = 0; dwIx < psidPrincipal->dwRidCount; dwIx += 1)
|
|
*GetSidSubAuthority(principalSID, dwIx) = psidPrincipal->rgRids[dwIx];
|
|
if (!IsValidSid(principalSID))
|
|
{
|
|
delete[] (LPBYTE)principalSID;
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
aclSizeInfo.AclBytesInUse = 0;
|
|
if (*ppAcl != NULL)
|
|
GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
|
|
|
|
aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
|
|
|
|
newACL = (PACL) new BYTE[aclSize];
|
|
|
|
if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
|
|
{
|
|
delete[] (LPBYTE)principalSID;
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
returnValue = CopyACL(newACL, oldACL);
|
|
if (FAILED(returnValue))
|
|
{
|
|
delete[] (LPBYTE)principalSID;
|
|
return returnValue;
|
|
}
|
|
|
|
if (!AddAccessAllowedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID))
|
|
{
|
|
delete[] (LPBYTE)principalSID;
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
*ppAcl = newACL;
|
|
|
|
if (oldACL != NULL)
|
|
delete[] (LPBYTE)(oldACL);
|
|
delete[] (LPBYTE)principalSID;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CSecurityDescriptor::AddAccessAllowedACEToACL(PACL *ppAcl, LPCTSTR pszPrincipal, DWORD dwAccessMask)
|
|
{
|
|
ACL_SIZE_INFORMATION aclSizeInfo;
|
|
int aclSize;
|
|
DWORD returnValue;
|
|
PSID principalSID;
|
|
PACL oldACL, newACL;
|
|
|
|
oldACL = *ppAcl;
|
|
|
|
returnValue = GetPrincipalSID(pszPrincipal, &principalSID);
|
|
if (FAILED(returnValue))
|
|
return returnValue;
|
|
|
|
aclSizeInfo.AclBytesInUse = 0;
|
|
if (*ppAcl != NULL)
|
|
GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
|
|
|
|
aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
|
|
|
|
newACL = (PACL) new BYTE[aclSize];
|
|
|
|
if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
|
|
{
|
|
delete[] (LPBYTE)(principalSID);
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
returnValue = CopyACL(newACL, oldACL);
|
|
if (FAILED(returnValue))
|
|
{
|
|
delete[] (LPBYTE)(principalSID);
|
|
return returnValue;
|
|
}
|
|
|
|
if (!AddAccessAllowedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID))
|
|
{
|
|
delete[] (LPBYTE)(principalSID);
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
*ppAcl = newACL;
|
|
|
|
if (oldACL != NULL)
|
|
delete[] (LPBYTE)(oldACL);
|
|
delete[] (LPBYTE)(principalSID);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CSecurityDescriptor::RemovePrincipalFromACL(PACL pAcl, LPCTSTR pszPrincipal)
|
|
{
|
|
ACL_SIZE_INFORMATION aclSizeInfo;
|
|
ULONG i;
|
|
LPVOID ace;
|
|
ACCESS_ALLOWED_ACE *accessAllowedAce;
|
|
ACCESS_DENIED_ACE *accessDeniedAce;
|
|
SYSTEM_AUDIT_ACE *systemAuditAce;
|
|
PSID principalSID;
|
|
DWORD returnValue;
|
|
ACE_HEADER *aceHeader;
|
|
|
|
returnValue = GetPrincipalSID(pszPrincipal, &principalSID);
|
|
if (FAILED(returnValue))
|
|
return returnValue;
|
|
|
|
GetAclInformation(pAcl, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
|
|
|
|
for (i = 0; i < aclSizeInfo.AceCount; i++)
|
|
{
|
|
if (!GetAce(pAcl, i, &ace))
|
|
{
|
|
delete[] (LPBYTE)(principalSID);
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
aceHeader = (ACE_HEADER *) ace;
|
|
|
|
if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
|
|
{
|
|
accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace;
|
|
|
|
if (EqualSid(principalSID, (PSID) &accessAllowedAce->SidStart))
|
|
{
|
|
DeleteAce(pAcl, i);
|
|
delete[] (LPBYTE)(principalSID);
|
|
return S_OK;
|
|
}
|
|
} else
|
|
|
|
if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE)
|
|
{
|
|
accessDeniedAce = (ACCESS_DENIED_ACE *) ace;
|
|
|
|
if (EqualSid(principalSID, (PSID) &accessDeniedAce->SidStart))
|
|
{
|
|
DeleteAce(pAcl, i);
|
|
delete[] (LPBYTE)(principalSID);
|
|
return S_OK;
|
|
}
|
|
} else
|
|
|
|
if (aceHeader->AceType == SYSTEM_AUDIT_ACE_TYPE)
|
|
{
|
|
systemAuditAce = (SYSTEM_AUDIT_ACE *) ace;
|
|
|
|
if (EqualSid(principalSID, (PSID) &systemAuditAce->SidStart))
|
|
{
|
|
DeleteAce(pAcl, i);
|
|
delete[] (LPBYTE)(principalSID);
|
|
return S_OK;
|
|
}
|
|
}
|
|
}
|
|
delete[] (LPBYTE)(principalSID);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CSecurityDescriptor::SetPrivilege(LPCTSTR privilege, BOOL bEnable, HANDLE hToken)
|
|
{
|
|
HRESULT hr;
|
|
TOKEN_PRIVILEGES tpPrevious;
|
|
TOKEN_PRIVILEGES tp;
|
|
DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
|
|
LUID luid;
|
|
|
|
// if no token specified open process token
|
|
if (hToken == 0)
|
|
{
|
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
_ASSERTE(FALSE);
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
if (!LookupPrivilegeValue(NULL, privilege, &luid ))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
_ASSERTE(FALSE);
|
|
return hr;
|
|
}
|
|
|
|
tp.PrivilegeCount = 1;
|
|
tp.Privileges[0].Luid = luid;
|
|
tp.Privileges[0].Attributes = 0;
|
|
|
|
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
_ASSERTE(FALSE);
|
|
return hr;
|
|
}
|
|
|
|
tpPrevious.PrivilegeCount = 1;
|
|
tpPrevious.Privileges[0].Luid = luid;
|
|
|
|
if (bEnable)
|
|
tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
|
|
else
|
|
tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes);
|
|
|
|
if (!AdjustTokenPrivileges(hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
_ASSERTE(FALSE);
|
|
return hr;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
CSecurityDescriptor::operator LPSECURITY_ATTRIBUTES()
|
|
{
|
|
m_saAttrs.nLength = sizeof (m_saAttrs);
|
|
m_saAttrs.lpSecurityDescriptor = m_pSD;
|
|
m_saAttrs.bInheritHandle = m_fInheritance;
|
|
return (&m_saAttrs);
|
|
};
|
|
|
|
|