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.

1684 lines
45 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name :
  4. sslcontext.cxx
  5. Abstract:
  6. SSL stream context for the client SSL support.
  7. Author:
  8. Rajesh Sundaram (rajeshsu) 1-April-2001.
  9. Environment:
  10. Win32 - User Mode
  11. Project:
  12. Stream Filter Worker Process
  13. --*/
  14. #include "precomp.hxx"
  15. // BUGBUG: close connection to server thro SSPI when cert validation fails
  16. // BUGBUG: Explore - server cert alert messages
  17. SECURITY_STATUS
  18. CreateCredentialsHandle(
  19. IN DWORD dwProtocolType,
  20. IN DWORD dwFlags,
  21. IN PCCERT_CONTEXT pCertContext,
  22. OUT PCredHandle phClienCred
  23. );
  24. UC_SSL_STREAM_CONTEXT::UC_SSL_STREAM_CONTEXT(
  25. FILTER_CHANNEL_CONTEXT *pUcContext
  26. )
  27. : STREAM_CONTEXT (pUcContext),
  28. _pServerName (0),
  29. _ServerNameLength (0),
  30. _SslProtocolVersion (0),
  31. _sslState (UC_SSL_STATE_HANDSHAKE_START),
  32. _fRenegotiate (FALSE),
  33. _fValidContext (FALSE),
  34. _fValidClientCred (FALSE),
  35. _cbReReadOffset (0),
  36. _pServerCert (NULL),
  37. _pSerializedCert (NULL),
  38. _SerializedCertLength (0),
  39. _pSerializedStore (NULL),
  40. _SerializedStoreLength (0),
  41. _pClientCert (NULL),
  42. _cbDecrypted (0),
  43. _ValidateServerCertFlag (0),
  44. _fValidServerCertInfo (FALSE)
  45. {
  46. //
  47. // Initialize security buffer structs
  48. //
  49. //
  50. // Setup buffer to hold incoming raw data
  51. //
  52. _Message.ulVersion = SECBUFFER_VERSION;
  53. _Message.cBuffers = 4;
  54. _Message.pBuffers = _Buffers;
  55. _Buffers[0].BufferType = SECBUFFER_EMPTY;
  56. _Buffers[1].BufferType = SECBUFFER_EMPTY;
  57. _Buffers[2].BufferType = SECBUFFER_EMPTY;
  58. _Buffers[3].BufferType = SECBUFFER_EMPTY;
  59. //
  60. // Setup buffer for ISC to return raw data to be sent to client
  61. //
  62. _MessageOut.ulVersion = SECBUFFER_VERSION;
  63. _MessageOut.cBuffers = 4;
  64. _MessageOut.pBuffers = _OutBuffers;
  65. _OutBuffers[0].BufferType = SECBUFFER_EMPTY;
  66. _OutBuffers[1].BufferType = SECBUFFER_EMPTY;
  67. _OutBuffers[2].BufferType = SECBUFFER_EMPTY;
  68. _OutBuffers[3].BufferType = SECBUFFER_EMPTY;
  69. //
  70. // Setup buffer for app data to be encrypted
  71. //
  72. _EncryptMessage.ulVersion = SECBUFFER_VERSION;
  73. _EncryptMessage.cBuffers = 4;
  74. _EncryptMessage.pBuffers = _EncryptBuffers;
  75. _EncryptBuffers[0].BufferType = SECBUFFER_EMPTY;
  76. _EncryptBuffers[1].BufferType = SECBUFFER_EMPTY;
  77. _EncryptBuffers[2].BufferType = SECBUFFER_EMPTY;
  78. _EncryptBuffers[3].BufferType = SECBUFFER_EMPTY;
  79. //
  80. // Zero out data structures
  81. //
  82. ZeroMemory(&_hContext, sizeof(_hContext));
  83. ZeroMemory(&_hClientCred, sizeof(_hClientCred));
  84. ZeroMemory(&_ucServerCertInfo, sizeof(_ucServerCertInfo));
  85. ZeroMemory(&_IssuerListInfo, sizeof(_IssuerListInfo));
  86. }
  87. UC_SSL_STREAM_CONTEXT::~UC_SSL_STREAM_CONTEXT()
  88. {
  89. if (_fValidContext)
  90. {
  91. DeleteSecurityContext(&_hContext);
  92. _fValidContext = FALSE;
  93. }
  94. if (_fValidClientCred)
  95. {
  96. FreeCredentialsHandle(&_hClientCred);
  97. _fValidClientCred = FALSE;
  98. }
  99. if (_pServerCert != NULL)
  100. {
  101. CertFreeCertificateContext(_pServerCert);
  102. _pServerCert = NULL;
  103. }
  104. if (_pClientCert != NULL)
  105. {
  106. CertFreeCertificateContext(_pClientCert);
  107. _pClientCert = NULL;
  108. }
  109. if (_pServerName != _ServerNameBuffer && _pServerName)
  110. {
  111. delete[] _pServerName;
  112. _pServerName = NULL;
  113. }
  114. if (_IssuerListInfo.aIssuers)
  115. {
  116. DBG_ASSERT(_IssuerListInfo.cIssuers);
  117. FreeContextBuffer(_IssuerListInfo.aIssuers);
  118. _IssuerListInfo.aIssuers = NULL;
  119. }
  120. if (_pSerializedCert)
  121. {
  122. delete[] _pSerializedCert;
  123. _pSerializedCert = NULL;
  124. _SerializedCertLength = 0;
  125. }
  126. if (_pSerializedStore)
  127. {
  128. delete[] _pSerializedStore;
  129. _pSerializedStore = NULL;
  130. _SerializedStoreLength = 0;
  131. }
  132. }
  133. /****************************************************************************++
  134. Routine Description:
  135. Handle a new raw connection
  136. Arguments:
  137. pConnectionInfo - The magic connection information
  138. Return Value:
  139. HRESULT
  140. --****************************************************************************/
  141. HRESULT
  142. UC_SSL_STREAM_CONTEXT::ProcessNewConnection(
  143. CONNECTION_INFO *pConnectionInfo,
  144. ENDPOINT_CONFIG * /*pEndpointConfig*/
  145. )
  146. {
  147. SECURITY_STATUS secStatus;
  148. DBG_ASSERT(_sslState == UC_SSL_STATE_HANDSHAKE_START);
  149. QueryFiltChannelContext()->SetIsSecure( TRUE );
  150. DBG_ASSERT(pConnectionInfo->pClientSSLContext);
  151. // Protocol version
  152. _SslProtocolVersion = (DWORD)
  153. pConnectionInfo->pClientSSLContext->SslProtocolVersion;
  154. if (_SslProtocolVersion == 0)
  155. {
  156. // By default, all protocols are enabled.
  157. _SslProtocolVersion = SP_PROT_CLIENTS;
  158. }
  159. // Client Cert
  160. _pClientCert = (PCCERT_CONTEXT)
  161. pConnectionInfo->pClientSSLContext->pClientCertContext;
  162. if (_pClientCert)
  163. {
  164. // Bump up the reference count on the certificate context
  165. _pClientCert = CertDuplicateCertificateContext(_pClientCert);
  166. }
  167. // Server cert validation
  168. switch (pConnectionInfo->pClientSSLContext->ServerCertValidation)
  169. {
  170. case HttpSslServerCertValidationIgnore:
  171. case HttpSslServerCertValidationManual:
  172. case HttpSslServerCertValidationManualOnce:
  173. _ValidateServerCertFlag = SCH_CRED_MANUAL_CRED_VALIDATION;
  174. break;
  175. case HttpSslServerCertValidationAutomatic:
  176. _ValidateServerCertFlag = SCH_CRED_AUTO_CRED_VALIDATION;
  177. break;
  178. default:
  179. // Catch this invalid case
  180. DBG_ASSERT( FALSE );
  181. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  182. break;
  183. }
  184. //
  185. // Store the server name.
  186. //
  187. _ServerNameLength = pConnectionInfo->pClientSSLContext->ServerNameLength+1;
  188. if (_ServerNameLength <= UC_SERVER_NAME_BUFFER_SIZE * sizeof(WCHAR))
  189. {
  190. _pServerName = _ServerNameBuffer;
  191. }
  192. else
  193. {
  194. _pServerName = new WCHAR [_ServerNameLength];
  195. if (!_pServerName)
  196. {
  197. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  198. }
  199. }
  200. // Copy server name
  201. memcpy(_pServerName,
  202. pConnectionInfo->pClientSSLContext->ServerName,
  203. pConnectionInfo->pClientSSLContext->ServerNameLength);
  204. // Null termination
  205. _pServerName[_ServerNameLength] = L'\0';
  206. //
  207. // Now create client credential handle
  208. //
  209. secStatus = CreateCredentialsHandle(_SslProtocolVersion,
  210. _ValidateServerCertFlag,
  211. _pClientCert,
  212. &_hClientCred);
  213. if (secStatus != SEC_E_OK)
  214. {
  215. DBGPRINTF((DBG_CONTEXT, "CreateCredentialsHandle failed 0x%x\n",
  216. secStatus));
  217. return secStatus;
  218. }
  219. _fValidClientCred = TRUE;
  220. DBGPRINTF((DBG_CONTEXT,
  221. "ProcessNewConnection: Got a new connection for server %ws \n",
  222. _pServerName));
  223. // Everything was Okay
  224. return S_OK;
  225. }
  226. /****************************************************************************++
  227. Routine Description:
  228. Handle an SSL read completion off the wire
  229. Arguments:
  230. pRawStreamInfo - Points to input stream and size
  231. pfReadMore - Set to TRUE if we should read more
  232. pfComplete - Set to TRUE if we should disconnect
  233. Return Value:
  234. HRESULT
  235. --****************************************************************************/
  236. HRESULT
  237. UC_SSL_STREAM_CONTEXT::ProcessRawReadData(
  238. RAW_STREAM_INFO *pRawStreamInfo,
  239. BOOL *pfReadMore,
  240. BOOL *pfComplete
  241. )
  242. {
  243. HRESULT hr = S_OK;
  244. BOOL fExtraData = FALSE;
  245. //
  246. // Loop for extra data
  247. // Sometimes one RawStreamInfo buffer may contain multiple blobs
  248. // some to be processed by DoHandshake() and some by DoDecrypt()
  249. // The do-while loop enables switching between these 2 functions as needed
  250. //
  251. do
  252. {
  253. fExtraData = FALSE;
  254. *pfReadMore = FALSE;
  255. *pfComplete = FALSE;
  256. //
  257. // Either continue handshake or immediate decrypt data
  258. //
  259. switch (_sslState)
  260. {
  261. case UC_SSL_STATE_HANDSHAKE_START:
  262. case UC_SSL_STATE_HANDSHAKE_IN_PROGRESS:
  263. DBGPRINTF((DBG_CONTEXT,
  264. "ProcessRawReadData (Wire): _sslState %d, Handshake \n",
  265. _sslState));
  266. hr = DoHandshake(pRawStreamInfo,
  267. pfReadMore,
  268. pfComplete,
  269. &fExtraData);
  270. break;
  271. case UC_SSL_STATE_HANDSHAKE_COMPLETE:
  272. DBGPRINTF((DBG_CONTEXT,
  273. "ProcessRawReadData (Wire): _sslState %d, Decrypt \n",
  274. _sslState));
  275. hr = DoDecrypt(pRawStreamInfo,
  276. pfReadMore,
  277. pfComplete,
  278. &fExtraData);
  279. break;
  280. default:
  281. DBG_ASSERT(FALSE);
  282. }
  283. if (FAILED(hr))
  284. {
  285. DBGPRINTF((DBG_CONTEXT,
  286. "ProcessRawReadData (Wire): _sslState %d, failed %x\n",
  287. _sslState, hr));
  288. break;
  289. }
  290. //
  291. // Is there still some extra data to be processed?
  292. //
  293. } while(fExtraData);
  294. return hr;
  295. }
  296. /****************************************************************************++
  297. Routine Description:
  298. Called on read completion from app
  299. Arguments:
  300. pRawStreamInfo - Points to input stream and size
  301. pfComplete - Set to TRUE if we should disconnect
  302. Return Value:
  303. HRESULT
  304. --****************************************************************************/
  305. HRESULT
  306. UC_SSL_STREAM_CONTEXT::ProcessRawWriteData(
  307. RAW_STREAM_INFO *pRawStreamInfo,
  308. BOOL *pfComplete
  309. )
  310. {
  311. HRESULT hr;
  312. DBG_ASSERT(QueryFiltChannelContext()->QueryFilterBufferType() ==
  313. HttpFilterBufferHttpStream);
  314. DBGPRINTF((DBG_CONTEXT,
  315. "ProcessRawWriteData (App): _sslState %d, Encrypt \n", _sslState));
  316. hr = DoEncrypt(pRawStreamInfo,
  317. pfComplete);
  318. if (FAILED(hr))
  319. {
  320. DBGPRINTF((DBG_CONTEXT,
  321. "ProcessRawWriteData(App): _sslState %d, failed %x\n",
  322. _sslState,hr));
  323. }
  324. return hr;
  325. }
  326. HRESULT
  327. UC_SSL_STREAM_CONTEXT::DoHandshakeCompleted()
  328. {
  329. HRESULT hr = S_OK;
  330. SECURITY_STATUS secStatus = SEC_E_OK;
  331. SecPkgContext_StreamSizes StreamSizes;
  332. HTTP_FILTER_BUFFER ulFilterBuffer;
  333. _sslState = UC_SSL_STATE_HANDSHAKE_COMPLETE;
  334. DBGPRINTF((DBG_CONTEXT, "DoHandShakeCompleted Enter\n"));
  335. //
  336. // Get some buffer size info for this connection. We only need
  337. // to do this on completion of the initial handshake, and NOT
  338. // subsequent renegotiation handshake (if any)
  339. //
  340. if (!_cbHeader && !_cbTrailer)
  341. {
  342. secStatus = QueryContextAttributes(&_hContext,
  343. SECPKG_ATTR_STREAM_SIZES,
  344. &StreamSizes);
  345. if (FAILED(secStatus))
  346. {
  347. DBGPRINTF((DBG_CONTEXT, "QueryContextAttributes failed! - 0x%x\n",
  348. secStatus ));
  349. return secStatus;
  350. }
  351. _cbHeader = StreamSizes.cbHeader;
  352. _cbTrailer = StreamSizes.cbTrailer;
  353. _cbBlockSize = StreamSizes.cbBlockSize;
  354. _cbMaximumMessage = StreamSizes.cbMaximumMessage;
  355. }
  356. if (!_fValidServerCertInfo)
  357. {
  358. //
  359. // Build up a message for the application indicating stuff
  360. // about the negotiated connection
  361. //
  362. hr = BuildServerCertInfo(SEC_E_OK, TRUE, FALSE);
  363. if ( FAILED( hr ) )
  364. {
  365. DBGPRINTF((DBG_CONTEXT,
  366. "BuildServerCertInfo failed! - 0x%x\n",
  367. hr));
  368. return hr;
  369. }
  370. }
  371. DBG_ASSERT(_fValidServerCertInfo);
  372. ulFilterBuffer.BufferType = HttpFilterBufferSslServerCert;
  373. ulFilterBuffer.pBuffer = (PBYTE) &_ucServerCertInfo;
  374. ulFilterBuffer.BufferSize = sizeof( _ucServerCertInfo );
  375. //
  376. // Write the message to the application
  377. //
  378. hr = QueryFiltChannelContext()->DoAppWrite(UL_CONTEXT_FLAG_SYNC,
  379. &ulFilterBuffer,
  380. NULL);
  381. // No longer have a valid server cert info.
  382. _fValidServerCertInfo = FALSE;
  383. return hr;
  384. }
  385. /****************************************************************************++
  386. Routine Description:
  387. Do the SSL handshake for the client.
  388. Arguments:
  389. pRawStreamInfo - Raw data buffer
  390. pfReadMore - Set to true if more data should be read
  391. pfComplete - Set to true if we should disconnect
  392. Return Value:
  393. HRESULT
  394. --****************************************************************************/
  395. HRESULT
  396. UC_SSL_STREAM_CONTEXT::DoHandshake(
  397. RAW_STREAM_INFO *pRawStreamInfo,
  398. BOOL *pfReadMore,
  399. BOOL *pfComplete,
  400. BOOL *pfExtraData
  401. )
  402. {
  403. DWORD dwSSPIFlags;
  404. DWORD dwSSPIOutFlags;
  405. SECURITY_STATUS scRet = SEC_E_OK;
  406. TimeStamp tsExpiry;
  407. HRESULT hr = S_OK;
  408. HTTP_FILTER_BUFFER ulFilterBuffer;
  409. *pfReadMore = FALSE;
  410. *pfComplete = FALSE;
  411. *pfExtraData = FALSE;
  412. //
  413. // Setup a call to InitializeSecurityContext
  414. //
  415. dwSSPIFlags = UC_SSL_ISC_FLAGS |
  416. ((_ValidateServerCertFlag == SCH_CRED_MANUAL_CRED_VALIDATION)?
  417. ISC_REQ_MANUAL_CRED_VALIDATION : 0);
  418. //
  419. // First, set up the InBuffers.
  420. //
  421. _Buffers[0].pvBuffer = pRawStreamInfo->pbBuffer + _cbReReadOffset;
  422. _Buffers[0].BufferType = SECBUFFER_TOKEN;
  423. _Buffers[0].cbBuffer = pRawStreamInfo->cbData - _cbReReadOffset;
  424. _Buffers[1].BufferType = SECBUFFER_EMPTY;
  425. _Buffers[2].BufferType = SECBUFFER_EMPTY;
  426. _Buffers[3].BufferType = SECBUFFER_EMPTY;
  427. //
  428. // Then, the out buffers.
  429. //
  430. _OutBuffers[0].pvBuffer = NULL;
  431. _OutBuffers[0].cbBuffer = 0;
  432. _OutBuffers[0].BufferType = SECBUFFER_EMPTY;
  433. _OutBuffers[1].BufferType = SECBUFFER_EMPTY;
  434. _OutBuffers[2].BufferType = SECBUFFER_EMPTY;
  435. _OutBuffers[3].BufferType = SECBUFFER_EMPTY;
  436. if (_sslState == UC_SSL_STATE_HANDSHAKE_START)
  437. {
  438. scRet = InitializeSecurityContext(
  439. &_hClientCred,
  440. NULL,
  441. _pServerName,
  442. dwSSPIFlags,
  443. 0,
  444. SECURITY_NATIVE_DREP,
  445. NULL,
  446. 0,
  447. &_hContext,
  448. &_MessageOut,
  449. &dwSSPIOutFlags,
  450. &tsExpiry
  451. );
  452. DBGPRINTF((DBG_CONTEXT,
  453. "[DoHandshake]:1st InitializeSecurityContext : Return 0x%x \n",
  454. scRet));
  455. if (SUCCEEDED(scRet))
  456. {
  457. _cbHeader = 0;
  458. _cbTrailer = 0;
  459. _cbBlockSize = 0;
  460. _cbMaximumMessage = 0;
  461. _fValidContext = TRUE;
  462. _sslState = UC_SSL_STATE_HANDSHAKE_IN_PROGRESS;
  463. }
  464. }
  465. else
  466. {
  467. DBG_ASSERT(_sslState == UC_SSL_STATE_HANDSHAKE_IN_PROGRESS);
  468. //
  469. // We have already called InitializeSecurityContext once.
  470. //
  471. scRet = InitializeSecurityContext(
  472. &_hClientCred,
  473. &_hContext,
  474. _pServerName,
  475. dwSSPIFlags,
  476. 0,
  477. SECURITY_NATIVE_DREP,
  478. &_Message,
  479. 0,
  480. &_hContext,
  481. &_MessageOut,
  482. &dwSSPIOutFlags,
  483. &tsExpiry
  484. );
  485. DBGPRINTF((DBG_CONTEXT,
  486. "[DoHandshake]:2nd InitializeSecurityContext 0x%x\n",
  487. scRet));
  488. }
  489. if (SUCCEEDED(scRet))
  490. {
  491. //
  492. // Send response to the server if there is one.
  493. //
  494. if (_OutBuffers[0].pvBuffer && _OutBuffers[0].cbBuffer != 0)
  495. {
  496. hr = QueryFiltChannelContext()->DoRawWrite(UL_CONTEXT_FLAG_SYNC,
  497. _OutBuffers[0].pvBuffer,
  498. _OutBuffers[0].cbBuffer,
  499. NULL);
  500. if (FAILED(hr))
  501. {
  502. goto ExitPoint;
  503. }
  504. }
  505. if (scRet == SEC_E_OK)
  506. {
  507. //
  508. // Done with handshake.
  509. //
  510. hr = DoHandshakeCompleted();
  511. if (FAILED(hr))
  512. {
  513. goto ExitPoint;
  514. }
  515. }
  516. else if (scRet == SEC_I_INCOMPLETE_CREDENTIALS)
  517. {
  518. DBGPRINTF((DBG_CONTEXT, "[DoHandshake]:Client cert needed!\n"));
  519. if (_fRenegotiate)
  520. {
  521. //
  522. // Get issuer list from schannel
  523. //
  524. hr = BuildServerCertInfo(SEC_E_OK, TRUE, TRUE);
  525. if (FAILED(hr))
  526. {
  527. goto ErrorPoint;
  528. }
  529. }
  530. //
  531. // Caller will resume handshake
  532. //
  533. *pfExtraData = TRUE;
  534. //
  535. // caller has to detect that some data is
  536. // still in the buffer not processed and
  537. //
  538. hr = S_OK;
  539. goto ExitPoint;
  540. }
  541. //
  542. // If the input buffer has more info to be SChannelized, then do it
  543. // now. If we haven't completed the handshake, call DoHandshake again,
  544. // else, call DoEncrypt
  545. //
  546. if (_Buffers[1].BufferType == SECBUFFER_EXTRA)
  547. {
  548. //
  549. // We better have valid extra data
  550. // only cbBuffer is used, pvBuffer is not used with SECBUFFER_EXTRA
  551. //
  552. DBG_ASSERT( _Buffers[ 1 ].cbBuffer != 0 );
  553. //
  554. // Move extra data right after decrypted data (if any)
  555. //
  556. memmove( pRawStreamInfo->pbBuffer + _cbDecrypted,
  557. pRawStreamInfo->pbBuffer + pRawStreamInfo->cbData
  558. - _Buffers[ 1 ].cbBuffer,
  559. _Buffers[ 1 ].cbBuffer);
  560. //
  561. // Now we have to adjust pRawStreamInfo->cbData and _cbReReadOffset
  562. //
  563. pRawStreamInfo->cbData = ( _cbDecrypted + _Buffers[ 1 ].cbBuffer );
  564. _cbReReadOffset = _cbDecrypted;
  565. *pfExtraData = TRUE;
  566. //
  567. // caller has to detect that some data is
  568. // still in the buffer not processed and
  569. //
  570. hr = S_OK;
  571. goto ExitPoint;
  572. }
  573. else
  574. {
  575. //
  576. // There is no extra data to be processed
  577. // If we got here as the result of renegotiation
  578. // there may be some decrypted data in StreamInfo buffer already
  579. //
  580. // (without renegotiation _cbDecrypted must always be 0
  581. // because SEC_I_RENEGOTIATE is the only way to get
  582. // from DoDecrypt() to DoHandshake() )
  583. //
  584. DBG_ASSERT ( _fRenegotiate || _cbDecrypted == 0 );
  585. pRawStreamInfo->cbData = _cbDecrypted;
  586. _cbReReadOffset = _cbDecrypted;
  587. if ( _sslState != UC_SSL_STATE_HANDSHAKE_COMPLETE )
  588. {
  589. //
  590. // If we have no more data, and we still haven't completed the
  591. // handshake, then read some more data
  592. //
  593. *pfReadMore = TRUE;
  594. hr = S_OK;
  595. goto ExitPoint;
  596. }
  597. }
  598. //
  599. // final return from DoHandshake on handshake completion
  600. // Cleanup _cbDecrypted and _cbReReadOffset to make
  601. // sure that next ProcessRawReadData() will work fine
  602. //
  603. _cbReReadOffset = 0;
  604. _cbDecrypted = 0;
  605. hr = S_OK;
  606. goto ExitPoint;
  607. }
  608. else
  609. {
  610. //
  611. // Does Schannel requires more data?
  612. //
  613. if ( scRet == SEC_E_INCOMPLETE_MESSAGE )
  614. {
  615. *pfReadMore = TRUE;
  616. hr = S_OK;
  617. goto ExitPoint;
  618. }
  619. if (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR)
  620. {
  621. if (_OutBuffers[ 0 ].pvBuffer!= NULL &&
  622. _OutBuffers[ 0 ].cbBuffer != 0 )
  623. {
  624. hr = QueryFiltChannelContext()->DoRawWrite(
  625. UL_CONTEXT_FLAG_SYNC,
  626. _OutBuffers[ 0 ].pvBuffer,
  627. _OutBuffers[ 0 ].cbBuffer,
  628. NULL);
  629. }
  630. }
  631. //
  632. // InitializeSecurityContext failed!
  633. //
  634. goto ErrorPoint;
  635. }
  636. ErrorPoint:
  637. {
  638. //
  639. // InitializeSecurityContext failed!
  640. //
  641. ZeroMemory(&_ucServerCertInfo, sizeof(_ucServerCertInfo));
  642. _ucServerCertInfo.Status = scRet;
  643. ulFilterBuffer.BufferType = HttpFilterBufferSslServerCert;
  644. ulFilterBuffer.pBuffer = (PBYTE) &_ucServerCertInfo;
  645. ulFilterBuffer.BufferSize = sizeof( _ucServerCertInfo );
  646. //
  647. // Write the message to the application
  648. //
  649. QueryFiltChannelContext()->DoAppWrite( UL_CONTEXT_FLAG_SYNC,
  650. &ulFilterBuffer,
  651. NULL );
  652. hr = scRet;
  653. }
  654. ExitPoint:
  655. if ( _OutBuffers[ 0 ].pvBuffer != NULL )
  656. {
  657. FreeContextBuffer( _OutBuffers[ 0 ].pvBuffer );
  658. _OutBuffers[ 0 ].pvBuffer = NULL;
  659. }
  660. return hr;
  661. }
  662. /****************************************************************************++
  663. Routine Description:
  664. Encrypt data from the application
  665. Arguments:
  666. pRawStreamInfo - Raw data buffer
  667. pfComplete - Set to true if we should disconnect
  668. Return Value:
  669. HRESULT
  670. --****************************************************************************/
  671. HRESULT
  672. UC_SSL_STREAM_CONTEXT::DoEncrypt(
  673. RAW_STREAM_INFO *pRawStreamInfo,
  674. BOOL *pfComplete
  675. )
  676. {
  677. SECURITY_STATUS secStatus = SEC_E_OK;
  678. // number of chunks the data to be encrypted will be split to
  679. DWORD dwChunks = 0;
  680. // current Data chunk size to be encrypted
  681. DWORD cbDataChunk = 0;
  682. // bytes already encrypted from the source
  683. DWORD cbDataProcessed = 0;
  684. // offset to _buffRawWrite where new chunk should be placed
  685. DWORD cbRawWriteOffset = 0;
  686. if ( pRawStreamInfo == NULL || pfComplete == NULL )
  687. {
  688. DBG_ASSERT( FALSE );
  689. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  690. }
  691. *pfComplete = FALSE;
  692. //
  693. // Each protocol has limit on maximum size of message
  694. // that can be encrypted with one EncryptMessage() call
  695. //
  696. DBG_ASSERT( _cbMaximumMessage != 0 );
  697. //
  698. // Calculate number of chunks based on _cbMaximumMessage
  699. //
  700. dwChunks = pRawStreamInfo->cbData / _cbMaximumMessage;
  701. if ( pRawStreamInfo->cbData % _cbMaximumMessage != 0 )
  702. {
  703. dwChunks++;
  704. }
  705. //
  706. // Allocate a large enough buffer for encrypted data
  707. // ( remember that each chunk needs header and trailer )
  708. //
  709. if ( !_buffRawWrite.Resize( pRawStreamInfo->cbData +
  710. dwChunks * _cbHeader +
  711. dwChunks * _cbTrailer ) )
  712. {
  713. return HRESULT_FROM_WIN32( GetLastError() );
  714. }
  715. //
  716. // Loop to encrypt required data in chunks each not exceeding
  717. // _cbMaximumMessage
  718. //
  719. for( UINT dwCurrentChunk = 0; dwCurrentChunk < dwChunks; dwCurrentChunk++ )
  720. {
  721. DBG_ASSERT( _buffRawWrite.QuerySize() > cbRawWriteOffset );
  722. cbDataChunk = min( pRawStreamInfo->cbData - cbDataProcessed,
  723. _cbMaximumMessage );
  724. memcpy( (PBYTE) _buffRawWrite.QueryPtr() + _cbHeader + cbRawWriteOffset,
  725. pRawStreamInfo->pbBuffer + cbDataProcessed,
  726. cbDataChunk );
  727. _EncryptBuffers[ 0 ].pvBuffer = (PBYTE) _buffRawWrite.QueryPtr() +
  728. cbRawWriteOffset;
  729. _EncryptBuffers[ 0 ].cbBuffer = _cbHeader;
  730. _EncryptBuffers[ 0 ].BufferType = SECBUFFER_STREAM_HEADER;
  731. _EncryptBuffers[ 1 ].pvBuffer = (PBYTE) _buffRawWrite.QueryPtr() +
  732. _cbHeader +
  733. cbRawWriteOffset;
  734. _EncryptBuffers[ 1 ].cbBuffer = cbDataChunk;
  735. _EncryptBuffers[ 1 ].BufferType = SECBUFFER_DATA;
  736. _EncryptBuffers[ 2 ].pvBuffer = (PBYTE) _buffRawWrite.QueryPtr() +
  737. _cbHeader +
  738. cbDataChunk +
  739. cbRawWriteOffset;
  740. _EncryptBuffers[ 2 ].cbBuffer = _cbTrailer;
  741. _EncryptBuffers[ 2 ].BufferType = SECBUFFER_STREAM_TRAILER;
  742. _EncryptBuffers[ 3 ].BufferType = SECBUFFER_EMPTY;
  743. secStatus = EncryptMessage( &_hContext,
  744. 0,
  745. &_EncryptMessage,
  746. 0 );
  747. DBGPRINTF((DBG_CONTEXT,
  748. "EncryptMessage() secStatus=0x%x\n", secStatus));
  749. if (SUCCEEDED(secStatus))
  750. {
  751. //
  752. // next chunk was successfully encrypted
  753. //
  754. cbDataProcessed += cbDataChunk;
  755. cbRawWriteOffset += _EncryptBuffers[ 0 ].cbBuffer +
  756. _EncryptBuffers[ 1 ].cbBuffer +
  757. _EncryptBuffers[ 2 ].cbBuffer;
  758. }
  759. else
  760. {
  761. //
  762. // Set cbData to 0 just for the case that caller ignored error
  763. // and tried to send not encrypted data to client
  764. //
  765. pRawStreamInfo->cbData = 0;
  766. return secStatus;
  767. }
  768. }
  769. //
  770. // Replace the raw stream buffer with the encrypted data
  771. //
  772. pRawStreamInfo->pbBuffer = (PBYTE) _buffRawWrite.QueryPtr();
  773. pRawStreamInfo->cbBuffer = _buffRawWrite.QuerySize();
  774. pRawStreamInfo->cbData = cbRawWriteOffset;
  775. return S_OK;
  776. }
  777. /****************************************************************************++
  778. Routine Description:
  779. Decrypt some data
  780. Arguments:
  781. pRawStreamInfo - Raw data buffer
  782. pfReadMore - Set to true if we should read more data
  783. pfComplete - Set to true if we should disconnect
  784. Return Value:
  785. HRESULT
  786. --****************************************************************************/
  787. HRESULT
  788. UC_SSL_STREAM_CONTEXT::DoDecrypt(
  789. RAW_STREAM_INFO *pRawStreamInfo,
  790. BOOL *pfReadMore,
  791. BOOL *pfComplete,
  792. BOOL *pfExtraData
  793. )
  794. {
  795. SECURITY_STATUS secStatus = SEC_E_OK;
  796. INT iExtra;
  797. if ( pRawStreamInfo == NULL ||
  798. pfReadMore == NULL ||
  799. pfComplete == NULL )
  800. {
  801. DBG_ASSERT( FALSE );
  802. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  803. }
  804. *pfReadMore = FALSE;
  805. *pfComplete = FALSE;
  806. *pfExtraData = FALSE;
  807. DBGPRINTF((DBG_CONTEXT,
  808. "DoDecrypt(): _cbDecrypted = %d, _cbReReadOffset=%d\n",
  809. _cbDecrypted, _cbReReadOffset));
  810. //
  811. // Setup an DecryptMessage call. The input buffer is the _buffRaw plus
  812. // an offset. The offset is non-zero if we had to do another read to
  813. // get more data for a previously incomplete message
  814. //
  815. DBG_ASSERT( pRawStreamInfo->cbData > _cbReReadOffset );
  816. _Buffers[ 0 ].pvBuffer = pRawStreamInfo->pbBuffer + _cbReReadOffset;
  817. _Buffers[ 0 ].cbBuffer = pRawStreamInfo->cbData - _cbReReadOffset;
  818. _Buffers[ 0 ].BufferType = SECBUFFER_DATA;
  819. _Buffers[ 1 ].BufferType = SECBUFFER_EMPTY;
  820. _Buffers[ 2 ].BufferType = SECBUFFER_EMPTY;
  821. _Buffers[ 3 ].BufferType = SECBUFFER_EMPTY;
  822. DecryptAgain:
  823. secStatus = DecryptMessage( &_hContext,
  824. &_Message,
  825. 0,
  826. NULL );
  827. DBGPRINTF((DBG_CONTEXT,
  828. "DecryptMessage( bytes:%d) secStatus=0x%x\n",
  829. pRawStreamInfo->cbData - _cbReReadOffset,
  830. secStatus
  831. ));
  832. if ( FAILED( secStatus ) )
  833. {
  834. if ( secStatus == SEC_E_INCOMPLETE_MESSAGE )
  835. {
  836. //
  837. // Setup another read since the message is incomplete. Remember
  838. // where the new data is going to since we only pass this data
  839. // to the next DecryptMessage call
  840. //
  841. _cbReReadOffset = (DWORD) DIFF( (BYTE *)_Buffers[ 0 ].pvBuffer -
  842. pRawStreamInfo->pbBuffer );
  843. QueryFiltChannelContext()->SetNextRawReadSize( _Buffers[ 1 ].cbBuffer );
  844. *pfReadMore = TRUE;
  845. return S_OK;
  846. }
  847. return secStatus;
  848. }
  849. if (secStatus != SEC_E_OK &&
  850. secStatus != SEC_I_RENEGOTIATE)
  851. {
  852. return secStatus;
  853. }
  854. if ( secStatus == SEC_E_OK )
  855. {
  856. DBG_ASSERT( _Buffers[ 1 ].BufferType == SECBUFFER_DATA );
  857. //
  858. // Take decrypted data and fit it into read buffer
  859. //
  860. memmove( pRawStreamInfo->pbBuffer + _cbDecrypted,
  861. _Buffers[ 1 ].pvBuffer,
  862. _Buffers[ 1 ].cbBuffer );
  863. _cbDecrypted += _Buffers[ 1 ].cbBuffer;
  864. }
  865. //
  866. // Locate extra data (may be available)
  867. //
  868. iExtra = 0;
  869. for ( int i = 1; i < 4; i++ )
  870. {
  871. if ( _Buffers[ i ].BufferType == SECBUFFER_EXTRA )
  872. {
  873. iExtra = i;
  874. break;
  875. }
  876. }
  877. if ( iExtra != 0 )
  878. {
  879. //
  880. // process extra buffer
  881. //
  882. _cbReReadOffset = (DWORD) DIFF( (PBYTE) _Buffers[ iExtra ].pvBuffer -
  883. pRawStreamInfo->pbBuffer );
  884. if ( secStatus != SEC_I_RENEGOTIATE )
  885. {
  886. _Buffers[ 0 ].pvBuffer = _Buffers[ iExtra ].pvBuffer;
  887. _Buffers[ 0 ].cbBuffer = _Buffers[ iExtra ].cbBuffer;
  888. _Buffers[ 0 ].BufferType = SECBUFFER_DATA;
  889. _Buffers[ 1 ].BufferType = SECBUFFER_EMPTY;
  890. _Buffers[ 2 ].BufferType = SECBUFFER_EMPTY;
  891. _Buffers[ 3 ].BufferType = SECBUFFER_EMPTY;
  892. goto DecryptAgain;
  893. }
  894. }
  895. if ( secStatus == SEC_I_RENEGOTIATE )
  896. {
  897. //
  898. // If a renegotiation is triggered, resume the handshake state
  899. //
  900. _fRenegotiate = TRUE;
  901. _sslState = UC_SSL_STATE_HANDSHAKE_IN_PROGRESS;
  902. //
  903. // Caller has to detect that some data is
  904. // still in the buffer not processed and
  905. // That will signal to call DoHandshake()
  906. // for that extra data
  907. //
  908. *pfExtraData = TRUE;
  909. return S_OK;
  910. }
  911. //
  912. // there would have been extra data with SEC_I_RENEGOTIATE
  913. // so we must never get here when renegotiating
  914. //
  915. DBG_ASSERT( secStatus != SEC_I_RENEGOTIATE );
  916. //
  917. // Adjust cbData to include only decrypted data
  918. //
  919. pRawStreamInfo->cbData = _cbDecrypted;
  920. //
  921. // We have final decrypted buffer and no extra data left
  922. // Cleanup _cbDecrypted and _cbReReadOffset to make sure that
  923. // next ProcessRawReadData() will work fine.
  924. //
  925. _cbDecrypted = 0;
  926. _cbReReadOffset = 0;
  927. return S_OK;
  928. }
  929. /****************************************************************************++
  930. Routine Description:
  931. Initialize SSL
  932. Arguments:
  933. None
  934. Return Value:
  935. HRESULT
  936. --****************************************************************************/
  937. //static
  938. HRESULT
  939. UC_SSL_STREAM_CONTEXT::Initialize(
  940. VOID
  941. )
  942. {
  943. return S_OK;
  944. }
  945. /****************************************************************************++
  946. Routine Description:
  947. Terminate SSL
  948. Arguments:
  949. None
  950. Return Value:
  951. None
  952. --****************************************************************************/
  953. //static
  954. VOID
  955. UC_SSL_STREAM_CONTEXT::Terminate(
  956. VOID
  957. )
  958. {
  959. }
  960. /*++
  961. Routine Description:
  962. Build UL_SSL_INFO structure given Schannel context handle
  963. Arguments:
  964. None
  965. Return Value:
  966. HRESULT
  967. --*/
  968. HRESULT
  969. UC_SSL_STREAM_CONTEXT::BuildServerCertInfo(
  970. SECURITY_STATUS InfoStatus,
  971. BOOL fServerCert,
  972. BOOL fIssuerList
  973. )
  974. {
  975. SECURITY_STATUS secStatus;
  976. DBG_ASSERT(_fValidServerCertInfo == FALSE);
  977. if (fServerCert)
  978. {
  979. secStatus = GetServerCert();
  980. if (FAILED(secStatus))
  981. {
  982. DBGPRINTF((DBG_CONTEXT, "Failed GetServerCert 0x%x\n", secStatus));
  983. return secStatus;
  984. }
  985. }
  986. // Is issuer list required?
  987. if (fIssuerList)
  988. {
  989. secStatus = GetIssuerList();
  990. if (FAILED(secStatus))
  991. {
  992. DBGPRINTF((DBG_CONTEXT, "Failed GetIssuerList 0x%x\n", secStatus));
  993. return secStatus;
  994. }
  995. }
  996. //
  997. // Build Server cert Info
  998. //
  999. ZeroMemory(&_ucServerCertInfo, sizeof(_ucServerCertInfo));
  1000. // Issuer list required?
  1001. if (fIssuerList)
  1002. {
  1003. _ucServerCertInfo.IssuerInfo.IssuerCount = _IssuerListInfo.cIssuers;
  1004. _ucServerCertInfo.IssuerInfo.pIssuerList = _IssuerListInfo.aIssuers;
  1005. _ucServerCertInfo.IssuerInfo.IssuerListLength =
  1006. _IssuerListInfo.aIssuers[_IssuerListInfo.cIssuers-1].pbData -
  1007. (PBYTE)_IssuerListInfo.aIssuers +
  1008. _IssuerListInfo.aIssuers[_IssuerListInfo.cIssuers-1].cbData;
  1009. }
  1010. else
  1011. {
  1012. _ucServerCertInfo.IssuerInfo.IssuerListLength = 0;
  1013. _ucServerCertInfo.IssuerInfo.IssuerCount = 0;
  1014. _ucServerCertInfo.IssuerInfo.pIssuerList = 0;
  1015. }
  1016. if (fServerCert)
  1017. {
  1018. BuildServerCert();
  1019. }
  1020. // Ssl handshake was completed
  1021. _ucServerCertInfo.Status = InfoStatus;
  1022. // We now have a valid server cert info
  1023. _fValidServerCertInfo = TRUE;
  1024. return S_OK;
  1025. }
  1026. HRESULT
  1027. UC_SSL_STREAM_CONTEXT::GetServerCert(
  1028. VOID
  1029. )
  1030. {
  1031. SECURITY_STATUS secStatus;
  1032. PUCHAR pbCertContext;
  1033. DWORD cbCertContext;
  1034. CRYPT_DATA_BLOB CertStoreData;
  1035. // Free server cert before getting a new server cert
  1036. if (_pServerCert != NULL)
  1037. {
  1038. CertFreeCertificateContext(_pServerCert);
  1039. _pServerCert = NULL;
  1040. }
  1041. // Free serialized cert
  1042. if (_pSerializedCert)
  1043. {
  1044. delete[] _pSerializedCert;
  1045. _pSerializedCert = NULL;
  1046. _SerializedCertLength = 0;
  1047. }
  1048. // Free serialized store
  1049. if (_pSerializedStore)
  1050. {
  1051. delete[] _pSerializedStore;
  1052. _pSerializedStore = NULL;
  1053. _SerializedStoreLength = 0;
  1054. }
  1055. // Retrieve the server certificate
  1056. secStatus = QueryContextAttributes(&_hContext,
  1057. SECPKG_ATTR_REMOTE_CERT_CONTEXT,
  1058. (PVOID)&_pServerCert);
  1059. if (!SUCCEEDED(secStatus))
  1060. {
  1061. DBGPRINTF((DBG_CONTEXT,
  1062. "Error 0x%x querying server certificate\n",
  1063. secStatus));
  1064. return secStatus;
  1065. }
  1066. //
  1067. // Serialize Server Certificate
  1068. //
  1069. pbCertContext = NULL;
  1070. cbCertContext = 0;
  1071. // First find the length of serialized cert
  1072. if (!CertSerializeCertificateStoreElement(_pServerCert,
  1073. 0,
  1074. NULL,
  1075. &cbCertContext))
  1076. {
  1077. secStatus = GetLastError();
  1078. DBGPRINTF((DBG_CONTEXT,
  1079. "Error 0x%x serialize cert store element\n",
  1080. secStatus));
  1081. return secStatus;
  1082. }
  1083. // Allocate memory for serialized cert
  1084. pbCertContext = new UCHAR[cbCertContext];
  1085. if (!pbCertContext)
  1086. {
  1087. DBGPRINTF((DBG_CONTEXT, "Error allocating memory for cert context\n"));
  1088. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  1089. }
  1090. // Now get the serialized cert
  1091. if (!CertSerializeCertificateStoreElement(_pServerCert,
  1092. 0,
  1093. pbCertContext,
  1094. &cbCertContext))
  1095. {
  1096. secStatus = GetLastError();
  1097. DBGPRINTF((DBG_CONTEXT,
  1098. "Error 0x%x serialize cert store element\n",
  1099. secStatus));
  1100. return secStatus;
  1101. }
  1102. // Store away the serialized cert
  1103. _pSerializedCert = pbCertContext;
  1104. _SerializedCertLength = cbCertContext;
  1105. //
  1106. // Serialize Server Certificate's store
  1107. //
  1108. CertStoreData.pbData = NULL;
  1109. CertStoreData.cbData = 0;
  1110. if (_pServerCert->hCertStore)
  1111. {
  1112. // Find the length of serialized store
  1113. if (!CertSaveStore(_pServerCert->hCertStore,
  1114. X509_ASN_ENCODING,
  1115. CERT_STORE_SAVE_AS_STORE,
  1116. CERT_STORE_SAVE_TO_MEMORY,
  1117. (PVOID)&CertStoreData,
  1118. 0))
  1119. {
  1120. secStatus = GetLastError();
  1121. DBGPRINTF((DBG_CONTEXT, "CertSaveStore failed 0x%x\n", secStatus));
  1122. return secStatus;
  1123. }
  1124. // Allocate memory for serialized store
  1125. CertStoreData.pbData = new UCHAR[CertStoreData.cbData];
  1126. if (!CertStoreData.pbData)
  1127. {
  1128. DBGPRINTF((DBG_CONTEXT, "Error allocating memory cert store\n"));
  1129. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  1130. }
  1131. // Now get the serialized store
  1132. if (!CertSaveStore(_pServerCert->hCertStore,
  1133. X509_ASN_ENCODING,
  1134. CERT_STORE_SAVE_AS_STORE,
  1135. CERT_STORE_SAVE_TO_MEMORY,
  1136. (PVOID)&CertStoreData,
  1137. 0))
  1138. {
  1139. secStatus = GetLastError();
  1140. DBGPRINTF((DBG_CONTEXT, "CertSaveStore failed 0x%x\n", secStatus));
  1141. return secStatus;
  1142. }
  1143. _pSerializedStore = CertStoreData.pbData;
  1144. _SerializedStoreLength = CertStoreData.cbData;
  1145. }
  1146. return S_OK;
  1147. }
  1148. HRESULT
  1149. UC_SSL_STREAM_CONTEXT::GetIssuerList(
  1150. VOID
  1151. )
  1152. {
  1153. SECURITY_STATUS secStatus;
  1154. // If there is a previous issuer list, free it now
  1155. if (_IssuerListInfo.aIssuers)
  1156. {
  1157. DBG_ASSERT(_IssuerListInfo.cIssuers);
  1158. FreeContextBuffer(_IssuerListInfo.aIssuers);
  1159. ZeroMemory(&_IssuerListInfo, sizeof(_IssuerListInfo));
  1160. }
  1161. // Get Issuer list from schannel
  1162. secStatus = QueryContextAttributes(&_hContext,
  1163. SECPKG_ATTR_ISSUER_LIST_EX,
  1164. (PVOID)&_IssuerListInfo);
  1165. if (secStatus != SEC_E_OK)
  1166. {
  1167. DBGPRINTF((DBG_CONTEXT,
  1168. "Error 0x%x querying issuer list info\n", secStatus));
  1169. }
  1170. return secStatus;
  1171. }
  1172. HRESULT
  1173. UC_SSL_STREAM_CONTEXT::BuildServerCert(
  1174. VOID
  1175. )
  1176. {
  1177. SECURITY_STATUS secStatus = SEC_E_OK;
  1178. DWORD CertHashLength;
  1179. DBG_ASSERT(_pServerCert);
  1180. //
  1181. // Server certificate
  1182. //
  1183. //_ucServerCertInfo.Cert.pCertContext = (PVOID)_pServerCert;
  1184. //
  1185. // Get server certificate hash
  1186. //
  1187. CertHashLength = sizeof(_ucServerCertInfo.Cert.CertHash);
  1188. // Certificate hash
  1189. if (!CertGetCertificateContextProperty(_pServerCert,
  1190. CERT_SHA1_HASH_PROP_ID,
  1191. _ucServerCertInfo.Cert.CertHash,
  1192. &CertHashLength))
  1193. {
  1194. secStatus = GetLastError();
  1195. DBGPRINTF((DBG_CONTEXT,
  1196. "Error 0x%x getting server certificate hash\n",
  1197. secStatus));
  1198. return secStatus;
  1199. }
  1200. DBG_ASSERT(CertHashLength <= sizeof(_ucServerCertInfo.Cert.CertHash));
  1201. // Server certificate hash length
  1202. _ucServerCertInfo.Cert.CertHashLength = CertHashLength;
  1203. // Serialized server cert
  1204. _ucServerCertInfo.Cert.pSerializedCert = _pSerializedCert;
  1205. _ucServerCertInfo.Cert.SerializedCertLength = _SerializedCertLength;
  1206. DBGPRINTF((DBG_CONTEXT, "Cert 0x%x, Length 0x%x\n",
  1207. _pSerializedCert,
  1208. _SerializedCertLength));
  1209. // Serialized cert store
  1210. _ucServerCertInfo.Cert.pSerializedCertStore = _pSerializedStore;
  1211. _ucServerCertInfo.Cert.SerializedCertStoreLength = _SerializedStoreLength;
  1212. DBGPRINTF((DBG_CONTEXT, "Store 0x%x, Length 0x%x\n",
  1213. _pSerializedStore,
  1214. _SerializedStoreLength));
  1215. return S_OK;
  1216. }
  1217. /****************************************************************************++
  1218. Routine Description:
  1219. Calls AcquireCredentialsHandle & returns the handle to the caller.
  1220. Arguments:
  1221. dwProtocolType - Supported protocol types by SSPI.
  1222. (SP_PROT_SSL2_CLIENT, SP_PROT_SSL3_CLIENT,
  1223. SP_PROT_TLS1_CLIENT, etc)
  1224. dwFlags - Additional flags that are passed to
  1225. AcquireCredentialsHandle
  1226. pCertContext - Client certificate, if any
  1227. phClientCred - client credentials handle (returned)
  1228. Return Value:
  1229. SECURITY_STATUS
  1230. --****************************************************************************/
  1231. SECURITY_STATUS
  1232. CreateCredentialsHandle(
  1233. IN DWORD dwProtocolType,
  1234. IN DWORD dwFlags,
  1235. IN PCCERT_CONTEXT pCertContext,
  1236. OUT PCredHandle phClientCred
  1237. )
  1238. {
  1239. SCHANNEL_CRED SChannelCred;
  1240. SECURITY_STATUS Status;
  1241. TimeStamp tsExpiry;
  1242. ZeroMemory(&SChannelCred, sizeof(SCHANNEL_CRED));
  1243. SChannelCred.dwVersion = SCHANNEL_CRED_VERSION;
  1244. if (pCertContext)
  1245. {
  1246. SChannelCred.paCred = &pCertContext;
  1247. SChannelCred.cCreds = 1;
  1248. }
  1249. SChannelCred.grbitEnabledProtocols = dwProtocolType;
  1250. #if 0
  1251. //
  1252. // This is used to pick RSA over DH, I don't think we need this for
  1253. // HTTP client (IE does not use this)
  1254. //
  1255. if (aiKeyExch)
  1256. {
  1257. rgbSupportedAlgs[cSupportedAlgs++] = aiKeyExch;
  1258. }
  1259. if (cSupportedAlgs)
  1260. {
  1261. SChannelCred.cSupportedAlgs = cSupportedAlgs;
  1262. SChannelCred.palgSupportedAlgs = rgbSupportedAlgs;
  1263. }
  1264. #endif
  1265. SChannelCred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
  1266. // dwFlags can be either
  1267. // SCH_CRED_MANUAL_CRED_VALIDATION or
  1268. // SCH_CRED_AUTO_CRED_VALIDATION
  1269. //
  1270. SChannelCred.dwFlags |= dwFlags;
  1271. //
  1272. // Create an SSPI handle.
  1273. //
  1274. Status = AcquireCredentialsHandle(
  1275. NULL, // name of principal
  1276. UNISP_NAME, // Name of package
  1277. SECPKG_CRED_OUTBOUND, // Flags indicating use
  1278. NULL, // LogonID
  1279. &SChannelCred, // Package specific data
  1280. NULL, // GetKey() function
  1281. NULL, // GetKey context
  1282. phClientCred, // (out) Cred handle
  1283. &tsExpiry // (out) lifetime
  1284. );
  1285. if (Status != SEC_E_OK)
  1286. {
  1287. DBGPRINTF((DBG_CONTEXT,
  1288. "AcquireCredentialsHandle failed with 0x%x \n",
  1289. Status));
  1290. }
  1291. return Status;
  1292. }