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.

273 lines
8.3 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1998.
  5. //
  6. // File: seccache.cxx
  7. //
  8. // Contents: Security descriptor cache that maps SDIDs to granted/denied
  9. //
  10. // Class: CSecurityCache
  11. //
  12. // History: 25-Sep-95 dlee Created
  13. // 22 Jan 96 Alanw Modified for use in user mode
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.cxx>
  17. #pragma hdrstop
  18. // Local includes:
  19. #include <seccache.hxx>
  20. #include <catalog.hxx>
  21. //+---------------------------------------------------------------------------
  22. //
  23. // Method: CSecurityCache::CSecurityCache, public
  24. //
  25. // Synopsis: Creates a CSecurityCache. In user mode, an
  26. // impersonation token to use with the AccessCheck call is
  27. // obtained.
  28. //
  29. // History: 22 Jan 96 Alanw Created
  30. //
  31. //----------------------------------------------------------------------------
  32. CSecurityCache::CSecurityCache( PCatalog & rCat ) :
  33. _aEntries( cDefaultSecurityDescriptorEntries ),
  34. _hToken( INVALID_HANDLE_VALUE ),
  35. _Cat( rCat )
  36. {
  37. InitToken();
  38. }
  39. //+---------------------------------------------------------------------------
  40. //
  41. // Method: CSecurityCache::InitToken, public
  42. //
  43. // Synopsis: Captures an impersonation token to use with the AccessCheck
  44. // call.
  45. //
  46. // History: 15 Feb 96 Alanw Created
  47. //
  48. //----------------------------------------------------------------------------
  49. void CSecurityCache::InitToken( )
  50. {
  51. DWORD ReturnLength;
  52. NTSTATUS status;
  53. TOKEN_STATISTICS TokenInformation;
  54. status = NtOpenThreadToken( GetCurrentThread(),
  55. TOKEN_QUERY | TOKEN_DUPLICATE |
  56. TOKEN_IMPERSONATE, // Desired Access
  57. TRUE, // OpenAsSelf
  58. &_hToken);
  59. if (!NT_SUCCESS(status)) {
  60. if (status == STATUS_NO_TOKEN)
  61. {
  62. status = NtOpenProcessToken( GetCurrentProcess(),
  63. TOKEN_QUERY | TOKEN_DUPLICATE |
  64. TOKEN_IMPERSONATE, // Desired Access
  65. &_hToken);
  66. }
  67. if (!NT_SUCCESS(status))
  68. {
  69. vqDebugOut(( DEB_ERROR,
  70. "CSecurityCache: failed to get token handle, %x\n",
  71. status ));
  72. THROW(CException( status ));
  73. }
  74. }
  75. status = NtQueryInformationToken ( _hToken,
  76. TokenStatistics,
  77. (LPVOID)&TokenInformation,
  78. sizeof TokenInformation,
  79. &ReturnLength);
  80. if (!NT_SUCCESS(status))
  81. {
  82. NtClose( _hToken );
  83. _hToken = INVALID_HANDLE_VALUE;
  84. vqDebugOut(( DEB_ERROR,
  85. "CSecurityCache: failed to get token info, %x\n",
  86. status ));
  87. THROW(CException( status ));
  88. }
  89. if ( TokenInformation.TokenType != TokenImpersonation )
  90. {
  91. HANDLE hNewToken = INVALID_HANDLE_VALUE;
  92. OBJECT_ATTRIBUTES ObjA;
  93. SECURITY_QUALITY_OF_SERVICE SecurityQOS;
  94. SecurityQOS.Length = sizeof( SECURITY_QUALITY_OF_SERVICE );
  95. SecurityQOS.ImpersonationLevel = SecurityIdentification;
  96. SecurityQOS.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  97. SecurityQOS.EffectiveOnly = FALSE;
  98. InitializeObjectAttributes( &ObjA,
  99. NULL,
  100. 0,
  101. NULL,
  102. NULL );
  103. ObjA.SecurityQualityOfService = &SecurityQOS;
  104. status = NtDuplicateToken( _hToken,
  105. TOKEN_IMPERSONATE | TOKEN_QUERY,
  106. &ObjA,
  107. FALSE,
  108. TokenImpersonation,
  109. &hNewToken );
  110. if (! NT_SUCCESS( status ) )
  111. {
  112. NtClose( _hToken );
  113. _hToken = INVALID_HANDLE_VALUE;
  114. vqDebugOut(( DEB_ERROR,
  115. "CSecurityCache: failed to duplicate token, %x\n",
  116. status ));
  117. THROW(CException( status ));
  118. }
  119. NtClose( _hToken );
  120. _hToken = hNewToken;
  121. }
  122. }
  123. CSecurityCache::~CSecurityCache()
  124. {
  125. if ( INVALID_HANDLE_VALUE != _hToken )
  126. NtClose( _hToken );
  127. }
  128. //+---------------------------------------------------------------------------
  129. //
  130. // Method: CSecurityCache::_IsCached, private
  131. //
  132. // Synopsis: Determines whether a sdid is granted access given the
  133. // cache's security context.
  134. //
  135. // Arguments: [sdidOrd] -- security descriptor ordinal to test
  136. // [am] -- access mask of the request
  137. // [fGranted] -- if return value is TRUE, this is either
  138. // TRUE (if access is granted) or FALSE.
  139. //
  140. // Returns: TRUE if sdid was in the cache and fGranted is set
  141. // FALSE if sdid is not cached and fGranted should be ignored
  142. //
  143. // History: 25-Sep-95 dlee Created
  144. //
  145. //----------------------------------------------------------------------------
  146. inline BOOL CSecurityCache::_IsCached(
  147. ULONG sdidOrd,
  148. ACCESS_MASK am,
  149. BOOL & fGranted ) const
  150. {
  151. // Look for the sdid in the cache
  152. for ( unsigned i = 0; i < _aEntries.Count(); i++ )
  153. {
  154. if ( ( _aEntries[i].sdidOrd == sdidOrd ) &&
  155. ( _aEntries[i].am == am ) )
  156. {
  157. fGranted = _aEntries[i].fGranted;
  158. return TRUE;
  159. }
  160. }
  161. return FALSE;
  162. } //_IsCached
  163. //+---------------------------------------------------------------------------
  164. //
  165. // Method: CSecurityCache::IsGranted, public
  166. //
  167. // Synopsis: Determines whether a security ordinal is granted access given
  168. // the cache's security context, and caches the result.
  169. //
  170. // Arguments: [sdidOrdinal] -- security descriptor ordinal to test
  171. // [am] -- access mask of the request, one or more of
  172. // FILE_READ_ATTRIBUTES
  173. // FILE_READ_DATA / FILE_LIST_DIRECTORY
  174. // FILE_TRAVERSE
  175. //
  176. // Returns: TRUE if sdid was granted access, FALSE otherwise
  177. //
  178. // History: 25-Sep-95 dlee Created
  179. // 22 Jan 96 Alanw Modified for use in user mode
  180. //
  181. //----------------------------------------------------------------------------
  182. BOOL CSecurityCache::IsGranted(
  183. ULONG sdidOrdinal,
  184. ACCESS_MASK am )
  185. {
  186. // if nothing asked for, grant
  187. if ( 0 == am )
  188. return TRUE;
  189. if ( sdidNull == sdidOrdinal )
  190. return TRUE;
  191. if ( sdidInvalid == sdidOrdinal )
  192. return FALSE;
  193. BOOL fGranted;
  194. {
  195. CLock lock( _mutex );
  196. if ( _IsCached( sdidOrdinal, am, fGranted ) )
  197. return fGranted;
  198. }
  199. // do the security check
  200. fGranted = FALSE;
  201. BOOL fResult = _Cat.AccessCheck( sdidOrdinal,
  202. GetToken(),
  203. am,
  204. fGranted);
  205. if (! fResult)
  206. {
  207. DWORD dwError = GetLastError();
  208. Win4Assert( fResult && dwError == NO_ERROR );
  209. }
  210. // Not cached yet -- do so
  211. vqDebugOut(( DEB_ITRACE, "cacheing sdid %x, granted: %x\n",
  212. sdidOrdinal, fGranted ));
  213. {
  214. CLock lock( _mutex );
  215. // check the cache again -- it may have slipped in via a different
  216. // thread while we weren't holding the lock.
  217. if ( !_IsCached( sdidOrdinal, am, fGranted ) )
  218. {
  219. unsigned i = _aEntries.Count();
  220. _aEntries[i].sdidOrd = sdidOrdinal;
  221. _aEntries[i].am = am;
  222. _aEntries[i].fGranted = fGranted;
  223. }
  224. }
  225. return fGranted;
  226. } //IsGranted