///////////////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1998 Active Voice Corporation. All Rights Reserved. // // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation. // // Other brand and29 product names used herein are trademarks of their respective owners. // // The entire program and user interface including the structure, sequence, selection, // and arrangement of the dialog, the exclusively "yes" and "no" choices represented // by "1" and "2," and each dialog message are protected by copyrights registered in // the United States and by international treaties. // // Protected by one or more of the following United States patents: 5,070,526, 5,488,650, // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054. // // Active Voice Corporation // Seattle, Washington // USA // ///////////////////////////////////////////////////////////////////////////////////////// #include #include #include "res.h" #include "objsec.h" #include "rndsec.h" #define DSOP_FILTER_COMMON ( DSOP_FILTER_USERS | \ DSOP_FILTER_UNIVERSAL_GROUPS_SE | \ DSOP_FILTER_GLOBAL_GROUPS_SE ) #define DSOP_FILTER_DL_COMMON1 ( DSOP_DOWNLEVEL_FILTER_USERS \ | DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS \ | DSOP_DOWNLEVEL_FILTER_COMPUTERS \ ) #define DSOP_FILTER_DL_COMMON2 ( DSOP_FILTER_DL_COMMON1 \ | DSOP_DOWNLEVEL_FILTER_ALL_WELLKNOWN_SIDS \ ) #define DSOP_FILTER_DL_COMMON3 ( DSOP_FILTER_DL_COMMON2 \ | DSOP_DOWNLEVEL_FILTER_LOCAL_GROUPS \ ) #define DECLARE_SCOPE(t,f,b,m,n,d) \ { sizeof(DSOP_SCOPE_INIT_INFO), (t), (f), { { (b), (m), (n) }, (d) }, NULL, NULL, S_OK } static const DSOP_SCOPE_INIT_INFO g_aDSOPScopes[] = { // The domain to which the target computer is joined. DECLARE_SCOPE(DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN, \ DSOP_SCOPE_FLAG_STARTING_SCOPE, \ 0, \ DSOP_FILTER_COMMON & ~DSOP_FILTER_UNIVERSAL_GROUPS_SE, \ DSOP_FILTER_COMMON, \ 0), DECLARE_SCOPE(DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN,0,0,0,0,DSOP_FILTER_DL_COMMON2), // The Global Catalog DECLARE_SCOPE(DSOP_SCOPE_TYPE_GLOBAL_CATALOG,0,DSOP_FILTER_COMMON|DSOP_FILTER_WELL_KNOWN_PRINCIPALS,0,0,0), // The domains in the same forest (enterprise) as the domain to which // the target machine is joined. Note these can only be DS-aware DECLARE_SCOPE(DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN,0,DSOP_FILTER_COMMON,0,0,0), // Domains external to the enterprise but trusted directly by the // domain to which the target machine is joined. DECLARE_SCOPE(DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN | DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN, \ 0, \ DSOP_FILTER_COMMON, \ 0, \ 0, \ DSOP_DOWNLEVEL_FILTER_USERS | DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS), // Target computer scope. Computer scopes are always treated as // downlevel (i.e., they use the WinNT provider). DECLARE_SCOPE(DSOP_SCOPE_TYPE_TARGET_COMPUTER,0,0,0,0,DSOP_FILTER_DL_COMMON3), }; GENERIC_MAPPING ObjMap = { ACCESS_READ, ACCESS_MODIFY, ACCESS_DELETE, }; SI_ACCESS g_siObjAccesses[] = { { &GUID_NULL, ACCESS_READ, MAKEINTRESOURCEW(IDS_PRIV_READ), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, { &GUID_NULL, ACCESS_MODIFY, MAKEINTRESOURCEW(IDS_PRIV_MODIFY), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, { &GUID_NULL, ACCESS_DELETE, MAKEINTRESOURCEW(IDS_PRIV_DELETE), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, }; #define g_iObjDefAccess GENERIC_READ // The following array defines the inheritance types for my containers. SI_INHERIT_TYPE g_siObjInheritTypes[] = { &GUID_NULL, 0, L"This container/object only", }; ///////////////////////////////////////////////////////////////////////////////////////// CObjSecurity::CObjSecurity() : m_cRef(1) { USES_CONVERSION; m_dwSIFlags = NULL; m_pConfProp = NULL; // // Let's have a properly constructor // m_bstrObject = NULL; m_bstrPage = NULL; m_pObjectPicker = NULL; } ///////////////////////////////////////////////////////////////////////////////////////// CObjSecurity::~CObjSecurity() { // // Properly deallocation // if( m_bstrObject ) SysFreeString( m_bstrObject ); if( m_bstrPage ) SysFreeString( m_bstrPage ); if ( m_pObjectPicker ) m_pObjectPicker->Release(); } ///////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CObjSecurity::InternalInitialize( CONFPROP* pConfProp ) { HRESULT hr = S_OK; // // we can initialize BSTRs here // m_bstrObject = SysAllocString( T2COLE(String(g_hInstLib, IDS_CONFPROP_PERMISSIONS_OBJECT )) ); if( IsBadStringPtr( m_bstrObject, (UINT)-1) ) return E_OUTOFMEMORY; m_bstrPage = SysAllocString( T2COLE(String(g_hInstLib, IDS_CONFPROP_PERMISSIONS_PAGE )) ); if( IsBadStringPtr( m_bstrPage, (UINT)-1) ) { SysFreeString( m_bstrObject); return E_OUTOFMEMORY; } m_pConfProp = pConfProp; return hr; } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// //IUnknown Methods ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_(ULONG) CObjSecurity::AddRef() { return ++m_cRef; } ///////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_(ULONG) CObjSecurity::Release() { if (--m_cRef == 0) { delete this; return 0; } return m_cRef; } ///////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CObjSecurity::QueryInterface(REFIID riid, LPVOID FAR* ppv) { if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ISecurityInformation)) { *ppv = (LPSECURITYINFO)this; } else if ( IsEqualIID(riid, IID_IDsObjectPicker) ) { *ppv = static_cast (this); } else { *ppv = NULL; return E_NOINTERFACE; } m_cRef++; return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// // IDsObjectPicker ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CObjSecurity::Initialize( PDSOP_INIT_INFO pInitInfo ) { HRESULT hr = S_OK; DSOP_INIT_INFO InitInfo; PDSOP_SCOPE_INIT_INFO pDSOPScopes = NULL; _ASSERT( pInitInfo->cbSize >= FIELD_OFFSET(DSOP_INIT_INFO, cAttributesToFetch) ); // Create an instance of the object if (!m_pObjectPicker) { hr = CoCreateInstance(CLSID_DsObjectPicker, NULL, CLSCTX_INPROC_SERVER, IID_IDsObjectPicker, (LPVOID*)&m_pObjectPicker); } if ( SUCCEEDED(hr) ) { // Make a local copy of the InitInfo so we can modify it safely CopyMemory(&InitInfo, pInitInfo, min(pInitInfo->cbSize, sizeof(InitInfo))); // Make a local copy of g_aDSOPScopes so we can modify it safely. // Note also that m_pObjectPicker->Initialize returns HRESULTs // in this buffer. pDSOPScopes = (PDSOP_SCOPE_INIT_INFO)LocalAlloc(LPTR, sizeof(g_aDSOPScopes)); if (pDSOPScopes) { CopyMemory(pDSOPScopes, g_aDSOPScopes, sizeof(g_aDSOPScopes)); // Override the ACLUI default scopes, but don't touch // the other stuff. // pDSOPScopes->pwzDcName = m_strServerName; InitInfo.cDsScopeInfos = ARRAYSIZE(g_aDSOPScopes); InitInfo.aDsScopeInfos = pDSOPScopes; hr = m_pObjectPicker->Initialize(&InitInfo); LocalFree(pDSOPScopes); } else { hr = E_OUTOFMEMORY; } } return hr; } STDMETHODIMP CObjSecurity::InvokeDialog( HWND hwndParent, IDataObject **ppdoSelection ) { HRESULT hr = E_UNEXPECTED; _ASSERT( ppdoSelection ); if (m_pObjectPicker) hr = m_pObjectPicker->InvokeDialog(hwndParent, ppdoSelection); return hr; } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// // ISecurityInformation methods ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CObjSecurity::GetObjectInformation(PSI_OBJECT_INFO pObjectInfo) { m_dwSIFlags = SI_EDIT_OWNER | SI_EDIT_PERMS | SI_NO_ACL_PROTECT | \ SI_PAGE_TITLE; pObjectInfo->dwFlags = m_dwSIFlags; pObjectInfo->hInstance = g_hInstLib; pObjectInfo->pszServerName = NULL; //use local computer pObjectInfo->pszObjectName = m_bstrObject; pObjectInfo->pszPageTitle = m_bstrPage; return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CObjSecurity::GetSecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR *ppSD, BOOL fDefault) { HRESULT hr = S_OK; // Make the default if necessary... if ( !m_pConfProp->ConfInfo.m_pSecDesc ) { hr = CoCreateInstance( CLSID_SecurityDescriptor, NULL, CLSCTX_INPROC_SERVER, IID_IADsSecurityDescriptor, (void **) &m_pConfProp->ConfInfo.m_pSecDesc ); // Add default settings if successfully created the ACE if ( SUCCEEDED(hr) ) hr = m_pConfProp->ConfInfo.AddDefaultACEs( m_pConfProp->ConfInfo.IsNewConference() ); } // If we failed to get the defaults, just use whatever you can... if ( !m_pConfProp->ConfInfo.m_pSecDesc ) { PSECURITY_DESCRIPTOR psdNewSD = LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH); // // Validate the allocation // if( psdNewSD == NULL ) { hr = E_OUTOFMEMORY; } else { // // Allocation succeeded // if( !InitializeSecurityDescriptor(psdNewSD,SECURITY_DESCRIPTOR_REVISION) ) { hr = GetLastError(); } } *ppSD = psdNewSD; } else { DWORD dwSDLen = 0; ATLTRACE(_T(".1.CObjSecurity::GetSecurity() pre->Convert ticks = %ld.\n"), GetTickCount() ); hr = ConvertObjectToSD( m_pConfProp->ConfInfo.m_pSecDesc, ppSD, &dwSDLen ); ATLTRACE(_T(".1.CObjSecurity::GetSecurity() post Convert ticks = %ld.\n"), GetTickCount() ); } return hr; } ///////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CObjSecurity::SetSecurity( SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR pSD) { if ( !m_pConfProp ) return E_UNEXPECTED; HRESULT hr = S_OK; m_pConfProp->ConfInfo.SetSecuritySet( true ); /////////////////////////////////////////////////////////// // If we don't have an existing SD, create one // if ( !m_pConfProp->ConfInfo.m_pSecDesc ) { hr = CoCreateInstance( CLSID_SecurityDescriptor, NULL, CLSCTX_INPROC_SERVER, IID_IADsSecurityDescriptor, (void **) &m_pConfProp->ConfInfo.m_pSecDesc ); // Failed te create the security descriptor object if ( FAILED(hr) ) return hr; } ///////////////////////////////////////////////////////////////////////////////// // Set properties on the Security Descriptor // // Get control and revision information from SD DWORD dwRevision = 0; WORD wControl = 0; DWORD dwRet = GetSecurityDescriptorControl( pSD, &wControl, &dwRevision ); if ( !dwRet ) return HRESULT_FROM_WIN32(GetLastError()); hr = m_pConfProp->ConfInfo.m_pSecDesc->put_Control( wControl ); BAIL_ON_FAILURE(hr); hr = m_pConfProp->ConfInfo.m_pSecDesc->put_Revision( dwRevision ); BAIL_ON_FAILURE(hr); //////////////////////////////////////////////// // What was modified on the SD? if ( si & OWNER_SECURITY_INFORMATION ) { BOOL bOwnerDefaulted = FALSE; LPBYTE pOwnerSidAddress = NULL; dwRet = GetSecurityDescriptorOwner( pSD, (PSID *) &pOwnerSidAddress, &bOwnerDefaulted ); if ( dwRet ) { LPWSTR pszOwner = NULL; if ( SUCCEEDED(hr = ConvertSidToFriendlyName(pOwnerSidAddress, &pszOwner)) ) { if ( SUCCEEDED(hr = m_pConfProp->ConfInfo.m_pSecDesc->put_OwnerDefaulted((VARIANT_BOOL) bOwnerDefaulted)) ) hr = m_pConfProp->ConfInfo.m_pSecDesc->put_Owner( pszOwner ); } // Clean - up if ( pszOwner ) delete pszOwner; } else { hr = HRESULT_FROM_WIN32(GetLastError()); } } /////////////////////////////////////////////////////// // Group security information changing... if ( si & GROUP_SECURITY_INFORMATION ) { BOOL bGroupDefaulted = FALSE; LPBYTE pGroupSidAddress = NULL; dwRet = GetSecurityDescriptorGroup( pSD, (PSID *)&pGroupSidAddress, &bGroupDefaulted ); if ( dwRet ) { LPWSTR pszGroup = NULL; if ( SUCCEEDED(hr = ConvertSidToFriendlyName(pGroupSidAddress, &pszGroup)) ) { if ( SUCCEEDED(hr = m_pConfProp->ConfInfo.m_pSecDesc->put_GroupDefaulted((VARIANT_BOOL) bGroupDefaulted)) ) hr = m_pConfProp->ConfInfo.m_pSecDesc->put_Group( pszGroup ); } // Clean - up if ( pszGroup ) delete pszGroup; } else { hr = HRESULT_FROM_WIN32(GetLastError()); } } /////////////////////////////////////////////// // DACL list changing if ( si & DACL_SECURITY_INFORMATION ) { LPBYTE pDACLAddress = NULL; BOOL bDaclPresent = FALSE, bDaclDefaulted = FALSE; VARIANT varDACL; VariantInit( &varDACL ); // Extract DACL GetSecurityDescriptorDacl( pSD, &bDaclPresent, (PACL*) &pDACLAddress, &bDaclDefaulted ); if ( bDaclPresent && pDACLAddress && SUCCEEDED(hr = ConvertACLToVariant((PACL) pDACLAddress, &varDACL)) ) { if ( SUCCEEDED(hr = m_pConfProp->ConfInfo.m_pSecDesc->put_DaclDefaulted((VARIANT_BOOL) bDaclDefaulted)) ) hr = m_pConfProp->ConfInfo.m_pSecDesc->put_DiscretionaryAcl( V_DISPATCH(&varDACL) ); } // Clean - up VariantClear( &varDACL ); } failed: return hr; } ///////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CObjSecurity::GetAccessRights(const GUID* /*pguidObjectType*/, DWORD dwFlags, PSI_ACCESS *ppAccesses, ULONG *pcAccesses, ULONG *piDefaultAccess) { *ppAccesses = g_siObjAccesses; *pcAccesses = sizeof(g_siObjAccesses)/sizeof(g_siObjAccesses[0]); *piDefaultAccess = g_iObjDefAccess; return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CObjSecurity::MapGeneric(const GUID* /*pguidObjectType*/, UCHAR *pAceFlags, ACCESS_MASK *pmask) { MapGenericMask(pmask, &ObjMap); return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CObjSecurity::GetInheritTypes(PSI_INHERIT_TYPE *ppInheritTypes, ULONG *pcInheritTypes) { *ppInheritTypes = g_siObjInheritTypes; *pcInheritTypes = sizeof(g_siObjInheritTypes)/sizeof(g_siObjInheritTypes[0]); return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CObjSecurity::PropertySheetPageCallback(HWND hwnd, UINT uMsg, SI_PAGE_TYPE uPage) { return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////