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.

1429 lines
41 KiB

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