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