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.

301 lines
7.9 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. GETPRIV.C
  5. Abstract:
  6. Contains functions for obtaining and relinquishing privileges
  7. Author:
  8. Dan Lafferty (danl) 20-Mar-1991
  9. Environment:
  10. User Mode -Win32
  11. Revision History:
  12. 20-Mar-1991 danl
  13. created
  14. --*/
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <netdebug.h>
  20. #include <debuglib.h>
  21. #define PRIVILEGE_BUF_SIZE 512
  22. DWORD
  23. NetpGetPrivilege(
  24. IN DWORD numPrivileges,
  25. IN PULONG pulPrivileges
  26. )
  27. /*++
  28. Routine Description:
  29. This function alters the privilege level for the current thread.
  30. It does this by duplicating the token for the current thread, and then
  31. applying the new privileges to that new token, then the current thread
  32. impersonates with that new token.
  33. Privileges can be relinquished by calling NetpReleasePrivilege().
  34. Arguments:
  35. numPrivileges - This is a count of the number of privileges in the
  36. array of privileges.
  37. pulPrivileges - This is a pointer to the array of privileges that are
  38. desired. This is an array of ULONGs.
  39. Return Value:
  40. NO_ERROR - If the operation was completely successful.
  41. Otherwise, it returns mapped return codes from the various NT
  42. functions that are called.
  43. --*/
  44. {
  45. DWORD status;
  46. NTSTATUS ntStatus;
  47. HANDLE ourToken;
  48. HANDLE newToken;
  49. OBJECT_ATTRIBUTES Obja;
  50. SECURITY_QUALITY_OF_SERVICE SecurityQofS;
  51. ULONG bufLen;
  52. ULONG returnLen;
  53. PTOKEN_PRIVILEGES pPreviousState;
  54. PTOKEN_PRIVILEGES pTokenPrivilege = NULL;
  55. DWORD i;
  56. //
  57. // Initialize the Privileges Structure
  58. //
  59. pTokenPrivilege = LocalAlloc(LMEM_FIXED, sizeof(TOKEN_PRIVILEGES) +
  60. (sizeof(LUID_AND_ATTRIBUTES) * numPrivileges));
  61. if (pTokenPrivilege == NULL) {
  62. status = GetLastError();
  63. IF_DEBUG(SECURITY) {
  64. NetpKdPrint(("NetpGetPrivilege:LocalAlloc Failed %d\n", status));
  65. }
  66. return(status);
  67. }
  68. pTokenPrivilege->PrivilegeCount = numPrivileges;
  69. for (i=0; i<numPrivileges ;i++ ) {
  70. pTokenPrivilege->Privileges[i].Luid = RtlConvertUlongToLuid(
  71. pulPrivileges[i]);
  72. pTokenPrivilege->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED;
  73. }
  74. //
  75. // Initialize Object Attribute Structure.
  76. //
  77. InitializeObjectAttributes(&Obja,NULL,0L,NULL,NULL);
  78. //
  79. // Initialize Security Quality Of Service Structure
  80. //
  81. SecurityQofS.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  82. SecurityQofS.ImpersonationLevel = SecurityImpersonation;
  83. SecurityQofS.ContextTrackingMode = FALSE; // Snapshot client context
  84. SecurityQofS.EffectiveOnly = FALSE;
  85. Obja.SecurityQualityOfService = &SecurityQofS;
  86. //
  87. // Allocate storage for the structure that will hold the Previous State
  88. // information.
  89. //
  90. pPreviousState = LocalAlloc(LMEM_FIXED, PRIVILEGE_BUF_SIZE);
  91. if (pPreviousState == NULL) {
  92. status = GetLastError();
  93. IF_DEBUG(SECURITY) {
  94. NetpKdPrint(("NetpGetPrivilege: LocalAlloc Failed "FORMAT_DWORD"\n",
  95. status));
  96. }
  97. LocalFree(pTokenPrivilege);
  98. return(status);
  99. }
  100. //
  101. // Open our own Token
  102. //
  103. ntStatus = NtOpenProcessToken(
  104. NtCurrentProcess(),
  105. TOKEN_DUPLICATE,
  106. &ourToken);
  107. if (!NT_SUCCESS(ntStatus)) {
  108. IF_DEBUG(SECURITY) {
  109. NetpKdPrint(( "NetpGetPrivilege: NtOpenThreadToken Failed "
  110. "FORMAT_NTSTATUS" "\n", ntStatus));
  111. }
  112. LocalFree(pPreviousState);
  113. LocalFree(pTokenPrivilege);
  114. return(RtlNtStatusToDosError(ntStatus));
  115. }
  116. //
  117. // Duplicate that Token
  118. //
  119. ntStatus = NtDuplicateToken(
  120. ourToken,
  121. TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  122. &Obja,
  123. FALSE, // Duplicate the entire token
  124. TokenImpersonation, // TokenType
  125. &newToken); // Duplicate token
  126. if (!NT_SUCCESS(ntStatus)) {
  127. IF_DEBUG(SECURITY) {
  128. NetpKdPrint(( "NetpGetPrivilege: NtDuplicateToken Failed "
  129. "FORMAT_NTSTATUS" "\n", ntStatus));
  130. }
  131. LocalFree(pPreviousState);
  132. LocalFree(pTokenPrivilege);
  133. NtClose(ourToken);
  134. return(RtlNtStatusToDosError(ntStatus));
  135. }
  136. //
  137. // Add new privileges
  138. //
  139. bufLen = PRIVILEGE_BUF_SIZE;
  140. ntStatus = NtAdjustPrivilegesToken(
  141. newToken, // TokenHandle
  142. FALSE, // DisableAllPrivileges
  143. pTokenPrivilege, // NewState
  144. bufLen, // bufferSize for previous state
  145. pPreviousState, // pointer to previous state info
  146. &returnLen); // numBytes required for buffer.
  147. if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
  148. LocalFree(pPreviousState);
  149. bufLen = returnLen;
  150. pPreviousState = LocalAlloc(LMEM_FIXED, bufLen);
  151. ntStatus = NtAdjustPrivilegesToken(
  152. newToken, // TokenHandle
  153. FALSE, // DisableAllPrivileges
  154. pTokenPrivilege, // NewState
  155. bufLen, // bufferSize for previous state
  156. pPreviousState, // pointer to previous state info
  157. &returnLen); // numBytes required for buffer.
  158. }
  159. if (!NT_SUCCESS(ntStatus)) {
  160. IF_DEBUG(SECURITY) {
  161. NetpKdPrint(( "NetpGetPrivilege: NtAdjustPrivilegesToken Failed "
  162. "FORMAT_NTSTATUS" "\n", ntStatus));
  163. }
  164. LocalFree(pPreviousState);
  165. LocalFree(pTokenPrivilege);
  166. NtClose(ourToken);
  167. NtClose(newToken);
  168. return(RtlNtStatusToDosError(ntStatus));
  169. }
  170. //
  171. // Begin impersonating with the new token
  172. //
  173. ntStatus = NtSetInformationThread(
  174. NtCurrentThread(),
  175. ThreadImpersonationToken,
  176. (PVOID)&newToken,
  177. (ULONG)sizeof(HANDLE));
  178. if (!NT_SUCCESS(ntStatus)) {
  179. IF_DEBUG(SECURITY) {
  180. NetpKdPrint(( "NetpGetPrivilege: NtAdjustPrivilegesToken Failed "
  181. "FORMAT_NTSTATUS" "\n", ntStatus));
  182. }
  183. LocalFree(pPreviousState);
  184. LocalFree(pTokenPrivilege);
  185. NtClose(ourToken);
  186. NtClose(newToken);
  187. return(RtlNtStatusToDosError(ntStatus));
  188. }
  189. LocalFree(pPreviousState);
  190. LocalFree(pTokenPrivilege);
  191. NtClose(ourToken);
  192. NtClose(newToken);
  193. return(NO_ERROR);
  194. }
  195. DWORD
  196. NetpReleasePrivilege(
  197. VOID
  198. )
  199. /*++
  200. Routine Description:
  201. This function relinquishes privileges obtained by calling NetpGetPrivilege().
  202. Arguments:
  203. none
  204. Return Value:
  205. NO_ERROR - If the operation was completely successful.
  206. Otherwise, it returns mapped return codes from the various NT
  207. functions that are called.
  208. --*/
  209. {
  210. NTSTATUS ntStatus;
  211. HANDLE NewToken;
  212. //
  213. // Revert To Self.
  214. //
  215. NewToken = NULL;
  216. ntStatus = NtSetInformationThread(
  217. NtCurrentThread(),
  218. ThreadImpersonationToken,
  219. (PVOID)&NewToken,
  220. (ULONG)sizeof(HANDLE));
  221. if ( !NT_SUCCESS(ntStatus) ) {
  222. return(RtlNtStatusToDosError(ntStatus));
  223. }
  224. return(NO_ERROR);
  225. }