1633 lines
50 KiB
C++
1633 lines
50 KiB
C++
// 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 );
|
|
}
|