// NKChseCA.cpp : implementation file // #include "stdafx.h" #include "keyring.h" #include "NKChseCA.h" #include "certcli.h" #include "OnlnAuth.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CNKPages dialog CNKPages::CNKPages( UINT nIDCaption ) : CPropertyPage( nIDCaption ) { } // resource strings #define SZ_PARAMETERS "Software\\Microsoft\\Keyring\\Parameters" //--------------------------------------------------------------------------- void CNKPages::OnFinish() {} //--------------------------------------------------------------------------- // returns TRUE if it was able get the value BOOL CNKPages::FGetStoredString( CString &sz, LPCSTR szValueName ) { // start by opening the key DWORD err; HKEY hKey; err = RegOpenKeyEx( HKEY_CURRENT_USER, // handle of open key SZ_PARAMETERS, // address of name of subkey to open 0, // reserved KEY_READ, // security access mask &hKey // address of handle of open key ); ASSERT(err == ERROR_SUCCESS); if ( err != ERROR_SUCCESS ) return FALSE; // prepare to get the value LPTSTR pszValue; pszValue = sz.GetBuffer( MAX_PATH+1 ); // get the value of the item in the key DWORD type; DWORD cbData = MAX_PATH; err = RegQueryValueEx( hKey, // handle of key to query szValueName, // name of value to query NULL, // reserved &type, // address of buffer for value type (PUCHAR)pszValue, // address of data buffer &cbData // address of data buffer size ); // release the string so we can use it sz.ReleaseBuffer(); // all done, close the key before leaving if ( hKey ) RegCloseKey( hKey ); // check to see if we got the value if ( err != ERROR_SUCCESS ) return FALSE; // return any errors return TRUE; } //--------------------------------------------------------------------------- void CNKPages::SetStoredString( CString &sz, LPCSTR szValueName ) { // start by opening the key DWORD err; HKEY hKey; err = RegOpenKeyEx( HKEY_CURRENT_USER, // handle of open key SZ_PARAMETERS, // address of name of subkey to open 0, // reserved KEY_ALL_ACCESS, // security access mask &hKey // address of handle of open key ); ASSERT(err == ERROR_SUCCESS); if ( err != ERROR_SUCCESS ) return; // set the value of the item in the key err = RegSetValueEx ( hKey, // handle of key to query szValueName, // name of value to query NULL, // reserved REG_SZ, // address of buffer for value type (PUCHAR)(LPCTSTR)sz, // address of data buffer sz.GetLength() + 1 // data buffer size ); // all done, close the key before leaving if ( hKey ) RegCloseKey( hKey ); } ///////////////////////////////////////////////////////////////////////////// // CNKChooseCA dialog CNKChooseCA::CNKChooseCA(CWnd* pParent /*=NULL*/) : CNKPages(CNKChooseCA::IDD) { //{{AFX_DATA_INIT(CNKChooseCA) m_nkca_sz_file = _T(""); m_nkca_radio = -1; m_nkca_sz_online = _T(""); //}}AFX_DATA_INIT } void CNKChooseCA::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CNKChooseCA) DDX_Control(pDX, IDC_NK_CA_ONLINE, m_nkca_ccombo_online); DDX_Control(pDX, IDC_NK_CA_FILE, m_nkca_cedit_file); DDX_Control(pDX, IDC_NK_CA_BROWSE, m_nkca_btn_browse); DDX_Control(pDX, IDC_BK_CA_PROPERTIES, m_nkca_btn_properties); DDX_Text(pDX, IDC_NK_CA_FILE, m_nkca_sz_file); DDX_Radio(pDX, IDC_NK_CA_FILE_RADIO, m_nkca_radio); DDX_CBString(pDX, IDC_NK_CA_ONLINE, m_nkca_sz_online); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CNKChooseCA, CDialog) //{{AFX_MSG_MAP(CNKChooseCA) ON_BN_CLICKED(IDC_NK_CA_ONLINE_RADIO, OnNkCaOnlineRadio) ON_BN_CLICKED(IDC_NK_CA_FILE_RADIO, OnNkCaFileRadio) ON_BN_CLICKED(IDC_NK_CA_BROWSE, OnNkCaBrowse) ON_BN_CLICKED(IDC_BK_CA_PROPERTIES, OnBkCaProperties) ON_CBN_SELCHANGE(IDC_NK_CA_ONLINE, OnSelchangeNkCaOnline) //}}AFX_MSG_MAP END_MESSAGE_MAP() #define SZ_TARGET_CA "TARGET_CA" #define SZ_FILE_BASED "FILE_BASED" //--------------------------------------------------------------------------- void CNKChooseCA::OnFinish() { try { CString szCA; // if we are targeting a manual/remote ca, loat the "FileBased" string if ( m_nkca_radio == 0 ) szCA = SZ_FILE_BASED; // othewise, it should be the name of the chosen online ca else szCA = m_nkca_sz_online; // now store that value away SetStoredString( szCA, SZ_TARGET_CA ); } catch (CException e) { } } //---------------------------------------------------------------- BOOL CNKChooseCA::OnInitDialog( ) { // load the default file name m_nkca_sz_file.LoadString( IDS_DEFAULT_REQUEST_FILE ); // default to targeting the request towards a file m_nkca_radio = 0; // call the base oninit CPropertyPage::OnInitDialog(); // Initialze the list of available online authorties. Record how many there were DWORD numCA = InitOnlineList(); // now get the default authority used from last time CString szLastCA; BOOL fGotLastCA = FGetStoredString( szLastCA, SZ_TARGET_CA ); // if there were no online authorities, disable that option if ( numCA == 0 ) GetDlgItem(IDC_NK_CA_ONLINE_RADIO)->EnableWindow(FALSE); // initialze to the appropriate item if ( (numCA == 0) || (szLastCA == SZ_FILE_BASED) ) { // by default, select the first item in the list m_nkca_ccombo_online.SetCurSel(0); // set up windows m_nkca_ccombo_online.EnableWindow( FALSE ); m_nkca_btn_properties.EnableWindow( FALSE ); // finish getting ready by calling OnNkCaFileRadio OnNkCaFileRadio(); } else // there are items in the online dropdown { // by default, select the first item in the list m_nkca_ccombo_online.SetCurSel(0); // if we retrieved a default from last time, select that if ( fGotLastCA ) m_nkca_ccombo_online.SelectString( -1, szLastCA ); // since there are online authorities available, default to them m_nkca_radio = 1; UpdateData( FALSE ); // finish getting ready by calling OnNkCaOnlineRadio OnNkCaOnlineRadio(); } // return 0 to say we set the default item // return 1 to just select the default default item return 1; } //---------------------------------------------------------------- // returns the number of items in the dropdown DWORD CNKChooseCA::GetSelectedCA( CString &szCA) { ASSERT( m_nkca_radio == 1 ); // this becomes easy szCA = m_nkca_sz_online; return ERROR_SUCCESS; /* // now load up the registry key CString szRegKeyName; szRegKeyName.LoadString( IDS_CA_LOCATION ); // and open the key DWORD err; HKEY hKey; 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 ); ASSERT(err == ERROR_SUCCESS); if ( err != ERROR_SUCCESS ) { szGUID.Empty(); return err; } // prepare to get the name LPTSTR pGUID; pGUID = szGUID.GetBuffer( MAX_PATH+1 ); // get the value of the item in the key DWORD type; DWORD cbData = MAX_PATH; err = RegQueryValueEx( hKey, // handle of key to query m_nkca_sz_online, // name of value to query NULL, // reserved &type, // address of buffer for value type (PUCHAR)pGUID, // address of data buffer &cbData // address of data buffer size ); // release the string so we can use it szGUID.ReleaseBuffer(); // all done, close the key before leaving if ( hKey ) RegCloseKey( hKey ); ASSERT(err == ERROR_SUCCESS); if ( err != ERROR_SUCCESS ) szGUID.Empty(); // return any errors return err; */ } //---------------------------------------------------------------- // returns the number of items in the dropdown WORD CNKChooseCA::InitOnlineList() { DWORD err; CString szRegKeyName; HKEY hKey; DWORD cbCAName = MAX_PATH+1; CString szCAName; LPTSTR pCAName; FILETIME filetime; WORD i = 0; CWaitCursor waitcursor; // load the registry key name szRegKeyName.LoadString( IDS_CA_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 pCAName = szCAName.GetBuffer( MAX_PATH+1 ); // each onling authority sets up a key under "Certificate Authorities" // the title of that key is the title that shows up in the list. The // key itself contains the CLSIDs of the necessary class factories to // instantiate the com objects that we need to do all this stuff // we opened the key. Now we enumerate the values and reconnect the machines while ( RegEnumKeyEx(hKey, i, pCAName, &cbCAName, NULL, NULL, 0, &filetime) == ERROR_SUCCESS ) { // add the name of the certificate authority to the list m_nkca_ccombo_online.AddString( pCAName ); // increment the number found counter i++; cbCAName = MAX_PATH+1; } // release the name buffers szCAName.ReleaseBuffer(); // all done, close the key before leaving RegCloseKey( hKey ); // return how many we found return i; } //---------------------------------------------------------------- BOOL CNKChooseCA::OnSetActive() { CString sz; sz.LoadString(IDS_TITLE_CREATE_WIZ); m_pPropSheet->SetTitle( sz ); m_pPropSheet->SetWizardButtons( PSWIZB_NEXT ); return CPropertyPage::OnSetActive(); } ///////////////////////////////////////////////////////////////////////////// // CNKChooseCA message handlers //---------------------------------------------------------------- BOOL CNKChooseCA::OnKillActive() { UpdateData( TRUE ); // if the target is an online certificate authority - we don't have to bother // with checking the file. if ( m_nkca_radio == 1 ) return TRUE; // get the attributes of the specified file DWORD dwAttrib = GetFileAttributes( m_nkca_sz_file ); // we actually want the function to fail - then the file doesn't exist if ( dwAttrib == 0xFFFFFFFF ) return TRUE; // if the name is a directory, or system file, don't allow it if ( (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) || (dwAttrib & FILE_ATTRIBUTE_SYSTEM) ) { AfxMessageBox( IDS_BAD_FILE_NAME ); // set the focus back to the file name m_nkca_cedit_file.SetFocus(); return FALSE; } // ah. Well the file already exits. Warn the user CString szWarning; AfxFormatString1( szWarning, IDS_FILE_EXISTS, m_nkca_sz_file ); if ( AfxMessageBox( szWarning, MB_YESNO ) == IDYES ) return TRUE; // set the focus back to the file name m_nkca_cedit_file.SetFocus(); return FALSE; } //---------------------------------------------------------------- void CNKChooseCA::OnNkCaFileRadio() { // enable the file related items m_nkca_cedit_file.EnableWindow( TRUE ); m_nkca_btn_browse.EnableWindow( TRUE ); // disable the online related items m_nkca_ccombo_online.EnableWindow( FALSE ); m_nkca_btn_properties.EnableWindow( FALSE ); } //---------------------------------------------------------------- void CNKChooseCA::OnNkCaOnlineRadio() { // disable the file related items m_nkca_cedit_file.EnableWindow( FALSE ); m_nkca_btn_browse.EnableWindow( FALSE ); // enable the online related items m_nkca_ccombo_online.EnableWindow( TRUE ); m_nkca_btn_properties.EnableWindow( TRUE ); } //---------------------------------------------------------------- void CNKChooseCA::OnNkCaBrowse() { UpdateData( TRUE ); CFileDialog cfdlg(FALSE, _T("txt"), m_nkca_sz_file); 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; // we prompt for the overwrite when the "Next" button is pushed cfdlg.m_ofn.Flags &= ~OFN_OVERWRITEPROMPT; // run the dialog if ( cfdlg.DoModal() == IDOK ) { // get the path for the file from the dialog m_nkca_sz_file = cfdlg.GetPathName(); UpdateData( FALSE ); } // release the buffer in the filter string szFilter.ReleaseBuffer(60); } //---------------------------------------------------------------- void CNKChooseCA::OnBkCaProperties() { HRESULT hErr; // get the string for the CA CString szCA; UpdateData( TRUE ); if ( GetSelectedCA(szCA) != ERROR_SUCCESS ) { AfxMessageBox( IDS_LOAD_CA_ERR ); return; } // prepare the authority object COnlineAuthority authority; if ( !authority.FInitSZ(szCA) ) { AfxMessageBox( IDS_CA_NO_INTERFACE ); return; } // run the UI BSTR bstr; hErr = authority.pIConfig->GetConfig(0, &bstr); // save the config string if ( SUCCEEDED(hErr ) ) authority.FSetPropertyString( bstr ); // clean up SysFreeString( bstr ); } //---------------------------------------------------------------- void CNKChooseCA::OnSelchangeNkCaOnline() { // check if there are stored preferences for the selected ca server }