/*****************************************************************************/ /* Copyright (c) 2000-2001 Microsoft Corporation, All Rights Reserved / /*****************************************************************************/ /* * SecurityDescriptor.cpp - implementation file for CSecureKernelObj class. * * Created: 11-27-00 by Kevin Hughes */ #include "precomp.h" #include "AccessEntry.h" // CAccessEntry class #include "AccessEntryList.h" #include "aclapi.h" #include "DACL.h" // CDACL class #include "SACL.h" // CSACL class #include "SecurityDescriptor.h" #include "securefile.h" #include "tokenprivilege.h" #include "ImpLogonUser.h" #include "AdvApi32Api.h" #include "smartptr.h" #include "SecureKernelObj.h" /////////////////////////////////////////////////////////////////// // // Function: CSecureKernelObj::CSecureKernelObj // // Default class constructor. // // Inputs: // None. // // Outputs: // None. // // Returns: // None. // // Comments: // /////////////////////////////////////////////////////////////////// CSecureKernelObj::CSecureKernelObj() : CSecurityDescriptor() { } /////////////////////////////////////////////////////////////////// // // Function: CSecureKernelObj::CSecureKernelObj // // Alternate Class CTOR // // Inputs: // LPCWSTR wszObjName - The kernel object to handle // security for. // BOOL fGetSACL - Should we get the SACL? // // Outputs: // None. // // Returns: // None. // // Comments: // /////////////////////////////////////////////////////////////////// CSecureKernelObj::CSecureKernelObj( HANDLE hObject, BOOL fGetSACL /*= TRUE*/ ) : CSecurityDescriptor() { SetObject(hObject, fGetSACL); } /////////////////////////////////////////////////////////////////// // // Function: CSecureKernelObj::CSecureKernelObj // // Alternate Class CTOR // // Inputs: // LPCWSTR wszObjName - The object name to handle // security for. // // PSECURITY_DESCRIPTOR pSD - The Security Descriptor to associate with this object // // Outputs: // None. // // Returns: // None. // // Comments: // /////////////////////////////////////////////////////////////////// CSecureKernelObj::CSecureKernelObj( HANDLE hObject, PSECURITY_DESCRIPTOR pSD) : CSecurityDescriptor() { if(InitSecurity(pSD)) { // we just get a copy - we don't take ownership. m_hObject = hObject; } } /////////////////////////////////////////////////////////////////// // // Function: CSecureKernelObj::~CSecureKernelObj // // Class Destructor. // // Inputs: // None. // // Outputs: // None. // // Returns: // None. // // Comments: // /////////////////////////////////////////////////////////////////// CSecureKernelObj::~CSecureKernelObj(void) { } /////////////////////////////////////////////////////////////////// // // Function: CSecureKernelObj::SetObject // // Public Entry point to set which object this instance // of the class is to supply security for. // // Inputs: // HANDLE hObject - The object to handle // security for. // BOOL fGetSACL - Should we get the SACL? // // Outputs: // None. // // Returns: // DWORD ERROR_SUCCESS if successful // // Comments: // // This will clear any previously set filenames and/or security // information. // /////////////////////////////////////////////////////////////////// DWORD CSecureKernelObj::SetObject( HANDLE hObject, BOOL fGetSACL /*= TRUE*/ ) { DWORD dwError = ERROR_SUCCESS; SECURITY_INFORMATION siFlags = OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; // We must have the security privilege enabled in order to access the object's SACL CTokenPrivilege securityPrivilege( SE_SECURITY_NAME ); BOOL fDisablePrivilege = FALSE; if ( fGetSACL ) { fDisablePrivilege = (securityPrivilege.Enable() == ERROR_SUCCESS); siFlags |= SACL_SECURITY_INFORMATION; } // Determine the length needed for self-relative SD DWORD dwLengthNeeded = 0; BOOL fSuccess = ::GetKernelObjectSecurity( hObject, siFlags, NULL, 0, &dwLengthNeeded); dwError = ::GetLastError(); // It is possible that the user lacked the permissions required to obtain the SACL, // even though we set the token's SE_SECURITY_NAME privilege. So if we obtained an // access denied error, try it again, this time without requesting the SACL. if(dwError == ERROR_ACCESS_DENIED || dwError == ERROR_PRIVILEGE_NOT_HELD) { siFlags = OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; fSuccess = ::GetKernelObjectSecurity( hObject, siFlags, NULL, 0, &dwLengthNeeded); dwError = ::GetLastError(); } // The only expected error at this point is insuficient buffer if(!fSuccess && ERROR_INSUFFICIENT_BUFFER == dwError) { PSECURITY_DESCRIPTOR pSD = NULL; try { pSD = new BYTE[dwLengthNeeded]; if(pSD) { // Now obtain security descriptor if(::GetKernelObjectSecurity( hObject, siFlags, pSD, dwLengthNeeded, &dwLengthNeeded)) { dwError = ERROR_SUCCESS; if(InitSecurity(pSD)) { m_hObject = hObject; } else { dwError = ERROR_INVALID_PARAMETER; } } else { dwError = ::GetLastError(); } // free up the security descriptor delete pSD; } } catch(...) { delete pSD; throw; } } // Cleanup the Name Privilege as necessary. if(fDisablePrivilege) { securityPrivilege.Enable(FALSE); } return dwError; } /////////////////////////////////////////////////////////////////// // // Function: CSecureKernelObj::WriteAcls // // Protected entry point called by CSecurityDescriptor when // a user Applies Security and wants to apply security for // the DACL and/or SACL. // // Inputs: // PSECURITY_DESCRIPTOR pAbsoluteSD - Security // descriptor to apply to // the object. // SECURITY_INFORMATION securityinfo - Flags // indicating which ACL(s) // to set. // // Outputs: // None. // // Returns: // DWORD ERROR_SUCCESS if successful // // Comments: // /////////////////////////////////////////////////////////////////// DWORD CSecureKernelObj::WriteAcls( PSECURITY_DESCRIPTOR pAbsoluteSD, SECURITY_INFORMATION securityinfo) { DWORD dwError = ERROR_SUCCESS; // We must have the security privilege enabled in order to access the object's SACL CTokenPrivilege securityPrivilege( SE_SECURITY_NAME ); BOOL fDisablePrivilege = FALSE; if(securityinfo & SACL_SECURITY_INFORMATION || securityinfo & PROTECTED_SACL_SECURITY_INFORMATION || securityinfo & UNPROTECTED_SACL_SECURITY_INFORMATION) { fDisablePrivilege = (securityPrivilege.Enable() == ERROR_SUCCESS); } if(!::SetKernelObjectSecurity( m_hObject, securityinfo, pAbsoluteSD)) { dwError = ::GetLastError(); } // Cleanup the Name Privilege as necessary. if(fDisablePrivilege) { securityPrivilege.Enable(FALSE); } return dwError; } /////////////////////////////////////////////////////////////////// // // Function: CSecureKernelObj::WriteOwner // // Protected entry point called by CSecurityDescriptor when // a user Applies Security and wants to apply security for // the owner. // // Inputs: // PSECURITY_DESCRIPTOR pAbsoluteSD - Security // descriptor to apply to // the object. // // Outputs: // None. // // Returns: // DWORD ERROR_SUCCESS if successful // // Comments: // /////////////////////////////////////////////////////////////////// DWORD CSecureKernelObj::WriteOwner(PSECURITY_DESCRIPTOR pAbsoluteSD) { DWORD dwError = ERROR_SUCCESS; // Open with the appropriate access, set the security and leave if(!::SetKernelObjectSecurity( m_hObject, OWNER_SECURITY_INFORMATION, pAbsoluteSD)) { dwError = ::GetLastError(); } return dwError; } DWORD CSecureKernelObj::AllAccessMask(void) { // File specific All Access Mask return TOKEN_ALL_ACCESS; }