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.

1134 lines
29 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: context.c
  7. //
  8. // Contents: Schannel context management routines.
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 09-23-97 jbanes LSA integration stuff.
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <spbase.h>
  18. #include <certmap.h>
  19. #include <mapper.h>
  20. #include <dsysdbg.h>
  21. DWORD g_cContext = 0;
  22. /************************************************************************
  23. * SPContextCreate
  24. *
  25. * Create a new SPContext, and initialize it.
  26. *
  27. * Returns - PSPContext pointer to context object.
  28. *
  29. \***********************************************************************/
  30. PSPContext SPContextCreate(LPWSTR pszTarget)
  31. {
  32. PSPContext pContext;
  33. SP_BEGIN("SPContextCreate");
  34. pContext = (PSPContext)SPExternalAlloc( sizeof(SPContext));
  35. if(!pContext)
  36. {
  37. SP_RETURN(NULL);
  38. }
  39. DebugLog((DEB_TRACE, "Create context:0x%p\n", pContext));
  40. FillMemory(pContext, sizeof(SPContext), 0);
  41. pContext->Magic = SP_CONTEXT_MAGIC;
  42. pContext->Flags = 0;
  43. if(!NT_SUCCESS(GenerateRandomThumbprint(&pContext->ContextThumbprint)))
  44. {
  45. SPExternalFree(pContext);
  46. SP_RETURN(NULL);
  47. }
  48. if(pszTarget)
  49. {
  50. pContext->pszTarget = SPExternalAlloc((lstrlenW(pszTarget) + 1) * sizeof(WCHAR));
  51. if(pContext->pszTarget == NULL)
  52. {
  53. SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  54. SPExternalFree(pContext);
  55. SP_RETURN(NULL);
  56. }
  57. lstrcpyW(pContext->pszTarget, pszTarget);
  58. }
  59. pContext->dwRequestedCF = CF_EXPORT;
  60. pContext->dwRequestedCF |= CF_DOMESTIC;
  61. pContext->fCertChainsAllowed = FALSE;
  62. g_cContext++;
  63. SP_RETURN(pContext);
  64. }
  65. /************************************************************************
  66. * VOID SPContextClean(PSPContext pContext)
  67. *
  68. * Clean out everything used by the handshake (in case we want
  69. * to do another).
  70. *
  71. \***********************************************************************/
  72. BOOL
  73. SPContextClean(PSPContext pContext)
  74. {
  75. SP_BEGIN("SPContextClean");
  76. if(pContext == NULL || pContext->Magic != SP_CONTEXT_MAGIC) {
  77. DebugLog((DEB_WARN, "Attempt to delete invalid context\n"));
  78. SP_RETURN(FALSE);
  79. }
  80. if(pContext->pbEncryptedKey)
  81. {
  82. SPExternalFree(pContext->pbEncryptedKey);
  83. pContext->pbEncryptedKey = NULL;
  84. }
  85. if(pContext->pbServerKeyExchange)
  86. {
  87. SPExternalFree(pContext->pbServerKeyExchange);
  88. pContext->pbServerKeyExchange = NULL;
  89. }
  90. if(pContext->pbIssuerList)
  91. {
  92. SPExternalFree(pContext->pbIssuerList);
  93. pContext->pbIssuerList = NULL;
  94. }
  95. if(pContext->pClientHello)
  96. {
  97. SPExternalFree(pContext->pClientHello);
  98. pContext->pClientHello = NULL;
  99. }
  100. if((pContext->Flags & CONTEXT_FLAG_FULL_HANDSHAKE) &&
  101. (pContext->RipeZombie != NULL) &&
  102. (pContext->RipeZombie->pClientCred != NULL))
  103. {
  104. // We've just done a client-side full handshake in which a default
  105. // client certificate was selected. This client credential
  106. // technically belongs to the cache (so that other contexts can
  107. // query the certificate etc) but we want to free up the
  108. // application-process hProv now, while we're in the context
  109. // of the owning process.
  110. PSPCredential pClientCred = pContext->RipeZombie->pClientCred;
  111. if(pClientCred->hRemoteProv)
  112. {
  113. if(!RemoteCryptReleaseContext(
  114. pClientCred->hRemoteProv,
  115. 0))
  116. {
  117. SP_LOG_RESULT(GetLastError());
  118. }
  119. pClientCred->hRemoteProv = 0;
  120. }
  121. }
  122. pContext->fExchKey = FALSE;
  123. SP_RETURN(TRUE);
  124. }
  125. /************************************************************************
  126. * VOID SPDeleteContext(PSPContext pContext)
  127. *
  128. * Delete an existing context object.
  129. *
  130. \***********************************************************************/
  131. BOOL
  132. SPContextDelete(PSPContext pContext)
  133. {
  134. SP_BEGIN("SPContextDelete");
  135. DebugLog((DEB_TRACE, "Delete context:0x%p\n", pContext));
  136. if(pContext == NULL || pContext->Magic != SP_CONTEXT_MAGIC)
  137. {
  138. DebugLog((DEB_WARN, "Attempt to delete invalid context\n"));
  139. SP_RETURN(FALSE);
  140. }
  141. // DsysAssert((pContext->pCredGroup->dwFlags & CRED_FLAG_DELETED) == 0);
  142. if(pContext->State != SP_STATE_CONNECTED &&
  143. pContext->State != SP_STATE_SHUTDOWN)
  144. {
  145. DebugLog((DEB_WARN, "Attempting to delete an incompleted context\n"));
  146. // The context is being deleted in the middle of a handshake,
  147. // which is curious. This may be caused by the user aborting
  148. // an operation, or it may be caused by a reconfiguration of
  149. // the remote computer that caused the reconnect attempt to
  150. // fail. If it's the latter cause, then the only way to recover
  151. // is to request a full handshake next time. We have no way
  152. // of knowing which it is, so it's probably best that we kill
  153. // the current cache entry.
  154. if(pContext->RipeZombie)
  155. {
  156. pContext->RipeZombie->ZombieJuju = FALSE;
  157. pContext->RipeZombie->DeferredJuju = FALSE;
  158. }
  159. }
  160. SPContextClean(pContext);
  161. if(pContext->pszTarget)
  162. {
  163. SPExternalFree(pContext->pszTarget);
  164. pContext->pszTarget = NULL;
  165. }
  166. if(pContext->pszCredentialName)
  167. {
  168. SPExternalFree(pContext->pszCredentialName);
  169. pContext->pszCredentialName = NULL;
  170. }
  171. //
  172. // Delete session keys.
  173. //
  174. if(pContext->hReadKey)
  175. {
  176. CryptDestroyKey(pContext->hReadKey);
  177. pContext->hReadKey = 0;
  178. }
  179. if(pContext->hPendingReadKey)
  180. {
  181. CryptDestroyKey(pContext->hPendingReadKey);
  182. pContext->hPendingReadKey = 0;
  183. }
  184. if(pContext->hWriteKey)
  185. {
  186. CryptDestroyKey(pContext->hWriteKey);
  187. pContext->hWriteKey = 0;
  188. }
  189. if(pContext->hPendingWriteKey)
  190. {
  191. CryptDestroyKey(pContext->hPendingWriteKey);
  192. pContext->hPendingWriteKey = 0;
  193. }
  194. if(pContext->hReadMAC)
  195. {
  196. CryptDestroyKey(pContext->hReadMAC);
  197. pContext->hReadMAC = 0;
  198. }
  199. if(pContext->hPendingReadMAC)
  200. {
  201. CryptDestroyKey(pContext->hPendingReadMAC);
  202. pContext->hPendingReadMAC = 0;
  203. }
  204. if(pContext->hWriteMAC)
  205. {
  206. CryptDestroyKey(pContext->hWriteMAC);
  207. pContext->hWriteMAC = 0;
  208. }
  209. if(pContext->hPendingWriteMAC)
  210. {
  211. CryptDestroyKey(pContext->hPendingWriteMAC);
  212. pContext->hPendingWriteMAC = 0;
  213. }
  214. //
  215. // Delete the handshake hashes
  216. //
  217. if(pContext->hMd5Handshake)
  218. {
  219. CryptDestroyHash(pContext->hMd5Handshake);
  220. pContext->hMd5Handshake = 0;
  221. }
  222. if(pContext->hShaHandshake)
  223. {
  224. CryptDestroyHash(pContext->hShaHandshake);
  225. pContext->hShaHandshake = 0;
  226. }
  227. SPDereferenceCredential(pContext->pCredGroup, FALSE);
  228. SPCacheDereference(pContext->RipeZombie);
  229. FillMemory( pContext, sizeof( SPContext ), 0 );
  230. g_cContext--;
  231. SPExternalFree( pContext );
  232. SP_RETURN(TRUE);
  233. }
  234. /************************************************************************
  235. * SPContext SPContextSetCredentials
  236. *
  237. * Associate a set of credentials with a context.
  238. *
  239. * Returns - PSPContext pointer to context object.
  240. *
  241. \***********************************************************************/
  242. SP_STATUS
  243. SPContextSetCredentials(
  244. PSPContext pContext,
  245. PSPCredentialGroup pCred)
  246. {
  247. BOOL fNewCredentials = FALSE;
  248. SP_BEGIN("SPContextSetCredentials");
  249. if(pContext->Magic != SP_CONTEXT_MAGIC)
  250. {
  251. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  252. }
  253. //
  254. // Associate the credential group with the context.
  255. //
  256. if(pCred != pContext->pCredGroup)
  257. {
  258. if(pContext->pCredGroup)
  259. {
  260. SPDereferenceCredential(pContext->pCredGroup, FALSE);
  261. }
  262. SPReferenceCredential(pCred);
  263. pContext->pCredGroup = pCred;
  264. fNewCredentials = TRUE;
  265. }
  266. //
  267. // Set the protocol.
  268. //
  269. if(pContext->State == SP_STATE_NONE)
  270. {
  271. switch(pCred->grbitProtocol)
  272. {
  273. case SP_PROT_UNI_CLIENT:
  274. case SP_PROT_UNI_SERVER:
  275. case SP_PROT_PCT1_CLIENT:
  276. case SP_PROT_PCT1_SERVER:
  277. case SP_PROT_SSL2_CLIENT:
  278. case SP_PROT_SSL2_SERVER:
  279. case SP_PROT_SSL3_CLIENT:
  280. case SP_PROT_SSL3_SERVER:
  281. case SP_PROT_TLS1_CLIENT:
  282. case SP_PROT_TLS1_SERVER:
  283. pContext->ProtocolHandler = ServerProtocolHandler;
  284. pContext->InitiateHello = GenerateHello;
  285. break;
  286. default:
  287. SP_RETURN(SP_LOG_RESULT(PCT_INT_SPECS_MISMATCH));
  288. }
  289. }
  290. //
  291. // If the client application has supplied a new credential, then
  292. // attempt to choose a suitable client certificate to send to
  293. // the server.
  294. //
  295. if(fNewCredentials &&
  296. pContext->State == SSL3_STATE_GEN_SERVER_HELLORESP)
  297. {
  298. Ssl3CheckForExistingCred(pContext);
  299. }
  300. //
  301. // Allow the "manual cred validation" flag to be set from either
  302. // AcquireCredentialsHandle or InitializeSecurityContext.
  303. //
  304. if(pCred->dwFlags & CRED_FLAG_MANUAL_CRED_VALIDATION)
  305. {
  306. if((pContext->Flags & CONTEXT_FLAG_MUTUAL_AUTH) == 0)
  307. {
  308. pContext->Flags |= CONTEXT_FLAG_MANUAL_CRED_VALIDATION;
  309. }
  310. }
  311. SP_RETURN(PCT_ERR_OK);
  312. }
  313. SP_STATUS
  314. ContextInitCiphersFromCache(SPContext *pContext)
  315. {
  316. PSessCacheItem pZombie;
  317. SP_STATUS pctRet;
  318. pZombie = pContext->RipeZombie;
  319. pContext->pPendingCipherInfo = GetCipherInfo(pZombie->aiCipher, pZombie->dwStrength);
  320. pContext->pPendingHashInfo = GetHashInfo(pZombie->aiHash);
  321. pContext->pKeyExchInfo = GetKeyExchangeInfo(pZombie->SessExchSpec);
  322. pContext->dwPendingCipherSuiteIndex = pZombie->dwCipherSuiteIndex;
  323. if(!IsCipherAllowed(pContext,
  324. pContext->pPendingCipherInfo,
  325. pZombie->fProtocol,
  326. pZombie->dwCF))
  327. {
  328. pContext->pPendingCipherInfo = NULL;
  329. return (SP_LOG_RESULT(PCT_INT_SPECS_MISMATCH));
  330. }
  331. // Load the pending hash structure
  332. pContext->pPendingHashInfo = GetHashInfo(pZombie->aiHash);
  333. if(!IsHashAllowed(pContext,
  334. pContext->pPendingHashInfo,
  335. pZombie->fProtocol))
  336. {
  337. pContext->pPendingHashInfo = NULL;
  338. return (SP_LOG_RESULT(PCT_INT_SPECS_MISMATCH));
  339. }
  340. // load the exch info structure
  341. pContext->pKeyExchInfo = GetKeyExchangeInfo(pZombie->SessExchSpec);
  342. if(!IsExchAllowed(pContext,
  343. pContext->pKeyExchInfo,
  344. pZombie->fProtocol))
  345. {
  346. pContext->pKeyExchInfo = NULL;
  347. return (SP_LOG_RESULT(PCT_INT_SPECS_MISMATCH));
  348. }
  349. // Determine the CSP to use, based on the key exchange algorithm.
  350. pctRet = DetermineClientCSP(pContext);
  351. if(pctRet != PCT_ERR_OK)
  352. {
  353. return SP_LOG_RESULT(PCT_ERR_SPECS_MISMATCH);
  354. }
  355. #if DBG
  356. switch(pZombie->fProtocol)
  357. {
  358. case SP_PROT_PCT1_CLIENT:
  359. DebugLog((DEB_TRACE, "Protocol:PCT Client\n"));
  360. break;
  361. case SP_PROT_PCT1_SERVER:
  362. DebugLog((DEB_TRACE, "Protocol:PCT Server\n"));
  363. break;
  364. case SP_PROT_SSL2_CLIENT:
  365. DebugLog((DEB_TRACE, "Protocol:SSL2 Client\n"));
  366. break;
  367. case SP_PROT_SSL2_SERVER:
  368. DebugLog((DEB_TRACE, "Protocol:SSL2 Server\n"));
  369. break;
  370. case SP_PROT_SSL3_CLIENT:
  371. DebugLog((DEB_TRACE, "Protocol:SSL3 Client\n"));
  372. break;
  373. case SP_PROT_SSL3_SERVER:
  374. DebugLog((DEB_TRACE, "Protocol:SSL3 Server\n"));
  375. break;
  376. case SP_PROT_TLS1_CLIENT:
  377. DebugLog((DEB_TRACE, "Protocol:TLS Client\n"));
  378. break;
  379. case SP_PROT_TLS1_SERVER:
  380. DebugLog((DEB_TRACE, "Protocol:TLS Server\n"));
  381. break;
  382. default:
  383. DebugLog((DEB_TRACE, "Protocol:0x%x\n", pZombie->fProtocol));
  384. }
  385. DebugLog((DEB_TRACE, "Cipher: %s\n", pContext->pPendingCipherInfo->szName));
  386. DebugLog((DEB_TRACE, "Strength:%d\n", pContext->pPendingCipherInfo->dwStrength));
  387. DebugLog((DEB_TRACE, "Hash: %s\n", pContext->pPendingHashInfo->szName));
  388. DebugLog((DEB_TRACE, "Exchange:%s\n", pContext->pKeyExchInfo->szName));
  389. #endif
  390. return PCT_ERR_OK;
  391. }
  392. SP_STATUS
  393. DetermineClientCSP(PSPContext pContext)
  394. {
  395. if(!(pContext->RipeZombie->fProtocol & SP_PROT_CLIENTS))
  396. {
  397. return PCT_ERR_OK;
  398. }
  399. if(pContext->RipeZombie->hMasterProv != 0)
  400. {
  401. return PCT_ERR_OK;
  402. }
  403. switch(pContext->pKeyExchInfo->Spec)
  404. {
  405. case SP_EXCH_RSA_PKCS1:
  406. pContext->RipeZombie->hMasterProv = g_hRsaSchannel;
  407. break;
  408. case SP_EXCH_DH_PKCS3:
  409. pContext->RipeZombie->hMasterProv = g_hDhSchannelProv;
  410. break;
  411. default:
  412. DebugLog((DEB_ERROR, "Appropriate Schannel CSP not available!\n"));
  413. pContext->RipeZombie->hMasterProv = 0;
  414. return SP_LOG_RESULT(PCT_ERR_SPECS_MISMATCH);
  415. }
  416. return PCT_ERR_OK;
  417. }
  418. SP_STATUS
  419. ContextInitCiphers(
  420. SPContext *pContext,
  421. BOOL fRead,
  422. BOOL fWrite)
  423. {
  424. SP_BEGIN("ContextInitCiphers");
  425. if((pContext == NULL) ||
  426. (pContext->RipeZombie == NULL))
  427. {
  428. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  429. }
  430. pContext->pCipherInfo = pContext->pPendingCipherInfo;
  431. if ((NULL == pContext->pCipherInfo) || ((pContext->RipeZombie->fProtocol & pContext->pCipherInfo->fProtocol) == 0))
  432. {
  433. SP_RETURN(SP_LOG_RESULT(PCT_INT_SPECS_MISMATCH));
  434. }
  435. pContext->pHashInfo = pContext->pPendingHashInfo;
  436. if ((NULL == pContext->pHashInfo)|| ((pContext->RipeZombie->fProtocol & pContext->pHashInfo->fProtocol) == 0))
  437. {
  438. SP_RETURN(SP_LOG_RESULT(PCT_INT_SPECS_MISMATCH));
  439. }
  440. if (NULL == pContext->pKeyExchInfo)
  441. {
  442. SP_RETURN(SP_LOG_RESULT(PCT_INT_SPECS_MISMATCH));
  443. }
  444. if(fRead)
  445. {
  446. pContext->pReadCipherInfo = pContext->pPendingCipherInfo;
  447. pContext->pReadHashInfo = pContext->pPendingHashInfo;
  448. }
  449. if(fWrite)
  450. {
  451. pContext->pWriteCipherInfo = pContext->pPendingCipherInfo;
  452. pContext->pWriteHashInfo = pContext->pPendingHashInfo;
  453. }
  454. SP_RETURN(PCT_ERR_OK);
  455. }
  456. SP_STATUS
  457. SPContextDoMapping(
  458. PSPContext pContext)
  459. {
  460. PSessCacheItem pZombie;
  461. PSPCredentialGroup pCred;
  462. SP_STATUS pctRet;
  463. LONG iMapper;
  464. SP_BEGIN("SPContextDoMapping");
  465. if(pContext->Flags & CONTEXT_FLAG_NO_CERT_MAPPING)
  466. {
  467. DebugLog((DEB_TRACE, "Skip certificate mapper\n"));
  468. SP_RETURN(PCT_ERR_OK);
  469. }
  470. pZombie = pContext->RipeZombie;
  471. pCred = pContext->RipeZombie->pServerCred;
  472. for(iMapper = 0; iMapper < pCred->cMappers; iMapper++)
  473. {
  474. DebugLog((DEB_TRACE, "Invoke certificate mapper\n"));
  475. // Invoke mapper.
  476. pctRet = SslMapCredential(
  477. pCred->pahMappers[iMapper],
  478. X509_ASN_CHAIN,
  479. pZombie->pRemoteCert,
  480. NULL,
  481. &pZombie->hLocator);
  482. pCred->pahMappers[iMapper]->m_dwFlags |= SCH_FLAG_MAPPER_CALLED;
  483. if(NT_SUCCESS(pctRet))
  484. {
  485. // Mapping was successful.
  486. DebugLog((DEB_TRACE, "Mapping was successful (0x%p)\n", pZombie->hLocator));
  487. SslReferenceMapper(pCred->pahMappers[iMapper]);
  488. if(pZombie->phMapper)
  489. {
  490. SslDereferenceMapper(pZombie->phMapper);
  491. }
  492. pZombie->phMapper = pCred->pahMappers[iMapper];
  493. pZombie->LocatorStatus = SEC_E_OK;
  494. break;
  495. }
  496. else
  497. {
  498. // Mapping failed.
  499. DebugLog((DEB_TRACE, "Mapping failed (0x%x)\n", pctRet));
  500. pZombie->LocatorStatus = pctRet;
  501. }
  502. }
  503. SP_RETURN(PCT_ERR_OK);
  504. }
  505. SP_STATUS
  506. RemoveDuplicateIssuers(
  507. PBYTE pbIssuers,
  508. PDWORD pcbIssuers)
  509. {
  510. DWORD cbIssuers = *pcbIssuers;
  511. DWORD cBlob;
  512. PCRYPT_DATA_BLOB rgBlob;
  513. DWORD cbIssuer;
  514. PBYTE pbIssuer;
  515. PBYTE pbSource, pbDest;
  516. DWORD i, j;
  517. if(pbIssuers == NULL || cbIssuers < 2)
  518. {
  519. return PCT_ERR_OK;
  520. }
  521. // Count number of issuers.
  522. cBlob = 0;
  523. pbIssuer = pbIssuers;
  524. while(pbIssuer + 1 < pbIssuers + cbIssuers)
  525. {
  526. cbIssuer = MAKEWORD(pbIssuer[1], pbIssuer[0]);
  527. pbIssuer += 2 + cbIssuer;
  528. cBlob++;
  529. }
  530. // Allocate memory for blob list.
  531. rgBlob = SPExternalAlloc(cBlob * sizeof(CRYPT_DATA_BLOB));
  532. if(rgBlob == NULL)
  533. {
  534. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  535. }
  536. // Build blob list.
  537. cBlob = 0;
  538. pbIssuer = pbIssuers;
  539. while(pbIssuer + 1 < pbIssuers + cbIssuers)
  540. {
  541. cbIssuer = MAKEWORD(pbIssuer[1], pbIssuer[0]);
  542. rgBlob[cBlob].cbData = 2 + cbIssuer;
  543. rgBlob[cBlob].pbData = pbIssuer;
  544. pbIssuer += 2 + cbIssuer;
  545. cBlob++;
  546. }
  547. // Mark duplicates.
  548. for(i = 0; i < cBlob; i++)
  549. {
  550. if(rgBlob[i].pbData == NULL) continue;
  551. for(j = i + 1; j < cBlob; j++)
  552. {
  553. if(rgBlob[j].pbData == NULL) continue;
  554. if(rgBlob[i].cbData == rgBlob[j].cbData &&
  555. memcmp(rgBlob[i].pbData, rgBlob[j].pbData, rgBlob[j].cbData) == 0)
  556. {
  557. // duplicate found
  558. rgBlob[j].pbData = NULL;
  559. }
  560. }
  561. }
  562. // Compact list.
  563. pbSource = pbIssuers;
  564. pbDest = pbIssuers;
  565. for(i = 0; i < cBlob; i++)
  566. {
  567. if(rgBlob[i].pbData)
  568. {
  569. if(pbDest != pbSource)
  570. {
  571. MoveMemory(pbDest, pbSource, rgBlob[i].cbData);
  572. }
  573. pbDest += rgBlob[i].cbData;
  574. }
  575. pbSource += rgBlob[i].cbData;
  576. }
  577. *pcbIssuers = (DWORD)(pbDest - pbIssuers);
  578. // Free blob list.
  579. SPExternalFree(rgBlob);
  580. return PCT_ERR_OK;
  581. }
  582. SP_STATUS
  583. SPContextGetIssuers(
  584. PSPCredentialGroup pCredGroup)
  585. {
  586. LONG i;
  587. PBYTE pbIssuerList;
  588. DWORD cbIssuerList;
  589. PBYTE pbIssuer;
  590. DWORD cbIssuer;
  591. PBYTE pbNew;
  592. DWORD Status;
  593. LockCredentialExclusive(pCredGroup);
  594. if((pCredGroup->pbTrustedIssuers != NULL) &&
  595. !(pCredGroup->dwFlags & CRED_FLAG_UPDATE_ISSUER_LIST))
  596. {
  597. // Issuer list has already been built.
  598. Status = PCT_ERR_OK;
  599. goto cleanup;
  600. }
  601. // Free existing issuer list.
  602. if(pCredGroup->pbTrustedIssuers)
  603. {
  604. LocalFree(pCredGroup->pbTrustedIssuers);
  605. pCredGroup->pbTrustedIssuers = NULL;
  606. pCredGroup->cbTrustedIssuers = 0;
  607. }
  608. pCredGroup->dwFlags &= ~CRED_FLAG_UPDATE_ISSUER_LIST;
  609. //
  610. // Get issuers from application-specified ROOT store.
  611. //
  612. pbIssuerList = NULL;
  613. cbIssuerList = 0;
  614. while(pCredGroup->hApplicationRoots)
  615. {
  616. Status = ExtractIssuerNamesFromStore(pCredGroup->hApplicationRoots,
  617. NULL,
  618. &cbIssuerList);
  619. if(Status != PCT_ERR_OK)
  620. {
  621. break;
  622. }
  623. pbIssuerList = LocalAlloc(LPTR, cbIssuerList);
  624. if(pbIssuerList == NULL)
  625. {
  626. cbIssuerList = 0;
  627. break;
  628. }
  629. Status = ExtractIssuerNamesFromStore(pCredGroup->hApplicationRoots,
  630. pbIssuerList,
  631. &cbIssuerList);
  632. if(Status != PCT_ERR_OK)
  633. {
  634. LocalFree(pbIssuerList);
  635. pbIssuerList = NULL;
  636. cbIssuerList = 0;
  637. }
  638. break;
  639. }
  640. //
  641. // Call each of the mappers in turn, building a large
  642. // list of all trusted issuers.
  643. //
  644. for(i = 0; i < pCredGroup->cMappers; i++)
  645. {
  646. Status = SslGetMapperIssuerList(pCredGroup->pahMappers[i],
  647. &pbIssuer,
  648. &cbIssuer);
  649. if(!NT_SUCCESS(Status))
  650. {
  651. continue;
  652. }
  653. if(pbIssuerList == NULL)
  654. {
  655. pbIssuerList = LocalAlloc(LPTR, cbIssuer);
  656. if(pbIssuerList == NULL)
  657. {
  658. SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  659. break;
  660. }
  661. }
  662. else
  663. {
  664. pbNew = LocalReAlloc(pbIssuerList,
  665. cbIssuerList + cbIssuer,
  666. LMEM_MOVEABLE);
  667. if(pbNew == NULL)
  668. {
  669. SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  670. break;
  671. }
  672. pbIssuerList = pbNew;
  673. }
  674. CopyMemory(pbIssuerList + cbIssuerList,
  675. pbIssuer,
  676. cbIssuer);
  677. cbIssuerList += cbIssuer;
  678. SPExternalFree(pbIssuer);
  679. }
  680. //
  681. // Remove duplicates from list.
  682. //
  683. if(pbIssuerList)
  684. {
  685. Status = RemoveDuplicateIssuers(pbIssuerList, &cbIssuerList);
  686. if(!NT_SUCCESS(Status))
  687. {
  688. LocalFree(pbIssuerList);
  689. goto cleanup;
  690. }
  691. }
  692. //
  693. // Check for issuer list overflow
  694. //
  695. if((pbIssuerList != NULL) && (cbIssuerList > SSL3_MAX_ISSUER_LIST))
  696. {
  697. DWORD cbList = 0;
  698. PBYTE pbList = pbIssuerList;
  699. DWORD cbIssuer;
  700. while(cbList < cbIssuerList)
  701. {
  702. cbIssuer = COMBINEBYTES(pbList[0], pbList[1]);
  703. if(cbList + 2 + cbIssuer > SSL3_MAX_ISSUER_LIST)
  704. {
  705. // This issuer puts us over the limit.
  706. cbIssuerList = cbList;
  707. break;
  708. }
  709. cbList += 2 + cbIssuer;
  710. pbList += 2 + cbIssuer;
  711. }
  712. // Log warning event
  713. LogIssuerOverflowEvent();
  714. }
  715. pCredGroup->cbTrustedIssuers = cbIssuerList; // do not reverse these lines
  716. pCredGroup->pbTrustedIssuers = pbIssuerList;
  717. Status = PCT_ERR_OK;
  718. cleanup:
  719. UnlockCredential(pCredGroup);
  720. return Status;
  721. }
  722. SP_STATUS
  723. SPPickClientCertificate(
  724. PSPContext pContext,
  725. DWORD dwExchSpec)
  726. {
  727. PSPCredentialGroup pCred;
  728. PSPCredential pCurrentCred;
  729. SP_STATUS pctRet;
  730. PLIST_ENTRY pList;
  731. pCred = pContext->pCredGroup;
  732. if((pCred == NULL) || (pCred->CredCount == 0))
  733. {
  734. return SP_LOG_RESULT(PCT_ERR_SPECS_MISMATCH);
  735. }
  736. pContext->pActiveClientCred = NULL;
  737. pctRet = PCT_ERR_SPECS_MISMATCH;
  738. LockCredentialShared(pCred);
  739. pList = pCred->CredList.Flink ;
  740. while ( pList != &pCred->CredList )
  741. {
  742. pCurrentCred = CONTAINING_RECORD( pList, SPCredential, ListEntry.Flink );
  743. pList = pList->Flink ;
  744. if(pCurrentCred->pCert == NULL)
  745. {
  746. continue;
  747. }
  748. if(pCurrentCred->pPublicKey == NULL)
  749. {
  750. continue;
  751. }
  752. // Does this cert contain the proper key type.
  753. if(dwExchSpec != pCurrentCred->dwExchSpec)
  754. {
  755. continue; // try the next cert.
  756. }
  757. // Does this cert have the proper encoding type?
  758. if(pCurrentCred->pCert->dwCertEncodingType != X509_ASN_ENCODING)
  759. {
  760. continue;
  761. }
  762. // WE FOUND ONE
  763. pContext->pActiveClientCred = pCurrentCred;
  764. pctRet = PCT_ERR_OK;
  765. break;
  766. }
  767. UnlockCredential(pCred);
  768. return pctRet;
  769. }
  770. SP_STATUS
  771. SPPickServerCertificate(
  772. PSPContext pContext,
  773. DWORD dwExchSpec)
  774. {
  775. PSPCredentialGroup pCred;
  776. PSPCredential pCurrentCred;
  777. SP_STATUS pctRet;
  778. PLIST_ENTRY pList;
  779. //
  780. // Get pointer to server credential
  781. //
  782. pCred = pContext->RipeZombie->pServerCred;
  783. if((pCred == NULL) || (pCred->CredCount == 0))
  784. {
  785. return SP_LOG_RESULT(PCT_ERR_SPECS_MISMATCH);
  786. }
  787. DsysAssert((pContext->RipeZombie->dwFlags & SP_CACHE_FLAG_READONLY) == 0);
  788. pContext->RipeZombie->pActiveServerCred = NULL;
  789. //
  790. // Check for certificate renewal.
  791. //
  792. if(pCred->dwFlags & CRED_FLAG_CHECK_FOR_RENEWAL)
  793. {
  794. CheckForCredentialRenewal(pCred);
  795. }
  796. //
  797. // Enumerate server certificates, looking for a suitable one.
  798. //
  799. pctRet = PCT_ERR_SPECS_MISMATCH;
  800. LockCredentialShared(pCred);
  801. pList = pCred->CredList.Flink ;
  802. while ( pList != &pCred->CredList )
  803. {
  804. pCurrentCred = CONTAINING_RECORD( pList, SPCredential, ListEntry.Flink );
  805. pList = pList->Flink ;
  806. if(pCurrentCred->pCert == NULL)
  807. {
  808. continue;
  809. }
  810. if(pCurrentCred->pPublicKey == NULL)
  811. {
  812. continue;
  813. }
  814. // Does this cert contain the proper key type.
  815. if(dwExchSpec != pCurrentCred->dwExchSpec)
  816. {
  817. continue; // try the next cert.
  818. }
  819. // Does this cert have the proper encoding type?
  820. if(pCurrentCred->pCert->dwCertEncodingType != X509_ASN_ENCODING)
  821. {
  822. continue;
  823. }
  824. // WE FOUND ONE
  825. pContext->RipeZombie->pActiveServerCred = pCurrentCred;
  826. pContext->RipeZombie->CredThumbprint = pCred->CredThumbprint;
  827. pContext->RipeZombie->CertThumbprint = pCurrentCred->CertThumbprint;
  828. // Set "master" provider handle to current credential's. Note that
  829. // SSL3 will sometimes overide this selection in favor of its
  830. // ephemeral key pair.
  831. pContext->RipeZombie->hMasterProv = pCurrentCred->hProv;
  832. pctRet = PCT_ERR_OK;
  833. break;
  834. }
  835. UnlockCredential(pCred);
  836. return pctRet;
  837. }
  838. // This routine is called by the user process. It frees a context
  839. // structure that was originally allocated by the LSA process,
  840. // and passed over via the SPContextDeserialize routine.
  841. BOOL
  842. LsaContextDelete(PSPContext pContext)
  843. {
  844. if(pContext)
  845. {
  846. if(pContext->hReadKey)
  847. {
  848. CryptDestroyKey(pContext->hReadKey);
  849. pContext->hReadKey = 0;
  850. }
  851. if(pContext->hReadMAC)
  852. {
  853. CryptDestroyKey(pContext->hReadMAC);
  854. pContext->hReadMAC = 0;
  855. }
  856. if(pContext->hWriteKey)
  857. {
  858. CryptDestroyKey(pContext->hWriteKey);
  859. pContext->hWriteKey = 0;
  860. }
  861. if(pContext->hWriteMAC)
  862. {
  863. CryptDestroyKey(pContext->hWriteMAC);
  864. pContext->hWriteMAC = 0;
  865. }
  866. if(pContext->RipeZombie)
  867. {
  868. if(pContext->RipeZombie->hLocator)
  869. {
  870. NtClose((HANDLE)pContext->RipeZombie->hLocator);
  871. pContext->RipeZombie->hLocator = 0;
  872. }
  873. if(pContext->RipeZombie->pbServerCertificate)
  874. {
  875. SPExternalFree(pContext->RipeZombie->pbServerCertificate);
  876. pContext->RipeZombie->pbServerCertificate = NULL;
  877. }
  878. }
  879. }
  880. return TRUE;
  881. }
  882. /*
  883. *
  884. * Misc Utility functions.
  885. *
  886. */
  887. #if DBG
  888. typedef struct _DbgMapCrypto {
  889. DWORD C;
  890. PSTR psz;
  891. } DbgMapCrypto;
  892. DbgMapCrypto DbgCryptoNames[] = { {CALG_RC4, "RC4 "},
  893. };
  894. CHAR DbgNameSpace[100];
  895. PSTR DbgAlgNames[] = { "Basic RSA", "RSA with MD2", "RSA with MD5", "RC4 stream"};
  896. #define AlgName(x) ((x < sizeof(DbgAlgNames) / sizeof(PSTR)) ? DbgAlgNames[x] : "Unknown")
  897. PSTR
  898. DbgGetNameOfCrypto(DWORD x)
  899. {
  900. int i;
  901. for (i = 0; i < sizeof(DbgCryptoNames) / sizeof(DbgMapCrypto) ; i++ )
  902. {
  903. if (x == DbgCryptoNames[i].C)
  904. {
  905. wsprintf(DbgNameSpace, "%s",
  906. (DbgCryptoNames[i].psz));
  907. return DbgNameSpace;
  908. }
  909. }
  910. return("Unknown");
  911. }
  912. #endif