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

611 lines
20 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: cps.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. //
  11. // File: select.cpp
  12. //
  13. // Description: This file contains the implmentation code for the
  14. // "Certificate Select" dialog.
  15. //
  16. #pragma warning (disable: 4201) // nameless struct/union
  17. #pragma warning (disable: 4514) // remove inline functions
  18. #pragma warning (disable: 4127) // conditional expression is constant
  19. #include "global.hxx"
  20. #include <dbgdef.h>
  21. extern HINSTANCE HinstDll;
  22. extern HMODULE HmodRichEdit;
  23. typedef struct _CPS_STATE_STRUCT {
  24. LPWSTR pwszURL;
  25. LPWSTR pwszDisplayText;
  26. DWORD dwChainError;
  27. BOOL fNoCOM;
  28. } CPS_STATE_STRUCT, *PCPS_STATE_STRUCT;
  29. INT_PTR CALLBACK CPSDlgProc(HWND hwndDlg, UINT msg,
  30. WPARAM wParam, LPARAM lParam)
  31. {
  32. BOOL f;
  33. CPS_STATE_STRUCT *pcpsStateStruct;
  34. switch (msg) {
  35. case WM_INITDIALOG:
  36. pcpsStateStruct = (CPS_STATE_STRUCT *) lParam;
  37. SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR) pcpsStateStruct);
  38. // set the text for the CPS
  39. CryptUISetRicheditTextW(hwndDlg, IDC_CPS_TEXT, pcpsStateStruct->pwszDisplayText);
  40. // if there is no URL then hide the more info button,
  41. //
  42. // DSIE: Bug 364742, also hide if the URL is not safe to be execute.
  43. if (!pcpsStateStruct->pwszURL ||
  44. !IsOKToFormatAsLinkW(pcpsStateStruct->pwszURL, pcpsStateStruct->dwChainError))
  45. {
  46. EnableWindow(GetDlgItem(hwndDlg, ID_MORE_INFO), FALSE);
  47. }
  48. break;
  49. case WM_NOTIFY:
  50. //if (((NMHDR FAR *) lParam)->code == EN_LINK)
  51. break;
  52. case WM_COMMAND:
  53. switch (LOWORD(wParam)) {
  54. case ID_MORE_INFO:
  55. if (HIWORD(wParam) == BN_CLICKED)
  56. {
  57. DWORD numBytes = 0;
  58. LPSTR pszURL = NULL;
  59. pcpsStateStruct = (CPS_STATE_STRUCT *) GetWindowLongPtr(hwndDlg, DWLP_USER);
  60. pszURL = CertUIMkMBStr(pcpsStateStruct->pwszURL);
  61. if (pszURL == NULL)
  62. {
  63. return TRUE;
  64. }
  65. CryptuiGoLink(hwndDlg, pszURL, pcpsStateStruct->fNoCOM);
  66. free(pszURL);
  67. return TRUE;
  68. }
  69. break;
  70. case IDOK:
  71. case IDCANCEL:
  72. case IDOK_CPS:
  73. case IDCANCEL_CPS:
  74. EndDialog(hwndDlg, IDOK);
  75. return TRUE;
  76. }
  77. break;
  78. //
  79. // Use the default handler -- we don't do anything for it
  80. //
  81. default:
  82. return FALSE;
  83. }
  84. return FALSE;
  85. }
  86. DWORD GetCPSInfo(PCCERT_CONTEXT pCertContext, LPWSTR * ppwszUrlString, LPWSTR * ppwszDisplayText)
  87. {
  88. DWORD dwRetCode = 0;
  89. PCERT_EXTENSION pExt = NULL;
  90. DWORD i,j,k;
  91. DWORD cbCertPolicyInfo = 0;
  92. CERT_POLICIES_INFO * pCertPolicyInfo = NULL;
  93. CERT_NAME_VALUE * pCertName = NULL;
  94. DWORD cbCertName = 0;
  95. CERT_POLICY_QUALIFIER_USER_NOTICE * pUserNotice = NULL;
  96. DWORD cbUserNotice = 0;
  97. PSPC_SP_AGENCY_INFO pInfo = NULL;
  98. DWORD cbInfo = 0;
  99. CERT_POLICY95_QUALIFIER1 * pCertPolicy95Qualifier = NULL;
  100. DWORD cbCertPolicy95Qualifier = 0;
  101. //
  102. // Check parameters and intialize return values.
  103. //
  104. if (NULL == pCertContext || NULL == ppwszUrlString || NULL == ppwszDisplayText)
  105. {
  106. return ERROR_INVALID_PARAMETER;
  107. }
  108. *ppwszUrlString = *ppwszDisplayText = NULL;
  109. //
  110. // first look for the PKIX policy extension and see if it has an URL
  111. //
  112. if ((pExt = CertFindExtension(szOID_CERT_POLICIES,
  113. pCertContext->pCertInfo->cExtension,
  114. pCertContext->pCertInfo->rgExtension)))
  115. {
  116. //
  117. // decode the policy extension
  118. //
  119. CryptDecodeObject(X509_ASN_ENCODING,
  120. szOID_CERT_POLICIES,
  121. pExt->Value.pbData,
  122. pExt->Value.cbData,
  123. 0,
  124. NULL,
  125. &cbCertPolicyInfo);
  126. if (!(pCertPolicyInfo = (CERT_POLICIES_INFO *) malloc(cbCertPolicyInfo)))
  127. {
  128. dwRetCode = ERROR_OUTOFMEMORY;
  129. goto ErrorExit;
  130. }
  131. if (!(CryptDecodeObject(X509_ASN_ENCODING,
  132. szOID_CERT_POLICIES,
  133. pExt->Value.pbData,
  134. pExt->Value.cbData,
  135. 0,
  136. pCertPolicyInfo,
  137. &cbCertPolicyInfo)))
  138. {
  139. dwRetCode = GetLastError();
  140. goto ErrorExit;
  141. }
  142. //
  143. // look for display text and/or and URL in the extension
  144. //
  145. for (i = 0; i < pCertPolicyInfo->cPolicyInfo ; i++)
  146. {
  147. for (j = 0; j < pCertPolicyInfo->rgPolicyInfo[i].cPolicyQualifier; j++)
  148. {
  149. // check to see what type of qualifier it is
  150. if (0 == strcmp(szOID_PKIX_POLICY_QUALIFIER_CPS,
  151. pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].pszPolicyQualifierId))
  152. {
  153. // decode as an anystring
  154. CryptDecodeObject(X509_ASN_ENCODING,
  155. X509_UNICODE_ANY_STRING,
  156. pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.pbData,
  157. pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.cbData,
  158. 0,
  159. NULL,
  160. &cbCertName);
  161. if (!(pCertName = (CERT_NAME_VALUE *) malloc(cbCertName)))
  162. {
  163. dwRetCode = ERROR_OUTOFMEMORY;
  164. goto ErrorExit;
  165. }
  166. if (!(CryptDecodeObject(X509_ASN_ENCODING,
  167. X509_UNICODE_ANY_STRING,
  168. pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.pbData,
  169. pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.cbData,
  170. 0,
  171. pCertName,
  172. &cbCertName)))
  173. {
  174. dwRetCode = GetLastError();
  175. goto ErrorExit;
  176. }
  177. if (pCertName->Value.cbData && NULL == *ppwszUrlString)
  178. {
  179. if (!(*ppwszUrlString = (LPWSTR) malloc(pCertName->Value.cbData + sizeof(WCHAR))))
  180. {
  181. dwRetCode = ERROR_OUTOFMEMORY;
  182. goto ErrorExit;
  183. }
  184. wcscpy(*ppwszUrlString, (LPWSTR) pCertName->Value.pbData);
  185. }
  186. free(pCertName);
  187. pCertName = NULL;
  188. }
  189. else if (0 == strcmp(szOID_PKIX_POLICY_QUALIFIER_USERNOTICE,
  190. pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].pszPolicyQualifierId))
  191. {
  192. // decode as user notice
  193. CryptDecodeObject(X509_ASN_ENCODING,
  194. szOID_PKIX_POLICY_QUALIFIER_USERNOTICE,
  195. pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.pbData,
  196. pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.cbData,
  197. 0,
  198. NULL,
  199. &cbUserNotice);
  200. if (!(pUserNotice = (CERT_POLICY_QUALIFIER_USER_NOTICE *) malloc(cbUserNotice)))
  201. {
  202. dwRetCode = ERROR_OUTOFMEMORY;
  203. goto ErrorExit;
  204. }
  205. if (!(CryptDecodeObject(X509_ASN_ENCODING,
  206. szOID_PKIX_POLICY_QUALIFIER_USERNOTICE,
  207. pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.pbData,
  208. pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.cbData,
  209. 0,
  210. pUserNotice,
  211. &cbUserNotice)))
  212. {
  213. dwRetCode = GetLastError();
  214. goto ErrorExit;
  215. }
  216. // NOTE: pUserNotice->pszDisplayText may be NULL
  217. if (pUserNotice->pszDisplayText && NULL == *ppwszDisplayText)
  218. {
  219. if (!(*ppwszDisplayText = (LPWSTR) malloc((wcslen(pUserNotice->pszDisplayText) + 1) * sizeof(WCHAR))))
  220. {
  221. dwRetCode = ERROR_OUTOFMEMORY;
  222. goto ErrorExit;
  223. }
  224. wcscpy(*ppwszDisplayText, pUserNotice->pszDisplayText);
  225. }
  226. free(pUserNotice);
  227. pUserNotice = NULL;
  228. }
  229. }
  230. }
  231. }
  232. //
  233. // next look for display information in the SPC Agency Info
  234. //
  235. else if ((pExt = CertFindExtension(SPC_SP_AGENCY_INFO_OBJID,
  236. pCertContext->pCertInfo->cExtension,
  237. pCertContext->pCertInfo->rgExtension)))
  238. {
  239. CryptDecodeObject(X509_ASN_ENCODING,
  240. SPC_SP_AGENCY_INFO_STRUCT,
  241. pExt->Value.pbData,
  242. pExt->Value.cbData,
  243. 0,
  244. NULL,
  245. &cbInfo);
  246. if (!(pInfo = (PSPC_SP_AGENCY_INFO) malloc(cbInfo)))
  247. {
  248. dwRetCode = ERROR_OUTOFMEMORY;
  249. goto ErrorExit;
  250. }
  251. if (!(CryptDecodeObject(X509_ASN_ENCODING,
  252. SPC_SP_AGENCY_INFO_STRUCT,
  253. pExt->Value.pbData,
  254. pExt->Value.cbData,
  255. 0,
  256. pInfo,
  257. &cbInfo)))
  258. {
  259. dwRetCode = GetLastError();
  260. goto ErrorExit;
  261. }
  262. if (!(pInfo->pPolicyInformation))
  263. {
  264. dwRetCode = CRYPT_E_NOT_FOUND;
  265. goto ErrorExit;
  266. }
  267. if (pInfo->pwszPolicyDisplayText)
  268. {
  269. if (!(*ppwszDisplayText = (LPWSTR) malloc((wcslen(pInfo->pwszPolicyDisplayText) + 1) * sizeof(WCHAR))))
  270. {
  271. dwRetCode = ERROR_OUTOFMEMORY;
  272. goto ErrorExit;
  273. }
  274. wcscpy(*ppwszDisplayText, pInfo->pwszPolicyDisplayText);
  275. }
  276. switch (pInfo->pPolicyInformation->dwLinkChoice)
  277. {
  278. case SPC_URL_LINK_CHOICE:
  279. {
  280. if (pInfo->pPolicyInformation->pwszUrl)
  281. {
  282. if (!(*ppwszUrlString = (LPWSTR) malloc((wcslen(pInfo->pPolicyInformation->pwszUrl) + 1) * sizeof(WCHAR))))
  283. {
  284. dwRetCode = ERROR_OUTOFMEMORY;
  285. goto ErrorExit;
  286. }
  287. wcscpy(*ppwszUrlString, pInfo->pPolicyInformation->pwszUrl);
  288. }
  289. break;
  290. }
  291. case SPC_FILE_LINK_CHOICE:
  292. {
  293. if (pInfo->pPolicyInformation->pwszFile)
  294. {
  295. if (!(*ppwszUrlString = (LPWSTR) malloc((wcslen(pInfo->pPolicyInformation->pwszFile) + 1) * sizeof(WCHAR))))
  296. {
  297. dwRetCode = ERROR_OUTOFMEMORY;
  298. goto ErrorExit;
  299. }
  300. wcscpy(*ppwszUrlString, pInfo->pPolicyInformation->pwszFile);
  301. }
  302. break;
  303. }
  304. }
  305. }
  306. //
  307. // finally, look for info in the 2.5.29.3 extension
  308. //
  309. else if ((pExt = CertFindExtension(szOID_CERT_POLICIES_95,
  310. pCertContext->pCertInfo->cExtension,
  311. pCertContext->pCertInfo->rgExtension)))
  312. {
  313. CryptDecodeObject(X509_ASN_ENCODING,
  314. szOID_CERT_POLICIES_95,
  315. pExt->Value.pbData,
  316. pExt->Value.cbData,
  317. 0,
  318. NULL,
  319. &cbCertPolicyInfo);
  320. if (!(pCertPolicyInfo = (CERT_POLICIES_INFO *) malloc(cbCertPolicyInfo)))
  321. {
  322. dwRetCode = ERROR_OUTOFMEMORY;
  323. goto ErrorExit;
  324. }
  325. if (!(CryptDecodeObject(X509_ASN_ENCODING,
  326. szOID_CERT_POLICIES_95,
  327. pExt->Value.pbData,
  328. pExt->Value.cbData,
  329. 0,
  330. pCertPolicyInfo,
  331. &cbCertPolicyInfo)))
  332. {
  333. dwRetCode = GetLastError();
  334. goto ErrorExit;
  335. }
  336. // now decode the qualifiers
  337. for (i = 0; i < pCertPolicyInfo->cPolicyInfo; i++)
  338. {
  339. for (j = 0; j < pCertPolicyInfo->rgPolicyInfo[i].cPolicyQualifier; j++)
  340. {
  341. if (0 == strcmp(szOID_CERT_POLICIES_95_QUALIFIER1,
  342. pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].pszPolicyQualifierId))
  343. {
  344. CryptDecodeObject(X509_ASN_ENCODING,
  345. szOID_CERT_POLICIES_95_QUALIFIER1,
  346. pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.pbData,
  347. pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.cbData,
  348. 0,
  349. NULL,
  350. &cbCertPolicy95Qualifier);
  351. if (!(pCertPolicy95Qualifier = (CERT_POLICY95_QUALIFIER1 *) malloc(cbCertPolicy95Qualifier)))
  352. {
  353. dwRetCode = ERROR_OUTOFMEMORY;
  354. goto ErrorExit;
  355. }
  356. if (!(CryptDecodeObject(X509_ASN_ENCODING,
  357. szOID_CERT_POLICIES_95_QUALIFIER1,
  358. pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.pbData,
  359. pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.cbData,
  360. 0,
  361. pCertPolicy95Qualifier,
  362. &cbCertPolicy95Qualifier)))
  363. {
  364. dwRetCode = GetLastError();
  365. goto ErrorExit;
  366. }
  367. // check to see what is available
  368. if ((NULL != pCertPolicy95Qualifier->pszPracticesReference) && (NULL == *ppwszDisplayText))
  369. {
  370. if (!(*ppwszDisplayText = (LPWSTR) malloc((wcslen(pCertPolicy95Qualifier->pszPracticesReference) + 1) * sizeof(WCHAR))))
  371. {
  372. dwRetCode = ERROR_OUTOFMEMORY;
  373. goto ErrorExit;
  374. }
  375. wcscpy(*ppwszDisplayText, pCertPolicy95Qualifier->pszPracticesReference);
  376. }
  377. for (k = 0; k < pCertPolicy95Qualifier->cCPSURLs; k++)
  378. {
  379. if ((NULL != pCertPolicy95Qualifier->rgCPSURLs[k].pszURL) && (NULL == *ppwszUrlString))
  380. {
  381. if (!(*ppwszUrlString = (LPWSTR) malloc((wcslen(pCertPolicy95Qualifier->rgCPSURLs[k].pszURL) + 1) * sizeof(WCHAR))))
  382. {
  383. dwRetCode = ERROR_OUTOFMEMORY;
  384. goto ErrorExit;
  385. }
  386. wcscpy(*ppwszUrlString, pCertPolicy95Qualifier->rgCPSURLs[k].pszURL);
  387. }
  388. }
  389. free(pCertPolicy95Qualifier);
  390. pCertPolicy95Qualifier = NULL;
  391. }
  392. }
  393. }
  394. }
  395. //
  396. // If there is neither display text nor an URL, then return CRYPT_E_NOT_FOUND.
  397. //
  398. if ((NULL == *ppwszUrlString) && (NULL == *ppwszDisplayText))
  399. {
  400. dwRetCode = CRYPT_E_NOT_FOUND;
  401. }
  402. CommonExit:
  403. if (pInfo)
  404. free(pInfo);
  405. if (pCertPolicyInfo)
  406. free(pCertPolicyInfo);
  407. if (pUserNotice)
  408. free(pUserNotice);
  409. if (pCertName)
  410. free(pCertName);
  411. if (pCertPolicy95Qualifier)
  412. free(pCertPolicy95Qualifier);
  413. return dwRetCode;
  414. ErrorExit:
  415. if (*ppwszUrlString)
  416. {
  417. free(*ppwszUrlString);
  418. *ppwszUrlString = NULL;
  419. }
  420. if (*ppwszDisplayText)
  421. {
  422. free(*ppwszDisplayText);
  423. *ppwszDisplayText = NULL;
  424. }
  425. goto CommonExit;
  426. }
  427. BOOL IsOKToDisplayCPS(PCCERT_CONTEXT pCertContext, DWORD dwChainError)
  428. {
  429. BOOL fResult = FALSE;
  430. LPWSTR pwszUrlString = NULL;
  431. LPWSTR pwszDisplayText = NULL;
  432. //
  433. // Check parameters and initialize.
  434. //
  435. if (NULL == pCertContext)
  436. {
  437. goto CommonExit;
  438. }
  439. //
  440. // Get CPS info.
  441. //
  442. if ((0 == GetCPSInfo(pCertContext, &pwszUrlString, &pwszDisplayText)) &&
  443. (pwszDisplayText || IsOKToFormatAsLinkW(pwszUrlString, dwChainError)))
  444. {
  445. fResult = TRUE;
  446. }
  447. CommonExit:
  448. if (pwszUrlString)
  449. {
  450. free(pwszUrlString);
  451. }
  452. if (pwszDisplayText)
  453. {
  454. free(pwszDisplayText);
  455. }
  456. return fResult;
  457. }
  458. BOOL DisplayCPS(HWND hwnd, PCCERT_CONTEXT pCertContext, DWORD dwChainError, BOOL fNoCOM)
  459. {
  460. BOOL fRet = FALSE;
  461. DWORD dwRetCode = 0;
  462. CPS_STATE_STRUCT cpsStateStruct;
  463. //
  464. // Initialize and check parameters.
  465. //
  466. memset(&cpsStateStruct, 0, sizeof(cpsStateStruct));
  467. if (NULL == pCertContext)
  468. {
  469. goto Return;
  470. }
  471. //
  472. // Get CPS info.
  473. //
  474. if (0 != (dwRetCode = GetCPSInfo(pCertContext, &cpsStateStruct.pwszURL, &cpsStateStruct.pwszDisplayText)))
  475. {
  476. goto Return;
  477. }
  478. // NOW, set up for, and launch that dialog
  479. if ((HmodRichEdit == NULL) && (NULL == (HmodRichEdit = LoadLibraryA("RichEd20.dll"))))
  480. {
  481. goto Return;
  482. }
  483. //
  484. // If there is an URL but no text then just invoke the browser and don't bring
  485. // up the dialog
  486. //
  487. if ((cpsStateStruct.pwszDisplayText == NULL) && (cpsStateStruct.pwszURL != NULL))
  488. {
  489. DWORD numBytes = 0;
  490. LPSTR pszURL = NULL;
  491. pszURL = CertUIMkMBStr(cpsStateStruct.pwszURL);
  492. if (pszURL == NULL)
  493. {
  494. goto Return;
  495. }
  496. CryptuiGoLink(hwnd, pszURL, fNoCOM);
  497. free(pszURL);
  498. }
  499. else
  500. {
  501. cpsStateStruct.fNoCOM = fNoCOM;
  502. cpsStateStruct.dwChainError = dwChainError;
  503. DialogBoxParamU(HinstDll, (LPWSTR) MAKEINTRESOURCE(IDD_CPS_DIALOG), hwnd, CPSDlgProc, (LPARAM) &cpsStateStruct);
  504. }
  505. fRet = TRUE;
  506. Return:
  507. if (cpsStateStruct.pwszURL)
  508. free(cpsStateStruct.pwszURL);
  509. if (cpsStateStruct.pwszDisplayText)
  510. free(cpsStateStruct.pwszDisplayText);
  511. return fRet;
  512. }