Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

518 lines
14 KiB

  1. // NKChseCA.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "keyring.h"
  5. #include "NKChseCA.h"
  6. #include "certcli.h"
  7. #include "OnlnAuth.h"
  8. #ifdef _DEBUG
  9. #define new DEBUG_NEW
  10. #undef THIS_FILE
  11. static char THIS_FILE[] = __FILE__;
  12. #endif
  13. /////////////////////////////////////////////////////////////////////////////
  14. // CNKPages dialog
  15. CNKPages::CNKPages( UINT nIDCaption )
  16. : CPropertyPage( nIDCaption )
  17. {
  18. }
  19. // resource strings
  20. #define SZ_PARAMETERS "Software\\Microsoft\\Keyring\\Parameters"
  21. //---------------------------------------------------------------------------
  22. void CNKPages::OnFinish()
  23. {}
  24. //---------------------------------------------------------------------------
  25. // returns TRUE if it was able get the value
  26. BOOL CNKPages::FGetStoredString( CString &sz, LPCSTR szValueName )
  27. {
  28. // start by opening the key
  29. DWORD err;
  30. HKEY hKey;
  31. err = RegOpenKeyEx(
  32. HKEY_CURRENT_USER, // handle of open key
  33. SZ_PARAMETERS, // address of name of subkey to open
  34. 0, // reserved
  35. KEY_READ, // security access mask
  36. &hKey // address of handle of open key
  37. );
  38. ASSERT(err == ERROR_SUCCESS);
  39. if ( err != ERROR_SUCCESS )
  40. return FALSE;
  41. // prepare to get the value
  42. LPTSTR pszValue;
  43. pszValue = sz.GetBuffer( MAX_PATH+1 );
  44. // get the value of the item in the key
  45. DWORD type;
  46. DWORD cbData = MAX_PATH;
  47. err = RegQueryValueEx(
  48. hKey, // handle of key to query
  49. szValueName, // name of value to query
  50. NULL, // reserved
  51. &type, // address of buffer for value type
  52. (PUCHAR)pszValue, // address of data buffer
  53. &cbData // address of data buffer size
  54. );
  55. // release the string so we can use it
  56. sz.ReleaseBuffer();
  57. // all done, close the key before leaving
  58. if ( hKey )
  59. RegCloseKey( hKey );
  60. // check to see if we got the value
  61. if ( err != ERROR_SUCCESS )
  62. return FALSE;
  63. // return any errors
  64. return TRUE;
  65. }
  66. //---------------------------------------------------------------------------
  67. void CNKPages::SetStoredString( CString &sz, LPCSTR szValueName )
  68. {
  69. // start by opening the key
  70. DWORD err;
  71. HKEY hKey;
  72. err = RegOpenKeyEx(
  73. HKEY_CURRENT_USER, // handle of open key
  74. SZ_PARAMETERS, // address of name of subkey to open
  75. 0, // reserved
  76. KEY_ALL_ACCESS, // security access mask
  77. &hKey // address of handle of open key
  78. );
  79. ASSERT(err == ERROR_SUCCESS);
  80. if ( err != ERROR_SUCCESS )
  81. return;
  82. // set the value of the item in the key
  83. err = RegSetValueEx
  84. (
  85. hKey, // handle of key to query
  86. szValueName, // name of value to query
  87. NULL, // reserved
  88. REG_SZ, // address of buffer for value type
  89. (PUCHAR)(LPCTSTR)sz, // address of data buffer
  90. sz.GetLength() + 1 // data buffer size
  91. );
  92. // all done, close the key before leaving
  93. if ( hKey )
  94. RegCloseKey( hKey );
  95. }
  96. /////////////////////////////////////////////////////////////////////////////
  97. // CNKChooseCA dialog
  98. CNKChooseCA::CNKChooseCA(CWnd* pParent /*=NULL*/)
  99. : CNKPages(CNKChooseCA::IDD)
  100. {
  101. //{{AFX_DATA_INIT(CNKChooseCA)
  102. m_nkca_sz_file = _T("");
  103. m_nkca_radio = -1;
  104. m_nkca_sz_online = _T("");
  105. //}}AFX_DATA_INIT
  106. }
  107. void CNKChooseCA::DoDataExchange(CDataExchange* pDX)
  108. {
  109. CDialog::DoDataExchange(pDX);
  110. //{{AFX_DATA_MAP(CNKChooseCA)
  111. DDX_Control(pDX, IDC_NK_CA_ONLINE, m_nkca_ccombo_online);
  112. DDX_Control(pDX, IDC_NK_CA_FILE, m_nkca_cedit_file);
  113. DDX_Control(pDX, IDC_NK_CA_BROWSE, m_nkca_btn_browse);
  114. DDX_Control(pDX, IDC_BK_CA_PROPERTIES, m_nkca_btn_properties);
  115. DDX_Text(pDX, IDC_NK_CA_FILE, m_nkca_sz_file);
  116. DDX_Radio(pDX, IDC_NK_CA_FILE_RADIO, m_nkca_radio);
  117. DDX_CBString(pDX, IDC_NK_CA_ONLINE, m_nkca_sz_online);
  118. //}}AFX_DATA_MAP
  119. }
  120. BEGIN_MESSAGE_MAP(CNKChooseCA, CDialog)
  121. //{{AFX_MSG_MAP(CNKChooseCA)
  122. ON_BN_CLICKED(IDC_NK_CA_ONLINE_RADIO, OnNkCaOnlineRadio)
  123. ON_BN_CLICKED(IDC_NK_CA_FILE_RADIO, OnNkCaFileRadio)
  124. ON_BN_CLICKED(IDC_NK_CA_BROWSE, OnNkCaBrowse)
  125. ON_BN_CLICKED(IDC_BK_CA_PROPERTIES, OnBkCaProperties)
  126. ON_CBN_SELCHANGE(IDC_NK_CA_ONLINE, OnSelchangeNkCaOnline)
  127. //}}AFX_MSG_MAP
  128. END_MESSAGE_MAP()
  129. #define SZ_TARGET_CA "TARGET_CA"
  130. #define SZ_FILE_BASED "FILE_BASED"
  131. //---------------------------------------------------------------------------
  132. void CNKChooseCA::OnFinish()
  133. {
  134. try
  135. {
  136. CString szCA;
  137. // if we are targeting a manual/remote ca, loat the "FileBased" string
  138. if ( m_nkca_radio == 0 )
  139. szCA = SZ_FILE_BASED;
  140. // othewise, it should be the name of the chosen online ca
  141. else
  142. szCA = m_nkca_sz_online;
  143. // now store that value away
  144. SetStoredString( szCA, SZ_TARGET_CA );
  145. }
  146. catch (CException e)
  147. {
  148. }
  149. }
  150. //----------------------------------------------------------------
  151. BOOL CNKChooseCA::OnInitDialog( )
  152. {
  153. // load the default file name
  154. m_nkca_sz_file.LoadString( IDS_DEFAULT_REQUEST_FILE );
  155. // default to targeting the request towards a file
  156. m_nkca_radio = 0;
  157. // call the base oninit
  158. CPropertyPage::OnInitDialog();
  159. // Initialze the list of available online authorties. Record how many there were
  160. DWORD numCA = InitOnlineList();
  161. // now get the default authority used from last time
  162. CString szLastCA;
  163. BOOL fGotLastCA = FGetStoredString( szLastCA, SZ_TARGET_CA );
  164. // if there were no online authorities, disable that option
  165. if ( numCA == 0 )
  166. GetDlgItem(IDC_NK_CA_ONLINE_RADIO)->EnableWindow(FALSE);
  167. // initialze to the appropriate item
  168. if ( (numCA == 0) || (szLastCA == SZ_FILE_BASED) )
  169. {
  170. // by default, select the first item in the list
  171. m_nkca_ccombo_online.SetCurSel(0);
  172. // set up windows
  173. m_nkca_ccombo_online.EnableWindow( FALSE );
  174. m_nkca_btn_properties.EnableWindow( FALSE );
  175. // finish getting ready by calling OnNkCaFileRadio
  176. OnNkCaFileRadio();
  177. }
  178. else
  179. // there are items in the online dropdown
  180. {
  181. // by default, select the first item in the list
  182. m_nkca_ccombo_online.SetCurSel(0);
  183. // if we retrieved a default from last time, select that
  184. if ( fGotLastCA )
  185. m_nkca_ccombo_online.SelectString( -1, szLastCA );
  186. // since there are online authorities available, default to them
  187. m_nkca_radio = 1;
  188. UpdateData( FALSE );
  189. // finish getting ready by calling OnNkCaOnlineRadio
  190. OnNkCaOnlineRadio();
  191. }
  192. // return 0 to say we set the default item
  193. // return 1 to just select the default default item
  194. return 1;
  195. }
  196. //----------------------------------------------------------------
  197. // returns the number of items in the dropdown
  198. DWORD CNKChooseCA::GetSelectedCA( CString &szCA)
  199. {
  200. ASSERT( m_nkca_radio == 1 );
  201. // this becomes easy
  202. szCA = m_nkca_sz_online;
  203. return ERROR_SUCCESS;
  204. /*
  205. // now load up the registry key
  206. CString szRegKeyName;
  207. szRegKeyName.LoadString( IDS_CA_LOCATION );
  208. // and open the key
  209. DWORD err;
  210. HKEY hKey;
  211. err = RegOpenKeyEx(
  212. HKEY_LOCAL_MACHINE, // handle of open key
  213. szRegKeyName, // address of name of subkey to open
  214. 0, // reserved
  215. KEY_READ, // security access mask
  216. &hKey // address of handle of open key
  217. );
  218. ASSERT(err == ERROR_SUCCESS);
  219. if ( err != ERROR_SUCCESS )
  220. {
  221. szGUID.Empty();
  222. return err;
  223. }
  224. // prepare to get the name
  225. LPTSTR pGUID;
  226. pGUID = szGUID.GetBuffer( MAX_PATH+1 );
  227. // get the value of the item in the key
  228. DWORD type;
  229. DWORD cbData = MAX_PATH;
  230. err = RegQueryValueEx(
  231. hKey, // handle of key to query
  232. m_nkca_sz_online, // name of value to query
  233. NULL, // reserved
  234. &type, // address of buffer for value type
  235. (PUCHAR)pGUID, // address of data buffer
  236. &cbData // address of data buffer size
  237. );
  238. // release the string so we can use it
  239. szGUID.ReleaseBuffer();
  240. // all done, close the key before leaving
  241. if ( hKey )
  242. RegCloseKey( hKey );
  243. ASSERT(err == ERROR_SUCCESS);
  244. if ( err != ERROR_SUCCESS )
  245. szGUID.Empty();
  246. // return any errors
  247. return err;
  248. */
  249. }
  250. //----------------------------------------------------------------
  251. // returns the number of items in the dropdown
  252. WORD CNKChooseCA::InitOnlineList()
  253. {
  254. DWORD err;
  255. CString szRegKeyName;
  256. HKEY hKey;
  257. DWORD cbCAName = MAX_PATH+1;
  258. CString szCAName;
  259. LPTSTR pCAName;
  260. FILETIME filetime;
  261. WORD i = 0;
  262. CWaitCursor waitcursor;
  263. // load the registry key name
  264. szRegKeyName.LoadString( IDS_CA_LOCATION );
  265. // open the registry key, if it exists
  266. err = RegOpenKeyEx(
  267. HKEY_LOCAL_MACHINE, // handle of open key
  268. szRegKeyName, // address of name of subkey to open
  269. 0, // reserved
  270. KEY_READ, // security access mask
  271. &hKey // address of handle of open key
  272. );
  273. // if we did not open the key for any reason (say... it doesn't exist)
  274. // then leave right away
  275. if ( err != ERROR_SUCCESS )
  276. return FALSE;
  277. // set up the buffers
  278. pCAName = szCAName.GetBuffer( MAX_PATH+1 );
  279. // each onling authority sets up a key under "Certificate Authorities"
  280. // the title of that key is the title that shows up in the list. The
  281. // key itself contains the CLSIDs of the necessary class factories to
  282. // instantiate the com objects that we need to do all this stuff
  283. // we opened the key. Now we enumerate the values and reconnect the machines
  284. while ( RegEnumKeyEx(hKey, i, pCAName,
  285. &cbCAName, NULL, NULL,
  286. 0, &filetime) == ERROR_SUCCESS )
  287. {
  288. // add the name of the certificate authority to the list
  289. m_nkca_ccombo_online.AddString( pCAName );
  290. // increment the number found counter
  291. i++;
  292. cbCAName = MAX_PATH+1;
  293. }
  294. // release the name buffers
  295. szCAName.ReleaseBuffer();
  296. // all done, close the key before leaving
  297. RegCloseKey( hKey );
  298. // return how many we found
  299. return i;
  300. }
  301. //----------------------------------------------------------------
  302. BOOL CNKChooseCA::OnSetActive()
  303. {
  304. CString sz;
  305. sz.LoadString(IDS_TITLE_CREATE_WIZ);
  306. m_pPropSheet->SetTitle( sz );
  307. m_pPropSheet->SetWizardButtons( PSWIZB_NEXT );
  308. return CPropertyPage::OnSetActive();
  309. }
  310. /////////////////////////////////////////////////////////////////////////////
  311. // CNKChooseCA message handlers
  312. //----------------------------------------------------------------
  313. BOOL CNKChooseCA::OnKillActive()
  314. {
  315. UpdateData( TRUE );
  316. // if the target is an online certificate authority - we don't have to bother
  317. // with checking the file.
  318. if ( m_nkca_radio == 1 )
  319. return TRUE;
  320. // get the attributes of the specified file
  321. DWORD dwAttrib = GetFileAttributes( m_nkca_sz_file );
  322. // we actually want the function to fail - then the file doesn't exist
  323. if ( dwAttrib == 0xFFFFFFFF )
  324. return TRUE;
  325. // if the name is a directory, or system file, don't allow it
  326. if ( (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) || (dwAttrib & FILE_ATTRIBUTE_SYSTEM) )
  327. {
  328. AfxMessageBox( IDS_BAD_FILE_NAME );
  329. // set the focus back to the file name
  330. m_nkca_cedit_file.SetFocus();
  331. return FALSE;
  332. }
  333. // ah. Well the file already exits. Warn the user
  334. CString szWarning;
  335. AfxFormatString1( szWarning, IDS_FILE_EXISTS, m_nkca_sz_file );
  336. if ( AfxMessageBox( szWarning, MB_YESNO ) == IDYES )
  337. return TRUE;
  338. // set the focus back to the file name
  339. m_nkca_cedit_file.SetFocus();
  340. return FALSE;
  341. }
  342. //----------------------------------------------------------------
  343. void CNKChooseCA::OnNkCaFileRadio()
  344. {
  345. // enable the file related items
  346. m_nkca_cedit_file.EnableWindow( TRUE );
  347. m_nkca_btn_browse.EnableWindow( TRUE );
  348. // disable the online related items
  349. m_nkca_ccombo_online.EnableWindow( FALSE );
  350. m_nkca_btn_properties.EnableWindow( FALSE );
  351. }
  352. //----------------------------------------------------------------
  353. void CNKChooseCA::OnNkCaOnlineRadio()
  354. {
  355. // disable the file related items
  356. m_nkca_cedit_file.EnableWindow( FALSE );
  357. m_nkca_btn_browse.EnableWindow( FALSE );
  358. // enable the online related items
  359. m_nkca_ccombo_online.EnableWindow( TRUE );
  360. m_nkca_btn_properties.EnableWindow( TRUE );
  361. }
  362. //----------------------------------------------------------------
  363. void CNKChooseCA::OnNkCaBrowse()
  364. {
  365. UpdateData( TRUE );
  366. CFileDialog cfdlg(FALSE, _T("txt"), m_nkca_sz_file);
  367. CString szFilter;
  368. WORD i = 0;
  369. LPSTR lpszBuffer;
  370. // prepare the filter string
  371. szFilter.LoadString( IDS_CERTIFICATE_FILTER );
  372. // replace the "!" characters with nulls
  373. lpszBuffer = szFilter.GetBuffer(MAX_PATH+1);
  374. while( lpszBuffer[i] )
  375. {
  376. if ( lpszBuffer[i] == _T('!') )
  377. lpszBuffer[i] = _T('\0'); // yes, set \0 on purpose
  378. i++;
  379. }
  380. // prep the dialog
  381. cfdlg.m_ofn.lpstrFilter = lpszBuffer;
  382. // we prompt for the overwrite when the "Next" button is pushed
  383. cfdlg.m_ofn.Flags &= ~OFN_OVERWRITEPROMPT;
  384. // run the dialog
  385. if ( cfdlg.DoModal() == IDOK )
  386. {
  387. // get the path for the file from the dialog
  388. m_nkca_sz_file = cfdlg.GetPathName();
  389. UpdateData( FALSE );
  390. }
  391. // release the buffer in the filter string
  392. szFilter.ReleaseBuffer(60);
  393. }
  394. //----------------------------------------------------------------
  395. void CNKChooseCA::OnBkCaProperties()
  396. {
  397. HRESULT hErr;
  398. // get the string for the CA
  399. CString szCA;
  400. UpdateData( TRUE );
  401. if ( GetSelectedCA(szCA) != ERROR_SUCCESS )
  402. {
  403. AfxMessageBox( IDS_LOAD_CA_ERR );
  404. return;
  405. }
  406. // prepare the authority object
  407. COnlineAuthority authority;
  408. if ( !authority.FInitSZ(szCA) )
  409. {
  410. AfxMessageBox( IDS_CA_NO_INTERFACE );
  411. return;
  412. }
  413. // run the UI
  414. BSTR bstr;
  415. hErr = authority.pIConfig->GetConfig(0, &bstr);
  416. // save the config string
  417. if ( SUCCEEDED(hErr ) )
  418. authority.FSetPropertyString( bstr );
  419. // clean up
  420. SysFreeString( bstr );
  421. }
  422. //----------------------------------------------------------------
  423. void CNKChooseCA::OnSelchangeNkCaOnline()
  424. {
  425. // check if there are stored preferences for the selected ca server
  426. }