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.

1114 lines
32 KiB

  1. // File: certui.cpp
  2. #include "precomp.h"
  3. #include "resource.h"
  4. #include "nmmkcert.h"
  5. #include "certui.h"
  6. #include <tsecctrl.h>
  7. #include "SDKInternal.h"
  8. #include "ConfUtil.h"
  9. #define SZ_CRYPTDLGDLL "CRYPTDLG"
  10. extern INmSysInfo2 * g_pNmSysInfo;
  11. //
  12. // While the credentials underlying the certificate we are using
  13. // are in use, we need to keep the certificate context around
  14. // and the store open. So we hold the currently open cert store
  15. // and cert context in these globals:
  16. static PCCERT_CONTEXT g_pCertContext;
  17. static HCERTSTORE g_hCertStore;
  18. TCHAR * FormatCert ( PBYTE pbEncodedCert, DWORD cbEncodedCert )
  19. {
  20. DWORD sc;
  21. PCCERT_CONTEXT pCert = NULL, pIssuerCert = NULL, pCACert = NULL;
  22. DWORD cbRet = 0;
  23. CHAR * pSubject = NULL;
  24. CHAR * pIssuer = NULL;
  25. DWORD cbSubject = 0;
  26. DWORD cbIssuer = 0;
  27. DWORD dwFlags;
  28. DWORD cbTotalRequired;
  29. CHAR szLoadStringBuf[512];
  30. HCERTSTORE hRootStore = NULL;
  31. HCERTSTORE hCAStore = NULL;
  32. BOOL fSelfIssued = FALSE;
  33. TCHAR * pInfo = NULL;
  34. TCHAR szNotBefore[64];
  35. TCHAR szNotAfter[64];
  36. ASSERT(pbEncodedCert);
  37. ASSERT(cbEncodedCert);
  38. //
  39. // Get the certificate from the encoded blob
  40. //
  41. pCert = CertCreateCertificateContext ( X509_ASN_ENCODING,
  42. pbEncodedCert,
  43. cbEncodedCert );
  44. if ( NULL == pCert )
  45. {
  46. // Creating the cert context failed
  47. ERROR_OUT(("Error creating cert context from %x (%d bytes): %x",
  48. pbEncodedCert, cbEncodedCert, GetLastError()));
  49. goto cleanup;
  50. }
  51. //
  52. // Get the subject information
  53. //
  54. cbSubject = CertNameToStr (
  55. pCert->dwCertEncodingType,
  56. &pCert->pCertInfo->Subject,
  57. CERT_FORMAT_FLAGS,
  58. NULL, 0);
  59. if ( 0 == cbSubject )
  60. {
  61. ERROR_OUT(("GetUserInfo: no subject string"));
  62. goto cleanup;
  63. }
  64. pSubject = new CHAR[cbSubject + 1];
  65. if ( NULL == pSubject )
  66. {
  67. ERROR_OUT(("GetUserInfo: error allocating subject name"));
  68. goto cleanup;
  69. }
  70. if ( 0 >= CertNameToStr (
  71. pCert->dwCertEncodingType,
  72. &pCert->pCertInfo->Subject,
  73. CERT_FORMAT_FLAGS,
  74. pSubject, cbSubject+1))
  75. {
  76. ERROR_OUT(("GetUserInfo: error getting subject string"));
  77. goto cleanup;
  78. }
  79. //
  80. // Get the issuer information
  81. //
  82. cbIssuer = CertNameToStr (
  83. pCert->dwCertEncodingType,
  84. &pCert->pCertInfo->Issuer,
  85. CERT_FORMAT_FLAGS,
  86. NULL, 0);
  87. if ( 0 == cbIssuer )
  88. {
  89. ERROR_OUT(("GetUserInfo: no issuer string"));
  90. goto cleanup;
  91. }
  92. pIssuer = new CHAR[cbIssuer + 1];
  93. if ( NULL == pIssuer )
  94. {
  95. ERROR_OUT(("GetUserInfo: error allocating issuer name"));
  96. }
  97. if ( 0 >= CertNameToStr (
  98. pCert->dwCertEncodingType,
  99. &pCert->pCertInfo->Issuer,
  100. CERT_FORMAT_FLAGS,
  101. pIssuer, cbIssuer+1))
  102. {
  103. ERROR_OUT(("GetUserInfo: error getting issuer string"));
  104. goto cleanup;
  105. }
  106. //
  107. // Format the file time from the cert
  108. //
  109. SYSTEMTIME stNotBefore;
  110. SYSTEMTIME stNotAfter;
  111. FileTimeToSystemTime(&(pCert->pCertInfo->NotBefore), &stNotBefore);
  112. FileTimeToSystemTime(&(pCert->pCertInfo->NotAfter), &stNotAfter);
  113. FmtDateTime(&stNotBefore, szNotBefore, CCHMAX(szNotBefore));
  114. FmtDateTime(&stNotAfter, szNotAfter, CCHMAX(szNotAfter));
  115. //
  116. // Open the root store for certificate verification
  117. //
  118. hRootStore = CertOpenSystemStore(0, "Root");
  119. if( NULL == hRootStore )
  120. {
  121. ERROR_OUT(("Couldn't open root certificate store"));
  122. goto cleanup;
  123. }
  124. //
  125. // Get the issuer certificate from the root store and check for problems
  126. //
  127. dwFlags = CERT_STORE_REVOCATION_FLAG |
  128. CERT_STORE_SIGNATURE_FLAG |
  129. CERT_STORE_TIME_VALIDITY_FLAG;
  130. // Get the issuer of this cert
  131. pIssuerCert = CertGetIssuerCertificateFromStore(
  132. hRootStore,
  133. pCert,
  134. NULL,
  135. &dwFlags );
  136. // If the issuer of the certificate cannot be found in the root store,
  137. // check the CA store iteratively until we work our way back to a root
  138. // certificate
  139. pCACert = pCert;
  140. while ( NULL == pIssuerCert )
  141. {
  142. PCCERT_CONTEXT pTmpCert;
  143. if ( NULL == hCAStore )
  144. {
  145. hCAStore = CertOpenSystemStore(0, "CA");
  146. if ( NULL == hCAStore )
  147. {
  148. ERROR_OUT(("Couldn't open CA certificate store"));
  149. goto cleanup;
  150. }
  151. }
  152. dwFlags = CERT_STORE_REVOCATION_FLAG |
  153. CERT_STORE_SIGNATURE_FLAG |
  154. CERT_STORE_TIME_VALIDITY_FLAG;
  155. pTmpCert = CertGetIssuerCertificateFromStore(
  156. hCAStore,
  157. pCACert,
  158. NULL,
  159. &dwFlags );
  160. if ( NULL == pTmpCert )
  161. {
  162. TRACE_OUT(("Issuer not found in CA store either"));
  163. break;
  164. }
  165. if ( pCACert != pCert )
  166. CertFreeCertificateContext(pCACert);
  167. pCACert = pTmpCert;
  168. if ((( CERT_STORE_REVOCATION_FLAG & dwFlags ) &&
  169. !( CERT_STORE_NO_CRL_FLAG & dwFlags )) ||
  170. ( CERT_STORE_SIGNATURE_FLAG & dwFlags ) ||
  171. ( CERT_STORE_TIME_VALIDITY_FLAG & dwFlags ))
  172. {
  173. TRACE_OUT(("Problem with issuer in CA store: %x", dwFlags));
  174. break;
  175. }
  176. dwFlags = CERT_STORE_REVOCATION_FLAG |
  177. CERT_STORE_SIGNATURE_FLAG |
  178. CERT_STORE_TIME_VALIDITY_FLAG;
  179. pIssuerCert = CertGetIssuerCertificateFromStore(
  180. hRootStore,
  181. pCACert,
  182. NULL,
  183. &dwFlags );
  184. }
  185. if ( pCACert != pCert )
  186. CertFreeCertificateContext ( pCACert );
  187. //
  188. // Total up the return buffer required
  189. //
  190. // BUGBUG this overestimates the requirements slightly because
  191. // this formatting buffer contains specifiers which will be
  192. // replaced during wsprintf
  193. cbTotalRequired = cbSubject +
  194. cbIssuer +
  195. lstrlen(szNotBefore) +
  196. lstrlen(szNotAfter) +
  197. FLoadString2( IDS_FMTBUFFER, szLoadStringBuf,
  198. sizeof(szLoadStringBuf)) + 1;
  199. //
  200. // If there are problems, account for the extra info:
  201. //
  202. if ( NULL == pIssuerCert )
  203. {
  204. // If after all we couldn't find the issuer check if this is
  205. // a NetMeeting self-issued certificate and generate an appropriate
  206. // message if so:
  207. DWORD dwMagic;
  208. DWORD cbMagic;
  209. cbMagic = sizeof(dwMagic);
  210. // BUGBUG: why is user prop not available for remote context?
  211. //if (pSecurityInterface->pfn_CertGetCertificateContextProperty(pCert,
  212. // CERT_FIRST_USER_PROP_ID, &dwMagic, &cbMagic) &&
  213. // cbMagic == sizeof(dwMagic) && dwMagic == NMMKCERT_MAGIC )
  214. if ( !lstrcmp( pIssuer, SZ_NMROOTNAME ))
  215. {
  216. // We're just going to return some generic text about the
  217. // NetMeeting default certificate
  218. cbTotalRequired = FLoadString2( IDS_GENERIC_NMDC_TEXT,
  219. szLoadStringBuf, sizeof(szLoadStringBuf)) + 1;
  220. fSelfIssued = TRUE;
  221. }
  222. else
  223. {
  224. cbTotalRequired += FLoadString2( IDS_CERTERR_NOISSUER,
  225. szLoadStringBuf, sizeof(szLoadStringBuf)) + 1;
  226. }
  227. }
  228. else
  229. {
  230. if ( dwFlags & CERT_STORE_SIGNATURE_FLAG )
  231. {
  232. WARNING_OUT(("Verify: Signature invalid"));
  233. cbTotalRequired += FLoadString2( IDS_CERTERR_SIG,
  234. szLoadStringBuf, sizeof(szLoadStringBuf)) + 1;
  235. }
  236. if ( dwFlags & CERT_STORE_TIME_VALIDITY_FLAG )
  237. {
  238. WARNING_OUT(("Verify: Cert expired"));
  239. cbTotalRequired += FLoadString2( IDS_CERTERR_EXPIRED,
  240. szLoadStringBuf, sizeof(szLoadStringBuf)) + 1;
  241. }
  242. if ( (dwFlags & CERT_STORE_REVOCATION_FLAG) &&
  243. !(dwFlags & CERT_STORE_NO_CRL_FLAG ) )
  244. {
  245. WARNING_OUT(("Verify: Cert revoked"));
  246. cbTotalRequired += FLoadString2( IDS_CERTERR_REVOKED,
  247. szLoadStringBuf, sizeof(szLoadStringBuf)) + 1;
  248. }
  249. if ( 0 == (dwFlags & ~CERT_STORE_NO_CRL_FLAG) )
  250. {
  251. // Everything is OK:
  252. cbTotalRequired += FLoadString2( IDS_CERT_VERIFIED,
  253. szLoadStringBuf, sizeof(szLoadStringBuf));
  254. }
  255. }
  256. //
  257. // Allocate the required buffer
  258. //
  259. pInfo = new TCHAR[cbTotalRequired];
  260. if ( NULL == pInfo )
  261. {
  262. ERROR_OUT(("Error allocating FormatCert return buffer"));
  263. goto cleanup;
  264. }
  265. //
  266. // If we're reporting on a NetMeeting issued certificate, just load
  267. // the generic text and return.
  268. //
  269. if ( fSelfIssued )
  270. {
  271. FLoadString( IDS_GENERIC_NMDC_TEXT, pInfo, cbTotalRequired );
  272. goto cleanup;
  273. }
  274. //
  275. // If we are here we can go ahead and format the data into the buffer
  276. //
  277. FLoadString( IDS_FMTBUFFER, szLoadStringBuf,
  278. sizeof(szLoadStringBuf));
  279. //
  280. // Do the formatting
  281. //
  282. wsprintf( pInfo, szLoadStringBuf, pSubject, pIssuer,
  283. szNotBefore, szNotAfter );
  284. if ( NULL == pIssuerCert )
  285. {
  286. FLoadString( IDS_CERTERR_NOISSUER,
  287. szLoadStringBuf, sizeof(szLoadStringBuf));
  288. lstrcat( pInfo, szLoadStringBuf );
  289. }
  290. else
  291. {
  292. if ( dwFlags & CERT_STORE_SIGNATURE_FLAG )
  293. {
  294. FLoadString( IDS_CERTERR_SIG,
  295. szLoadStringBuf, sizeof(szLoadStringBuf));
  296. lstrcat( pInfo, szLoadStringBuf );
  297. }
  298. if ( dwFlags & CERT_STORE_TIME_VALIDITY_FLAG )
  299. {
  300. FLoadString( IDS_CERTERR_EXPIRED,
  301. szLoadStringBuf, sizeof(szLoadStringBuf));
  302. lstrcat( pInfo, szLoadStringBuf );
  303. }
  304. if ( (dwFlags & CERT_STORE_REVOCATION_FLAG) &&
  305. !(dwFlags & CERT_STORE_NO_CRL_FLAG ) )
  306. {
  307. FLoadString( IDS_CERTERR_REVOKED,
  308. szLoadStringBuf, sizeof(szLoadStringBuf));
  309. lstrcat( pInfo, szLoadStringBuf );
  310. }
  311. if ( 0 == (dwFlags & ~CERT_STORE_NO_CRL_FLAG) )
  312. {
  313. // Everything is OK:
  314. FLoadString( IDS_CERT_VERIFIED,
  315. szLoadStringBuf, sizeof(szLoadStringBuf));
  316. lstrcat( pInfo, szLoadStringBuf );
  317. }
  318. }
  319. ASSERT( cbRet < 1000 ); // Reasonableness check
  320. cleanup:
  321. if ( NULL != pSubject )
  322. delete [] pSubject;
  323. if ( NULL != pIssuer )
  324. delete [] pIssuer;
  325. if ( NULL != pCert )
  326. {
  327. CertFreeCertificateContext ( pCert );
  328. }
  329. if ( NULL != pIssuerCert )
  330. {
  331. CertFreeCertificateContext ( pIssuerCert );
  332. }
  333. if ( NULL != hRootStore )
  334. {
  335. if ( !CertCloseStore(hRootStore, CERT_CLOSE_STORE_CHECK_FLAG))
  336. {
  337. WARNING_OUT(("FormatCert: error closing root store"));
  338. }
  339. }
  340. if ( NULL != hCAStore )
  341. {
  342. if ( !CertCloseStore(hCAStore, CERT_CLOSE_STORE_CHECK_FLAG))
  343. {
  344. WARNING_OUT(("FormatCert: error closing CA store"));
  345. }
  346. }
  347. return pInfo;
  348. }
  349. BOOL RefreshSelfIssuedCert (VOID)
  350. {
  351. BOOL bRet = FALSE;
  352. DWORD dwResult;
  353. RegEntry reCONF(CONFERENCING_KEY, HKEY_CURRENT_USER);
  354. if (reCONF.GetNumber(REGVAL_SECURITY_AUTHENTICATION,
  355. DEFAULT_SECURITY_AUTHENTICATION))
  356. {
  357. return TRUE;
  358. }
  359. //
  360. // If there's no sys info interface, that's probably OK, we're just
  361. // being called in the setup wizard.
  362. //
  363. if (!g_pNmSysInfo)
  364. return FALSE;
  365. //
  366. // Clear old cert out of transport
  367. //
  368. g_pNmSysInfo->ProcessSecurityData(
  369. TPRTCTRL_SETX509CREDENTIALS,
  370. 0, 0,
  371. &dwResult);
  372. if ( g_pCertContext )
  373. {
  374. CertFreeCertificateContext ( g_pCertContext );
  375. g_pCertContext = NULL;
  376. }
  377. if ( g_hCertStore )
  378. {
  379. if ( !CertCloseStore ( g_hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ))
  380. {
  381. WARNING_OUT(("SetSelfIssuedCert: closing store failed"));
  382. }
  383. g_hCertStore = NULL;
  384. }
  385. g_hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,
  386. X509_ASN_ENCODING,
  387. 0,
  388. CERT_SYSTEM_STORE_CURRENT_USER,
  389. WSZNMSTORE );
  390. if ( g_hCertStore )
  391. {
  392. //
  393. // We only expect one cert in here, get it
  394. //
  395. g_pCertContext = CertFindCertificateInStore(
  396. g_hCertStore,
  397. X509_ASN_ENCODING,
  398. 0,
  399. CERT_FIND_ANY,
  400. NULL,
  401. NULL);
  402. if ( g_pCertContext )
  403. {
  404. dwResult = -1;
  405. g_pNmSysInfo->ProcessSecurityData(
  406. TPRTCTRL_SETX509CREDENTIALS,
  407. (DWORD_PTR)g_pCertContext, 0,
  408. &dwResult);
  409. //
  410. // g_hCertStore and g_pCertContext now in use
  411. //
  412. if ( !dwResult )
  413. {
  414. bRet = TRUE;
  415. }
  416. else
  417. {
  418. ERROR_OUT(("RefreshSelfIssuedCert - failed in T.120"));
  419. }
  420. }
  421. else
  422. {
  423. ERROR_OUT(("RefreshPrivacyCert: no cert in %s?", SZNMSTORE));
  424. }
  425. }
  426. else
  427. {
  428. WARNING_OUT(("RefreshSelfIssuedCert: error opening %s store %x",
  429. SZNMSTORE, GetLastError()));
  430. }
  431. return bRet;
  432. }
  433. DWORD NumUserCerts(VOID)
  434. {
  435. DWORD cCerts = 0;
  436. HCERTSTORE hStore;
  437. PCCERT_CONTEXT pCert = NULL;
  438. if ( hStore = CertOpenSystemStore(0, "MY"))
  439. {
  440. while ( pCert = CertEnumCertificatesInStore(
  441. hStore, (PCERT_CONTEXT)pCert ))
  442. cCerts++;
  443. if ( !CertCloseStore( hStore, CERT_CLOSE_STORE_CHECK_FLAG ))
  444. {
  445. WARNING_OUT(("NumUserCerts: error closing store"));
  446. }
  447. }
  448. return cCerts;
  449. }
  450. #include "cryptdlg.h"
  451. typedef BOOL (WINAPI *PFN_CERT_SELECT_CERTIFICATE)(PCERT_SELECT_STRUCT_A);
  452. BOOL ChangeCertDlg ( HWND hwndParent, HINSTANCE hInstance,
  453. PBYTE * ppEncodedCert, DWORD * pcbEncodedCert )
  454. {
  455. HINSTANCE hCryptDlg = NmLoadLibrary ( SZ_CRYPTDLGDLL ,TRUE);
  456. PFN_CERT_SELECT_CERTIFICATE pfn_CertSelectCertificate;
  457. RegEntry reCONF(CONFERENCING_KEY, HKEY_CURRENT_USER);
  458. PCCERT_CONTEXT pOldCert = NULL;
  459. BOOL bRet = FALSE;
  460. //
  461. // First, make sure we can get the CRYPTDLG entry point we need
  462. //
  463. if ( NULL == hCryptDlg )
  464. {
  465. ERROR_OUT(("Error loading CRYPTDLG"));
  466. return bRet;
  467. }
  468. pfn_CertSelectCertificate =
  469. (PFN_CERT_SELECT_CERTIFICATE)GetProcAddress ( hCryptDlg,
  470. "CertSelectCertificateA" );
  471. if ( NULL == pfn_CertSelectCertificate )
  472. {
  473. ERROR_OUT(("Error getting CertSelectCertificate entry point"));
  474. goto cleanup;
  475. }
  476. //
  477. // Prepare to bring up the choose dialog
  478. //
  479. CERT_SELECT_STRUCT_A css;
  480. ZeroMemory ( &css, sizeof(css) );
  481. css.dwSize = sizeof(css);
  482. css.hwndParent = hwndParent;
  483. css.hInstance = hInstance;
  484. css.cCertStore = 1;
  485. HCERTSTORE aCertStore[1];
  486. aCertStore[0] = CertOpenSystemStore(0, "MY" );
  487. if ( NULL == aCertStore[0] )
  488. {
  489. ERROR_OUT(("Error opening 'my' store"));
  490. goto cleanup;
  491. }
  492. css.arrayCertStore = aCertStore;
  493. css.szPurposeOid = szOID_PKIX_KP_CLIENT_AUTH; // BUGBUG add server auth?
  494. PCCERT_CONTEXT pcc;
  495. pcc = NULL;
  496. //
  497. // Now, get access to the current NetMeeting certificate, if any
  498. //
  499. LPBYTE pCertID;
  500. DWORD cbCertID;
  501. if ( cbCertID = reCONF.GetBinary ( REGVAL_CERT_ID, (void**)&pCertID ))
  502. {
  503. while ( pOldCert = CertEnumCertificatesInStore(
  504. aCertStore[0], (PCERT_CONTEXT)pOldCert ))
  505. {
  506. if (cbCertID == pOldCert->pCertInfo->SerialNumber.cbData &&
  507. !memcmp(pCertID, pOldCert->pCertInfo->SerialNumber.pbData,
  508. pOldCert->pCertInfo->SerialNumber.cbData))
  509. {
  510. // pOldCert must now be freed via CertFreeCertificateContext
  511. pcc = pOldCert;
  512. break;
  513. }
  514. }
  515. }
  516. css.cCertContext = 0;
  517. css.arrayCertContext = &pcc;
  518. if (pfn_CertSelectCertificate ( &css ))
  519. {
  520. ASSERT(1 == css.cCertContext);
  521. //
  522. // It worked, return the new cert
  523. //
  524. CoTaskMemFree ( *ppEncodedCert );
  525. if ( *ppEncodedCert = (PBYTE)CoTaskMemAlloc ( pcc->cbCertEncoded ))
  526. {
  527. memcpy ( *ppEncodedCert, pcc->pbCertEncoded, pcc->cbCertEncoded );
  528. *pcbEncodedCert = pcc->cbCertEncoded;
  529. bRet = TRUE;
  530. }
  531. }
  532. cleanup:
  533. if ( aCertStore[0] )
  534. if (!CertCloseStore ( aCertStore[0], 0 ))
  535. {
  536. WARNING_OUT(("ChangeCertDlg: error closing store"));
  537. }
  538. if ( pOldCert )
  539. {
  540. CertFreeCertificateContext(pOldCert);
  541. }
  542. if ( hCryptDlg )
  543. FreeLibrary ( hCryptDlg );
  544. return bRet;
  545. }
  546. typedef BOOL (WINAPI *PFN_CERT_VIEW_PROPERTIES)(PCERT_VIEWPROPERTIES_STRUCT);
  547. VOID ViewCertDlg ( HWND hwndParent, PCCERT_CONTEXT pCert )
  548. {
  549. HINSTANCE hCryptDlg = NmLoadLibrary ( SZ_CRYPTDLGDLL, TRUE );
  550. PFN_CERT_VIEW_PROPERTIES pfn_CertViewProperties;
  551. //
  552. // First, make sure we can get the CRYPTDLG entry point we need
  553. //
  554. if ( NULL == hCryptDlg )
  555. {
  556. ERROR_OUT(("Error loading CRYPTDLG"));
  557. return;
  558. }
  559. pfn_CertViewProperties =
  560. (PFN_CERT_VIEW_PROPERTIES)GetProcAddress ( hCryptDlg,
  561. "CertViewPropertiesA" );
  562. if ( NULL == pfn_CertViewProperties )
  563. {
  564. ERROR_OUT(("Error getting CertViewProperties entry point"));
  565. goto cleanup;
  566. }
  567. CERT_VIEWPROPERTIES_STRUCT cvp;
  568. ZeroMemory(&cvp, sizeof(cvp));
  569. cvp.dwSize = sizeof(cvp);
  570. cvp.pCertContext = pCert;
  571. cvp.hwndParent = hwndParent;
  572. pfn_CertViewProperties ( &cvp );
  573. cleanup:
  574. if ( hCryptDlg )
  575. FreeLibrary ( hCryptDlg );
  576. return;
  577. }
  578. VOID FreeT120EncodedCert ( PBYTE pbEncodedCert )
  579. {
  580. CoTaskMemFree(pbEncodedCert);
  581. }
  582. BOOL GetT120ActiveCert ( PBYTE * ppbEncodedCert, DWORD * pcbEncodedCert )
  583. {
  584. if ( !g_pNmSysInfo )
  585. {
  586. ERROR_OUT(("GetT120ActiveCert: g_pNmSysInfo NULL"));
  587. return FALSE;
  588. }
  589. DWORD dwResult = -1;
  590. g_pNmSysInfo->ProcessSecurityData(TPRTCTRL_GETX509CREDENTIALS,
  591. (DWORD_PTR)ppbEncodedCert,
  592. (DWORD_PTR)pcbEncodedCert,
  593. &dwResult);
  594. return ( dwResult == 0 );
  595. }
  596. BOOL SetT120CertInRegistry ( PBYTE pbEncodedCert, DWORD cbEncodedCert )
  597. {
  598. PCCERT_CONTEXT pCert = CertCreateCertificateContext ( X509_ASN_ENCODING,
  599. pbEncodedCert,
  600. cbEncodedCert );
  601. if ( pCert )
  602. {
  603. RegEntry reCONF(CONFERENCING_KEY, HKEY_CURRENT_USER);
  604. //
  605. // Set the new value
  606. //
  607. reCONF.SetValue ( REGVAL_CERT_ID,
  608. pCert->pCertInfo->SerialNumber.pbData,
  609. pCert->pCertInfo->SerialNumber.cbData );
  610. CertFreeCertificateContext(pCert);
  611. return TRUE;
  612. }
  613. return FALSE;
  614. }
  615. BOOL SetT120ActiveCert ( BOOL fSelfIssued,
  616. PBYTE pbEncodedCert, DWORD cbEncodedCert )
  617. {
  618. BOOL bRet = FALSE;
  619. DWORD dwResult = -1;
  620. if ( !g_pNmSysInfo )
  621. {
  622. ERROR_OUT(("SetT120ActiveCert: g_pNmSysInfo NULL"));
  623. return FALSE;
  624. }
  625. //
  626. // Clear old cert out of transport
  627. //
  628. g_pNmSysInfo->ProcessSecurityData(
  629. TPRTCTRL_SETX509CREDENTIALS,
  630. 0, 0,
  631. &dwResult);
  632. if (!g_pNmSysInfo)
  633. return FALSE;
  634. if ( g_pCertContext )
  635. {
  636. CertFreeCertificateContext ( g_pCertContext );
  637. g_pCertContext = NULL;
  638. }
  639. if ( g_hCertStore )
  640. {
  641. if ( !CertCloseStore ( g_hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ))
  642. {
  643. WARNING_OUT(("SetT120ActiveCert: closing store failed"));
  644. }
  645. g_hCertStore = NULL;
  646. }
  647. if ( fSelfIssued )
  648. {
  649. g_hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,
  650. X509_ASN_ENCODING,
  651. 0,
  652. CERT_SYSTEM_STORE_CURRENT_USER,
  653. WSZNMSTORE );
  654. if ( g_hCertStore )
  655. {
  656. //
  657. // We only expect one cert in here, get it
  658. //
  659. g_pCertContext = CertFindCertificateInStore(
  660. g_hCertStore,
  661. X509_ASN_ENCODING,
  662. 0,
  663. CERT_FIND_ANY,
  664. NULL,
  665. NULL);
  666. if ( g_pCertContext )
  667. {
  668. dwResult = -1;
  669. g_pNmSysInfo->ProcessSecurityData(
  670. TPRTCTRL_SETX509CREDENTIALS,
  671. (DWORD_PTR)g_pCertContext, 0,
  672. &dwResult);
  673. bRet = ( dwResult == 0 ); // BUGBUG TPRTSEC_NOERROR
  674. }
  675. else
  676. {
  677. WARNING_OUT(("SetT120ActiveCert: no cert in %s?", SZNMSTORE));
  678. }
  679. }
  680. else
  681. {
  682. WARNING_OUT(("SetT120ActiveCert: error opening %s store %x",
  683. SZNMSTORE, GetLastError()));
  684. }
  685. }
  686. else // !fSelfIssued
  687. {
  688. PCCERT_CONTEXT pCert = NULL;
  689. PCCERT_CONTEXT pCertMatch = CertCreateCertificateContext (
  690. X509_ASN_ENCODING,
  691. pbEncodedCert,
  692. cbEncodedCert );
  693. if ( pCertMatch )
  694. {
  695. //
  696. // Open the user's store
  697. //
  698. if ( g_hCertStore = CertOpenSystemStore(0, "MY"))
  699. {
  700. while ( pCert = CertEnumCertificatesInStore(
  701. g_hCertStore, (PCERT_CONTEXT)pCert ))
  702. {
  703. //
  704. // Is this the same cert?
  705. //
  706. if ( ( pCert->pCertInfo->SerialNumber.cbData ==
  707. pCertMatch->pCertInfo->SerialNumber.cbData ) &&
  708. (!memcmp(pCert->pCertInfo->SerialNumber.pbData,
  709. pCertMatch->pCertInfo->SerialNumber.pbData,
  710. pCert->pCertInfo->SerialNumber.cbData)))
  711. {
  712. dwResult = -1;
  713. g_pNmSysInfo->ProcessSecurityData(
  714. TPRTCTRL_SETX509CREDENTIALS,
  715. (DWORD_PTR)pCert, 0, &dwResult);
  716. bRet = ( dwResult == 0 ); // BUGBUG TPRTSEC_NOERROR
  717. break;
  718. }
  719. }
  720. if ( pCert )
  721. {
  722. // Found it.
  723. g_pCertContext = pCert;
  724. }
  725. else
  726. {
  727. WARNING_OUT(("SetT120ActiveCert: matching cert not found"));
  728. }
  729. }
  730. else
  731. {
  732. ERROR_OUT(("SetT120ActiveCert: can't open my store"));
  733. }
  734. CertFreeCertificateContext ( pCertMatch );
  735. }
  736. }
  737. return bRet;
  738. }
  739. static PCCERT_CONTEXT IGetDefaultCert ( BOOL fSystemOnly,
  740. HCERTSTORE * phCertStore )
  741. {
  742. RegEntry reCONF(CONFERENCING_KEY, HKEY_CURRENT_USER);
  743. HCERTSTORE hStore = NULL;
  744. PCCERT_CONTEXT pCertContext = NULL;
  745. BOOL fNmDefaultCert = TRUE;
  746. LPBYTE pCertID;
  747. if ( fSystemOnly )
  748. fNmDefaultCert = FALSE;
  749. else
  750. fNmDefaultCert = !reCONF.GetNumber(REGVAL_SECURITY_AUTHENTICATION,
  751. DEFAULT_SECURITY_AUTHENTICATION);
  752. hStore = CertOpenSystemStore(0, fNmDefaultCert ?
  753. SZNMSTORE : "MY");
  754. if ( NULL != hStore )
  755. {
  756. PCCERT_CONTEXT pCert = NULL;
  757. DWORD cbCertID;
  758. if (!fNmDefaultCert && ( cbCertID = reCONF.GetBinary (
  759. REGVAL_CERT_ID, (void**)&pCertID )))
  760. {
  761. while ( pCert = CertEnumCertificatesInStore(
  762. hStore, (PCERT_CONTEXT)pCert ))
  763. {
  764. if ( cbCertID == pCert->pCertInfo->SerialNumber.cbData &&
  765. !memcmp(pCertID, pCert->pCertInfo->SerialNumber.pbData,
  766. pCert->pCertInfo->SerialNumber.cbData))
  767. {
  768. // pCert must now be freed via CertFreeCertificateContext
  769. pCertContext = pCert;
  770. break;
  771. }
  772. }
  773. }
  774. if ( NULL == pCertContext )
  775. {
  776. // Delete the (stale) reg entry... the cert might have
  777. // been deleted by other UI.
  778. if ( !fNmDefaultCert )
  779. reCONF.DeleteValue( REGVAL_CERT_ID );
  780. // Find any old client certificate - if fNmDefaultCert this will be
  781. // the only one in the store.
  782. pCertContext = CertFindCertificateInStore(hStore,
  783. X509_ASN_ENCODING,
  784. 0,
  785. CERT_FIND_ANY,
  786. NULL,
  787. NULL);
  788. }
  789. }
  790. else
  791. {
  792. WARNING_OUT(("User store %s not opened!", fNmDefaultCert ? SZNMSTORE : "MY"));
  793. *phCertStore = NULL;
  794. }
  795. // Caller to free cert context
  796. *phCertStore = hStore;
  797. return pCertContext;
  798. }
  799. BOOL GetDefaultSystemCert ( PBYTE * ppEncodedCert, DWORD * pcbEncodedCert )
  800. {
  801. HCERTSTORE hStore;
  802. PCCERT_CONTEXT pCertContext = IGetDefaultCert(TRUE, &hStore);
  803. BOOL bRet = FALSE;
  804. if ( pCertContext )
  805. {
  806. DWORD cb;
  807. PBYTE pb;
  808. if ( pb = (PBYTE)CoTaskMemAlloc ( pCertContext->cbCertEncoded ))
  809. {
  810. memcpy ( pb, pCertContext->pbCertEncoded,
  811. pCertContext->cbCertEncoded );
  812. *ppEncodedCert = pb;
  813. *pcbEncodedCert = pCertContext->cbCertEncoded;
  814. bRet = TRUE;
  815. }
  816. CertFreeCertificateContext(pCertContext);
  817. }
  818. if ( hStore )
  819. {
  820. if ( !CertCloseStore ( hStore, CERT_CLOSE_STORE_CHECK_FLAG ))
  821. {
  822. WARNING_OUT(("GetDefaultSystemCert: error closing store"));
  823. }
  824. }
  825. return bRet;;
  826. }
  827. BOOL InitT120SecurityFromRegistry(VOID)
  828. {
  829. BOOL bRet = FALSE;
  830. if ( !g_pNmSysInfo )
  831. {
  832. ERROR_OUT(("InitT120SecurityFromRegistry: g_pNmSysInfo NULL"));
  833. return FALSE;
  834. }
  835. //
  836. // Expect this to be called only once on startup
  837. //
  838. ASSERT( NULL == g_pCertContext );
  839. ASSERT( NULL == g_hCertStore );
  840. g_pCertContext = IGetDefaultCert(FALSE, &g_hCertStore);
  841. if ( NULL == g_pCertContext )
  842. {
  843. WARNING_OUT(("No user certificate found!"));
  844. // BUGBUG
  845. // This means the transport will not be ready for secure
  846. // calls... we return false but what does the caller do?
  847. //
  848. }
  849. else
  850. {
  851. DWORD dwResult = -1;
  852. g_pNmSysInfo->ProcessSecurityData(TPRTCTRL_SETX509CREDENTIALS,
  853. (DWORD_PTR)g_pCertContext, 0, &dwResult);
  854. if ( !dwResult )
  855. bRet = TRUE;
  856. else
  857. {
  858. ERROR_OUT(("InitT120SecurityFromRegistry: picked up bad cert"));
  859. }
  860. }
  861. return bRet;
  862. }
  863. HRESULT SetCertFromCertInfo ( PCERT_INFO pCertInfo )
  864. {
  865. HRESULT hRet = S_FALSE;
  866. ASSERT( pCertInfo );
  867. if (!g_pNmSysInfo)
  868. return hRet;
  869. //
  870. // Clear old cert out of transport
  871. //
  872. DWORD dwResult = -1;
  873. g_pNmSysInfo->ProcessSecurityData(
  874. TPRTCTRL_SETX509CREDENTIALS,
  875. 0, 0,
  876. &dwResult);
  877. if ( g_pCertContext )
  878. {
  879. CertFreeCertificateContext ( g_pCertContext );
  880. g_pCertContext = NULL;
  881. }
  882. if ( g_hCertStore )
  883. {
  884. if ( !CertCloseStore ( g_hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ))
  885. {
  886. WARNING_OUT(("SetCertFromCertInfo: closing store failed"));
  887. }
  888. g_hCertStore = NULL;
  889. }
  890. if ( g_hCertStore = CertOpenSystemStore(0, "MY"))
  891. {
  892. //
  893. // Fix up relative pointers inside pCertInfo: Note that only
  894. // the pointers relevant to CertGetSubjectCertificateFromStore
  895. // are fixed up.
  896. //
  897. pCertInfo->SerialNumber.pbData += (DWORD_PTR)pCertInfo;
  898. pCertInfo->Issuer.pbData += (DWORD_PTR)pCertInfo;
  899. PCCERT_CONTEXT pCert = CertGetSubjectCertificateFromStore(
  900. g_hCertStore, X509_ASN_ENCODING, pCertInfo );
  901. if ( pCert )
  902. {
  903. g_pNmSysInfo->ProcessSecurityData(
  904. TPRTCTRL_SETX509CREDENTIALS,
  905. (DWORD_PTR)pCert, 0, &dwResult);
  906. if ( 0 == dwResult ) // TPRTSEC_NO_ERROR
  907. {
  908. hRet = S_OK;
  909. g_pCertContext = pCert;
  910. }
  911. }
  912. else
  913. {
  914. WARNING_OUT(("SetCertFromCertInfo: matching cert not found"));
  915. }
  916. }
  917. else
  918. {
  919. ERROR_OUT(("SetCertFromCertInfo: can't open my store"));
  920. }
  921. return hRet;
  922. }