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.

3098 lines
88 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 or
  28. // SECURITY_CREDENTIALS::CredentialsHandle due to DeleteSecurityContext
  29. // or FreeCredentialHandle returning SEC_E_INSUFFICIENT_MEMORY.
  30. unsigned int nSecurityStructuresLeaked = 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)
  266. {
  267. Status = RPC_S_OUT_OF_MEMORY;
  268. goto Cleanup;
  269. }
  270. if (Status == RPC_S_INVALID_ARG)
  271. {
  272. delete ProviderDll;
  273. Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  274. goto Cleanup;
  275. }
  276. else if (Status != RPC_S_OK)
  277. {
  278. delete ProviderDll;
  279. goto Cleanup;
  280. }
  281. ASSERT(!RpcpCheckHeap());
  282. InitSecurityInterface = (INIT_SECURITY_INTERFACE_W)
  283. ProviderDll->GetEntryPoint(SECURITY_ENTRYPOINT_ANSIW);
  284. if ( InitSecurityInterface == 0 )
  285. {
  286. delete ProviderDll;
  287. Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  288. goto Cleanup;
  289. }
  290. SecurityInterface = (*InitSecurityInterface)();
  291. if ( (SecurityInterface == 0)
  292. || (SecurityInterface->dwVersion
  293. < SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION) )
  294. {
  295. delete ProviderDll;
  296. Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  297. goto Cleanup;
  298. }
  299. Status = (*SecurityInterface->EnumerateSecurityPackages)(
  300. &NumberOfPackages, &tmpPkgList);
  301. if ( Status != SEC_E_OK)
  302. {
  303. delete ProviderDll;
  304. if (Status == SEC_E_INSUFFICIENT_MEMORY)
  305. {
  306. Status = RPC_S_OUT_OF_MEMORY;
  307. }
  308. else
  309. {
  310. VALIDATE(Status) {
  311. SEC_E_SECPKG_NOT_FOUND
  312. } END_VALIDATE;
  313. Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  314. }
  315. goto Cleanup;
  316. }
  317. ProviderList[LoadedProviders].Count = NumberOfPackages;
  318. ProviderList[LoadedProviders].RpcSecurityInterface = SecurityInterface;
  319. ProviderList[LoadedProviders].ProviderDll = ProviderDll;
  320. ProviderList[LoadedProviders].ProviderDllName = DllName;
  321. *ProviderIndex = LoadedProviders;
  322. //
  323. // Fill in the SecurityPackages member for this Provider.
  324. //
  325. ProviderList[LoadedProviders].SecurityPackages =
  326. (SECURITY_PACKAGE_INFO *) new char
  327. [sizeof(SECURITY_PACKAGE_INFO) * NumberOfPackages];
  328. if (ProviderList[LoadedProviders].SecurityPackages == NULL)
  329. {
  330. Status = RPC_S_OUT_OF_MEMORY;
  331. goto Cleanup;
  332. }
  333. //
  334. // Save the SecPkgInfo array to the SecurityPackages structure.
  335. //
  336. for (i = 0; i < NumberOfPackages; i++)
  337. {
  338. ProviderList[LoadedProviders].
  339. SecurityPackages[i].
  340. PackageInfo = tmpPkgList[i];
  341. ProviderList[LoadedProviders].
  342. SecurityPackages[i].
  343. ServerSecurityCredentials = NULL;
  344. }
  345. SecurityPackages = ProviderList[LoadedProviders].SecurityPackages;
  346. Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  347. for (i = 0; i < NumberOfPackages; i++)
  348. {
  349. if ( SecurityPackages[i].PackageInfo.wRPCID == AuthenticationService )
  350. {
  351. if ( ( AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY )
  352. ||( AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT) )
  353. {
  354. if ( (SecurityPackages[i].PackageInfo.fCapabilities
  355. & SECPKG_FLAG_INTEGRITY) == 0 )
  356. {
  357. Status = RPC_S_UNKNOWN_AUTHN_LEVEL;
  358. continue;
  359. }
  360. }
  361. if ( AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY )
  362. {
  363. if ( (SecurityPackages[i].PackageInfo.fCapabilities
  364. & SECPKG_FLAG_PRIVACY) == 0 )
  365. {
  366. Status = RPC_S_UNKNOWN_AUTHN_LEVEL;
  367. continue;
  368. }
  369. }
  370. *PackageIndex = i;
  371. Status = RPC_S_OK;
  372. break;
  373. }
  374. }
  375. LoadedProviders++;
  376. Cleanup:
  377. SecurityCritSect->Clear();
  378. return(Status);
  379. }
  380. RPC_STATUS
  381. FindServerCredentials (
  382. IN RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
  383. IN void __RPC_FAR * Arg,
  384. IN unsigned long AuthenticationService,
  385. IN unsigned long AuthenticationLevel,
  386. IN RPC_CHAR __RPC_FAR * Principal,
  387. IN OUT SECURITY_CREDENTIALS ** SecurityCredentials
  388. )
  389. /*++
  390. Routine Description:
  391. The method is used to find cached server credentials for use by the
  392. server.
  393. Arguments:
  394. AuthenticationService - Supplies the authentication service to be used
  395. (for the credentials and for the context).
  396. AuthenticationLevel - Supplies the authentication level to be used by
  397. these credentials. It will already have been mapped by the protocol
  398. module into the final level.
  399. SecurityCredentials - TBS
  400. RpcStatus - Returns the status of the operation. It will be one of the
  401. following values.
  402. RPC_S_OK - The return value from this routine is the index of
  403. the appropriate security package.
  404. RPC_S_UNKNOWN_AUTHN_SERVICE - The specified authentication service is
  405. not supported by the current configuration.
  406. RPC_S_UNKNOWN_AUTHN_LEVEL - The specified authentication level is not
  407. supported by the requested authentication service.
  408. Return Value:
  409. If RpcStatus contains RPC_S_OK, then valid credentials are passed
  410. back.
  411. --*/
  412. {
  413. SECURITY_STATUS SecurityStatus;
  414. TimeStamp TimeStamp;
  415. RPC_STATUS RpcStatus, CredStatus = RPC_S_OK;
  416. PSecurityFunctionTable RpcSecurityInterface;
  417. SECURITY_PACKAGE_INFO *pPackageInfo = 0;
  418. SECURITY_CREDENTIALS *pSecCredentials = 0;
  419. CredHandle tmpCredHandle;
  420. unsigned int ProviderIndex;
  421. unsigned int PackageIndex;
  422. //
  423. // NULL out the OUT parameters.
  424. //
  425. *SecurityCredentials = NULL;
  426. //
  427. // Find the right security package
  428. //
  429. RpcStatus = FindSecurityPackage(
  430. AuthenticationService,
  431. AuthenticationLevel,
  432. &ProviderIndex,
  433. &PackageIndex
  434. );
  435. if (RpcStatus != RPC_S_OK)
  436. {
  437. RpcpErrorAddRecord (EEInfoGCRuntime,
  438. RpcStatus,
  439. EEInfoDLFindServerCredentials10,
  440. AuthenticationService,
  441. AuthenticationLevel);
  442. return (RpcStatus);
  443. }
  444. //
  445. // Now, get the server-credentials for this security package.
  446. //
  447. pPackageInfo = &(ProviderList[ProviderIndex].
  448. SecurityPackages[PackageIndex]
  449. );
  450. // Protect the access
  451. SecurityCritSect->Request();
  452. //
  453. // Check to see if credentials have already been acquired for this
  454. // package. If yes, return them.
  455. //
  456. if (pPackageInfo->ServerSecurityCredentials)
  457. {
  458. *SecurityCredentials = pPackageInfo->ServerSecurityCredentials;
  459. // Add a reference for the caller.
  460. pPackageInfo->ServerSecurityCredentials->ReferenceCredentials();
  461. SecurityCritSect->Clear();
  462. return (RPC_S_OK);
  463. }
  464. //
  465. // Allocate a new set of credentials. Ref count is 1, if successful.
  466. //
  467. pSecCredentials = new SECURITY_CREDENTIALS(&CredStatus);
  468. if (pSecCredentials == NULL)
  469. {
  470. SecurityCritSect->Clear();
  471. return (RPC_S_OUT_OF_MEMORY);
  472. }
  473. if (CredStatus != RPC_S_OK)
  474. {
  475. delete pSecCredentials;
  476. SecurityCritSect->Clear();
  477. return (CredStatus);
  478. }
  479. //
  480. // This is the first time Credentials are being acquired for this
  481. // package. Acquire them now.
  482. //
  483. RpcSecurityInterface = ProviderList[ProviderIndex].RpcSecurityInterface;
  484. SecurityStatus = (*RpcSecurityInterface->AcquireCredentialsHandle)(
  485. (SEC_TCHAR __SEC_FAR *) Principal,
  486. pPackageInfo->PackageInfo.Name,
  487. SECPKG_CRED_INBOUND,
  488. 0,
  489. Arg,
  490. (SEC_GET_KEY_FN) GetKeyFn,
  491. Arg,
  492. &(pSecCredentials->CredentialsHandle),
  493. &TimeStamp
  494. );
  495. if (SecurityStatus != SEC_E_OK)
  496. {
  497. SetExtendedError(SecurityStatus);
  498. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  499. SecurityStatus,
  500. EEInfoDLFindServerCredentials20,
  501. Principal,
  502. pPackageInfo->PackageInfo.Name);
  503. SecurityCritSect->Clear();
  504. delete pSecCredentials;
  505. switch (SecurityStatus)
  506. {
  507. case SEC_E_INSUFFICIENT_MEMORY:
  508. RpcStatus = RPC_S_OUT_OF_MEMORY;
  509. break;
  510. case SEC_E_SHUTDOWN_IN_PROGRESS:
  511. RpcStatus = ERROR_SHUTDOWN_IN_PROGRESS;
  512. break;
  513. case SEC_E_SECPKG_NOT_FOUND:
  514. RpcStatus = RPC_S_UNKNOWN_AUTHN_SERVICE;
  515. break;
  516. case SEC_E_NO_SPM:
  517. RpcStatus = RPC_S_SEC_PKG_ERROR;
  518. break;
  519. default:
  520. {
  521. #if DBG
  522. if ((SecurityStatus != SEC_E_NO_CREDENTIALS) &&
  523. (SecurityStatus != SEC_E_UNKNOWN_CREDENTIALS))
  524. {
  525. PrintToDebugger("RPC SEC: AcquireCredentialsForServer "
  526. "Returned 0x%x\n", SecurityStatus);
  527. }
  528. #endif
  529. RpcStatus = RPC_S_INVALID_AUTH_IDENTITY;
  530. }
  531. } // end of switch
  532. RpcpErrorAddRecord (EEInfoGCRuntime,
  533. RpcStatus,
  534. EEInfoDLFindServerCredentials30,
  535. SecurityStatus);
  536. return RpcStatus;
  537. }
  538. //
  539. // Setup the new Credentials.
  540. //
  541. pSecCredentials->Valid = TRUE;
  542. pSecCredentials->AuthenticationService = AuthenticationService;
  543. pSecCredentials->ProviderIndex = ProviderIndex;
  544. pSecCredentials->PackageIndex = PackageIndex;
  545. //
  546. // Cache the new credentials. They are created with refcount 1
  547. // and this refcount will be removed in RemoveCredentialsFromCache
  548. //
  549. pPackageInfo->ServerSecurityCredentials = pSecCredentials;
  550. // Add a reference for the Cache.
  551. pPackageInfo->ServerSecurityCredentials->ReferenceCredentials();
  552. *SecurityCredentials = pSecCredentials;
  553. SecurityCritSect->Clear();
  554. return (RPC_S_OK);
  555. }
  556. RPC_STATUS
  557. RemoveCredentialsFromCache (
  558. IN unsigned long AuthenticationService
  559. )
  560. /*++
  561. Routine Description:
  562. An RPC server can call RpcRegisterAuthInfo() a second time on the same
  563. Authentication Service to update the GetKeyFunction and Arg values.
  564. In this case, we need to flush our credentials cache so that when
  565. the server tries to acquires credentials again, the credentials can
  566. be acquired using the new values.
  567. Arguments:
  568. AuthenticationService - Supplies the authentication service to be used
  569. (for the credentials and for the context).
  570. Return Value:
  571. RPC_S_OK, If Cache has been successfully flushed.
  572. Return Value from FindSecurityPackage(), if not
  573. --*/
  574. {
  575. unsigned int ProviderIndex;
  576. unsigned int PackageIndex;
  577. SECURITY_PACKAGE_INFO *pPackageInfo = 0;
  578. RPC_STATUS RpcStatus;
  579. //
  580. // First, find the right security package
  581. //
  582. RpcStatus = FindSecurityPackage(
  583. AuthenticationService,
  584. RPC_C_AUTHN_LEVEL_DEFAULT, // Doesn't matter
  585. &ProviderIndex,
  586. &PackageIndex
  587. );
  588. ASSERT(RpcStatus == RPC_S_OK);
  589. if (RpcStatus != RPC_S_OK)
  590. {
  591. return (RpcStatus);
  592. }
  593. pPackageInfo = &(ProviderList[ProviderIndex].SecurityPackages[PackageIndex]);
  594. //
  595. // Flush the credentials.
  596. //
  597. SecurityCritSect->Request();
  598. if (pPackageInfo->ServerSecurityCredentials)
  599. {
  600. // Remove the reference maintained by the cache.
  601. pPackageInfo->ServerSecurityCredentials->DereferenceCredentials();
  602. pPackageInfo->ServerSecurityCredentials = NULL;
  603. }
  604. SecurityCritSect->Clear();
  605. return (RPC_S_OK);
  606. }
  607. #define INVALID_INDEX 0xFFFF
  608. SECURITY_CREDENTIALS::SECURITY_CREDENTIALS (
  609. IN OUT RPC_STATUS PAPI * Status
  610. ) : CredentialsMutex(Status)
  611. /*++
  612. Routine Description:
  613. We need this here to keep the compiler happy.
  614. --*/
  615. {
  616. DefaultPrincName = NULL;
  617. ReferenceCount = 1;
  618. Valid = FALSE;
  619. // Initialize to invalid values.
  620. ProviderIndex = INVALID_INDEX;
  621. PackageIndex = INVALID_INDEX;
  622. }
  623. SECURITY_CREDENTIALS::~SECURITY_CREDENTIALS (
  624. )
  625. {
  626. PSecurityFunctionTable RpcSecurityInterface;
  627. if (DefaultPrincName != NULL)
  628. {
  629. RpcSecurityInterface = InquireProviderFunctionTable();
  630. ASSERT(RpcSecurityInterface != NULL);
  631. (*RpcSecurityInterface->FreeContextBuffer)(DefaultPrincName);
  632. }
  633. }
  634. void
  635. SECURITY_CREDENTIALS::ReferenceCredentials(
  636. )
  637. {
  638. CredentialsMutex.Request();
  639. LogEvent(SU_SECCRED, EV_INC, this, 0, ReferenceCount, 1, 0);
  640. ReferenceCount++;
  641. CredentialsMutex.Clear();
  642. }
  643. void
  644. SECURITY_CREDENTIALS::DereferenceCredentials(
  645. void
  646. )
  647. {
  648. CredentialsMutex.Request();
  649. LogEvent(SU_SECCRED, EV_DEC, this, 0, ReferenceCount, 1, 0);
  650. ReferenceCount--;
  651. ASSERT(((long)ReferenceCount) >= 0);
  652. if (ReferenceCount == 0)
  653. {
  654. //
  655. // Server side SCENARIOS when (ReferenceCount == 0)
  656. //
  657. // a. RemoveCredentialsFromCache() removes the extra reference
  658. // held by the cache. It does so holding the cache Mutex ie.,
  659. // SecurityCritSect. So, no other thread can get a reference
  660. // on the credentials in the cache.
  661. //
  662. // b. DereferenceCredentials() has been called by one of the
  663. // threads possessing the cached credentials AND the cache
  664. // has already removed it's reference. Cache will remove its
  665. // reference only when it removes this credential from the
  666. // cache. This implies no other thread could have gotten a
  667. // reference on the credentials in the cache, in the meantime.
  668. //
  669. // These two imply that ReferenceCount cannot change here. Also,
  670. // in case (a), credentials will soon be removed from the cache.
  671. // In case (b), credentials have already been removed.
  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. unsigned int nRetries = 0;
  883. if (Valid)
  884. {
  885. SECURITY_STATUS SecurityStatus;
  886. PSecurityFunctionTable RpcSecurityInterface
  887. = ProviderList[ProviderIndex].RpcSecurityInterface;
  888. // SEC_E_INSUFFICIENT_MEMORY may be returned under extremely low
  889. // memory conditions. We will do the following:
  890. // - Retry 10 times to delete the credential handle.
  891. // - Raise a flag in the process that we have leaked one or more security ts.
  892. do
  893. {
  894. SecurityStatus = (*RpcSecurityInterface->FreeCredentialHandle)(
  895. &CredentialsHandle);
  896. nRetries++;
  897. }
  898. while (SecurityStatus == SEC_E_INSUFFICIENT_MEMORY && nRetries < 10);
  899. if (SecurityStatus == SEC_E_INSUFFICIENT_MEMORY)
  900. {
  901. nSecurityStructuresLeaked++;
  902. }
  903. #if DBG
  904. if ((SecurityStatus != SEC_E_OK) && (SecurityStatus != SEC_E_SHUTDOWN_IN_PROGRESS))
  905. {
  906. PrintToDebugger("FreeCredentialHandle(0x%x) Returned [%lx]\n",
  907. &CredentialsHandle,
  908. SecurityStatus);
  909. }
  910. if (SecurityStatus == SEC_E_INSUFFICIENT_MEMORY)
  911. {
  912. PrintToDebugger("CredentialsHandle(0x%x) leaked\n",
  913. &CredentialsHandle);
  914. }
  915. #endif
  916. ASSERT( SecurityStatus == SEC_E_OK ||
  917. SecurityStatus == SEC_E_SECPKG_NOT_FOUND ||
  918. SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS ||
  919. SecurityStatus == SEC_E_INSUFFICIENT_MEMORY);
  920. }
  921. }
  922. RPC_STATUS
  923. SECURITY_CONTEXT::SetMaximumLengths (
  924. )
  925. /*++
  926. Routine Description:
  927. This routine initializes the maximum header length and maximum signature
  928. length fields of this object.
  929. --*/
  930. {
  931. SECURITY_STATUS SecurityStatus;
  932. SecPkgContext_Sizes ContextSizes;
  933. RPC_STATUS Status;
  934. if (FailedContext != 0)
  935. {
  936. // We cheat if 3rd Leg Failed as we dont really have a true Context
  937. // Provider is going to really complain if we call QueryContextAttr()
  938. // .. we get around that by picking large values.
  939. // The rest of the code prevents these values to be really used
  940. // We do this because we do not want to block 3rd Leg, rather fail the
  941. // first request!
  942. MaxSignatureLength = 256;
  943. MaxHeaderLength = 256;
  944. cbBlockSize = 64;
  945. return RPC_S_OK;
  946. }
  947. ASSERT( FullyConstructed() );
  948. SecurityStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  949. &SecurityContext, SECPKG_ATTR_SIZES, &ContextSizes);
  950. if (SecurityStatus != SEC_E_OK)
  951. {
  952. #ifdef DEBUGRPC
  953. PrintToDebugger("RPC: secclnt.cxx: QueryContextAttributes returned: %lx\n",
  954. SecurityStatus);
  955. #endif
  956. Status = GetLastError();
  957. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  958. RPC_S_OUT_OF_MEMORY,
  959. EEInfoDLSetMaximumLengths10,
  960. SecurityStatus,
  961. Status,
  962. AuthenticationService,
  963. (ULONGLONG)&SecurityContext
  964. );
  965. return RPC_S_OUT_OF_MEMORY;
  966. }
  967. MaxSignatureLength = (unsigned int) ContextSizes.cbMaxSignature;
  968. MaxHeaderLength = (unsigned int) ContextSizes.cbSecurityTrailer;
  969. cbBlockSize = (unsigned int) ContextSizes.cbBlockSize;
  970. ASSERT(ContextSizes.cbBlockSize <= MAXIMUM_SECURITY_BLOCK_SIZE );
  971. return RPC_S_OK;
  972. }
  973. SECURITY_CONTEXT::SECURITY_CONTEXT (
  974. CLIENT_AUTH_INFO *myAuthInfo,
  975. unsigned myAuthContextId,
  976. BOOL fUseDatagram,
  977. RPC_STATUS __RPC_FAR * pStatus
  978. )
  979. : CLIENT_AUTH_INFO (myAuthInfo, pStatus),
  980. AuthContextId (myAuthContextId),
  981. fDatagram ((boolean) fUseDatagram),
  982. fFullyConstructed (FALSE),
  983. Legs (LegsUnknown),
  984. ContextAttributes (0)
  985. /*++
  986. Routine Description:
  987. We need to set the flag indicating that there is no security context
  988. to be deleted.
  989. --*/
  990. {
  991. CORRUPTION_ASSERT( AuthenticationLevel != 0 );
  992. DontForgetToDelete = 0;
  993. FailedContext = 0;
  994. FailedContextEEInfo = NULL;
  995. AuthzClientContext = NULL;
  996. }
  997. RPC_STATUS
  998. SECURITY_CONTEXT::CompleteSecurityToken (
  999. IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * BufferDescriptor
  1000. )
  1001. /*++
  1002. --*/
  1003. {
  1004. SECURITY_STATUS SecurityStatus;
  1005. RPC_STATUS Status;
  1006. ASSERT( ( SecuritySupportLoaded != 0 )
  1007. && ( FailedToLoad == 0 ) );
  1008. SecurityStatus = (*RpcSecurityInterface->CompleteAuthToken)(
  1009. &SecurityContext, BufferDescriptor);
  1010. if (SecurityStatus == SEC_E_OK)
  1011. {
  1012. return (RPC_S_OK);
  1013. }
  1014. SetExtendedError(SecurityStatus);
  1015. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1016. SecurityStatus,
  1017. EEInfoDLCompleteSecurityToken10,
  1018. AuthenticationService,
  1019. AuthenticationLevel);
  1020. if ( (SecurityStatus == SEC_E_NO_CREDENTIALS)
  1021. || (SecurityStatus == SEC_E_LOGON_DENIED)
  1022. || (SecurityStatus == SEC_E_INVALID_TOKEN)
  1023. || (SecurityStatus == SEC_E_UNKNOWN_CREDENTIALS)
  1024. || (SecurityStatus == SEC_E_WRONG_PRINCIPAL)
  1025. || (SecurityStatus == SEC_E_TIME_SKEW))
  1026. {
  1027. Status = RPC_S_ACCESS_DENIED;
  1028. }
  1029. else if ( SecurityStatus == SEC_E_INSUFFICIENT_MEMORY )
  1030. {
  1031. Status = RPC_S_OUT_OF_MEMORY;
  1032. }
  1033. else if ( SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS )
  1034. {
  1035. Status = ERROR_SHUTDOWN_IN_PROGRESS;
  1036. }
  1037. else
  1038. {
  1039. #if DBG
  1040. PrintToDebugger("RPC: CompleteSecurityContext Returned %lx\n",
  1041. SecurityStatus);
  1042. #endif
  1043. Status = RPC_S_SEC_PKG_ERROR;
  1044. }
  1045. RpcpErrorAddRecord (EEInfoGCRuntime,
  1046. Status,
  1047. EEInfoDLCompleteSecurityToken20,
  1048. SecurityStatus);
  1049. return Status;
  1050. }
  1051. RPC_STATUS
  1052. SECURITY_CONTEXT::SignOrSeal (
  1053. IN unsigned long Sequence,
  1054. IN unsigned int SignNotSealFlag,
  1055. IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * BufferDescriptor
  1056. )
  1057. /*++
  1058. Routine Description:
  1059. A protocol module will use this routine to prepare a message to be
  1060. sent so that it can be verified that the message has not been tampered
  1061. with, and that it has not been exchanged out of sequence. The sender
  1062. will use this routine to prepare the message; the receiver will use
  1063. SECURITY_CONTEXT::VerifyOrUnseal to verify the message. Typically,
  1064. the security package will generate a cryptographic checksum of the
  1065. message and include sequencing information.
  1066. Arguments:
  1067. SignNotSealFlag - Supplies a flag indicating that MakeSignature should
  1068. be called rather than SealMessage.
  1069. BufferDescriptor - Supplies the message to to signed or sealed and returns
  1070. the resulting message (after being signed or sealed).
  1071. Return Value:
  1072. RPC_S_OK - This routine will always succeed.
  1073. --*/
  1074. {
  1075. SECURITY_STATUS SecurityStatus;
  1076. SEAL_MESSAGE_FN SealMessage;
  1077. {
  1078. DWORD Status = 0;
  1079. CallTestHook( TH_SECURITY_FN_SIGN, this, &Status );
  1080. if (Status)
  1081. {
  1082. return Status;
  1083. }
  1084. }
  1085. if ( SignNotSealFlag == 0 )
  1086. {
  1087. SealMessage = (SEAL_MESSAGE_FN) RpcSecurityInterface->Reserved3;
  1088. SecurityStatus = (*SealMessage)(&SecurityContext,
  1089. 0, BufferDescriptor, Sequence);
  1090. }
  1091. else
  1092. {
  1093. SecurityStatus = (*RpcSecurityInterface->MakeSignature)(
  1094. &SecurityContext, 0, BufferDescriptor, Sequence);
  1095. }
  1096. #if DBG
  1097. if ( (SecurityStatus != SEC_E_OK)
  1098. &&(SecurityStatus != SEC_E_CONTEXT_EXPIRED)
  1099. &&(SecurityStatus != SEC_E_QOP_NOT_SUPPORTED) )
  1100. {
  1101. PrintToDebugger("Sign/Seal Returned [%lx]\n", SecurityStatus);
  1102. }
  1103. #endif
  1104. if ( SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS )
  1105. {
  1106. SecurityStatus = ERROR_SHUTDOWN_IN_PROGRESS;
  1107. }
  1108. if (SecurityStatus != SEC_E_OK)
  1109. {
  1110. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1111. SecurityStatus,
  1112. EEInfoDLSignOrSeal10,
  1113. AuthenticationService,
  1114. AuthenticationLevel);
  1115. }
  1116. return(SecurityStatus);
  1117. }
  1118. extern BOOL gfRpcDisableVerifyOrUnsealAssert;
  1119. RPC_STATUS
  1120. SECURITY_CONTEXT::VerifyOrUnseal (
  1121. IN unsigned long Sequence,
  1122. IN unsigned int VerifyNotUnsealFlag,
  1123. IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * BufferDescriptor
  1124. )
  1125. /*++
  1126. Routine Description:
  1127. This routine works with SECURITY_CONTEXT::SignOrSeal. A sender will
  1128. prepare a message using SignOrSeal, and then the receiver will use
  1129. this routine to verify that the message has not been tampered with, and
  1130. that it has not been exchanged out of sequence.
  1131. Arguments:
  1132. VerifyNotUnsealFlag - Supplies a flag indicating that VerifySignature
  1133. should be called rather than UnsealMessage.
  1134. BufferDescriptor - Supplies the message to be verified or unsealed.
  1135. Return Value:
  1136. RPC_S_OK - The message has not been tampered with, and it is from the
  1137. expected client.
  1138. RPC_S_ACCESS_DENIED - A security violation occured.
  1139. --*/
  1140. {
  1141. SECURITY_STATUS SecurityStatus;
  1142. RPC_STATUS RpcStatus;
  1143. unsigned long QualityOfProtection;
  1144. UNSEAL_MESSAGE_FN UnsealMessage;
  1145. {
  1146. DWORD Status = 0;
  1147. CallTestHook( TH_SECURITY_FN_VERIFY, this, &Status );
  1148. if (Status)
  1149. {
  1150. return Status;
  1151. }
  1152. }
  1153. //
  1154. // If the context had failed previously..
  1155. // Just go ahead and return an error..
  1156. // This is only for connetion-oriented RPC.
  1157. //
  1158. if (FailedContext != 0 || !FullyConstructed() )
  1159. {
  1160. RpcpSetEEInfo(FailedContextEEInfo);
  1161. FailedContextEEInfo = NULL;
  1162. SetLastError(FailedContext);
  1163. if ((FailedContext == ERROR_PASSWORD_MUST_CHANGE)
  1164. || (FailedContext == ERROR_PASSWORD_EXPIRED)
  1165. || (FailedContext == ERROR_ACCOUNT_DISABLED)
  1166. || (FailedContext == ERROR_INVALID_LOGON_HOURS))
  1167. {
  1168. return FailedContext;
  1169. }
  1170. RpcpErrorAddRecord (EEInfoGCRuntime,
  1171. RPC_S_ACCESS_DENIED,
  1172. EEInfoDLVerifyOrUnseal20,
  1173. FailedContext);
  1174. return (RPC_S_ACCESS_DENIED);
  1175. }
  1176. if ( VerifyNotUnsealFlag == 0 )
  1177. {
  1178. UnsealMessage = (UNSEAL_MESSAGE_FN) RpcSecurityInterface->Reserved4;
  1179. SecurityStatus = (*UnsealMessage)(
  1180. &SecurityContext, BufferDescriptor, Sequence,
  1181. &QualityOfProtection);
  1182. }
  1183. else
  1184. {
  1185. SecurityStatus = (*RpcSecurityInterface->VerifySignature)(
  1186. &SecurityContext, BufferDescriptor, Sequence,
  1187. &QualityOfProtection);
  1188. }
  1189. if ( SecurityStatus != SEC_E_OK )
  1190. {
  1191. #if DBG
  1192. if ((SecurityStatus != SEC_E_MESSAGE_ALTERED)
  1193. &&(SecurityStatus != SEC_E_OUT_OF_SEQUENCE)
  1194. &&(SecurityStatus != SEC_E_SECPKG_NOT_FOUND)) // on system shutdown, if the security
  1195. { // package is already uninitialized, we may get this error
  1196. PrintToDebugger("Verify/UnSeal Returned Unexp. Code [%lx]\n",
  1197. SecurityStatus);
  1198. }
  1199. #endif
  1200. SetExtendedError(SecurityStatus);
  1201. if ( SecurityStatus == SEC_E_INSUFFICIENT_MEMORY )
  1202. {
  1203. RpcStatus = RPC_S_OUT_OF_MEMORY;
  1204. }
  1205. else
  1206. {
  1207. if (!gfRpcDisableVerifyOrUnsealAssert
  1208. && !fDatagram)
  1209. {
  1210. VALIDATE (SecurityStatus)
  1211. {
  1212. SEC_E_SHUTDOWN_IN_PROGRESS,
  1213. SEC_E_SECPKG_NOT_FOUND
  1214. }
  1215. CORRUPTION_VALIDATE
  1216. {
  1217. SEC_E_MESSAGE_ALTERED,
  1218. SEC_E_OUT_OF_SEQUENCE,
  1219. SEC_E_INVALID_TOKEN
  1220. } CORRUPTION_END_VALIDATE;
  1221. }
  1222. RpcStatus = RPC_S_ACCESS_DENIED;
  1223. }
  1224. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1225. RpcStatus,
  1226. EEInfoDLVerifyOrUnseal10,
  1227. SecurityStatus,
  1228. AuthenticationService,
  1229. AuthenticationLevel);
  1230. SetLastError(RpcStatus);
  1231. return(RpcStatus);
  1232. }
  1233. return(RPC_S_OK);
  1234. }
  1235. RPC_STATUS
  1236. SECURITY_CONTEXT::InitializeFirstTime (
  1237. IN SECURITY_CREDENTIALS * Credentials,
  1238. IN RPC_CHAR * ServerPrincipalName,
  1239. IN unsigned long AuthenticationLevel,
  1240. IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * BufferDescriptor,
  1241. IN OUT unsigned char *NewAuthType
  1242. )
  1243. /*++
  1244. Routine Description:
  1245. Arguments:
  1246. Return Value:
  1247. RPC_S_OK - Send the token to the server; everything worked fine so
  1248. far.
  1249. RPC_P_CONTINUE_NEEDED - Indicates that that everything is ok, but that
  1250. we need to call into the security package again when we have
  1251. received a token back from the server.
  1252. RPC_P_COMPLETE_NEEDED - Indicates that everyting is ok, but that we
  1253. need to call CompleteAuthToken before sending the message.
  1254. RPC_P_COMPLETE_AND_CONTINUE - Needs both a complete and a continue.
  1255. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to perform the
  1256. operation.
  1257. RPC_S_ACCESS_DENIED - Access is denied.
  1258. --*/
  1259. {
  1260. SECURITY_STATUS SecurityStatus;
  1261. TimeStamp TimeStamp;
  1262. unsigned long ContextRequirements;
  1263. RPC_STATUS Status;
  1264. RPC_STATUS Status2;
  1265. unsigned char RetrievedAuthType;
  1266. BOOL fDone;
  1267. ASSERT( ( SecuritySupportLoaded != 0 )
  1268. && ( FailedToLoad == 0 ) );
  1269. RpcSecurityInterface = Credentials->InquireProviderFunctionTable();
  1270. switch ( AuthenticationLevel )
  1271. {
  1272. case RPC_C_AUTHN_LEVEL_CONNECT :
  1273. ContextRequirements = 0;
  1274. break;
  1275. case RPC_C_AUTHN_LEVEL_PKT :
  1276. ContextRequirements = ISC_REQ_REPLAY_DETECT;
  1277. break;
  1278. case RPC_C_AUTHN_LEVEL_PKT_INTEGRITY :
  1279. ContextRequirements = ISC_REQ_REPLAY_DETECT
  1280. | ISC_REQ_SEQUENCE_DETECT
  1281. | ISC_REQ_INTEGRITY;
  1282. break;
  1283. case RPC_C_AUTHN_LEVEL_PKT_PRIVACY :
  1284. ContextRequirements = ISC_REQ_REPLAY_DETECT
  1285. | ISC_REQ_SEQUENCE_DETECT
  1286. | ISC_REQ_CONFIDENTIALITY
  1287. | ISC_REQ_INTEGRITY;
  1288. break;
  1289. default :
  1290. ASSERT( ( AuthenticationLevel == RPC_C_AUTHN_LEVEL_CONNECT )
  1291. || ( AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT )
  1292. || ( AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY )
  1293. || ( AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY ) );
  1294. return RPC_S_INTERNAL_ERROR;
  1295. }
  1296. if (fDatagram)
  1297. {
  1298. ContextRequirements |= ISC_REQ_DATAGRAM;
  1299. }
  1300. else
  1301. {
  1302. ContextRequirements |= ISC_REQ_CONNECTION;
  1303. }
  1304. switch(ImpersonationType)
  1305. {
  1306. case RPC_C_IMP_LEVEL_IDENTIFY:
  1307. ContextRequirements |= ISC_REQ_IDENTIFY;
  1308. break;
  1309. case RPC_C_IMP_LEVEL_IMPERSONATE:
  1310. break;
  1311. case RPC_C_IMP_LEVEL_DELEGATE:
  1312. ContextRequirements |= ISC_REQ_DELEGATE;
  1313. break;
  1314. default:
  1315. ASSERT( ImpersonationType == RPC_C_IMP_LEVEL_ANONYMOUS
  1316. || ImpersonationType == RPC_C_IMP_LEVEL_IDENTIFY
  1317. || ImpersonationType == RPC_C_IMP_LEVEL_IMPERSONATE
  1318. || ImpersonationType == RPC_C_IMP_LEVEL_DELEGATE
  1319. || ImpersonationType == RPC_C_IMP_LEVEL_DEFAULT );
  1320. ContextRequirements |= ISC_REQ_IDENTIFY;
  1321. break;
  1322. }
  1323. if (Capabilities & RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH)
  1324. {
  1325. ContextRequirements |= ISC_REQ_MUTUAL_AUTH;
  1326. }
  1327. if (Credentials->AuthenticationService == RPC_C_AUTHN_GSS_SCHANNEL)
  1328. {
  1329. #if MANUAL_CERT_CHECK
  1330. ContextRequirements |= ISC_REQ_MANUAL_CRED_VALIDATION;
  1331. #endif
  1332. }
  1333. else
  1334. {
  1335. ContextRequirements |= ISC_REQ_USE_DCE_STYLE;
  1336. }
  1337. SecurityStatus = (*RpcSecurityInterface->InitializeSecurityContext)(
  1338. Credentials->InquireCredHandle(),
  1339. 0,
  1340. (SEC_TCHAR __SEC_FAR *) ServerPrincipalName,
  1341. ContextRequirements,
  1342. 0,
  1343. 0,
  1344. (fDatagram ? BufferDescriptor : 0),
  1345. 0,
  1346. &SecurityContext,
  1347. (fDatagram ? 0 : BufferDescriptor),
  1348. &ContextAttributes,
  1349. &TimeStamp
  1350. );
  1351. if ( ( SecurityStatus != SEC_E_OK )
  1352. && ( SecurityStatus != SEC_I_CONTINUE_NEEDED )
  1353. && ( SecurityStatus != SEC_I_COMPLETE_NEEDED )
  1354. && ( SecurityStatus != SEC_I_COMPLETE_AND_CONTINUE ) )
  1355. {
  1356. SetExtendedError(SecurityStatus);
  1357. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1358. SecurityStatus,
  1359. EEInfoDLInitializeFirstTime10,
  1360. AuthenticationService,
  1361. AuthenticationLevel,
  1362. ServerPrincipalName,
  1363. ContextRequirements);
  1364. if ((SecurityStatus == SEC_E_NO_CREDENTIALS)
  1365. || (SecurityStatus == SEC_E_LOGON_DENIED)
  1366. || (SecurityStatus == SEC_E_INVALID_TOKEN)
  1367. || (SecurityStatus == SEC_E_UNKNOWN_CREDENTIALS)
  1368. || (SecurityStatus == SEC_E_NO_KERB_KEY)
  1369. || (SecurityStatus == SEC_E_TIME_SKEW)
  1370. || (SecurityStatus == STATUS_AUTHENTICATION_FIREWALL_FAILED))
  1371. {
  1372. Status = RPC_S_ACCESS_DENIED;
  1373. }
  1374. else if ( SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS )
  1375. {
  1376. Status = ERROR_SHUTDOWN_IN_PROGRESS;
  1377. }
  1378. else if (SecurityStatus == SEC_E_SECPKG_NOT_FOUND)
  1379. {
  1380. Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  1381. }
  1382. else if ( SecurityStatus == SEC_E_INSUFFICIENT_MEMORY )
  1383. {
  1384. Status = RPC_S_OUT_OF_MEMORY;
  1385. }
  1386. else
  1387. {
  1388. #if DBG
  1389. PrintToDebugger("RPC: InitializeFirstTime Returned %lx\n", SecurityStatus);
  1390. #endif
  1391. //
  1392. // Originally the default for all providers was SEC_PKG_ERROR. This seems less
  1393. // helpful than ACCESS_DENIED, but we can't change it for NTLM and Kerberos because
  1394. // it might break old app code.
  1395. //
  1396. // SCHANNEL is new, so we can return ACCESS_DENIED.
  1397. //
  1398. if (AuthenticationService == RPC_C_AUTHN_GSS_SCHANNEL)
  1399. {
  1400. Status = RPC_S_ACCESS_DENIED;
  1401. }
  1402. else
  1403. {
  1404. Status = RPC_S_SEC_PKG_ERROR;
  1405. }
  1406. }
  1407. RpcpErrorAddRecord (EEInfoGCRuntime,
  1408. Status,
  1409. EEInfoDLInitializeFirstTime20,
  1410. SecurityStatus);
  1411. return Status;
  1412. }
  1413. RetrievedAuthType = 0;
  1414. DontForgetToDelete = 1;
  1415. if (NewAuthType)
  1416. {
  1417. ASSERT(*NewAuthType == this->AuthenticationService);
  1418. if (*NewAuthType == RPC_C_AUTHN_GSS_NEGOTIATE)
  1419. {
  1420. SecPkgContext_NegotiationInfo NegoInfo;
  1421. SECURITY_STATUS Status;
  1422. Status = (*RpcSecurityInterface->QueryContextAttributes)(
  1423. &SecurityContext,
  1424. SECPKG_ATTR_NEGOTIATION_INFO,
  1425. &NegoInfo);
  1426. if (Status == SEC_E_OK)
  1427. {
  1428. if (NegoInfo.NegotiationState == SECPKG_NEGOTIATION_COMPLETE)
  1429. {
  1430. RetrievedAuthType = (unsigned char) NegoInfo.PackageInfo->wRPCID;
  1431. }
  1432. (*RpcSecurityInterface->FreeContextBuffer)(NegoInfo.PackageInfo);
  1433. }
  1434. else
  1435. {
  1436. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1437. RPC_S_OUT_OF_MEMORY,
  1438. EEInfoDLInitializeFirstTime30,
  1439. Status,
  1440. (ULONG)AuthenticationService,
  1441. AuthenticationLevel,
  1442. (ULONG)ContextRequirements);
  1443. return RPC_S_OUT_OF_MEMORY;
  1444. }
  1445. }
  1446. }
  1447. Flags = ContextRequirements;
  1448. fDone = TRUE;
  1449. if ( SecurityStatus == SEC_I_CONTINUE_NEEDED )
  1450. {
  1451. if (!fDatagram)
  1452. {
  1453. fDone = FALSE;
  1454. }
  1455. Status = RPC_P_CONTINUE_NEEDED;
  1456. }
  1457. else if ( SecurityStatus == SEC_I_COMPLETE_NEEDED )
  1458. {
  1459. // Can't set the maximum lengths on a partly completed connection.
  1460. Status = RPC_P_COMPLETE_NEEDED;
  1461. }
  1462. else if ( SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE )
  1463. {
  1464. if (!fDatagram)
  1465. {
  1466. fDone = FALSE;
  1467. }
  1468. Status = RPC_P_COMPLETE_AND_CONTINUE;
  1469. }
  1470. else
  1471. {
  1472. Status = RPC_S_OK;
  1473. }
  1474. if (fDone)
  1475. {
  1476. fFullyConstructed = TRUE;
  1477. Status2 = SetMaximumLengths();
  1478. if (Status2 != RPC_S_OK)
  1479. {
  1480. return Status2;
  1481. }
  1482. }
  1483. if (RetrievedAuthType)
  1484. *NewAuthType = RetrievedAuthType;
  1485. return(Status);
  1486. }
  1487. RPC_STATUS
  1488. SECURITY_CONTEXT::InitializeThirdLeg (
  1489. IN SECURITY_CREDENTIALS * Credentials,
  1490. IN unsigned long DataRepresentation,
  1491. IN SECURITY_BUFFER_DESCRIPTOR PAPI * InputBufferDescriptor,
  1492. IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * OutputBufferDescriptor
  1493. )
  1494. /*++
  1495. Routine Description:
  1496. Arguments:
  1497. Return Value:
  1498. RPC_S_OK - Send the token to the server; everything worked fine so
  1499. far.
  1500. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to perform the
  1501. operation.
  1502. RPC_S_ACCESS_DENIED - Access is denied.
  1503. --*/
  1504. {
  1505. SECURITY_STATUS SecurityStatus;
  1506. TimeStamp TimeStamp;
  1507. RPC_STATUS Status;
  1508. ASSERT( (SecuritySupportLoaded != 0)
  1509. && (FailedToLoad == 0) );
  1510. SecurityStatus = (*RpcSecurityInterface->InitializeSecurityContext)(
  1511. Credentials->InquireCredHandle(),
  1512. &SecurityContext,
  1513. 0,
  1514. Flags,
  1515. 0,
  1516. DataRepresentation,
  1517. InputBufferDescriptor,
  1518. 0,
  1519. &SecurityContext,
  1520. OutputBufferDescriptor,
  1521. &ContextAttributes,
  1522. &TimeStamp
  1523. );
  1524. if ( ( SecurityStatus != SEC_E_OK )
  1525. && ( SecurityStatus != SEC_I_CONTINUE_NEEDED )
  1526. && ( SecurityStatus != SEC_I_COMPLETE_NEEDED )
  1527. && ( SecurityStatus != SEC_I_COMPLETE_AND_CONTINUE ) )
  1528. {
  1529. SetExtendedError(SecurityStatus);
  1530. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1531. SecurityStatus,
  1532. EEInfoDLInitializeThirdLeg10,
  1533. AuthenticationService,
  1534. AuthenticationLevel,
  1535. ContextAttributes);
  1536. if ( (SecurityStatus == SEC_E_NO_CREDENTIALS)
  1537. || (SecurityStatus == SEC_E_LOGON_DENIED)
  1538. || (SecurityStatus == SEC_E_INVALID_TOKEN)
  1539. || (SecurityStatus == SEC_E_UNKNOWN_CREDENTIALS)
  1540. || (SecurityStatus == SEC_E_NO_KERB_KEY)
  1541. || (SecurityStatus == SEC_E_TIME_SKEW)
  1542. || (SecurityStatus == STATUS_AUTHENTICATION_FIREWALL_FAILED))
  1543. {
  1544. Status = RPC_S_ACCESS_DENIED;
  1545. }
  1546. else if ( SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS )
  1547. {
  1548. Status = ERROR_SHUTDOWN_IN_PROGRESS;
  1549. }
  1550. else if (SecurityStatus == SEC_E_SECPKG_NOT_FOUND)
  1551. {
  1552. Status = RPC_S_UNKNOWN_AUTHN_SERVICE;
  1553. }
  1554. else if ( SecurityStatus == SEC_E_INSUFFICIENT_MEMORY )
  1555. {
  1556. Status = RPC_S_OUT_OF_MEMORY;
  1557. }
  1558. else
  1559. {
  1560. #if DBG
  1561. PrintToDebugger("RPC: InitializeThirdLeg Returned %lx\n",
  1562. SecurityStatus );
  1563. #endif
  1564. //
  1565. // Originally the default for all connection-oriented providers
  1566. // was SEC_PKG_ERROR. This seems less helpful than ACESS_DENIED,
  1567. // but we can't change it for NTLM and Kerberos because it might
  1568. // break old app code. SCHANNEL is new, so we can return ACCESS_DENIED.
  1569. //
  1570. // Datagram returns the bare error code.
  1571. //
  1572. if (AuthenticationService == RPC_C_AUTHN_GSS_SCHANNEL)
  1573. {
  1574. Status = RPC_S_ACCESS_DENIED;
  1575. }
  1576. else if (fDatagram)
  1577. {
  1578. // leave the error code alone
  1579. }
  1580. else
  1581. {
  1582. Status = RPC_S_SEC_PKG_ERROR;
  1583. }
  1584. }
  1585. RpcpErrorAddRecord (EEInfoGCRuntime,
  1586. Status,
  1587. EEInfoDLInitializeThirdLeg20,
  1588. SecurityStatus);
  1589. return Status;
  1590. }
  1591. if ( SecurityStatus == SEC_I_CONTINUE_NEEDED )
  1592. {
  1593. return(RPC_P_CONTINUE_NEEDED);
  1594. }
  1595. if ( SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE )
  1596. {
  1597. return(RPC_P_COMPLETE_AND_CONTINUE);
  1598. }
  1599. ASSERT(SecurityStatus == SEC_E_OK
  1600. || SecurityStatus == SEC_I_COMPLETE_NEEDED);
  1601. if ( (ImpersonationType == RPC_C_IMP_LEVEL_IDENTIFY) &&
  1602. (!(ContextAttributes & ISC_RET_IDENTIFY)) )
  1603. {
  1604. RpcpErrorAddRecord (EEInfoGCRuntime,
  1605. RPC_S_SEC_PKG_ERROR,
  1606. EEInfoDLInitializeThirdLeg30,
  1607. SEC_E_SECURITY_QOS_FAILED,
  1608. ImpersonationType,
  1609. ContextAttributes);
  1610. SetExtendedError(SEC_E_SECURITY_QOS_FAILED);
  1611. return (RPC_S_SEC_PKG_ERROR);
  1612. }
  1613. if ( (ImpersonationType == RPC_C_IMP_LEVEL_DELEGATE) &&
  1614. (!(ContextAttributes & ISC_RET_DELEGATE)) &&
  1615. (!(Capabilities & RPC_C_QOS_CAPABILITIES_IGNORE_DELEGATE_FAILURE)) &&
  1616. (!(IsIgnoreDelegationFailureSet())) )
  1617. {
  1618. RpcpErrorAddRecord (EEInfoGCRuntime,
  1619. RPC_S_SEC_PKG_ERROR,
  1620. EEInfoDLInitializeThirdLeg40,
  1621. SEC_E_SECURITY_QOS_FAILED,
  1622. ImpersonationType,
  1623. ContextAttributes,
  1624. Capabilities);
  1625. SetExtendedError(SEC_E_SECURITY_QOS_FAILED);
  1626. return (RPC_S_SEC_PKG_ERROR);
  1627. }
  1628. if ( (!(ContextAttributes & ISC_RET_MUTUAL_AUTH) )&&
  1629. (Capabilities & RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH) )
  1630. {
  1631. RpcpErrorAddRecord (EEInfoGCRuntime,
  1632. RPC_S_SEC_PKG_ERROR,
  1633. EEInfoDLInitializeThirdLeg50,
  1634. SEC_E_SECURITY_QOS_FAILED,
  1635. ImpersonationType,
  1636. ContextAttributes);
  1637. SetExtendedError(SEC_E_SECURITY_QOS_FAILED);
  1638. return (RPC_S_SEC_PKG_ERROR);
  1639. }
  1640. if ( SecurityStatus == SEC_I_COMPLETE_NEEDED )
  1641. {
  1642. fFullyConstructed = TRUE;
  1643. Status = SetMaximumLengths();
  1644. if (Status != RPC_S_OK)
  1645. return Status;
  1646. return(RPC_P_COMPLETE_NEEDED);
  1647. }
  1648. fFullyConstructed = TRUE;
  1649. Status = SetMaximumLengths();
  1650. if (Status != RPC_S_OK)
  1651. return Status;
  1652. if (AuthenticationService == RPC_C_AUTHN_GSS_SCHANNEL)
  1653. {
  1654. return VerifyCertificate();
  1655. }
  1656. return(RPC_S_OK);
  1657. }
  1658. RPC_STATUS
  1659. SECURITY_CONTEXT::GetWireIdForSnego(
  1660. OUT unsigned char *WireId
  1661. )
  1662. {
  1663. SecPkgContext_NegotiationInfo NegoInfo;
  1664. SECURITY_STATUS SecStatus;
  1665. RPC_STATUS RpcStatus = RPC_S_OK;
  1666. if (AuthenticationService != RPC_C_AUTHN_GSS_NEGOTIATE)
  1667. return RPC_S_INVALID_BINDING;
  1668. ASSERT(RpcSecurityInterface != NULL);
  1669. SecStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  1670. &SecurityContext,
  1671. SECPKG_ATTR_NEGOTIATION_INFO,
  1672. &NegoInfo);
  1673. if (SecStatus == SEC_E_OK)
  1674. {
  1675. if (NegoInfo.NegotiationState == SECPKG_NEGOTIATION_COMPLETE)
  1676. {
  1677. *WireId = (unsigned char) NegoInfo.PackageInfo->wRPCID;
  1678. }
  1679. else
  1680. RpcStatus = RPC_S_SEC_PKG_ERROR;
  1681. (*RpcSecurityInterface->FreeContextBuffer)(NegoInfo.PackageInfo);
  1682. }
  1683. else
  1684. {
  1685. SetExtendedError(SecStatus);
  1686. RpcStatus = RPC_S_OUT_OF_MEMORY;
  1687. }
  1688. return RpcStatus;
  1689. }
  1690. RPC_STATUS
  1691. SECURITY_CONTEXT::InqMarshalledTargetInfo (
  1692. OUT unsigned long *MarshalledTargetInfoLength,
  1693. OUT unsigned char **MarshalledTargetInfo
  1694. )
  1695. {
  1696. SecPkgContext_TargetInformation TargetInfo;
  1697. SECURITY_STATUS SecStatus;
  1698. RPC_STATUS RpcStatus = RPC_S_OK;
  1699. ASSERT(RpcSecurityInterface != NULL);
  1700. SecStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  1701. &SecurityContext,
  1702. SECPKG_ATTR_TARGET_INFORMATION,
  1703. &TargetInfo);
  1704. if (SecStatus == SEC_E_OK)
  1705. {
  1706. // Security will allocate the string containing MarshalledTargetInfo.
  1707. // We can just pass it on to user and have the user free it.
  1708. *MarshalledTargetInfoLength = TargetInfo.MarshalledTargetInfoLength;
  1709. *MarshalledTargetInfo = TargetInfo.MarshalledTargetInfo;
  1710. ASSERT(
  1711. ((*MarshalledTargetInfoLength == 0) && (*MarshalledTargetInfo == NULL)) ||
  1712. ((*MarshalledTargetInfoLength != 0) && (*MarshalledTargetInfo != NULL))
  1713. );
  1714. }
  1715. else
  1716. {
  1717. SetExtendedError(SecStatus);
  1718. RpcStatus = RPC_S_OUT_OF_MEMORY;
  1719. }
  1720. return RpcStatus;
  1721. }
  1722. RPC_STATUS
  1723. SECURITY_CONTEXT::AcceptFirstTime (
  1724. IN SECURITY_CREDENTIALS * NewCredentials,
  1725. IN SECURITY_BUFFER_DESCRIPTOR PAPI * InputBufferDescriptor,
  1726. IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * OutputBufferDescriptor,
  1727. IN unsigned long AuthenticationLevel,
  1728. IN unsigned long DataRepresentation,
  1729. IN unsigned long NewContextNeededFlag
  1730. )
  1731. /*++
  1732. Routine Description:
  1733. Arguments:
  1734. Return Value:
  1735. RPC_S_OK - Everything worked just fine.
  1736. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the
  1737. operation.
  1738. RPC_P_CONTINUE_NEEDED - Indicates that everything is ok, but that we
  1739. need to send the output token back to the client, and then wait
  1740. for a token back from the client.
  1741. RPC_P_COMPLETE_NEEDED - Indicates that everyting is ok, but that we
  1742. need to call CompleteAuthToken before sending the message.
  1743. RPC_P_COMPLETE_AND_CONTINUE - Needs both a complete and a continue.
  1744. RPC_S_ACCESS_DENIED - Access is denied.
  1745. --*/
  1746. {
  1747. SECURITY_STATUS SecurityStatus;
  1748. TimeStamp TimeStamp;
  1749. unsigned long ContextRequirements;
  1750. RPC_STATUS RpcStatus;
  1751. DWORD Status = 0;
  1752. ASSERT( (SecuritySupportLoaded != 0)
  1753. && (FailedToLoad == 0) );
  1754. if (Credentials)
  1755. {
  1756. Credentials->DereferenceCredentials();
  1757. }
  1758. Credentials = NewCredentials;
  1759. Credentials->ReferenceCredentials();
  1760. RpcSecurityInterface = Credentials->InquireProviderFunctionTable();
  1761. if (NewContextNeededFlag == 1)
  1762. {
  1763. DeleteSecurityContext();
  1764. }
  1765. switch ( AuthenticationLevel )
  1766. {
  1767. case RPC_C_AUTHN_LEVEL_CONNECT :
  1768. ContextRequirements = ASC_REQ_MUTUAL_AUTH;
  1769. break;
  1770. case RPC_C_AUTHN_LEVEL_PKT :
  1771. ContextRequirements = ASC_REQ_MUTUAL_AUTH
  1772. | ASC_REQ_REPLAY_DETECT;
  1773. break;
  1774. case RPC_C_AUTHN_LEVEL_PKT_INTEGRITY :
  1775. ContextRequirements = ASC_REQ_MUTUAL_AUTH
  1776. | ASC_REQ_REPLAY_DETECT | ASC_REQ_SEQUENCE_DETECT;
  1777. break;
  1778. case RPC_C_AUTHN_LEVEL_PKT_PRIVACY :
  1779. ContextRequirements = ASC_REQ_MUTUAL_AUTH
  1780. | ASC_REQ_REPLAY_DETECT | ASC_REQ_SEQUENCE_DETECT
  1781. | ASC_REQ_CONFIDENTIALITY;
  1782. break;
  1783. default :
  1784. ASSERT(AuthenticationLevel == RPC_C_AUTHN_LEVEL_CONNECT ||
  1785. AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT ||
  1786. AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY ||
  1787. AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY );
  1788. return RPC_S_INTERNAL_ERROR;
  1789. }
  1790. if (fDatagram)
  1791. {
  1792. ContextRequirements |= ASC_REQ_DATAGRAM;
  1793. }
  1794. else
  1795. {
  1796. ContextRequirements |= ASC_REQ_CONNECTION;
  1797. }
  1798. if (Credentials->AuthenticationService == RPC_C_AUTHN_WINNT ||
  1799. Credentials->AuthenticationService == RPC_C_AUTHN_DCE_PRIVATE ||
  1800. Credentials->AuthenticationService == RPC_C_AUTHN_GSS_KERBEROS ||
  1801. Credentials->AuthenticationService == RPC_C_AUTHN_GSS_NEGOTIATE)
  1802. {
  1803. ContextRequirements |= ASC_REQ_USE_DCE_STYLE | ASC_REQ_DELEGATE;
  1804. }
  1805. if (AuthenticationService == RPC_C_AUTHN_WINNT
  1806. || AuthenticationService == RPC_C_AUTHN_GSS_NEGOTIATE)
  1807. {
  1808. ContextRequirements |= ASC_REQ_ALLOW_NON_USER_LOGONS;
  1809. }
  1810. CallTestHook( TH_SECURITY_FN_ACCEPT1, this, &Status );
  1811. if (Status)
  1812. {
  1813. SetExtendedError(Status);
  1814. return Status;
  1815. }
  1816. SecurityStatus = (*RpcSecurityInterface->AcceptSecurityContext)(
  1817. Credentials->InquireCredHandle(), 0, InputBufferDescriptor,
  1818. ContextRequirements, DataRepresentation, &SecurityContext,
  1819. OutputBufferDescriptor, &ContextAttributes, &TimeStamp);
  1820. if ( ( SecurityStatus != SEC_E_OK )
  1821. && ( SecurityStatus != SEC_I_CONTINUE_NEEDED )
  1822. && ( SecurityStatus != SEC_I_COMPLETE_NEEDED )
  1823. && ( SecurityStatus != SEC_I_COMPLETE_AND_CONTINUE ) )
  1824. {
  1825. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1826. SecurityStatus,
  1827. EEInfoDLAcceptFirstTime10,
  1828. AuthenticationService,
  1829. AuthenticationLevel,
  1830. ContextRequirements);
  1831. SetExtendedError(SecurityStatus);
  1832. if ( (SecurityStatus == SEC_E_NO_CREDENTIALS)
  1833. || (SecurityStatus == SEC_E_LOGON_DENIED)
  1834. || (SecurityStatus == SEC_E_INVALID_TOKEN)
  1835. || (SecurityStatus == SEC_E_NO_AUTHENTICATING_AUTHORITY)
  1836. || (SecurityStatus == SEC_E_UNKNOWN_CREDENTIALS)
  1837. || (SecurityStatus == SEC_E_CONTEXT_EXPIRED)
  1838. || (SecurityStatus == SEC_E_TIME_SKEW)
  1839. || (SecurityStatus == STATUS_AUTHENTICATION_FIREWALL_FAILED))
  1840. {
  1841. RpcStatus = RPC_S_ACCESS_DENIED;
  1842. }
  1843. else if ( SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS )
  1844. {
  1845. RpcStatus = ERROR_SHUTDOWN_IN_PROGRESS;
  1846. }
  1847. else if (SecurityStatus == SEC_E_SECPKG_NOT_FOUND)
  1848. {
  1849. RpcStatus = RPC_S_UNKNOWN_AUTHN_SERVICE;
  1850. }
  1851. else
  1852. RpcStatus = RPC_S_OUT_OF_MEMORY;
  1853. }
  1854. else
  1855. {
  1856. RpcStatus = RPC_S_OK;
  1857. }
  1858. // We need to make sure that the context returned supports the required
  1859. // functionality.
  1860. // This needs to be done only for a completed context.
  1861. if (SecurityStatus == SEC_E_OK)
  1862. {
  1863. if (((ContextRequirements & ASC_REQ_REPLAY_DETECT) && !(ContextAttributes & ASC_RET_REPLAY_DETECT))
  1864. || ((ContextRequirements & ASC_REQ_SEQUENCE_DETECT) && !(ContextAttributes & ASC_RET_SEQUENCE_DETECT))
  1865. || ((ContextRequirements & ASC_REQ_CONFIDENTIALITY) && !(ContextAttributes & ASC_RET_CONFIDENTIALITY)))
  1866. {
  1867. RpcStatus = RPC_S_ACCESS_DENIED;
  1868. }
  1869. }
  1870. if (RpcStatus != RPC_S_OK)
  1871. {
  1872. RpcpErrorAddRecord (EEInfoGCRuntime,
  1873. RpcStatus,
  1874. EEInfoDLAcceptFirstTime20,
  1875. SecurityStatus);
  1876. return RpcStatus;
  1877. }
  1878. DontForgetToDelete = 1;
  1879. Flags = ContextRequirements;
  1880. if ( SecurityStatus == SEC_I_CONTINUE_NEEDED )
  1881. {
  1882. return(RPC_P_CONTINUE_NEEDED);
  1883. }
  1884. if ( SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE )
  1885. {
  1886. return(RPC_P_COMPLETE_AND_CONTINUE);
  1887. }
  1888. ASSERT((SecurityStatus == SEC_I_COMPLETE_NEEDED)
  1889. || (SecurityStatus == SEC_E_OK));
  1890. fFullyConstructed = TRUE;
  1891. RpcStatus = SetMaximumLengths();
  1892. if (RpcStatus != RPC_S_OK)
  1893. return RpcStatus;
  1894. Credentials->DereferenceCredentials();
  1895. Credentials = 0;
  1896. if ( SecurityStatus == SEC_I_COMPLETE_NEEDED )
  1897. return(RPC_P_COMPLETE_NEEDED);
  1898. else
  1899. return(RPC_S_OK);
  1900. }
  1901. RPC_STATUS
  1902. SECURITY_CONTEXT::AcceptThirdLeg (
  1903. IN unsigned long DataRepresentation,
  1904. IN SECURITY_BUFFER_DESCRIPTOR PAPI * BufferDescriptor,
  1905. OUT SECURITY_BUFFER_DESCRIPTOR PAPI * OutBufferDescriptor
  1906. )
  1907. /*++
  1908. Routine Description:
  1909. Arguments:
  1910. Return Value:
  1911. RPC_S_OK - Everything worked just fine.
  1912. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the
  1913. operation.
  1914. RPC_S_ACCESS_DENIED - Access is denied.
  1915. RPC_P_COMPLETE_NEEDED - Indicates that everyting is ok, but that we
  1916. need to call CompleteAuthToken before sending the message.
  1917. --*/
  1918. {
  1919. SECURITY_STATUS SecurityStatus;
  1920. TimeStamp TimeStamp;
  1921. RPC_STATUS RpcStatus;
  1922. // Set when AcceptSecurityContext returns a failure.
  1923. BOOL ASCReturnedFailure = FALSE;
  1924. // Set when AcceptSecurityContext suceeds but returns ContextAttributes
  1925. // which indicate that the resulting security context does not support
  1926. // the required security settings and is unusable.
  1927. BOOL ASCReturnedBadContextAttributes = FALSE;
  1928. ASSERT( (SecuritySupportLoaded != 0)
  1929. && (FailedToLoad == 0) );
  1930. SetLastError(0);
  1931. {
  1932. DWORD Status = 0;
  1933. CallTestHook( TH_SECURITY_FN_ACCEPT3, this, &Status );
  1934. if (Status)
  1935. {
  1936. FailedContext = Status;
  1937. SetExtendedError(Status);
  1938. return Status;
  1939. }
  1940. }
  1941. SecurityStatus = (*RpcSecurityInterface->AcceptSecurityContext)(
  1942. Credentials->InquireCredHandle(),
  1943. &SecurityContext,
  1944. BufferDescriptor,
  1945. Flags,
  1946. DataRepresentation,
  1947. &SecurityContext,
  1948. OutBufferDescriptor,
  1949. &ContextAttributes,
  1950. &TimeStamp
  1951. );
  1952. //
  1953. // If 3rd Leg Failed Bit is set, map all errors other than out of memory
  1954. // to SUCCESS
  1955. //
  1956. if (
  1957. (
  1958. ( SecurityStatus != SEC_E_OK )
  1959. && ( SecurityStatus != SEC_I_COMPLETE_NEEDED)
  1960. && ( SecurityStatus != SEC_I_CONTINUE_NEEDED)
  1961. && ( SecurityStatus != SEC_I_COMPLETE_AND_CONTINUE)
  1962. && ( SecurityStatus != SEC_E_INSUFFICIENT_MEMORY )
  1963. && ( ContextAttributes & ASC_RET_THIRD_LEG_FAILED )
  1964. )
  1965. ||
  1966. (
  1967. ( SecurityStatus == SEC_E_LOGON_DENIED )
  1968. || ( SecurityStatus == SEC_E_NO_CREDENTIALS )
  1969. || ( SecurityStatus == SEC_E_INVALID_TOKEN )
  1970. || ( SecurityStatus == SEC_E_UNKNOWN_CREDENTIALS )
  1971. || ( SecurityStatus == SEC_E_NO_AUTHENTICATING_AUTHORITY )
  1972. || ( SecurityStatus == SEC_E_TIME_SKEW )
  1973. || ( SecurityStatus == STATUS_AUTHENTICATION_FIREWALL_FAILED )
  1974. )
  1975. )
  1976. {
  1977. ASCReturnedFailure = TRUE;
  1978. }
  1979. // We need to make sure that the context returned supports the required
  1980. // functionality.
  1981. // This needs to be done only for a completed context.
  1982. if (SecurityStatus == SEC_E_OK)
  1983. {
  1984. if (((Flags & ASC_REQ_REPLAY_DETECT) && !(ContextAttributes & ASC_RET_REPLAY_DETECT))
  1985. || ((Flags & ASC_REQ_SEQUENCE_DETECT) && !(ContextAttributes & ASC_RET_SEQUENCE_DETECT))
  1986. || ((Flags & ASC_REQ_CONFIDENTIALITY) && !(ContextAttributes & ASC_RET_CONFIDENTIALITY)))
  1987. {
  1988. ASCReturnedBadContextAttributes = TRUE;
  1989. }
  1990. }
  1991. if (ASCReturnedFailure || ASCReturnedBadContextAttributes)
  1992. {
  1993. if (ASCReturnedFailure)
  1994. FailedContext = GetLastError();
  1995. else
  1996. FailedContext = RPC_S_ACCESS_DENIED;
  1997. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  1998. SecurityStatus,
  1999. EEInfoDLAcceptThirdLeg10,
  2000. AuthenticationService,
  2001. AuthenticationLevel,
  2002. FailedContext);
  2003. if (!fDatagram)
  2004. {
  2005. SecurityStatus = SEC_E_OK;
  2006. }
  2007. SetExtendedError(SecurityStatus);
  2008. if (ASCReturnedFailure)
  2009. {
  2010. if ( (FailedContext != ERROR_PASSWORD_MUST_CHANGE)
  2011. && (FailedContext != ERROR_PASSWORD_EXPIRED)
  2012. && (FailedContext != ERROR_ACCOUNT_DISABLED)
  2013. && (FailedContext != ERROR_INVALID_LOGON_HOURS) )
  2014. {
  2015. FailedContext = RPC_S_ACCESS_DENIED;
  2016. RpcpErrorAddRecord (EEInfoGCRuntime,
  2017. FailedContext,
  2018. EEInfoDLAcceptThirdLeg30);
  2019. }
  2020. }
  2021. ASSERT(FailedContextEEInfo == NULL);
  2022. FailedContextEEInfo = RpcpGetEEInfo();
  2023. RpcpClearEEInfo();
  2024. }
  2025. if ( ( SecurityStatus != SEC_E_OK )
  2026. && ( SecurityStatus != SEC_I_COMPLETE_NEEDED )
  2027. && ( SecurityStatus != SEC_I_CONTINUE_NEEDED )
  2028. && ( SecurityStatus != SEC_I_COMPLETE_AND_CONTINUE ) )
  2029. {
  2030. SetExtendedError(SecurityStatus);
  2031. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  2032. SecurityStatus,
  2033. EEInfoDLAcceptThirdLeg20,
  2034. AuthenticationService,
  2035. AuthenticationLevel);
  2036. if ( SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS )
  2037. {
  2038. RpcStatus = ERROR_SHUTDOWN_IN_PROGRESS;
  2039. }
  2040. else if ( (SecurityStatus == SEC_E_SECPKG_NOT_FOUND)
  2041. || (SecurityStatus == SEC_E_NO_CREDENTIALS)
  2042. || (SecurityStatus == SEC_E_LOGON_DENIED)
  2043. || (SecurityStatus == SEC_E_INVALID_TOKEN)
  2044. || (SecurityStatus == SEC_E_UNKNOWN_CREDENTIALS)
  2045. || (SecurityStatus == SEC_E_NO_AUTHENTICATING_AUTHORITY)
  2046. || (SecurityStatus == SEC_E_CONTEXT_EXPIRED)
  2047. || (SecurityStatus == SEC_E_TIME_SKEW)
  2048. || (SecurityStatus == STATUS_AUTHENTICATION_FIREWALL_FAILED))
  2049. {
  2050. RpcStatus = RPC_S_ACCESS_DENIED;
  2051. }
  2052. else
  2053. {
  2054. ASSERT( SecurityStatus == SEC_E_INSUFFICIENT_MEMORY );
  2055. RpcStatus = RPC_S_OUT_OF_MEMORY;
  2056. }
  2057. RpcpErrorAddRecord (EEInfoGCRuntime,
  2058. RpcStatus,
  2059. EEInfoDLAcceptThirdLeg40,
  2060. SecurityStatus);
  2061. return RpcStatus;
  2062. }
  2063. if ( SecurityStatus == SEC_I_CONTINUE_NEEDED )
  2064. {
  2065. return(RPC_P_CONTINUE_NEEDED);
  2066. }
  2067. if ( SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE )
  2068. {
  2069. return(RPC_P_COMPLETE_AND_CONTINUE);
  2070. }
  2071. ASSERT ( (SecurityStatus == SEC_I_COMPLETE_NEEDED)
  2072. || (SecurityStatus == SEC_E_OK));
  2073. fFullyConstructed = TRUE;
  2074. RpcStatus = SetMaximumLengths();
  2075. if (RpcStatus)
  2076. {
  2077. FailedContext = RpcStatus;
  2078. ASSERT(FailedContextEEInfo == NULL);
  2079. FailedContextEEInfo = RpcpGetEEInfo();
  2080. RpcpClearEEInfo();
  2081. //
  2082. // We don't want to block third leg - mimic success
  2083. // Failed context has already been set
  2084. //
  2085. MaxSignatureLength = 256;
  2086. MaxHeaderLength = 256;
  2087. cbBlockSize = 64;
  2088. }
  2089. if (SecurityStatus == SEC_I_COMPLETE_NEEDED)
  2090. return(RPC_P_COMPLETE_NEEDED);
  2091. else
  2092. return RPC_S_OK;
  2093. }
  2094. unsigned long
  2095. SECURITY_CONTEXT::InquireAuthorizationService (
  2096. )
  2097. /*++
  2098. Return Value:
  2099. The authorization service for this security context will be returned.
  2100. --*/
  2101. {
  2102. SecPkgContext_DceInfo DceInfo;
  2103. SECURITY_STATUS SecurityStatus;
  2104. SecurityStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  2105. &SecurityContext, SECPKG_ATTR_DCE_INFO, &DceInfo);
  2106. ASSERT( SecurityStatus == SEC_E_OK );
  2107. return(DceInfo.AuthzSvc);
  2108. }
  2109. RPC_AUTHZ_HANDLE
  2110. SECURITY_CONTEXT::InquirePrivileges (
  2111. )
  2112. /*++
  2113. Return Value:
  2114. The privileges of the client at the other end of this security context
  2115. will be returned.
  2116. --*/
  2117. {
  2118. SecPkgContext_DceInfo DceInfo;
  2119. SECURITY_STATUS SecurityStatus;
  2120. SecurityStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  2121. &SecurityContext, SECPKG_ATTR_DCE_INFO, &DceInfo);
  2122. ASSERT( SecurityStatus == SEC_E_OK );
  2123. return(DceInfo.pPac);
  2124. }
  2125. RPC_STATUS
  2126. SECURITY_CONTEXT::GetDceInfo (
  2127. RPC_AUTHZ_HANDLE __RPC_FAR * PacHandle,
  2128. unsigned long __RPC_FAR * AuthzSvc
  2129. )
  2130. /*++
  2131. Return Value:
  2132. The privileges of the client at the other end of this security context
  2133. will be returned.
  2134. --*/
  2135. {
  2136. SecPkgContext_DceInfo DceInfo;
  2137. SECURITY_STATUS SecurityStatus;
  2138. *PacHandle = 0;
  2139. *AuthzSvc = 0;
  2140. SecurityStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  2141. &SecurityContext, SECPKG_ATTR_DCE_INFO, &DceInfo);
  2142. ASSERT( (SecurityStatus == SEC_E_OK)
  2143. || (SecurityStatus == SEC_E_UNSUPPORTED_FUNCTION)
  2144. || (SecurityStatus == SEC_E_INVALID_HANDLE));
  2145. if (SecurityStatus == SEC_E_OK)
  2146. {
  2147. *PacHandle = DceInfo.pPac;
  2148. *AuthzSvc = DceInfo.AuthzSvc;
  2149. return RPC_S_OK;
  2150. }
  2151. if (AuthenticationService == RPC_C_AUTHN_GSS_SCHANNEL)
  2152. {
  2153. SecurityStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  2154. &SecurityContext, SECPKG_ATTR_REMOTE_CERT_CONTEXT, PacHandle);
  2155. if (SecurityStatus != SEC_E_OK)
  2156. {
  2157. *PacHandle = 0;
  2158. }
  2159. }
  2160. if (SecurityStatus != SEC_E_OK)
  2161. {
  2162. return RPC_S_SEC_PKG_ERROR;
  2163. }
  2164. return RPC_S_OK;
  2165. }
  2166. void
  2167. SECURITY_CONTEXT::DeleteSecurityContext (
  2168. void
  2169. )
  2170. /*++
  2171. Routine Description:
  2172. If there is a valid security context, we need to delete it.
  2173. --*/
  2174. {
  2175. SECURITY_STATUS SecurityStatus;
  2176. unsigned int nRetries = 0;
  2177. if ( DontForgetToDelete != 0 )
  2178. {
  2179. if (AuthzClientContext)
  2180. {
  2181. AuthzFreeContextFn(AuthzClientContext);
  2182. AuthzClientContext = NULL;
  2183. }
  2184. // SEC_E_INSUFFICIENT_MEMORY may be returned under extremely low
  2185. // memory conditions. We will do the following:
  2186. // - Retry 10 times to delete the security context.
  2187. // - Raise a flag in the process that we have leaked one or more security contexts.
  2188. do
  2189. {
  2190. SecurityStatus = (*RpcSecurityInterface->DeleteSecurityContext)(
  2191. &SecurityContext );
  2192. nRetries++;
  2193. }
  2194. while (SecurityStatus == SEC_E_INSUFFICIENT_MEMORY && nRetries < 10);
  2195. if (SecurityStatus == SEC_E_INSUFFICIENT_MEMORY)
  2196. {
  2197. nSecurityStructuresLeaked++;
  2198. }
  2199. // when the process shutdowns, the security system may return SEC_E_SECPKG_NOT_FOUND
  2200. // since it is uninitialized. This is the only time when this error will be
  2201. // returned, so it is safe to ignore.
  2202. if (SecurityStatus == SEC_E_SECPKG_NOT_FOUND)
  2203. SecurityStatus = SEC_E_OK;
  2204. #if DBG
  2205. if ((SecurityStatus != SEC_E_OK) && (SecurityStatus != SEC_E_SHUTDOWN_IN_PROGRESS))
  2206. {
  2207. PrintToDebugger("DeleteSecurityContext(0x%x) Returned [%lx]\n",
  2208. &SecurityContext,
  2209. SecurityStatus);
  2210. }
  2211. if (SecurityStatus == SEC_E_INSUFFICIENT_MEMORY)
  2212. {
  2213. PrintToDebugger("SecurityContext(0x%x) leaked\n",
  2214. &SecurityContext);
  2215. }
  2216. #endif
  2217. ASSERT( SecurityStatus == SEC_E_OK ||
  2218. SecurityStatus == SEC_E_SHUTDOWN_IN_PROGRESS ||
  2219. SecurityStatus == SEC_E_INSUFFICIENT_MEMORY);
  2220. DontForgetToDelete = 0;
  2221. }
  2222. if (FailedContextEEInfo)
  2223. {
  2224. FreeEEInfoChain(FailedContextEEInfo);
  2225. FailedContextEEInfo = NULL;
  2226. }
  2227. }
  2228. RPC_STATUS
  2229. SECURITY_CONTEXT::CheckForFailedThirdLeg (
  2230. void
  2231. )
  2232. /*++
  2233. Routine Description:
  2234. If the third leg has failed, we will return the error code
  2235. and restore the eeinfo.
  2236. --*/
  2237. {
  2238. ASSERT( ( SecuritySupportLoaded != 0 )
  2239. && ( FailedToLoad == 0 ) );
  2240. if (FailedContext != 0)
  2241. {
  2242. if (FailedContextEEInfo)
  2243. {
  2244. RpcpSetEEInfo(FailedContextEEInfo);
  2245. FailedContextEEInfo = NULL;
  2246. }
  2247. return (RPC_S_ACCESS_DENIED);
  2248. }
  2249. return RPC_S_OK;
  2250. }
  2251. void
  2252. SECURITY_CONTEXT::DeletePac(
  2253. void __RPC_FAR * PacHandle
  2254. )
  2255. /*++
  2256. Return Value:
  2257. --*/
  2258. {
  2259. if (AuthenticationService == RPC_C_AUTHN_GSS_SCHANNEL)
  2260. {
  2261. if (!LoadCrypt32Imports())
  2262. {
  2263. return;
  2264. }
  2265. CertFreeCertificateContext( (PCERT_CONTEXT) PacHandle );
  2266. }
  2267. else
  2268. {
  2269. (*RpcSecurityInterface->FreeContextBuffer)( PacHandle );
  2270. }
  2271. }
  2272. RPC_STATUS
  2273. SECURITY_CONTEXT::ImpersonateClient (
  2274. )
  2275. /*++
  2276. Routine Description:
  2277. The server thread calling this routine will impersonate the client at the
  2278. other end of this security context.
  2279. Return Value:
  2280. RPC_S_OK - The impersonation successfully occured.
  2281. RPC_S_NO_CONTEXT_AVAILABLE - There is no security context available to
  2282. be impersonated.
  2283. --*/
  2284. {
  2285. SECURITY_STATUS SecurityStatus;
  2286. ASSERT( ( SecuritySupportLoaded != 0 )
  2287. && ( FailedToLoad == 0 ) );
  2288. if (FailedContext != 0)
  2289. {
  2290. if (FailedContextEEInfo)
  2291. {
  2292. RpcpSetEEInfo(FailedContextEEInfo);
  2293. FailedContextEEInfo = NULL;
  2294. }
  2295. return (RPC_S_ACCESS_DENIED);
  2296. }
  2297. ASSERT( FullyConstructed() );
  2298. SecurityStatus = (*RpcSecurityInterface->ImpersonateSecurityContext)(
  2299. &SecurityContext);
  2300. if ( SecurityStatus != SEC_E_OK )
  2301. {
  2302. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  2303. RPC_S_NO_CONTEXT_AVAILABLE,
  2304. EEInfoDLImpersonateClient10,
  2305. SecurityStatus,
  2306. AuthenticationService,
  2307. AuthenticationLevel);
  2308. ASSERT( SecurityStatus == SEC_E_NO_IMPERSONATION );
  2309. return(RPC_S_NO_CONTEXT_AVAILABLE);
  2310. }
  2311. return(RPC_S_OK);
  2312. }
  2313. void
  2314. SECURITY_CONTEXT::RevertToSelf (
  2315. )
  2316. /*++
  2317. Routine Description:
  2318. The server thread calling this routine will stop impersonating. If the
  2319. thread is not impersonating, then this is a noop.
  2320. --*/
  2321. {
  2322. SECURITY_STATUS SecurityStatus;
  2323. ASSERT( ( SecuritySupportLoaded != 0 )
  2324. && ( FailedToLoad == 0 ) );
  2325. SecurityStatus = (*RpcSecurityInterface->RevertSecurityContext)(
  2326. &SecurityContext);
  2327. ASSERT( SecurityStatus == SEC_E_OK );
  2328. }
  2329. RPC_STATUS
  2330. SECURITY_CONTEXT::GetAccessToken (
  2331. OUT HANDLE *ImpersonationToken,
  2332. OUT BOOL *fNeedToCloseToken
  2333. )
  2334. /*++
  2335. Routine Description:
  2336. Gets the access token maintained by the security provider.
  2337. Arguments:
  2338. ImpersonationToken - contains the impersonation token on success
  2339. fNeedToCloseToken - true if the resulting token needs closing.
  2340. False otherwise. Some security providers support handing off
  2341. of the token itself (faster). Some don't. All support handing
  2342. off a copy of the token. Depending on what security provider
  2343. we have, we'll get the token, and set this variable. This
  2344. parameter is undefined in case of failure.
  2345. Return Value:
  2346. RPC_S_OK on success, or RPC_S_* on failure. Supports EEInfo.
  2347. --*/
  2348. {
  2349. SECURITY_STATUS SecurityStatus;
  2350. HANDLE Token;
  2351. ASSERT( ( SecuritySupportLoaded != 0 )
  2352. && ( FailedToLoad == 0 ) );
  2353. ASSERT( FullyConstructed() );
  2354. SecurityStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  2355. &SecurityContext,
  2356. SECPKG_ATTR_ACCESS_TOKEN,
  2357. &Token);
  2358. if ( (SecurityStatus != SEC_E_OK)
  2359. && (SecurityStatus != SEC_E_UNSUPPORTED_FUNCTION) )
  2360. {
  2361. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  2362. RPC_S_NO_CONTEXT_AVAILABLE,
  2363. EEInfoDLSECURITY_CONTEXT__GetAccessToken10,
  2364. SecurityStatus,
  2365. AuthenticationService,
  2366. AuthenticationLevel);
  2367. ASSERT( 0 );
  2368. return(RPC_S_NO_CONTEXT_AVAILABLE);
  2369. }
  2370. if (SecurityStatus != SEC_E_OK)
  2371. {
  2372. ASSERT(SecurityStatus == SEC_E_UNSUPPORTED_FUNCTION);
  2373. // the security provider does not provide quick retrieval
  2374. // of token - go the long way
  2375. SecurityStatus = (*RpcSecurityInterface->QuerySecurityContextToken)(
  2376. &SecurityContext, &Token);
  2377. if (SecurityStatus != SEC_E_OK)
  2378. {
  2379. RpcpErrorAddRecord (EEInfoGCSecurityProvider,
  2380. RPC_S_NO_CONTEXT_AVAILABLE,
  2381. EEInfoDLSECURITY_CONTEXT__GetAccessToken20,
  2382. SecurityStatus,
  2383. AuthenticationService,
  2384. AuthenticationLevel);
  2385. ASSERT( SecurityStatus == SEC_E_NO_IMPERSONATION );
  2386. return(RPC_S_NO_CONTEXT_AVAILABLE);
  2387. }
  2388. *fNeedToCloseToken = TRUE;
  2389. }
  2390. else
  2391. {
  2392. *fNeedToCloseToken = FALSE;
  2393. }
  2394. *ImpersonationToken = Token;
  2395. return RPC_S_OK;
  2396. }
  2397. PACKAGE_LEG_COUNT
  2398. GetPackageLegCount(
  2399. DWORD id
  2400. )
  2401. /*++
  2402. Routine Description:
  2403. This fn determines whether the given security package is a 3- or 4-leg
  2404. protocol. The relevance of this information is described in
  2405. ReadPackageLegInfo(). This fn. first searches the hardcoded entries in
  2406. PredefinedPackageLegInfo[], and if the package is not found it turns to the
  2407. registry information stored in FourLeggedPackages[].
  2408. Return Values:
  2409. LegsUnknown = the fn cannot give a reliable answer
  2410. ThreeLegs = this is a 3-leg protocol
  2411. EvenNumberOfLegs = this is not a 3-leg protocol
  2412. --*/
  2413. {
  2414. int i;
  2415. if ( InsureSecuritySupportLoaded() != RPC_S_OK )
  2416. {
  2417. return LegsUnknown;
  2418. }
  2419. for (i=0; PredefinedPackageLegInfo[i].Package != 0; ++i)
  2420. {
  2421. if (PredefinedPackageLegInfo[i].Package == id)
  2422. {
  2423. return PredefinedPackageLegInfo[i].Legs;
  2424. }
  2425. }
  2426. CLAIM_MUTEX Lock( *SecurityCritSect );
  2427. if (!FourLeggedPackages)
  2428. {
  2429. if (!ReadPackageLegInfo())
  2430. {
  2431. return LegsUnknown;
  2432. }
  2433. }
  2434. ASSERT(FourLeggedPackages);
  2435. for (i=0; FourLeggedPackages[i] != 0; ++i)
  2436. {
  2437. if (FourLeggedPackages[i] == id)
  2438. {
  2439. return EvenNumberOfLegs;
  2440. }
  2441. }
  2442. return ThreeLegs;
  2443. }
  2444. DWORD
  2445. SECURITY_CONTEXT::VerifyCertificate()
  2446. {
  2447. DWORD SecurityStatus = 0;
  2448. //
  2449. // Compare the name on the certificate against the expected principal name.
  2450. //
  2451. if (ServerPrincipalName)
  2452. {
  2453. //
  2454. // Get a copy of the raw certificate.
  2455. //
  2456. if (!LoadCrypt32Imports())
  2457. {
  2458. return GetLastError();
  2459. }
  2460. PCERT_CONTEXT ClientContext;
  2461. SecurityStatus = (*RpcSecurityInterface->QueryContextAttributes)(
  2462. &SecurityContext,
  2463. SECPKG_ATTR_REMOTE_CERT_CONTEXT,
  2464. &ClientContext
  2465. );
  2466. if (SecurityStatus)
  2467. {
  2468. RpcpErrorAddRecord ( EEInfoGCSecurityProvider,
  2469. RPC_S_OUT_OF_MEMORY,
  2470. EEInfoDLInitializeThirdLeg60,
  2471. SecurityStatus );
  2472. ASSERT( SecurityStatus == SEC_E_INSUFFICIENT_MEMORY );
  2473. return SecurityStatus;
  2474. }
  2475. SecurityStatus = RpcCertMatchPrincipalName( ClientContext, ServerPrincipalName );
  2476. switch (SecurityStatus)
  2477. {
  2478. case 0:
  2479. case ERROR_NOT_ENOUGH_MEMORY:
  2480. break;
  2481. default:
  2482. //
  2483. // we are supposed to have verified the princ name earlier.
  2484. //
  2485. ASSERT( SecurityStatus != ERROR_INVALID_PARAMETER );
  2486. SetExtendedError(SecurityStatus);
  2487. SecurityStatus = RPC_S_ACCESS_DENIED;
  2488. break;
  2489. }
  2490. CertFreeCertificateContext( ClientContext );
  2491. }
  2492. return SecurityStatus;
  2493. }