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.

2083 lines
55 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. schnlui.cxx
  5. Abstract:
  6. Contains immplimentation of generic Windows Dialog
  7. Manipulation Code. This code supports SCHANNEL
  8. (Secure Channel SSL/PCT) specific UI for Certifcates.
  9. Contents:
  10. CertPickDialogProc
  11. Author:
  12. Arthur L Bierer (arthurbi) 27-Jun-1996
  13. Revision History:
  14. 27-Jun-1996 arthurbi
  15. Created
  16. --*/
  17. #include <wininetp.h>
  18. #include <ntsecapi.h>
  19. #include "resource.h"
  20. #include "ierrui.hxx"
  21. #include "inethelp.h"
  22. #include <softpub.h>
  23. #include <htmlhelp.h>
  24. #define USE_NT5_CRYPTOUI
  25. #ifdef USE_NT5_CRYPTOUI
  26. #include <cryptui.h>
  27. HINSTANCE g_hCryptoUI = NULL; // handle for cryptui.dll
  28. #endif
  29. //
  30. // private prototypes, and defines.
  31. //
  32. #define TYPICAL_MD5_HASH_SIZE 16
  33. #define NUM_DN_UNITS 6
  34. #define MAX_ITEM_LEN 1000
  35. #define DN_COMMON_NAME 0
  36. #define DN_COUNTRY 1
  37. #define DN_ORG 2
  38. #define DN_ORGUNIT 3
  39. #define DN_LOCALE 4
  40. #define DN_STATE 5
  41. #define MAX_CERT_FIELDS 20
  42. typedef struct _ATTR_MAP
  43. {
  44. DWORD dwAttr;
  45. DWORD dwStringID;
  46. } ATTR_MAP;
  47. // Now for some common attribute maps
  48. ATTR_MAP ProtocolAttrMap[] =
  49. {
  50. {SP_PROT_SSL2_CLIENT, IDS_PROTOCOL_SSL2},
  51. {SP_PROT_SSL3_CLIENT, IDS_PROTOCOL_SSL3},
  52. {SP_PROT_PCT1_CLIENT, IDS_PROTOCOL_PCT1},
  53. {SP_PROT_TLS1_CLIENT, IDS_PROTOCOL_TLS1}
  54. };
  55. ATTR_MAP AlgAttrMap[] =
  56. {
  57. {CALG_MD2, IDS_ALG_MD2},
  58. {CALG_MD4, IDS_ALG_MD4},
  59. {CALG_MD5, IDS_ALG_MD5},
  60. {CALG_SHA, IDS_ALG_SHA},
  61. {CALG_SHA1, IDS_ALG_SHA},
  62. {CALG_MAC, IDS_ALG_MAC},
  63. {CALG_HMAC, IDS_ALG_HMAC},
  64. {CALG_RSA_SIGN, IDS_ALG_RSA_SIGN},
  65. {CALG_DSS_SIGN, IDS_ALG_DSS_SIGN},
  66. {CALG_RSA_KEYX, IDS_ALG_RSA_KEYX},
  67. {CALG_DES, IDS_ALG_DES},
  68. {CALG_3DES_112, IDS_ALG_3DES_112},
  69. {CALG_3DES, IDS_ALG_3DES},
  70. {CALG_RC2, IDS_ALG_RC2},
  71. {CALG_RC4, IDS_ALG_RC4},
  72. {CALG_RC5, IDS_ALG_RC5},
  73. {CALG_SEAL, IDS_ALG_SEAL},
  74. {CALG_DH_SF, IDS_ALG_DH_SF},
  75. {CALG_DH_EPHEM, IDS_ALG_DH_EPHEM},
  76. {CALG_KEA_KEYX, IDS_ALG_KEA_KEYX},
  77. {CALG_SKIPJACK, IDS_ALG_SKIPJACK},
  78. {CALG_TEK, IDS_ALG_TEK}
  79. };
  80. typedef struct {
  81. LPWSTR lpszListBoxText;
  82. LPWSTR lpszEditBoxText;
  83. DWORD dwSpcCtlId; // special id for item to be placed in ctl.
  84. } ShowCertMapping;
  85. #define szHelpFile "iexplore.hlp"
  86. //
  87. // private function declariations
  88. //
  89. PRIVATE
  90. BOOL
  91. PlaceCertContextsInListBox(
  92. IN HWND hWndListBox,
  93. IN HWND hWndViewCertButton,
  94. IN HWND hWndExportButton,
  95. IN CERT_CONTEXT_ARRAY* pCertContexts
  96. );
  97. PRIVATE
  98. BOOL
  99. PlaceCertificateDataIntoListBox(
  100. IN HWND hWndDlg,
  101. IN HWND hWndListBox,
  102. IN ShowCertMapping *pMapCertFields
  103. );
  104. PRIVATE
  105. DWORD
  106. OnSelectionOfACertField(
  107. IN HWND hWndListBox,
  108. IN HWND hWndEditBox,
  109. IN ShowCertMapping *pMapCertFields
  110. );
  111. PRIVATE
  112. BOOL
  113. CALLBACK
  114. ViewCertDlgProc(
  115. HWND hwnd,
  116. UINT msg,
  117. WPARAM wparam,
  118. LPARAM lparam
  119. );
  120. LPWSTR GetCertStatus(LPINTERNET_SECURITY_INFO pciCert);
  121. //
  122. // public functions
  123. //
  124. #ifdef USE_NT5_CRYPTOUI
  125. //+-------------------------------------------------------------------------
  126. // Returns TRUE if cryptui.dll was found
  127. //--------------------------------------------------------------------------
  128. BOOL UseCryptoUI()
  129. {
  130. static long fTriedOnce = FALSE;
  131. // Only try to load the dll once
  132. if (!fTriedOnce)
  133. {
  134. //
  135. // Note: if this gets called by multiple threads the worst that will
  136. // happen is that load library will be called twice. Apparently,
  137. // there is is no danger of the global getting mangled because
  138. // writes are atomic.
  139. //
  140. g_hCryptoUI = LoadLibrary("cryptui.dll");
  141. fTriedOnce = TRUE;
  142. }
  143. return (g_hCryptoUI != NULL);
  144. }
  145. //+-------------------------------------------------------------------------
  146. // Delay load version of the function in cryptui.dll
  147. //--------------------------------------------------------------------------
  148. BOOL _CryptUIDlgViewCertificate(
  149. IN PCCRYPTUI_VIEWCERTIFICATE_STRUCT pCertViewInfo,
  150. OUT BOOL *pfPropertiesChanged // OPTIONAL
  151. )
  152. {
  153. // Caller must call UseCryptoUI() first to load the dll!
  154. INET_ASSERT(g_hCryptoUI);
  155. typedef BOOL (CALLBACK* CRYPTUIDLGVIEWCERTIFICATE)(PCCRYPTUI_VIEWCERTIFICATE_STRUCT, BOOL*);
  156. static CRYPTUIDLGVIEWCERTIFICATE fnCryptUIDlgViewCertificate = NULL;
  157. if (fnCryptUIDlgViewCertificate == NULL)
  158. {
  159. //
  160. // Note: if this gets called by multiple threads the worst that will
  161. // happen is that GetProcAddress will be called twice. Apparently,
  162. // there is is no danger of the global getting mangled because
  163. // writes are atomic.
  164. //
  165. fnCryptUIDlgViewCertificate = (CRYPTUIDLGVIEWCERTIFICATE)GetProcAddress(g_hCryptoUI, "CryptUIDlgViewCertificateA");
  166. if (fnCryptUIDlgViewCertificate == NULL)
  167. {
  168. return FALSE;
  169. }
  170. }
  171. // Call the real function
  172. return fnCryptUIDlgViewCertificate(pCertViewInfo, pfPropertiesChanged);
  173. }
  174. #endif USE_NT5_CRYPTOUI
  175. INTERNETAPI_(BOOL) InternetAlgIdToStringA(
  176. IN ALG_ID ai,
  177. IN LPSTR lpstr,
  178. IN OUT LPDWORD lpdwstrLength,
  179. IN DWORD dwReserved /* Must be 0 */
  180. )
  181. /*++
  182. Routine Description:
  183. Converts a algid to a user-displayable string.
  184. Arguments:
  185. ai - Algorithm identifiers ( defined in wincrypt.h)
  186. lpstr - Buffer to copy string into.
  187. lpdwstrLength - pass in num of characters, return no of characters copied if successful,
  188. else no of chars required (including null terminator)
  189. dwReserved = Must be 0
  190. Return Value:
  191. DWORD
  192. Win32 or WININET error code.
  193. --*/
  194. {
  195. DEBUG_ENTER_API((DBG_API,
  196. Bool,
  197. "InternetAlgIdToStringA",
  198. "%#x, %q, %#x, %#x",
  199. ai,
  200. lpstr,
  201. lpdwstrLength,
  202. dwReserved
  203. ));
  204. DWORD error = ERROR_SUCCESS;
  205. if ((dwReserved!=0) || (lpdwstrLength == NULL))
  206. {
  207. error = ERROR_INVALID_PARAMETER;
  208. goto quit;
  209. }
  210. if (lpstr == NULL)
  211. *lpdwstrLength = 0;
  212. int i;
  213. for (i=0; i < ARRAY_ELEMENTS(AlgAttrMap) ; i++ )
  214. {
  215. if (ai == AlgAttrMap[i].dwAttr)
  216. break;
  217. }
  218. if ( i == ARRAY_ELEMENTS(AlgAttrMap) )
  219. {
  220. INET_ASSERT(FALSE); // Could be because our table is not up to date.
  221. error = ERROR_INVALID_PARAMETER;
  222. goto quit;
  223. }
  224. CHAR szTempBuffer[100];
  225. int nRet;
  226. nRet = LoadStringA(GlobalDllHandle,
  227. AlgAttrMap[i].dwStringID,
  228. szTempBuffer,
  229. ARRAY_ELEMENTS(szTempBuffer)
  230. );
  231. // If the return value is within one less than the arraysize, it implies the
  232. // string could have been terminated by LoadString. This should not happen
  233. // since we have allocated a large enough buffer. If it does we need to bump the
  234. // size of the temporary array above.
  235. INET_ASSERT(nRet < ARRAY_ELEMENTS(szTempBuffer) - 1);
  236. if (*lpdwstrLength > (DWORD)nRet)
  237. {
  238. memcpy(lpstr, szTempBuffer, (nRet + 1));
  239. *lpdwstrLength = nRet;
  240. error = ERROR_SUCCESS;
  241. }
  242. else
  243. {
  244. *lpdwstrLength = nRet + 1;
  245. error = ERROR_INSUFFICIENT_BUFFER;
  246. }
  247. quit:
  248. if (ERROR_SUCCESS != error)
  249. {
  250. SetLastError(error);
  251. DEBUG_ERROR(API, error);
  252. }
  253. DEBUG_LEAVE_API(error==ERROR_SUCCESS);
  254. return (error == ERROR_SUCCESS);
  255. }
  256. INTERNETAPI_(BOOL) InternetSecurityProtocolToStringA(
  257. IN DWORD dwProtocol,
  258. IN LPSTR lpstr,
  259. IN OUT LPDWORD lpdwstrLength,
  260. IN DWORD dwReserved /* Must be 0 */
  261. )
  262. /*++
  263. Routine Description:
  264. Converts a security protocol to a user-displayable string.
  265. Arguments:
  266. dwProtocol - Security protocol identifier ( defined in wincrypt.h)
  267. lpstr - Buffer to copy string into.
  268. lpdwstrLength - pass in num of characters, return no of characters copied if successful,
  269. else no of chars required (including null terminator)
  270. dwReserved = Must be 0
  271. Return Value:
  272. DWORD
  273. Win32 or WININET error code.
  274. --*/
  275. {
  276. DEBUG_ENTER_API((DBG_API,
  277. Bool,
  278. "InternetSecurityProtocolToStringA",
  279. "%d, %q, %#x, %#x",
  280. dwProtocol,
  281. lpstr,
  282. lpdwstrLength,
  283. dwReserved
  284. ));
  285. DWORD error = ERROR_SUCCESS;
  286. if ((dwReserved!=0) || (lpdwstrLength == NULL))
  287. {
  288. error = ERROR_INVALID_PARAMETER;
  289. goto quit;
  290. }
  291. if (lpstr == NULL)
  292. *lpdwstrLength = 0;
  293. int i;
  294. for (i=0; i < ARRAY_ELEMENTS(ProtocolAttrMap) ; i++ )
  295. {
  296. if (dwProtocol == ProtocolAttrMap[i].dwAttr)
  297. break;
  298. }
  299. if ( i == ARRAY_ELEMENTS(ProtocolAttrMap) )
  300. {
  301. INET_ASSERT(FALSE); // Could be because our table is not up to date.
  302. error = ERROR_INVALID_PARAMETER;
  303. goto quit;
  304. }
  305. CHAR szTempBuffer[100];
  306. int nRet;
  307. nRet = LoadStringA(GlobalDllHandle,
  308. ProtocolAttrMap[i].dwStringID,
  309. szTempBuffer,
  310. ARRAY_ELEMENTS(szTempBuffer)
  311. );
  312. // If the return value is within one less than the arraysize, it implies the
  313. // string could have been terminated by LoadString. This should not happen
  314. // since we have allocated a large enough buffer. If it does we need to bump the
  315. // size of the temporary array above.
  316. INET_ASSERT(nRet < ARRAY_ELEMENTS(szTempBuffer) - 1);
  317. if (*lpdwstrLength > (DWORD)nRet)
  318. {
  319. memcpy(lpstr, szTempBuffer, (nRet + 1));
  320. *lpdwstrLength = nRet;
  321. error = ERROR_SUCCESS;
  322. }
  323. else
  324. {
  325. *lpdwstrLength = nRet + 1;
  326. error = ERROR_INSUFFICIENT_BUFFER;
  327. }
  328. quit:
  329. if (ERROR_SUCCESS != error)
  330. {
  331. SetLastError(error);
  332. DEBUG_ERROR(API, error);
  333. }
  334. DEBUG_LEAVE_API(error==ERROR_SUCCESS);
  335. return (error == ERROR_SUCCESS);
  336. }
  337. LPWSTR DupAnsiToUnicode(
  338. char *lpszAnsi,
  339. INT iLen
  340. )
  341. {
  342. DWORD cbSize = (iLen > 0 ) ? iLen : (lstrlen(lpszAnsi) + 1);
  343. WCHAR *pwszUnicode = NULL;
  344. pwszUnicode = new WCHAR[cbSize];
  345. if(pwszUnicode)
  346. {
  347. SHAnsiToUnicode(lpszAnsi, pwszUnicode, cbSize);
  348. }
  349. return pwszUnicode;
  350. }
  351. DWORD
  352. ShowSecurityInfo(
  353. IN HWND hWndParent,
  354. IN LPINTERNET_SECURITY_INFO pSecurityInfo
  355. )
  356. /*++
  357. Routine Description:
  358. Displays a dialog box that shows the information found
  359. inside of a certificate.
  360. Arguments:
  361. hWndParent - Parent Window Handle
  362. pCertInfoEx - Certificate Information structure, containing the
  363. fields of info to show.
  364. Return Value:
  365. DWORD
  366. Win32 or WININET error code.
  367. --*/
  368. {
  369. #ifdef USE_NT5_CRYPTOUI
  370. //
  371. // For now, we use the new UI only if we can load the DLL. Otherwise we
  372. // resort to the old UI. Eventually, we may nuke the old UI.
  373. //
  374. if (UseCryptoUI())
  375. {
  376. CRYPTUI_VIEWCERTIFICATE_STRUCT cert;
  377. if(pWTHelperProvDataFromStateData && g_fDoSpecialMagicForSGCCerts)
  378. {
  379. WINTRUST_DATA sWTD;
  380. WINTRUST_CERT_INFO sWTCI;
  381. HTTPSPolicyCallbackData polHttps;
  382. LPCSTR pszPurpose = szOID_PKIX_KP_SERVER_AUTH;
  383. DWORD status;
  384. memset(&sWTD, 0x00, sizeof(WINTRUST_DATA));
  385. sWTD.cbStruct = sizeof(WINTRUST_DATA);
  386. sWTD.dwUIChoice = WTD_UI_NONE;
  387. sWTD.pPolicyCallbackData = (LPVOID)&polHttps;
  388. sWTD.dwUnionChoice = WTD_CHOICE_CERT;
  389. sWTD.pCert = &sWTCI;
  390. sWTD.pwszURLReference = NULL;
  391. sWTD.dwStateAction = WTD_STATEACTION_VERIFY;
  392. memset(&sWTCI, 0x00, sizeof(WINTRUST_CERT_INFO));
  393. sWTCI.cbStruct = sizeof(WINTRUST_CERT_INFO);
  394. sWTCI.psCertContext = (CERT_CONTEXT *)pSecurityInfo->pCertificate;
  395. sWTCI.chStores = 1;
  396. sWTCI.pahStores = (HCERTSTORE *)&pSecurityInfo->pCertificate->hCertStore;
  397. memset(&polHttps, 0x00, sizeof(HTTPSPolicyCallbackData));
  398. polHttps.cbStruct = sizeof(HTTPSPolicyCallbackData);
  399. polHttps.dwAuthType = AUTHTYPE_SERVER;
  400. polHttps.fdwChecks = INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
  401. SECURITY_FLAG_IGNORE_WRONG_USAGE;
  402. polHttps.pwszServerName = NULL;
  403. status = WinVerifySecureChannel(NULL, &sWTD);
  404. ZeroMemory(&cert, sizeof(cert));
  405. cert.dwSize = sizeof(cert);
  406. cert.hwndParent = hWndParent;
  407. cert.pCertContext = pSecurityInfo->pCertificate;
  408. cert.hWVTStateData = pWTHelperProvDataFromStateData(sWTD.hWVTStateData);
  409. cert.fpCryptProviderDataTrustedUsage = (status == ERROR_SUCCESS) ? TRUE : FALSE;
  410. cert.rgszPurposes = &pszPurpose;
  411. cert.cPurposes = 1;
  412. status = _CryptUIDlgViewCertificate(&cert, NULL);
  413. sWTD.dwStateAction = WTD_STATEACTION_CLOSE;
  414. WinVerifySecureChannel(NULL, &sWTD);
  415. return status;
  416. }
  417. else
  418. {
  419. ZeroMemory(&cert, sizeof(cert));
  420. cert.dwSize = sizeof(cert);
  421. cert.hwndParent = hWndParent;
  422. cert.pCertContext = pSecurityInfo->pCertificate;
  423. cert.cStores = 1;
  424. cert.rghStores = (HCERTSTORE *) & (cert.pCertContext->hCertStore);
  425. return _CryptUIDlgViewCertificate(&cert, NULL);
  426. }
  427. }
  428. #endif
  429. #ifdef _WIN64
  430. return ERROR_INTERNET_INTERNAL_ERROR;
  431. #else
  432. LPTSTR szResult = NULL;
  433. PLOCAL_STRINGS plszStrings;
  434. ShowCertMapping MapCertFields[MAX_CERT_FIELDS];
  435. WCHAR szTempBuffer[100];
  436. INT i = 0, j=0;
  437. DWORD error;
  438. LPTSTR lpszSubject = NULL;
  439. LPWSTR lpwszTempSubject = NULL;
  440. LPTSTR lpszIssuer = NULL;
  441. LPWSTR lpwszTempIssuer = NULL;
  442. WCHAR lpszProtocol[100];
  443. LPWSTR lpwszCipher = NULL;
  444. LPWSTR lpwszHash = NULL;
  445. LPWSTR lpwszExch = NULL;
  446. LPTSTR szFrom = NULL;
  447. LPWSTR pwszTempFrom = NULL;
  448. LPTSTR szUntil = NULL;
  449. LPWSTR pwszTempUntil = NULL;
  450. LPWSTR pwszStatus = NULL;
  451. LPSTR lpszHashStr = NULL;
  452. LPWSTR pwszTempHashStr = NULL;
  453. DWORD adwFormatParams[3];
  454. PCERT_INFO pCertInfo = NULL;
  455. DWORD dwProtocolID = IDS_PROTOCOL_UNKNOWN;
  456. DWORD dwHashID = IDS_HASH_UNKNOWN;
  457. DWORD dwCipherID = IDS_CIPHER_UNKNOWN;
  458. DWORD dwExchID = IDS_EXCH_UNKNOWN;
  459. DWORD cbSize;
  460. error = ERROR_SUCCESS;
  461. if((pSecurityInfo == NULL) || (pSecurityInfo->pCertificate == NULL))
  462. {
  463. return ERROR_INTERNET_INTERNAL_ERROR;
  464. }
  465. pCertInfo = pSecurityInfo->pCertificate->pCertInfo;
  466. if(pCertInfo == NULL)
  467. {
  468. return ERROR_INTERNET_INTERNAL_ERROR;
  469. }
  470. //
  471. // Get the Certificate Information.
  472. //
  473. plszStrings = FetchLocalStrings();
  474. if ( plszStrings == NULL )
  475. {
  476. error = ERROR_NOT_ENOUGH_MEMORY;
  477. goto quit;
  478. }
  479. szFrom = FTtoString(&pCertInfo->NotBefore);
  480. szUntil = FTtoString(&pCertInfo->NotAfter);
  481. //
  482. // Put a comment string about the certificate if there is one availble.
  483. //
  484. //
  485. // BUGBUG [arthurbi] This is broken. We never determnine the host name,
  486. // so therefore we never show a Comment for bad CA certificates.
  487. //
  488. pwszStatus = GetCertStatus(pSecurityInfo);
  489. if(pwszStatus)
  490. {
  491. MapCertFields[i].lpszListBoxText = plszStrings->szCertComment;
  492. MapCertFields[i].lpszEditBoxText = pwszStatus;
  493. MapCertFields[i].dwSpcCtlId = 0;//IDC_CERT_COMMENT;
  494. i++;
  495. }
  496. if ( pCertInfo->Subject.cbData )
  497. {
  498. cbSize = CertNameToStr(pSecurityInfo->pCertificate->dwCertEncodingType,
  499. &pCertInfo->Subject,
  500. CERT_SIMPLE_NAME_STR |
  501. CERT_NAME_STR_CRLF_FLAG |
  502. CERT_NAME_STR_NO_PLUS_FLAG,
  503. NULL,
  504. 0);
  505. lpszSubject = new TCHAR[cbSize];
  506. if ( lpszSubject )
  507. {
  508. CertNameToStr(pSecurityInfo->pCertificate->dwCertEncodingType,
  509. &pCertInfo->Subject,
  510. CERT_SIMPLE_NAME_STR |
  511. CERT_NAME_STR_CRLF_FLAG |
  512. CERT_NAME_STR_NO_PLUS_FLAG ,
  513. lpszSubject,
  514. cbSize);
  515. MapCertFields[i].lpszListBoxText = plszStrings->szCertSubject;
  516. lpwszTempSubject = DupAnsiToUnicode(lpszSubject, cbSize);
  517. MapCertFields[i].lpszEditBoxText = lpwszTempSubject;
  518. MapCertFields[i].dwSpcCtlId = 0;//IDC_CERT_SUBJECT;
  519. i++;
  520. }
  521. }
  522. if ( pCertInfo->Issuer.cbData )
  523. {
  524. cbSize = CertNameToStr(pSecurityInfo->pCertificate->dwCertEncodingType,
  525. &pCertInfo->Issuer,
  526. CERT_SIMPLE_NAME_STR |
  527. CERT_NAME_STR_CRLF_FLAG |
  528. CERT_NAME_STR_NO_PLUS_FLAG,
  529. NULL,
  530. 0);
  531. lpszIssuer = new TCHAR[cbSize];
  532. if ( lpszIssuer )
  533. {
  534. CertNameToStr(pSecurityInfo->pCertificate->dwCertEncodingType,
  535. &pCertInfo->Issuer,
  536. CERT_SIMPLE_NAME_STR |
  537. CERT_NAME_STR_CRLF_FLAG |
  538. CERT_NAME_STR_NO_PLUS_FLAG ,
  539. lpszIssuer,
  540. cbSize);
  541. MapCertFields[i].lpszListBoxText = plszStrings->szCertIssuer;
  542. lpwszTempIssuer = DupAnsiToUnicode(lpszIssuer, cbSize);
  543. MapCertFields[i].lpszEditBoxText = lpwszTempIssuer;
  544. MapCertFields[i].dwSpcCtlId = 0;//IDC_CERT_ISSUER;
  545. i++;
  546. }
  547. }
  548. if ( szFrom )
  549. {
  550. MapCertFields[i].lpszListBoxText = plszStrings->szCertEffectiveDate;
  551. pwszTempFrom = DupAnsiToUnicode(szFrom, 0);
  552. MapCertFields[i].lpszEditBoxText = pwszTempFrom;
  553. MapCertFields[i].dwSpcCtlId = 0;
  554. i++;
  555. }
  556. if ( szUntil )
  557. {
  558. MapCertFields[i].lpszListBoxText = plszStrings->szCertExpirationDate;
  559. pwszTempUntil = DupAnsiToUnicode(szUntil, 0);
  560. MapCertFields[i].lpszEditBoxText = pwszTempUntil;
  561. MapCertFields[i].dwSpcCtlId = 0;//IDC_CERT_EXPIRES;
  562. i++;
  563. }
  564. //
  565. // Get the fingerprint... aka MD5 Hash
  566. //
  567. {
  568. CHAR lpMD5Hash[TYPICAL_MD5_HASH_SIZE];
  569. DWORD dwMD5HashSize = TYPICAL_MD5_HASH_SIZE;
  570. BOOL fSuccess;
  571. fSuccess = CertGetCertificateContextProperty(
  572. pSecurityInfo->pCertificate,
  573. CERT_MD5_HASH_PROP_ID,
  574. (LPVOID) lpMD5Hash,
  575. &dwMD5HashSize
  576. );
  577. if ( fSuccess )
  578. {
  579. CertHashToStr( lpMD5Hash,
  580. dwMD5HashSize,
  581. &lpszHashStr
  582. );
  583. if ( lpszHashStr )
  584. {
  585. MapCertFields[i].lpszListBoxText = plszStrings->szFingerprint;
  586. pwszTempHashStr = DupAnsiToUnicode(lpszHashStr, 0);
  587. MapCertFields[i].lpszEditBoxText = pwszTempHashStr;
  588. MapCertFields[i].dwSpcCtlId = 0;
  589. i++;
  590. }
  591. }
  592. }
  593. // Now fill in the connection attributes
  594. if(pSecurityInfo->dwProtocol)
  595. {
  596. for(j=0; j < sizeof(ProtocolAttrMap)/sizeof(ProtocolAttrMap[0]); j++)
  597. {
  598. if(ProtocolAttrMap[j].dwAttr == pSecurityInfo->dwProtocol)
  599. {
  600. dwProtocolID = ProtocolAttrMap[j].dwStringID;
  601. break;
  602. }
  603. }
  604. if(LoadStringWrapW(GlobalDllHandle,
  605. dwProtocolID,
  606. lpszProtocol,
  607. sizeof(lpszProtocol)/sizeof(lpszProtocol[0])))
  608. {
  609. MapCertFields[i].lpszEditBoxText = lpszProtocol;
  610. MapCertFields[i].lpszListBoxText = plszStrings->szCertProtocol;
  611. MapCertFields[i].dwSpcCtlId = 0;
  612. i++;
  613. }
  614. }
  615. if(pSecurityInfo->aiCipher)
  616. {
  617. for(j=0; j < sizeof(AlgAttrMap)/sizeof(AlgAttrMap[0]); j++)
  618. {
  619. if(AlgAttrMap[j].dwAttr == pSecurityInfo->aiCipher)
  620. {
  621. dwCipherID = AlgAttrMap[j].dwStringID;
  622. break;
  623. }
  624. }
  625. LoadStringWrapW(GlobalDllHandle,
  626. dwCipherID,
  627. szTempBuffer,
  628. sizeof(szTempBuffer)/sizeof(szTempBuffer[0]));
  629. adwFormatParams[0] = (DWORD)szTempBuffer;
  630. adwFormatParams[1] = (DWORD)pSecurityInfo->dwCipherStrength;
  631. if (96 <= pSecurityInfo->dwCipherStrength) // Recommended Key strength
  632. adwFormatParams[2] = (DWORD)plszStrings->szStrengthHigh;
  633. else if (64 <= pSecurityInfo->dwCipherStrength) // Passable key strength
  634. adwFormatParams[2] = (DWORD)plszStrings->szStrengthMedium;
  635. else // Ick! Low key strength.
  636. adwFormatParams[2] = (DWORD)plszStrings->szStrengthLow;
  637. if(FormatMessageWrapW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  638. FORMAT_MESSAGE_FROM_STRING |
  639. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  640. plszStrings->szCiphMsg,
  641. 0,
  642. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  643. (LPWSTR)&lpwszCipher,
  644. 0,
  645. (va_list *)adwFormatParams))
  646. {
  647. MapCertFields[i].lpszEditBoxText = lpwszCipher;
  648. MapCertFields[i].lpszListBoxText = plszStrings->szHttpsEncryptAlg;
  649. MapCertFields[i].dwSpcCtlId = 0;
  650. i++;
  651. }
  652. }
  653. if(pSecurityInfo->aiHash)
  654. {
  655. for(j=0; j < sizeof(AlgAttrMap)/sizeof(AlgAttrMap[0]); j++)
  656. {
  657. if(AlgAttrMap[j].dwAttr == pSecurityInfo->aiHash)
  658. {
  659. dwHashID = AlgAttrMap[j].dwStringID;
  660. break;
  661. }
  662. }
  663. LoadStringWrapW(GlobalDllHandle,
  664. dwHashID,
  665. szTempBuffer,
  666. sizeof(szTempBuffer)/sizeof(szTempBuffer[0]));
  667. adwFormatParams[0] = (DWORD)szTempBuffer;
  668. adwFormatParams[1] = (DWORD)pSecurityInfo->dwHashStrength;
  669. if (96 <= pSecurityInfo->dwHashStrength) // Recommended Key strength
  670. adwFormatParams[2] = (DWORD)plszStrings->szStrengthHigh;
  671. else if (64 <= pSecurityInfo->dwHashStrength) // Passable key strength
  672. adwFormatParams[2] = (DWORD)plszStrings->szStrengthMedium;
  673. else // Ick! Low key strength.
  674. adwFormatParams[2] = (DWORD)plszStrings->szStrengthLow;
  675. if(FormatMessageWrapW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  676. FORMAT_MESSAGE_FROM_STRING |
  677. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  678. plszStrings->szHashMsg,
  679. 0,
  680. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  681. (LPWSTR)&lpwszHash,
  682. 0,
  683. (va_list *)adwFormatParams))
  684. {
  685. MapCertFields[i].lpszEditBoxText = lpwszHash;
  686. MapCertFields[i].lpszListBoxText = plszStrings->szHttpsHashAlg;
  687. MapCertFields[i].dwSpcCtlId = 0;
  688. i++;
  689. }
  690. }
  691. if(pSecurityInfo->aiExch)
  692. {
  693. for(j=0; j < sizeof(AlgAttrMap)/sizeof(AlgAttrMap[0]); j++)
  694. {
  695. if(AlgAttrMap[j].dwAttr == pSecurityInfo->aiExch)
  696. {
  697. dwExchID = AlgAttrMap[j].dwStringID;
  698. break;
  699. }
  700. }
  701. LoadStringWrapW(GlobalDllHandle,
  702. dwExchID,
  703. szTempBuffer,
  704. sizeof(szTempBuffer)/sizeof(szTempBuffer[0]));
  705. adwFormatParams[0] = (DWORD)szTempBuffer;
  706. adwFormatParams[1] = (DWORD)pSecurityInfo->dwExchStrength;
  707. if (1024 <= pSecurityInfo->dwExchStrength) // Recommended Key strength
  708. adwFormatParams[2] = (DWORD)plszStrings->szStrengthHigh;
  709. else // Ick! Low key strength.
  710. adwFormatParams[2] = (DWORD)plszStrings->szStrengthLow;
  711. if(FormatMessageWrapW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  712. FORMAT_MESSAGE_FROM_STRING |
  713. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  714. plszStrings->szExchMsg,
  715. 0,
  716. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  717. (LPWSTR)&lpwszExch,
  718. 0,
  719. (va_list *)adwFormatParams))
  720. {
  721. MapCertFields[i].lpszEditBoxText = lpwszExch;
  722. MapCertFields[i].lpszListBoxText = plszStrings->szHttpsExchAlg;
  723. MapCertFields[i].dwSpcCtlId = 0;
  724. i++;
  725. }
  726. }
  727. //
  728. // Last Array Item is marked with 2 NULLs
  729. //
  730. MapCertFields[i].lpszListBoxText = NULL;
  731. MapCertFields[i].lpszEditBoxText = NULL;
  732. MapCertFields[i].dwSpcCtlId = 0;
  733. INET_ASSERT(i < MAX_CERT_FIELDS);
  734. //
  735. // Now Launch the Dlg so we can show it.
  736. //
  737. ERRORINFODLGTYPE CertDlgInfo;
  738. CertDlgInfo.dwDlgFlags = DLG_FLAGS_HAS_CERT_INFO;
  739. CertDlgInfo.dwDlgId = IDD_SHOW_CERT;
  740. CertDlgInfo.hInternetMapped = NULL;
  741. CertDlgInfo.lpVoid = (LPVOID) MapCertFields;
  742. LaunchDlg(
  743. hWndParent,
  744. (LPVOID) &CertDlgInfo,
  745. IDD_VIEW_CERT,
  746. ViewCertDlgProc
  747. );
  748. quit:
  749. if(lpszIssuer) {
  750. FREE_MEMORY(lpszIssuer);
  751. }
  752. if(lpwszTempIssuer) {
  753. FREE_MEMORY(lpwszTempIssuer);
  754. }
  755. if(lpszSubject)
  756. {
  757. FREE_MEMORY(lpszSubject);
  758. }
  759. if(lpwszTempSubject) {
  760. FREE_MEMORY(lpwszTempSubject);
  761. }
  762. if (szFrom) {
  763. FREE_MEMORY(szFrom);
  764. }
  765. if(pwszTempFrom) {
  766. FREE_MEMORY(pwszTempFrom);
  767. }
  768. if (szUntil) {
  769. FREE_MEMORY(szUntil);
  770. }
  771. if(pwszTempUntil) {
  772. FREE_MEMORY(pwszTempUntil);
  773. }
  774. if (lpwszCipher) {
  775. FREE_MEMORY(lpwszCipher);
  776. }
  777. if (lpwszHash) {
  778. FREE_MEMORY(lpwszHash);
  779. }
  780. if (lpwszExch) {
  781. FREE_MEMORY(lpwszExch);
  782. }
  783. if (lpszHashStr) {
  784. delete lpszHashStr;
  785. }
  786. if(pwszTempHashStr) {
  787. FREE_MEMORY(pwszTempHashStr);
  788. }
  789. return error;
  790. #endif
  791. }
  792. STDAPI_(DWORD) ShowCertificate(
  793. IN HWND hWndParent,
  794. IN LPVOID pCertInfoEx
  795. )
  796. /*++
  797. Routine Description:
  798. Displays a dialog box that shows the information found
  799. inside of a certificate.
  800. Arguments:
  801. hWndParent - Parent Window Handle
  802. pCertInfoEx - Certificate Information structure, containing the
  803. fields of info to show.
  804. Return Value:
  805. DWORD
  806. Win32 or WININET error code.
  807. --*/
  808. {
  809. //DWORD error = ShowSecurityInfo(
  810. // hWndParent,
  811. // (LPINTERNET_SECURITY_INFO) pCertInfoEx // BAD..
  812. // );
  813. //return error;
  814. return ERROR_INTERNET_INTERNAL_ERROR;
  815. }
  816. BOOL
  817. CALLBACK
  818. ViewCertDlgProc(
  819. HWND hwnd,
  820. UINT msg,
  821. WPARAM wparam,
  822. LPARAM lparam
  823. )
  824. /*++
  825. Routine Description:
  826. Shows a Certificate, and relevent security information to the user.
  827. Arguments:
  828. hwnd - standard dialog params
  829. msg - "
  830. wparam - "
  831. lparam - "
  832. Return Value:
  833. BOOL
  834. TRUE - we handled message
  835. FALSE - Windows should handle message
  836. --*/
  837. {
  838. PERRORINFODLGTYPE pDlgInfo;
  839. const static DWORD mapIDCsToIDHs[] =
  840. {
  841. IDC_CERTPICKLIST ,IDH_LIST_CERT,
  842. ID_SHOW_CERTIFICATE ,IDH_VIEW_CERT,
  843. IDC_DELETE_CERT ,IDH_DEL_CERT,
  844. 0,0
  845. };
  846. switch (msg)
  847. {
  848. case WM_INITDIALOG:
  849. INET_ASSERT(lparam);
  850. pDlgInfo = (PERRORINFODLGTYPE)lparam;
  851. (void)SetWindowLongPtr(hwnd,
  852. DWLP_USER,
  853. lparam);
  854. INET_ASSERT(pDlgInfo->dwDlgFlags & DLG_FLAGS_HAS_CERT_INFO );
  855. INET_ASSERT(pDlgInfo->lpVoid);
  856. PlaceCertificateDataIntoListBox(
  857. hwnd,
  858. GetDlgItem(hwnd,IDC_FIELDLIST),
  859. (ShowCertMapping *) pDlgInfo->lpVoid
  860. );
  861. OnSelectionOfACertField(
  862. GetDlgItem(hwnd,IDC_FIELDLIST),
  863. GetDlgItem(hwnd,IDC_DETAILSLIST),
  864. (ShowCertMapping *) pDlgInfo->lpVoid
  865. );
  866. return TRUE;
  867. case WM_HELP: // F1
  868. WinHelp( (HWND)((LPHELPINFO)lparam)->hItemHandle,
  869. szHelpFile,
  870. HELP_WM_HELP,
  871. (ULONG_PTR)(LPSTR)mapIDCsToIDHs
  872. );
  873. break;
  874. case WM_CONTEXTMENU: // right mouse click
  875. WinHelp( (HWND) wparam,
  876. szHelpFile,
  877. HELP_CONTEXTMENU,
  878. (ULONG_PTR)(LPSTR)mapIDCsToIDHs
  879. );
  880. break;
  881. case WM_COMMAND:
  882. {
  883. WORD wID = LOWORD(wparam);
  884. WORD wNotificationCode = HIWORD(wparam);
  885. HWND hWndCtrl = (HWND) lparam;
  886. pDlgInfo =
  887. (PERRORINFODLGTYPE) GetWindowLongPtr(hwnd,DWLP_USER);
  888. switch (wID)
  889. {
  890. case ID_TELL_ME_ABOUT_SECURITY:
  891. //
  892. // Launches help for this button.
  893. //
  894. WinHelp(
  895. hwnd,
  896. szHelpFile,
  897. HELP_CONTEXT,
  898. (ULONG_PTR)HELP_TOPIC_SECURITY
  899. );
  900. break;
  901. case IDC_FIELDLIST:
  902. //
  903. // If the user changes the selection of the listbox
  904. // move the edit control field data to the correct
  905. // entry.
  906. //
  907. if ( wNotificationCode == LBN_SELCHANGE )
  908. {
  909. OnSelectionOfACertField(
  910. hWndCtrl,
  911. GetDlgItem(hwnd,IDC_DETAILSLIST),
  912. (ShowCertMapping *) pDlgInfo->lpVoid
  913. );
  914. }
  915. break;
  916. case IDOK:
  917. case IDYES:
  918. INET_ASSERT(pDlgInfo);
  919. INET_ASSERT(pDlgInfo->dwDlgId != 0);
  920. EndDialog(hwnd, TRUE);
  921. break;
  922. case IDCANCEL:
  923. case IDNO:
  924. EndDialog(hwnd, FALSE);
  925. break;
  926. }
  927. return TRUE;
  928. }
  929. }
  930. return FALSE;
  931. }
  932. DWORD
  933. ShowClientAuthCerts(
  934. IN HWND hWndParent
  935. )
  936. /*++
  937. Routine Description:
  938. Shows the Client Authentication Certificates found in the system.
  939. Arguments:
  940. hWndParent - Parent Window Handle
  941. Return Value:
  942. DWORD
  943. Win32 or WININET error code.
  944. --*/
  945. {
  946. // With the NT5 crypto UI we don't need to display client-auth certs anymore.
  947. // I left this in code in the source file in case we switch back to the old
  948. // crypto dlls for some reason. Once we decide to move on to the new crypto dlls
  949. // this code can be removed. - sgs
  950. #ifndef USE_NT5_CRYPTOUI
  951. DWORD error;
  952. ERRORINFODLGTYPE ErrorInfoDlgInfo;
  953. ErrorInfoDlgInfo.hInternetMapped = NULL;
  954. ErrorInfoDlgInfo.dwDlgId = IDD_CERTVIEWER;
  955. ErrorInfoDlgInfo.lpVoid = NULL;
  956. ErrorInfoDlgInfo.dwDlgFlags = 0;
  957. CliAuthAquireCertChains(
  958. NULL,
  959. NULL,
  960. (CERT_CHAIN_ARRAY **) &ErrorInfoDlgInfo.lpVoid
  961. );
  962. //
  963. // Don't Care about error code, from function.
  964. //
  965. error = LaunchDlg(
  966. hWndParent,
  967. (LPVOID) &ErrorInfoDlgInfo,
  968. ErrorInfoDlgInfo.dwDlgId,
  969. CertPickDialogProc
  970. );
  971. if ( ErrorInfoDlgInfo.lpVoid )
  972. delete ErrorInfoDlgInfo.lpVoid;
  973. return error;
  974. #else
  975. INET_ASSERT(FALSE);
  976. return ERROR_CALL_NOT_IMPLEMENTED;
  977. #endif
  978. }
  979. DWORD
  980. ParseX509EncodedCertificateForListBoxEntry(
  981. IN LPBYTE lpCert,
  982. IN DWORD cbCert,
  983. OUT LPSTR lpszListBoxEntry,
  984. IN LPDWORD lpdwListBoxEntry
  985. )
  986. /*++
  987. Routine Description:
  988. Parses an X509 certificate, into a single text entry that
  989. can be displayed on a line in a listbox.
  990. Arguments:
  991. lpCert - Certificte bytes to parse
  992. cbCert - Size of certificate to parse
  993. lpszListBoxEntry - Formated text to use in List Box.
  994. lpdwListBoxEntry - IN: size of lpszListBoxEntry, OUT: actual size of string.
  995. Return Value:
  996. DWORD
  997. Win32 or WININET error code.
  998. --*/
  999. {
  1000. BOOL fSuccess;
  1001. DWORD error = ERROR_SUCCESS;
  1002. PCCERT_CONTEXT pCert;
  1003. PCERT_NAME_INFO pName = NULL;
  1004. PCERT_RDN pIdentRDN;
  1005. PCERT_RDN_ATTR pIdentifier;
  1006. DWORD cbIdentifier;
  1007. DWORD cbName, cbName2;
  1008. INET_ASSERT(lpdwListBoxEntry);
  1009. if (lpszListBoxEntry == NULL)
  1010. *lpdwListBoxEntry = 0;
  1011. //
  1012. // 30-Aug-1997 pberkman:
  1013. // we need to do this to be backwards compatible with this function.
  1014. // however, becuase the create context function does not get us properties
  1015. // when we are creating it from a already existing context, we need the
  1016. // ability to just pass in the pre-existing context. To do this, just
  1017. // pass "-1" in for the cbCert and we'll do the "right thing".
  1018. //
  1019. if (cbCert == (-1))
  1020. {
  1021. pCert = (PCCERT_CONTEXT)lpCert;
  1022. }
  1023. else
  1024. {
  1025. pCert = CertCreateCertificateContext(X509_ASN_ENCODING,
  1026. lpCert,
  1027. cbCert);
  1028. }
  1029. //
  1030. // 30-Aug-1997 pberkman:
  1031. // look at the "Friendly Name" property first.
  1032. //
  1033. cbName = 0;
  1034. CertGetCertificateContextProperty(pCert, CERT_FRIENDLY_NAME_PROP_ID, NULL, &cbName);
  1035. if (cbName > 0)
  1036. {
  1037. WCHAR *pbFName;
  1038. if (pbFName = (WCHAR *)new BYTE[cbName])
  1039. {
  1040. if (CertGetCertificateContextProperty(pCert, CERT_FRIENDLY_NAME_PROP_ID, pbFName, &cbName))
  1041. {
  1042. cbName2 = WideCharToMultiByte(0, 0, (WCHAR *)pbFName, wcslen((WCHAR *)pbFName) + 1,
  1043. lpszListBoxEntry, *lpdwListBoxEntry, NULL, NULL);
  1044. if (cbName2 > *lpdwListBoxEntry)
  1045. {
  1046. error = ERROR_INSUFFICIENT_BUFFER;
  1047. *lpdwListBoxEntry = cbName2;
  1048. }
  1049. delete pbFName;
  1050. if ((pCert) && (cbCert != (-1)))
  1051. {
  1052. CertFreeCertificateContext(pCert);
  1053. }
  1054. return(error);
  1055. }
  1056. delete pbFName;
  1057. }
  1058. }
  1059. if(CryptDecodeObject(pCert->dwCertEncodingType,
  1060. X509_NAME,
  1061. pCert->pCertInfo->Subject.pbData,
  1062. pCert->pCertInfo->Subject.cbData,
  1063. 0,
  1064. NULL,
  1065. &cbName))
  1066. {
  1067. pName = (PCERT_NAME_INFO)new BYTE[cbName];
  1068. if(pName == NULL)
  1069. {
  1070. error = ERROR_NOT_ENOUGH_MEMORY;
  1071. }
  1072. else if(!CryptDecodeObject(pCert->dwCertEncodingType,
  1073. X509_NAME,
  1074. pCert->pCertInfo->Subject.pbData,
  1075. pCert->pCertInfo->Subject.cbData,
  1076. 0,
  1077. pName,
  1078. &cbName))
  1079. {
  1080. delete pName;
  1081. pName = NULL;
  1082. error = GetLastError();
  1083. }
  1084. }
  1085. else
  1086. {
  1087. error = GetLastError();
  1088. }
  1089. if((NULL != pName) && (pName->cRDN > 0))
  1090. {
  1091. pIdentifier = CertFindRDNAttr(szOID_COMMON_NAME, pName);
  1092. if(pIdentifier == NULL)
  1093. {
  1094. pIdentifier = CertFindRDNAttr(szOID_ORGANIZATIONAL_UNIT_NAME, pName);
  1095. if(pIdentifier == NULL)
  1096. {
  1097. pIdentifier = CertFindRDNAttr(szOID_ORGANIZATION_NAME, pName);
  1098. if(pIdentifier == NULL)
  1099. {
  1100. pIdentRDN = &pName->rgRDN[pName->cRDN-1];
  1101. pIdentifier = &pIdentRDN->rgRDNAttr[pIdentRDN->cRDNAttr-1];
  1102. }
  1103. }
  1104. }
  1105. if(pIdentifier != NULL)
  1106. {
  1107. cbIdentifier = CertRDNValueToStr(pIdentifier->dwValueType,
  1108. &pIdentifier->Value,
  1109. NULL,
  1110. 0);
  1111. if(cbIdentifier == 0)
  1112. {
  1113. error = GetLastError();
  1114. }
  1115. else if ( (lpszListBoxEntry != NULL) && (cbIdentifier > (*lpdwListBoxEntry)) )
  1116. {
  1117. error = ERROR_INSUFFICIENT_BUFFER;
  1118. *lpdwListBoxEntry = cbIdentifier;
  1119. }
  1120. else
  1121. {
  1122. *lpdwListBoxEntry = CertRDNValueToStr(pIdentifier->dwValueType,
  1123. &pIdentifier->Value,
  1124. lpszListBoxEntry,
  1125. cbIdentifier);
  1126. error = ERROR_SUCCESS;
  1127. }
  1128. }
  1129. else
  1130. {
  1131. *lpdwListBoxEntry = 0;
  1132. error = ERROR_INTERNET_INVALID_OPERATION;
  1133. }
  1134. delete pName;
  1135. }
  1136. //
  1137. // 30-Aug-1997 pberkman:
  1138. // we have to free this thing!
  1139. //
  1140. if ((pCert) && (cbCert != (-1)))
  1141. {
  1142. CertFreeCertificateContext(pCert);
  1143. }
  1144. return error;
  1145. }
  1146. DWORD
  1147. ShowX509EncodedCertificate(
  1148. IN HWND hWndParent,
  1149. IN LPBYTE lpCert,
  1150. IN DWORD cbCert
  1151. )
  1152. /*++
  1153. Routine Description:
  1154. Shows an encoded set of bytes which represent a certificate,
  1155. in a dialog box.
  1156. Arguments:
  1157. hWndParent
  1158. lpCert
  1159. cbCert
  1160. Return Value:
  1161. DWORD
  1162. ERROR_SUCCESS
  1163. --*/
  1164. {
  1165. DWORD error;
  1166. #ifdef USE_NT5_CRYPTOUI
  1167. //
  1168. // For now, we use the new UI only if we can load the DLL. Otherwise we
  1169. // resort to the old UI. Eventually, we may nuke the old UI.
  1170. //
  1171. if (UseCryptoUI())
  1172. {
  1173. CRYPTUI_VIEWCERTIFICATE_STRUCT cert;
  1174. ZeroMemory(&cert, sizeof(cert));
  1175. cert.dwSize = sizeof(cert);
  1176. cert.hwndParent = hWndParent;
  1177. cert.pCertContext = (PCCERT_CONTEXT)lpCert;
  1178. cert.cStores = 1;
  1179. cert.rghStores = (HCERTSTORE *) & (cert.pCertContext->hCertStore);
  1180. return _CryptUIDlgViewCertificate(&cert, NULL);
  1181. }
  1182. else
  1183. #endif
  1184. {
  1185. X509Certificate *pCertData = NULL;
  1186. INTERNET_SECURITY_INFO ciInfo;
  1187. ZeroMemory(&ciInfo, sizeof(ciInfo));
  1188. ciInfo.dwSize = sizeof(ciInfo);
  1189. ciInfo.pCertificate = CertCreateCertificateContext(X509_ASN_ENCODING,
  1190. lpCert,
  1191. cbCert);
  1192. error = ShowSecurityInfo(
  1193. hWndParent,
  1194. &ciInfo
  1195. );
  1196. }
  1197. return error;
  1198. }
  1199. BOOL _GetSelectedCertContext(HWND hwnd, PERRORINFODLGTYPE pDlgInfo, PCCERT_CONTEXT *ppCertContext)
  1200. {
  1201. CERT_CONTEXT_ARRAY* pCertContextArray;
  1202. if (ppCertContext == NULL)
  1203. return FALSE;
  1204. *ppCertContext = NULL;
  1205. pCertContextArray =
  1206. ((HTTP_REQUEST_HANDLE_OBJECT *)pDlgInfo->hInternetMapped)->GetCertContextArray();
  1207. PCERT_CHAIN pcCertChain;
  1208. LRESULT index;
  1209. INET_ASSERT(pCertContextArray);
  1210. if (!pCertContextArray)
  1211. return FALSE;
  1212. //
  1213. // Retrieve the Cert from List box
  1214. //
  1215. index = SendDlgItemMessage(hwnd,
  1216. IDC_CERTPICKLIST,
  1217. LB_GETCURSEL,
  1218. 0,
  1219. 0);
  1220. if ( index == LB_ERR )
  1221. index = 0;
  1222. if ( index >= (INT) pCertContextArray->GetArraySize())
  1223. {
  1224. INET_ASSERT(FALSE);
  1225. return FALSE;
  1226. }
  1227. *ppCertContext = pCertContextArray->GetCertContext((INT)index);
  1228. if (!*ppCertContext)
  1229. return FALSE;
  1230. else
  1231. return TRUE;
  1232. }
  1233. INT_PTR
  1234. CALLBACK
  1235. CertPickDialogProc(
  1236. HWND hwnd,
  1237. UINT msg,
  1238. WPARAM wparam,
  1239. LPARAM lparam
  1240. )
  1241. /*++
  1242. Routine Description:
  1243. Supports Ok/Cancel decisions for the Client Authentication UI.
  1244. Allows the User to select a specific Certificate that he wishes
  1245. to use for Client Auth.
  1246. Arguments:
  1247. hwnd - standard dialog params
  1248. msg - "
  1249. wparam - "
  1250. lparam - "
  1251. Return Value:
  1252. BOOL
  1253. TRUE - we handled message
  1254. FALSE - Windows should handle message
  1255. --*/
  1256. {
  1257. PERRORINFODLGTYPE pDlgInfo;
  1258. CERT_CONTEXT_ARRAY* pCertContextArray;
  1259. LRESULT index;
  1260. const static DWORD mapIDCsToIDHs[] =
  1261. {
  1262. IDC_CERTPICKLIST, IDH_CLIENT_AUTHENTICATION_LIST,
  1263. ID_SHOW_CERTIFICATE, IDH_CLIENT_AUTHENTICATION_CERT_PROPS,
  1264. IDCLOSE, IDH_ORG_FAVORITES_CLOSE,
  1265. IDC_BUTTON_IMPORT, IDH_CLIENTAUTH_IMPORT,
  1266. IDC_BUTTON_EXPORT, IDH_CLIENTAUTH_EXPORT,
  1267. 0,0
  1268. };
  1269. switch (msg)
  1270. {
  1271. case WM_INITDIALOG:
  1272. {
  1273. INET_ASSERT(lparam);
  1274. pDlgInfo = (PERRORINFODLGTYPE)lparam;
  1275. (void)SetWindowLongPtr(hwnd,
  1276. DWLP_USER,
  1277. lparam);
  1278. // We used to have other dialogs use the same dialog proc, but this
  1279. // shouldn't happen with the removal of the personal certs dialog.
  1280. INET_ASSERT(pDlgInfo->dwDlgId == IDD_CERTPICKER);
  1281. pCertContextArray =
  1282. ((HTTP_REQUEST_HANDLE_OBJECT *)pDlgInfo->hInternetMapped)->GetCertContextArray();
  1283. PlaceCertContextsInListBox(
  1284. GetDlgItem(hwnd, IDC_CERTPICKLIST),
  1285. GetDlgItem(hwnd, ID_SHOW_CERTIFICATE),
  1286. GetDlgItem(hwnd, IDC_BUTTON_EXPORT),
  1287. pCertContextArray
  1288. );
  1289. return TRUE;
  1290. }
  1291. case WM_HELP: // F1
  1292. WinHelp( (HWND)((LPHELPINFO)lparam)->hItemHandle,
  1293. szHelpFile,
  1294. HELP_WM_HELP,
  1295. (ULONG_PTR)(LPSTR)mapIDCsToIDHs
  1296. );
  1297. break;
  1298. case WM_CONTEXTMENU: // right mouse click
  1299. WinHelp( (HWND) wparam,
  1300. szHelpFile,
  1301. HELP_CONTEXTMENU,
  1302. (ULONG_PTR)(LPSTR)mapIDCsToIDHs
  1303. );
  1304. break;
  1305. case WM_COMMAND:
  1306. {
  1307. WORD wID = LOWORD(wparam);
  1308. WORD wNotificationCode = HIWORD(wparam);
  1309. HWND hWndCtrl = (HWND) lparam;
  1310. pDlgInfo =
  1311. (PERRORINFODLGTYPE) GetWindowLongPtr(hwnd,DWLP_USER);
  1312. switch (wID)
  1313. {
  1314. case ID_TELL_ME_ABOUT_SECURITY:
  1315. //
  1316. // Launches help for this button.
  1317. //
  1318. WinHelp(
  1319. hwnd,
  1320. szHelpFile,
  1321. HELP_CONTEXT,
  1322. (ULONG_PTR)HELP_TOPIC_SECURITY
  1323. );
  1324. break;
  1325. case ID_SHOW_CERTIFICATE:
  1326. {
  1327. //
  1328. // If this dialog supports this behavior, then launch
  1329. // a show certficate dlg.
  1330. //
  1331. PCCERT_CONTEXT pCertContext;
  1332. if ( wNotificationCode == BN_CLICKED &&
  1333. _GetSelectedCertContext(hwnd, pDlgInfo, &pCertContext ))
  1334. {
  1335. ShowX509EncodedCertificate( hwnd, (LPBYTE)pCertContext, sizeof(pCertContext) );
  1336. }
  1337. break;
  1338. }
  1339. case ID_CERT_MORE_INFO:
  1340. HtmlHelp(hwnd, TEXT("iexplore.chm > iedefault"), HH_DISPLAY_TOPIC, (DWORD_PTR)TEXT("cert_ovr.htm"));
  1341. break;
  1342. case IDCANCEL:
  1343. index = -1;
  1344. goto lskip_getcursel;
  1345. case IDOK:
  1346. //
  1347. // Get the selected Cert.
  1348. //
  1349. index = SendDlgItemMessage(hwnd,
  1350. IDC_CERTPICKLIST,
  1351. LB_GETCURSEL,
  1352. 0,
  1353. 0);
  1354. if ( index == LB_ERR )
  1355. index = -1;
  1356. lskip_getcursel:
  1357. INET_ASSERT(pDlgInfo);
  1358. INET_ASSERT(pDlgInfo->dwDlgId != 0);
  1359. //
  1360. // Select the Client Auth Cert to use,
  1361. // but only if we've got the cert picker dialog.
  1362. //
  1363. pCertContextArray =
  1364. ((HTTP_REQUEST_HANDLE_OBJECT *)pDlgInfo->hInternetMapped)->GetCertContextArray();
  1365. if (pCertContextArray)
  1366. {
  1367. pCertContextArray->SelectCertContext((INT)index);
  1368. }
  1369. EndDialog(hwnd, TRUE);
  1370. break;
  1371. case IDCLOSE:
  1372. //
  1373. // We're done, so return FALSE.
  1374. //
  1375. EndDialog(hwnd, FALSE);
  1376. break;
  1377. }
  1378. return TRUE;
  1379. }
  1380. }
  1381. return FALSE;
  1382. }
  1383. //
  1384. // private functions
  1385. //
  1386. PRIVATE
  1387. BOOL
  1388. PlaceCertContextsInListBox(
  1389. IN HWND hWndListBox,
  1390. IN HWND hWndViewCertButton,
  1391. IN HWND hWndExportButton,
  1392. IN CERT_CONTEXT_ARRAY* pCertContextArray
  1393. )
  1394. /*++
  1395. Routine Description:
  1396. Takes an array of CertContext's and puts them into a listbox,
  1397. by cracking their contents one at a time.
  1398. Arguments:
  1399. hWndListBox - Window Handle to ListBox to add items to.
  1400. pCertContext's - Pointer to array of cert chains.
  1401. hWndViewCertButton - Window handle to ViewCert Button, NULL if no button is around
  1402. Return Value:
  1403. BOOL
  1404. TRUE - success.
  1405. FALSE - failure.
  1406. --*/
  1407. {
  1408. DWORD i = 0;
  1409. if ( !pCertContextArray)
  1410. {
  1411. goto quit;
  1412. }
  1413. SendMessage(hWndListBox, LB_RESETCONTENT, 0, 0 );
  1414. for ( i = 0; i < pCertContextArray->GetArraySize(); i++ )
  1415. {
  1416. PCCERT_CONTEXT pCert;
  1417. // PCERT_NAME_INFO pName = NULL;
  1418. // PCERT_RDN_ATTR pCommonName;
  1419. DWORD cbName;
  1420. DWORD dwRet;
  1421. pCert = pCertContextArray->GetCertContext(i);
  1422. INET_ASSERT(pCert);
  1423. LPSTR lpszSubject;
  1424. cbName = 0;
  1425. ParseX509EncodedCertificateForListBoxEntry(pCert->pbCertEncoded,
  1426. pCert->cbCertEncoded,
  1427. NULL,
  1428. &cbName);
  1429. if (cbName > 0)
  1430. {
  1431. if (lpszSubject = new TCHAR[cbName])
  1432. {
  1433. if (ParseX509EncodedCertificateForListBoxEntry(pCert->pbCertEncoded,
  1434. pCert->cbCertEncoded,
  1435. lpszSubject,
  1436. &cbName) == ERROR_SUCCESS)
  1437. {
  1438. SendMessage(hWndListBox, LB_INSERTSTRING, (WPARAM)-1, (LPARAM) lpszSubject);
  1439. }
  1440. FREE_MEMORY(lpszSubject);
  1441. }
  1442. }
  1443. }
  1444. quit:
  1445. // Select the first item in the list box
  1446. // TODO: move selection to current default item.
  1447. SendMessage(hWndListBox, LB_SETCURSEL, 0, 0 );
  1448. // If nothing was added, disable the windows, otherwise enable them
  1449. EnableWindow(hWndListBox, (i != 0));
  1450. if ( hWndViewCertButton )
  1451. EnableWindow(hWndViewCertButton, (i != 0));
  1452. if ( hWndExportButton )
  1453. EnableWindow(hWndExportButton, (i != 0));
  1454. return TRUE;
  1455. }
  1456. PRIVATE
  1457. BOOL
  1458. PlaceCertificateDataIntoListBox(
  1459. IN HWND hWndDlg,
  1460. IN HWND hWndListBox,
  1461. IN ShowCertMapping *pMapCertFields
  1462. )
  1463. {
  1464. DWORD i;
  1465. INET_ASSERT(pMapCertFields);
  1466. INET_ASSERT(IsWindow(hWndListBox));
  1467. for ( i = 0; pMapCertFields[i].lpszListBoxText != NULL; i++ )
  1468. {
  1469. if ( pMapCertFields[i].dwSpcCtlId != 0 )
  1470. {
  1471. SetDlgItemTextWrapW(hWndDlg,pMapCertFields[i].dwSpcCtlId,
  1472. pMapCertFields[i].lpszEditBoxText );
  1473. SetWindowLong(GetDlgItem(hWndDlg,pMapCertFields[i].dwSpcCtlId),
  1474. GWL_STYLE, ES_READONLY |
  1475. GetWindowLong(GetDlgItem(hWndDlg,pMapCertFields[i].dwSpcCtlId), GWL_STYLE));
  1476. }
  1477. SendMessage(hWndListBox, LB_ADDSTRING, 0, (LPARAM)pMapCertFields[i].lpszListBoxText);
  1478. }
  1479. INET_ASSERT(i>0);
  1480. SendMessage(hWndListBox, LB_SETCURSEL, 0, 0 );
  1481. return TRUE;
  1482. }
  1483. PRIVATE
  1484. DWORD
  1485. OnSelectionOfACertField(
  1486. IN HWND hWndListBox,
  1487. IN HWND hWndEditBox,
  1488. IN ShowCertMapping *pMapCertFields
  1489. )
  1490. {
  1491. LRESULT index;
  1492. index = SendMessage(hWndListBox, LB_GETCURSEL, 0, 0);
  1493. if (index == LB_ERR )
  1494. index = 0;
  1495. if ( pMapCertFields[index].lpszListBoxText != NULL )
  1496. {
  1497. SetWindowTextWrapW(hWndEditBox,
  1498. pMapCertFields[index].lpszEditBoxText );
  1499. SetWindowLong(hWndEditBox,
  1500. GWL_STYLE, ES_READONLY |
  1501. GetWindowLong(hWndEditBox, GWL_STYLE));
  1502. }
  1503. return ERROR_SUCCESS;
  1504. }
  1505. #ifndef CERT_E_WRONG_USAGE
  1506. # define CERT_E_WRONG_USAGE _HRESULT_TYPEDEF_(0x800B0110L)
  1507. #endif
  1508. #ifndef SECURITY_FLAG_IGNORE_WRONG_USAGE
  1509. # define SECURITY_FLAG_IGNORE_WRONG_USAGE 0x00010000
  1510. #endif
  1511. /* get a string representing the status of a certificate */
  1512. LPWSTR GetCertStatus(LPINTERNET_SECURITY_INFO pciCert)
  1513. {
  1514. // We've done our handshake, now update the security info
  1515. DWORD dwCertFlags;
  1516. PLOCAL_STRINGS plszStrings;
  1517. GUID gHTTPS = HTTPSPROV_ACTION;
  1518. WINTRUST_DATA sWTD;
  1519. WINTRUST_CERT_INFO sWTCI;
  1520. HTTPSPolicyCallbackData polHttps;
  1521. DWORD cbServerName;
  1522. DWORD error;
  1523. plszStrings = FetchLocalStrings();
  1524. if(plszStrings == NULL)
  1525. {
  1526. return NULL;
  1527. }
  1528. if((pciCert == NULL) || (pciCert->pCertificate == NULL))
  1529. {
  1530. return NULL;
  1531. }
  1532. //
  1533. // initialize the structures for forward/backward support of wintrust.dll!!!
  1534. //
  1535. memset(&sWTD, 0x00, sizeof(WINTRUST_DATA));
  1536. sWTD.cbStruct = sizeof(WINTRUST_DATA);
  1537. sWTD.dwUIChoice = WTD_UI_NONE;
  1538. sWTD.pPolicyCallbackData = (LPVOID)&polHttps;
  1539. sWTD.dwUnionChoice = WTD_CHOICE_CERT;
  1540. sWTD.pCert = &sWTCI;
  1541. sWTD.pwszURLReference = NULL;
  1542. memset(&sWTCI, 0x00, sizeof(WINTRUST_CERT_INFO));
  1543. sWTCI.cbStruct = sizeof(WINTRUST_CERT_INFO);
  1544. sWTCI.psCertContext = (CERT_CONTEXT *)pciCert->pCertificate;
  1545. sWTCI.chStores = 1;
  1546. sWTCI.pahStores = (HCERTSTORE *)&pciCert->pCertificate->hCertStore;
  1547. memset(&polHttps, 0x00, sizeof(HTTPSPolicyCallbackData));
  1548. polHttps.cbStruct = sizeof(HTTPSPolicyCallbackData);
  1549. polHttps.dwAuthType = AUTHTYPE_SERVER;
  1550. polHttps.fdwChecks = INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
  1551. SECURITY_FLAG_IGNORE_WRONG_USAGE;
  1552. polHttps.pwszServerName = NULL;
  1553. sWTCI.pcwszDisplayName = NULL;
  1554. error = LoadWinTrust();
  1555. if(ERROR_SUCCESS == error)
  1556. {
  1557. error = WinVerifySecureChannel(NULL, &sWTD);
  1558. }
  1559. // If we are unable to verify revocation, then ignore.
  1560. if(error == CERT_E_REVOCATION_FAILURE)
  1561. {
  1562. error = ERROR_SUCCESS;
  1563. }
  1564. switch(error)
  1565. {
  1566. case CERT_E_EXPIRED:
  1567. case CERT_E_VALIDITYPERIODNESTING:
  1568. return plszStrings->szCommentExpires;
  1569. case CERT_E_UNTRUSTEDROOT:
  1570. return plszStrings->szCommentBadCA;
  1571. case CERT_E_CN_NO_MATCH:
  1572. return plszStrings->szCommentBadCN;
  1573. case CRYPT_E_REVOKED:
  1574. return plszStrings->szCommentRevoked;
  1575. case CERT_E_WRONG_USAGE:
  1576. return plszStrings->szCertUsage;
  1577. case CERT_E_ROLE:
  1578. case CERT_E_PATHLENCONST:
  1579. case CERT_E_CRITICAL:
  1580. case CERT_E_PURPOSE:
  1581. case CERT_E_ISSUERCHAINING:
  1582. case CERT_E_MALFORMED:
  1583. case CERT_E_CHAINING:
  1584. return plszStrings->szCommentNotValid;
  1585. case ERROR_SUCCESS:
  1586. return NULL;
  1587. default:
  1588. return plszStrings->szCommentNotValid;
  1589. }
  1590. }