/****************************************************************************** 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 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; iGroupCount; 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 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 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 */ }