// SecurityManager.cpp : Implementation of CSecurityManager #include "stdafx.h" #include "VideoSurvDll.h" #include "SecurityManager.h" #include "SecurityLoginDlg.h" //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // CSecurityManager //\_ STDMETHODIMP CSecurityManager::FinalConstruct () { return S_OK; } STDMETHODIMP CSecurityManager::FinalRelease () { return S_OK; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // ISctructure Item //\_ STDMETHODIMP CSecurityManager::Init() { // create one user with the full permissions CComPtr oUser; _ComVerifyRS( CreateAppObject( CLSID_SecurityUser, &oUser, GetApplication(), (IAppObject*) this ) ); _ComVerifyRS( oUser->put_Login(CComBSTR("Admin")) ); _ComVerifyRS( oUser->put_Name(CComBSTR("Main system administrator")) ); _ComVerifyRS( oUser->put_DefaultPermissions(sdlFullAccess) ); _ComVerifyRS( AddUser(oUser) ); return IStructureLevelImpl::Init(); } STDMETHODIMP CSecurityManager::PostInit() { _ComVerifyRS( LogInit( GetApplication(), 1) ); _ComVerifyRS( DoAdvise( GetApplication(), IID__IApplicationStateEvents ) ); return IStructureLevelImpl::PostInit(); } STDMETHODIMP_(void) CSecurityManager::PreClose() { IStructureLevelImpl::PreClose(); } STDMETHODIMP_(void) CSecurityManager::Close() { IStructureLevelImpl::Close(); } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // ISecurity group //\_ STDMETHODIMP CSecurityManager::get_Users(IEnumSecurityUsers* *pVal) { typedef CComObject< CComEnum< IEnumSecurityUsers, &IID_IEnumSecurityUsers, ISecurityUser*, _CopyInterface< ISecurityUser > > > EnumSecurityUsers; if ( !pVal ) return E_POINTER; EnumSecurityUsers* pEnum = NULL; EnumSecurityUsers::CreateInstance( &pEnum ); HRESULT hr = pEnum->Init( (ISecurityUser**) m_vecUsers.begin(), (ISecurityUser**) m_vecUsers.end(), NULL, AtlFlagCopy ); if ( SUCCEEDED( hr ) ) hr = pEnum->QueryInterface( IID_IEnumSecurityUsers, (void**) pVal ); if ( FAILED( hr ) ) delete pEnum; return hr; } // add new user to system STDMETHODIMP CSecurityManager::AddUser(ISecurityUser *pUser) { if (pUser==NULL) return E_POINTER; // all simply, if we do not have any user with same SecurityID we can add it, if not... CComBSTR bsSecID; _ComVerifyRS( pUser->get_SecurityID(&bsSecID) ); for (int i=0; iget_SecurityID(&bsTemp) ); if (bsSecID==bsTemp) { string sError; LoadString(271, &sError); return Error(sError.c_str()); } } m_vecUsers.push_back(pUser); return S_OK; } // remove user from group STDMETHODIMP CSecurityManager::DeleteUser(ISecurityUser *pUser) { if (pUser==NULL) return E_POINTER; CComBSTR bsSecID; _ComVerifyRS( pUser->get_SecurityID(&bsSecID) ); std::vector < CComPtr < ISecurityUser > >::iterator pIt; for (pIt = m_vecUsers.begin(); pItget_SecurityID(&bsTemp) ); if (bsSecID==bsTemp) { m_vecUsers.erase(pIt); return S_OK; } } string sError; LoadString(272, &sError); return Error(sError.c_str()); } STDMETHODIMP CSecurityManager::GetUser(BSTR bsSecurityID, ISecurityUser **ppUser) { if (ppUser==NULL) return E_POINTER; std::vector < CComPtr < ISecurityUser > >::iterator pIt; for (pIt = m_vecUsers.begin(); pItget_SecurityID(&bsTemp) ); if (bsTemp==bsSecurityID) { (*pIt).CopyTo(ppUser); return S_OK; } } return S_FALSE; } STDMETHODIMP CSecurityManager::get_UserCount(long *pVal) { if (pVal==NULL) return E_POINTER; *pVal=m_vecUsers.size(); return S_OK; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // IPersistsStream //\_ HRESULT CSecurityManager::LoadSecurityData(IStorage *pStg) { m_vecUsers.clear(); CComPtr oUsersStream; if ( FAILED( pStg->OpenStream( CComBSTR("Users"), NULL, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &oUsersStream ) ) ) return S_FALSE; long nUsersCount; _ComCallRH( oUsersStream->Read( &nUsersCount, sizeof( nUsersCount ), NULL ) ); for (int i=0; iRead( &ClsID, sizeof( ClsID ), NULL ) ); CComPtr oPersistStream; _ComVerifyRS( CreateAppObject( ClsID, &oPersistStream, GetApplication(), (IAppObject*) this ) ); _ComCallRH( oPersistStream->Load(oUsersStream) ); CComQIPtr oUser(oPersistStream); if (oUser) m_vecUsers.push_back(oUser.p); } // now group structure CComPtr oGroupsStream; if ( FAILED( pStg->OpenStream( CComBSTR("Groups"), NULL, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &oGroupsStream ) ) ) return S_FALSE; long nGroups; _ComCallRH( oGroupsStream->Read(&nGroups,sizeof(nGroups), NULL) ); for (i = 0; i oUser; _ComVerifyRS( GetUser(bsTemp,&oUser) ); CComQIPtr oGroup(oUser); _VerifyRS( oGroup ); long nUsers; _ComCallRH( oGroupsStream->Read(&nUsers,sizeof(nUsers), NULL) ); // add users to group for (int j=0; jAddUser(oUser) ); } } // now security data CComPtr oSecStream; if ( FAILED( pStg->OpenStream( CComBSTR("Security"), NULL, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &oSecStream ) ) ) return S_FALSE; return LoadSecurityItem(oSecStream); } HRESULT CSecurityManager::SaveSecurityData(IStorage *pStg) { // firstly save all users CComPtr oUsersStream; _ComCallRH( pStg->CreateStream( CComBSTR("Users"), STGM_CREATE | STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &oUsersStream ) ); long nUsersCount = m_vecUsers.size(); _ComCallRH( oUsersStream->Write( &nUsersCount, sizeof( nUsersCount ), NULL ) ); std::vector < CComPtr < ISecurityUser > >::iterator pIt; for (pIt = m_vecUsers.begin(); pIt oPersistStream(*pIt); CLSID ClsID; if (oPersistStream) { _ComVerifyRS( oPersistStream->GetClassID( &ClsID ) ); _ComCallRH( oUsersStream->Write( &ClsID, sizeof( ClsID ), NULL ) ); _ComCallRH( oPersistStream->Save(oUsersStream,TRUE) ); } } // now group structure CComPtr oGroupsStream; _ComCallRH( pStg->CreateStream( CComBSTR("Groups"), STGM_CREATE | STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &oGroupsStream ) ); long nGroups=0; _ComCallRH( oGroupsStream->Write(&nGroups,sizeof(nGroups), NULL) ); for (pIt = m_vecUsers.begin(); pIt oPersistStream(*pIt); CComQIPtr oSecurityGroup(*pIt); if (oPersistStream && oSecurityGroup) { CComBSTR bsTemp; long nLength; // write groupid _ComVerifyRS( (*pIt)->get_SecurityID(&bsTemp) ); _ComCallRH( bsTemp.WriteToStream(oGroupsStream) ); // write group count _ComVerifyRS( oSecurityGroup->get_UserCount(&nLength) ); _ComCallRH( oGroupsStream->Write(&nLength,sizeof(nLength), NULL) ); // write group member ids CComPtr oUsers; _ComVerifyRS( oSecurityGroup->get_Users(&oUsers) ); CComPtr oUser; ULONG lReaded; while ( SUCCEEDED( oUsers->Next( 1, &oUser, &lReaded ) ) && lReaded == 1 ) { bsTemp.Empty(); _ComVerifyRS( oUser->get_SecurityID(&bsTemp) ); _ComCallRH( bsTemp.WriteToStream(oGroupsStream) ); oUser.Release(); } nGroups++; } } // write group count to reserved place LARGE_INTEGER lSeek; lSeek.QuadPart = 0; _ComCallRH( oGroupsStream->Seek(lSeek,STREAM_SEEK_SET,NULL) ); _ComCallRH( oGroupsStream->Write(&nGroups,sizeof(nGroups), NULL) ); // now group structure CComPtr oSecStream; _ComCallRH( pStg->CreateStream( CComBSTR("Security"), STGM_CREATE | STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &oSecStream ) ); return SaveSecurityItem(oSecStream); } STDMETHODIMP CSecurityManager::LoadItem( IStorage* pIParentStorage, BOOL bGlobalWorkspace ) { if ( bGlobalWorkspace ) { CComPtr oStorage; // try open security storage if ( FAILED( pIParentStorage->OpenStorage( L"Security", NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &oStorage ) ) ) return S_FALSE; _ComCallRH( LoadSecurityData( oStorage ) ); } return S_OK; } STDMETHODIMP CSecurityManager::SaveItem( IStorage* pIParentStorage, BOOL bGlobalWorkspace ) { if ( bGlobalWorkspace ) { CComPtr oStorage; // try open security storage if ( FAILED( pIParentStorage->OpenStorage( L"Security", NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &oStorage ) ) ) // try create security storage _ComCallRH( pIParentStorage->CreateStorage( L"Security", STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &oStorage ) ); _ComCallRH( SaveSecurityData( oStorage ) ); } return S_OK; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // ISecurityManager //\_ STDMETHODIMP CSecurityManager::Login(BSTR bsName, BSTR bsPass) { // iterate throught all users to find can we login existing or not for (int i=0; iget_Login(&bsLogin) ); _ComVerifyRS( m_vecUsers[i]->get_Password(&bsPassword) ); if ( (bsLogin == bsName) && (bsPassword == bsPass ) ) { // user exist m_oLoggedUser = m_vecUsers[i]; _ComCallRH( AddLogMessage(rctInfo,1000) ); return S_OK; } } // report error string sTemp; LoadString (270, &sTemp); _ComCallRH( AddLogMessage(rctWarning,1001) ); return Error(sTemp.c_str()); } STDMETHODIMP CSecurityManager::UILogin(HWND hWndParent) { CComPtr oLoc; _ComVerifyRS( GetSertainSubItem( GetApplication(), CLSID_LogManager, &oLoc) ); CSecurityLoginDlg Dlg(GetApplication()); string sCap; _ComVerifyRS( LoadString(152,&sCap) ); HRESULT hr; do { if (Dlg.DoModal(hWndParent)!=IDOK) return S_FALSE; hr = Login(Dlg.bsName,Dlg.bsPass); if (FAILED(hr)) MessageBox(hWndParent,GetErrorDescription().c_str(),sCap.c_str(),MB_OK|MB_ICONWARNING); } while (hr!=S_OK); return S_OK; } STDMETHODIMP CSecurityManager::get_LoggedUser(ISecurityUser **pVal) { AUTO_LOCKER; return m_oLoggedUser.CopyTo(pVal); } STDMETHODIMP CSecurityManager::CheckPermission(IUnknown *pObj, long nPropID, BOOL *bPermit) { if (m_oLoggedUser == NULL) return E_FAIL; CComQIPtr oSecItem (pObj); _VerifyRS( oSecItem ); // fristly try to get permission for reegistered user CComBSTR bsUserID; _ComVerifyRS( m_oLoggedUser->get_SecurityID(&bsUserID) ); if (S_OK == oSecItem->get_SecProperty(bsUserID, nPropID, bPermit)) return S_OK; // get default user privelege SECURITY_DEFAULT_LEVEL DefID; _ComVerifyRS( m_oLoggedUser->get_DefaultPermissions(&DefID) ); return oSecItem->get_DefSecProperty(DefID, nPropID, bPermit); } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // ICloneObject //\_ HRESULT CSecurityManager::AssignISecurityGroup(IUnknown *pSrc) { HRESULT hr; // ISecurityGroup, asign object, property by property CComQIPtr oSecurityGroup(pSrc); if (oSecurityGroup==NULL) return E_NOINTERFACE; m_vecUsers.clear(); // get enum for all users CComPtr oUsers; _ComVerifyRS( hr = oSecurityGroup->get_Users(&oUsers) ); CComPtr oUser; ULONG lReaded; while ( SUCCEEDED( oUsers->Next( 1, &oUser, &lReaded ) ) && lReaded == 1 ) { m_vecUsers.push_back(oUser); oUser.Release(); } return S_OK; } STDMETHODIMP CSecurityManager::Assign(IUnknown* pSourseObj) { if (pSourseObj==NULL) return E_POINTER; CComQIPtr oCloneObject (pSourseObj); if (oCloneObject==NULL) return E_NOINTERFACE; // check objects id CLSID clsid; _ComVerifyRS( oCloneObject->get_ObjectCLSID(&clsid) ); _VerifyRS( InlineIsEqualGUID(clsid,GetObjectCLSID()) ); _ComCallRH( AssignISecurityItem(pSourseObj) ); _ComCallRH( AssignIStructureItem(pSourseObj) ); _ComCallRH( LogInit( GetApplication(), 1) ); return AssignISecurityGroup(pSourseObj); } STDMETHODIMP CSecurityManager::AssignPart(REFIID riid, IUnknown *pSource) { if (pSource == NULL) return E_POINTER; if (InlineIsEqualGUID(riid,IID_ISecurityItem)) return AssignISecurityItem(pSource); else if (InlineIsEqualGUID(riid,IID_ISecurityGroup)) return AssignISecurityGroup(pSource); else if (InlineIsEqualGUID(riid,IID_IStructureItem)) return AssignIStructureItem(pSource); else return E_NOTIMPL; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // _IApplicationStateEvents //\_ STDMETHODIMP CSecurityManager::OnAppLoadComplete() { HWND hwndMain = ::GetLastActivePopup(NULL); CComPtr oAppWindow; _ComVerifyRS( GetApplication()->get_AppWindow(&oAppWindow) ); _ComVerifyRS( oAppWindow->get_hWnd(&hwndMain) ); DoUnadvise( IID__IApplicationStateEvents ); return UILogin( hwndMain ) == S_OK ? S_OK : E_ABORT; }