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.
2368 lines
71 KiB
2368 lines
71 KiB
/******************************************************************************
|
|
|
|
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 */
|
|
}
|