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.

276 lines
7.8 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. {
  59. //
  60. // This thread is currently not impersonating anyone. We don't
  61. // have to become system. We should already have the correct
  62. // privileges.
  63. //
  64. }
  65. else
  66. {
  67. ciDebugOut(( DEB_ERROR,
  68. "NtOpenThreadToken() failed with error %#x\n",
  69. status ));
  70. THROW( CException( status ) );
  71. }
  72. }
  73. else
  74. {
  75. _fRevertedToSystem = RevertToSelf();
  76. //
  77. // NTRAID#DB-NTBUG9-84492-2000/07/31-dlee Indexing Service assumes in multiple places that RevertToSelf will always succeed
  78. // what should we do if we fail to revert to self?
  79. //
  80. if ( !_fRevertedToSystem )
  81. {
  82. ciDebugOut(( DEB_ERROR,
  83. "RevertToSelf() failed with error %d\n", GetLastError() ));
  84. }
  85. }
  86. }
  87. //+---------------------------------------------------------------------------
  88. //
  89. // Member: CImpersonateSystem::~CImpersonateSystem
  90. //
  91. // Synopsis: ~dtor of the CImpersonateSystem class. Will restore the
  92. // context of the thread before making it privileged.
  93. //
  94. // History: 2-19-96 srikants Created
  95. //
  96. // Notes:
  97. //
  98. //----------------------------------------------------------------------------
  99. CImpersonateSystem::~CImpersonateSystem()
  100. {
  101. if ( _fRevertedToSystem )
  102. {
  103. Win4Assert( INVALID_HANDLE_VALUE != _hClientToken );
  104. BOOL fResult = ImpersonateLoggedOnUser( _hClientToken );
  105. if ( !fResult )
  106. {
  107. DWORD dwError = GetLastError();
  108. ciDebugOut(( DEB_ERROR, "ImpersonateLoggedOnUser failed with error code %d\n",
  109. dwError ));
  110. }
  111. }
  112. if ( INVALID_HANDLE_VALUE != _hClientToken )
  113. {
  114. CloseHandle( _hClientToken );
  115. }
  116. }
  117. //+---------------------------------------------------------------------------
  118. //
  119. // Function: IsImpersonated
  120. //
  121. // Synopsis: Tests if the caller is impersonated.
  122. //
  123. // Returns: TRUE if impersonated; FALSE if not.
  124. //
  125. // History: 12-31-96 srikants Created
  126. //
  127. //----------------------------------------------------------------------------
  128. BOOL CImpersonateSystem::IsImpersonated()
  129. {
  130. BOOL fImpersonated = FALSE;
  131. HANDLE hThreadToken;
  132. NTSTATUS status = NtOpenThreadToken( GetCurrentThread(),
  133. TOKEN_QUERY,
  134. TRUE, // Access check against the process
  135. &hThreadToken );
  136. if ( NT_SUCCESS( status ) )
  137. {
  138. CloseHandle( hThreadToken );
  139. fImpersonated = TRUE;
  140. }
  141. else
  142. {
  143. if ( STATUS_NO_TOKEN != status )
  144. {
  145. ciDebugOut(( DEB_ERROR,
  146. "NtOpenThreadToken() failed with error %#x\n",
  147. status ));
  148. fImpersonated = TRUE;
  149. }
  150. }
  151. return fImpersonated;
  152. }
  153. //+---------------------------------------------------------------------------
  154. //
  155. // Member: CImpersonateClient::Impersonate
  156. //
  157. // Synopsis: Assume a client context.
  158. //
  159. // History: 19 Mar 96 AlanW Created
  160. //
  161. // Notes: We are assuming that the "original" context of the thread
  162. // is a "privileged" context.
  163. //
  164. //----------------------------------------------------------------------------
  165. void CImpersonateClient::Impersonate()
  166. {
  167. if ( INVALID_HANDLE_VALUE != _hClientToken )
  168. {
  169. BOOL fResult = ImpersonateLoggedOnUser( _hClientToken );
  170. if ( !fResult )
  171. {
  172. ciDebugOut(( DEB_ERROR,
  173. "ImpersonateLoggedOnUser failed with error code %d\n",
  174. GetLastError() ));
  175. }
  176. }
  177. }
  178. //+---------------------------------------------------------------------------
  179. //
  180. // Member: CImpersonateClient::~CImpersonateClient
  181. //
  182. // Synopsis: ~dtor of the CImpersonateClient class. Will restore the
  183. // context of the thread before impersonating (assumed to be
  184. // running as "system" previously).
  185. //
  186. // History: 19 Mar 96 AlanW Created
  187. //
  188. // Notes:
  189. //
  190. //----------------------------------------------------------------------------
  191. CImpersonateClient::~CImpersonateClient()
  192. {
  193. if ( INVALID_HANDLE_VALUE != _hClientToken )
  194. {
  195. BOOL fRevertedToSystem = RevertToSelf();
  196. if ( !fRevertedToSystem )
  197. {
  198. ciDebugOut(( DEB_ERROR,
  199. "RevertToSelf() failed with error %d\n",
  200. GetLastError() ));
  201. }
  202. }
  203. }
  204. //+---------------------------------------------------------------------------
  205. //
  206. // Function: VerifyThreadHasAdminPrivilege, public
  207. //
  208. // Synopsis: Checks to see if the client has administrative access.
  209. //
  210. // Arguments: - NONE -
  211. //
  212. // Returns: Nothing, throws if access is denied.
  213. //
  214. // Notes: The ACL on the HKEY_CURRENT_MACHINE\system\CurrentControlSet\
  215. // Control\ContentIndex registry key is used to determine if
  216. // access is permitted.
  217. //
  218. // History: 26 Jun 96 AlanW Created.
  219. // History: 1 Oct 96 dlee Stole from idq and renamed
  220. //
  221. //----------------------------------------------------------------------------
  222. void VerifyThreadHasAdminPrivilege()
  223. {
  224. HKEY hNewKey = (HKEY) INVALID_HANDLE_VALUE;
  225. LONG dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  226. wcsRegAdminSubKey,
  227. 0,
  228. KEY_WRITE,
  229. &hNewKey );
  230. if ( ERROR_SUCCESS == dwError )
  231. {
  232. RegCloseKey( hNewKey );
  233. }
  234. else if ( ERROR_ACCESS_DENIED == dwError )
  235. {
  236. THROW( CException( STATUS_ACCESS_DENIED ) );
  237. }
  238. else
  239. {
  240. ciDebugOut(( DEB_ERROR,
  241. "Can't open reg key %ws, error %d\n",
  242. wcsRegAdminSubKey, dwError ));
  243. THROW( CException( HRESULT_FROM_WIN32( dwError ) ) );
  244. }
  245. } //VerifyThreadHasAdminPrivilege