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.

2953 lines
79 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1991 - 1999
  3. Module Name:
  4. secclnt.cxx
  5. Abstract:
  6. Implementation of security objects.
  7. Author:
  8. Michael Montague (mikemon) 11-Apr-1992
  9. Revision History:
  10. 21-Feb-1997 jroberts Added some SSL support.
  11. --*/
  12. #include <precomp.hxx>
  13. #include <wincrypt.h>
  14. #include <rpcssl.h>
  15. #include <cryptimp.hxx>
  16. #include <rpccfg.h>
  17. #include <spseal.h>
  18. #include <schnlsp.h>
  19. #include <hndlsvr.hxx>
  20. int SecuritySupportLoaded = 0;
  21. int FailedToLoad = 0;
  22. unsigned long NumberOfProviders = 0;
  23. unsigned long LoadedProviders = 0;
  24. unsigned long AvailableProviders = 0;
  25. SECURITY_PROVIDER_INFO PAPI * ProviderList = 0;
  26. MUTEX * SecurityCritSect; // Mutex for the Server credentials cache.
  27. // Incremented each time we leak SECURITY_CONTEXT::SecurityContext
  28. // due to RpcSecurityInterface->DeleteSecurityContext
  29. // returning SEC_E_INSUFFICIENT_MEMORY.
  30. unsigned int nSecurityContextsLeaked = 0;
  31. struct PACKAGE_LEG_INFO
  32. {
  33. DWORD Package;
  34. PACKAGE_LEG_COUNT Legs;
  35. };
  36. const PACKAGE_LEG_INFO PredefinedPackageLegInfo[] =
  37. {
  38. { RPC_C_AUTHN_WINNT, ThreeLegs },
  39. { RPC_C_AUTHN_GSS_NEGOTIATE,EvenNumberOfLegs },
  40. { RPC_C_AUTHN_GSS_KERBEROS, EvenNumberOfLegs },
  41. { RPC_C_AUTHN_GSS_SCHANNEL, EvenNumberOfLegs },
  42. { RPC_C_AUTHN_DPA, ThreeLegs },
  43. { RPC_C_AUTHN_DCE_PRIVATE, ThreeLegs },
  44. { 0x44, ThreeLegs }, // RPC_C_AUTHN_NETLOGON from net\svcdlls\logonsrv\nlbind.h
  45. { 0, LegsUnknown }
  46. };
  47. // defined in principal.cxx
  48. //
  49. extern
  50. DWORD
  51. RpcCertMatchPrincipalName(
  52. PCCERT_CONTEXT Context,
  53. RPC_CHAR PrincipalName[]
  54. );
  55. #ifdef UNICODE
  56. #define SEC_TCHAR SEC_WCHAR
  57. #else
  58. #define SEC_TCHAR SEC_CHAR
  59. #endif
  60. RPC_STATUS
  61. FindSecurityPackage (
  62. IN unsigned long AuthenticationService,
  63. IN unsigned long AuthenticationLevel,
  64. OUT unsigned int __RPC_FAR * ProviderIndex,
  65. OUT unsigned int __RPC_FAR * PackageIndex
  66. );
  67. RPC_STATUS
  68. InsureSecuritySupportLoaded (
  69. )
  70. /*++
  71. Routine Description:
  72. This routine insures that the security support is loaded; if it is not
  73. loaded, then we go ahead and load it.
  74. Return Value:
  75. A zero result indicates that security support has successfully been
  76. loaded, and is ready to go.
  77. --*/
  78. {
  79. RPC_STATUS Status = RPC_S_OK;
  80. if ( SecuritySupportLoaded != 0 )
  81. {
  82. return(0);
  83. }
  84. RequestGlobalMutex();
  85. if ( SecuritySupportLoaded != 0 )
  86. {
  87. ClearGlobalMutex();
  88. return(0);
  89. }
  90. SecurityCritSect = new MUTEX(&Status,
  91. TRUE // pre-allocate semaphore
  92. );
  93. if (SecurityCritSect == 0)
  94. {
  95. Status = RPC_S_OUT_OF_MEMORY;
  96. }
  97. if (Status == RPC_S_OK)
  98. {
  99. SecuritySupportLoaded = 1;
  100. }
  101. ClearGlobalMutex();
  102. return (Status);
  103. }
  104. RPC_STATUS
  105. IsAuthenticationServiceSupported (
  106. IN unsigned long AuthenticationService
  107. )
  108. /*++
  109. Routine Description:
  110. This routine is used to determine whether or not an authentication
  111. service is supported by the current configuration.
  112. Arguments:
  113. AuthenticationService - Supplies a proposed authentication service.
  114. Return Value:
  115. RPC_S_OK - The supplied authentication service is supported by the
  116. current configuration.
  117. RPC_S_UNKNOWN_AUTHN_SERVICE - The supplied authentication service
  118. is unknown, and not supported by the current configuration.
  119. --*/
  120. {
  121. unsigned int PackageIndex, ProviderIndex;
  122. // First make sure that the security support has been loaded.
  123. if ( InsureSecuritySupportLoaded() != RPC_S_OK )
  124. {
  125. return(RPC_S_OUT_OF_MEMORY);
  126. }
  127. return ( FindSecurityPackage(
  128. AuthenticationService,
  129. RPC_C_AUTHN_LEVEL_CONNECT,
  130. &ProviderIndex,
  131. &PackageIndex
  132. ) );
  133. }
  134. RPC_STATUS
  135. FindSecurityPackage (
  136. IN unsigned long AuthenticationService,
  137. IN unsigned long AuthenticationLevel,
  138. OUT unsigned int __RPC_FAR * ProviderIndex,
  139. OUT unsigned int __RPC_FAR * PackageIndex
  140. )
  141. /*++
  142. Routine Description:
  143. The methods used to acquire credentials for the client and the server use
  144. this routine to find a security package, given the an authentication
  145. service.
  146. Arguments:
  147. AuthenticationService - Supplies the authentication service to be used
  148. (for the credentials and for the context).
  149. AuthenticationLevel - Supplies the authentication level to be used by
  150. these credentials. It will already have been mapped by the protocol
  151. module into the final level.
  152. RpcStatus - Returns the status of the operation. It will be one of the
  153. following values.
  154. RPC_S_OK - The return value from this routine is the index of
  155. the appropriate security package.
  156. RPC_S_UNKNOWN_AUTHN_SERVICE - The specified authentication service is
  157. not supported by the current configuration.
  158. RPC_S_UNKNOWN_AUTHN_LEVEL - The specified authentication level is not
  159. supported by the requested authentication service.
  160. Return Value:
  161. If RpcStatus contains RPC_S_OK, then the index of the appropriate
  162. security package will be returned.
  163. --*/
  164. {
  165. unsigned int Index, i;
  166. INIT_SECURITY_INTERFACE InitSecurityInterface;
  167. PSecurityFunctionTable SecurityInterface = 0;
  168. SecPkgInfo PAPI * tmpPkgList;
  169. SECURITY_PACKAGE_INFO * SecurityPackages;
  170. SECURITY_PROVIDER_INFO PAPI * List;
  171. unsigned long NumberOfPackages, Total;
  172. RPC_CHAR * DllName = NULL;
  173. DLL * ProviderDll;
  174. RPC_STATUS Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  175. // First make sure that the security support has been loaded.
  176. if ( InsureSecuritySupportLoaded() != RPC_S_OK )
  177. {
  178. return(RPC_S_OUT_OF_MEMORY);
  179. }
  180. // 0xFFFF ia a "not-an-RPC-ID", indicating that the protocol
  181. // is not for use by RPC.
  182. if (AuthenticationService == 0xFFFF)
  183. {
  184. return(RPC_S_UNKNOWN_AUTHN_SERVICE);
  185. }
  186. SecurityCritSect->Request();
  187. List = ProviderList;
  188. for (i = 0; i < LoadedProviders; i ++)
  189. {
  190. SecurityPackages = List->SecurityPackages;
  191. NumberOfPackages = List->Count;
  192. for (Index = 0;Index < (unsigned int) NumberOfPackages;Index++)
  193. {
  194. if ( SecurityPackages[Index].PackageInfo.wRPCID == AuthenticationService )
  195. {
  196. if ( (AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
  197. || ( AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT) )
  198. {
  199. if ( (SecurityPackages[Index].PackageInfo.fCapabilities
  200. & SECPKG_FLAG_INTEGRITY) == 0 )
  201. {
  202. Status = RPC_S_UNKNOWN_AUTHN_LEVEL;
  203. goto Cleanup;
  204. }
  205. }
  206. if ( AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY )
  207. {
  208. if ( (SecurityPackages[Index].PackageInfo.fCapabilities
  209. & SECPKG_FLAG_PRIVACY) == 0 )
  210. {
  211. Status = RPC_S_UNKNOWN_AUTHN_LEVEL;
  212. goto Cleanup;
  213. }
  214. }
  215. Status = RPC_S_OK;
  216. *ProviderIndex = i;
  217. *PackageIndex = Index;
  218. break;
  219. }
  220. } //For over all packages in one provider(dll)
  221. if (Status == RPC_S_OK)
  222. {
  223. SecurityCritSect->Clear();
  224. return(Status);
  225. }
  226. List++;
  227. } //For over all providers(dll)
  228. if ((LoadedProviders == AvailableProviders) && (LoadedProviders != 0))
  229. {
  230. goto Cleanup;
  231. }
  232. Status = RpcGetSecurityProviderInfo (
  233. AuthenticationService, &DllName, &Total);
  234. ASSERT(!RpcpCheckHeap());
  235. if (Status != RPC_S_OK)
  236. {
  237. goto Cleanup;
  238. }
  239. if (ProviderList == 0)
  240. {
  241. ProviderList = (SECURITY_PROVIDER_INFO PAPI *)
  242. new char [sizeof(SECURITY_PROVIDER_INFO) * Total];
  243. if (ProviderList == 0)
  244. {
  245. Status = RPC_S_OUT_OF_MEMORY;
  246. goto Cleanup;
  247. }
  248. AvailableProviders = Total;
  249. }
  250. else
  251. {
  252. List = ProviderList;
  253. for (i = 0; i < LoadedProviders; i ++)
  254. {
  255. if (RpcpStringCompare(DllName, List->ProviderDllName) == 0)
  256. {
  257. delete DllName;
  258. Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  259. goto Cleanup;
  260. }
  261. List++;
  262. }
  263. }
  264. ProviderDll = new DLL(DllName, &Status);
  265. if ((ProviderDll == NULL) && (Status == RPC_S_INVALID_ARG))
  266. {
  267. Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  268. }
  269. if (Status != RPC_S_OK)
  270. {
  271. goto Cleanup;
  272. }
  273. ASSERT(!RpcpCheckHeap());
  274. InitSecurityInterface = (INIT_SECURITY_INTERFACE_W)
  275. ProviderDll->GetEntryPoint(SECURITY_ENTRYPOINT_ANSIW);
  276. if ( InitSecurityInterface == 0 )
  277. {
  278. delete ProviderDll;
  279. Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  280. goto Cleanup;
  281. }
  282. SecurityInterface = (*InitSecurityInterface)();
  283. if ( (SecurityInterface == 0)
  284. || (SecurityInterface->dwVersion
  285. < SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION) )
  286. {
  287. delete ProviderDll;
  288. Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  289. goto Cleanup;
  290. }
  291. Status = (*SecurityInterface->EnumerateSecurityPackages)(
  292. &NumberOfPackages, &tmpPkgList);
  293. if ( Status != SEC_E_OK)
  294. {
  295. delete ProviderDll;
  296. if (Status == SEC_E_INSUFFICIENT_MEMORY)
  297. {
  298. Status = RPC_S_OUT_OF_MEMORY;
  299. }
  300. else
  301. {
  302. VALIDATE(Status) {
  303. SEC_E_SECPKG_NOT_FOUND
  304. } END_VALIDATE;
  305. Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  306. }
  307. goto Cleanup;
  308. }
  309. ProviderList[LoadedProviders].Count = NumberOfPackages;
  310. ProviderList[LoadedProviders].RpcSecurityInterface = SecurityInterface;
  311. ProviderList[LoadedProviders].ProviderDll = ProviderDll;
  312. ProviderList[LoadedProviders].ProviderDllName = DllName;
  313. *ProviderIndex = LoadedProviders;
  314. //
  315. // Fill in the SecurityPackages member for this Provider.
  316. //
  317. ProviderList[LoadedProviders].SecurityPackages =
  318. (SECURITY_PACKAGE_INFO *) new char
  319. [sizeof(SECURITY_PACKAGE_INFO) * NumberOfPackages];
  320. if (ProviderList[LoadedProviders].SecurityPackages == NULL)
  321. {
  322. Status = RPC_S_OUT_OF_MEMORY;
  323. goto Cleanup;
  324. }
  325. //
  326. // Save the SecPkgInfo array to the SecurityPackages structure.
  327. //
  328. for (i = 0; i < NumberOfPackages; i++)
  329. {
  330. ProviderList[LoadedProviders].
  331. SecurityPackages[i].
  332. PackageInfo = tmpPkgList[i];
  333. ProviderList[LoadedProviders].
  334. SecurityPackages[i].
  335. ServerSecurityCredentials = NULL;
  336. }
  337. SecurityPackages = ProviderList[LoadedProviders].SecurityPackages;
  338. Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  339. for (i = 0; i < NumberOfPackages; i++)
  340. {
  341. if ( SecurityPackages[i].PackageInfo.wRPCID == AuthenticationService )
  342. {
  343. if ( ( AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY )
  344. ||( AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT) )
  345. {
  346. if ( (SecurityPackages[i].PackageInfo.fCapabilities
  347. & SECPKG_FLAG_INTEGRITY) == 0 )
  348. {
  349. Status = RPC_S_UNKNOWN_AUTHN_LEVEL;
  350. continue;
  351. }
  352. }
  353. if ( AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY )
  354. {
  355. if ( (SecurityPackages[i].PackageInfo.fCapabilities
  356. & SECPKG_FLAG_PRIVACY) == 0 )
  357. {
  358. Status = RPC_S_UNKNOWN_AUTHN_LEVEL;
  359. continue;
  360. }
  361. }
  362. *PackageIndex = i;
  363. Status = RPC_S_OK;
  364. break;
  365. }
  366. }
  367. LoadedProviders++;
  368. Cleanup:
  369. SecurityCritSect->Clear();
  370. return(Status);
  371. }
  372. RPC_STATUS
  373. FindServerCredentials (
  374. IN RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
  375. IN void __RPC_FAR * Arg,
  376. IN unsigned long AuthenticationService,
  377. IN unsigned long AuthenticationLevel,
  378. IN RPC_CHAR __RPC_FAR * Principal,
  379. IN OUT SECURITY_CREDENTIALS ** SecurityCredentials
  380. )
  381. /*++
  382. Routine Description:
  383. The method is used to find cached server credentials for use by the
  384. server.
  385. Arguments:
  386. AuthenticationService - Supplies the authentication service to be used
  387. (for the credentials and for the context).
  388. AuthenticationLevel - Supplies the authentication level to be used by
  389. these credentials. It will already have been mapped by the protocol
  390. module into the final level.
  391. SecurityCredentials - TBS
  392. RpcStatus - Returns the status of the operation. It will be one of the
  393. following values.
  394. RPC_S_OK - The return value from this routine is the index of
  395. the appropriate security package.
  396. RPC_S_UNKNOWN_AUTHN_SERVICE - The specified authentication service is
  397. not supported by the current configuration.
  398. RPC_S_UNKNOWN_AUTHN_LEVEL - The specified authentication level is not
  399. supported by the requested authentication service.
  400. Return Value:
  401. If RpcStatus contains RPC_S_OK, then valid credentials are passed
  402. back.
  403. --*/
  404. {
  405. SECURITY_STATUS SecurityStatus;
  406. TimeStamp TimeStamp;
  407. RPC_STATUS RpcStatus, CredStatus = RPC_S_OK;
  408. PSecurityFunctionTable RpcSecurityInterface;
  409. SECURITY_PACKAGE_INFO *pPackageInfo = 0;
  410. SECURITY_CREDENTIALS *pSecCredentials = 0;
  411. CredHandle tmpCredHandle;
  412. unsigned int ProviderIndex;
  413. unsigned int PackageIndex;
  414. //
  415. // NULL out the OUT parameters.
  416. //
  417. *SecurityCredentials = NULL;
  418. //
  419. // Find the right security package
  420. //
  421. RpcStatus = FindSecurityPackage(
  422. AuthenticationService,
  423. AuthenticationLevel,
  424. &ProviderIndex,
  425. &PackageIndex
  426. );
  427. if (RpcStatus != RPC_S_OK)
  428. {
  429. RpcpErrorAddRecord (EEInfoGCRuntime,
  430. RpcStatus,
  431. EEInfoDLFindServerCredentials10,
  432. AuthenticationService,
  433. AuthenticationLevel);
  434. return (RpcStatus);
  435. }
  436. //
  437. // Now, get the server-credentials for this security package.
  438. //
  439. pPackageInfo = &(ProviderList[ProviderIndex].
  440. SecurityPackages[PackageIndex]
  441. );
  442. // Protect the access
  443. SecurityCritSect->Request();
  444. //
  445. // Check to see if credentials have already been acquired for this
  446. // package. If yes, return them.
  447. //
  448. if (pPackageInfo->ServerSecurityCredentials)
  449. {
  450. *SecurityCredentials = pPackageInfo->ServerSecurityCredentials;
  451. // Add a reference for the caller.
  452. pPackageInfo->ServerSecurityCredentials->ReferenceCredentials();
  453. SecurityCritSect->Clear();
  454. return (RPC_S_OK);
  455. }
  456. //
  457. // Allocate a new set of credentials. Ref count is 1, if successful.
  458. //
  459. pSecCredentials = new SECURITY_CREDENTIALS(&CredStatus);
  460. if (pSecCredentials == NULL)
  461. {
  462. SecurityCritSect->Clear();
  463. return (RPC_S_OUT_OF_MEMORY);
  464. }
  465. if (CredStatus != RPC_S_OK)
  466. {
  467. delete pSecCredentials;
  468. SecurityCritSect->Clear();
  469. return (CredStatus);
  470. }
  471. //
  472. // This is the first time Credentials are being acquired for this
  473. // package. Acquire them now.
  474. //
  475. RpcSecurityInterface = ProviderList[ProviderIndex].RpcSecurityInterface;
  476. SecurityStatus = (*RpcSecurityInterface->AcquireCredentialsHandle)(
  477. (SEC_TCHAR __SEC_FAR *) Principal,
  478. pPackageInfo->PackageInfo.Name,
  479. SECPKG_CRED_INBOUND,
  480. 0,
  481. Arg,
  482. (SEC_GET_KEY_FN) GetKeyFn,
  483. Arg,
  484. &(pSecCredentials->CredentialsHandle),
  485. &TimeStamp
  486. );
  487. if (SecurityStatus != SEC_E_OK)
  488. {
  489. SetExtendedError(SecurityStatus);
  490. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  491. SecurityStatus,
  492. EEInfoDLFindServerCredentials20,
  493. Principal,
  494. pPackageInfo->PackageInfo.Name);
  495. SecurityCritSect->Clear();
  496. delete pSecCredentials;
  497. switch (SecurityStatus)
  498. {
  499. case SEC_E_INSUFFICIENT_MEMORY:
  500. RpcStatus = RPC_S_OUT_OF_MEMORY;
  501. break;
  502. case SEC_E_SHUTDOWN_IN_PROGRESS:
  503. RpcStatus = ERROR_SHUTDOWN_IN_PROGRESS;
  504. break;
  505. case SEC_E_SECPKG_NOT_FOUND:
  506. RpcStatus = RPC_S_UNKNOWN_AUTHN_SERVICE;
  507. break;
  508. case SEC_E_NO_SPM:
  509. RpcStatus = RPC_S_SEC_PKG_ERROR;
  510. break;
  511. default:
  512. {
  513. #if DBG
  514. if ((SecurityStatus != SEC_E_NO_CREDENTIALS) &&
  515. (SecurityStatus != SEC_E_UNKNOWN_CREDENTIALS))
  516. {
  517. PrintToDebugger("RPC SEC: AcquireCredentialsForServer "
  518. "Returned 0x%x\n", SecurityStatus);
  519. }
  520. #endif
  521. RpcStatus = RPC_S_INVALID_AUTH_IDENTITY;
  522. }
  523. } // end of switch
  524. RpcpErrorAddRecord (EEInfoGCRuntime,
  525. RpcStatus,
  526. EEInfoDLFindServerCredentials30,
  527. SecurityStatus);
  528. return RpcStatus;
  529. }
  530. //
  531. // Setup the new Credentials.
  532. //
  533. pSecCredentials->Valid = TRUE;
  534. pSecCredentials->bServerCredentials = TRUE;
  535. pSecCredentials->AuthenticationService = AuthenticationService;
  536. pSecCredentials->ProviderIndex = ProviderIndex;
  537. pSecCredentials->PackageIndex = PackageIndex;
  538. //
  539. // Cache the new credentials.
  540. //
  541. pPackageInfo->ServerSecurityCredentials = pSecCredentials;
  542. // Add a reference for the Cache.
  543. pPackageInfo->ServerSecurityCredentials->ReferenceCredentials();
  544. *SecurityCredentials = pSecCredentials;
  545. SecurityCritSect->Clear();
  546. return (RPC_S_OK);
  547. }
  548. RPC_STATUS
  549. RemoveCredentialsFromCache (
  550. IN unsigned long AuthenticationService
  551. )
  552. /*++
  553. Routine Description:
  554. An RPC server can call RpcRegisterAuthInfo() a second time on the same
  555. Authentication Service to update the GetKeyFunction and Arg values.
  556. In this case, we need to flush our credentials cache so that when
  557. the server tries to acquires credentials again, the credentials can
  558. be acquired using the new values.
  559. Arguments:
  560. AuthenticationService - Supplies the authentication service to be used
  561. (for the credentials and for the context).
  562. Return Value:
  563. RPC_S_OK, If Cache has been successfully flushed.
  564. Return Value from FindSecurityPackage(), if not
  565. --*/
  566. {
  567. unsigned int ProviderIndex;
  568. unsigned int PackageIndex;
  569. SECURITY_PACKAGE_INFO *pPackageInfo = 0;
  570. RPC_STATUS RpcStatus;
  571. //
  572. // First, find the right security package
  573. //
  574. RpcStatus = FindSecurityPackage(
  575. AuthenticationService,
  576. RPC_C_AUTHN_LEVEL_DEFAULT, // Doesn't matter
  577. &ProviderIndex,
  578. &PackageIndex
  579. );
  580. ASSERT(RpcStatus == RPC_S_OK);
  581. if (RpcStatus != RPC_S_OK)
  582. {
  583. return (RpcStatus);
  584. }
  585. pPackageInfo = &(ProviderList[ProviderIndex].SecurityPackages[PackageIndex]);
  586. //
  587. // Flush the credentials.
  588. //
  589. SecurityCritSect->Request();
  590. if (pPackageInfo->ServerSecurityCredentials)
  591. {
  592. // Remove the reference maintained by the cache.
  593. pPackageInfo->ServerSecurityCredentials->DereferenceCredentials(TRUE);
  594. pPackageInfo->ServerSecurityCredentials = NULL;
  595. }
  596. SecurityCritSect->Clear();
  597. return (RPC_S_OK);
  598. }
  599. #define INVALID_INDEX 0xFFFF
  600. SECURITY_CREDENTIALS::SECURITY_CREDENTIALS (
  601. IN OUT RPC_STATUS PAPI * Status
  602. ) : CredentialsMutex(Status)
  603. /*++
  604. Routine Description:
  605. We need this here to keep the compiler happy.
  606. --*/
  607. {
  608. DefaultPrincName = NULL;
  609. ReferenceCount = 1;
  610. Valid = FALSE;
  611. bServerCredentials = FALSE;
  612. fDeleted = FALSE;
  613. // Initialize to invalid values.
  614. ProviderIndex = INVALID_INDEX;
  615. PackageIndex = INVALID_INDEX;
  616. }
  617. SECURITY_CREDENTIALS::~SECURITY_CREDENTIALS (
  618. )
  619. {
  620. PSecurityFunctionTable RpcSecurityInterface;
  621. if (DefaultPrincName != NULL)
  622. {
  623. RpcSecurityInterface = InquireProviderFunctionTable();
  624. ASSERT(RpcSecurityInterface != NULL);
  625. (*RpcSecurityInterface->FreeContextBuffer)(DefaultPrincName);
  626. }
  627. }
  628. void
  629. SECURITY_CREDENTIALS::ReferenceCredentials(
  630. )
  631. {
  632. CredentialsMutex.Request();
  633. ReferenceCount++;
  634. CredentialsMutex.Clear();
  635. }
  636. void
  637. SECURITY_CREDENTIALS::DereferenceCredentials(
  638. BOOL fRemoveIt OPTIONAL
  639. )
  640. {
  641. CredentialsMutex.Request();
  642. ReferenceCount--;
  643. ASSERT(((long)ReferenceCount) >= 0);
  644. if (fRemoveIt)
  645. {
  646. fDeleted = TRUE;
  647. }
  648. if (ReferenceCount == 0)
  649. {
  650. //
  651. // Server side SCENARIOS when (ReferenceCount == 0)
  652. //
  653. // a. RemoveCredentialsFromCache() removes the extra reference
  654. // held by the cache. It does so holding the cache Mutex ie.,
  655. // SecurityCritSect. So, no other thread can get a reference
  656. // on the credentials in the cache.
  657. //
  658. // b. DereferenceCredentials() has been called by one of the
  659. // threads possessing the cached credentials AND the cache
  660. // has already removed it's reference. Cache will remove it's
  661. // reference only when it removes this credential from the
  662. // cache. This implies no other thread could have gotten a
  663. // reference on the credentials in the cache, in the meantime.
  664. //
  665. // These two imply that ReferenceCount cannot change here. Also,
  666. // in case (a), credentials will soon be removed from the cache.
  667. // In case (b), credentials have already been removed.
  668. //
  669. if (bServerCredentials)
  670. {
  671. ASSERT(fDeleted);
  672. }
  673. CredentialsMutex.Clear();
  674. FreeCredentials();
  675. delete this;
  676. } // if (ReferenceCount == 0)
  677. else
  678. {
  679. CredentialsMutex.Clear();
  680. }
  681. }
  682. RPC_STATUS
  683. SECURITY_CREDENTIALS::AcquireCredentialsForClient (
  684. IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity,
  685. IN unsigned long AuthenticationService,
  686. IN unsigned long AuthenticationLevel
  687. )
  688. /*++
  689. Routine Description:
  690. We need to use this method in order to acquire security credentials. We
  691. need the security credentials so that we (as a client) can initialize
  692. a security context with a server. This method, with
  693. SECURITY_CREDENTIALS::FreeCredentials may cache security credentials,
  694. but that is transparent to clients of this class.
  695. Arguments:
  696. AuthIdentity - Supplies the security identity for which we wish to obtain
  697. credentials. If this argument is not supplied, then we use the
  698. security identity of this process.
  699. AuthenticationService - Supplies the authentication service to be used
  700. (for the credentials and for the context).
  701. AuthenticationLevel - Supplies the authentication level to be used by
  702. these credentials. It will already have been mapped by the protocol
  703. module into the final level.
  704. Return Value:
  705. RPC_S_OK - We now have security credentials for the requested
  706. authentication service.
  707. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to perform the
  708. operation.
  709. RPC_S_UNKNOWN_AUTHN_SERVICE - The specified authentication service is
  710. not supported by the current configuration.
  711. RPC_S_INVALID_AUTH_IDENTITY - The specified identity is not known to
  712. the requested authentication service.
  713. RPC_S_UNKNOWN_AUTHN_LEVEL - The specified authentication level is not
  714. supported by the requested authentication service.
  715. --*/
  716. {
  717. SECURITY_STATUS SecurityStatus;
  718. TimeStamp TimeStamp;
  719. RPC_STATUS RpcStatus;
  720. PSecurityFunctionTable RpcSecurityInterface;
  721. unsigned Flags = SCH_CRED_USE_DEFAULT_CREDS;
  722. RpcStatus = FindSecurityPackage(
  723. AuthenticationService,
  724. AuthenticationLevel,
  725. &ProviderIndex,
  726. &PackageIndex
  727. );
  728. if ( RpcStatus != RPC_S_OK )
  729. {
  730. RpcpErrorAddRecord(EEInfoGCRuntime,
  731. RpcStatus,
  732. EEInfoDLAcquireCredentialsForClient20,
  733. AuthenticationService,
  734. AuthenticationLevel);
  735. return(RpcStatus);
  736. }
  737. RpcSecurityInterface = ProviderList[ProviderIndex].RpcSecurityInterface;
  738. if (AuthIdentity == RPC_C_NO_CREDENTIALS)
  739. {
  740. Flags = 0;
  741. AuthIdentity = 0;
  742. }
  743. //
  744. // RPC does its own name checking using msstd or fullsic names.
  745. // This requires the ability to disable schannel's name checking,
  746. // a feature available only with credentials version-4 or better.
  747. //
  748. #define MINIMUM_SCHANNEL_CRED_VERSION 4
  749. if (AuthenticationService == RPC_C_AUTHN_GSS_SCHANNEL &&
  750. AuthIdentity != NULL)
  751. {
  752. SCHANNEL_CRED * cred = (SCHANNEL_CRED *) AuthIdentity;
  753. Flags |= SCH_CRED_NO_SERVERNAME_CHECK;
  754. if (cred->dwVersion < MINIMUM_SCHANNEL_CRED_VERSION)
  755. {
  756. RpcpErrorAddRecord(EEInfoGCRuntime,
  757. ERROR_INVALID_PARAMETER,
  758. EEInfoDLAcquireCredentialsForClient30,
  759. AuthenticationService,
  760. AuthenticationLevel);
  761. return RPC_S_INVALID_AUTH_IDENTITY;
  762. }
  763. cred->dwFlags |= Flags;
  764. }
  765. SecurityStatus = (*RpcSecurityInterface->AcquireCredentialsHandle)(
  766. 0,
  767. ProviderList[ProviderIndex].SecurityPackages[PackageIndex].PackageInfo.Name,
  768. SECPKG_CRED_OUTBOUND,
  769. 0,
  770. AuthIdentity, 0, 0, &CredentialsHandle, &TimeStamp);
  771. if ( SecurityStatus != SEC_E_OK )
  772. {
  773. RpcpErrorAddRecord(EEInfoGCSecurityProvider,
  774. SecurityStatus,
  775. EEInfoDLAcquireCredentialsForClient10,
  776. AuthenticationService,
  777. AuthenticationLevel);
  778. }
  779. if (SecurityStatus != SEC_E_OK)
  780. {
  781. if ( SecurityStatus == SEC_E_INSUFFICIENT_MEMORY )
  782. {
  783. RpcStatus = RPC_S_OUT_OF_MEMORY;
  784. }
  785. else if ( SecurityStatus == SEC_E_SECPKG_NOT_FOUND )
  786. {
  787. RpcStatus = RPC_S_UNKNOWN_AUTHN_SERVICE;
  788. }
  789. else if ( SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS )
  790. {
  791. RpcStatus = ERROR_SHUTDOWN_IN_PROGRESS;
  792. }
  793. else if ( SecurityStatus == SEC_E_NO_SPM)
  794. {
  795. RpcStatus = RPC_S_SEC_PKG_ERROR;
  796. }
  797. else
  798. {
  799. VALIDATE(SecurityStatus)
  800. {
  801. SEC_E_NO_CREDENTIALS,
  802. SEC_E_UNKNOWN_CREDENTIALS,
  803. SEC_E_NO_AUTHENTICATING_AUTHORITY,
  804. SEC_E_INVALID_TOKEN
  805. }
  806. END_VALIDATE;
  807. RpcStatus = RPC_S_INVALID_AUTH_IDENTITY;
  808. }
  809. RpcpErrorAddRecord(EEInfoGCRuntime,
  810. RpcStatus,
  811. EEInfoDLAcquireCredentialsForClient30,
  812. SecurityStatus);
  813. return RpcStatus;
  814. }
  815. this->AuthenticationService = AuthenticationService;
  816. Valid = TRUE;
  817. return(RPC_S_OK);
  818. }
  819. RPC_STATUS
  820. SECURITY_CREDENTIALS::InquireDefaultPrincName(
  821. OUT SEC_CHAR __SEC_FAR **MyDefaultPrincName
  822. )
  823. {
  824. SECURITY_STATUS SecurityStatus;
  825. SecPkgCredentials_NamesA CredentialsNames;
  826. PSecurityFunctionTable RpcSecurityInterface;
  827. RPC_STATUS Status;
  828. if (DefaultPrincName == NULL)
  829. {
  830. RpcSecurityInterface = InquireProviderFunctionTable();
  831. if (RpcSecurityInterface == NULL) {
  832. return (RPC_S_OUT_OF_MEMORY);
  833. }
  834. if (RpcSecurityInterface->QueryCredentialsAttributes == NULL) {
  835. return (RPC_S_CANNOT_SUPPORT);
  836. }
  837. SecurityStatus = (*RpcSecurityInterface->QueryCredentialsAttributes)(
  838. InquireCredHandle(), SECPKG_CRED_ATTR_NAMES, &CredentialsNames);
  839. if (SecurityStatus != SEC_E_OK)
  840. {
  841. SetExtendedError(SecurityStatus);
  842. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  843. SecurityStatus,
  844. EEInfoDLInquireDefaultPrincName10,
  845. AuthenticationService);
  846. if (SecurityStatus == SEC_E_INSUFFICIENT_MEMORY)
  847. {
  848. Status = RPC_S_OUT_OF_MEMORY;
  849. }
  850. else if ( SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS )
  851. {
  852. Status = ERROR_SHUTDOWN_IN_PROGRESS;
  853. }
  854. else
  855. {
  856. Status = RPC_S_SEC_PKG_ERROR;
  857. }
  858. RpcpErrorAddRecord (EEInfoGCRuntime,
  859. Status,
  860. EEInfoDLInquireDefaultPrincName20,
  861. SecurityStatus);
  862. return Status;
  863. }
  864. if (CredentialsNames.sUserName == NULL)
  865. {
  866. return RPC_S_OUT_OF_MEMORY;
  867. }
  868. DefaultPrincName = CredentialsNames.sUserName;
  869. }
  870. *MyDefaultPrincName = DefaultPrincName;
  871. return (RPC_S_OK);
  872. }
  873. void
  874. SECURITY_CREDENTIALS::FreeCredentials (
  875. )
  876. /*++
  877. Routine Description:
  878. When we are done using the credentials, we call this routine to free
  879. them.
  880. --*/
  881. {
  882. if (Valid)
  883. {
  884. SECURITY_STATUS SecurityStatus;
  885. PSecurityFunctionTable RpcSecurityInterface
  886. = ProviderList[ProviderIndex].RpcSecurityInterface;
  887. SecurityStatus = (*RpcSecurityInterface->FreeCredentialHandle)(
  888. &CredentialsHandle);
  889. ASSERT( SecurityStatus == SEC_E_OK ||
  890. SecurityStatus == SEC_E_SECPKG_NOT_FOUND ||
  891. SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS );
  892. }
  893. }
  894. RPC_STATUS
  895. SECURITY_CONTEXT::SetMaximumLengths (
  896. )
  897. /*++
  898. Routine Description:
  899. This routine initializes the maximum header length and maximum signature
  900. length fields of this object.
  901. --*/
  902. {
  903. SECURITY_STATUS SecurityStatus;
  904. SecPkgContext_Sizes ContextSizes;
  905. RPC_STATUS Status;
  906. if (FailedContext != 0)
  907. {
  908. // We cheat if 3rd Leg Failed as we dont really have a true Context
  909. // Provider is going to really complain if we call QueryContextAttr()
  910. // .. we get around that by picking large values.
  911. // The rest of the code prevents these values to be really used
  912. // We do this because we do not want to block 3rd Leg, rather fail the
  913. // first request!
  914. MaxSignatureLength = 256;
  915. MaxHeaderLength = 256;
  916. cbBlockSize = 64;
  917. return RPC_S_OK;
  918. }
  919. ASSERT( FullyConstructed() );
  920. SecurityStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  921. &SecurityContext, SECPKG_ATTR_SIZES, &ContextSizes);
  922. if (SecurityStatus != SEC_E_OK)
  923. {
  924. #ifdef DEBUGRPC
  925. PrintToDebugger("RPC: secclnt.cxx: QueryContextAttributes returned: %lx\n",
  926. SecurityStatus);
  927. #endif
  928. Status = GetLastError();
  929. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  930. RPC_S_OUT_OF_MEMORY,
  931. EEInfoDLSetMaximumLengths10,
  932. SecurityStatus,
  933. Status,
  934. AuthenticationService,
  935. (ULONGLONG)&SecurityContext
  936. );
  937. return RPC_S_OUT_OF_MEMORY;
  938. }
  939. MaxSignatureLength = (unsigned int) ContextSizes.cbMaxSignature;
  940. MaxHeaderLength = (unsigned int) ContextSizes.cbSecurityTrailer;
  941. cbBlockSize = (unsigned int) ContextSizes.cbBlockSize;
  942. ASSERT(ContextSizes.cbBlockSize <= MAXIMUM_SECURITY_BLOCK_SIZE );
  943. return RPC_S_OK;
  944. }
  945. SECURITY_CONTEXT::SECURITY_CONTEXT (
  946. CLIENT_AUTH_INFO *myAuthInfo,
  947. unsigned myAuthContextId,
  948. BOOL fUseDatagram,
  949. RPC_STATUS __RPC_FAR * pStatus
  950. )
  951. : CLIENT_AUTH_INFO (myAuthInfo, pStatus),
  952. AuthContextId (myAuthContextId),
  953. fDatagram ((boolean) fUseDatagram),
  954. fFullyConstructed (FALSE),
  955. Legs (LegsUnknown),
  956. ContextAttributes (0)
  957. /*++
  958. Routine Description:
  959. We need to set the flag indicating that there is no security context
  960. to be deleted.
  961. --*/
  962. {
  963. ASSERT( AuthenticationLevel != 0 );
  964. DontForgetToDelete = 0;
  965. FailedContext = 0;
  966. FailedContextEEInfo = NULL;
  967. AuthzClientContext = NULL;
  968. }
  969. RPC_STATUS
  970. SECURITY_CONTEXT::CompleteSecurityToken (
  971. IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * BufferDescriptor
  972. )
  973. /*++
  974. --*/
  975. {
  976. SECURITY_STATUS SecurityStatus;
  977. RPC_STATUS Status;
  978. ASSERT( ( SecuritySupportLoaded != 0 )
  979. && ( FailedToLoad == 0 ) );
  980. SecurityStatus = (*RpcSecurityInterface->CompleteAuthToken)(
  981. &SecurityContext, BufferDescriptor);
  982. if (SecurityStatus == SEC_E_OK)
  983. {
  984. return (RPC_S_OK);
  985. }
  986. SetExtendedError(SecurityStatus);
  987. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  988. SecurityStatus,
  989. EEInfoDLCompleteSecurityToken10,
  990. AuthenticationService,
  991. AuthenticationLevel);
  992. if ( (SecurityStatus == SEC_E_NO_CREDENTIALS)
  993. || (SecurityStatus == SEC_E_LOGON_DENIED)
  994. || (SecurityStatus == SEC_E_INVALID_TOKEN)
  995. || (SecurityStatus == SEC_E_UNKNOWN_CREDENTIALS)
  996. || (SecurityStatus == SEC_E_WRONG_PRINCIPAL)
  997. || (SecurityStatus == SEC_E_TIME_SKEW))
  998. {
  999. Status = RPC_S_ACCESS_DENIED;
  1000. }
  1001. else if ( SecurityStatus == SEC_E_INSUFFICIENT_MEMORY )
  1002. {
  1003. Status = RPC_S_OUT_OF_MEMORY;
  1004. }
  1005. else if ( SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS )
  1006. {
  1007. Status = ERROR_SHUTDOWN_IN_PROGRESS;
  1008. }
  1009. else
  1010. {
  1011. #if DBG
  1012. PrintToDebugger("RPC: CompleteSecurityContext Returned %lx\n",
  1013. SecurityStatus);
  1014. #endif
  1015. Status = RPC_S_SEC_PKG_ERROR;
  1016. }
  1017. RpcpErrorAddRecord (EEInfoGCRuntime,
  1018. Status,
  1019. EEInfoDLCompleteSecurityToken20,
  1020. SecurityStatus);
  1021. return Status;
  1022. }
  1023. RPC_STATUS
  1024. SECURITY_CONTEXT::SignOrSeal (
  1025. IN unsigned long Sequence,
  1026. IN unsigned int SignNotSealFlag,
  1027. IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * BufferDescriptor
  1028. )
  1029. /*++
  1030. Routine Description:
  1031. A protocol module will use this routine to prepare a message to be
  1032. sent so that it can be verified that the message has not been tampered
  1033. with, and that it has not been exchanged out of sequence. The sender
  1034. will use this routine to prepare the message; the receiver will use
  1035. SECURITY_CONTEXT::VerifyOrUnseal to verify the message. Typically,
  1036. the security package will generate a cryptographic checksum of the
  1037. message and include sequencing information.
  1038. Arguments:
  1039. SignNotSealFlag - Supplies a flag indicating that MakeSignature should
  1040. be called rather than SealMessage.
  1041. BufferDescriptor - Supplies the message to to signed or sealed and returns
  1042. the resulting message (after being signed or sealed).
  1043. Return Value:
  1044. RPC_S_OK - This routine will always succeed.
  1045. --*/
  1046. {
  1047. SECURITY_STATUS SecurityStatus;
  1048. SEAL_MESSAGE_FN SealMessage;
  1049. {
  1050. DWORD Status = 0;
  1051. CallTestHook( TH_SECURITY_FN_SIGN, this, &Status );
  1052. if (Status)
  1053. {
  1054. return Status;
  1055. }
  1056. }
  1057. if ( SignNotSealFlag == 0 )
  1058. {
  1059. SealMessage = (SEAL_MESSAGE_FN) RpcSecurityInterface->Reserved3;
  1060. SecurityStatus = (*SealMessage)(&SecurityContext,
  1061. 0, BufferDescriptor, Sequence);
  1062. }
  1063. else
  1064. {
  1065. SecurityStatus = (*RpcSecurityInterface->MakeSignature)(
  1066. &SecurityContext, 0, BufferDescriptor, Sequence);
  1067. }
  1068. #if DBG
  1069. if ( (SecurityStatus != SEC_E_OK)
  1070. &&(SecurityStatus != SEC_E_CONTEXT_EXPIRED)
  1071. &&(SecurityStatus != SEC_E_QOP_NOT_SUPPORTED) )
  1072. {
  1073. PrintToDebugger("Sign/Seal Returned [%lx]\n", SecurityStatus);
  1074. }
  1075. #endif
  1076. if ( SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS )
  1077. {
  1078. SecurityStatus = ERROR_SHUTDOWN_IN_PROGRESS;
  1079. }
  1080. if (SecurityStatus != SEC_E_OK)
  1081. {
  1082. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1083. SecurityStatus,
  1084. EEInfoDLSignOrSeal10,
  1085. AuthenticationService,
  1086. AuthenticationLevel);
  1087. }
  1088. return(SecurityStatus);
  1089. }
  1090. RPC_STATUS
  1091. SECURITY_CONTEXT::VerifyOrUnseal (
  1092. IN unsigned long Sequence,
  1093. IN unsigned int VerifyNotUnsealFlag,
  1094. IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * BufferDescriptor
  1095. )
  1096. /*++
  1097. Routine Description:
  1098. This routine works with SECURITY_CONTEXT::SignOrSeal. A sender will
  1099. prepare a message using SignOrSeal, and then the receiver will use
  1100. this routine to verify that the message has not been tampered with, and
  1101. that it has not been exchanged out of sequence.
  1102. Arguments:
  1103. VerifyNotUnsealFlag - Supplies a flag indicating that VerifySignature
  1104. should be called rather than UnsealMessage.
  1105. BufferDescriptor - Supplies the message to be verified or unsealed.
  1106. Return Value:
  1107. RPC_S_OK - The message has not been tampered with, and it is from the
  1108. expected client.
  1109. RPC_S_ACCESS_DENIED - A security violation occured.
  1110. --*/
  1111. {
  1112. SECURITY_STATUS SecurityStatus;
  1113. unsigned long QualityOfProtection;
  1114. UNSEAL_MESSAGE_FN UnsealMessage;
  1115. {
  1116. DWORD Status = 0;
  1117. CallTestHook( TH_SECURITY_FN_VERIFY, this, &Status );
  1118. if (Status)
  1119. {
  1120. return Status;
  1121. }
  1122. }
  1123. //
  1124. // If the context had failed previously..
  1125. // Just go ahead and return an error..
  1126. // This is only for connetion-oriented RPC.
  1127. //
  1128. if (FailedContext != 0 || !FullyConstructed() )
  1129. {
  1130. RpcpSetEEInfo(FailedContextEEInfo);
  1131. FailedContextEEInfo = NULL;
  1132. SetLastError(FailedContext);
  1133. if ((FailedContext == ERROR_PASSWORD_MUST_CHANGE)
  1134. || (FailedContext == ERROR_PASSWORD_EXPIRED)
  1135. || (FailedContext == ERROR_ACCOUNT_DISABLED)
  1136. || (FailedContext == ERROR_INVALID_LOGON_HOURS))
  1137. {
  1138. return FailedContext;
  1139. }
  1140. RpcpErrorAddRecord (EEInfoGCRuntime,
  1141. RPC_S_ACCESS_DENIED,
  1142. EEInfoDLVerifyOrUnseal20,
  1143. FailedContext);
  1144. return (RPC_S_ACCESS_DENIED);
  1145. }
  1146. if ( VerifyNotUnsealFlag == 0 )
  1147. {
  1148. UnsealMessage = (UNSEAL_MESSAGE_FN) RpcSecurityInterface->Reserved4;
  1149. SecurityStatus = (*UnsealMessage)(
  1150. &SecurityContext, BufferDescriptor, Sequence,
  1151. &QualityOfProtection);
  1152. }
  1153. else
  1154. {
  1155. SecurityStatus = (*RpcSecurityInterface->VerifySignature)(
  1156. &SecurityContext, BufferDescriptor, Sequence,
  1157. &QualityOfProtection);
  1158. }
  1159. if ( SecurityStatus != SEC_E_OK )
  1160. {
  1161. #if DBG
  1162. if ((SecurityStatus != SEC_E_MESSAGE_ALTERED)
  1163. &&(SecurityStatus != SEC_E_OUT_OF_SEQUENCE)
  1164. &&(SecurityStatus != SEC_E_SECPKG_NOT_FOUND)) // on system shutdown, if the security
  1165. { // package is already uninitialized, we may get this error
  1166. PrintToDebugger("Verify/UnSeal Returned Unexp. Code [%lx]\n",
  1167. SecurityStatus);
  1168. }
  1169. #endif
  1170. SetExtendedError(SecurityStatus);
  1171. if ( SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS )
  1172. {
  1173. SecurityStatus = ERROR_SHUTDOWN_IN_PROGRESS;
  1174. }
  1175. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1176. RPC_S_ACCESS_DENIED,
  1177. EEInfoDLVerifyOrUnseal10,
  1178. SecurityStatus,
  1179. AuthenticationService,
  1180. AuthenticationLevel);
  1181. ASSERT( (SecurityStatus == SEC_E_MESSAGE_ALTERED) ||
  1182. (SecurityStatus == SEC_E_OUT_OF_SEQUENCE) ||
  1183. (SecurityStatus == SEC_E_SECPKG_NOT_FOUND) );
  1184. SetLastError(RPC_S_ACCESS_DENIED);
  1185. return(RPC_S_ACCESS_DENIED);
  1186. }
  1187. return(RPC_S_OK);
  1188. }
  1189. RPC_STATUS
  1190. SECURITY_CONTEXT::InitializeFirstTime (
  1191. IN SECURITY_CREDENTIALS * Credentials,
  1192. IN RPC_CHAR * ServerPrincipalName,
  1193. IN unsigned long AuthenticationLevel,
  1194. IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * BufferDescriptor,
  1195. IN OUT unsigned char *NewAuthType
  1196. )
  1197. /*++
  1198. Routine Description:
  1199. Arguments:
  1200. Return Value:
  1201. RPC_S_OK - Send the token to the server; everything worked fine so
  1202. far.
  1203. RPC_P_CONTINUE_NEEDED - Indicates that that everything is ok, but that
  1204. we need to call into the security package again when we have
  1205. received a token back from the server.
  1206. RPC_P_COMPLETE_NEEDED - Indicates that everyting is ok, but that we
  1207. need to call CompleteAuthToken before sending the message.
  1208. RPC_P_COMPLETE_AND_CONTINUE - Needs both a complete and a continue.
  1209. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to perform the
  1210. operation.
  1211. RPC_S_ACCESS_DENIED - Access is denied.
  1212. --*/
  1213. {
  1214. SECURITY_STATUS SecurityStatus;
  1215. TimeStamp TimeStamp;
  1216. unsigned long ContextRequirements;
  1217. RPC_STATUS Status;
  1218. RPC_STATUS Status2;
  1219. unsigned char RetrievedAuthType;
  1220. BOOL fDone;
  1221. ASSERT( ( SecuritySupportLoaded != 0 )
  1222. && ( FailedToLoad == 0 ) );
  1223. RpcSecurityInterface = Credentials->InquireProviderFunctionTable();
  1224. switch ( AuthenticationLevel )
  1225. {
  1226. case RPC_C_AUTHN_LEVEL_CONNECT :
  1227. ContextRequirements = 0;
  1228. break;
  1229. case RPC_C_AUTHN_LEVEL_PKT :
  1230. ContextRequirements = ISC_REQ_REPLAY_DETECT;
  1231. break;
  1232. case RPC_C_AUTHN_LEVEL_PKT_INTEGRITY :
  1233. ContextRequirements = ISC_REQ_REPLAY_DETECT
  1234. | ISC_REQ_SEQUENCE_DETECT
  1235. | ISC_REQ_INTEGRITY;
  1236. break;
  1237. case RPC_C_AUTHN_LEVEL_PKT_PRIVACY :
  1238. ContextRequirements = ISC_REQ_REPLAY_DETECT
  1239. | ISC_REQ_SEQUENCE_DETECT
  1240. | ISC_REQ_CONFIDENTIALITY
  1241. | ISC_REQ_INTEGRITY;
  1242. break;
  1243. default :
  1244. ASSERT( ( AuthenticationLevel == RPC_C_AUTHN_LEVEL_CONNECT )
  1245. || ( AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT )
  1246. || ( AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY )
  1247. || ( AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY ) );
  1248. return RPC_S_INTERNAL_ERROR;
  1249. }
  1250. if (fDatagram)
  1251. {
  1252. ContextRequirements |= ISC_REQ_DATAGRAM;
  1253. }
  1254. else
  1255. {
  1256. ContextRequirements |= ISC_REQ_CONNECTION;
  1257. }
  1258. switch(ImpersonationType)
  1259. {
  1260. case RPC_C_IMP_LEVEL_IDENTIFY:
  1261. ContextRequirements |= ISC_REQ_IDENTIFY;
  1262. break;
  1263. case RPC_C_IMP_LEVEL_IMPERSONATE:
  1264. break;
  1265. case RPC_C_IMP_LEVEL_DELEGATE:
  1266. ContextRequirements |= ISC_REQ_DELEGATE;
  1267. break;
  1268. default:
  1269. ASSERT( ImpersonationType == RPC_C_IMP_LEVEL_ANONYMOUS
  1270. || ImpersonationType == RPC_C_IMP_LEVEL_IDENTIFY
  1271. || ImpersonationType == RPC_C_IMP_LEVEL_IMPERSONATE
  1272. || ImpersonationType == RPC_C_IMP_LEVEL_DELEGATE );
  1273. ContextRequirements |= ISC_REQ_IDENTIFY;
  1274. break;
  1275. }
  1276. if (Capabilities == RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH)
  1277. {
  1278. ContextRequirements |= ISC_REQ_MUTUAL_AUTH;
  1279. }
  1280. if (Credentials->AuthenticationService == RPC_C_AUTHN_GSS_SCHANNEL)
  1281. {
  1282. #if MANUAL_CERT_CHECK
  1283. ContextRequirements |= ISC_REQ_MANUAL_CRED_VALIDATION;
  1284. #endif
  1285. }
  1286. else
  1287. {
  1288. ContextRequirements |= ISC_REQ_USE_DCE_STYLE;
  1289. }
  1290. SecurityStatus = (*RpcSecurityInterface->InitializeSecurityContext)(
  1291. Credentials->InquireCredHandle(),
  1292. 0,
  1293. (SEC_TCHAR __SEC_FAR *) ServerPrincipalName,
  1294. ContextRequirements,
  1295. 0,
  1296. 0,
  1297. (fDatagram ? BufferDescriptor : 0),
  1298. 0,
  1299. &SecurityContext,
  1300. (fDatagram ? 0 : BufferDescriptor),
  1301. &ContextAttributes,
  1302. &TimeStamp
  1303. );
  1304. if ( ( SecurityStatus != SEC_E_OK )
  1305. && ( SecurityStatus != SEC_I_CONTINUE_NEEDED )
  1306. && ( SecurityStatus != SEC_I_COMPLETE_NEEDED )
  1307. && ( SecurityStatus != SEC_I_COMPLETE_AND_CONTINUE ) )
  1308. {
  1309. SetExtendedError(SecurityStatus);
  1310. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1311. SecurityStatus,
  1312. EEInfoDLInitializeFirstTime10,
  1313. AuthenticationService,
  1314. AuthenticationLevel,
  1315. ServerPrincipalName,
  1316. ContextRequirements);
  1317. if ((SecurityStatus == SEC_E_NO_CREDENTIALS)
  1318. || (SecurityStatus == SEC_E_LOGON_DENIED)
  1319. || (SecurityStatus == SEC_E_INVALID_TOKEN)
  1320. || (SecurityStatus == SEC_E_UNKNOWN_CREDENTIALS)
  1321. || (SecurityStatus == SEC_E_NO_KERB_KEY)
  1322. || (SecurityStatus == SEC_E_TIME_SKEW) )
  1323. {
  1324. Status = RPC_S_ACCESS_DENIED;
  1325. }
  1326. else if ( SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS )
  1327. {
  1328. Status = ERROR_SHUTDOWN_IN_PROGRESS;
  1329. }
  1330. else if (SecurityStatus == SEC_E_SECPKG_NOT_FOUND)
  1331. {
  1332. Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  1333. }
  1334. else if ( SecurityStatus == SEC_E_INSUFFICIENT_MEMORY )
  1335. {
  1336. Status = RPC_S_OUT_OF_MEMORY;
  1337. }
  1338. else
  1339. {
  1340. #if DBG
  1341. PrintToDebugger("RPC: InitializeFirstTime Returned %lx\n", SecurityStatus);
  1342. #endif
  1343. //
  1344. // Originally the default for all providers was SEC_PKG_ERROR. This seems less
  1345. // helpful than ACCESS_DENIED, but we can't change it for NTLM and Kerberos because
  1346. // it might break old app code.
  1347. //
  1348. // SCHANNEL is new, so we can return ACCESS_DENIED.
  1349. //
  1350. if (AuthenticationService == RPC_C_AUTHN_GSS_SCHANNEL)
  1351. {
  1352. Status = RPC_S_ACCESS_DENIED;
  1353. }
  1354. else
  1355. {
  1356. Status = RPC_S_SEC_PKG_ERROR;
  1357. }
  1358. }
  1359. RpcpErrorAddRecord (EEInfoGCRuntime,
  1360. Status,
  1361. EEInfoDLInitializeFirstTime20,
  1362. SecurityStatus);
  1363. return Status;
  1364. }
  1365. RetrievedAuthType = 0;
  1366. DontForgetToDelete = 1;
  1367. if (NewAuthType)
  1368. {
  1369. ASSERT(*NewAuthType == this->AuthenticationService);
  1370. if (*NewAuthType == RPC_C_AUTHN_GSS_NEGOTIATE)
  1371. {
  1372. SecPkgContext_NegotiationInfo NegoInfo;
  1373. SECURITY_STATUS Status;
  1374. Status = (*RpcSecurityInterface->QueryContextAttributes)(
  1375. &SecurityContext,
  1376. SECPKG_ATTR_NEGOTIATION_INFO,
  1377. &NegoInfo);
  1378. if (Status == SEC_E_OK)
  1379. {
  1380. if (NegoInfo.NegotiationState == SECPKG_NEGOTIATION_COMPLETE)
  1381. {
  1382. RetrievedAuthType = (unsigned char) NegoInfo.PackageInfo->wRPCID;
  1383. }
  1384. (*RpcSecurityInterface->FreeContextBuffer)(NegoInfo.PackageInfo);
  1385. }
  1386. else
  1387. {
  1388. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1389. RPC_S_OUT_OF_MEMORY,
  1390. EEInfoDLInitializeFirstTime30,
  1391. Status,
  1392. (ULONG)AuthenticationService,
  1393. AuthenticationLevel,
  1394. (ULONG)ContextRequirements);
  1395. return RPC_S_OUT_OF_MEMORY;
  1396. }
  1397. }
  1398. }
  1399. Flags = ContextRequirements;
  1400. fDone = TRUE;
  1401. if ( SecurityStatus == SEC_I_CONTINUE_NEEDED )
  1402. {
  1403. if (!fDatagram)
  1404. {
  1405. fDone = FALSE;
  1406. }
  1407. Status = RPC_P_CONTINUE_NEEDED;
  1408. }
  1409. else if ( SecurityStatus == SEC_I_COMPLETE_NEEDED )
  1410. {
  1411. // Can't set the maximum lengths on a partly completed connection.
  1412. Status = RPC_P_COMPLETE_NEEDED;
  1413. }
  1414. else if ( SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE )
  1415. {
  1416. if (!fDatagram)
  1417. {
  1418. fDone = FALSE;
  1419. }
  1420. Status = RPC_P_COMPLETE_AND_CONTINUE;
  1421. }
  1422. else
  1423. {
  1424. Status = RPC_S_OK;
  1425. }
  1426. if (fDone)
  1427. {
  1428. fFullyConstructed = TRUE;
  1429. Status2 = SetMaximumLengths();
  1430. if (Status2 != RPC_S_OK)
  1431. {
  1432. return Status2;
  1433. }
  1434. }
  1435. if (RetrievedAuthType)
  1436. *NewAuthType = RetrievedAuthType;
  1437. return(Status);
  1438. }
  1439. RPC_STATUS
  1440. SECURITY_CONTEXT::InitializeThirdLeg (
  1441. IN SECURITY_CREDENTIALS * Credentials,
  1442. IN unsigned long DataRepresentation,
  1443. IN SECURITY_BUFFER_DESCRIPTOR PAPI * InputBufferDescriptor,
  1444. IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * OutputBufferDescriptor
  1445. )
  1446. /*++
  1447. Routine Description:
  1448. Arguments:
  1449. Return Value:
  1450. RPC_S_OK - Send the token to the server; everything worked fine so
  1451. far.
  1452. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to perform the
  1453. operation.
  1454. RPC_S_ACCESS_DENIED - Access is denied.
  1455. --*/
  1456. {
  1457. SECURITY_STATUS SecurityStatus;
  1458. TimeStamp TimeStamp;
  1459. RPC_STATUS Status;
  1460. ASSERT( (SecuritySupportLoaded != 0)
  1461. && (FailedToLoad == 0) );
  1462. SecurityStatus = (*RpcSecurityInterface->InitializeSecurityContext)(
  1463. Credentials->InquireCredHandle(),
  1464. &SecurityContext,
  1465. 0,
  1466. Flags,
  1467. 0,
  1468. DataRepresentation,
  1469. InputBufferDescriptor,
  1470. 0,
  1471. &SecurityContext,
  1472. OutputBufferDescriptor,
  1473. &ContextAttributes,
  1474. &TimeStamp
  1475. );
  1476. if ( ( SecurityStatus != SEC_E_OK )
  1477. && ( SecurityStatus != SEC_I_CONTINUE_NEEDED )
  1478. && ( SecurityStatus != SEC_I_COMPLETE_NEEDED )
  1479. && ( SecurityStatus != SEC_I_COMPLETE_AND_CONTINUE ) )
  1480. {
  1481. SetExtendedError(SecurityStatus);
  1482. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1483. SecurityStatus,
  1484. EEInfoDLInitializeThirdLeg10,
  1485. AuthenticationService,
  1486. AuthenticationLevel,
  1487. ContextAttributes);
  1488. if ( (SecurityStatus == SEC_E_NO_CREDENTIALS)
  1489. || (SecurityStatus == SEC_E_LOGON_DENIED)
  1490. || (SecurityStatus == SEC_E_INVALID_TOKEN)
  1491. || (SecurityStatus == SEC_E_UNKNOWN_CREDENTIALS)
  1492. || (SecurityStatus == SEC_E_NO_KERB_KEY)
  1493. || (SecurityStatus == SEC_E_TIME_SKEW) )
  1494. {
  1495. Status = RPC_S_ACCESS_DENIED;
  1496. }
  1497. else if ( SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS )
  1498. {
  1499. Status = ERROR_SHUTDOWN_IN_PROGRESS;
  1500. }
  1501. else if (SecurityStatus == SEC_E_SECPKG_NOT_FOUND)
  1502. {
  1503. Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  1504. }
  1505. else if ( SecurityStatus == SEC_E_INSUFFICIENT_MEMORY )
  1506. {
  1507. Status = RPC_S_OUT_OF_MEMORY;
  1508. }
  1509. else
  1510. {
  1511. #if DBG
  1512. PrintToDebugger("RPC: InitializeThirdLeg Returned %lx\n",
  1513. SecurityStatus );
  1514. #endif
  1515. //
  1516. // Originally the default for all connection-oriented providers
  1517. // was SEC_PKG_ERROR. This seems less helpful than ACESS_DENIED,
  1518. // but we can't change it for NTLM and Kerberos because it might
  1519. // break old app code. SCHANNEL is new, so we can return ACCESS_DENIED.
  1520. //
  1521. // Datagram returns the bare error code.
  1522. //
  1523. if (AuthenticationService == RPC_C_AUTHN_GSS_SCHANNEL)
  1524. {
  1525. Status = RPC_S_ACCESS_DENIED;
  1526. }
  1527. else if (fDatagram)
  1528. {
  1529. // leave the error code alone
  1530. }
  1531. else
  1532. {
  1533. Status = RPC_S_SEC_PKG_ERROR;
  1534. }
  1535. }
  1536. RpcpErrorAddRecord (EEInfoGCRuntime,
  1537. Status,
  1538. EEInfoDLInitializeThirdLeg20,
  1539. SecurityStatus);
  1540. return Status;
  1541. }
  1542. if ( SecurityStatus == SEC_I_CONTINUE_NEEDED )
  1543. {
  1544. return(RPC_P_CONTINUE_NEEDED);
  1545. }
  1546. if ( SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE )
  1547. {
  1548. return(RPC_P_COMPLETE_AND_CONTINUE);
  1549. }
  1550. ASSERT(SecurityStatus == SEC_E_OK
  1551. || SecurityStatus == SEC_I_COMPLETE_NEEDED);
  1552. if ( (ImpersonationType == RPC_C_IMP_LEVEL_IDENTIFY) &&
  1553. (!(ContextAttributes & ISC_RET_IDENTIFY)) )
  1554. {
  1555. RpcpErrorAddRecord (EEInfoGCRuntime,
  1556. RPC_S_SEC_PKG_ERROR,
  1557. EEInfoDLInitializeThirdLeg30,
  1558. SEC_E_SECURITY_QOS_FAILED,
  1559. ImpersonationType,
  1560. ContextAttributes);
  1561. SetExtendedError(SEC_E_SECURITY_QOS_FAILED);
  1562. return (RPC_S_SEC_PKG_ERROR);
  1563. }
  1564. if ( (ImpersonationType == RPC_C_IMP_LEVEL_DELEGATE) &&
  1565. (!(ContextAttributes & ISC_RET_DELEGATE)) )
  1566. {
  1567. RpcpErrorAddRecord (EEInfoGCRuntime,
  1568. RPC_S_SEC_PKG_ERROR,
  1569. EEInfoDLInitializeThirdLeg40,
  1570. SEC_E_SECURITY_QOS_FAILED,
  1571. ImpersonationType,
  1572. ContextAttributes);
  1573. SetExtendedError(SEC_E_SECURITY_QOS_FAILED);
  1574. return (RPC_S_SEC_PKG_ERROR);
  1575. }
  1576. if ( (!(ContextAttributes & ISC_RET_MUTUAL_AUTH) )&&
  1577. (Capabilities == RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH) )
  1578. {
  1579. RpcpErrorAddRecord (EEInfoGCRuntime,
  1580. RPC_S_SEC_PKG_ERROR,
  1581. EEInfoDLInitializeThirdLeg50,
  1582. SEC_E_SECURITY_QOS_FAILED,
  1583. ImpersonationType,
  1584. ContextAttributes);
  1585. SetExtendedError(SEC_E_SECURITY_QOS_FAILED);
  1586. return (RPC_S_SEC_PKG_ERROR);
  1587. }
  1588. if ( SecurityStatus == SEC_I_COMPLETE_NEEDED )
  1589. {
  1590. fFullyConstructed = TRUE;
  1591. Status = SetMaximumLengths();
  1592. if (Status != RPC_S_OK)
  1593. return Status;
  1594. return(RPC_P_COMPLETE_NEEDED);
  1595. }
  1596. fFullyConstructed = TRUE;
  1597. Status = SetMaximumLengths();
  1598. if (Status != RPC_S_OK)
  1599. return Status;
  1600. if (AuthenticationService == RPC_C_AUTHN_GSS_SCHANNEL)
  1601. {
  1602. return VerifyCertificate();
  1603. }
  1604. return(RPC_S_OK);
  1605. }
  1606. RPC_STATUS
  1607. SECURITY_CONTEXT::GetWireIdForSnego(
  1608. OUT unsigned char *WireId
  1609. )
  1610. {
  1611. SecPkgContext_NegotiationInfo NegoInfo;
  1612. SECURITY_STATUS SecStatus;
  1613. RPC_STATUS RpcStatus = RPC_S_OK;
  1614. if (AuthenticationService != RPC_C_AUTHN_GSS_NEGOTIATE)
  1615. return RPC_S_INVALID_BINDING;
  1616. ASSERT(RpcSecurityInterface != NULL);
  1617. SecStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  1618. &SecurityContext,
  1619. SECPKG_ATTR_NEGOTIATION_INFO,
  1620. &NegoInfo);
  1621. if (SecStatus == SEC_E_OK)
  1622. {
  1623. if (NegoInfo.NegotiationState == SECPKG_NEGOTIATION_COMPLETE)
  1624. {
  1625. *WireId = (unsigned char) NegoInfo.PackageInfo->wRPCID;
  1626. }
  1627. else
  1628. RpcStatus = RPC_S_SEC_PKG_ERROR;
  1629. (*RpcSecurityInterface->FreeContextBuffer)(NegoInfo.PackageInfo);
  1630. }
  1631. else
  1632. {
  1633. SetExtendedError(SecStatus);
  1634. RpcStatus = RPC_S_OUT_OF_MEMORY;
  1635. }
  1636. return RpcStatus;
  1637. }
  1638. RPC_STATUS
  1639. SECURITY_CONTEXT::AcceptFirstTime (
  1640. IN SECURITY_CREDENTIALS * NewCredentials,
  1641. IN SECURITY_BUFFER_DESCRIPTOR PAPI * InputBufferDescriptor,
  1642. IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * OutputBufferDescriptor,
  1643. IN unsigned long AuthenticationLevel,
  1644. IN unsigned long DataRepresentation,
  1645. IN unsigned long NewContextNeededFlag
  1646. )
  1647. /*++
  1648. Routine Description:
  1649. Arguments:
  1650. Return Value:
  1651. RPC_S_OK - Everything worked just fine.
  1652. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the
  1653. operation.
  1654. RPC_P_CONTINUE_NEEDED - Indicates that everything is ok, but that we
  1655. need to send the output token back to the client, and then wait
  1656. for a token back from the client.
  1657. RPC_P_COMPLETE_NEEDED - Indicates that everyting is ok, but that we
  1658. need to call CompleteAuthToken before sending the message.
  1659. RPC_P_COMPLETE_AND_CONTINUE - Needs both a complete and a continue.
  1660. RPC_S_ACCESS_DENIED - Access is denied.
  1661. --*/
  1662. {
  1663. SECURITY_STATUS SecurityStatus;
  1664. TimeStamp TimeStamp;
  1665. unsigned long ContextRequirements;
  1666. RPC_STATUS RpcStatus;
  1667. DWORD Status = 0;
  1668. ASSERT( (SecuritySupportLoaded != 0)
  1669. && (FailedToLoad == 0) );
  1670. if (Credentials)
  1671. {
  1672. Credentials->DereferenceCredentials();
  1673. }
  1674. Credentials = NewCredentials;
  1675. Credentials->ReferenceCredentials();
  1676. RpcSecurityInterface = Credentials->InquireProviderFunctionTable();
  1677. if (NewContextNeededFlag == 1)
  1678. {
  1679. DeleteSecurityContext();
  1680. }
  1681. switch ( AuthenticationLevel )
  1682. {
  1683. case RPC_C_AUTHN_LEVEL_CONNECT :
  1684. ContextRequirements = ASC_REQ_MUTUAL_AUTH;
  1685. break;
  1686. case RPC_C_AUTHN_LEVEL_PKT :
  1687. ContextRequirements = ASC_REQ_MUTUAL_AUTH
  1688. | ASC_REQ_REPLAY_DETECT;
  1689. break;
  1690. case RPC_C_AUTHN_LEVEL_PKT_INTEGRITY :
  1691. ContextRequirements = ASC_REQ_MUTUAL_AUTH
  1692. | ASC_REQ_REPLAY_DETECT | ASC_REQ_SEQUENCE_DETECT;
  1693. break;
  1694. case RPC_C_AUTHN_LEVEL_PKT_PRIVACY :
  1695. ContextRequirements = ASC_REQ_MUTUAL_AUTH
  1696. | ASC_REQ_REPLAY_DETECT | ASC_REQ_SEQUENCE_DETECT
  1697. | ASC_REQ_CONFIDENTIALITY;
  1698. break;
  1699. default :
  1700. ASSERT(AuthenticationLevel == RPC_C_AUTHN_LEVEL_CONNECT ||
  1701. AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT ||
  1702. AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY ||
  1703. AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY );
  1704. return RPC_S_INTERNAL_ERROR;
  1705. }
  1706. if (fDatagram)
  1707. {
  1708. ContextRequirements |= ASC_REQ_DATAGRAM;
  1709. }
  1710. else
  1711. {
  1712. ContextRequirements |= ASC_REQ_CONNECTION;
  1713. }
  1714. if (Credentials->AuthenticationService == RPC_C_AUTHN_WINNT ||
  1715. Credentials->AuthenticationService == RPC_C_AUTHN_DCE_PRIVATE ||
  1716. Credentials->AuthenticationService == RPC_C_AUTHN_GSS_KERBEROS ||
  1717. Credentials->AuthenticationService == RPC_C_AUTHN_GSS_NEGOTIATE)
  1718. {
  1719. ContextRequirements |= ASC_REQ_USE_DCE_STYLE | ASC_REQ_DELEGATE;
  1720. }
  1721. if (AuthenticationService == RPC_C_AUTHN_WINNT
  1722. || AuthenticationService == RPC_C_AUTHN_GSS_NEGOTIATE)
  1723. {
  1724. ContextRequirements |= ASC_REQ_ALLOW_NON_USER_LOGONS;
  1725. }
  1726. CallTestHook( TH_SECURITY_FN_ACCEPT1, this, &Status );
  1727. if (Status)
  1728. {
  1729. SetExtendedError(Status);
  1730. return Status;
  1731. }
  1732. SecurityStatus = (*RpcSecurityInterface->AcceptSecurityContext)(
  1733. Credentials->InquireCredHandle(), 0, InputBufferDescriptor,
  1734. ContextRequirements, DataRepresentation, &SecurityContext,
  1735. OutputBufferDescriptor, &ContextAttributes, &TimeStamp);
  1736. if ( ( SecurityStatus != SEC_E_OK )
  1737. && ( SecurityStatus != SEC_I_CONTINUE_NEEDED )
  1738. && ( SecurityStatus != SEC_I_COMPLETE_NEEDED )
  1739. && ( SecurityStatus != SEC_I_COMPLETE_AND_CONTINUE ) )
  1740. {
  1741. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1742. SecurityStatus,
  1743. EEInfoDLAcceptFirstTime10,
  1744. AuthenticationService,
  1745. AuthenticationLevel,
  1746. ContextRequirements);
  1747. SetExtendedError(SecurityStatus);
  1748. if ( (SecurityStatus == SEC_E_NO_CREDENTIALS)
  1749. || (SecurityStatus == SEC_E_LOGON_DENIED)
  1750. || (SecurityStatus == SEC_E_INVALID_TOKEN)
  1751. || (SecurityStatus == SEC_E_NO_AUTHENTICATING_AUTHORITY)
  1752. || (SecurityStatus == SEC_E_UNKNOWN_CREDENTIALS)
  1753. || (SecurityStatus == SEC_E_CONTEXT_EXPIRED)
  1754. || (SecurityStatus == SEC_E_TIME_SKEW))
  1755. {
  1756. RpcStatus = RPC_S_ACCESS_DENIED;
  1757. }
  1758. else if ( SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS )
  1759. {
  1760. RpcStatus = ERROR_SHUTDOWN_IN_PROGRESS;
  1761. }
  1762. else if (SecurityStatus == SEC_E_SECPKG_NOT_FOUND)
  1763. {
  1764. RpcStatus = RPC_S_UNKNOWN_AUTHN_SERVICE;
  1765. }
  1766. else
  1767. RpcStatus = RPC_S_OUT_OF_MEMORY;
  1768. RpcpErrorAddRecord (EEInfoGCRuntime,
  1769. RpcStatus,
  1770. EEInfoDLAcceptFirstTime20,
  1771. SecurityStatus);
  1772. return RpcStatus;
  1773. }
  1774. DontForgetToDelete = 1;
  1775. Flags = ContextRequirements;
  1776. if ( SecurityStatus == SEC_I_CONTINUE_NEEDED )
  1777. {
  1778. return(RPC_P_CONTINUE_NEEDED);
  1779. }
  1780. if ( SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE )
  1781. {
  1782. return(RPC_P_COMPLETE_AND_CONTINUE);
  1783. }
  1784. ASSERT((SecurityStatus == SEC_I_COMPLETE_NEEDED)
  1785. || (SecurityStatus == SEC_E_OK));
  1786. fFullyConstructed = TRUE;
  1787. RpcStatus = SetMaximumLengths();
  1788. if (RpcStatus != RPC_S_OK)
  1789. return RpcStatus;
  1790. Credentials->DereferenceCredentials();
  1791. Credentials = 0;
  1792. if ( SecurityStatus == SEC_I_COMPLETE_NEEDED )
  1793. return(RPC_P_COMPLETE_NEEDED);
  1794. else
  1795. return(RPC_S_OK);
  1796. }
  1797. RPC_STATUS
  1798. SECURITY_CONTEXT::AcceptThirdLeg (
  1799. IN unsigned long DataRepresentation,
  1800. IN SECURITY_BUFFER_DESCRIPTOR PAPI * BufferDescriptor,
  1801. OUT SECURITY_BUFFER_DESCRIPTOR PAPI * OutBufferDescriptor
  1802. )
  1803. /*++
  1804. Routine Description:
  1805. Arguments:
  1806. Return Value:
  1807. RPC_S_OK - Everything worked just fine.
  1808. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the
  1809. operation.
  1810. RPC_S_ACCESS_DENIED - Access is denied.
  1811. RPC_P_COMPLETE_NEEDED - Indicates that everyting is ok, but that we
  1812. need to call CompleteAuthToken before sending the message.
  1813. --*/
  1814. {
  1815. SECURITY_STATUS SecurityStatus;
  1816. TimeStamp TimeStamp;
  1817. RPC_STATUS RpcStatus;
  1818. ASSERT( (SecuritySupportLoaded != 0)
  1819. && (FailedToLoad == 0) );
  1820. SetLastError(0);
  1821. {
  1822. DWORD Status = 0;
  1823. CallTestHook( TH_SECURITY_FN_ACCEPT3, this, &Status );
  1824. if (Status)
  1825. {
  1826. FailedContext = Status;
  1827. SetExtendedError(Status);
  1828. return Status;
  1829. }
  1830. }
  1831. SecurityStatus = (*RpcSecurityInterface->AcceptSecurityContext)(
  1832. Credentials->InquireCredHandle(),
  1833. &SecurityContext,
  1834. BufferDescriptor,
  1835. Flags,
  1836. DataRepresentation,
  1837. &SecurityContext,
  1838. OutBufferDescriptor,
  1839. &ContextAttributes,
  1840. &TimeStamp
  1841. );
  1842. //
  1843. // If 3rd Leg Failed Bit is set, map all errors other than out of memory
  1844. // to SUCCESS
  1845. //
  1846. if (
  1847. (
  1848. ( SecurityStatus != SEC_E_OK )
  1849. && ( SecurityStatus != SEC_I_COMPLETE_NEEDED)
  1850. && ( SecurityStatus != SEC_I_CONTINUE_NEEDED)
  1851. && ( SecurityStatus != SEC_I_COMPLETE_AND_CONTINUE)
  1852. && ( SecurityStatus != SEC_E_INSUFFICIENT_MEMORY )
  1853. && ( ContextAttributes & ASC_RET_THIRD_LEG_FAILED )
  1854. )
  1855. ||
  1856. (
  1857. ( SecurityStatus == SEC_E_LOGON_DENIED )
  1858. || ( SecurityStatus == SEC_E_NO_CREDENTIALS )
  1859. || ( SecurityStatus == SEC_E_INVALID_TOKEN )
  1860. || ( SecurityStatus == SEC_E_UNKNOWN_CREDENTIALS )
  1861. || ( SecurityStatus == SEC_E_NO_AUTHENTICATING_AUTHORITY )
  1862. || ( SecurityStatus == SEC_E_TIME_SKEW )
  1863. )
  1864. )
  1865. {
  1866. FailedContext = GetLastError();
  1867. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1868. SecurityStatus,
  1869. EEInfoDLAcceptThirdLeg10,
  1870. AuthenticationService,
  1871. AuthenticationLevel,
  1872. FailedContext);
  1873. if (!fDatagram)
  1874. {
  1875. SecurityStatus = SEC_E_OK;
  1876. }
  1877. SetExtendedError(SecurityStatus);
  1878. if ( (FailedContext != ERROR_PASSWORD_MUST_CHANGE)
  1879. && (FailedContext != ERROR_PASSWORD_EXPIRED)
  1880. && (FailedContext != ERROR_ACCOUNT_DISABLED)
  1881. && (FailedContext != ERROR_INVALID_LOGON_HOURS) )
  1882. {
  1883. FailedContext = RPC_S_ACCESS_DENIED;
  1884. RpcpErrorAddRecord (EEInfoGCRuntime,
  1885. FailedContext,
  1886. EEInfoDLAcceptThirdLeg30);
  1887. }
  1888. ASSERT(FailedContextEEInfo == NULL);
  1889. FailedContextEEInfo = RpcpGetEEInfo();
  1890. RpcpClearEEInfo();
  1891. }
  1892. if ( ( SecurityStatus != SEC_E_OK )
  1893. && ( SecurityStatus != SEC_I_COMPLETE_NEEDED )
  1894. && ( SecurityStatus != SEC_I_CONTINUE_NEEDED )
  1895. && ( SecurityStatus != SEC_I_COMPLETE_AND_CONTINUE ) )
  1896. {
  1897. SetExtendedError(SecurityStatus);
  1898. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1899. SecurityStatus,
  1900. EEInfoDLAcceptThirdLeg20,
  1901. AuthenticationService,
  1902. AuthenticationLevel);
  1903. DontForgetToDelete = 0;
  1904. if ( SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS )
  1905. {
  1906. RpcStatus = ERROR_SHUTDOWN_IN_PROGRESS;
  1907. }
  1908. else if ( (SecurityStatus == SEC_E_SECPKG_NOT_FOUND)
  1909. || (SecurityStatus == SEC_E_NO_CREDENTIALS)
  1910. || (SecurityStatus == SEC_E_LOGON_DENIED)
  1911. || (SecurityStatus == SEC_E_INVALID_TOKEN)
  1912. || (SecurityStatus == SEC_E_UNKNOWN_CREDENTIALS)
  1913. || (SecurityStatus == SEC_E_NO_AUTHENTICATING_AUTHORITY)
  1914. || (SecurityStatus == SEC_E_CONTEXT_EXPIRED)
  1915. || (SecurityStatus == SEC_E_TIME_SKEW))
  1916. {
  1917. RpcStatus = RPC_S_ACCESS_DENIED;
  1918. }
  1919. else
  1920. {
  1921. ASSERT( SecurityStatus == SEC_E_INSUFFICIENT_MEMORY );
  1922. RpcStatus = RPC_S_OUT_OF_MEMORY;
  1923. }
  1924. RpcpErrorAddRecord (EEInfoGCRuntime,
  1925. RpcStatus,
  1926. EEInfoDLAcceptThirdLeg40,
  1927. SecurityStatus);
  1928. return RpcStatus;
  1929. }
  1930. if ( SecurityStatus == SEC_I_CONTINUE_NEEDED )
  1931. {
  1932. return(RPC_P_CONTINUE_NEEDED);
  1933. }
  1934. if ( SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE )
  1935. {
  1936. return(RPC_P_COMPLETE_AND_CONTINUE);
  1937. }
  1938. ASSERT ( (SecurityStatus == SEC_I_COMPLETE_NEEDED)
  1939. || (SecurityStatus == SEC_E_OK));
  1940. fFullyConstructed = TRUE;
  1941. RpcStatus = SetMaximumLengths();
  1942. if (RpcStatus)
  1943. {
  1944. FailedContext = RpcStatus;
  1945. ASSERT(FailedContextEEInfo == NULL);
  1946. FailedContextEEInfo = RpcpGetEEInfo();
  1947. RpcpClearEEInfo();
  1948. //
  1949. // We don't want to block third leg - mimic success
  1950. // Failed context has already been set
  1951. //
  1952. MaxSignatureLength = 256;
  1953. MaxHeaderLength = 256;
  1954. cbBlockSize = 64;
  1955. }
  1956. if (SecurityStatus == SEC_I_COMPLETE_NEEDED)
  1957. return(RPC_P_COMPLETE_NEEDED);
  1958. else
  1959. return RPC_S_OK;
  1960. }
  1961. unsigned long
  1962. SECURITY_CONTEXT::InquireAuthorizationService (
  1963. )
  1964. /*++
  1965. Return Value:
  1966. The authorization service for this security context will be returned.
  1967. --*/
  1968. {
  1969. SecPkgContext_DceInfo DceInfo;
  1970. SECURITY_STATUS SecurityStatus;
  1971. SecurityStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  1972. &SecurityContext, SECPKG_ATTR_DCE_INFO, &DceInfo);
  1973. ASSERT( SecurityStatus == SEC_E_OK );
  1974. return(DceInfo.AuthzSvc);
  1975. }
  1976. RPC_AUTHZ_HANDLE
  1977. SECURITY_CONTEXT::InquirePrivileges (
  1978. )
  1979. /*++
  1980. Return Value:
  1981. The privileges of the client at the other end of this security context
  1982. will be returned.
  1983. --*/
  1984. {
  1985. SecPkgContext_DceInfo DceInfo;
  1986. SECURITY_STATUS SecurityStatus;
  1987. SecurityStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  1988. &SecurityContext, SECPKG_ATTR_DCE_INFO, &DceInfo);
  1989. ASSERT( SecurityStatus == SEC_E_OK );
  1990. return(DceInfo.pPac);
  1991. }
  1992. DWORD
  1993. SECURITY_CONTEXT::GetDceInfo (
  1994. RPC_AUTHZ_HANDLE __RPC_FAR * PacHandle,
  1995. unsigned long __RPC_FAR * AuthzSvc
  1996. )
  1997. /*++
  1998. Return Value:
  1999. The privileges of the client at the other end of this security context
  2000. will be returned.
  2001. --*/
  2002. {
  2003. SecPkgContext_DceInfo DceInfo;
  2004. SECURITY_STATUS SecurityStatus;
  2005. *PacHandle = 0;
  2006. *AuthzSvc = 0;
  2007. SecurityStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  2008. &SecurityContext, SECPKG_ATTR_DCE_INFO, &DceInfo);
  2009. ASSERT( (SecurityStatus == SEC_E_OK)
  2010. || (SecurityStatus == SEC_E_UNSUPPORTED_FUNCTION)
  2011. || (SecurityStatus == SEC_E_INVALID_HANDLE));
  2012. if (SecurityStatus == SEC_E_OK)
  2013. {
  2014. *PacHandle = DceInfo.pPac;
  2015. *AuthzSvc = DceInfo.AuthzSvc;
  2016. return 0;
  2017. }
  2018. if (AuthenticationService == RPC_C_AUTHN_GSS_SCHANNEL)
  2019. {
  2020. SecurityStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  2021. &SecurityContext, SECPKG_ATTR_REMOTE_CERT_CONTEXT, PacHandle);
  2022. if (SecurityStatus != SEC_E_OK)
  2023. {
  2024. *PacHandle = 0;
  2025. }
  2026. }
  2027. return SecurityStatus;
  2028. }
  2029. void
  2030. SECURITY_CONTEXT::DeleteSecurityContext (
  2031. void
  2032. )
  2033. /*++
  2034. Routine Description:
  2035. If there is a valid security context, we need to delete it.
  2036. --*/
  2037. {
  2038. SECURITY_STATUS SecurityStatus;
  2039. unsigned int nRetries = 0;
  2040. if ( DontForgetToDelete != 0 )
  2041. {
  2042. if (AuthzClientContext)
  2043. {
  2044. AuthzFreeContextFn(AuthzClientContext);
  2045. AuthzClientContext = NULL;
  2046. }
  2047. // SEC_E_INSUFFICIENT_MEMORY may be returned under extremely low
  2048. // memory conditions. We will do the following:
  2049. // - Retry 10 times to delete the security context.
  2050. // - Raise a flag in the process that we have leaked one or more security contexts.
  2051. do
  2052. {
  2053. SecurityStatus = (*RpcSecurityInterface->DeleteSecurityContext)(
  2054. &SecurityContext );
  2055. nRetries++;
  2056. }
  2057. while (SecurityStatus == SEC_E_INSUFFICIENT_MEMORY && nRetries < 10);
  2058. if (SecurityStatus == SEC_E_INSUFFICIENT_MEMORY)
  2059. {
  2060. nSecurityContextsLeaked++;
  2061. }
  2062. // when the process shutdowns, the security system may return SEC_E_SECPKG_NOT_FOUND
  2063. // since it is uninitialized. This is the only time when this error will be
  2064. // returned, so it is safe to ignore.
  2065. if (SecurityStatus == SEC_E_SECPKG_NOT_FOUND)
  2066. SecurityStatus = SEC_E_OK;
  2067. #if DBG
  2068. if ((SecurityStatus != SEC_E_OK) && (SecurityStatus != SEC_E_SHUTDOWN_IN_PROGRESS))
  2069. {
  2070. PrintToDebugger("DeleteSecurityContext(0x%x) Returned [%lx]\n",
  2071. &SecurityContext,
  2072. SecurityStatus);
  2073. }
  2074. if (SecurityStatus == SEC_E_INSUFFICIENT_MEMORY)
  2075. {
  2076. PrintToDebugger("SecurityContext(0x%x) leaked\n",
  2077. &SecurityContext);
  2078. }
  2079. #endif
  2080. ASSERT( SecurityStatus == SEC_E_OK ||
  2081. SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS ||
  2082. SecurityStatus == SEC_E_INSUFFICIENT_MEMORY);
  2083. DontForgetToDelete = 0;
  2084. }
  2085. if (FailedContextEEInfo)
  2086. {
  2087. FreeEEInfoChain(FailedContextEEInfo);
  2088. FailedContextEEInfo = NULL;
  2089. }
  2090. }
  2091. RPC_STATUS
  2092. SECURITY_CONTEXT::CheckForFailedThirdLeg (
  2093. void
  2094. )
  2095. /*++
  2096. Routine Description:
  2097. If the third leg has failed, we will return the error code
  2098. and restore the eeinfo.
  2099. --*/
  2100. {
  2101. ASSERT( ( SecuritySupportLoaded != 0 )
  2102. && ( FailedToLoad == 0 ) );
  2103. if (FailedContext != 0)
  2104. {
  2105. if (FailedContextEEInfo)
  2106. {
  2107. RpcpSetEEInfo(FailedContextEEInfo);
  2108. FailedContextEEInfo = NULL;
  2109. }
  2110. return (RPC_S_ACCESS_DENIED);
  2111. }
  2112. return RPC_S_OK;
  2113. }
  2114. void
  2115. SECURITY_CONTEXT::DeletePac(
  2116. void __RPC_FAR * PacHandle
  2117. )
  2118. /*++
  2119. Return Value:
  2120. --*/
  2121. {
  2122. if (AuthenticationService == RPC_C_AUTHN_GSS_SCHANNEL)
  2123. {
  2124. if (!LoadCrypt32Imports())
  2125. {
  2126. return;
  2127. }
  2128. CertFreeCertificateContext( (PCERT_CONTEXT) PacHandle );
  2129. }
  2130. else
  2131. {
  2132. (*RpcSecurityInterface->FreeContextBuffer)( PacHandle );
  2133. }
  2134. }
  2135. RPC_STATUS
  2136. SECURITY_CONTEXT::ImpersonateClient (
  2137. )
  2138. /*++
  2139. Routine Description:
  2140. The server thread calling this routine will impersonate the client at the
  2141. other end of this security context.
  2142. Return Value:
  2143. RPC_S_OK - The impersonation successfully occured.
  2144. RPC_S_NO_CONTEXT_AVAILABLE - There is no security context available to
  2145. be impersonated.
  2146. --*/
  2147. {
  2148. SECURITY_STATUS SecurityStatus;
  2149. ASSERT( ( SecuritySupportLoaded != 0 )
  2150. && ( FailedToLoad == 0 ) );
  2151. if (FailedContext != 0)
  2152. {
  2153. if (FailedContextEEInfo)
  2154. {
  2155. RpcpSetEEInfo(FailedContextEEInfo);
  2156. FailedContextEEInfo = NULL;
  2157. }
  2158. return (RPC_S_ACCESS_DENIED);
  2159. }
  2160. ASSERT( FullyConstructed() );
  2161. SecurityStatus = (*RpcSecurityInterface->ImpersonateSecurityContext)(
  2162. &SecurityContext);
  2163. if ( SecurityStatus != SEC_E_OK )
  2164. {
  2165. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  2166. RPC_S_NO_CONTEXT_AVAILABLE,
  2167. EEInfoDLImpersonateClient10,
  2168. SecurityStatus,
  2169. AuthenticationService,
  2170. AuthenticationLevel);
  2171. ASSERT( SecurityStatus == SEC_E_NO_IMPERSONATION );
  2172. return(RPC_S_NO_CONTEXT_AVAILABLE);
  2173. }
  2174. return(RPC_S_OK);
  2175. }
  2176. void
  2177. SECURITY_CONTEXT::RevertToSelf (
  2178. )
  2179. /*++
  2180. Routine Description:
  2181. The server thread calling this routine will stop impersonating. If the
  2182. thread is not impersonating, then this is a noop.
  2183. --*/
  2184. {
  2185. SECURITY_STATUS SecurityStatus;
  2186. ASSERT( ( SecuritySupportLoaded != 0 )
  2187. && ( FailedToLoad == 0 ) );
  2188. SecurityStatus = (*RpcSecurityInterface->RevertSecurityContext)(
  2189. &SecurityContext);
  2190. ASSERT( SecurityStatus == SEC_E_OK );
  2191. }
  2192. RPC_STATUS
  2193. SECURITY_CONTEXT::GetAccessToken (
  2194. OUT HANDLE *ImpersonationToken,
  2195. OUT BOOL *fNeedToCloseToken
  2196. )
  2197. /*++
  2198. Routine Description:
  2199. Gets the access token maintained by the security provider.
  2200. Arguments:
  2201. ImpersonationToken - contains the impersonation token on success
  2202. fNeedToCloseToken - true if the resulting token needs closing.
  2203. False otherwise. Some security providers support handing off
  2204. of the token itself (faster). Some don't. All support handing
  2205. off a copy of the token. Depending on what security provider
  2206. we have, we'll get the token, and set this variable. This
  2207. parameter is undefined in case of failure.
  2208. Return Value:
  2209. RPC_S_OK on success, or RPC_S_* on failure. Supports EEInfo.
  2210. --*/
  2211. {
  2212. SECURITY_STATUS SecurityStatus;
  2213. HANDLE Token;
  2214. ASSERT( ( SecuritySupportLoaded != 0 )
  2215. && ( FailedToLoad == 0 ) );
  2216. ASSERT( FullyConstructed() );
  2217. SecurityStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  2218. &SecurityContext,
  2219. SECPKG_ATTR_ACCESS_TOKEN,
  2220. &Token);
  2221. if ( (SecurityStatus != SEC_E_OK)
  2222. && (SecurityStatus != SEC_E_UNSUPPORTED_FUNCTION) )
  2223. {
  2224. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  2225. RPC_S_NO_CONTEXT_AVAILABLE,
  2226. EEInfoDLSECURITY_CONTEXT__GetAccessToken10,
  2227. SecurityStatus,
  2228. AuthenticationService,
  2229. AuthenticationLevel);
  2230. ASSERT( 0 );
  2231. return(RPC_S_NO_CONTEXT_AVAILABLE);
  2232. }
  2233. if (SecurityStatus != SEC_E_OK)
  2234. {
  2235. ASSERT(SecurityStatus == SEC_E_UNSUPPORTED_FUNCTION);
  2236. // the security provider does not provide quick retrieval
  2237. // of token - go the long way
  2238. SecurityStatus = (*RpcSecurityInterface->QuerySecurityContextToken)(
  2239. &SecurityContext, &Token);
  2240. if (SecurityStatus != SEC_E_OK)
  2241. {
  2242. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  2243. RPC_S_NO_CONTEXT_AVAILABLE,
  2244. EEInfoDLSECURITY_CONTEXT__GetAccessToken20,
  2245. SecurityStatus,
  2246. AuthenticationService,
  2247. AuthenticationLevel);
  2248. ASSERT( SecurityStatus == SEC_E_NO_IMPERSONATION );
  2249. return(RPC_S_NO_CONTEXT_AVAILABLE);
  2250. }
  2251. *fNeedToCloseToken = TRUE;
  2252. }
  2253. else
  2254. {
  2255. *fNeedToCloseToken = FALSE;
  2256. }
  2257. *ImpersonationToken = Token;
  2258. return RPC_S_OK;
  2259. }
  2260. PACKAGE_LEG_COUNT
  2261. GetPackageLegCount(
  2262. DWORD id
  2263. )
  2264. /*++
  2265. Routine Description:
  2266. This fn determines whether the given security package is a 3- or 4-leg
  2267. protocol. The relevance of this information is described in
  2268. ReadPackageLegInfo(). This fn. first searches the hardcoded entries in
  2269. PredefinedPackageLegInfo[], and if the package is not found it turns to the
  2270. registry information stored in FourLeggedPackages[].
  2271. Return Values:
  2272. LegsUnknown = the fn cannot give a reliable answer
  2273. ThreeLegs = this is a 3-leg protocol
  2274. EvenNumberOfLegs = this is not a 3-leg protocol
  2275. --*/
  2276. {
  2277. int i;
  2278. if ( InsureSecuritySupportLoaded() != RPC_S_OK )
  2279. {
  2280. return LegsUnknown;
  2281. }
  2282. for (i=0; PredefinedPackageLegInfo[i].Package != 0; ++i)
  2283. {
  2284. if (PredefinedPackageLegInfo[i].Package == id)
  2285. {
  2286. return PredefinedPackageLegInfo[i].Legs;
  2287. }
  2288. }
  2289. CLAIM_MUTEX Lock( *SecurityCritSect );
  2290. if (!FourLeggedPackages)
  2291. {
  2292. if (!ReadPackageLegInfo())
  2293. {
  2294. return LegsUnknown;
  2295. }
  2296. }
  2297. ASSERT(FourLeggedPackages);
  2298. for (i=0; FourLeggedPackages[i] != 0; ++i)
  2299. {
  2300. if (FourLeggedPackages[i] == id)
  2301. {
  2302. return EvenNumberOfLegs;
  2303. }
  2304. }
  2305. return ThreeLegs;
  2306. }
  2307. DWORD
  2308. SECURITY_CONTEXT::VerifyCertificate()
  2309. {
  2310. DWORD SecurityStatus = 0;
  2311. //
  2312. // Compare the name on the certificate against the expected principal name.
  2313. //
  2314. if (ServerPrincipalName)
  2315. {
  2316. //
  2317. // Get a copy of the raw certificate.
  2318. //
  2319. if (!LoadCrypt32Imports())
  2320. {
  2321. return GetLastError();
  2322. }
  2323. PCERT_CONTEXT ClientContext;
  2324. SecurityStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  2325. &SecurityContext,
  2326. SECPKG_ATTR_REMOTE_CERT_CONTEXT,
  2327. &ClientContext
  2328. );
  2329. if (SecurityStatus)
  2330. {
  2331. RpcpErrorAddRecord ( EEInfoGCSecurityProvider,
  2332. RPC_S_OUT_OF_MEMORY,
  2333. EEInfoDLInitializeThirdLeg60,
  2334. SecurityStatus );
  2335. ASSERT( SecurityStatus == SEC_E_INSUFFICIENT_MEMORY );
  2336. return SecurityStatus;
  2337. }
  2338. SecurityStatus = RpcCertMatchPrincipalName( ClientContext, ServerPrincipalName );
  2339. switch (SecurityStatus)
  2340. {
  2341. case 0:
  2342. case ERROR_NOT_ENOUGH_MEMORY:
  2343. break;
  2344. default:
  2345. //
  2346. // we are supposed to have verified the princ name earlier.
  2347. //
  2348. ASSERT( SecurityStatus != ERROR_INVALID_PARAMETER );
  2349. SetExtendedError(SecurityStatus);
  2350. SecurityStatus = RPC_S_ACCESS_DENIED;
  2351. break;
  2352. }
  2353. CertFreeCertificateContext( ClientContext );
  2354. }
  2355. return SecurityStatus;
  2356. }