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.

277 lines
8.2 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: imprsnat.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 2-16-96 srikants Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <pch.cxx>
  18. #pragma hdrstop
  19. #include <imprsnat.hxx>
  20. #include <ciregkey.hxx>
  21. BOOL CImpersonateSystem::_fIsRunningAsSystem = TRUE;
  22. BOOL CImpersonateSystem::IsRunningAsSystem()
  23. {
  24. return CImpersonateSystem::_fIsRunningAsSystem;
  25. }
  26. void CImpersonateSystem::SetRunningAsSystem()
  27. {
  28. CImpersonateSystem::_fIsRunningAsSystem = TRUE;
  29. }
  30. //+---------------------------------------------------------------------------
  31. //
  32. // Member: CImpersonateSystem::MakePrivileged
  33. //
  34. // Synopsis: This call makes the caller a "privileged" user by reverting
  35. // to the "original" context.
  36. //
  37. // History: 2-19-96 srikants Created
  38. //
  39. // Notes: We are assuming that the "original" context of the thread
  40. // is a "privileged" context.
  41. //
  42. //----------------------------------------------------------------------------
  43. void CImpersonateSystem::MakePrivileged()
  44. {
  45. Win4Assert( !_fRevertedToSystem );
  46. //
  47. // The typical path here is failure, and it's expensive for NT to
  48. // convert the NTSTATUS to a Win32 error. So call NT.
  49. //
  50. NTSTATUS status = NtOpenThreadToken( GetCurrentThread(),
  51. TOKEN_DUPLICATE | TOKEN_QUERY |
  52. TOKEN_IMPERSONATE,
  53. TRUE, // Access check against the process
  54. &_hClientToken );
  55. if ( NT_ERROR( status ) )
  56. {
  57. if ( ( STATUS_NO_TOKEN == status ) ||
  58. ( STATUS_ACCESS_DENIED == status ) )
  59. {
  60. //
  61. // This thread is currently not impersonating anyone. We don't
  62. // have to become system. We should already have the correct
  63. // privileges. Or we're in asp.net and can't get the token.
  64. //
  65. }
  66. else
  67. {
  68. ciDebugOut(( DEB_ERROR,
  69. "NtOpenThreadToken() failed with error %#x\n",
  70. status ));
  71. THROW( CException( status ) );
  72. }
  73. }
  74. else
  75. {
  76. _fRevertedToSystem = RevertToSelf();
  77. //
  78. // NTRAID#DB-NTBUG9-84492-2000/07/31-dlee Indexing Service assumes in multiple places that RevertToSelf will always succeed
  79. // what should we do if we fail to revert to self?
  80. //
  81. if ( !_fRevertedToSystem )
  82. {
  83. ciDebugOut(( DEB_ERROR,
  84. "RevertToSelf() failed with error %d\n", GetLastError() ));
  85. }
  86. }
  87. }
  88. //+---------------------------------------------------------------------------
  89. //
  90. // Member: CImpersonateSystem::~CImpersonateSystem
  91. //
  92. // Synopsis: ~dtor of the CImpersonateSystem class. Will restore the
  93. // context of the thread before making it privileged.
  94. //
  95. // History: 2-19-96 srikants Created
  96. //
  97. // Notes:
  98. //
  99. //----------------------------------------------------------------------------
  100. CImpersonateSystem::~CImpersonateSystem()
  101. {
  102. if ( _fRevertedToSystem )
  103. {
  104. Win4Assert( INVALID_HANDLE_VALUE != _hClientToken );
  105. BOOL fResult = ImpersonateLoggedOnUser( _hClientToken );
  106. if ( !fResult )
  107. {
  108. DWORD dwError = GetLastError();
  109. ciDebugOut(( DEB_ERROR, "ImpersonateLoggedOnUser failed with error code %d\n",
  110. dwError ));
  111. }
  112. }
  113. if ( INVALID_HANDLE_VALUE != _hClientToken )
  114. {
  115. CloseHandle( _hClientToken );
  116. }
  117. }
  118. //+---------------------------------------------------------------------------
  119. //
  120. // Function: IsImpersonated
  121. //
  122. // Synopsis: Tests if the caller is impersonated.
  123. //
  124. // Returns: TRUE if impersonated; FALSE if not.
  125. //
  126. // History: 12-31-96 srikants Created
  127. //
  128. //----------------------------------------------------------------------------
  129. BOOL CImpersonateSystem::IsImpersonated()
  130. {
  131. BOOL fImpersonated = FALSE;
  132. HANDLE hThreadToken;
  133. NTSTATUS status = NtOpenThreadToken( GetCurrentThread(),
  134. TOKEN_QUERY,
  135. TRUE, // Access check against the process
  136. &hThreadToken );
  137. if ( NT_SUCCESS( status ) )
  138. {
  139. CloseHandle( hThreadToken );
  140. fImpersonated = TRUE;
  141. }
  142. else
  143. {
  144. if ( STATUS_NO_TOKEN != status )
  145. {
  146. ciDebugOut(( DEB_ERROR,
  147. "NtOpenThreadToken() failed with error %#x\n",
  148. status ));
  149. fImpersonated = TRUE;
  150. }
  151. }
  152. return fImpersonated;
  153. }
  154. //+---------------------------------------------------------------------------
  155. //
  156. // Member: CImpersonateClient::Impersonate
  157. //
  158. // Synopsis: Assume a client context.
  159. //
  160. // History: 19 Mar 96 AlanW Created
  161. //
  162. // Notes: We are assuming that the "original" context of the thread
  163. // is a "privileged" context.
  164. //
  165. //----------------------------------------------------------------------------
  166. void CImpersonateClient::Impersonate()
  167. {
  168. if ( INVALID_HANDLE_VALUE != _hClientToken )
  169. {
  170. BOOL fResult = ImpersonateLoggedOnUser( _hClientToken );
  171. if ( !fResult )
  172. {
  173. ciDebugOut(( DEB_ERROR,
  174. "ImpersonateLoggedOnUser failed with error code %d\n",
  175. GetLastError() ));
  176. }
  177. }
  178. }
  179. //+---------------------------------------------------------------------------
  180. //
  181. // Member: CImpersonateClient::~CImpersonateClient
  182. //
  183. // Synopsis: ~dtor of the CImpersonateClient class. Will restore the
  184. // context of the thread before impersonating (assumed to be
  185. // running as "system" previously).
  186. //
  187. // History: 19 Mar 96 AlanW Created
  188. //
  189. // Notes:
  190. //
  191. //----------------------------------------------------------------------------
  192. CImpersonateClient::~CImpersonateClient()
  193. {
  194. if ( INVALID_HANDLE_VALUE != _hClientToken )
  195. {
  196. BOOL fRevertedToSystem = RevertToSelf();
  197. if ( !fRevertedToSystem )
  198. {
  199. ciDebugOut(( DEB_ERROR,
  200. "RevertToSelf() failed with error %d\n",
  201. GetLastError() ));
  202. }
  203. }
  204. }
  205. //+---------------------------------------------------------------------------
  206. //
  207. // Function: VerifyThreadHasAdminPrivilege, public
  208. //
  209. // Synopsis: Checks to see if the client has administrative access.
  210. //
  211. // Arguments: - NONE -
  212. //
  213. // Returns: Nothing, throws if access is denied.
  214. //
  215. // Notes: The ACL on the HKEY_CURRENT_MACHINE\system\CurrentControlSet\
  216. // Control\ContentIndex registry key is used to determine if
  217. // access is permitted.
  218. //
  219. // History: 26 Jun 96 AlanW Created.
  220. // History: 1 Oct 96 dlee Stole from idq and renamed
  221. //
  222. //----------------------------------------------------------------------------
  223. void VerifyThreadHasAdminPrivilege()
  224. {
  225. HKEY hNewKey = (HKEY) INVALID_HANDLE_VALUE;
  226. LONG dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  227. wcsRegAdminSubKey,
  228. 0,
  229. KEY_WRITE,
  230. &hNewKey );
  231. if ( ERROR_SUCCESS == dwError )
  232. {
  233. RegCloseKey( hNewKey );
  234. }
  235. else if ( ERROR_ACCESS_DENIED == dwError )
  236. {
  237. THROW( CException( STATUS_ACCESS_DENIED ) );
  238. }
  239. else
  240. {
  241. ciDebugOut(( DEB_ERROR,
  242. "Can't open reg key %ws, error %d\n",
  243. wcsRegAdminSubKey, dwError ));
  244. THROW( CException( HRESULT_FROM_WIN32( dwError ) ) );
  245. }
  246. } //VerifyThreadHasAdminPrivilege