|
|
/******************************************************************************
Copyright (c) 2000 Microsoft Corporation
Module Name: Security.cpp
Abstract: This file contains the implementation of various security functions/classes.
Revision History: Davide Massarenti (Dmassare) 04/26/2000 created
******************************************************************************/
#include "stdafx.h"
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
const SID MPC::SecurityDescriptor::s_EveryoneSid = { SID_REVISION, 1, SECURITY_WORLD_SID_AUTHORITY, SECURITY_WORLD_RID }; const SID MPC::SecurityDescriptor::s_SystemSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY , SECURITY_LOCAL_SYSTEM_RID };
const MPC::SID2 MPC::SecurityDescriptor::s_AdminSid = { SID_REVISION , 2 , SECURITY_NT_AUTHORITY , SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_USER_RID_ADMIN };
const MPC::SID2 MPC::SecurityDescriptor::s_Alias_AdminsSid = { SID_REVISION , 2 , SECURITY_NT_AUTHORITY , SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS };
const MPC::SID2 MPC::SecurityDescriptor::s_Alias_PowerUsersSid = { SID_REVISION , 2 , SECURITY_NT_AUTHORITY , SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS };
const MPC::SID2 MPC::SecurityDescriptor::s_Alias_UsersSid = { SID_REVISION , 2 , SECURITY_NT_AUTHORITY , SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS };
const MPC::SID2 MPC::SecurityDescriptor::s_Alias_GuestsSid = { SID_REVISION , 2 , SECURITY_NT_AUTHORITY , SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS };
////////////////////////////////////////////////////////////////////////////////
static DWORD Local_GenerateAccessMask( /*[in]*/ SECURITY_INFORMATION secInfo, /*[in]*/ bool fRead ) { DWORD dwAccess;
if(fRead) { dwAccess = 0;
if(secInfo & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION)) { dwAccess |= READ_CONTROL; }
if(secInfo & SACL_SECURITY_INFORMATION) { dwAccess |= ACCESS_SYSTEM_SECURITY; } } else { dwAccess = MAXIMUM_ALLOWED;
if(secInfo & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION)) { dwAccess |= WRITE_OWNER; }
if(secInfo & DACL_SECURITY_INFORMATION) { dwAccess |= WRITE_DAC; }
if(secInfo & SACL_SECURITY_INFORMATION) { dwAccess |= ACCESS_SYSTEM_SECURITY; } }
return dwAccess; }
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::SecurityDescriptor::AllocateMemory( /*[in/out]*/ LPVOID& ptr , /*[in] */ size_t iLen ) { ReleaseMemory( ptr );
ATLTRY(ptr = malloc( iLen ));
return (ptr == NULL) ? E_OUTOFMEMORY : S_OK; }
void MPC::SecurityDescriptor::ReleaseMemory( /*[in/out]*/ LPVOID& ptr ) { if(ptr) { free( ptr ); ptr = NULL; } }
void MPC::SecurityDescriptor::InitLsaString( /*[in/out]*/ LSA_UNICODE_STRING& lsaString , /*[in ]*/ LPCWSTR szText ) { if(szText == NULL) { lsaString.Buffer = NULL; lsaString.Length = 0; lsaString.MaximumLength = 0; } else { DWORD dwLen = wcslen( szText );
lsaString.Buffer = (LPWSTR) szText; lsaString.Length = dwLen * sizeof(WCHAR); lsaString.MaximumLength = (dwLen+1) * sizeof(WCHAR); } }
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::SecurityDescriptor::SetPrivilege( /*[in]*/ LPCWSTR Privilege , /*[in]*/ BOOL bEnable , /*[in]*/ HANDLE hToken ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetPrivilege" );
HRESULT hr; TOKEN_PRIVILEGES tp; TOKEN_PRIVILEGES tpPrevious; DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES); LUID luid; HANDLE hTokenUsed = NULL;
// if no token specified open process token
if(hToken == NULL) { __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::OpenProcessToken( ::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTokenUsed ));
hToken = hTokenUsed; }
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::LookupPrivilegeValueW( NULL, Privilege, &luid ));
tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = 0;
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious ));
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;
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::AdjustTokenPrivileges( hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
if(hTokenUsed) ::CloseHandle( hTokenUsed );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::AddPrivilege( /*[in]*/ LPCWSTR szPrincipal , /*[in]*/ LPCWSTR szPrivilege ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::AddPrivilege" );
HRESULT hr; NTSTATUS ntRes; LSA_OBJECT_ATTRIBUTES objectAttributes; ::ZeroMemory( &objectAttributes, sizeof(objectAttributes) ); LSA_UNICODE_STRING lsaPrivilege; PSID pSid = NULL; HANDLE policyHandle = NULL;
InitLsaString( lsaPrivilege, szPrivilege );
__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pSid ));
ntRes = ::LsaOpenPolicy( NULL, &objectAttributes, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &policyHandle ); if(ntRes != STATUS_SUCCESS) { __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::LsaNtStatusToWinError( ntRes )); }
ntRes = ::LsaAddAccountRights( policyHandle, pSid, &lsaPrivilege, 1 ); if(ntRes != STATUS_SUCCESS) { __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::LsaNtStatusToWinError( ntRes )); }
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)pSid );
if(policyHandle) ::LsaClose( policyHandle );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::RemovePrivilege( /*[in]*/ LPCWSTR szPrincipal , /*[in]*/ LPCWSTR szPrivilege ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::RemovePrivilege" );
HRESULT hr; NTSTATUS ntRes; LSA_OBJECT_ATTRIBUTES objectAttributes; ::ZeroMemory( &objectAttributes, sizeof(objectAttributes) ); LSA_UNICODE_STRING lsaPrivilege; PSID pSid = NULL; HANDLE policyHandle = NULL;
InitLsaString( lsaPrivilege, szPrivilege );
__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pSid ));
ntRes = ::LsaOpenPolicy( NULL, &objectAttributes, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &policyHandle ); if(ntRes != STATUS_SUCCESS) { __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::LsaNtStatusToWinError( ntRes )); }
ntRes = ::LsaRemoveAccountRights( policyHandle, pSid, FALSE, &lsaPrivilege, 1 ); if(ntRes != STATUS_SUCCESS) { __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::LsaNtStatusToWinError( ntRes )); }
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)pSid );
if(policyHandle) ::LsaClose( policyHandle );
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::SecurityDescriptor::GetTokenSids( /*[in] */ HANDLE hToken , /*[out]*/ PSID *ppUserSid , /*[out]*/ PSID *ppGroupSid ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetTokenSids" );
HRESULT hr; DWORD dwRes; PTOKEN_USER ptkUser = NULL; PTOKEN_PRIMARY_GROUP ptkGroup = NULL; PSID pSid = NULL; DWORD dwSize = 0;
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 ); if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER) { __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes); }
__MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)ptkUser, dwSize ));
// Get Sid of process token.
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetTokenInformation( hToken, TokenUser, ptkUser, dwSize, &dwSize ));
// Make a copy of the Sid for the return value
dwSize = ::GetLengthSid( ptkUser->User.Sid ); __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( pSid, dwSize ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CopySid( dwSize, pSid, ptkUser->User.Sid ));
ATLASSERT(::IsValidSid( pSid ));
*ppUserSid = pSid; pSid = NULL; }
if(ppGroupSid) { // Get length required for TokenPrimaryGroup by specifying buffer length of 0
::GetTokenInformation( hToken, TokenPrimaryGroup, NULL, 0, &dwSize ); if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER) { __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes); }
__MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)ptkGroup, dwSize ));
// Get Sid of process token.
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetTokenInformation( hToken, TokenPrimaryGroup, ptkGroup, dwSize, &dwSize ));
// Make a copy of the Sid for the return value
dwSize = ::GetLengthSid( ptkGroup->PrimaryGroup ); __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( pSid, dwSize ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CopySid( dwSize, pSid, ptkGroup->PrimaryGroup ));
ATLASSERT(::IsValidSid( pSid ));
*ppGroupSid = pSid; pSid = NULL; }
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)ptkUser ); ReleaseMemory( (void*&)ptkGroup ); ReleaseMemory( (void*&)pSid );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::GetProcessSids( /*[out]*/ PSID *ppUserSid , /*[out]*/ PSID *ppGroupSid ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetProcessSids" );
HRESULT hr; HANDLE hToken = NULL;
if(ppUserSid ) *ppUserSid = NULL; if(ppGroupSid) *ppGroupSid = NULL;
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::OpenProcessToken( ::GetCurrentProcess(), TOKEN_QUERY, &hToken ));
__MPC_EXIT_IF_METHOD_FAILS(hr, GetTokenSids( hToken, ppUserSid, ppGroupSid ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
if(hToken) ::CloseHandle( hToken );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::GetThreadSids( /*[out]*/ PSID *ppUserSid , /*[out]*/ PSID *ppGroupSid , /*[in] */ BOOL bOpenAsSelf ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetThreadSids" );
HRESULT hr; HANDLE hToken = NULL;
if(ppUserSid ) *ppUserSid = NULL; if(ppGroupSid) *ppGroupSid = NULL;
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::OpenThreadToken( ::GetCurrentThread(), TOKEN_QUERY, bOpenAsSelf, &hToken ));
__MPC_EXIT_IF_METHOD_FAILS(hr, GetTokenSids( hToken, ppUserSid, ppGroupSid ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
if(hToken) ::CloseHandle( hToken );
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::SecurityDescriptor::VerifyPrincipal( /*[in]*/ LPCWSTR szPrincipal ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::VerifyPrincipal" );
HRESULT hr; PSID pSid = NULL;
__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pSid ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)pSid );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::ConvertPrincipalToSID( /*[in ]*/ LPCWSTR szPrincipal , /*[out]*/ PSID& pSid , /*[out]*/ LPCWSTR *pszDomain ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::ConvertPrincipalToSID" );
HRESULT hr; DWORD dwRes; LPWSTR szDomain = NULL; DWORD dwDomainSize = 0; DWORD dwSidSize = 0; PSID pSidLocal = NULL; SID_NAME_USE snu;
if(pszDomain) *pszDomain = NULL;
if(::ConvertStringSidToSidW( szPrincipal, &pSidLocal )) { dwSidSize = ::GetLengthSid( pSidLocal );
__MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)pSid, dwSidSize ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CopySid( dwSidSize, pSid, pSidLocal )); } else { //
// Call to get size info for alloc
//
::LookupAccountNameW( NULL, szPrincipal, NULL, &dwSidSize, NULL, &dwDomainSize, &snu ); if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER) { __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes); }
__MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)pSid , dwSidSize )); __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)szDomain, sizeof(WCHAR)*(dwDomainSize+1) ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::LookupAccountNameW( NULL, szPrincipal, pSid, &dwSidSize, szDomain, &dwDomainSize, &snu ));
if(pszDomain) { *pszDomain = szDomain; szDomain = NULL; } }
hr = S_OK;
__MPC_FUNC_CLEANUP;
if(pSidLocal) ::LocalFree( pSidLocal );
ReleaseMemory( (void*&)szDomain );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::ConvertSIDToPrincipal( /*[in] */ PSID pSid , /*[out]*/ LPCWSTR *pszPrincipal , /*[out]*/ LPCWSTR *pszDomain ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::ConvertSIDToPrincipal" );
HRESULT hr; DWORD dwRes; LPWSTR szPrincipal = NULL; LPWSTR szDomain = NULL; DWORD dwPrincipalSize = 0; DWORD dwDomainSize = 0; SID_NAME_USE snu;
if(pszPrincipal) *pszPrincipal = NULL; if(pszDomain ) *pszDomain = NULL;
// Call to get size info for alloc
::LookupAccountSidW( NULL, pSid, NULL, &dwPrincipalSize, NULL, &dwDomainSize, &snu ); if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER) { __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes); }
__MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)szPrincipal, sizeof(WCHAR)*(dwPrincipalSize+1) )); __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)szDomain , sizeof(WCHAR)*(dwDomainSize +1) ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::LookupAccountSidW( NULL, pSid, szPrincipal, &dwPrincipalSize, szDomain, &dwDomainSize, &snu ));
if(pszDomain == NULL && szDomain[0]) { if(pszPrincipal) { LPWSTR szPrincipalAndDomain = NULL; UINT cchAlloc = dwPrincipalSize+dwDomainSize+2;
__MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)szPrincipalAndDomain, cchAlloc*sizeof(WCHAR)));
StringCchCopyW( szPrincipalAndDomain, cchAlloc, szDomain ); StringCchCatW( szPrincipalAndDomain, cchAlloc, L"\\" ); StringCchCatW( szPrincipalAndDomain, cchAlloc, szPrincipal );
*pszPrincipal = szPrincipalAndDomain; } } else { if(pszPrincipal) { *pszPrincipal = szPrincipal; szPrincipal = NULL; } if(pszDomain ) { *pszDomain = szDomain ; szDomain = NULL; } }
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)szPrincipal ); ReleaseMemory( (void*&)szDomain );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::ConvertSIDToPrincipal( /*[in] */ PSID pSid , /*[out]*/ MPC::wstring& strPrincipal ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::ConvertSIDToPrincipal" );
HRESULT hr; LPCWSTR szPrincipal = NULL;
__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertSIDToPrincipal( pSid, &szPrincipal ));
strPrincipal = SAFEWSTR( szPrincipal ); hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)szPrincipal );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::NormalizePrincipalToStringSID( /*[in ]*/ LPCWSTR szPrincipal , /*[in ]*/ LPCWSTR szDomain , /*[out]*/ MPC::wstring& strSID ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::NormalizePrincipalToStringSID" );
HRESULT hr; MPC::wstring strAccount; PSID pSid = NULL; LPWSTR szUserSid = NULL;
if(szDomain) { strAccount = szDomain; strAccount += L"\\"; } strAccount += SAFEWSTR(szPrincipal);
//
// First convert the principal to a SID, then back to a string.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( strAccount.c_str(), pSid ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::ConvertSidToStringSidW( pSid, &szUserSid ));
strSID = SAFEWSTR( szUserSid ); hr = S_OK;
__MPC_FUNC_CLEANUP;
if(szUserSid) ::LocalFree( szUserSid );
ReleaseMemory( (void*&)pSid );
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::SecurityDescriptor::GetAccountName( /*[in]*/ LPCWSTR szPrincipal, /*[out]*/ MPC::wstring& strName ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetAccountName" );
HRESULT hr; PSID pSid = NULL; LPCWSTR szUser = NULL; LPCWSTR szDomain = NULL;
__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pSid ));
__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertSIDToPrincipal( pSid, &szUser, &szDomain ));
strName = SAFEWSTR(szUser);
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)pSid ); ReleaseMemory( (void*&)szUser ); ReleaseMemory( (void*&)szDomain );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::GetAccountDomain( /*[in]*/ LPCWSTR szPrincipal, /*[out]*/ MPC::wstring& strName ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetAccountDomain" );
HRESULT hr; PSID pSid = NULL; LPCWSTR szUser = NULL; LPCWSTR szDomain = NULL;
__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pSid ));
__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertSIDToPrincipal( pSid, &szUser, &szDomain ));
strName = SAFEWSTR(szDomain);
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)pSid ); ReleaseMemory( (void*&)szUser ); ReleaseMemory( (void*&)szDomain );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::GetAccountDisplayName( /*[in]*/ LPCWSTR szPrincipal, /*[out]*/ MPC::wstring& strName ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetAccountDisplayName" );
HRESULT hr; PSID pSid = NULL; LPCWSTR szUser = NULL; LPWSTR szDisplay = NULL; ULONG lSize = 0;
__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pSid )); __MPC_EXIT_IF_METHOD_FAILS(hr, ConvertSIDToPrincipal( pSid, &szUser ));
//
// First call is to get size, second to get the actual data.
//
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::TranslateNameW( szUser, NameSamCompatible, NameDisplay, NULL, &lSize ));
__MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)szDisplay, sizeof(WCHAR)*(lSize+1) ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::TranslateNameW( szUser, NameSamCompatible, NameDisplay, szDisplay, &lSize ));
strName = SAFEWSTR(szDisplay);
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)pSid ); ReleaseMemory( (void*&)szUser ); ReleaseMemory( (void*&)szDisplay );
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::SecurityDescriptor::CopyACL( /*[in]*/ PACL pDest, /*[in]*/ PACL pSrc ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::CopyACL" );
HRESULT hr; ACL_SIZE_INFORMATION aclSizeInfo; ACE_HEADER* aceHeader; LPVOID pACE;
if(pSrc) { __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetAclInformation( pSrc, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation ));
// Copy all of the ACEs to the new ACL
for(DWORD i = 0; i < aclSizeInfo.AceCount; i++) { __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetAce( pSrc, i, (LPVOID*)&pACE ));
aceHeader = (ACE_HEADER *)pACE;
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::AddAce( pDest, ACL_REVISION, 0xFFFFFFFF, pACE, aceHeader->AceSize )); }
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::IsValidAcl( pDest )); }
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::CloneACL( /*[in/out]*/ PACL& pDest , /*[in ]*/ PACL pSrc ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::CloneACL" );
HRESULT hr; ACL_SIZE_INFORMATION aclSizeInfo;
ReleaseMemory( (void*&)pDest );
if(pSrc) { __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetAclInformation( pSrc, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation ));
__MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)pDest, pSrc->AclSize ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::InitializeAcl( pDest, pSrc->AclSize, ACL_REVISION ));
__MPC_EXIT_IF_METHOD_FAILS(hr, CopyACL( pDest, pSrc )); }
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::EnsureACLSize( /*[in/out]*/ PACL& pACL , /*[in ]*/ DWORD dwExpand ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::EnsureACLSize" );
HRESULT hr; DWORD dwSizeAvailable; DWORD dwSizeRequired; ACL_SIZE_INFORMATION aclSizeInfo; PACL newACL = NULL;
if(pACL) { __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetAclInformation( pACL, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation ));
dwSizeAvailable = pACL->AclSize; dwSizeRequired = aclSizeInfo.AclBytesInUse + dwExpand; } else { ::ZeroMemory( &aclSizeInfo, sizeof(aclSizeInfo) );
dwSizeAvailable = 0; dwSizeRequired = sizeof(ACL) + dwExpand; }
//
// If too little free space is
//
if(dwSizeAvailable < dwSizeRequired) { __MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)newACL, dwSizeRequired ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::InitializeAcl( newACL, dwSizeRequired, ACL_REVISION ));
__MPC_EXIT_IF_METHOD_FAILS(hr, CopyACL( newACL, pACL ));
ReleaseMemory( (void*&)pACL ); pACL = newACL; newACL = NULL; }
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)newACL );
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::SecurityDescriptor::RemovePrincipalFromACL( /*[in]*/ PACL pACL , /*[in]*/ PSID pPrincipalSid , /*[in]*/ int pos ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::RemovePrincipalFromACL" );
HRESULT hr; DWORD i; int seen = 0; ACL_SIZE_INFORMATION aclSizeInfo; PACE_HEADER aceHeader; PSID pSid;
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetAclInformation( pACL, (LPVOID)&aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation ));
for(i = 0; i < aclSizeInfo.AceCount; i++) { __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetAce(pACL, i, (LPVOID*)&aceHeader));
switch(aceHeader->AceType) { case ACCESS_ALLOWED_ACE_TYPE : pSid = &((PACCESS_ALLOWED_ACE )aceHeader)->SidStart; break; case ACCESS_ALLOWED_OBJECT_ACE_TYPE: pSid = &((PACCESS_ALLOWED_OBJECT_ACE)aceHeader)->SidStart; break; case ACCESS_DENIED_ACE_TYPE : pSid = &((PACCESS_DENIED_ACE )aceHeader)->SidStart; break; case ACCESS_DENIED_OBJECT_ACE_TYPE : pSid = &((PACCESS_DENIED_OBJECT_ACE )aceHeader)->SidStart; break; case SYSTEM_AUDIT_ACE_TYPE : pSid = &((PSYSTEM_AUDIT_ACE )aceHeader)->SidStart; break; case SYSTEM_AUDIT_OBJECT_ACE_TYPE : pSid = &((PSYSTEM_AUDIT_OBJECT_ACE )aceHeader)->SidStart; break; default : __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG); }
if(::EqualSid( pPrincipalSid, pSid )) { if(seen == pos || pos == -1) { ::DeleteAce( pACL, i );
aclSizeInfo.AceCount--; i--; }
seen++; } }
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::AddACEToACL( /*[in/out]*/ PACL& pACL , /*[in ]*/ PSID pPrincipalSid , /*[in ]*/ DWORD dwAceType , /*[in ]*/ DWORD dwAceFlags , /*[in ]*/ DWORD dwAccessMask , /*[in ]*/ GUID* guidObjectType , /*[in ]*/ GUID* guidInheritedObjectType ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::AddACEToACL" );
HRESULT hr; DWORD dwSize; BOOL fRes;
dwSize = ::GetLengthSid( pPrincipalSid );
switch(dwAceType) { case ACCESS_ALLOWED_ACE_TYPE : dwSize += sizeof(ACCESS_ALLOWED_ACE ) - sizeof(DWORD); break; case ACCESS_ALLOWED_OBJECT_ACE_TYPE: dwSize += sizeof(ACCESS_ALLOWED_OBJECT_ACE) - sizeof(DWORD); break; case ACCESS_DENIED_ACE_TYPE : dwSize += sizeof(ACCESS_DENIED_ACE ) - sizeof(DWORD); break; case ACCESS_DENIED_OBJECT_ACE_TYPE : dwSize += sizeof(ACCESS_DENIED_OBJECT_ACE ) - sizeof(DWORD); break; case SYSTEM_AUDIT_ACE_TYPE : dwSize += sizeof(SYSTEM_AUDIT_ACE ) - sizeof(DWORD); break; case SYSTEM_AUDIT_OBJECT_ACE_TYPE : dwSize += sizeof(SYSTEM_AUDIT_OBJECT_ACE ) - sizeof(DWORD); break; default : __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG); }
__MPC_EXIT_IF_METHOD_FAILS(hr, EnsureACLSize( pACL, dwSize ));
switch(dwAceType) { case ACCESS_ALLOWED_ACE_TYPE : fRes = ::AddAccessAllowedAceEx ( pACL, ACL_REVISION, dwAceFlags, dwAccessMask , pPrincipalSid ); break; case ACCESS_ALLOWED_OBJECT_ACE_TYPE: fRes = ::AddAccessAllowedObjectAce( pACL, ACL_REVISION, dwAceFlags, dwAccessMask, guidObjectType, guidInheritedObjectType, pPrincipalSid ); break; case ACCESS_DENIED_ACE_TYPE : fRes = ::AddAccessDeniedAceEx ( pACL, ACL_REVISION, dwAceFlags, dwAccessMask , pPrincipalSid ); break; case ACCESS_DENIED_OBJECT_ACE_TYPE : fRes = ::AddAccessDeniedObjectAce ( pACL, ACL_REVISION, dwAceFlags, dwAccessMask, guidObjectType, guidInheritedObjectType, pPrincipalSid ); break; case SYSTEM_AUDIT_ACE_TYPE : fRes = ::AddAuditAccessAceEx ( pACL, ACL_REVISION, dwAceFlags, dwAccessMask , pPrincipalSid, TRUE, TRUE ); break; case SYSTEM_AUDIT_OBJECT_ACE_TYPE : fRes = ::AddAuditAccessObjectAce ( pACL, ACL_REVISION, dwAceFlags, dwAccessMask, guidObjectType, guidInheritedObjectType, pPrincipalSid, TRUE, TRUE ); break; }
if(fRes == FALSE) { __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::GetLastError()); }
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
MPC::SecurityDescriptor::SecurityDescriptor() { m_pSD = NULL; // PSECURITY_DESCRIPTOR m_pSD;
m_pOwner = NULL; // PSID m_pOwner;
m_bOwnerDefaulted = TRUE; // BOOL m_bOwnerDefaulted;
m_pGroup = NULL; // PSID m_pGroup;
m_bGroupDefaulted = TRUE; // BOOL m_bGroupDefaulted;
m_pDACL = NULL; // PACL m_pDACL;
m_bDaclDefaulted = TRUE; // BOOL m_bDaclDefaulted;
m_pSACL = NULL; // PACL m_pSACL;
m_bSaclDefaulted = TRUE; // BOOL m_bSaclDefaulted;
}
MPC::SecurityDescriptor::~SecurityDescriptor() { CleanUp(); }
void MPC::SecurityDescriptor::CleanUp() { ReleaseMemory( (void*&)m_pSD ); ReleaseMemory( (void*&)m_pOwner ); ReleaseMemory( (void*&)m_pGroup ); ReleaseMemory( (void*&)m_pDACL ); ReleaseMemory( (void*&)m_pSACL );
m_bOwnerDefaulted = TRUE; m_bGroupDefaulted = TRUE; m_bDaclDefaulted = TRUE; m_bSaclDefaulted = TRUE; }
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::SecurityDescriptor::Initialize() { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::Initialize" );
HRESULT hr;
CleanUp();
__MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (void*&)m_pSD, sizeof(SECURITY_DESCRIPTOR) ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::InitializeSecurityDescriptor( m_pSD, SECURITY_DESCRIPTOR_REVISION ));
//
// Set the DACL to allow EVERYONE.
//
#pragma prefast(suppress:248, this is a base class, derived classes are responsible for setting the appropriate DACL (PREfast bug 516684))
::SetSecurityDescriptorDacl( m_pSD, TRUE, NULL, FALSE );
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::InitializeFromProcessToken( /*[in]*/ BOOL bDefaulted ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::InitializeFromProcessToken" );
HRESULT hr; PSID pUserSid = NULL; PSID pGroupSid = NULL;
__MPC_EXIT_IF_METHOD_FAILS(hr, Initialize());
__MPC_EXIT_IF_METHOD_FAILS(hr, GetProcessSids( &pUserSid, &pGroupSid ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SetOwner( pUserSid , bDefaulted )); __MPC_EXIT_IF_METHOD_FAILS(hr, SetGroup( pGroupSid, bDefaulted ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( pUserSid ); ReleaseMemory( pGroupSid );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::InitializeFromThreadToken( /*[in]*/ BOOL bDefaulted , /*[in]*/ BOOL bRevertToProcessToken ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::InitializeFromThreadToken" );
HRESULT hr; PSID pUserSid = NULL; PSID pGroupSid = NULL;
__MPC_EXIT_IF_METHOD_FAILS(hr, Initialize());
if(FAILED(hr = GetThreadSids( &pUserSid, &pGroupSid ))) { if(HRESULT_CODE(hr) == ERROR_NO_TOKEN && bRevertToProcessToken) { __MPC_EXIT_IF_METHOD_FAILS(hr, GetProcessSids( &pUserSid, &pGroupSid )); } else { __MPC_FUNC_LEAVE; } }
__MPC_EXIT_IF_METHOD_FAILS(hr, SetOwner( pUserSid , bDefaulted )); __MPC_EXIT_IF_METHOD_FAILS(hr, SetGroup( pGroupSid, bDefaulted ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( pUserSid ); ReleaseMemory( pGroupSid );
__MPC_FUNC_EXIT(hr); } ////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::SecurityDescriptor::ConvertFromString( /*[in]*/ LPCWSTR szSD ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::ConvertFromString" );
HRESULT hr; PSECURITY_DESCRIPTOR pSD = NULL;
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::ConvertStringSecurityDescriptorToSecurityDescriptorW( szSD, SDDL_REVISION_1, &pSD, NULL ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Attach( pSD ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
if(pSD) ::LocalFree( pSD );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::ConvertToString( /*[out]*/ BSTR *pbstrSD ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::ConvertToString" );
HRESULT hr; LPWSTR szSD = NULL;
__MPC_PARAMCHECK_BEGIN(hr) __MPC_PARAMCHECK_POINTER_AND_SET(pbstrSD,NULL); __MPC_PARAMCHECK_END();
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::ConvertSecurityDescriptorToStringSecurityDescriptorW( m_pSD, SDDL_REVISION_1, s_SecInfo_ALL, &szSD, NULL ));
*pbstrSD = ::SysAllocString( szSD ); hr = S_OK;
__MPC_FUNC_CLEANUP;
if(szSD) ::LocalFree( szSD );
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::SecurityDescriptor::Attach( /*[in]*/ PSECURITY_DESCRIPTOR pSelfRelativeSD ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::Attach" );
HRESULT hr; PSID pOwnerSid; PSID pGroupSid; PACL pDACL; PACL pSACL; BOOL bDefaulted; BOOL bPresent; ACCESS_ALLOWED_ACE* pACE; SECURITY_DESCRIPTOR_CONTROL sdcFlags; DWORD dwRev;
__MPC_EXIT_IF_METHOD_FAILS(hr, Initialize());
if(pSelfRelativeSD == NULL) // Empty SD?
{ __MPC_SET_ERROR_AND_EXIT(hr, S_OK); }
//
// Copy flags of interest.
//
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetSecurityDescriptorControl( pSelfRelativeSD , &sdcFlags, &dwRev )); __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorControl( m_pSD, s_sdcMask, sdcFlags & s_sdcMask ));
//
// Copy owner and group.
//
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetSecurityDescriptorOwner( pSelfRelativeSD, &pOwnerSid, &bDefaulted )); __MPC_EXIT_IF_METHOD_FAILS(hr, SetOwner( pOwnerSid, bDefaulted ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetSecurityDescriptorGroup( pSelfRelativeSD, &pGroupSid, &bDefaulted )); __MPC_EXIT_IF_METHOD_FAILS(hr, SetGroup( pGroupSid, bDefaulted ));
//
// Copy the existing DACL.
//
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetSecurityDescriptorDacl( pSelfRelativeSD, &bPresent, &pDACL, &m_bDaclDefaulted ));
if(bPresent) { __MPC_EXIT_IF_METHOD_FAILS(hr, CloneACL( m_pDACL, pDACL ));
//
// set the DACL
//
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorDacl( m_pSD, m_pDACL ? TRUE : FALSE, m_pDACL, m_bDaclDefaulted )); }
//
// Copy the existing SACL.
//
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetSecurityDescriptorSacl( pSelfRelativeSD, &bPresent, &pSACL, &m_bSaclDefaulted ));
if(bPresent) { __MPC_EXIT_IF_METHOD_FAILS(hr, CloneACL( m_pSACL, pSACL ));
// set the SACL
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorSacl(m_pSD, m_pSACL ? TRUE : FALSE, m_pSACL, m_bSaclDefaulted )); }
if(m_pSD) { __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::IsValidSecurityDescriptor( m_pSD )); }
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::AttachObject( /*[in]*/ HANDLE hObject, /*[in]*/ SECURITY_INFORMATION secInfo ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::AttachObject" );
HRESULT hr; DWORD dwRes; DWORD dwSize; PSECURITY_DESCRIPTOR pSD = NULL;
::GetKernelObjectSecurity( hObject, secInfo, pSD, 0, &dwSize ); if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER) { if(dwRes == ERROR_SUCCESS) { __MPC_SET_ERROR_AND_EXIT(hr, Initialize()); // Empty SD.
}
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes); }
__MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( pSD, dwSize ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetKernelObjectSecurity( hObject, secInfo, pSD, dwSize, &dwSize ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Attach( pSD ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( pSD );
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::SecurityDescriptor::GetControl( /*[out]*/ SECURITY_DESCRIPTOR_CONTROL& sdc ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetControl" );
HRESULT hr; DWORD dwRev;
ATLASSERT(m_pSD);
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetSecurityDescriptorControl( m_pSD, &sdc, &dwRev ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::SetControl( /*[in ]*/ SECURITY_DESCRIPTOR_CONTROL sdc ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetControl" );
HRESULT hr;
ATLASSERT(m_pSD);
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorControl( m_pSD, s_sdcMask, s_sdcMask & sdc ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::SetOwner( /*[in]*/ PSID pOwnerSid , /*[in]*/ BOOL bDefaulted ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetOwner" );
HRESULT hr;
ATLASSERT(m_pSD);
m_bOwnerDefaulted = bDefaulted;
//
// Mark the SD as having no owner
//
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorOwner( m_pSD, NULL, bDefaulted ));
ReleaseMemory( m_pOwner );
if(pOwnerSid) { // Make a copy of the Sid for the return value
DWORD dwSize = ::GetLengthSid( pOwnerSid );
__MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( m_pOwner, dwSize ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CopySid( dwSize, m_pOwner, pOwnerSid ));
ATLASSERT(::IsValidSid( m_pOwner ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorOwner( m_pSD, m_pOwner, bDefaulted )); }
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::SetOwner( /*[in]*/ LPCWSTR szOwnerName , /*[in]*/ BOOL bDefaulted ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetOwner" );
HRESULT hr; PSID pOwnerSid = NULL;
__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szOwnerName, pOwnerSid ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SetOwner( pOwnerSid, bDefaulted ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)pOwnerSid );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::SetGroup( /*[in]*/ PSID pGroupSid , /*[in]*/ BOOL bDefaulted ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetGroup" );
HRESULT hr;
ATLASSERT(m_pSD);
m_bGroupDefaulted = bDefaulted;
//
// Mark the SD as having no owner
//
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorGroup( m_pSD, NULL, bDefaulted ));
ReleaseMemory( m_pGroup );
if(pGroupSid) { // Make a copy of the Sid for the return value
DWORD dwSize = ::GetLengthSid( pGroupSid );
__MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( m_pGroup, dwSize ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CopySid( dwSize, m_pGroup, pGroupSid ));
ATLASSERT(::IsValidSid( m_pGroup ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorGroup( m_pSD, m_pGroup, bDefaulted )); }
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::SetGroup( /*[in]*/ LPCWSTR szGroupName , /*[in]*/ BOOL bDefaulted ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetGroup" );
HRESULT hr; PSID pGroupSid = NULL;
__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szGroupName, pGroupSid ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SetGroup( pGroupSid, bDefaulted ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)pGroupSid );
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::SecurityDescriptor::Remove( /*[in]*/ PSID pPrincipalSid , /*[in]*/ int pos ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::Remove" );
HRESULT hr;
ATLASSERT(m_pSD);
__MPC_EXIT_IF_METHOD_FAILS(hr, RemovePrincipalFromACL( m_pDACL, pPrincipalSid, pos ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorDacl( m_pSD, TRUE, m_pDACL, FALSE ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::Remove( /*[in]*/ LPCWSTR szPrincipal , /*[in]*/ int pos ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::Remove" );
HRESULT hr; PSID pPrincipalSid = NULL;
__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pPrincipalSid ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Remove( pPrincipalSid, pos ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)pPrincipalSid );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::Add( /*[in]*/ PSID pPrincipalSid , /*[in]*/ DWORD dwAceType , /*[in]*/ DWORD dwAceFlags , /*[in]*/ DWORD dwAccessMask , /*[in]*/ GUID* guidObjectType , /*[in]*/ GUID* guidInheritedObjectType ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::Add" );
HRESULT hr;
ATLASSERT(m_pSD);
__MPC_EXIT_IF_METHOD_FAILS(hr, AddACEToACL( m_pDACL, pPrincipalSid, dwAceType, dwAceFlags, dwAccessMask, guidObjectType, guidInheritedObjectType ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetSecurityDescriptorDacl( m_pSD, TRUE, m_pDACL, FALSE ));
m_bDaclDefaulted = FALSE; hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::Add( /*[in]*/ LPCWSTR szPrincipal , /*[in]*/ DWORD dwAceType , /*[in]*/ DWORD dwAceFlags , /*[in]*/ DWORD dwAccessMask , /*[in]*/ GUID* guidObjectType , /*[in]*/ GUID* guidInheritedObjectType ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::Add" );
HRESULT hr; PSID pPrincipalSid = NULL;
__MPC_EXIT_IF_METHOD_FAILS(hr, ConvertPrincipalToSID( szPrincipal, pPrincipalSid ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Add( pPrincipalSid, dwAceType, dwAceFlags, dwAccessMask, guidObjectType, guidInheritedObjectType ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)pPrincipalSid );
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::SecurityDescriptor::GetForFile( /*[in]*/ LPCWSTR szFilename , /*[in]*/ SECURITY_INFORMATION secInfo ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetForFile" );
HRESULT hr; PSECURITY_DESCRIPTOR pSD = NULL; DWORD dwLen = 0; DWORD dwRes;
__MPC_PARAMCHECK_BEGIN(hr) __MPC_PARAMCHECK_STRING_NOT_EMPTY(szFilename); __MPC_PARAMCHECK_END();
//
// Get the security descriptor for the file.
//
::GetFileSecurityW( szFilename, secInfo, NULL, 0, &dwLen ); if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER) { if(dwRes == ERROR_SUCCESS) { __MPC_SET_ERROR_AND_EXIT(hr, Initialize()); // Empty SD.
}
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes); }
__MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (LPVOID&)pSD, dwLen ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetFileSecurityW( szFilename, secInfo, pSD, dwLen, &dwLen ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Attach( pSD ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)pSD );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::SetForFile( /*[in]*/ LPCWSTR szFilename , /*[in]*/ SECURITY_INFORMATION secInfo ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetForFile" );
HRESULT hr;
__MPC_PARAMCHECK_BEGIN(hr) __MPC_PARAMCHECK_STRING_NOT_EMPTY(szFilename); __MPC_PARAMCHECK_END();
//
// Set the security descriptor for the file.
//
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetFileSecurityW( szFilename, secInfo, GetSD() ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::GetForRegistry( /*[in]*/ LPCWSTR szKey , /*[in]*/ SECURITY_INFORMATION secInfo , /*[in]*/ HKEY hKeyRoot ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::GetForRegistry" );
HRESULT hr; HKEY hKey = NULL; PSECURITY_DESCRIPTOR pSD = NULL; DWORD dwLen; DWORD dwRes;
__MPC_PARAMCHECK_BEGIN(hr) __MPC_PARAMCHECK_STRING_NOT_EMPTY(szKey); __MPC_PARAMCHECK_END();
if(hKeyRoot == NULL) { //
// Extract the hive from the string....
//
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::RegKey::ParsePath( szKey, hKeyRoot, szKey )); }
__MPC_EXIT_IF_SYSCALL_FAILS(hr, dwRes, ::RegOpenKeyExW( hKeyRoot, szKey, 0, Local_GenerateAccessMask( secInfo, true ), &hKey ));
//
// Get the security descriptor for the registry key.
//
dwLen = 0; dwRes = ::RegGetKeySecurity( hKey, secInfo, NULL, &dwLen ); if(dwRes != ERROR_INSUFFICIENT_BUFFER) { if(dwRes == ERROR_SUCCESS) { __MPC_SET_ERROR_AND_EXIT(hr, Initialize()); // Empty SD.
}
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes); }
__MPC_EXIT_IF_METHOD_FAILS(hr, AllocateMemory( (LPVOID&)pSD, dwLen ));
__MPC_EXIT_IF_SYSCALL_FAILS(hr, dwRes, ::RegGetKeySecurity( hKey, secInfo, pSD, &dwLen ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Attach( pSD ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
ReleaseMemory( (void*&)pSD );
if(hKey) ::RegCloseKey( hKey );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SecurityDescriptor::SetForRegistry( /*[in]*/ LPCWSTR szKey , /*[in]*/ SECURITY_INFORMATION secInfo , /*[in]*/ HKEY hKeyRoot ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SecurityDescriptor::SetForRegistry" );
HRESULT hr; HKEY hKey = NULL; DWORD dwRes;
__MPC_PARAMCHECK_BEGIN(hr) __MPC_PARAMCHECK_STRING_NOT_EMPTY(szKey); __MPC_PARAMCHECK_END();
if(hKeyRoot == NULL) { //
// Extract the hive from the string....
//
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::RegKey::ParsePath( szKey, hKeyRoot, szKey )); }
__MPC_EXIT_IF_SYSCALL_FAILS(hr, dwRes, ::RegOpenKeyExW( hKeyRoot, szKey, 0, Local_GenerateAccessMask( secInfo, false ), &hKey ));
//
// Set the security descriptor for the registry key.
//
__MPC_EXIT_IF_SYSCALL_FAILS(hr, dwRes, ::RegSetKeySecurity( hKey, secInfo, GetSD() ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
if(hKey) ::RegCloseKey( hKey );
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
MPC::Impersonation::Impersonation() { m_hToken = NULL; // HANDLE m_hToken;
m_fImpersonating = false; // bool m_fImpersonating;
}
MPC::Impersonation::Impersonation( /*[in]*/ const MPC::Impersonation& imp ) { m_hToken = NULL; // HANDLE m_hToken;
m_fImpersonating = false; // bool m_fImpersonating;
*this = imp; }
MPC::Impersonation::~Impersonation() { Release(); }
MPC::Impersonation& MPC::Impersonation::operator=( /*[in]*/ const MPC::Impersonation& imp ) { Release();
if(!::DuplicateHandle( ::GetCurrentProcess(), imp.m_hToken, ::GetCurrentProcess(), & m_hToken, 0, FALSE, DUPLICATE_SAME_ACCESS )) { ; // Error...
}
return *this; }
////////////////////////////////////////////////////////////////////////////////
void MPC::Impersonation::Release() { (void)RevertToSelf();
if(m_hToken) { ::CloseHandle( m_hToken ); m_hToken = NULL; } }
HRESULT MPC::Impersonation::Initialize( DWORD dwDesiredAccess ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::Impersonation::Initialize" );
HRESULT hr; CComPtr<IServerSecurity> ss; bool fRevert = false;
Release();
__MPC_EXIT_IF_METHOD_FAILS(hr, ::CoGetCallContext( IID_IServerSecurity, (void**)&ss ));
__MPC_EXIT_IF_METHOD_FAILS(hr, ss->ImpersonateClient()); fRevert = true;
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::OpenThreadToken( ::GetCurrentThread(), dwDesiredAccess, TRUE, &m_hToken ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
if(fRevert && ss) ss->RevertToSelf();
__MPC_FUNC_EXIT(hr); }
void MPC::Impersonation::Attach( /*[in]*/ HANDLE hToken ) { Release();
m_hToken = hToken; }
HANDLE MPC::Impersonation::Detach() { HANDLE hToken = m_hToken;
(void)RevertToSelf();
m_hToken = NULL;
return hToken; }
HRESULT MPC::Impersonation::Impersonate() { __MPC_FUNC_ENTRY( COMMONID, "MPC::Impersonation::Impersonate" );
HRESULT hr;
__MPC_PARAMCHECK_BEGIN(hr) __MPC_PARAMCHECK_NOTNULL(m_hToken); __MPC_PARAMCHECK_END();
if(m_fImpersonating == false) { __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetThreadToken( NULL, m_hToken ));
m_fImpersonating = true; }
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::Impersonation::RevertToSelf() { __MPC_FUNC_ENTRY( COMMONID, "MPC::Impersonation::RevertToSelf" );
HRESULT hr;
if(m_fImpersonating) { __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetThreadToken( NULL, NULL ));
m_fImpersonating = false; }
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
MPC::AccessCheck::AccessCheck() { m_hToken = NULL; // HANDLE m_hToken;
}
MPC::AccessCheck::~AccessCheck() { Release(); }
void MPC::AccessCheck::Release() { if(m_hToken) { ::CloseHandle( m_hToken ); m_hToken = NULL; } }
HRESULT MPC::AccessCheck::GetTokenFromImpersonation() { __MPC_FUNC_ENTRY( COMMONID, "MPC::AccessCheck::GetTokenFromImpersonation" );
HRESULT hr; MPC::Impersonation imp;
Release();
__MPC_EXIT_IF_METHOD_FAILS(hr, imp.Initialize( TOKEN_QUERY ));
m_hToken = imp.Detach(); hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
void MPC::AccessCheck::Attach( /*[in]*/ HANDLE hToken ) { Release();
m_hToken = hToken; }
HANDLE MPC::AccessCheck::Detach() { HANDLE hToken = m_hToken;
m_hToken = NULL;
return hToken; }
HRESULT MPC::AccessCheck::Verify( /*[in ]*/ DWORD dwDesired , /*[out]*/ BOOL& fGranted , /*[out]*/ DWORD& dwGranted , /*[in ]*/ PSECURITY_DESCRIPTOR sd ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::AccessCheck::Verify" );
HRESULT hr; PRIVILEGE_SET PrivilegeSet; DWORD dwPrivSetSize = sizeof( PRIVILEGE_SET ); GENERIC_MAPPING ObjMap = { ACCESS_READ , ACCESS_WRITE, ACCESS_NONE , ACCESS_ALL };
fGranted = FALSE;
if(sd == NULL || !::IsValidSecurityDescriptor( sd ) ) { __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG); }
//
// This only does something if we specify generic access rights
// like GENERIC_ALL. We are not.
//
::MapGenericMask( &dwDesired, &ObjMap );
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::AccessCheck( sd , m_hToken , dwDesired , &ObjMap , &PrivilegeSet , &dwPrivSetSize , &dwGranted , &fGranted ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::AccessCheck::Verify( /*[in ]*/ DWORD dwDesired , /*[out]*/ BOOL& fGranted , /*[out]*/ DWORD& dwGranted , /*[in ]*/ MPC::SecurityDescriptor& sd ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::AccessCheck::Verify" );
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, Verify( dwDesired, fGranted, dwGranted, sd.GetSD() ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::AccessCheck::Verify( /*[in ]*/ DWORD dwDesired , /*[out]*/ BOOL& fGranted , /*[out]*/ DWORD& dwGranted , /*[in ]*/ LPCWSTR sd ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::AccessCheck::Verify" );
HRESULT hr; MPC::SecurityDescriptor sdd;
__MPC_EXIT_IF_METHOD_FAILS(hr, sdd.ConvertFromString( sd ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Verify( dwDesired, fGranted, dwGranted, sdd.GetSD() ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::ChangeSD( /*[in]*/ MPC::SecurityDescriptor& sdd , /*[in]*/ MPC::FileSystemObject& fso , /*[in]*/ SECURITY_INFORMATION secInfo , /*[in]*/ bool fDeep , /*[in]*/ bool fApplyToDirs , /*[in]*/ bool fApplyToFiles ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::ChangeSD" );
HRESULT hr; MPC::wstring szPath; MPC::FileSystemObject::List lst; MPC::FileSystemObject::Iter it;
__MPC_EXIT_IF_METHOD_FAILS(hr, fso.get_Path( szPath ));
if((fApplyToDirs && fso.IsDirectory()) || (fApplyToFiles && fso.IsFile ()) ) { //
// Set the security descriptor for the object.
//
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetFileSecurityW( szPath.c_str(), secInfo, sdd.GetSD() )); }
if(fDeep) { __MPC_EXIT_IF_METHOD_FAILS(hr, fso.EnumerateFiles( lst )); for(it=lst.begin(); it != lst.end(); it++) { __MPC_EXIT_IF_METHOD_FAILS(hr, ChangeSD( sdd, *(*it), secInfo, true, fApplyToDirs, fApplyToFiles )); }
__MPC_EXIT_IF_METHOD_FAILS(hr, fso.EnumerateFolders( lst )); for(it=lst.begin(); it != lst.end(); it++) { __MPC_EXIT_IF_METHOD_FAILS(hr, ChangeSD( sdd, *(*it), secInfo, true, fApplyToDirs, fApplyToFiles )); } }
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::ChangeSD( /*[in]*/ MPC::SecurityDescriptor& sdd , /*[in]*/ LPCWSTR szRoot , /*[in]*/ SECURITY_INFORMATION secInfo , /*[in]*/ bool fDeep , /*[in]*/ bool fApplyToDirs , /*[in]*/ bool fApplyToFiles ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::ChangeSD" );
HRESULT hr; MPC::wstring strRoot( szRoot ); MPC::SubstituteEnvVariables( strRoot ); MPC::FileSystemObject fso ( strRoot.c_str() );
__MPC_EXIT_IF_METHOD_FAILS(hr, fso.CreateDir( true ));
__MPC_EXIT_IF_METHOD_FAILS(hr, ChangeSD( sdd, fso, secInfo, fDeep, fApplyToDirs, fApplyToFiles ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::GetCallerPrincipal( /*[in ]*/ bool fImpersonate , /*[out]*/ CComBSTR& bstrUser , /*[out]*/ DWORD *pdwAllowedIdentity ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::GetCallerPrincipal" );
HRESULT hr; DWORD dwRes; LPWSTR szUserSid = NULL; PTOKEN_USER ptkUser = NULL; PTOKEN_GROUPS ptkGroups = NULL; DWORD dwSize; MPC::Impersonation imp;
if(fImpersonate) { __MPC_EXIT_IF_METHOD_FAILS(hr, imp.Initialize( TOKEN_QUERY )); } else { HANDLE hToken;
//
// First try the token attached to the thread, then the one attached to the process.
//
if(::OpenThreadToken( ::GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken ) == FALSE) { if((dwRes = ::GetLastError()) != ERROR_NO_TOKEN) { __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes); }
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::OpenProcessToken( ::GetCurrentProcess(), TOKEN_QUERY, &hToken )); }
imp.Attach( hToken ); }
//
// Get caller's credentials.
//
dwSize = 0; ::GetTokenInformation( (HANDLE)imp, TokenUser, NULL, 0, &dwSize ); if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER) { __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes); }
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SecurityDescriptor::AllocateMemory( (void*&)ptkUser, dwSize ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetTokenInformation( (HANDLE)imp, TokenUser, ptkUser, dwSize, &dwSize ));
//
// Convert to string.
//
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::ConvertSidToStringSidW( ptkUser->User.Sid, &szUserSid ));
//
// Verify identity, if requested.
//
if(pdwAllowedIdentity) { DWORD dwAllowedIdentity = 0;
if(::EqualSid( ptkUser->User.Sid, (PSID)& MPC::SecurityDescriptor::s_SystemSid )) dwAllowedIdentity |= IDENTITY_SYSTEM; if(::EqualSid( ptkUser->User.Sid, (PSID)&(SID&)MPC::SecurityDescriptor::s_AdminSid )) dwAllowedIdentity |= IDENTITY_ADMIN;
//
// Get caller's groups.
//
dwSize = 0; ::GetTokenInformation( (HANDLE)imp, TokenGroups, NULL, 0, &dwSize ); if((dwRes = ::GetLastError()) != ERROR_INSUFFICIENT_BUFFER) { __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes); }
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SecurityDescriptor::AllocateMemory( (void*&)ptkGroups, dwSize ));
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::GetTokenInformation( (HANDLE)imp, TokenGroups, ptkGroups, dwSize, &dwSize ));
for(DWORD i=0; i<ptkGroups->GroupCount; i++) { SID_AND_ATTRIBUTES* grp = &ptkGroups->Groups[i];
if(grp->Attributes & SE_GROUP_ENABLED) { if(::EqualSid( grp->Sid, (PSID)&(SID&)MPC::SecurityDescriptor::s_Alias_AdminsSid )) dwAllowedIdentity |= IDENTITY_ADMINS; if(::EqualSid( grp->Sid, (PSID)&(SID&)MPC::SecurityDescriptor::s_Alias_PowerUsersSid )) dwAllowedIdentity |= IDENTITY_POWERUSERS; if(::EqualSid( grp->Sid, (PSID)&(SID&)MPC::SecurityDescriptor::s_Alias_UsersSid )) dwAllowedIdentity |= IDENTITY_USERS; if(::EqualSid( grp->Sid, (PSID)&(SID&)MPC::SecurityDescriptor::s_Alias_GuestsSid )) dwAllowedIdentity |= IDENTITY_GUESTS; } }
*pdwAllowedIdentity = dwAllowedIdentity; }
bstrUser = szUserSid; hr = S_OK;
__MPC_FUNC_CLEANUP;
if(szUserSid) ::LocalFree( szUserSid );
MPC::SecurityDescriptor::ReleaseMemory( (void*&)ptkUser ); MPC::SecurityDescriptor::ReleaseMemory( (void*&)ptkGroups );
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::CheckCallerAgainstPrincipal( /*[in ]*/ bool fImpersonate , /*[out]*/ BSTR bstrUser , /*[in ]*/ DWORD dwAllowedIdentity ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::CheckCallerAgainstPrincipal" );
HRESULT hr; CComBSTR bstrRealUser; DWORD dwTokenIdentity;
__MPC_EXIT_IF_METHOD_FAILS(hr, GetCallerPrincipal( fImpersonate, bstrRealUser, &dwTokenIdentity ));
if(!MPC::StrICmp( bstrRealUser, bstrUser )) { //
// Same user, exit.
//
__MPC_SET_ERROR_AND_EXIT(hr, S_OK); }
if((dwTokenIdentity & dwAllowedIdentity) != 0) { //
// Not same user, but an authorized one, exit.
//
__MPC_SET_ERROR_AND_EXIT(hr, S_OK); }
hr = E_ACCESSDENIED;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
HRESULT MPC::GetInterfaceSecurity( /*[in ]*/ IUnknown* pUnk , /*[out]*/ DWORD *pAuthnSvc , /*[out]*/ DWORD *pAuthzSvc , /*[out]*/ OLECHAR* *pServerPrincName , /*[out]*/ DWORD *pAuthnLevel , /*[out]*/ DWORD *pImpLevel , /*[out]*/ RPC_AUTH_IDENTITY_HANDLE *pAuthInfo , /*[out]*/ DWORD *pCapabilities ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::GetInterfaceSecurity" );
HRESULT hr; CComPtr<IClientSecurity> pBlanket;
__MPC_EXIT_IF_METHOD_FAILS(hr, pUnk->QueryInterface( IID_IClientSecurity, (void**)&pBlanket ));
__MPC_EXIT_IF_METHOD_FAILS(hr, pBlanket->QueryBlanket( pUnk , pAuthnSvc , pAuthzSvc , pServerPrincName , pAuthnLevel , pImpLevel , pAuthInfo , pCapabilities ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SetInterfaceSecurity( /*[in]*/ IUnknown* pUnk , /*[in]*/ DWORD *pAuthnSvc , /*[in]*/ DWORD *pAuthzSvc , /*[in]*/ OLECHAR* pServerPrincName , /*[in]*/ DWORD *pAuthnLevel , /*[in]*/ DWORD *pImpLevel , /*[in]*/ RPC_AUTH_IDENTITY_HANDLE *pAuthInfo , /*[in]*/ DWORD *pCapabilities ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::SetInterfaceSecurity" );
HRESULT hr; CComPtr<IClientSecurity> pBlanket; DWORD AuthnSvc; DWORD AuthzSvc; OLECHAR* ServerPrincName = NULL; DWORD AuthnLevel; DWORD ImpLevel; DWORD Capabilities;
__MPC_EXIT_IF_METHOD_FAILS(hr, pUnk->QueryInterface( IID_IClientSecurity, (void**)&pBlanket ));
//
// First read the current settings.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, pBlanket->QueryBlanket( pUnk , &AuthnSvc , &AuthzSvc , &ServerPrincName , &AuthnLevel , &ImpLevel , NULL , &Capabilities ));
//
// Update only some of them.
//
if(pAuthnSvc ) AuthnSvc = *pAuthnSvc; if(pAuthzSvc ) AuthzSvc = *pAuthzSvc; if(pAuthnLevel ) AuthnLevel = *pAuthnLevel; if(pImpLevel ) ImpLevel = *pImpLevel; if(pCapabilities ) Capabilities = *pCapabilities;
//
// Write back.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, pBlanket->SetBlanket( pUnk , AuthnSvc , AuthzSvc , pServerPrincName , AuthnLevel , ImpLevel , pAuthInfo , Capabilities ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
if(ServerPrincName) ::CoTaskMemFree( ServerPrincName );
__MPC_FUNC_EXIT(hr); }
HRESULT MPC::SetInterfaceSecurity_ImpLevel( /*[in]*/ IUnknown* pUnk , /*[in]*/ DWORD ImpLevel ) { return MPC::SetInterfaceSecurity( pUnk , /* IUnknown* pUnk */ NULL , /* DWORD *pAuthnSvc */ NULL , /* DWORD *pAuthzSvc */ NULL , /* OLECHAR* pServerPrincName */ NULL , /* DWORD *pAuthnLevel */ &ImpLevel , /* DWORD *pImpLevel */ NULL , /* RPC_AUTH_IDENTITY_HANDLE *pAuthInfo */ NULL ); /* DWORD *pCapabilities */ }
|