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.

214 lines
7.5 KiB

  1. // AdjustTokenPrivileges.cpp: implementation of the CAdjustTokenPrivileges class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "AdjustTokenPrivileges.h"
  6. //////////////////////////////////////////////////////////////////////
  7. // Construction/Destruction
  8. //////////////////////////////////////////////////////////////////////
  9. CAdjustTokenPrivileges::CAdjustTokenPrivileges() :
  10. m_dwAttributesPrev(0), m_bImpersonation(false), m_hToken(INVALID_HANDLE_VALUE), m_hTokenDuplicate(INVALID_HANDLE_VALUE)
  11. {
  12. }
  13. CAdjustTokenPrivileges::~CAdjustTokenPrivileges()
  14. {
  15. if ( m_bImpersonation )
  16. RevertToSelf(); // Deletes the thread token so there is no need to reset the TokenPrivilege
  17. else if ( INVALID_HANDLE_VALUE != m_hToken )
  18. {
  19. TOKEN_PRIVILEGES TokenPrivileges;
  20. DWORD dwRC = GetLastError();
  21. TokenPrivileges.PrivilegeCount = 1;
  22. TokenPrivileges.Privileges[0].Luid = m_luid;
  23. TokenPrivileges.Privileges[0].Attributes = m_dwAttributesPrev;
  24. //adjust the privlige to this new privilege
  25. AdjustTokenPrivileges( m_hToken, FALSE, &TokenPrivileges, sizeof( TOKEN_PRIVILEGES ), NULL, NULL );
  26. CloseHandle( m_hToken );
  27. if ( ERROR_SUCCESS != dwRC ) // Preserve any error code
  28. SetLastError( dwRC );
  29. }
  30. if ( INVALID_HANDLE_VALUE != m_hTokenDuplicate )
  31. CloseHandle( m_hTokenDuplicate );
  32. }
  33. //////////////////////////////////////////////////////////////////////
  34. // Implementation : public
  35. //////////////////////////////////////////////////////////////////////
  36. DWORD CAdjustTokenPrivileges::AdjustPrivileges( LPCTSTR lpPrivelegeName, DWORD dwAttributes )
  37. {
  38. //local variables
  39. TOKEN_PRIVILEGES TokenPrivileges, TokenPrivilegesOld;
  40. DWORD dwRC = ERROR_SUCCESS, dwSize = sizeof( TokenPrivilegesOld );
  41. if ( !LookupPrivilegeValue( NULL, lpPrivelegeName, &m_luid ))
  42. dwRC = GetLastError();
  43. if ( ERROR_SUCCESS == dwRC )
  44. { // open the token of the current process
  45. if ( !OpenThreadToken( GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &m_hToken ))
  46. {
  47. dwRC = GetLastError();
  48. if ( ERROR_NO_TOKEN == dwRC )
  49. {// There's no impersonation let's impersonate self so we can make this work
  50. if ( ImpersonateSelf( SecurityImpersonation ))
  51. {
  52. if ( OpenThreadToken( GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &m_hToken ))
  53. {
  54. dwRC = ERROR_SUCCESS;
  55. m_bImpersonation = true;
  56. }
  57. else
  58. {
  59. dwRC = GetLastError();
  60. RevertToSelf(); // Already have an error, don't want to overwrite if this fails
  61. }
  62. }
  63. else
  64. dwRC = GetLastError();
  65. }
  66. }
  67. }
  68. if ( ERROR_SUCCESS == dwRC )
  69. { // Set up the privilege set we will need
  70. TokenPrivileges.PrivilegeCount = 1;
  71. TokenPrivileges.Privileges[0].Luid = m_luid;
  72. TokenPrivileges.Privileges[0].Attributes = dwAttributes;
  73. //adjust the privlige to this new privilege
  74. if ( AdjustTokenPrivileges( m_hToken, FALSE, &TokenPrivileges, sizeof( TOKEN_PRIVILEGES ), &TokenPrivilegesOld, &dwSize ))
  75. m_dwAttributesPrev = TokenPrivilegesOld.Privileges[0].Attributes;
  76. dwRC = GetLastError(); // We need to check the return code regardless of what AdjustTokenPrivileges returns
  77. // AdjustTokenPrivileges set last error to ERROR_SUCCESS if it set all specified privileges!
  78. }
  79. if ( dwRC != ERROR_SUCCESS )
  80. {
  81. CloseHandle( m_hToken );
  82. m_hToken = INVALID_HANDLE_VALUE;
  83. }
  84. return dwRC;
  85. }
  86. DWORD CAdjustTokenPrivileges::DuplicateProcessToken( LPCTSTR lpPrivelegeName, DWORD dwAttributes )
  87. {
  88. DWORD dwRC = ERROR_SUCCESS;
  89. HANDLE hToken;
  90. HANDLE hTokenThread = INVALID_HANDLE_VALUE;
  91. if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_DUPLICATE, &hToken ))
  92. dwRC = GetLastError();
  93. if ( ERROR_SUCCESS == dwRC )
  94. {
  95. if ( !DuplicateToken( hToken, SecurityImpersonation, &m_hTokenDuplicate ))
  96. dwRC = GetLastError();
  97. CloseHandle( hToken );
  98. }
  99. if ( ERROR_SUCCESS == dwRC )
  100. {
  101. if ( !OpenThreadToken( GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hTokenThread ))
  102. {
  103. dwRC = GetLastError();
  104. if ( ERROR_NO_TOKEN == dwRC )
  105. {
  106. dwRC = ERROR_SUCCESS;
  107. hTokenThread = INVALID_HANDLE_VALUE;
  108. }
  109. }
  110. }
  111. if ( ERROR_SUCCESS == dwRC )
  112. {
  113. if ( SetThreadToken( NULL, m_hTokenDuplicate ))
  114. {
  115. dwRC = AdjustPrivileges( SE_RESTORE_NAME, SE_PRIVILEGE_ENABLED );
  116. m_hToken = INVALID_HANDLE_VALUE; // This is really the m_hTokenDuplicate, don't want to Close in the destructor
  117. if ( !SetThreadToken( NULL, NULL ))
  118. {
  119. if ( ERROR_SUCCESS == dwRC ) // Don't overwrite existing error code
  120. dwRC = GetLastError();
  121. }
  122. }
  123. else
  124. dwRC = GetLastError();
  125. }
  126. if ( INVALID_HANDLE_VALUE != hTokenThread )
  127. {
  128. if ( !SetThreadToken( NULL, hTokenThread ))
  129. dwRC = GetLastError();
  130. CloseHandle( hTokenThread );
  131. }
  132. return dwRC;
  133. }
  134. /////////////////////////////////////////////////////////////////////////////
  135. // ResetThreadToken, public
  136. //
  137. // Purpose:
  138. // Use the Duplicate process token to enable privileges for the thread.
  139. // If the Thread already has a token (unexpected) then adjust the privileges.
  140. //
  141. // Arguments:
  142. //
  143. // Returns: TRUE on success, FALSE otherwise
  144. DWORD CAdjustTokenPrivileges::ResetToken()
  145. {
  146. DWORD dwRC = ERROR_SUCCESS;
  147. HANDLE hToken;
  148. if ( INVALID_HANDLE_VALUE != m_hTokenDuplicate && INVALID_HANDLE_VALUE == m_hToken )
  149. {
  150. if ( !SetThreadToken( NULL, NULL ))
  151. dwRC = GetLastError();
  152. }
  153. else
  154. dwRC = ERROR_NO_TOKEN;
  155. return dwRC;
  156. }
  157. /////////////////////////////////////////////////////////////////////////////
  158. // SetThreadToken, public
  159. //
  160. // Purpose:
  161. // Use the Duplicated process token to enable privileges for the thread.
  162. // If the Thread already has a token (unexpected) then adjust the privileges.
  163. //
  164. // Arguments:
  165. //
  166. // Returns: TRUE on success, FALSE otherwise
  167. DWORD CAdjustTokenPrivileges::SetToken()
  168. {
  169. DWORD dwRC = ERROR_SUCCESS;
  170. HANDLE hToken;
  171. if ( INVALID_HANDLE_VALUE != m_hTokenDuplicate )
  172. {
  173. if ( OpenThreadToken( GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken ))
  174. { // The thread already has a token, let's work with it
  175. CloseHandle( hToken );
  176. dwRC = AdjustPrivileges( SE_RESTORE_NAME, SE_PRIVILEGE_ENABLED );
  177. }
  178. else
  179. { // Let's use are duplicate token
  180. if ( ERROR_NO_TOKEN == GetLastError() )
  181. {
  182. if ( !SetThreadToken( NULL, m_hTokenDuplicate ))
  183. dwRC = GetLastError();
  184. }
  185. else
  186. dwRC = GetLastError();
  187. }
  188. }
  189. else
  190. dwRC = ERROR_NO_TOKEN;
  191. return dwRC;
  192. }