|
|
// KRDoc.cpp : implementation of the CKeyRingDoc class
//
#include "stdafx.h"
#include "keyobjs.h"
#include "intrlkey.h"
#include <shlobj.h>
#include "machine.h"
#include "KeyRing.h"
#include "KRDoc.h"
#include "KRView.h"
#include "ConctDlg.h"
#include "InfoDlg.h"
#include "passdlg.h"
#include "ImprtDlg.h"
//#include "WizSheet.h"
#include "NKChseCA.h"
#include "NKDN.h"
#include "NKDN2.h"
#include "NKFlInfo.h"
#include "NKKyInfo.h"
#include "NKUsrInf.h"
#include "Creating.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
extern CKeyRingView* g_pTreeView; extern CString g_szRemoteCommand;
// 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) ON_COMMAND(IDS_NEW_CREATE_NEW, OnNewCreateNew) ON_UPDATE_COMMAND_UI(IDS_NEW_CREATE_NEW, OnUpdateNewCreateNew) ON_COMMAND(ID_HELPTOPICS, OnHelptopics) //}}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();
// set the selection to the first service on the first machine
// get the first item (a machine) in the list
CTreeCtrl* pTree = (CTreeCtrl*)g_pTreeView; HTREEITEM hItem = pTree->GetRootItem(); // if that worked, get the next sub item. (a service)
if ( hItem ) { hItem = pTree->GetChildItem(hItem); // if that worked, select the item
if ( hItem ) pTree->SelectItem(hItem); }
// 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 = (WORD)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() { BROWSEINFO bi; LPSTR lpBuffer; LPITEMIDLIST pidlBrowse, pidlStart; // PIDL selected by user
// Allocate a buffer to receive browse information.
lpBuffer = (LPSTR) GlobalAlloc( GPTR, MAX_PATH ); if ( !lpBuffer ) return;
// load the title
CString szTitle; szTitle.LoadString( IDS_CHOOSE_COMPUTER );
// tell it where to start looking
SHGetSpecialFolderLocation( AfxGetMainWnd()->m_hWnd, CSIDL_NETWORK, &pidlStart );
// Fill in the BROWSEINFO structure.
bi.hwndOwner = AfxGetMainWnd()->m_hWnd; bi.pidlRoot = pidlStart; bi.pszDisplayName = lpBuffer; bi.lpszTitle = szTitle; bi.ulFlags = BIF_BROWSEFORCOMPUTER; bi.lpfn = NULL; bi.lParam = 0;
// Browse for a folder and return its PIDL.
pidlBrowse = SHBrowseForFolder(&bi); if (pidlBrowse != NULL) { CString sz = lpBuffer; ConnectToMachine( sz );
// Free the PIDL returned by SHBrowseForFolder.
GlobalFree(pidlBrowse); }
//clean up the pidl
if ( pidlStart ) GlobalFree(pidlStart); }
// manage connections to machines
//----------------------------------------------------------------
void CKeyRingDoc::ConnectToMachine( CString &sz ) { CRemoteMachine *pRemoteMachine;
// don't "remote" connect to the local machine
CString szLocalName; DWORD cbBuff = MAX_COMPUTERNAME_LENGTH+1; GetComputerName(szLocalName.GetBuffer((cbBuff)*2), &cbBuff); szLocalName.ReleaseBuffer();
// if sz is the same as the local machine name, don't connect to it
if ( sz.CompareNoCase(szLocalName) == 0 ) return;
// see if we already are connected
// to the remote machine. If we are, then just hilight that one
if ( g_pTreeView ) { CString szItem; CTreeCtrl* pTree = (CTreeCtrl*)g_pTreeView; HTREEITEM hItem = pTree->GetRootItem(); while ( hItem ) { szItem = pTree->GetItemText(hItem); if ( sz.CompareNoCase(szItem) == 0 ) { // we are already connected to this machine
// select the item in the tree
pTree->Select( hItem, TVGN_CARET ); return; } // get the next item
hItem = pTree->GetNextSiblingItem( hItem ); } }
// 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 );
// finally, if the user requested a specific remote machine
// on the command line, connect to that one too
if ( !g_szRemoteCommand.IsEmpty() ) { ConnectToMachine( g_szRemoteCommand ); } }
//----------------------------------------------------------------
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() );
// if this is a full key - i.e. it has a certificate - we need to check it
if ( pClone->m_pCertificate ) { // we are going to re-install the cert anyway, so prevent it from being freed
PVOID pCert = pClone->m_pCertificate; DWORD cbCert = pClone->m_cbCertificate; CString szPass = pClone->m_szPassword; pClone->m_pCertificate = NULL; pClone->m_cbCertificate = 0; pClone->m_szPassword.Empty(); // make sure it can deal with the certificate.
if ( !pClone->FInstallCertificate(pCert,cbCert,szPass) ) { delete pClone; return; } }
// add the key to the service
pClone->FAddToTree( pService ); // make sure the cloned key has a caption
pClone->UpdateCaption();
// select the newly added key
if ( g_pTreeView ) ((CTreeCtrl*)g_pTreeView)->SelectItem(pClone->HGetTreeItem());
// if there is a certificate, then bring up the properties dialog
if ( pClone->m_cbCertificate ) { pClone->OnProperties(); }
// set the dirty flag
pClone->SetDirty( TRUE ); } 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() { }
//----------------------------------------------------------------
// if the key is targeted to an online authority, then we need to take
// special care. Otherwise, just go ahead and let them install a file cert.
void CKeyRingDoc::OnUpdateKeyInstallCertificate(CCmdUI* pCmdUI) { CTreeItem* pItem = g_pTreeView->PGetSelectedItem(); BOOL fEnable = FALSE;
// make sure we have a selected item and that it is a key
if ( pItem && pItem->IsKindOf(RUNTIME_CLASS(CKey)) ) { // cast the key
CKey* pKey = (CKey*)pItem;
// determine if this is a online authority key
LPREQUEST_HEADER pHeader = (LPREQUEST_HEADER)pKey->m_pCertificateRequest; if ( pHeader && pHeader->Identifier == REQUEST_HEADER_IDENTIFIER && pHeader->fReqSentToOnlineCA ) { // this key does target an online authority
// if the fWaitingForApproval is set then allow the action
if ( pHeader->fWaitingForApproval ) fEnable = TRUE;
// can optionally alter the text of the meny item here
} else { // the key does not target an online authority, just
// let the user attach a file-based certificate
fEnable = TRUE; } }
// do the enabling
pCmdUI->Enable( fEnable ); }
//----------------------------------------------------------------
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 {
// start by seeing if this is a online based key waiting for a response
LPREQUEST_HEADER pHeader = (LPREQUEST_HEADER)pKey->m_pCertificateRequest; if ( pHeader && pHeader->Identifier == REQUEST_HEADER_IDENTIFIER && pHeader->fReqSentToOnlineCA ) { // should be waiting for approval
ASSERT( pHeader->fWaitingForApproval );
// contact the online authority to get the certificate
GetOnlineKeyApproval( pKey );
// avoid all the file based stuff and leave now
return; }
// the old, file based stuff
// prepare the file dialog variables
CFileDialog cfdlg(TRUE); 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; cfdlg.m_ofn.lpstrDefExt = NULL;
// 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 ); } else { // now the plugin is responsible fot telling the user
// that the cert didn't install right
// tell the user that it didn't work
// AfxMessageBox( IDS_ERR_INSTALLING_CERT );
} } }
// 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 && pKey->IsKindOf(RUNTIME_CLASS(CKey)) ) {
// determine if this is a online authority key
LPREQUEST_HEADER pHeader = (LPREQUEST_HEADER)pKey->m_pCertificateRequest; if ( pHeader && pHeader->Identifier == REQUEST_HEADER_IDENTIFIER && pHeader->fReqSentToOnlineCA ) { // if we are already waiting for approval, do not ask for a new cert
fEnable = !pHeader->fWaitingForApproval; } else { // a file-based key
fEnable = TRUE; 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 );
// start by seeing if this is a new style key request
LPREQUEST_HEADER pHeader = (LPREQUEST_HEADER)pKey->m_pCertificateRequest; if ( pHeader && pHeader->Identifier == REQUEST_HEADER_IDENTIFIER ) { // should not be waiting for approval
ASSERT( !pHeader->fWaitingForApproval );
// send out the online key renewal request
DoKeyRenewal( pKey );
// avoid all the file based stuff and leave now
return; }
// the old, file based stuff
// 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 );
// select the newly added key
if ( g_pTreeView ) ((CTreeCtrl*)g_pTreeView)->SelectItem(pKey->HGetTreeItem());
// 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 ); 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; }
// if this is a full key - i.e. it has a certificate - we need to check it
if ( pKey->m_pCertificate ) { // we are going to re-install the cert anyway, so prevent it from being freed
PVOID pCert = pKey->m_pCertificate; DWORD cbCert = pKey->m_cbCertificate; CString szPass = pKey->m_szPassword; pKey->m_pCertificate = NULL; pKey->m_cbCertificate = 0; pKey->m_szPassword.Empty();
// make sure it can deal with the certificate.
if ( !pKey->FInstallCertificate(pCert,cbCert,szPass) ) { 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 );
// select the newly added key
if ( g_pTreeView ) ((CTreeCtrl*)g_pTreeView)->SelectItem(pKey->HGetTreeItem());
// if there is a certificate, then bring up the properties dialog
if ( pKey->m_cbCertificate ) { pKey->OnProperties(); }
} catch( CException e ) { return; } } }
//----------------------------------------------------------------
BOOL CKeyRingDoc::CanCloseFrame(CFrameWnd* pFrame) { BOOL fSuccess;
// 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); fSuccess = 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; }
//----------------------------------------------------------------
void CKeyRingDoc::OnUpdateNewCreateNew(CCmdUI* pCmdUI) { OnUpdateKeyCreateRequest(pCmdUI); }
//----------------------------------------------------------------
void CKeyRingDoc::OnNewCreateNew() { 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 create key wizard. We start by declaring all the pieces of it
CPropertySheet propsheet(IDS_TITLE_CREATE_WIZ); CNKChooseCA page_Choose_CA; CNKUserInfo page_User_Info; CNKKeyInfo page_Key_Info; CNKDistinguishedName page_DN; CNKDistinguisedName2 page_DN2; CNKFileInfo page_File_Info;
// fill in the member variables.
page_Choose_CA.m_pPropSheet = &propsheet; page_Choose_CA.m_pChooseCAPage = &page_Choose_CA; page_User_Info.m_pPropSheet = &propsheet; page_User_Info.m_pChooseCAPage = &page_Choose_CA; page_Key_Info.m_pPropSheet = &propsheet; page_Key_Info.m_pChooseCAPage = &page_Choose_CA; page_DN.m_pPropSheet = &propsheet; page_DN.m_pChooseCAPage = &page_Choose_CA; page_DN2.m_pPropSheet = &propsheet; page_DN2.m_pChooseCAPage = &page_Choose_CA; page_File_Info.m_pPropSheet = &propsheet; page_File_Info.m_pChooseCAPage = &page_Choose_CA;
// clear the help button bits
if ( propsheet.m_psh.dwFlags & PSH_HASHELP ) propsheet.m_psh.dwFlags &= ~PSH_HASHELP; page_Choose_CA.m_psp.dwFlags &= ~(PSP_HASHELP); page_User_Info.m_psp.dwFlags &= ~(PSP_HASHELP); page_Key_Info.m_psp.dwFlags &= ~(PSP_HASHELP); page_DN.m_psp.dwFlags &= ~(PSP_HASHELP); page_DN2.m_psp.dwFlags &= ~(PSP_HASHELP); page_File_Info.m_psp.dwFlags &= ~(PSP_HASHELP);
// add the pages to the property sheet
propsheet.AddPage( &page_Choose_CA ); propsheet.AddPage( &page_Key_Info ); propsheet.AddPage( &page_DN ); propsheet.AddPage( &page_DN2 ); propsheet.AddPage( &page_User_Info ); propsheet.AddPage( &page_File_Info );
// set the wizard property
propsheet.SetWizardMode();
// run the property sheet
int i = IDOK; i = IDCANCEL; i = propsheet.DoModal(); if ( i != IDCANCEL ) { // tell all the pages that it was successful
page_Choose_CA.OnFinish(); page_User_Info.OnFinish(); page_Key_Info.OnFinish(); page_DN.OnFinish(); page_DN2.OnFinish(); page_File_Info.OnFinish();
// ok, the wizard succeeded, now run the grinder.
CCreatingKeyDlg grinder;
// set the grinder up
grinder.m_ppage_Choose_CA = &page_Choose_CA; grinder.m_ppage_User_Info = &page_User_Info; grinder.m_ppage_Key_Info = &page_Key_Info; grinder.m_ppage_DN = &page_DN; grinder.m_ppage_DN2 = &page_DN2; grinder.m_pService = pService; grinder.m_fGenerateKeyPair = TRUE;
// let'er rip
if ( grinder.DoModal() == IDOK ) { ASSERT( grinder.m_pKey ); // add the new key to the tree
grinder.m_pKey->FAddToTree( pService ); // make sure the new key has a caption
grinder.m_pKey->UpdateCaption(); // make it dirty too
grinder.m_pKey->SetDirty(TRUE);
// select the newly added key
if ( g_pTreeView ) ((CTreeCtrl*)g_pTreeView)->SelectItem(grinder.m_pKey->HGetTreeItem());
// if the key is already complete, then bring up its properties dialog
if ( grinder.m_pKey->m_pCertificate ) grinder.m_pKey->OnProperties(); } } }
// online key support utilities
//----------------------------------------------------------------
void CKeyRingDoc::DoKeyRenewal( CKey* pKey ) { LPREQUEST_HEADER pHeader = (LPREQUEST_HEADER)pKey->m_pCertificateRequest;
CPropertySheet propsheet( IDS_TITLE_RENEW ); CNKChooseCA page_Choose_CA; CNKUserInfo page_User_Info;
page_Choose_CA.m_pPropSheet = &propsheet; page_Choose_CA.m_pChooseCAPage = &page_Choose_CA; page_User_Info.m_pPropSheet = &propsheet; page_User_Info.m_pChooseCAPage = &page_Choose_CA;
// set the renewal flag on the user page
page_User_Info.fRenewingKey = TRUE;
// add the pages to the property sheet
propsheet.AddPage( &page_Choose_CA ); propsheet.AddPage( &page_User_Info ); // set the wizard property
propsheet.SetWizardMode();
// get rid of the help button
DWORD NoHelpMask = 0xFFFFFFFF ^ PSH_HASHELP; propsheet.m_psh.dwFlags &= NoHelpMask;
// run the property sheet
int i = IDOK; i = IDCANCEL; i = propsheet.DoModal(); if ( i != IDCANCEL ) { // tell all the pages that it was successful
page_Choose_CA.OnFinish(); page_User_Info.OnFinish(); // create the grinder and prepare it
CCreatingKeyDlg grinder;
// set the grinder up
grinder.m_ppage_Choose_CA = &page_Choose_CA; grinder.m_ppage_User_Info = &page_User_Info; grinder.m_ppage_Key_Info = NULL; grinder.m_ppage_DN = NULL; grinder.m_ppage_DN2 = NULL; grinder.m_pService = NULL;
grinder.m_pKey = pKey; grinder.m_fRenewExistingKey = TRUE;
// let'er rip
if ( grinder.DoModal() ) { // make it dirty
grinder.m_pKey->SetDirty(TRUE);
// it has been decided not to bring up the properties dialog in the event
// a renewal request - the properties have already been set
// if ( grinder.m_pKey->m_pCertificate )
// grinder.m_pKey->OnProperties();
} } }
//----------------------------------------------------------------
void CKeyRingDoc::GetOnlineKeyApproval( CKey* pKey ) { // create the grinder and prepare it
CCreatingKeyDlg grinder;
// set the grinder up
grinder.m_ppage_Choose_CA = NULL; grinder.m_ppage_User_Info = NULL; grinder.m_ppage_Key_Info = NULL; grinder.m_ppage_DN = NULL; grinder.m_ppage_DN2 = NULL; grinder.m_pService = NULL;
grinder.m_pKey = pKey; grinder.m_fResubmitKey = TRUE;
// let'er rip
if ( grinder.DoModal() ) { // make it dirty
grinder.m_pKey->SetDirty(TRUE); // if the key is already complete, then bring up its properties dialog
if ( grinder.m_pKey->m_pCertificate ) grinder.m_pKey->OnProperties(); } }
//----------------------------------------------------------------
// invoke the help with a standard help ID
void CKeyRingDoc::OnHelptopics() { if ( g_pTreeView ) g_pTreeView->WinHelp( 0x50000 ); }
|