// KRDoc.cpp : implementation of the CKeyRingDoc class // #include "stdafx.h" #include "keyobjs.h" #include "machine.h" #include "KeyRing.h" #include "KRDoc.h" #include "KRView.h" #include "ConctDlg.h" #include "NwKeyDlg.h" #include "Creating.h" #include "InfoDlg.h" #include "passdlg.h" #include "ImprtDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif extern CKeyRingView* g_pTreeView; // a global reference to this doc object CKeyRingDoc* g_pDocument = NULL; ///////////////////////////////////////////////////////////////////////////// // CKeyRingDoc IMPLEMENT_DYNCREATE(CKeyRingDoc, CDocument) BEGIN_MESSAGE_MAP(CKeyRingDoc, CDocument) //{{AFX_MSG_MAP(CKeyRingDoc) ON_UPDATE_COMMAND_UI(ID_SERVER_CONNECT, OnUpdateServerConnect) ON_COMMAND(ID_SERVER_CONNECT, OnServerConnect) ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy) ON_COMMAND(ID_EDIT_COPY, OnEditCopy) ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut) ON_COMMAND(ID_EDIT_CUT, OnEditCut) ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste) ON_COMMAND(ID_EDIT_PASTE, OnEditPaste) ON_UPDATE_COMMAND_UI(ID_PROPERTIES, OnUpdateProperties) ON_COMMAND(ID_PROPERTIES, OnProperties) ON_UPDATE_COMMAND_UI(ID_SERVER_COMMIT_NOW, OnUpdateServerCommitNow) ON_COMMAND(ID_SERVER_COMMIT_NOW, OnServerCommitNow) ON_UPDATE_COMMAND_UI(ID_KEY_CREATE_REQUEST, OnUpdateKeyCreateRequest) ON_COMMAND(ID_KEY_CREATE_REQUEST, OnKeyCreateRequest) ON_UPDATE_COMMAND_UI(ID_KEY_INSTALL_CERTIFICATE, OnUpdateKeyInstallCertificate) ON_COMMAND(ID_KEY_INSTALL_CERTIFICATE, OnKeyInstallCertificate) ON_UPDATE_COMMAND_UI(ID_KEY_SAVE_REQUEST, OnUpdateKeySaveRequest) ON_COMMAND(ID_KEY_SAVE_REQUEST, OnKeySaveRequest) ON_UPDATE_COMMAND_UI(ID_KEY_EXPORT_BACKUP, OnUpdateKeyExportBackup) ON_COMMAND(ID_KEY_EXPORT_BACKUP, OnKeyExportBackup) ON_UPDATE_COMMAND_UI(ID_KEY_IMPORT_BACKUP, OnUpdateKeyImportBackup) ON_COMMAND(ID_KEY_IMPORT_BACKUP, OnKeyImportBackup) ON_UPDATE_COMMAND_UI(ID_KEY_IMPORT_KEYSET, OnUpdateKeyImportKeyset) ON_COMMAND(ID_KEY_IMPORT_KEYSET, OnKeyImportKeyset) ON_COMMAND(ID_KEY_DELETE, OnKeyDelete) ON_UPDATE_COMMAND_UI(ID_KEY_DELETE, OnUpdateKeyDelete) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CKeyRingDoc construction/destruction //---------------------------------------------------------------- CKeyRingDoc::CKeyRingDoc(): m_pScrapKey(NULL), m_fDirty( FALSE ) { g_pDocument = this; } //---------------------------------------------------------------- CKeyRingDoc::~CKeyRingDoc() { // clean up the add-on services DeleteAddOnServices(); } //---------------------------------------------------------------- // this is called once BOOL CKeyRingDoc::Initialize() { // see which machines we were logged into last time and restore their connections RestoreConnectedMachines(); // return success return TRUE; } //---------------------------------------------------------------- BOOL CKeyRingDoc::OnNewDocument() { CLocalMachine *pLocalMachine; if (!CDocument::OnNewDocument()) return FALSE; // initialize the add on services if( !FInitAddOnServices() ) AfxMessageBox( IDS_NO_SERVICE_MODS ); // connect to the local machine try { pLocalMachine = new CLocalMachine; } catch( CException e ) { return FALSE; } // add it to the tree at the top level pLocalMachine->FAddToTree( NULL ); // load the services add-ons into the machine if ( !FLoadAddOnServicesOntoMachine( pLocalMachine ) ) { pLocalMachine->FRemoveFromTree(); delete pLocalMachine; } // return success return TRUE; } ///////////////////////////////////////////////////////////////////////////// // CKeyRingDoc serialization void CKeyRingDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) { // TODO: add storing code here } else { // TODO: add loading code here } } ///////////////////////////////////////////////////////////////////////////// // CKeyRingDoc diagnostics #ifdef _DEBUG void CKeyRingDoc::AssertValid() const { CDocument::AssertValid(); } void CKeyRingDoc::Dump(CDumpContext& dc) const { CDocument::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // test what is selected in the treeview // if the selcted item is not of the requested type (machine, key, etc...) //-------------------------------------------------------------- // then it returns a NULL CTreeItem* CKeyRingDoc::PGetSelectedItem() { ASSERT( g_pTreeView ); CTreeCtrl* pTree = (CTreeCtrl*)g_pTreeView; // get the selected item HTREEITEM hTreeItem = pTree->GetSelectedItem(); // if nothing is selected, return a null if ( !hTreeItem ) return NULL; // get the associated internal object and return it CTreeItem* pItem = (CTreeItem*)pTree->GetItemData( hTreeItem ); return ( pItem ); } //-------------------------------------------------------------- CMachine* CKeyRingDoc::PGetSelectedMachine() { CMachine* pMachine = (CMachine*)PGetSelectedItem(); // make sure it is a machine object if ( !pMachine || pMachine->IsKindOf(RUNTIME_CLASS(CMachine)) ) return NULL; // its OK return pMachine; } //-------------------------------------------------------------- CService* CKeyRingDoc::PGetSelectedService() { CService* pService = (CService*)PGetSelectedItem(); // make sure it is a machine object if ( !pService || pService->IsKindOf(RUNTIME_CLASS(CService)) ) return NULL; // its OK return pService; } //-------------------------------------------------------------- CKey* CKeyRingDoc::PGetSelectedKey() { CKey* pKey = (CKey*)PGetSelectedItem(); // make sure it is a machine object if ( !pKey || pKey->IsKindOf(RUNTIME_CLASS(CKey)) ) return NULL; // its OK return pKey; } ///////////////////////////////////////////////////////////////////////////// // add-on service management //---------------------------------------------------------------- // pointers to the add-on services are stored in the registry //---------------------------------------------------------------- BOOL CKeyRingDoc::FInitAddOnServices() { DWORD err; CString szRegKeyName; HKEY hKey; DWORD iValue = 0; DWORD dwordType; DWORD cbValName = MAX_PATH+1; DWORD cbBuff = MAX_PATH+1; CString szValName, szServiceName; LPTSTR pValName, pServiceName; BOOL fLoadedOne = FALSE; CWaitCursor waitcursor; // load the registry key name szRegKeyName.LoadString( IDS_ADDONS_LOCATION ); // open the registry key, if it exists err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, // handle of open key szRegKeyName, // address of name of subkey to open 0, // reserved KEY_READ, // security access mask &hKey // address of handle of open key ); // if we did not open the key for any reason (say... it doesn't exist) // then leave right away if ( err != ERROR_SUCCESS ) return FALSE; // set up the buffers pValName = szValName.GetBuffer( MAX_PATH+1 ); pServiceName = szServiceName.GetBuffer( MAX_PATH+1 ); // we opened the key. Now we enumerate the values and reconnect the machines while ( RegEnumValue(hKey, iValue, pValName, &cbValName, NULL, &dwordType, (PUCHAR)pServiceName, &cbBuff) == ERROR_SUCCESS ) { // release the buffer so we can use the string szServiceName.ReleaseBuffer(); // attempt to load and initialize the add on service module CAddOnService* pService; try { // create the service object pService = new CAddOnService; // initialize it if ( pService->FInitializeAddOnService( szServiceName ) ) { // add it to the list m_AddOnServiceArray.Add( pService ); // we did load one fLoadedOne = TRUE; } else { // delete the services object because it didn't work delete pService; pService = NULL; } } catch (CException e) { // delete the services object because it didn't work if ( pService ) delete pService; pService = NULL; } // get the buffer again so we can get the next machine pServiceName = szServiceName.GetBuffer( MAX_PATH+1 ); // increment the value counter iValue++; cbValName = MAX_PATH+1; cbBuff = MAX_PATH+1; } // release the name buffers szValName.ReleaseBuffer(); szServiceName.ReleaseBuffer(); // all done, close the key before leaving RegCloseKey( hKey ); // return whether or not we loaded something return fLoadedOne; } //---------------------------------------------------------------- BOOL CKeyRingDoc::FLoadAddOnServicesOntoMachine( CMachine* pMachine ) { BOOL fAddedOne = FALSE; // loop though the list of add on services and add them to the machine WORD num = m_AddOnServiceArray.GetSize(); for ( WORD i = 0; i < num; i++ ) fAddedOne |= m_AddOnServiceArray[i]->LoadService( pMachine ); // return whether or not we added something return fAddedOne; } //---------------------------------------------------------------- void CKeyRingDoc::DeleteAddOnServices() { // loop backwards through the array and delete the objects for ( LONG i = m_AddOnServiceArray.GetSize()-1; i >= 0; i-- ) delete m_AddOnServiceArray[i]; // clear out the array m_AddOnServiceArray.RemoveAll(); } ///////////////////////////////////////////////////////////////////////////// // CKeyRingDoc commands //---------------------------------------------------------------- void CKeyRingDoc::OnUpdateServerConnect(CCmdUI* pCmdUI) { pCmdUI->Enable( TRUE ); } //---------------------------------------------------------------- void CKeyRingDoc::OnServerConnect() { CConnectOneDialog dlg; // invoke the dialog box if ( dlg.DoModal() == IDOK ) ConnectToMachine(dlg.m_ServerName); } // manage connections to machines //---------------------------------------------------------------- void CKeyRingDoc::ConnectToMachine( CString &sz ) { CRemoteMachine *pRemoteMachine; // since this could take a few seconds, put up a wait cursor CWaitCursor waitCursor; // connect to the local machine try { pRemoteMachine = new CRemoteMachine( sz ); } catch( CException e ) { AfxMessageBox( IDS_ERR_CONNECT ); return; } // add it to the tree at the top level pRemoteMachine->FAddToTree( NULL ); // load the services add-ons into the machine if ( !FLoadAddOnServicesOntoMachine( pRemoteMachine ) ) { AfxMessageBox( IDS_ERR_CONNECT ); pRemoteMachine->FRemoveFromTree(); delete pRemoteMachine; } } //---------------------------------------------------------------- // we want to save the machines the user was connected to so they remain connected // the next time we launch the program void CKeyRingDoc::StoreConnectedMachines( void ) { DWORD err, disposition; CString szRegKeyName; HKEY hKey; WORD cMachine = 1; // load the registry key name szRegKeyName.LoadString( IDS_REG_SERVER_STORAGE ); // first, we delete the machine subkey to get rid of all the previous values err = RegDeleteKey( HKEY_CURRENT_USER, szRegKeyName ); // create the registry key. If it already exists it merely opens it err = RegCreateKeyEx( HKEY_CURRENT_USER, // handle of an open key szRegKeyName, // address of subkey name 0, // reserved NULL, // address of class string REG_OPTION_NON_VOLATILE, // special options flag KEY_ALL_ACCESS, // desired security access NULL, // address of key security structure &hKey, // address of buffer for opened handle &disposition // address of disposition value buffer ); // if we did not open the key, give up if ( err != ERROR_SUCCESS ) return; // loop through the machines CTreeCtrl* pTree = (CTreeCtrl*)g_pTreeView; HTREEITEM hItem = pTree->GetRootItem(); while ( hItem ) { CRemoteMachine* pMachine = (CRemoteMachine*)pTree->GetItemData( hItem ); ASSERT( pMachine->IsKindOf( RUNTIME_CLASS(CMachine) ) ); // only bother if this is a remote machine if ( pMachine->IsKindOf(RUNTIME_CLASS(CRemoteMachine)) ) { // build the registry value name CString szMachineValue; szMachineValue.Format( "Machine#%d", cMachine ); // get the machine name CString szMachineName; pMachine->GetMachineName( szMachineName ); // set the data into place err = RegSetValueEx( hKey, // handle of key to set value for szMachineValue, // address of value to set 0, // reserved REG_SZ, // flag for value type (unsigned char *)LPCSTR(szMachineName), // address of value data (szMachineName.GetLength() + 1) * sizeof(TCHAR)// size of value data ); // increment the machine counter cMachine++; } // get the next item hItem = pTree->GetNextSiblingItem( hItem ); } // close the key RegCloseKey( hKey ); } //---------------------------------------------------------------- void CKeyRingDoc::RestoreConnectedMachines( void ) { DWORD err; CString szRegKeyName; HKEY hKey; DWORD iValue = 0; DWORD dwordType; DWORD cbValName = MAX_PATH+1; DWORD cbBuff = MAX_PATH+1; CString szValName, szMachineName; LPTSTR pValName, pMachineName; CWaitCursor waitcursor; // load the registry key name szRegKeyName.LoadString( IDS_REG_SERVER_STORAGE ); // open the registry key, if it exists err = RegOpenKeyEx( HKEY_CURRENT_USER, // handle of open key szRegKeyName, // address of name of subkey to open 0, // reserved KEY_READ, // security access mask &hKey // address of handle of open key ); // if we did not open the key for any reason (say... it doesn't exist) // then leave right away if ( err != ERROR_SUCCESS ) return; // set up the buffers pValName = szValName.GetBuffer( MAX_PATH+1 ); pMachineName = szMachineName.GetBuffer( MAX_PATH+1 ); // we opened the key. Now we enumerate the values and reconnect the machines while ( RegEnumValue(hKey, iValue, pValName, &cbValName, NULL, &dwordType, (PUCHAR)pMachineName, &cbBuff) == ERROR_SUCCESS ) { // release the buffer so we can use the string szMachineName.ReleaseBuffer(); // attempt to connect to the remote machine ConnectToMachine(szMachineName); // get the buffer again so we can get the next machine pMachineName = szMachineName.GetBuffer( MAX_PATH+1 ); // increment the value counter iValue++; cbValName = MAX_PATH+1; cbBuff = MAX_PATH+1; } // release the name buffers szValName.ReleaseBuffer(); szMachineName.ReleaseBuffer(); // all done, close the key before leaving RegCloseKey( hKey ); } //---------------------------------------------------------------- void CKeyRingDoc::OnCloseDocument() { if ( g_pTreeView ) ((CKeyRingView*)g_pTreeView)->DestroyItems(); // if we have a scrap key, delete it if ( m_pScrapKey ) { delete m_pScrapKey; m_pScrapKey = NULL; } CDocument::OnCloseDocument(); } // actions that depend on the selected item //---------------------------------------------------------------- void CKeyRingDoc::OnUpdateProperties(CCmdUI* pCmdUI) { CTreeItem* pItem = g_pTreeView->PGetSelectedItem(); // let the item decide if ( pItem ) pItem->OnUpdateProperties( pCmdUI ); else pCmdUI->Enable( FALSE ); } //---------------------------------------------------------------- void CKeyRingDoc::OnProperties() { CTreeItem* pItem = g_pTreeView->PGetSelectedItem(); ASSERT( pItem ); // let the item handle it pItem->OnProperties(); } //---------------------------------------------------------------- void CKeyRingDoc::OnUpdateServerCommitNow(CCmdUI* pCmdUI) { pCmdUI->Enable( m_fDirty ); } //---------------------------------------------------------------- void CKeyRingDoc::OnServerCommitNow() { ASSERT( m_fDirty ); // confirm that the user really wants to commit the changes if ( AfxMessageBox(IDS_SERVER_COMMIT, MB_YESNO) == IDNO ) return; // commit all the servers ASSERT(g_pTreeView); BOOL fSuccess = g_pTreeView->FCommitMachinesNow(); SetDirty( !fSuccess ); } //---------------------------------------------------------------- void CKeyRingDoc::OnUpdateKeyDelete(CCmdUI* pCmdUI) { CTreeItem* pItem = g_pTreeView->PGetSelectedItem(); if ( pItem ) pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CKey)) ); else pCmdUI->Enable( FALSE ); } //---------------------------------------------------------------- void CKeyRingDoc::OnKeyDelete() { CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem(); ASSERT( pKey ); ASSERT( pKey->IsKindOf(RUNTIME_CLASS(CKey)) ); // make sure the user REALLY wants to do this if ( pKey && (AfxMessageBox(IDS_KEY_DELETE_WARNING, MB_OKCANCEL) == IDOK) ) { // dirty things first pKey->SetDirty(TRUE); // update the view pKey->FRemoveFromTree(); delete pKey; } } //---------------------------------------------------------------- // set scrap key does NOT make a copy of the key. Thus, CUT would pass in // the key itself, but COPY would make a copy of the key object first, then // pass it over to SetScrapKey. void CKeyRingDoc::SetScrapKey( CKey* pKey ) { // if there already is a key in the scrap, delete it if ( m_pScrapKey ) delete m_pScrapKey; // set the new key into position m_pScrapKey = pKey; } //---------------------------------------------------------------- void CKeyRingDoc::OnUpdateEditCopy(CCmdUI* pCmdUI) { CTreeItem* pItem = g_pTreeView->PGetSelectedItem(); if ( pItem ) pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CKey)) ); else pCmdUI->Enable( FALSE ); } //---------------------------------------------------------------- void CKeyRingDoc::OnUpdateEditCut(CCmdUI* pCmdUI) { CTreeItem* pItem = g_pTreeView->PGetSelectedItem(); if ( pItem ) pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CKey)) ); else pCmdUI->Enable( FALSE ); } //---------------------------------------------------------------- void CKeyRingDoc::OnEditCut() { CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem(); ASSERT( pKey ); ASSERT( pKey->IsKindOf(RUNTIME_CLASS(CKey)) ); // mark the key dirty before we remove it so the dirty is propagated up // to the machine and the document pKey->SetDirty( TRUE ); // cut is the easiest. Remove it from the machine and put in on the doc scrap pKey->FRemoveFromTree(); SetScrapKey( pKey ); } //---------------------------------------------------------------- void CKeyRingDoc::OnEditCopy() { CKey* pKeySel = (CKey*)g_pTreeView->PGetSelectedItem(); CKey* pKeyCopy; ASSERT( pKeySel ); ASSERT( pKeySel->IsKindOf(RUNTIME_CLASS(CKey)) ); if ( !pKeySel ) return; // make a full copy of the key try { pKeyCopy = pKeySel->PClone(); } catch( CException e ) { return; } ASSERT( pKeyCopy ); // put the clone on the doc scrap SetScrapKey( pKeyCopy ); } //---------------------------------------------------------------- void CKeyRingDoc::OnUpdateEditPaste(CCmdUI* pCmdUI) { CTreeItem* pItem = g_pTreeView->PGetSelectedItem(); if ( pItem ) { pCmdUI->Enable( (pItem->IsKindOf(RUNTIME_CLASS(CService)) || pItem->IsKindOf(RUNTIME_CLASS(CKey))) && PGetScrapKey() ); } else pCmdUI->Enable( FALSE ); } //---------------------------------------------------------------- void CKeyRingDoc::OnEditPaste() { ASSERT( PGetScrapKey() ); CService* pService = (CService*)g_pTreeView->PGetSelectedItem(); ASSERT( pService ); ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) || pService->IsKindOf(RUNTIME_CLASS(CKey))); // if the selection is a key, get the key's parent, which should be a service if ( pService->IsKindOf(RUNTIME_CLASS(CKey)) ) { pService = (CService*)pService->PGetParent(); ASSERT( pService ); ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) ); } // clone the scrap key so we put a copy in the machine CKey* pClone; try { pClone = pService->PNewKey(); pClone->CopyDataFrom( PGetScrapKey() ); // add the key to the service pClone->FAddToTree( pService ); // make sure the cloned key has a caption pClone->UpdateCaption(); } catch( CException e ) { return; } // set the dirty flag pService->SetDirty( TRUE ); } //---------------------------------------------------------------- void CKeyRingDoc::OnUpdateKeyCreateRequest(CCmdUI* pCmdUI) { CTreeItem* pItem = g_pTreeView->PGetSelectedItem(); if ( pItem ) { pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CService)) || pItem->IsKindOf(RUNTIME_CLASS(CKey)) ); } else pCmdUI->Enable( FALSE ); } //---------------------------------------------------------------- void CKeyRingDoc::OnKeyCreateRequest() { CService* pService = (CService*)g_pTreeView->PGetSelectedItem(); ASSERT( pService ); ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) || pService->IsKindOf(RUNTIME_CLASS(CKey))); // if the selection is a key, get the key's parent, which should be a service if ( pService->IsKindOf(RUNTIME_CLASS(CKey)) ) { pService = (CService*)pService->PGetParent(); ASSERT( pService ); ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) ); } // run the dialog CCreateKeyDlg dlgCrKey; if ( dlgCrKey.DoModal() != IDOK ) return; // create the key and fill it out based on info from the new key dlg CKey* pNewKey; try { // create the key pNewKey = pService->PNewKey(); // set the name (easy) pNewKey->SetName( dlgCrKey.m_szKeyName ); // get the password (also easy) pNewKey->m_szPassword = dlgCrKey.m_szPassword; } catch( CException e ) { if ( pNewKey ) delete pNewKey; return; } // call the create key pair dialog. It creates the key pair // while showing a pretty animation. CCreatingKeyDlg dlgCreating; dlgCreating.m_pNwDlg = &dlgCrKey; if ( dlgCreating.DoModal() != IDOK ) { AfxMessageBox( IDS_GENERATE_KEY_ERROR, MB_OK|MB_ICONINFORMATION ); if ( pNewKey ) delete pNewKey; return; } // bring over the info from the "creating" dialog ASSERT( dlgCreating.m_cbPrivateKey ); ASSERT( dlgCreating.m_pPrivateKey ); ASSERT( dlgCreating.m_cbCertificateRequest ); ASSERT( dlgCreating.m_pCertificateRequest ); pNewKey->m_cbPrivateKey = dlgCreating.m_cbPrivateKey; pNewKey->m_pPrivateKey = dlgCreating.m_pPrivateKey; pNewKey->m_cbCertificateRequest = dlgCreating.m_cbCertificateRequest; pNewKey->m_pCertificateRequest = dlgCreating.m_pCertificateRequest; // add the key to the service pNewKey->FAddToTree( pService ); // make sure the new key has a caption pNewKey->UpdateCaption(); // output the request file if ( !pNewKey->FOutputRequestFile( dlgCrKey.m_szCertificateFile, FALSE, (PVOID)&dlgCrKey ) ) AfxMessageBox( IDS_ERR_WRITEREQUEST ); // display the "what to do next" information dialog CNewKeyInfoDlg dlgInfo; dlgInfo.m_szRequestFile = dlgCrKey.m_szCertificateFile; dlgInfo.DoModal(); // set the dirty flag pNewKey->SetDirty( TRUE ); } //---------------------------------------------------------------- void CKeyRingDoc::OnUpdateKeyInstallCertificate(CCmdUI* pCmdUI) { CTreeItem* pItem = g_pTreeView->PGetSelectedItem(); if ( pItem ) pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CKey)) ); else pCmdUI->Enable( FALSE ); } //---------------------------------------------------------------- void CKeyRingDoc::OnKeyInstallCertificate() { CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem(); ASSERT( pKey ); ASSERT( pKey->IsKindOf(RUNTIME_CLASS(CKey)) ); // put this in a try/catch to make errors easier to deal with try { // load the file extension CString szExtension; szExtension = _T("*.*"); // prepare the file dialog variables CFileDialog cfdlg(TRUE, szExtension); CString szFilter; WORD i = 0; LPSTR lpszBuffer; // prepare the filter string szFilter.LoadString( IDS_CERTIFICATE_FILTER ); // replace the "!" characters with nulls lpszBuffer = szFilter.GetBuffer(MAX_PATH+1); while( lpszBuffer[i] ) { if ( lpszBuffer[i] == _T('!') ) lpszBuffer[i] = _T('\0'); // yes, set \0 on purpose i++; } // prep the dialog cfdlg.m_ofn.lpstrFilter = lpszBuffer; // run the dialog if ( cfdlg.DoModal() == IDOK ) { // get the password string CConfirmPassDlg dlgconfirm; if ( dlgconfirm.DoModal() == IDOK ) { // tell the key to install the certificate if ( pKey->FInstallCertificate( cfdlg.GetPathName(), dlgconfirm.m_szPassword ) ) { pKey->OnProperties(); pKey->SetDirty( TRUE ); UpdateAllViews( NULL, HINT_None ); } } } // release the buffer in the filter string szFilter.ReleaseBuffer(-1); } catch ( CException e ) { } } //---------------------------------------------------------------- void CKeyRingDoc::OnUpdateKeySaveRequest(CCmdUI* pCmdUI) { BOOL fEnable = FALSE; CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem(); // quite a few conditions here, so do them one at a time if ( pKey ) { fEnable = pKey->IsKindOf(RUNTIME_CLASS(CKey)); if ( fEnable ) fEnable &= (pKey->m_cbCertificateRequest > 0); if ( fEnable ) fEnable &= (pKey->m_pCertificateRequest != NULL); } // enable the item pCmdUI->Enable( fEnable ); } //---------------------------------------------------------------- void CKeyRingDoc::OnKeySaveRequest() { CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem(); ASSERT( pKey ); ASSERT( pKey->IsKindOf(RUNTIME_CLASS(CKey)) ); ASSERT( pKey->m_cbCertificateRequest ); ASSERT( pKey->m_pCertificateRequest ); // get the key name CString szKeyName = pKey->GetName(); // make the default file name CString szDefaultFile; szDefaultFile = _T("C:\\"); szDefaultFile += szKeyName; szDefaultFile += _T(".req"); CFileDialog cfdlg(FALSE, _T("*.req"), szDefaultFile); CString szFilter; WORD i = 0; LPSTR lpszBuffer; // prepare the filter string szFilter.LoadString( IDS_REQUEST_FILTER ); // replace the "!" characters with nulls lpszBuffer = szFilter.GetBuffer(MAX_PATH+1); while( lpszBuffer[i] ) { if ( lpszBuffer[i] == _T('!') ) lpszBuffer[i] = _T('\0'); // yes, set \0 on purpose i++; } // prep the dialog cfdlg.m_ofn.lpstrFilter = lpszBuffer; // run the dialog if ( cfdlg.DoModal() == IDOK ) { // output the request file if ( !pKey->FOutputRequestFile(cfdlg.GetPathName()) ) { AfxMessageBox( IDS_ERR_WRITEREQUEST ); } else { // put up the user information box CNewKeyInfoDlg dlg; dlg.m_fNewKeyInfo = FALSE; dlg.m_szRequestFile = cfdlg.GetPathName(); dlg.DoModal(); } } // release the buffer in the filter string szFilter.ReleaseBuffer(60); } //---------------------------------------------------------------- void CKeyRingDoc::OnUpdateKeyImportKeyset(CCmdUI* pCmdUI) { CTreeItem* pItem = g_pTreeView->PGetSelectedItem(); if ( pItem ) pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CService)) || pItem->IsKindOf(RUNTIME_CLASS(CKey)) ); else pCmdUI->Enable( FALSE ); } //---------------------------------------------------------------- void CKeyRingDoc::OnKeyImportKeyset() { CService* pService = (CService*)g_pTreeView->PGetSelectedItem(); ASSERT( pService ); ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) || pService->IsKindOf(RUNTIME_CLASS(CKey))); // if the selection is a key, get the key's parent, which should be a service if ( pService->IsKindOf(RUNTIME_CLASS(CKey)) ) { pService = (CService*)pService->PGetParent(); ASSERT( pService ); ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) ); } CString szPrivateKey; CString szPublicKey; // get the names of the key files CImportDialog ImprtDlg; if ( ImprtDlg.DoModal() != IDOK ) { // exit because the user canceled return; } // the user must also give a password CConfirmPassDlg dlgconfirm; if ( dlgconfirm.DoModal() != IDOK ) return; try { // create the new import key object CKey* pKey = pService->PNewKey(); // tell it to do the importing if ( !pKey->FImportKeySetFiles(ImprtDlg.m_cstring_PrivateFile, ImprtDlg.m_cstring_CertFile, dlgconfirm.m_szPassword) ) { delete pKey; return; } // make sure its name is untitled CString szName; szName.LoadString( IDS_UNTITLED ); pKey->SetName( szName ); // add the key to the service pKey->FAddToTree( pService ); // make sure the key has a caption pKey->UpdateCaption(); // set the dirty flag pKey->SetDirty( TRUE ); // force properties dlg pKey->OnProperties(); } catch( CException e ) { return; } } //---------------------------------------------------------------- void CKeyRingDoc::OnUpdateKeyExportBackup(CCmdUI* pCmdUI) { CTreeItem* pItem = g_pTreeView->PGetSelectedItem(); if ( pItem ) pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CKey)) ); else pCmdUI->Enable( FALSE ); } //---------------------------------------------------------------- void CKeyRingDoc::OnKeyExportBackup() { CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem(); ASSERT( pKey ); ASSERT( pKey->IsKindOf(RUNTIME_CLASS(CKey)) ); CFileDialog cfdlg(FALSE, _T("*.key")); CString szFilter; WORD i = 0; LPSTR lpszBuffer; ASSERT(pKey); if ( !pKey ) return; // warn the user about security if ( AfxMessageBox(IDS_KEYFILE_WARNING, MB_OKCANCEL|MB_ICONEXCLAMATION) == IDCANCEL ) return; // prepare the filter string szFilter.LoadString( IDS_KEY_FILE_TYPE ); // replace the "!" characters with nulls lpszBuffer = szFilter.GetBuffer(MAX_PATH+1); while( lpszBuffer[i] ) { if ( lpszBuffer[i] == _T('!') ) lpszBuffer[i] = _T('\0'); // yes, set \0 on purpose i++; } // prep the dialog cfdlg.m_ofn.lpstrFilter = lpszBuffer; // run the dialog if ( cfdlg.DoModal() == IDOK ) { // tell the key to export itself pKey->FImportExportBackupFile( cfdlg.GetPathName(), FALSE ); } // release the buffer in the filter string szFilter.ReleaseBuffer(60); } //---------------------------------------------------------------- void CKeyRingDoc::OnUpdateKeyImportBackup(CCmdUI* pCmdUI) { CTreeItem* pItem = g_pTreeView->PGetSelectedItem(); if ( pItem ) pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CService)) || pItem->IsKindOf(RUNTIME_CLASS(CKey)) ); else pCmdUI->Enable( FALSE ); } //---------------------------------------------------------------- void CKeyRingDoc::OnKeyImportBackup() { CService* pService = (CService*)g_pTreeView->PGetSelectedItem(); ASSERT( pService ); ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) || pService->IsKindOf(RUNTIME_CLASS(CKey))); // if the selection is a key, get the key's parent, which should be a service if ( pService->IsKindOf(RUNTIME_CLASS(CKey)) ) { pService = (CService*)pService->PGetParent(); ASSERT( pService ); ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) ); } CFileDialog cfdlg(TRUE, _T("*.key") ); CString szFilter; WORD i = 0; LPSTR lpszBuffer; // make sure we are ok if ( !pService ) return; // prepare the filter string szFilter.LoadString( IDS_KEY_FILE_TYPE ); // replace the "!" characters with nulls lpszBuffer = szFilter.GetBuffer(MAX_PATH+1); while( lpszBuffer[i] ) { if ( lpszBuffer[i] == _T('!') ) lpszBuffer[i] = _T('\0'); // yes, set \0 on purpose i++; } // prep the dialog cfdlg.m_ofn.lpstrFilter = lpszBuffer; // run the dialog if ( cfdlg.DoModal() == IDOK ) { try { // create the new import key object CKey* pKey = pService->PNewKey(); // tell it to do the importing if ( !pKey->FImportExportBackupFile(cfdlg.GetPathName(), TRUE) ) { delete pKey; return; } // add the key to the service pKey->FAddToTree( pService ); // make sure the key has a caption pKey->UpdateCaption(); // set the dirty flag pKey->SetDirty( TRUE ); // if there is no Certificate then we can't install on a server. // so don't try to force the Properties dialog if ( pKey->m_cbCertificate ) // force properties dlg { pKey->OnProperties(); } } catch( CException e ) { return; } } } //---------------------------------------------------------------- BOOL CKeyRingDoc::CanCloseFrame(CFrameWnd* pFrame) { // if we are dirty, ask the user what to do - they can cancel here if ( m_fDirty ) { switch( AfxMessageBox(IDS_SERVER_COMMIT, MB_YESNOCANCEL|MB_ICONQUESTION) ) { case IDYES: // yes, they do want to commit // commit all the servers ASSERT(g_pTreeView); g_pTreeView->FCommitMachinesNow(); break; case IDNO: // no, they don't want to commit break; case IDCANCEL: // whoa nellie! Stop this return FALSE; } } // make a note in the user registry of which machines we are logged into so we // administer them again later StoreConnectedMachines(); // of course we can close the frame return TRUE; }