Leaked source code of windows server 2003
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.

1028 lines
23 KiB

  1. /*++
  2. Copyright (c) 1994-2001 Microsoft Corporation
  3. Module Name :
  4. security.cpp
  5. Abstract:
  6. WWW Security Property Page
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Sergei Antonov (sergeia)
  10. Project:
  11. Internet Services Manager
  12. Revision History:
  13. --*/
  14. #include "stdafx.h"
  15. #include "common.h"
  16. #include "inetprop.h"
  17. #include "InetMgrApp.h"
  18. #include "supdlgs.h"
  19. #include "shts.h"
  20. #include "w3sht.h"
  21. #include "wincrypt.h"
  22. #include "resource.h"
  23. #include "wsecure.h"
  24. #include "authent.h"
  25. #include "seccom.h"
  26. #include "ipdomdlg.h"
  27. #include <schannel.h>
  28. #include "cryptui.h"
  29. #ifdef _DEBUG
  30. #define new DEBUG_NEW
  31. #undef THIS_FILE
  32. static char THIS_FILE[] = __FILE__;
  33. #endif
  34. extern CInetmgrApp theApp;
  35. //
  36. // CW3SecurityPage property page
  37. //
  38. IMPLEMENT_DYNCREATE(CW3SecurityPage, CInetPropertyPage)
  39. CW3SecurityPage::CW3SecurityPage(
  40. IN CInetPropertySheet * pSheet,
  41. IN BOOL fHome,
  42. IN DWORD dwAttributes
  43. )
  44. /*++
  45. Routine Description:
  46. Constructor
  47. Arguments:
  48. CInetPropertySheet * pSheet : Sheet object
  49. BOOL fHome : TRUE if this is a home directory
  50. DWORD dwAttributes : Attributes
  51. Return Value:
  52. N/A
  53. --*/
  54. : CInetPropertyPage(CW3SecurityPage::IDD, pSheet,
  55. IS_FILE(dwAttributes)
  56. ? IDS_TAB_FILE_SECURITY
  57. : IDS_TAB_DIR_SECURITY
  58. ),
  59. m_oblAccessList(),
  60. m_fU2Installed(FALSE),
  61. m_fIpDirty(FALSE),
  62. m_fHome(fHome),
  63. m_fPasswordSync(FALSE),
  64. m_fPasswordSyncInitial(FALSE),
  65. //
  66. // By default, we grant access
  67. //
  68. m_fOldDefaultGranted(TRUE),
  69. m_fDefaultGranted(TRUE)
  70. {
  71. #if 0 // Keep class wizard happy
  72. //{{AFX_DATA_INIT(CW3SecurityPage)
  73. m_fUseNTMapper = FALSE;
  74. //}}AFX_DATA_INIT
  75. #endif // 0
  76. }
  77. CW3SecurityPage::~CW3SecurityPage()
  78. /*++
  79. Routine Description:
  80. Destructor
  81. Arguments:
  82. N/A
  83. Return Value:
  84. N/A
  85. --*/
  86. {
  87. }
  88. void
  89. CW3SecurityPage::DoDataExchange(
  90. IN CDataExchange * pDX
  91. )
  92. /*++
  93. Routine Description:
  94. Initialise/Store control data
  95. Arguments:
  96. CDataExchange * pDX - DDX/DDV control structure
  97. Return Value:
  98. None
  99. --*/
  100. {
  101. CInetPropertyPage::DoDataExchange(pDX);
  102. //{{AFX_DATA_MAP(CW3SecurityPage)
  103. DDX_Check(pDX, IDC_CHECK_ENABLE_DS, m_fUseNTMapper);
  104. DDX_Control(pDX, IDC_ICON_SECURE, m_icon_Secure);
  105. DDX_Control(pDX, IDC_STATIC_SSL_PROMPT, m_static_SSLPrompt);
  106. DDX_Control(pDX, IDC_CHECK_ENABLE_DS, m_check_EnableDS);
  107. DDX_Control(pDX, IDC_BUTTON_GET_CERTIFICATES, m_button_GetCertificates);
  108. DDX_Control(pDX, IDC_VIEW_CERTIFICATE, m_button_ViewCertificates);
  109. DDX_Control(pDX, IDC_BUTTON_COMMUNICATIONS, m_button_Communications);
  110. //}}AFX_DATA_MAP
  111. }
  112. //
  113. // Message Map
  114. //
  115. BEGIN_MESSAGE_MAP(CW3SecurityPage, CInetPropertyPage)
  116. //{{AFX_MSG_MAP(CW3SecurityPage)
  117. ON_BN_CLICKED(IDC_BUTTON_AUTHENTICATION, OnButtonAuthentication)
  118. ON_BN_CLICKED(IDC_BUTTON_COMMUNICATIONS, OnButtonCommunications)
  119. ON_BN_CLICKED(IDC_BUTTON_IP_SECURITY, OnButtonIpSecurity)
  120. ON_BN_CLICKED(IDC_BUTTON_GET_CERTIFICATES, OnButtonGetCertificates)
  121. ON_BN_CLICKED(IDC_VIEW_CERTIFICATE, OnButtonViewCertificates)
  122. //}}AFX_MSG_MAP
  123. ON_BN_CLICKED(IDC_CHECK_ENABLE_DS, OnItemChanged)
  124. END_MESSAGE_MAP()
  125. /* virtual */
  126. HRESULT
  127. CW3SecurityPage::FetchLoadedValues()
  128. /*++
  129. Routine Description:
  130. Move configuration data from sheet to dialog controls
  131. Arguments:
  132. None
  133. Return Value:
  134. HRESULT
  135. --*/
  136. {
  137. CError err;
  138. BEGIN_META_DIR_READ(CW3Sheet)
  139. FETCH_DIR_DATA_FROM_SHEET(m_dwAuthFlags);
  140. FETCH_DIR_DATA_FROM_SHEET(m_dwSSLAccessPermissions);
  141. FETCH_DIR_DATA_FROM_SHEET(m_strBasicDomain);
  142. FETCH_DIR_DATA_FROM_SHEET(m_strRealm);
  143. FETCH_DIR_DATA_FROM_SHEET(m_strAnonUserName);
  144. FETCH_DIR_DATA_FROM_SHEET_PASSWORD(m_strAnonPassword);
  145. if (GetSheet()->QueryMajorVersion() < 6)
  146. {
  147. FETCH_DIR_DATA_FROM_SHEET(m_fPasswordSync);
  148. }
  149. FETCH_DIR_DATA_FROM_SHEET(m_fU2Installed);
  150. FETCH_DIR_DATA_FROM_SHEET(m_fUseNTMapper);
  151. END_META_DIR_READ(err)
  152. m_fPasswordSyncInitial = m_fPasswordSync;
  153. //
  154. // First we need to read in the hash and the name of the store. If either
  155. // is not there then there is no certificate.
  156. //
  157. BEGIN_META_INST_READ(CW3Sheet)
  158. // BUGBUG we are not fetching the hash right now because it needs a new
  159. // copy constructor. Otherwise it does a bitwise copy of the pointer value.
  160. // Then this one desctructs, freeing the pointer. Then the other one desctucts
  161. // freeing it again.
  162. // FETCH_INST_DATA_FROM_SHEET(m_CertHash);
  163. FETCH_INST_DATA_FROM_SHEET(m_strCertStoreName);
  164. FETCH_INST_DATA_FROM_SHEET(m_strCTLIdentifier);
  165. FETCH_INST_DATA_FROM_SHEET(m_strCTLStoreName);
  166. END_META_INST_READ(err)
  167. //
  168. // Build the IPL list
  169. //
  170. err = BuildIplOblistFromBlob(
  171. GetIPL(),
  172. m_oblAccessList,
  173. m_fDefaultGranted
  174. );
  175. m_fOldDefaultGranted = m_fDefaultGranted;
  176. return err;
  177. }
  178. /* virtual */
  179. HRESULT
  180. CW3SecurityPage::SaveInfo()
  181. /*++
  182. Routine Description:
  183. Save the information on this property page
  184. Arguments:
  185. None
  186. Return Value:
  187. Error return code
  188. --*/
  189. {
  190. ASSERT(IsDirty());
  191. TRACEEOLID("Saving W3 security page now...");
  192. CError err;
  193. //
  194. // Check to see if the ip access list needs saving.
  195. //
  196. BOOL fIplDirty = m_fIpDirty || (m_fOldDefaultGranted != m_fDefaultGranted);
  197. //
  198. // Use m_ notation because the message crackers require it
  199. //
  200. CBlob m_ipl;
  201. if (fIplDirty)
  202. {
  203. BuildIplBlob(m_oblAccessList, m_fDefaultGranted, m_ipl);
  204. }
  205. BeginWaitCursor();
  206. BEGIN_META_DIR_WRITE(CW3Sheet)
  207. STORE_DIR_DATA_ON_SHEET(m_dwSSLAccessPermissions)
  208. STORE_DIR_DATA_ON_SHEET(m_dwAuthFlags)
  209. STORE_DIR_DATA_ON_SHEET(m_strBasicDomain)
  210. STORE_DIR_DATA_ON_SHEET(m_strRealm)
  211. if (fIplDirty)
  212. {
  213. STORE_DIR_DATA_ON_SHEET(m_ipl)
  214. }
  215. STORE_DIR_DATA_ON_SHEET(m_strAnonUserName)
  216. STORE_DIR_DATA_ON_SHEET(m_fUseNTMapper)
  217. if (GetSheet()->QueryMajorVersion() < 6)
  218. {
  219. STORE_DIR_DATA_ON_SHEET(m_fPasswordSync)
  220. if (m_fPasswordSync != m_fPasswordSyncInitial && m_fPasswordSync)
  221. {
  222. FLAG_DIR_DATA_FOR_DELETION(MD_ANONYMOUS_PWD);
  223. }
  224. else
  225. {
  226. STORE_DIR_DATA_ON_SHEET(m_strAnonPassword);
  227. }
  228. }
  229. else
  230. {
  231. STORE_DIR_DATA_ON_SHEET(m_strAnonPassword);
  232. }
  233. END_META_DIR_WRITE(err)
  234. if (err.Succeeded())
  235. {
  236. BEGIN_META_INST_WRITE(CW3Sheet)
  237. if ( m_strCTLIdentifier.IsEmpty() )
  238. {
  239. FLAG_INST_DATA_FOR_DELETION( MD_SSL_CTL_IDENTIFIER )
  240. }
  241. else
  242. {
  243. STORE_INST_DATA_ON_SHEET(m_strCTLIdentifier)
  244. }
  245. if ( m_strCTLStoreName.IsEmpty() )
  246. {
  247. FLAG_INST_DATA_FOR_DELETION( MD_SSL_CTL_STORE_NAME )
  248. }
  249. else
  250. {
  251. STORE_INST_DATA_ON_SHEET(m_strCTLStoreName)
  252. }
  253. END_META_INST_WRITE(err)
  254. }
  255. EndWaitCursor();
  256. if (err.Succeeded())
  257. {
  258. m_fIpDirty = FALSE;
  259. m_fOldDefaultGranted = m_fDefaultGranted;
  260. err = ((CW3Sheet *)GetSheet())->SetKeyType();
  261. }
  262. return err;
  263. }
  264. BOOL
  265. CW3SecurityPage::FetchSSLState()
  266. /*++
  267. Routine Description:
  268. Obtain the state of the dialog depending on whether certificates
  269. are installed or not.
  270. Arguments:
  271. None
  272. Return Value:
  273. TRUE if certificates are installed, FALSE otherwise
  274. --*/
  275. {
  276. BeginWaitCursor();
  277. m_fCertInstalled = ::IsCertInstalledOnServer(
  278. QueryAuthInfo(),
  279. QueryMetaPath()
  280. );
  281. EndWaitCursor();
  282. return m_fCertInstalled;
  283. }
  284. void
  285. CW3SecurityPage::SetSSLControlState()
  286. /*++
  287. Routine Description:
  288. Enable/disable supported controls depending on what's installed.
  289. Only available on non-master instance nodes.
  290. Arguments:
  291. None
  292. Return Value:
  293. None
  294. --*/
  295. {
  296. // only enable these buttons on the local system!
  297. FetchSSLState();
  298. m_static_SSLPrompt.EnableWindow(!IsMasterInstance());
  299. m_button_GetCertificates.EnableWindow(
  300. !IsMasterInstance()
  301. && m_fHome
  302. && IsLocal()
  303. );
  304. m_button_Communications.EnableWindow(
  305. !IsMasterInstance()
  306. && IsSSLSupported()
  307. // && FetchSSLState()
  308. && IsLocal()
  309. );
  310. m_button_ViewCertificates.EnableWindow(IsLocal() ? m_fCertInstalled: FALSE);
  311. }
  312. //
  313. // Message Handlers
  314. //
  315. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  316. BOOL
  317. CW3SecurityPage::OnSetActive()
  318. /*++
  319. Routine Description:
  320. Page got activated -- set the SSL state depending on whether a
  321. certificate is installed or not.
  322. Arguments:
  323. None
  324. Return Value:
  325. TRUE to activate the page, FALSE otherwise.
  326. --*/
  327. {
  328. //
  329. // Enable/disable ssl controls
  330. //
  331. SetSSLControlState();
  332. return CInetPropertyPage::OnSetActive();
  333. }
  334. BOOL
  335. CW3SecurityPage::OnInitDialog()
  336. /*++
  337. Routine Description:
  338. WM_INITDIALOG handler. Initialize the dialog.
  339. Arguments:
  340. None.
  341. Return Value:
  342. TRUE if no focus is to be set automatically, FALSE if the focus
  343. is already set.
  344. --*/
  345. {
  346. CInetPropertyPage::OnInitDialog();
  347. //
  348. // Initialize certificate authorities ocx
  349. //
  350. CRect rc(0, 0, 0, 0);
  351. m_ocx_CertificateAuthorities.Create(
  352. _T("CertWiz"),
  353. WS_BORDER,
  354. rc,
  355. this,
  356. IDC_APPSCTRL
  357. );
  358. GetDlgItem(IDC_GROUP_IP)->EnableWindow(HasIPAccessCheck());
  359. GetDlgItem(IDC_ICON_IP)->EnableWindow(HasIPAccessCheck());
  360. GetDlgItem(IDC_STATIC_IP)->EnableWindow(HasIPAccessCheck());
  361. GetDlgItem(IDC_BUTTON_IP_SECURITY)->EnableWindow(HasIPAccessCheck());
  362. GetDlgItem(IDC_BUTTON_AUTHENTICATION)->EnableWindow(!m_fU2Installed);
  363. //
  364. // Configure for either master or non-master display.
  365. //
  366. m_check_EnableDS.ShowWindow(IsMasterInstance() ? SW_SHOW : SW_HIDE);
  367. m_check_EnableDS.EnableWindow(
  368. HasAdminAccess()
  369. && IsMasterInstance()
  370. && HasNTCertMapper()
  371. );
  372. #define SHOW_NON_MASTER(x)\
  373. (x).ShowWindow(IsMasterInstance() ? SW_HIDE : SW_SHOW)
  374. SHOW_NON_MASTER(m_static_SSLPrompt);
  375. SHOW_NON_MASTER(m_icon_Secure);
  376. SHOW_NON_MASTER(m_button_GetCertificates);
  377. SHOW_NON_MASTER(m_button_Communications);
  378. SHOW_NON_MASTER(m_button_ViewCertificates);
  379. #undef SHOW_NON_MASTER
  380. return TRUE;
  381. }
  382. void
  383. CW3SecurityPage::OnButtonAuthentication()
  384. /*++
  385. Routine Description:
  386. 'Authentication' button hander
  387. Arguments:
  388. None
  389. Return Value:
  390. None
  391. --*/
  392. {
  393. CAuthenticationDlg dlg(
  394. QueryServerName(),
  395. QueryInstance(),
  396. m_strBasicDomain,
  397. m_strRealm,
  398. m_dwAuthFlags,
  399. m_dwSSLAccessPermissions,
  400. m_strAnonUserName,
  401. m_strAnonPassword,
  402. m_fPasswordSync,
  403. HasAdminAccess(),
  404. HasDigest(),
  405. this
  406. );
  407. DWORD dwOldAccess = m_dwSSLAccessPermissions;
  408. DWORD dwOldAuth = m_dwAuthFlags;
  409. CString strOldDomain = m_strBasicDomain;
  410. CString strOldRealm = m_strRealm;
  411. CString strOldUserName = m_strAnonUserName;
  412. CStrPassword strOldPassword = m_strAnonPassword;
  413. BOOL fOldPasswordSync = m_fPasswordSync;
  414. dlg.m_dwVersionMajor = GetSheet()->QueryMajorVersion();
  415. dlg.m_dwVersionMinor = GetSheet()->QueryMinorVersion();
  416. if (dlg.DoModal() == IDOK)
  417. {
  418. //
  419. // See if anything has changed
  420. //
  421. if (dwOldAccess != m_dwSSLAccessPermissions
  422. || dwOldAuth != m_dwAuthFlags
  423. || m_strBasicDomain != strOldDomain
  424. || m_strRealm != strOldRealm
  425. || m_strAnonUserName != strOldUserName
  426. || m_strAnonPassword != strOldPassword
  427. || m_fPasswordSync != fOldPasswordSync
  428. )
  429. {
  430. //
  431. // Mark as dirty
  432. //
  433. OnItemChanged();
  434. }
  435. }
  436. }
  437. void
  438. CW3SecurityPage::OnButtonCommunications()
  439. /*++
  440. Routine Description:
  441. 'Communications' button handler
  442. Arguments:
  443. None
  444. Return Value:
  445. None
  446. --*/
  447. {
  448. //
  449. // Prep the flag for if we can edit CTLs or not
  450. //
  451. BOOL fEditCTLs = IsMasterInstance() || m_fHome;
  452. //
  453. // Prep the communications dialog
  454. //
  455. CSecCommDlg dlg(
  456. QueryServerName(),
  457. QueryInstanceMetaPath(),
  458. m_strBasicDomain,
  459. m_dwAuthFlags,
  460. QueryAuthInfo(),
  461. m_dwSSLAccessPermissions,
  462. IsMasterInstance(),
  463. IsSSLSupported(),
  464. IsSSL128Supported(),
  465. m_fU2Installed,
  466. m_strCTLIdentifier,
  467. m_strCTLStoreName,
  468. fEditCTLs,
  469. IsLocal(),
  470. this
  471. );
  472. DWORD dwOldAccess = m_dwSSLAccessPermissions;
  473. DWORD dwOldAuth = m_dwAuthFlags;
  474. if (dlg.DoModal() == IDOK)
  475. {
  476. //
  477. // See if anything has changed
  478. //
  479. if (dwOldAccess != m_dwSSLAccessPermissions
  480. || dwOldAuth != m_dwAuthFlags
  481. )
  482. {
  483. //
  484. // Mark as dirty
  485. //
  486. OnItemChanged();
  487. }
  488. //
  489. // See if the CTL information has changed
  490. //
  491. if (dlg.m_bCTLDirty)
  492. {
  493. m_strCTLIdentifier = dlg.m_strCTLIdentifier;
  494. m_strCTLStoreName = dlg.m_strCTLStoreName;
  495. OnItemChanged();
  496. }
  497. }
  498. }
  499. void
  500. CW3SecurityPage::OnButtonIpSecurity()
  501. /*++
  502. Routine Description:
  503. 'tcpip' button handler
  504. Arguments:
  505. None
  506. Return Value:
  507. None
  508. --*/
  509. {
  510. CIPDomainDlg dlg(
  511. m_fIpDirty,
  512. m_fDefaultGranted,
  513. m_fOldDefaultGranted,
  514. m_oblAccessList,
  515. this
  516. );
  517. if (dlg.DoModal() == IDOK)
  518. {
  519. //
  520. // Rebuild the list. Temporarily reset ownership, otherwise
  521. // RemoveAll() will destroy the pointers which are shared with the
  522. // new list.
  523. //
  524. BOOL fOwn = m_oblAccessList.SetOwnership(FALSE);
  525. m_oblAccessList.RemoveAll();
  526. m_oblAccessList.AddTail(&dlg.GetAccessList());
  527. m_oblAccessList.SetOwnership(fOwn);
  528. if (m_fIpDirty || m_fOldDefaultGranted != m_fDefaultGranted)
  529. {
  530. OnItemChanged();
  531. }
  532. }
  533. }
  534. void
  535. CW3SecurityPage::OnButtonGetCertificates()
  536. /*++
  537. Routine Description:
  538. "get certicate" button handler
  539. Arguments:
  540. None
  541. Return Value:
  542. None
  543. --*/
  544. {
  545. m_ocx_CertificateAuthorities.SetMachineName(QueryServerName());
  546. m_ocx_CertificateAuthorities.SetServerInstance(QueryInstanceMetaPath());
  547. CThemeContextActivator activator(theApp.GetFusionInitHandle());
  548. m_ocx_CertificateAuthorities.DoClick();
  549. //
  550. // There may now be a certificate. See if we should enable the edit button.
  551. //
  552. SetSSLControlState();
  553. }
  554. void
  555. CW3SecurityPage::OnButtonViewCertificates()
  556. /*++
  557. Routine Description:
  558. "view certicate" button handler
  559. Arguments:
  560. None
  561. Return Value:
  562. None
  563. --*/
  564. {
  565. HCERTSTORE hStore = NULL;
  566. PCCERT_CONTEXT pCert = NULL;
  567. PCCERT_CONTEXT pNewCertificate = NULL;
  568. CMetaKey key(QueryAuthInfo(),
  569. QueryInstanceMetaPath(),
  570. METADATA_PERMISSION_READ,
  571. METADATA_MASTER_ROOT_HANDLE);
  572. if (key.Succeeded())
  573. {
  574. CString store_name;
  575. CBlob hash;
  576. if ( SUCCEEDED(key.QueryValue(MD_SSL_CERT_STORE_NAME, store_name))
  577. && SUCCEEDED(key.QueryValue(MD_SSL_CERT_HASH, hash))
  578. )
  579. {
  580. // We got our information already...
  581. // so don't keep the handle open...
  582. key.Close();
  583. hStore = CertOpenStore(
  584. CERT_STORE_PROV_SYSTEM,
  585. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  586. NULL,
  587. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  588. store_name
  589. );
  590. if (hStore != NULL)
  591. {
  592. // Now we need to find cert by hash
  593. CRYPT_HASH_BLOB crypt_hash;
  594. crypt_hash.cbData = hash.GetSize();
  595. crypt_hash.pbData = hash.GetData();
  596. pCert = CertFindCertificateInStore(hStore,
  597. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  598. 0, CERT_FIND_HASH, (LPVOID)&crypt_hash, NULL);
  599. // check if this cert has been renewed and is actually
  600. // pointing to another cert... if it is then display the other cert.
  601. if (pCert)
  602. {
  603. DWORD dwProtocol = SP_PROT_SERVERS;
  604. if (TRUE == CheckForCertificateRenewal(dwProtocol,pCert,&pNewCertificate))
  605. {
  606. TRACEEOLID(_T("Cert has been renewed:display new cert\r\n"));
  607. if (pCert != NULL)
  608. {
  609. // free the one we already had.
  610. ::CertFreeCertificateContext(pCert);pCert=NULL;
  611. }
  612. pCert = pNewCertificate;
  613. }
  614. }
  615. }
  616. }
  617. }
  618. if (pCert)
  619. {
  620. BOOL fPropertiesChanged;
  621. CRYPTUI_VIEWCERTIFICATE_STRUCT vcs;
  622. HCERTSTORE hCertStore = ::CertDuplicateStore(hStore);
  623. ::ZeroMemory (&vcs, sizeof (vcs));
  624. vcs.dwSize = sizeof (vcs);
  625. vcs.hwndParent = GetParent()->GetSafeHwnd();
  626. vcs.dwFlags = 0;
  627. vcs.cStores = 1;
  628. vcs.rghStores = &hCertStore;
  629. vcs.pCertContext = pCert;
  630. ::CryptUIDlgViewCertificate(&vcs, &fPropertiesChanged);
  631. ::CertCloseStore (hCertStore, 0);
  632. }
  633. if (pCert != NULL)
  634. {
  635. ::CertFreeCertificateContext(pCert);pCert=NULL;
  636. }
  637. if (hStore != NULL)
  638. {
  639. ::CertCloseStore(hStore, 0);
  640. }
  641. }
  642. void
  643. CW3SecurityPage::OnItemChanged()
  644. /*++
  645. Routine Description:
  646. All EN_CHANGE messages map to this function
  647. Arguments:
  648. None
  649. Return Value:
  650. None
  651. --*/
  652. {
  653. SetModified(TRUE);
  654. }
  655. #define CB_SHA_DIGEST_LEN 20
  656. BOOL
  657. CheckForCertificateRenewal(
  658. DWORD dwProtocol,
  659. PCCERT_CONTEXT pCertContext,
  660. PCCERT_CONTEXT *ppNewCertificate)
  661. {
  662. BYTE rgbThumbprint[CB_SHA_DIGEST_LEN];
  663. DWORD cbThumbprint = sizeof(rgbThumbprint);
  664. CRYPT_HASH_BLOB HashBlob;
  665. PCCERT_CONTEXT pNewCert;
  666. BOOL fMachineCert;
  667. PCRYPT_KEY_PROV_INFO pProvInfo = NULL;
  668. DWORD cbSize;
  669. HCERTSTORE hMyCertStore = 0;
  670. BOOL fRenewed = FALSE;
  671. HCERTSTORE g_hMyCertStore;
  672. if(dwProtocol & SP_PROT_SERVERS)
  673. {
  674. fMachineCert = TRUE;
  675. }
  676. else
  677. {
  678. fMachineCert = FALSE;
  679. }
  680. //
  681. // Loop through the linked list of renewed certificates, looking
  682. // for the last one.
  683. //
  684. while(TRUE)
  685. {
  686. //
  687. // Check for renewal property.
  688. //
  689. if(!CertGetCertificateContextProperty(pCertContext,
  690. CERT_RENEWAL_PROP_ID,
  691. rgbThumbprint,
  692. &cbThumbprint))
  693. {
  694. // Certificate has not been renewed.
  695. break;
  696. }
  697. //DebugLog((DEB_TRACE, "Certificate has renewal property\n"));
  698. //
  699. // Determine whether to look in the local machine MY store
  700. // or the current user MY store.
  701. //
  702. if(!hMyCertStore)
  703. {
  704. if(CertGetCertificateContextProperty(pCertContext,
  705. CERT_KEY_PROV_INFO_PROP_ID,
  706. NULL,
  707. &cbSize))
  708. {
  709. //SafeAllocaAllocate(pProvInfo, cbSize);
  710. pProvInfo = (PCRYPT_KEY_PROV_INFO) LocalAlloc(LPTR,cbSize);
  711. if(pProvInfo == NULL)
  712. {
  713. break;
  714. }
  715. if(CertGetCertificateContextProperty(pCertContext,
  716. CERT_KEY_PROV_INFO_PROP_ID,
  717. pProvInfo,
  718. &cbSize))
  719. {
  720. if(pProvInfo->dwFlags & CRYPT_MACHINE_KEYSET)
  721. {
  722. fMachineCert = TRUE;
  723. }
  724. else
  725. {
  726. fMachineCert = FALSE;
  727. }
  728. }
  729. if (pProvInfo)
  730. {
  731. LocalFree(pProvInfo);pProvInfo=NULL;
  732. }
  733. //SafeAllocaFree(pProvInfo);
  734. }
  735. }
  736. //
  737. // Open up the appropriate MY store, and attempt to find
  738. // the new certificate.
  739. //
  740. if(!hMyCertStore)
  741. {
  742. if(fMachineCert)
  743. {
  744. g_hMyCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,X509_ASN_ENCODING,0,CERT_SYSTEM_STORE_LOCAL_MACHINE,L"MY");
  745. if(g_hMyCertStore)
  746. {
  747. hMyCertStore = g_hMyCertStore;
  748. }
  749. }
  750. else
  751. {
  752. hMyCertStore = CertOpenSystemStore(0, _T("MY"));
  753. }
  754. if(!hMyCertStore)
  755. {
  756. //DebugLog((DEB_ERROR, "Error 0x%x opening %s MY certificate store!\n", GetLastError(),(fMachineCert ? "local machine" : "current user") ));
  757. break;
  758. }
  759. }
  760. HashBlob.cbData = cbThumbprint;
  761. HashBlob.pbData = rgbThumbprint;
  762. pNewCert = CertFindCertificateInStore(hMyCertStore,
  763. X509_ASN_ENCODING,
  764. 0,
  765. CERT_FIND_HASH,
  766. &HashBlob,
  767. NULL);
  768. if(pNewCert == NULL)
  769. {
  770. // Certificate has been renewed, but the new certificate
  771. // cannot be found.
  772. //DebugLog((DEB_ERROR, "New certificate cannot be found: 0x%x\n", GetLastError()));
  773. break;
  774. }
  775. //
  776. // Return the new certificate, but first loop back and see if it's been
  777. // renewed itself.
  778. //
  779. pCertContext = pNewCert;
  780. *ppNewCertificate = pNewCert;
  781. //DebugLog((DEB_TRACE, "Certificate has been renewed\n"));
  782. fRenewed = TRUE;
  783. }
  784. //
  785. // Cleanup.
  786. //
  787. if(hMyCertStore && hMyCertStore != g_hMyCertStore)
  788. {
  789. CertCloseStore(hMyCertStore, 0);
  790. }
  791. return fRenewed;
  792. }