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.

1424 lines
40 KiB

  1. #include "precomp.h"
  2. DEBUG_FILEZONE(ZONE_T120_MSMCSTCP);
  3. // #define FORCE_SSL3_NEGOTIATION
  4. #include "tprtsec.h"
  5. /* Tprtsec.cpp
  6. *
  7. * Copyright (c) 1997 by Microsoft Corporation
  8. *
  9. * Abstract:
  10. * This module maintains security for the TCP transport.
  11. *
  12. */
  13. /* External definitions */
  14. extern HINSTANCE g_hDllInst;
  15. /*
  16. * The following array contains a template for the X.224 data header.
  17. * The 5 of the 7 bytes that it initializes are actually sent to the
  18. * wire. Bytes 3 and 4 will be set to contain the size of the PDU.
  19. * The array is only used when we encode a data PDU.
  20. */
  21. extern UChar g_X224Header[];
  22. #ifdef DEBUG
  23. //#define TESTHACKS // DANGER! don't turn on in public build!
  24. //#define DUMP
  25. //#define DUMPCERTS
  26. //#undef TRACE_OUT
  27. //#define TRACE_OUT WARNING_OUT
  28. #endif //DEBUG
  29. #define SZSECPKG UNISP_NAME_A
  30. #define ISC_REQ_FLAGS ( ISC_REQ_SEQUENCE_DETECT |\
  31. ISC_REQ_REPLAY_DETECT |\
  32. ISC_REQ_CONFIDENTIALITY |\
  33. ISC_REQ_EXTENDED_ERROR |\
  34. ISC_REQ_ALLOCATE_MEMORY |\
  35. ISC_REQ_STREAM)
  36. #define ASC_REQ_FLAGS ( ASC_REQ_SEQUENCE_DETECT |\
  37. ASC_REQ_REPLAY_DETECT |\
  38. ASC_REQ_CONFIDENTIALITY |\
  39. ASC_REQ_EXTENDED_ERROR |\
  40. ASC_REQ_ALLOCATE_MEMORY |\
  41. ASC_REQ_MUTUAL_AUTH |\
  42. ASC_REQ_STREAM)
  43. #if defined(DUMP) || defined(DUMPCERTS)
  44. #define MAX_DUMP_BYTES 512
  45. void dumpbytes(PSTR szComment, PBYTE p, int cb)
  46. {
  47. int i,j;
  48. char buf[80];
  49. char buf2[80];
  50. DWORD dwCheckSum = 0;
  51. int cbShow = min(MAX_DUMP_BYTES,cb);
  52. for (i=0; i<cb; i++)
  53. dwCheckSum += p[i];
  54. wsprintf(buf,"%s (%d bytes, checksum %x):",
  55. szComment? szComment : "unknown", cb, dwCheckSum);
  56. OutputDebugString(buf);
  57. WARNING_OUT(("%s",buf));
  58. OutputDebugString("\n\r");
  59. for (i=0; i<cbShow/16; i++)
  60. {
  61. wsprintf(buf, "%08x: ", (DWORD) &p[(i*16)] );
  62. for (j=0; j<16; j++)
  63. {
  64. wsprintf(buf2," %02x", (int) (unsigned char) p[(i*16)+j] );
  65. lstrcat ( buf, buf2 );
  66. }
  67. WARNING_OUT(("%s",buf));
  68. lstrcat ( buf, "\n\r");
  69. OutputDebugString(buf);
  70. }
  71. if ( cbShow%16 )
  72. {
  73. wsprintf(buf, "%08x: ", (DWORD) &p[(i*16)] );
  74. for (j=0; j<cbShow%16; j++)
  75. {
  76. wsprintf(buf2," %02x", (int) (unsigned char) p[(i*16)+j] );
  77. lstrcat ( buf, buf2 );
  78. }
  79. WARNING_OUT(("%s",buf));
  80. lstrcat(buf,"\n\r");
  81. OutputDebugString(buf);
  82. }
  83. if ( cbShow < cb )
  84. {
  85. OutputDebugString("...\n\r");
  86. WARNING_OUT(("..."));
  87. }
  88. }
  89. #endif //DUMP or DUMPCERTS
  90. ///////////////////////////////////////////////////////////////////////////
  91. // Security Interface
  92. ///////////////////////////////////////////////////////////////////////////
  93. SecurityInterface::SecurityInterface(void) :
  94. LastError(TPRTSEC_NOERROR),
  95. bInboundCredentialValid(FALSE),
  96. bOutboundCredentialValid(FALSE),
  97. m_pbEncodedCert(NULL),
  98. m_cbEncodedCert(0),
  99. hSecurityDll(NULL),
  100. pfnTable(NULL)
  101. {
  102. }
  103. SecurityInterface::~SecurityInterface(VOID)
  104. {
  105. if ( pfnTable && bInboundCredentialValid )
  106. {
  107. pfnTable->FreeCredentialHandle ( &hInboundCredential );
  108. }
  109. if ( pfnTable && bOutboundCredentialValid )
  110. {
  111. pfnTable->FreeCredentialHandle ( &hOutboundCredential );
  112. }
  113. if ( NULL != m_pbEncodedCert )
  114. {
  115. delete m_pbEncodedCert;
  116. }
  117. if ( NULL != hSecurityDll )
  118. {
  119. FreeLibrary( hSecurityDll );
  120. }
  121. }
  122. #ifdef DUMPCERTS
  123. VOID DumpCertStore ( SecurityInterface * pSI, char * sz, HCERTSTORE hStore)
  124. {
  125. WARNING_OUT(("************ %s *************", sz));
  126. PCCERT_CONTEXT pC = NULL;
  127. int i = 0;
  128. char buf[256];
  129. while ( pC = CertEnumCertificatesInStore(
  130. hStore, (PCERT_CONTEXT)pC ))
  131. {
  132. WARNING_OUT(("----------- Entry %d: ----------------", i));
  133. // Dump stuff in pC->pCertInfo
  134. //DWORD dwVersion;
  135. //CRYPT_INTEGER_BLOB SerialNumber;
  136. //CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
  137. //CERT_NAME_BLOB Issuer;
  138. //FILETIME NotBefore;
  139. //FILETIME NotAfter;
  140. //CERT_NAME_BLOB Subject;
  141. //CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo;
  142. //CRYPT_BIT_BLOB IssuerUniqueId;
  143. //CRYPT_BIT_BLOB SubjectUniqueId;
  144. //DWORD cExtension;
  145. //PCERT_EXTENSION rgExtension;
  146. WARNING_OUT(("dwVersion: %x", pC->pCertInfo->dwVersion));
  147. dumpbytes("SerialNumber",
  148. pC->pCertInfo->SerialNumber.pbData,
  149. pC->pCertInfo->SerialNumber.cbData );
  150. WARNING_OUT(("SignatureAlgorithm (name): %s",
  151. pC->pCertInfo->SignatureAlgorithm.pszObjId ));
  152. CertNameToStr( pC->dwCertEncodingType, &pC->pCertInfo->Issuer,
  153. CERT_X500_NAME_STR, buf, sizeof(buf) );
  154. WARNING_OUT(("Issuer: %s", buf ));
  155. WARNING_OUT(("NotBefore: %x,%x",
  156. pC->pCertInfo->NotBefore.dwLowDateTime,
  157. pC->pCertInfo->NotBefore.dwHighDateTime ));
  158. WARNING_OUT(("NotAfter: %x,%x",
  159. pC->pCertInfo->NotAfter.dwLowDateTime,
  160. pC->pCertInfo->NotAfter.dwHighDateTime ));
  161. CertNameToStr( pC->dwCertEncodingType, &pC->pCertInfo->Subject,
  162. CERT_X500_NAME_STR, buf, sizeof(buf) );
  163. WARNING_OUT(("Subject: %s", buf ));
  164. WARNING_OUT(("<stuff omitted for now>"));
  165. dumpbytes("IssuerUniqueId",
  166. pC->pCertInfo->IssuerUniqueId.pbData,
  167. pC->pCertInfo->IssuerUniqueId.cbData );
  168. dumpbytes("SubjectUniqueId",
  169. pC->pCertInfo->SubjectUniqueId.pbData,
  170. pC->pCertInfo->SubjectUniqueId.cbData );
  171. WARNING_OUT(("cExtension: %x", pC->pCertInfo->cExtension ));
  172. WARNING_OUT(("<stuff omitted for now>"));
  173. i++;
  174. }
  175. }
  176. #endif // DUMPCERTS
  177. TransportSecurityError SecurityInterface::InitializeCreds(
  178. PCCERT_CONTEXT pCertContext )
  179. {
  180. SECURITY_STATUS ss;
  181. SCHANNEL_CRED CredData;
  182. CredHandle hNewInboundCred;
  183. CredHandle hNewOutboundCred;
  184. //
  185. // Are we going to create new creds or just clean up?
  186. //
  187. if ( NULL != pCertContext )
  188. {
  189. ZeroMemory(&CredData, sizeof(CredData));
  190. CredData.dwVersion = SCHANNEL_CRED_VERSION;
  191. #ifdef FORCE_SSL3_NEGOTIATION
  192. CredData.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT |
  193. SP_PROT_SSL3_SERVER;
  194. #endif // FORCE_SSL3_NEGOTIATION
  195. CredData.dwFlags = SCH_CRED_NO_SERVERNAME_CHECK |
  196. SCH_CRED_NO_DEFAULT_CREDS |
  197. SCH_CRED_MANUAL_CRED_VALIDATION;
  198. CredData.cCreds = 1;
  199. CredData.paCred = &pCertContext;
  200. // Acquire client and server credential handles
  201. ss = pfnTable->AcquireCredentialsHandle (
  202. NULL,
  203. SZSECPKG,
  204. SECPKG_CRED_INBOUND,
  205. NULL,
  206. &CredData,
  207. NULL,
  208. NULL,
  209. &hNewInboundCred,
  210. &tsExpiry );
  211. if ( SEC_E_OK != ss )
  212. {
  213. WARNING_OUT(("AcquireCredentialsHandle (inbound) failed %lx", ss));
  214. LastError = TPRTSEC_SSPIFAIL;
  215. goto error;
  216. }
  217. ss = pfnTable->AcquireCredentialsHandle (
  218. NULL,
  219. SZSECPKG,
  220. SECPKG_CRED_OUTBOUND,
  221. NULL,
  222. &CredData,
  223. NULL,
  224. NULL,
  225. &hNewOutboundCred,
  226. &tsExpiry );
  227. if ( SEC_E_OK != ss )
  228. {
  229. WARNING_OUT(("AcquireCredentialsHandle (outbound) failed %lx", ss));
  230. pfnTable->FreeCredentialHandle( &hNewInboundCred );
  231. LastError = TPRTSEC_SSPIFAIL;
  232. goto error;
  233. }
  234. // Empty the SSL cache
  235. if (pfn_SslEmptyCache)
  236. {
  237. pfn_SslEmptyCache();
  238. }
  239. // This member can be called even when we're already initialized, as
  240. // when the user chooses a different cert and we need to build new
  241. // credentials based on it. Clear out the old information as necessary:
  242. if ( NULL != m_pbEncodedCert )
  243. {
  244. delete m_pbEncodedCert;
  245. m_pbEncodedCert = NULL;
  246. }
  247. }
  248. if ( bInboundCredentialValid )
  249. pfnTable->FreeCredentialHandle ( &hInboundCredential );
  250. if ( bOutboundCredentialValid )
  251. pfnTable->FreeCredentialHandle ( &hOutboundCredential );
  252. if ( NULL != pCertContext )
  253. {
  254. hInboundCredential = hNewInboundCred;
  255. hOutboundCredential = hNewOutboundCred;
  256. bInboundCredentialValid = TRUE;
  257. bOutboundCredentialValid = TRUE;
  258. //
  259. // Save the cert name for later use
  260. //
  261. ASSERT( NULL == m_pbEncodedCert );
  262. m_pbEncodedCert = new BYTE[pCertContext->cbCertEncoded];
  263. if ( NULL == m_pbEncodedCert )
  264. {
  265. ERROR_OUT(("Error allocating data for encoded Cert"));
  266. goto error;
  267. }
  268. memcpy( m_pbEncodedCert, pCertContext->pbCertEncoded,
  269. pCertContext->cbCertEncoded );
  270. ASSERT(pCertContext->cbCertEncoded);
  271. m_cbEncodedCert = pCertContext->cbCertEncoded;
  272. }
  273. else
  274. {
  275. bInboundCredentialValid = FALSE;
  276. bOutboundCredentialValid = FALSE;
  277. }
  278. LastError = TPRTSEC_NOERROR;
  279. error:
  280. return LastError;
  281. }
  282. TransportSecurityError SecurityInterface::Initialize(VOID)
  283. {
  284. TRACE_OUT(("Initializing security interface"));
  285. // Load the security provider DLL
  286. hSecurityDll = LoadLibrary("SCHANNEL");
  287. if ( !hSecurityDll )
  288. {
  289. ERROR_OUT(("Loadlib schannel.dll failed"));
  290. LastError = TPRTSEC_NODLL;
  291. goto error;
  292. }
  293. // Get the initialization entrypoint
  294. pfnInitSecurityInterface = (INIT_SECURITY_INTERFACE)GetProcAddress(
  295. hSecurityDll,
  296. SECURITY_ENTRYPOINT );
  297. if ( NULL == pfnInitSecurityInterface )
  298. {
  299. ERROR_OUT(("GetProcAddr %s failed", SECURITY_ENTRYPOINT));
  300. LastError = TPRTSEC_NOENTRYPT;
  301. goto error;
  302. }
  303. // Get the SSPI function table
  304. pfnTable = (*pfnInitSecurityInterface)();
  305. if ( NULL == pfnTable )
  306. {
  307. ERROR_OUT(("InitializeSecurityProvider failed"));
  308. LastError = TPRTSEC_SSPIFAIL;
  309. goto error;
  310. }
  311. pfn_SslEmptyCache = (PFN_SSL_EMPTY_CACHE)GetProcAddress(hSecurityDll, SZ_SSLEMPTYCACHE);
  312. if ( NULL == pfnInitSecurityInterface )
  313. {
  314. ERROR_OUT(("GetProcAddr %s failed", SZ_SSLEMPTYCACHE));
  315. LastError = TPRTSEC_NOENTRYPT;
  316. goto error;
  317. }
  318. error:
  319. return LastError;
  320. }
  321. BOOL SecurityInterface::GetUserCert(PBYTE pInfo, PDWORD pcbInfo)
  322. {
  323. if ( NULL == m_pbEncodedCert)
  324. {
  325. WARNING_OUT(("GetUserCert: no encoded certname"));
  326. return FALSE;
  327. }
  328. ASSERT(m_cbEncodedCert > 0);
  329. if ( NULL == pInfo )
  330. {
  331. // Caller wants to know how much to allocate
  332. ASSERT(pcbInfo);
  333. *pcbInfo = m_cbEncodedCert;
  334. return TRUE;
  335. }
  336. if ( *pcbInfo < m_cbEncodedCert )
  337. {
  338. ERROR_OUT(("GetUserCert: insufficient buffer (%ld) %ld required",
  339. *pcbInfo, m_cbEncodedCert ));
  340. return FALSE;
  341. }
  342. memcpy ( (PCHAR)pInfo, m_pbEncodedCert, m_cbEncodedCert );
  343. *pcbInfo = m_cbEncodedCert;
  344. return TRUE;
  345. }
  346. ///////////////////////////////////////////////////////////////////////////
  347. // Security Context
  348. ///////////////////////////////////////////////////////////////////////////
  349. SecurityContext::SecurityContext(PSecurityInterface pSI, LPCSTR szHostName) :
  350. scstate(SECCTX_STATE_NEW),
  351. fContinueNeeded(FALSE),
  352. LastError(TPRTSEC_NOERROR),
  353. bContextHandleValid(FALSE)
  354. {
  355. ASSERT(pSI);
  356. ASSERT(szHostName);
  357. pSecurityInterface = pSI;
  358. OutBuffers[0].pvBuffer = NULL;
  359. OutBuffers[0].cbBuffer = 0;
  360. if ( NULL != szHostName )
  361. {
  362. wsprintf( szTargetName, "%s:%x%x", szHostName,
  363. pSI->hOutboundCredential.dwUpper,
  364. pSI->hOutboundCredential.dwLower);
  365. TRACE_OUT(("SecurityContext::SecurityContext: targ %s",szTargetName));
  366. }
  367. ASSERT(pSecurityInterface);
  368. }
  369. SecurityContext::~SecurityContext(VOID)
  370. {
  371. ASSERT(pSecurityInterface);
  372. if ( NULL != OutBuffers[0].pvBuffer )
  373. {
  374. ASSERT(pSecurityInterface->pfnTable);
  375. pSecurityInterface->pfnTable->FreeContextBuffer(OutBuffers[0].pvBuffer);
  376. OutBuffers[0].pvBuffer = NULL;
  377. }
  378. if ( bContextHandleValid )
  379. {
  380. pSecurityInterface->pfnTable->DeleteSecurityContext(&hContext);
  381. }
  382. }
  383. TransportSecurityError SecurityContext::InitContextAttributes(VOID)
  384. {
  385. SECURITY_STATUS ss;
  386. ss = pSecurityInterface->pfnTable->QueryContextAttributes(&hContext,
  387. SECPKG_ATTR_STREAM_SIZES,
  388. &Sizes );
  389. if (ss != ERROR_SUCCESS)
  390. {
  391. ERROR_OUT(("QueryContextAttributes returned [%x]", ss));
  392. return LastError = TPRTSEC_SSPIFAIL;
  393. }
  394. else
  395. {
  396. ASSERT (Sizes.cbHeader + Sizes.cbTrailer <= PROTOCOL_OVERHEAD_SECURITY);
  397. TRACE_OUT(("QueryContextAttributes returned header=%d trailer=%d",
  398. Sizes.cbHeader, Sizes.cbTrailer));
  399. }
  400. #ifdef DEBUG //////////////////////////////////////////////////////////
  401. SecPkgContext_KeyInfo KeyInfo;
  402. ss = pSecurityInterface->pfnTable->QueryContextAttributes(&hContext,
  403. SECPKG_ATTR_KEY_INFO,
  404. &KeyInfo );
  405. if (ss != ERROR_SUCCESS)
  406. {
  407. ERROR_OUT(("QueryContextAttributes (KEY_INFO) failed %x", ss));
  408. }
  409. else
  410. {
  411. WARNING_OUT(("KEY INFO: Sign:%s Encrypt:%s Keysize:%d",
  412. KeyInfo.sSignatureAlgorithmName,
  413. KeyInfo.sEncryptAlgorithmName,
  414. KeyInfo.KeySize ));
  415. pSecurityInterface->pfnTable->FreeContextBuffer(
  416. KeyInfo.sSignatureAlgorithmName );
  417. pSecurityInterface->pfnTable->FreeContextBuffer(
  418. KeyInfo.sEncryptAlgorithmName );
  419. }
  420. #endif //DEBUG ///////////////////////////////////////////////////////
  421. return TPRTSEC_NOERROR;
  422. }
  423. TransportSecurityError SecurityContext::Initialize(PBYTE pData, DWORD cbData)
  424. {
  425. SECURITY_STATUS ss;
  426. DWORD dwReqFlags;
  427. TRACE_OUT(("SecurityContext Initialize (%x,%d)", pData, cbData));
  428. fContinueNeeded = FALSE;
  429. ASSERT(pSecurityInterface);
  430. ASSERT(SECCTX_STATE_INIT == scstate || SECCTX_STATE_NEW == scstate);
  431. if ( !pSecurityInterface->bOutboundCredentialValid )
  432. {
  433. WARNING_OUT(("SecurityContext::Initialize: no outbound cred"));
  434. return TPRTSEC_SSPIFAIL;
  435. }
  436. if ( SECCTX_STATE_INIT == scstate)
  437. {
  438. ASSERT(NULL != pData);
  439. ASSERT(0 != cbData);
  440. if ( NULL == pData || 0 == cbData )
  441. {
  442. ERROR_OUT(("Second initialize call with no data"));
  443. return LastError = TPRTSEC_INVALID_PARAMETER;
  444. }
  445. // Build the input buffer descriptor
  446. InputBufferDescriptor.cBuffers = 2;
  447. InputBufferDescriptor.pBuffers = InBuffers;
  448. InputBufferDescriptor.ulVersion = SECBUFFER_VERSION;
  449. InBuffers[0].BufferType = SECBUFFER_TOKEN;
  450. InBuffers[0].cbBuffer = cbData;
  451. InBuffers[0].pvBuffer = pData;
  452. InBuffers[1].BufferType = SECBUFFER_EMPTY;
  453. InBuffers[1].cbBuffer = 0;
  454. InBuffers[1].pvBuffer = NULL;
  455. }
  456. else
  457. {
  458. ASSERT(NULL == pData);
  459. ASSERT(0 == cbData);
  460. }
  461. OutputBufferDescriptor.cBuffers = 1;
  462. OutputBufferDescriptor.pBuffers = OutBuffers;
  463. OutputBufferDescriptor.ulVersion = SECBUFFER_VERSION;
  464. // If there's a output buffer from a previous call, free it here
  465. if ( NULL != OutBuffers[0].pvBuffer )
  466. {
  467. pSecurityInterface->pfnTable->FreeContextBuffer(OutBuffers[0].pvBuffer);
  468. }
  469. dwReqFlags = ISC_REQ_FLAGS;
  470. while ( 1 )
  471. {
  472. OutBuffers[0].BufferType = SECBUFFER_TOKEN;
  473. OutBuffers[0].cbBuffer = 0;
  474. OutBuffers[0].pvBuffer = NULL;
  475. #ifdef DUMP
  476. if (SECCTX_STATE_INIT == scstate)
  477. {
  478. dumpbytes("input token", (unsigned char *)InBuffers[0].pvBuffer,
  479. InBuffers[0].cbBuffer);
  480. }
  481. #endif //DUMP
  482. ss = pSecurityInterface->pfnTable->InitializeSecurityContext(
  483. &(pSecurityInterface->hOutboundCredential),
  484. SECCTX_STATE_INIT == scstate ? &hContext : NULL,
  485. szTargetName, // TargetName
  486. dwReqFlags,
  487. 0, // Reserved
  488. SECURITY_NATIVE_DREP,
  489. SECCTX_STATE_INIT == scstate ? &InputBufferDescriptor : NULL,
  490. 0, // reserved
  491. &hContext,
  492. &OutputBufferDescriptor,
  493. &ContextAttributes,
  494. &Expiration );
  495. // Some security providers don't process all the packet data
  496. // in one call to SCA - readjust the input buffers with the offset
  497. // returned in the extra buffer and iterate as necessary
  498. if (( SEC_I_CONTINUE_NEEDED == ss
  499. && NULL == OutBuffers[0].pvBuffer )
  500. && SECBUFFER_EXTRA == InBuffers[1].BufferType
  501. && 0 != InBuffers[1].cbBuffer )
  502. {
  503. InBuffers[0].pvBuffer = (PBYTE)(InBuffers[0].pvBuffer) +
  504. ( InBuffers[0].cbBuffer - InBuffers[1].cbBuffer );
  505. InBuffers[0].BufferType = SECBUFFER_TOKEN;
  506. InBuffers[0].cbBuffer = InBuffers[1].cbBuffer;
  507. InBuffers[1].BufferType = SECBUFFER_EMPTY;
  508. InBuffers[1].cbBuffer = 0;
  509. InBuffers[1].pvBuffer = NULL;
  510. continue;
  511. }
  512. break;
  513. }
  514. #ifdef DUMP
  515. if ( SEC_E_OK == ss || SEC_I_CONTINUE_NEEDED == ss )
  516. {
  517. dumpbytes("output token",
  518. (unsigned char *)OutBuffers[0].pvBuffer,
  519. OutBuffers[0].cbBuffer);
  520. }
  521. #endif //DUMP
  522. #ifdef ALLOW_NON_AUTHENTICATED_CLIENTS
  523. if ( SEC_I_INCOMPLETE_CREDENTIALS == ss )
  524. {
  525. WARNING_OUT(("InitializeSecurityContext:SEC_I_INCOMPLETE_CREDENTIALS"));
  526. dwReqFlags |= ISC_REQ_USE_SUPPLIED_CREDS;
  527. ss = pSecurityInterface->pfnTable->InitializeSecurityContext(
  528. &(pSecurityInterface->hOutboundCredential),
  529. SECCTX_STATE_INIT == scstate ? &hContext : NULL,
  530. szTargetName, // TargetName
  531. dwReqFlags,
  532. 0, // Reserved
  533. SECURITY_NATIVE_DREP,
  534. SECCTX_STATE_INIT == scstate ? &InputBufferDescriptor : NULL,
  535. 0, // reserved
  536. &hContext,
  537. &OutputBufferDescriptor,
  538. &ContextAttributes,
  539. &Expiration );
  540. }
  541. #endif // ALLOW_NON_AUTHENTICATED_CLIENTS
  542. if ( SEC_E_OK != ss )
  543. {
  544. if ( SEC_I_CONTINUE_NEEDED == ss && NULL != OutBuffers[0].pvBuffer )
  545. {
  546. ASSERT(SECCTX_STATE_NEW == scstate || SECCTX_STATE_INIT == scstate);
  547. TRACE_OUT(("Initialize: SEC_I_CONTINUE_NEEDED"));
  548. scstate = SECCTX_STATE_INIT;
  549. }
  550. else
  551. {
  552. ERROR_OUT(("Initialize failed: %x in state %d",(DWORD)ss,scstate));
  553. return LastError = TPRTSEC_SSPIFAIL;
  554. }
  555. }
  556. else
  557. {
  558. // We're almost done,
  559. // find the header and trailer sizes
  560. //
  561. if ( TPRTSEC_NOERROR != InitContextAttributes() )
  562. return LastError;
  563. if ( !Verify() )
  564. return LastError = TPRTSEC_SSPIFAIL;
  565. TRACE_OUT(("INITIALIZE OK"));
  566. scstate = SECCTX_STATE_INIT_COMPLETE;
  567. }
  568. // If there is an output buffer, set the flag to get it sent accross
  569. if ( ( SEC_E_OK == ss || SEC_I_CONTINUE_NEEDED == ss ) &&
  570. NULL != OutBuffers[0].pvBuffer )
  571. {
  572. fContinueNeeded = TRUE;
  573. }
  574. bContextHandleValid = TRUE;
  575. return LastError = TPRTSEC_NOERROR;
  576. }
  577. TransportSecurityError SecurityContext::Accept(PBYTE pData, DWORD cbData)
  578. {
  579. SECURITY_STATUS ss;
  580. fContinueNeeded = FALSE;
  581. ASSERT(SECCTX_STATE_NEW == scstate || SECCTX_STATE_ACCEPT == scstate);
  582. if ( !pSecurityInterface->bInboundCredentialValid )
  583. {
  584. WARNING_OUT(("SecurityContext::Initialize: no inbound cred"));
  585. return TPRTSEC_SSPIFAIL;
  586. }
  587. // Check to see if the required data is present
  588. if ( NULL == pData || 0 == cbData )
  589. {
  590. ERROR_OUT(("Accept: no data"));
  591. return LastError = TPRTSEC_INVALID_PARAMETER;
  592. }
  593. // Build the input buffer descriptor
  594. InputBufferDescriptor.cBuffers = 2;
  595. InputBufferDescriptor.pBuffers = InBuffers;
  596. InputBufferDescriptor.ulVersion = SECBUFFER_VERSION;
  597. InBuffers[0].BufferType = SECBUFFER_TOKEN;
  598. InBuffers[0].cbBuffer = cbData;
  599. InBuffers[0].pvBuffer = pData;
  600. InBuffers[1].BufferType = SECBUFFER_EMPTY;
  601. InBuffers[1].cbBuffer = 0;
  602. InBuffers[1].pvBuffer = NULL;
  603. // Build the output buffer descriptor
  604. OutputBufferDescriptor.cBuffers = 1;
  605. OutputBufferDescriptor.pBuffers = OutBuffers;
  606. OutputBufferDescriptor.ulVersion = SECBUFFER_VERSION;
  607. // If there's a output buffer from a previous call, free it here
  608. if ( NULL != OutBuffers[0].pvBuffer )
  609. {
  610. pSecurityInterface->pfnTable->FreeContextBuffer(OutBuffers[0].pvBuffer);
  611. }
  612. while ( 1 )
  613. {
  614. OutBuffers[0].BufferType = SECBUFFER_TOKEN;
  615. OutBuffers[0].cbBuffer = 0;
  616. OutBuffers[0].pvBuffer = NULL;
  617. #ifdef DUMP
  618. dumpbytes("input token", (unsigned char *)InBuffers[0].pvBuffer,
  619. InBuffers[0].cbBuffer);
  620. #endif //DUMP
  621. ss = pSecurityInterface->pfnTable->AcceptSecurityContext(
  622. &(pSecurityInterface->hInboundCredential),
  623. SECCTX_STATE_NEW == scstate ? NULL : &hContext,
  624. &InputBufferDescriptor,
  625. ASC_REQ_FLAGS,
  626. SECURITY_NATIVE_DREP,
  627. &hContext, // receives new context handle
  628. &OutputBufferDescriptor, // receives output security token
  629. &ContextAttributes, // receives context attributes
  630. &Expiration ); // receives expiration time
  631. // Some security providers don't process all the packet data
  632. // in one call to SCA - readjust the input buffers with the offset
  633. // returned in the extra buffer and iterate as necessary
  634. if (( SEC_I_CONTINUE_NEEDED == ss
  635. && NULL == OutBuffers[0].pvBuffer )
  636. && SECBUFFER_EXTRA == InBuffers[1].BufferType
  637. && 0 != InBuffers[1].cbBuffer )
  638. {
  639. InBuffers[0].pvBuffer = (PBYTE)(InBuffers[0].pvBuffer) +
  640. ( InBuffers[0].cbBuffer - InBuffers[1].cbBuffer );
  641. InBuffers[0].BufferType = SECBUFFER_TOKEN;
  642. InBuffers[0].cbBuffer = InBuffers[1].cbBuffer;
  643. InBuffers[1].BufferType = SECBUFFER_EMPTY;
  644. InBuffers[1].cbBuffer = 0;
  645. InBuffers[1].pvBuffer = NULL;
  646. continue;
  647. }
  648. break;
  649. }
  650. #ifdef DUMP
  651. if ( SEC_E_OK == ss || SEC_I_CONTINUE_NEEDED == ss )
  652. {
  653. dumpbytes("output token",
  654. (unsigned char *)OutBuffers[0].pvBuffer,
  655. OutBuffers[0].cbBuffer);
  656. }
  657. #endif //DUMP
  658. if ( SEC_E_OK != ss )
  659. {
  660. if ( SEC_I_CONTINUE_NEEDED == ss )
  661. {
  662. TRACE_OUT(("Accept: SEC_I_CONTINUE_NEEDED"));
  663. scstate = SECCTX_STATE_ACCEPT;
  664. }
  665. else
  666. {
  667. ERROR_OUT(("AcceptSecurityContext failed: %x", (DWORD)ss));
  668. return LastError = TPRTSEC_SSPIFAIL;
  669. }
  670. }
  671. else
  672. {
  673. // We're almost done,
  674. // find the header and trailer sizes
  675. //
  676. if ( TPRTSEC_NOERROR != InitContextAttributes() )
  677. return LastError;
  678. if ( !Verify() )
  679. return LastError = TPRTSEC_SSPIFAIL;
  680. TRACE_OUT(("ACCEPT OK"));
  681. scstate = SECCTX_STATE_ACCEPT_COMPLETE;
  682. }
  683. // If there is an output buffer, set the flag to get it sent accross
  684. if ( ( SEC_E_OK == ss || SEC_I_CONTINUE_NEEDED == ss ) &&
  685. NULL != OutBuffers[0].pvBuffer )
  686. {
  687. fContinueNeeded = TRUE;
  688. }
  689. bContextHandleValid = TRUE;
  690. return LastError = TPRTSEC_NOERROR;
  691. }
  692. /////////////////////////////////////////////////////////////////////////////
  693. //
  694. // Encrypt()
  695. //
  696. // Description:
  697. // Encrypts a packet to be sent using SSL/PCT by calling SealMessage().
  698. //
  699. // Parameters:
  700. // phContext - security context handle returned from InitiateSecConnection
  701. // pBufIn1, pBufIn2 - buffers to be encrypted
  702. // cbBufIn1,cbBufIn2 - lengths of buffers to be encrypted
  703. // ppBufOut - allocated encrypted buffer, to be freed by caller
  704. // pcbBufOut - length of encrypted buffer
  705. //
  706. // Return:
  707. // TransprotSecurityError
  708. //
  709. TransportSecurityError SecurityContext::Encrypt(
  710. LPBYTE pBufIn1,
  711. UINT cbBufIn1,
  712. LPBYTE pBufIn2,
  713. UINT cbBufIn2,
  714. LPBYTE *ppBufOut,
  715. UINT *pcbBufOut)
  716. {
  717. SECURITY_STATUS scRet = ERROR_SUCCESS;
  718. SecBufferDesc Buffer;
  719. SecBuffer Buffers[4];
  720. UINT cbBufInTotal;
  721. LPBYTE pbTemp;
  722. // pBufIn2 and cbBufIn2 maybe NULL and 0, respectively.
  723. ASSERT(pBufIn1);
  724. ASSERT(cbBufIn1);
  725. ASSERT(ppBufOut);
  726. ASSERT(pcbBufOut);
  727. ASSERT(SECCTX_STATE_INIT_COMPLETE == scstate ||
  728. SECCTX_STATE_ACCEPT_COMPLETE == scstate);
  729. if (SECCTX_STATE_INIT_COMPLETE != scstate &&
  730. SECCTX_STATE_ACCEPT_COMPLETE != scstate)
  731. return LastError = TPRTSEC_INCOMPLETE_CONTEXT;
  732. *pcbBufOut = 0;
  733. cbBufInTotal = cbBufIn1 + cbBufIn2;
  734. // We allocate a buffer to hold the (larger) encrypted data.
  735. // This must be freed by the caller!
  736. // christts: The buffer will now also hold the X.224 header.
  737. if (NULL == (*ppBufOut = (LPBYTE)LocalAlloc(0, cbBufInTotal
  738. + Sizes.cbHeader + Sizes.cbTrailer +
  739. sizeof(X224_DATA_PACKET))))
  740. return LastError = TPRTSEC_NOMEM;
  741. pbTemp = *ppBufOut + sizeof(X224_DATA_PACKET);
  742. //
  743. // prepare data for SecBuffer
  744. //
  745. Buffers[0].pvBuffer = pbTemp;
  746. Buffers[0].cbBuffer = Sizes.cbHeader;
  747. Buffers[0].BufferType = SECBUFFER_STREAM_HEADER;
  748. Buffers[1].pvBuffer = pbTemp + Sizes.cbHeader;
  749. // Copy the user's data
  750. CopyMemory(Buffers[1].pvBuffer, pBufIn1, cbBufIn1);
  751. if (NULL != pBufIn2) {
  752. CopyMemory((PVoid) ((PUChar) (Buffers[1].pvBuffer) + cbBufIn1),
  753. pBufIn2, cbBufIn2);
  754. }
  755. Buffers[1].cbBuffer = cbBufInTotal;
  756. Buffers[1].BufferType = SECBUFFER_DATA;
  757. Buffers[2].pvBuffer = pbTemp + Sizes.cbHeader + cbBufInTotal;
  758. Buffers[2].cbBuffer = Sizes.cbTrailer;
  759. Buffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
  760. Buffers[3].pvBuffer = NULL;
  761. Buffers[3].cbBuffer = 0;
  762. Buffers[3].BufferType = SECBUFFER_EMPTY;
  763. Buffer.cBuffers = 4;
  764. Buffer.pBuffers = Buffers;
  765. Buffer.ulVersion = SECBUFFER_VERSION;
  766. #ifdef DUMP
  767. dumpbytes("data BEFORE encryption", (PBYTE)Buffers[1].pvBuffer,
  768. Buffers[1].cbBuffer);
  769. #endif // DUMP
  770. // Call the semi-documented SealMessage function (Reserved3)
  771. scRet = ((SEAL_MESSAGE_FN)pSecurityInterface->pfnTable->Reserved3)(
  772. &hContext, 0, &Buffer, 0);
  773. if (scRet != ERROR_SUCCESS)
  774. {
  775. //
  776. // Map the SSPI error.
  777. //
  778. ERROR_OUT(("SealMessage failed: %x", scRet));
  779. LocalFree(*ppBufOut);
  780. return LastError = TPRTSEC_SSPIFAIL;
  781. }
  782. // We also have to add the X.224 header.
  783. *pcbBufOut = cbBufInTotal + Sizes.cbHeader + Sizes.cbTrailer + sizeof(X224_DATA_PACKET);
  784. memcpy (*ppBufOut, g_X224Header, sizeof(X224_DATA_PACKET));
  785. AddRFCSize(*ppBufOut, *pcbBufOut);
  786. #ifdef TESTHACKS
  787. // Inject an error...
  788. if (GetAsyncKeyState(VK_CONTROL)&0x8000) {
  789. OutputDebugString("*** INJECTING ERROR IN OUTGOING PACKET ***\n\r");
  790. pbTemp[(*pcbBufOut - sizeof(X224_DATA_PACKET))/2] ^= 0x55;
  791. }
  792. #endif //TESTHACKS
  793. #ifdef DUMP
  794. dumpbytes("data AFTER encryption", pbTemp, *pcbBufOut - sizeof(X224_DATA_PACKET));
  795. #endif // DUMP
  796. TRACE_OUT(("SealMessage returned Buffer = %p, EncryptBytes = %d, UnencryptBytes = %d", pbTemp,
  797. *pcbBufOut - sizeof(X224_DATA_PACKET), cbBufInTotal));
  798. return LastError = TPRTSEC_NOERROR;
  799. }
  800. /////////////////////////////////////////////////////////////////////////////
  801. //
  802. // Decrypt
  803. //
  804. // Description:
  805. // Decrypts a buffer received using SCHANNEL by calling UnsealMessage().
  806. //
  807. // Parameters:
  808. // pBuf - buffer to be decrypted
  809. // cbBufIn - length of buffer to be decrypted
  810. //
  811. TransportSecurityError SecurityContext::Decrypt( PBYTE pBuf, DWORD cbBuf)
  812. {
  813. SecBufferDesc Buffer;
  814. SecBuffer Buffers[4];
  815. DWORD scRet = ERROR_SUCCESS;
  816. SecBuffer * pDataBuffer;
  817. int i;
  818. LastError = TPRTSEC_SSPIFAIL;
  819. ASSERT(SECCTX_STATE_INIT_COMPLETE == scstate ||
  820. SECCTX_STATE_ACCEPT_COMPLETE == scstate);
  821. if (SECCTX_STATE_INIT_COMPLETE != scstate &&
  822. SECCTX_STATE_ACCEPT_COMPLETE != scstate)
  823. return LastError = TPRTSEC_INCOMPLETE_CONTEXT;
  824. ASSERT(!IsBadWritePtr(pBuf,cbBuf));
  825. #ifdef TESTHACKS
  826. // Inject an error...
  827. if ( GetAsyncKeyState(VK_SHIFT) & 0x8000 ) {
  828. OutputDebugString("*** INJECTING ERROR IN INCOMING PACKET ***\n\r");
  829. pBuf[cbBuf/2] ^= 0x55;
  830. }
  831. #endif //TESTHACKS
  832. //
  833. // prepare data the SecBuffer for a call to SSL/PCT decryption code.
  834. //
  835. Buffers[0].pvBuffer = pBuf;
  836. Buffers[0].cbBuffer = cbBuf;
  837. Buffers[0].BufferType = SECBUFFER_DATA;
  838. Buffers[1].pvBuffer = NULL;
  839. Buffers[1].cbBuffer = 0;
  840. Buffers[1].BufferType = SECBUFFER_EMPTY;
  841. Buffers[2].pvBuffer = NULL;
  842. Buffers[2].cbBuffer = 0;
  843. Buffers[2].BufferType = SECBUFFER_EMPTY;
  844. Buffers[3].pvBuffer = NULL;
  845. Buffers[3].cbBuffer = 0;
  846. Buffers[3].BufferType = SECBUFFER_EMPTY;
  847. Buffer.cBuffers = 4;
  848. Buffer.pBuffers = Buffers;
  849. Buffer.ulVersion = SECBUFFER_VERSION;
  850. // Call the semi-documented UnsealMessage function (Reserved4)
  851. #ifdef DUMP
  852. dumpbytes("data BEFORE decryption:", (PBYTE)Buffers[0].pvBuffer,
  853. Buffers[0].cbBuffer);
  854. #endif // DUMP
  855. scRet = ((UNSEAL_MESSAGE_FN)pSecurityInterface->pfnTable->Reserved4)(
  856. &hContext, &Buffer, 0, NULL);
  857. pDataBuffer = NULL;
  858. for( i=0; i<4; i++ )
  859. {
  860. if ( NULL == pDataBuffer && SECBUFFER_DATA == Buffers[i].BufferType )
  861. {
  862. pDataBuffer = &Buffers[i];
  863. }
  864. }
  865. if ( NULL == pDataBuffer )
  866. {
  867. ERROR_OUT(("Unseal: no data buffer found"));
  868. return LastError = TPRTSEC_SSPIFAIL;
  869. }
  870. #ifdef DUMP
  871. dumpbytes("data AFTER decryption:", (PBYTE)pDataBuffer->pvBuffer,
  872. pDataBuffer->cbBuffer);
  873. #endif // DUMP
  874. if (scRet != ERROR_SUCCESS)
  875. {
  876. ERROR_OUT(("UnsealMessage failed with [%x]", scRet));
  877. return LastError = TPRTSEC_SSPIFAIL;
  878. }
  879. return LastError = TPRTSEC_NOERROR;
  880. }
  881. TransportSecurityError SecurityContext::AdvanceState(PBYTE pIncomingData,
  882. DWORD cbBuf)
  883. {
  884. TRACE_OUT(("AdvanceState: state %d using data %x (%d)",
  885. scstate, pIncomingData, cbBuf ));
  886. switch ( scstate )
  887. {
  888. case SECCTX_STATE_INIT:
  889. if ( TPRTSEC_NOERROR != Initialize( pIncomingData, cbBuf ) )
  890. {
  891. WARNING_OUT(("AdvanceState: Initialize failed in INIT"));
  892. goto error;
  893. }
  894. break;
  895. case SECCTX_STATE_ACCEPT:
  896. case SECCTX_STATE_NEW:
  897. if ( TPRTSEC_NOERROR != Accept( pIncomingData, cbBuf ) )
  898. {
  899. WARNING_OUT(("AdvanceState: Accept failed in ACCEPT or NEW"));
  900. goto error;
  901. }
  902. break;
  903. case SECCTX_STATE_INIT_COMPLETE:
  904. case SECCTX_STATE_ACCEPT_COMPLETE:
  905. case SECCTX_STATE_ERROR:
  906. default:
  907. ERROR_OUT(("AdvanceState: called in unexpected state %d"));
  908. goto error;
  909. }
  910. return LastError = TPRTSEC_NOERROR;
  911. error:
  912. scstate = SECCTX_STATE_ERROR;
  913. return LastError;
  914. }
  915. #define CHECKFLAGS (CERT_STORE_REVOCATION_FLAG |\
  916. CERT_STORE_SIGNATURE_FLAG |\
  917. CERT_STORE_TIME_VALIDITY_FLAG)
  918. BOOL SecurityContext::Verify(VOID)
  919. {
  920. BOOL fRet = TRUE;
  921. DWORD sc;
  922. PCCERT_CONTEXT pCert = NULL, pIssuerCert = NULL, pCACert = NULL;
  923. DWORD dwFlags;
  924. HCERTSTORE hStore = NULL;
  925. HCERTSTORE hCAStore = NULL;
  926. CHAR * pIssuer = NULL;
  927. ASSERT( NULL != pSecurityInterface );
  928. // Get the subject cert context
  929. sc = pSecurityInterface->pfnTable->QueryContextAttributes(&hContext,
  930. SECPKG_ATTR_REMOTE_CERT_CONTEXT,
  931. (PVOID)&pCert );
  932. if ( SEC_E_OK != sc )
  933. {
  934. ERROR_OUT(("QueryContextAttributes (REMOTE_CERT_CONTEXT) failed"));
  935. goto error;
  936. }
  937. if ( NULL == pCert )
  938. {
  939. // The caller is not authenticated
  940. WARNING_OUT(("No remote cred data"));
  941. goto error;
  942. }
  943. // Open the root store for certificate verification
  944. hStore = CertOpenSystemStore(0, "Root");
  945. if( NULL == hStore )
  946. {
  947. ERROR_OUT(("Couldn't open root certificate store"));
  948. goto error;
  949. }
  950. dwFlags = CHECKFLAGS;
  951. // Get the issuer of this cert
  952. pIssuerCert = CertGetIssuerCertificateFromStore(
  953. hStore,
  954. pCert,
  955. NULL,
  956. &dwFlags );
  957. // If the issuer of the certificate cannot be found in the root store,
  958. // check the CA store iteratively until we work our way back to a root
  959. // certificate
  960. pCACert = pCert;
  961. while ( NULL == pIssuerCert )
  962. {
  963. PCCERT_CONTEXT pTmpCert;
  964. if ( NULL == hCAStore )
  965. {
  966. hCAStore = CertOpenSystemStore(0, "CA");
  967. if ( NULL == hCAStore )
  968. {
  969. ERROR_OUT(("Couldn't open CA certificate store"));
  970. goto error;
  971. }
  972. }
  973. dwFlags = CERT_STORE_REVOCATION_FLAG |
  974. CERT_STORE_SIGNATURE_FLAG |
  975. CERT_STORE_TIME_VALIDITY_FLAG;
  976. pTmpCert = CertGetIssuerCertificateFromStore(
  977. hCAStore,
  978. pCACert,
  979. NULL,
  980. &dwFlags );
  981. if ( NULL == pTmpCert )
  982. {
  983. TRACE_OUT(("Issuer not found in CA store either"));
  984. break;
  985. }
  986. if ( pCACert != pCert )
  987. CertFreeCertificateContext(pCACert);
  988. pCACert = pTmpCert;
  989. if ((( CERT_STORE_REVOCATION_FLAG & dwFlags ) &&
  990. !( CERT_STORE_NO_CRL_FLAG & dwFlags )) ||
  991. ( CERT_STORE_SIGNATURE_FLAG & dwFlags ) ||
  992. ( CERT_STORE_TIME_VALIDITY_FLAG & dwFlags ))
  993. {
  994. TRACE_OUT(("Problem with issuer in CA store: %x", dwFlags));
  995. break;
  996. }
  997. dwFlags = CERT_STORE_REVOCATION_FLAG |
  998. CERT_STORE_SIGNATURE_FLAG |
  999. CERT_STORE_TIME_VALIDITY_FLAG;
  1000. pIssuerCert = CertGetIssuerCertificateFromStore(
  1001. hStore,
  1002. pCACert,
  1003. NULL,
  1004. &dwFlags );
  1005. }
  1006. if ( pCACert != pCert )
  1007. CertFreeCertificateContext ( pCACert );
  1008. if ( NULL == pIssuerCert )
  1009. {
  1010. WARNING_OUT(("Verify: Can't find issuer in store"));
  1011. }
  1012. // Check certificate
  1013. if ( NULL != pIssuerCert && 0 != dwFlags )
  1014. {
  1015. if ( dwFlags & CERT_STORE_SIGNATURE_FLAG )
  1016. {
  1017. WARNING_OUT(("Verify: Signature invalid"));
  1018. }
  1019. if ( dwFlags & CERT_STORE_TIME_VALIDITY_FLAG )
  1020. {
  1021. WARNING_OUT(("Verify: Cert expired"));
  1022. }
  1023. if ( dwFlags & CERT_STORE_REVOCATION_FLAG )
  1024. {
  1025. if (!(dwFlags & CERT_STORE_NO_CRL_FLAG))
  1026. {
  1027. WARNING_OUT(("Verify: Cert revoked"));
  1028. }
  1029. else
  1030. {
  1031. // We have no CRL for this issuer, do not
  1032. // treat as revoked by default:
  1033. dwFlags &= ~CERT_STORE_REVOCATION_FLAG;
  1034. }
  1035. }
  1036. }
  1037. //
  1038. // Check for no-incomplete-certs policy
  1039. //
  1040. #if 0
  1041. if (( NULL == pIssuerCert || ( 0 != ( CHECKFLAGS & dwFlags )))
  1042. {
  1043. WARNING_OUT(("Verify: policy prevents cert use"));
  1044. fRet = FALSE;
  1045. goto error;
  1046. }
  1047. //
  1048. // Is there a mandatory issuer?
  1049. //
  1050. if ( lstrlen(rePol.GetString( REGVAL_POL_ISSUER )))
  1051. {
  1052. DWORD cbIssuer;
  1053. //
  1054. // Get the issuer information
  1055. //
  1056. cbIssuer = CertNameToStr (
  1057. pCert->dwCertEncodingType,
  1058. &pCert->pCertInfo->Issuer,
  1059. CERT_FORMAT_FLAGS,
  1060. NULL, 0);
  1061. if ( 0 == cbIssuer )
  1062. {
  1063. ERROR_OUT(("GetUserInfo: no issuer string"));
  1064. fRet = FALSE;
  1065. goto error;
  1066. }
  1067. pIssuer = new CHAR[cbIssuer + 1];
  1068. if ( NULL == pIssuer )
  1069. {
  1070. ERROR_OUT(("GetUserInfo: error allocating issuer name"));
  1071. }
  1072. if ( 0 >= CertNameToStr (
  1073. pCert->dwCertEncodingType,
  1074. &pCert->pCertInfo->Issuer,
  1075. CERT_FORMAT_FLAGS,
  1076. pIssuer, cbIssuer+1))
  1077. {
  1078. ERROR_OUT(("GetUserInfo: error getting issuer string"));
  1079. fRet = FALSE;
  1080. goto error;
  1081. }
  1082. if ( lstrcmp ( rePol.GetString(REGVAL_POL_ISSUER),
  1083. pIssuer ))
  1084. {
  1085. WARNING_OUT(("Issuer (%s) didn't match policy (%s)",
  1086. pIssuer, rePol.GetString(REGVAL_POL_ISSUER)));
  1087. fRet = FALSE;
  1088. }
  1089. }
  1090. #endif
  1091. error:
  1092. if ( NULL != hStore )
  1093. {
  1094. CertCloseStore(hStore, 0);
  1095. }
  1096. if ( NULL != hCAStore )
  1097. {
  1098. CertCloseStore(hCAStore, 0);
  1099. }
  1100. if ( NULL != pCert )
  1101. {
  1102. CertFreeCertificateContext ( pCert );
  1103. }
  1104. if ( NULL != pIssuerCert )
  1105. {
  1106. CertFreeCertificateContext ( pIssuerCert );
  1107. }
  1108. if ( NULL != pIssuer )
  1109. {
  1110. delete pIssuer;
  1111. }
  1112. return fRet;
  1113. }
  1114. BOOL SecurityContext::GetUserCert(PBYTE pInfo, PDWORD pcbInfo)
  1115. {
  1116. BOOL fRet = FALSE;
  1117. DWORD sc;
  1118. PCCERT_CONTEXT pCert = NULL;
  1119. ASSERT( NULL != pSecurityInterface );
  1120. //
  1121. // Get the certificate from the context
  1122. //
  1123. sc = pSecurityInterface->pfnTable->QueryContextAttributes(&hContext,
  1124. SECPKG_ATTR_REMOTE_CERT_CONTEXT,
  1125. (PVOID)&pCert );
  1126. if ( SEC_E_OK != sc )
  1127. {
  1128. ERROR_OUT(("QueryContextAttributes failed"));
  1129. goto cleanup;
  1130. }
  1131. if ( NULL == pCert )
  1132. {
  1133. // The caller is not authenticated
  1134. WARNING_OUT(("No remote cred data"));
  1135. goto cleanup;
  1136. }
  1137. if ( NULL != pInfo && *pcbInfo >= pCert->cbCertEncoded )
  1138. {
  1139. memcpy ( pInfo, pCert->pbCertEncoded, pCert->cbCertEncoded );
  1140. }
  1141. *pcbInfo = pCert->cbCertEncoded;
  1142. fRet = TRUE;
  1143. cleanup:
  1144. if ( NULL != pCert )
  1145. {
  1146. CertFreeCertificateContext ( pCert );
  1147. }
  1148. return fRet;
  1149. }
  1150.