//+-------------------------------------------------------------------------- // File: certsd.h // Contents: CA's security descriptor class declaration //--------------------------------------------------------------------------- #ifndef __CERTSD_H__ #define __CERTSD_H__ namespace CertSrv { typedef struct _SID_LIST { DWORD dwSidCount; DWORD SidListStart[ANYSIZE_ARRAY]; } SID_LIST, *PSID_LIST; HRESULT GetWellKnownSID( PSID *ppSid, SID_IDENTIFIER_AUTHORITY *pAuth, BYTE SubauthorityCount, DWORD SubAuthority1, DWORD SubAuthority2=0, DWORD SubAuthority3=0, DWORD SubAuthority4=0, DWORD SubAuthority5=0, DWORD SubAuthority6=0, DWORD SubAuthority7=0, DWORD SubAuthority8=0); // caller is responsible for LocalFree'ing PSID HRESULT GetEveryoneSID(PSID *ppSid); HRESULT GetLocalSystemSID(PSID *ppSid); HRESULT GetBuiltinAdministratorsSID(PSID *ppSid); // This class wraps a SD with single writer multiple reader access control on // it. Allows any number of threads to LockGet() the pointer to the SD if no // thread is in the middle of a Set(). Set() is blocked until all threads // that already retrieved the SD released it (calling Unlock) // // Also provides the support for persistently saving/loading the SD to registy class CProtectedSecurityDescriptor { public: CProtectedSecurityDescriptor() : m_pSD(NULL), m_fInitialized(false), m_cReaders(0), m_hevtNoReaders(NULL), m_pcwszSanitizedName(NULL), m_pcwszPersistRegVal(NULL) {}; ~CProtectedSecurityDescriptor() { Uninitialize(); } void Uninitialize() { if(m_pSD) { LocalFree(m_pSD); m_pSD = NULL; } if(m_hevtNoReaders) { CloseHandle(m_hevtNoReaders); m_hevtNoReaders = NULL; } m_pcwszSanitizedName = NULL; m_fInitialized = false; m_cReaders = 0; if(IsInitialized()) { DeleteCriticalSection(&m_csWrite); } } BOOL IsInitialized() const { return m_fInitialized;} // init, loading SD from the registry HRESULT Initialize(LPCWSTR pwszSanitizedName); // init from supplied SD HRESULT Initialize(const PSECURITY_DESCRIPTOR pSD, LPCWSTR pwszSanitizedName); HRESULT InitializeFromTemplate(LPCWSTR pcwszTemplate, LPCWSTR pwszSanitizedName); HRESULT Set(const PSECURITY_DESCRIPTOR pSD); HRESULT LockGet(PSECURITY_DESCRIPTOR *ppSD); HRESULT Unlock(); PSECURITY_DESCRIPTOR Get() { return m_pSD; }; // load SD from registry HRESULT Load(); // save SD to registry HRESULT Save(); // delete SD from registry HRESULT Delete(); LPCWSTR GetPersistRegistryVal() { return m_pcwszPersistRegVal;} void ImportResourceStrings(LPCWSTR *pcwszStrings) {m_pcwszResources = pcwszStrings;}; protected: HRESULT Init(LPCWSTR pwszSanitizedName); HRESULT SetSD(PSECURITY_DESCRIPTOR pSD); PSECURITY_DESCRIPTOR m_pSD; bool m_fInitialized; LONG m_cReaders; HANDLE m_hevtNoReaders; CRITICAL_SECTION m_csWrite; LPCWSTR m_pcwszSanitizedName; // no free LPCWSTR m_pcwszPersistRegVal; // no free static LPCWSTR const *m_pcwszResources; // no free }; //class CProtectedSecurityDescriptor // The class stores a list of officers/groups and the principals they are // allowed to manage certificates for: // // officerSID1 -> clientSID1, clientSID2... // officerSID2 -> clientSID3, clientSID4... // // The information is stored as a DACL containing callback ACEs . // The officer SID is stored as in the ACE's SID and the list of client // SIDs are stored in the custom data space following the officer SID // (see definition of _ACCESS_*_CALLBACK_ACE) // // The DACL will be used to AccessCheck if an officer is allowed to perform // an action over a certificate. // // The SD contains only the officer DACL, SACL or other data is not used. class COfficerRightsSD : public CProtectedSecurityDescriptor { public: COfficerRightsSD() : m_fEnabled(FALSE) { m_pcwszPersistRegVal = wszREGOFFICERRIGHTS; } HRESULT InitializeEmpty(); HRESULT Initialize(LPCWSTR pwszSanitizedName); // The officer rights have to be in sync with the CA security descriptor. // An officer ACE for a certain SID can exist only if the principal is // an officer as defined by the CA SD. // Merge sets the internal officer DACL making sure it's in sync // with the CA SD: // - removes any ACE found in the officer DACL which is not present as an // allow ACE in the CA DACL // - add an Everyone ACE in the officer DACL for each allow ACE in CA DACL // that is not already present HRESULT Merge( PSECURITY_DESCRIPTOR pOfficerSD, PSECURITY_DESCRIPTOR pCASD); // Same as above but using the internal officer SD. Used to generate the // initial officer SD and to update it when CA SD changes HRESULT Adjust( PSECURITY_DESCRIPTOR pCASD); BOOL IsEnabled() { return m_fEnabled; } void SetEnable(BOOL fEnable) { m_fEnabled = fEnable;} HRESULT Save(); HRESULT Load(); HRESULT Validate() { return S_OK; } static HRESULT ConvertToString( IN PSECURITY_DESCRIPTOR pSD, OUT LPWSTR& rpwszSD); protected: static HRESULT ConvertAceToString( IN PACCESS_ALLOWED_CALLBACK_ACE pAce, OUT OPTIONAL PDWORD pdwSize, IN OUT OPTIONAL LPWSTR pwszSD); BOOL m_fEnabled; }; // class COfficerRightsSD class CCertificateAuthoritySD : public CProtectedSecurityDescriptor { public: CCertificateAuthoritySD() : m_pDefaultDSSD(NULL), m_pDefaultServiceSD(NULL), m_pDefaultDSAcl(NULL), m_pDefaultServiceAcl(NULL), m_pwszComputerSID(NULL) { m_pcwszPersistRegVal = wszREGCASECURITY; } ~CCertificateAuthoritySD() { if(m_pDefaultDSSD) LocalFree(m_pDefaultDSSD); if(m_pDefaultServiceSD) LocalFree(m_pDefaultServiceSD); if(m_pwszComputerSID) LocalFree(m_pwszComputerSID); } // Sets a new CA SD. Uses the new DACL but keeps the old owner, group and // SACL. // Also rebuilds the DACL for objects CA owns (eg DS pKIEnrollmentService, // service). The new DACL contains a default DACL plus additional aces // depending on the object: // DS - add an enroll ace for each enroll ace found in CA DACL // Service - add a full control ace for each CA admin ace HRESULT Set(const PSECURITY_DESCRIPTOR pSD, bool fSetDSSecurity); static HRESULT Validate(const PSECURITY_DESCRIPTOR pSD); HRESULT ResetSACL(); HRESULT MapAndSetDaclOnObjects(bool fSetDSSecurity); // Upgrade SD from Win2k. HRESULT UpgradeWin2k(bool fUseEnterpriseAcl); static HRESULT ConvertToString( IN PSECURITY_DESCRIPTOR pSD, OUT LPWSTR& rpwszSD); protected: enum ObjType { ObjType_DS, ObjType_Service, }; HRESULT MapAclGetSize(PVOID pAce, ObjType type, DWORD& dwSize); HRESULT MapAclAddAce(PACL pAcl, ObjType type, PVOID pAce); HRESULT SetDefaultAcl(ObjType type); HRESULT SetComputerSID(); HRESULT MapAclSetOnDS(const PACL pAcl); HRESULT MapAclSetOnService(const PACL pAcl); DWORD GetUpgradeAceSizeAndType(PVOID pAce, DWORD *pdwType, PSID *ppSid); static HRESULT ConvertAceToString( IN PACCESS_ALLOWED_ACE pAce, OUT OPTIONAL PDWORD pdwSize, IN OUT OPTIONAL LPWSTR pwszSD); PSECURITY_DESCRIPTOR m_pDefaultDSSD; PSECURITY_DESCRIPTOR m_pDefaultServiceSD; PACL m_pDefaultDSAcl; // no free PACL m_pDefaultServiceAcl; // no free LPWSTR m_pwszComputerSID; }; } // namespace CertSrv #endif //__CERTSD_H__