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.

700 lines
19 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT Security
  4. // Copyright (C) Microsoft Corporation, 1997 - 1999
  5. //
  6. // File: defce.cpp
  7. //
  8. // Contents: Default Chain Engine Manager
  9. //
  10. // History: 21-Apr-98 kirtd Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <global.hxx>
  14. //+---------------------------------------------------------------------------
  15. //
  16. // Member: CDefaultChainEngineMgr::CDefaultChainEngineMgr, public
  17. //
  18. // Synopsis: Constructor
  19. //
  20. //----------------------------------------------------------------------------
  21. CDefaultChainEngineMgr::CDefaultChainEngineMgr ()
  22. {
  23. }
  24. //+---------------------------------------------------------------------------
  25. //
  26. // Member: CDefaultChainEngineMgr::~CDefaultChainEngineMgr, public
  27. //
  28. // Synopsis: Destructor
  29. //
  30. //----------------------------------------------------------------------------
  31. CDefaultChainEngineMgr::~CDefaultChainEngineMgr ()
  32. {
  33. }
  34. //+---------------------------------------------------------------------------
  35. //
  36. // Member: CDefaultChainEngineMgr::Initialize, public
  37. //
  38. // Synopsis: initialization routine
  39. //
  40. //----------------------------------------------------------------------------
  41. BOOL
  42. CDefaultChainEngineMgr::Initialize ()
  43. {
  44. LRU_CACHE_CONFIG Config;
  45. if (!Pki_InitializeCriticalSection( &m_Lock ))
  46. {
  47. return FALSE;
  48. }
  49. m_hLocalMachineEngine = NULL;
  50. m_hProcessUserEngine = NULL;
  51. m_hImpersonationCache = NULL;
  52. memset( &Config, 0, sizeof( Config ) );
  53. Config.dwFlags = LRU_CACHE_NO_SERIALIZE;
  54. Config.cBuckets = DEFAULT_IMPERSONATION_CACHE_BUCKETS;
  55. Config.MaxEntries = MAX_IMPERSONATION_CACHE_ENTRIES;
  56. Config.pfnHash = DefaultChainEngineMgrHashTokenIdentifier;
  57. Config.pfnOnRemoval = DefaultChainEngineMgrOnImpersonationEngineRemoval;
  58. if (!I_CryptCreateLruCache( &Config, &m_hImpersonationCache ) )
  59. {
  60. DeleteCriticalSection( &m_Lock );
  61. return FALSE;
  62. }
  63. return TRUE;
  64. }
  65. //+---------------------------------------------------------------------------
  66. //
  67. // Member: CDefaultChainEngineMgr::Uninitialize, public
  68. //
  69. // Synopsis: uninitialization routine
  70. //
  71. //----------------------------------------------------------------------------
  72. VOID
  73. CDefaultChainEngineMgr::Uninitialize ()
  74. {
  75. if ( m_hLocalMachineEngine != NULL )
  76. {
  77. CertFreeCertificateChainEngine( m_hLocalMachineEngine );
  78. }
  79. if ( m_hProcessUserEngine != NULL )
  80. {
  81. CertFreeCertificateChainEngine( m_hProcessUserEngine );
  82. }
  83. if ( m_hImpersonationCache != NULL )
  84. {
  85. I_CryptFreeLruCache( m_hImpersonationCache, 0, NULL );
  86. }
  87. DeleteCriticalSection( &m_Lock );
  88. }
  89. //+---------------------------------------------------------------------------
  90. //
  91. // Member: CDefaultChainEngineMgr::GetDefaultEngine, public
  92. //
  93. // Synopsis: get the default engine
  94. //
  95. //----------------------------------------------------------------------------
  96. BOOL
  97. CDefaultChainEngineMgr::GetDefaultEngine (
  98. IN HCERTCHAINENGINE hDefaultHandle,
  99. OUT HCERTCHAINENGINE* phDefaultEngine
  100. )
  101. {
  102. assert( ( hDefaultHandle == HCCE_LOCAL_MACHINE ) ||
  103. ( hDefaultHandle == HCCE_CURRENT_USER ) );
  104. if ( hDefaultHandle == HCCE_LOCAL_MACHINE )
  105. {
  106. return( GetDefaultLocalMachineEngine( phDefaultEngine ) );
  107. }
  108. else if ( hDefaultHandle == HCCE_CURRENT_USER )
  109. {
  110. return( GetDefaultCurrentUserEngine( phDefaultEngine ) );
  111. }
  112. SetLastError( (DWORD) E_INVALIDARG );
  113. return( FALSE );
  114. }
  115. //+---------------------------------------------------------------------------
  116. //
  117. // Member: CDefaultChainEngineMgr::GetDefaultLocalMachineEngine, public
  118. //
  119. // Synopsis: get the default local machine chain engine
  120. //
  121. //----------------------------------------------------------------------------
  122. BOOL
  123. CDefaultChainEngineMgr::GetDefaultLocalMachineEngine (
  124. OUT HCERTCHAINENGINE* phDefaultEngine
  125. )
  126. {
  127. BOOL fResult = TRUE;
  128. EnterCriticalSection( &m_Lock );
  129. if ( m_hLocalMachineEngine == NULL )
  130. {
  131. HCERTCHAINENGINE hEngine = NULL;
  132. CERT_CHAIN_ENGINE_CONFIG Config;
  133. LeaveCriticalSection( &m_Lock );
  134. memset( &Config, 0, sizeof( Config ) );
  135. Config.cbSize = sizeof( Config );
  136. Config.dwFlags = CERT_CHAIN_USE_LOCAL_MACHINE_STORE;
  137. Config.dwFlags |= CERT_CHAIN_ENABLE_CACHE_AUTO_UPDATE |
  138. CERT_CHAIN_ENABLE_SHARE_STORE;
  139. fResult = CertCreateCertificateChainEngine(
  140. &Config,
  141. &hEngine
  142. );
  143. EnterCriticalSection( &m_Lock );
  144. if ( ( fResult == TRUE ) && ( m_hLocalMachineEngine == NULL ) )
  145. {
  146. m_hLocalMachineEngine = hEngine;
  147. hEngine = NULL;
  148. }
  149. if ( hEngine != NULL )
  150. {
  151. ( (PCCERTCHAINENGINE)hEngine )->Release();
  152. }
  153. }
  154. if ( fResult == TRUE )
  155. {
  156. ( (PCCERTCHAINENGINE)m_hLocalMachineEngine )->AddRef();
  157. *phDefaultEngine = m_hLocalMachineEngine;
  158. }
  159. LeaveCriticalSection( &m_Lock );
  160. return( fResult );
  161. }
  162. //+---------------------------------------------------------------------------
  163. //
  164. // Member: CDefaultChainEngineMgr::GetDefaultCurrentUserEngine, public
  165. //
  166. // Synopsis: get the default current user chain engine
  167. //
  168. //----------------------------------------------------------------------------
  169. BOOL
  170. CDefaultChainEngineMgr::GetDefaultCurrentUserEngine (
  171. OUT HCERTCHAINENGINE* phDefaultEngine
  172. )
  173. {
  174. BOOL fResult = TRUE;
  175. HANDLE hUserToken;
  176. EnterCriticalSection( &m_Lock );
  177. if ( IsImpersonatingUser( &hUserToken ) == FALSE )
  178. {
  179. if ( GetLastError() != ERROR_NO_TOKEN )
  180. {
  181. LeaveCriticalSection( &m_Lock );
  182. return( FALSE );
  183. }
  184. if ( m_hProcessUserEngine == NULL )
  185. {
  186. HCERTCHAINENGINE hEngine = NULL;
  187. CERT_CHAIN_ENGINE_CONFIG Config;
  188. LeaveCriticalSection( &m_Lock );
  189. memset( &Config, 0, sizeof( Config ) );
  190. Config.cbSize = sizeof( Config );
  191. Config.dwFlags |= CERT_CHAIN_ENABLE_CACHE_AUTO_UPDATE |
  192. CERT_CHAIN_ENABLE_SHARE_STORE;
  193. fResult = CertCreateCertificateChainEngine(
  194. &Config,
  195. &hEngine
  196. );
  197. EnterCriticalSection( &m_Lock );
  198. if ( ( fResult == TRUE ) && ( m_hProcessUserEngine == NULL ) )
  199. {
  200. m_hProcessUserEngine = hEngine;
  201. hEngine = NULL;
  202. }
  203. if ( hEngine != NULL )
  204. {
  205. ( (PCCERTCHAINENGINE)hEngine )->Release();
  206. }
  207. }
  208. if ( fResult == TRUE )
  209. {
  210. ( (PCCERTCHAINENGINE)m_hProcessUserEngine )->AddRef();
  211. *phDefaultEngine = m_hProcessUserEngine;
  212. }
  213. }
  214. else
  215. {
  216. fResult = GetDefaultCurrentImpersonatedUserEngine(
  217. hUserToken,
  218. phDefaultEngine
  219. );
  220. CloseHandle( hUserToken );
  221. }
  222. LeaveCriticalSection( &m_Lock );
  223. return( fResult );
  224. }
  225. //+---------------------------------------------------------------------------
  226. //
  227. // Member: CDefaultChainEngineMgr::FlushDefaultEngine, public
  228. //
  229. // Synopsis: flush default engine
  230. //
  231. //----------------------------------------------------------------------------
  232. VOID
  233. CDefaultChainEngineMgr::FlushDefaultEngine (IN HCERTCHAINENGINE hDefaultHandle)
  234. {
  235. HCERTCHAINENGINE hEngine = NULL;
  236. HLRUCACHE hCacheToFree = NULL;
  237. HLRUCACHE hCache = NULL;
  238. LRU_CACHE_CONFIG Config;
  239. EnterCriticalSection( &m_Lock );
  240. if ( hDefaultHandle == HCCE_CURRENT_USER )
  241. {
  242. hEngine = m_hProcessUserEngine;
  243. m_hProcessUserEngine = NULL;
  244. assert( m_hImpersonationCache != NULL );
  245. memset( &Config, 0, sizeof( Config ) );
  246. Config.dwFlags = LRU_CACHE_NO_SERIALIZE;
  247. Config.cBuckets = DEFAULT_IMPERSONATION_CACHE_BUCKETS;
  248. Config.MaxEntries = MAX_IMPERSONATION_CACHE_ENTRIES;
  249. Config.pfnHash = DefaultChainEngineMgrHashTokenIdentifier;
  250. Config.pfnOnRemoval = DefaultChainEngineMgrOnImpersonationEngineRemoval;
  251. if ( I_CryptCreateLruCache( &Config, &hCache ) == TRUE )
  252. {
  253. hCacheToFree = m_hImpersonationCache;
  254. m_hImpersonationCache = hCache;
  255. }
  256. else
  257. {
  258. I_CryptFlushLruCache( m_hImpersonationCache, 0, NULL );
  259. }
  260. assert( m_hImpersonationCache != NULL );
  261. }
  262. else if ( hDefaultHandle == HCCE_LOCAL_MACHINE )
  263. {
  264. hEngine = m_hLocalMachineEngine;
  265. m_hLocalMachineEngine = NULL;
  266. }
  267. LeaveCriticalSection( &m_Lock );
  268. if ( hEngine != NULL )
  269. {
  270. CertFreeCertificateChainEngine( hEngine );
  271. }
  272. if ( hCacheToFree != NULL )
  273. {
  274. I_CryptFreeLruCache( hCacheToFree, 0, NULL );
  275. }
  276. }
  277. //+---------------------------------------------------------------------------
  278. //
  279. // Member: CDefaultChainEngineMgr::GetDefaultCurrentImpersonatedUserEngine
  280. //
  281. // Synopsis: get current impersonated user chain engine
  282. //
  283. //----------------------------------------------------------------------------
  284. BOOL
  285. CDefaultChainEngineMgr::GetDefaultCurrentImpersonatedUserEngine (
  286. IN HANDLE hUserToken,
  287. OUT HCERTCHAINENGINE* phDefaultEngine
  288. )
  289. {
  290. BOOL fResult;
  291. CRYPT_DATA_BLOB TokenId;
  292. PCIMPERSONATIONENGINE pEngine = NULL;
  293. HCERTCHAINENGINE hChainEngine = NULL;
  294. fResult = GetTokenId( hUserToken, &TokenId );
  295. if ( fResult == TRUE )
  296. {
  297. if ( FindImpersonationEngine( &TokenId, &pEngine ) == FALSE )
  298. {
  299. CERT_CHAIN_ENGINE_CONFIG Config;
  300. LeaveCriticalSection( &m_Lock );
  301. memset( &Config, 0, sizeof( Config ) );
  302. Config.cbSize = sizeof( Config );
  303. Config.dwFlags |= CERT_CHAIN_ENABLE_CACHE_AUTO_UPDATE |
  304. CERT_CHAIN_ENABLE_SHARE_STORE;
  305. fResult = CertCreateCertificateChainEngine(
  306. &Config,
  307. &hChainEngine
  308. );
  309. EnterCriticalSection( &m_Lock );
  310. if ( fResult == TRUE )
  311. {
  312. fResult = FindImpersonationEngine( &TokenId, &pEngine );
  313. if ( fResult == FALSE )
  314. {
  315. fResult = CreateImpersonationEngine(
  316. &TokenId,
  317. hChainEngine,
  318. &pEngine
  319. );
  320. if ( fResult == TRUE )
  321. {
  322. hChainEngine = NULL;
  323. AddToImpersonationCache( pEngine );
  324. }
  325. }
  326. }
  327. }
  328. FreeTokenId( &TokenId );
  329. }
  330. if ( fResult == TRUE )
  331. {
  332. *phDefaultEngine = pEngine->ChainEngine();
  333. ( (PCCERTCHAINENGINE)*phDefaultEngine )->AddRef();
  334. }
  335. if ( pEngine != NULL )
  336. {
  337. pEngine->Release();
  338. }
  339. // NOTE: This release of the lock to free the unneeded chain engine handle
  340. // must happen AFTER we're done with the impersonation engine and
  341. // have addref'd the appropriate chain engine handle
  342. if ( hChainEngine != NULL )
  343. {
  344. LeaveCriticalSection( &m_Lock );
  345. CertFreeCertificateChainEngine( hChainEngine );
  346. EnterCriticalSection( &m_Lock );
  347. }
  348. return( fResult );
  349. }
  350. //+---------------------------------------------------------------------------
  351. //
  352. // Member: CDefaultChainEngineMgr::IsImpersonatingUser, public
  353. //
  354. // Synopsis: is impersonating user?
  355. //
  356. //----------------------------------------------------------------------------
  357. BOOL
  358. CDefaultChainEngineMgr::IsImpersonatingUser (
  359. OUT HANDLE* phUserToken
  360. )
  361. {
  362. if ( FIsWinNT() == FALSE )
  363. {
  364. SetLastError( ERROR_NO_TOKEN );
  365. return( FALSE );
  366. }
  367. return( OpenThreadToken(
  368. GetCurrentThread(),
  369. TOKEN_QUERY,
  370. TRUE,
  371. phUserToken
  372. ) );
  373. }
  374. //+---------------------------------------------------------------------------
  375. //
  376. // Member: CDefaultChainEngineMgr::GetTokenId, public
  377. //
  378. // Synopsis: get the token id which is the ModifiedId LUID inside of
  379. // the TOKEN_STATISTICS information
  380. //
  381. //----------------------------------------------------------------------------
  382. BOOL
  383. CDefaultChainEngineMgr::GetTokenId (
  384. IN HANDLE hUserToken,
  385. OUT PCRYPT_DATA_BLOB pTokenId
  386. )
  387. {
  388. BOOL fResult;
  389. TOKEN_STATISTICS ts;
  390. DWORD Length = 0;
  391. fResult = GetTokenInformation(
  392. hUserToken,
  393. TokenStatistics,
  394. &ts,
  395. sizeof( ts ),
  396. &Length
  397. );
  398. if ( fResult == TRUE )
  399. {
  400. pTokenId->cbData = sizeof( ts.ModifiedId );
  401. pTokenId->pbData = new BYTE [ sizeof( ts.ModifiedId ) ];
  402. if ( pTokenId->pbData != NULL )
  403. {
  404. memcpy(
  405. pTokenId->pbData,
  406. &ts.ModifiedId,
  407. sizeof( ts.ModifiedId )
  408. );
  409. }
  410. else
  411. {
  412. SetLastError( (DWORD) E_OUTOFMEMORY );
  413. fResult = FALSE;
  414. }
  415. }
  416. return( fResult );
  417. }
  418. //+---------------------------------------------------------------------------
  419. //
  420. // Member: CDefaultChainEngineMgr::FreeTokenId, public
  421. //
  422. // Synopsis: free token id
  423. //
  424. //----------------------------------------------------------------------------
  425. VOID
  426. CDefaultChainEngineMgr::FreeTokenId (
  427. IN PCRYPT_DATA_BLOB pTokenId
  428. )
  429. {
  430. delete pTokenId->pbData;
  431. }
  432. //+---------------------------------------------------------------------------
  433. //
  434. // Member: CDefaultChainEngineMgr::FindImpersonationEngine, public
  435. //
  436. // Synopsis: find the impersonation engine
  437. //
  438. //----------------------------------------------------------------------------
  439. BOOL
  440. CDefaultChainEngineMgr::FindImpersonationEngine (
  441. IN PCRYPT_DATA_BLOB pTokenId,
  442. OUT PCIMPERSONATIONENGINE* ppEngine
  443. )
  444. {
  445. HLRUENTRY hFound;
  446. PCIMPERSONATIONENGINE pEngine = NULL;
  447. hFound = I_CryptFindLruEntry( m_hImpersonationCache, pTokenId );
  448. if ( hFound != NULL )
  449. {
  450. pEngine = (PCIMPERSONATIONENGINE)I_CryptGetLruEntryData( hFound );
  451. pEngine->AddRef();
  452. *ppEngine = pEngine;
  453. I_CryptReleaseLruEntry( hFound );
  454. return( TRUE );
  455. }
  456. return( FALSE );
  457. }
  458. //+---------------------------------------------------------------------------
  459. //
  460. // Member: CDefaultChainEngineMgr::CreateImpersonationEngine, public
  461. //
  462. // Synopsis: create an impersonation engine
  463. //
  464. //----------------------------------------------------------------------------
  465. BOOL
  466. CDefaultChainEngineMgr::CreateImpersonationEngine (
  467. IN PCRYPT_DATA_BLOB pTokenId,
  468. IN HCERTCHAINENGINE hChainEngine,
  469. OUT PCIMPERSONATIONENGINE* ppEngine
  470. )
  471. {
  472. BOOL fResult = FALSE;
  473. PCIMPERSONATIONENGINE pEngine;
  474. pEngine = new CImpersonationEngine(
  475. m_hImpersonationCache,
  476. hChainEngine,
  477. pTokenId,
  478. fResult
  479. );
  480. if ( pEngine == NULL )
  481. {
  482. SetLastError( (DWORD) E_OUTOFMEMORY );
  483. return( FALSE );
  484. }
  485. else if ( fResult == FALSE )
  486. {
  487. delete pEngine;
  488. return( FALSE );
  489. }
  490. *ppEngine = pEngine;
  491. return( TRUE );
  492. }
  493. //+---------------------------------------------------------------------------
  494. //
  495. // Member: CDefaultChainEngineMgr::AddToImpersonationCache, public
  496. //
  497. // Synopsis: add to the cache
  498. //
  499. //----------------------------------------------------------------------------
  500. VOID
  501. CDefaultChainEngineMgr::AddToImpersonationCache(
  502. IN PCIMPERSONATIONENGINE pEngine
  503. )
  504. {
  505. pEngine->AddRef();
  506. I_CryptInsertLruEntry( pEngine->LruEntry(), NULL );
  507. }
  508. //+---------------------------------------------------------------------------
  509. //
  510. // Function: DefaultChainEngineMgrOnImpersonationEngineRemoval
  511. //
  512. // Synopsis: removal notification
  513. //
  514. //----------------------------------------------------------------------------
  515. VOID WINAPI
  516. DefaultChainEngineMgrOnImpersonationEngineRemoval (
  517. IN LPVOID pv,
  518. IN LPVOID pvRemovalContext
  519. )
  520. {
  521. ( (PCIMPERSONATIONENGINE)pv )->Release();
  522. }
  523. //+---------------------------------------------------------------------------
  524. //
  525. // Function: DefaultChainEngineMgrHashTokenIdentifier
  526. //
  527. // Synopsis: hash the token identifier
  528. //
  529. //----------------------------------------------------------------------------
  530. DWORD WINAPI
  531. DefaultChainEngineMgrHashTokenIdentifier (
  532. IN PCRYPT_DATA_BLOB pIdentifier
  533. )
  534. {
  535. DWORD dwHash = 0;
  536. DWORD cb = pIdentifier->cbData;
  537. LPBYTE pb = pIdentifier->pbData;
  538. while ( cb-- )
  539. {
  540. if ( dwHash & 0x80000000 )
  541. {
  542. dwHash = ( dwHash << 1 ) | 1;
  543. }
  544. else
  545. {
  546. dwHash = dwHash << 1;
  547. }
  548. dwHash += *pb++;
  549. }
  550. return( dwHash );
  551. }
  552. //+---------------------------------------------------------------------------
  553. //
  554. // Member: CImpersonationEngine::CImpersonationEngine, public
  555. //
  556. // Synopsis: Constructor
  557. //
  558. //----------------------------------------------------------------------------
  559. CImpersonationEngine::CImpersonationEngine (
  560. IN HLRUCACHE hCache,
  561. IN HCERTCHAINENGINE hChainEngine,
  562. IN PCRYPT_DATA_BLOB pTokenId,
  563. OUT BOOL& rfResult
  564. )
  565. {
  566. m_cRefs = 1;
  567. m_hChainEngine = NULL;
  568. m_hLruEntry = NULL;
  569. rfResult = I_CryptCreateLruEntry(
  570. hCache,
  571. pTokenId,
  572. this,
  573. &m_hLruEntry
  574. );
  575. if ( rfResult == TRUE )
  576. {
  577. m_hChainEngine = hChainEngine;
  578. }
  579. }
  580. //+---------------------------------------------------------------------------
  581. //
  582. // Member: CImpersonationEngine::~CImpersonationEngine, public
  583. //
  584. // Synopsis: Destructor
  585. //
  586. //----------------------------------------------------------------------------
  587. CImpersonationEngine::~CImpersonationEngine ()
  588. {
  589. if ( m_hLruEntry != NULL )
  590. {
  591. I_CryptReleaseLruEntry( m_hLruEntry );
  592. }
  593. if ( m_hChainEngine != NULL )
  594. {
  595. CertFreeCertificateChainEngine( m_hChainEngine );
  596. }
  597. }