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.

611 lines
14 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. priv.c
  5. Abstract:
  6. This module provides a command capability to enable and disable
  7. privileges. This command is expected to be an internal cmd.exe
  8. command, but is expected to be passed parameters as if it were
  9. an external command.
  10. THIS IS A TEMPORARY COMMAND. IF IT IS DESIRED TO MAKE THIS A
  11. PERMANENT COMMAND, THEN THIS FILE NEEDS TO BE GONE THROUGH WITH
  12. A FINE-TOOTH COMB TO ROBUSTLY HANDLE ALL ERROR SITUATIONS AND TO
  13. PROVIDE APPROPRIATE ERROR MESSAGES.
  14. Author:
  15. Jim Kelly 1-Apr-1991.
  16. Revision History:
  17. --*/
  18. #include <nt.h>
  19. #include <ntrtl.h>
  20. //#include <sys\types.h>
  21. //#include <sys\stat.h>
  22. //#include <malloc.h>
  23. //#include <stdlib.h>
  24. //#include <ctype.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. //#include <tools.h>
  28. //
  29. // command qualifier flag values
  30. //
  31. BOOLEAN SwitchEnable = FALSE;
  32. BOOLEAN SwitchDisable = FALSE;
  33. BOOLEAN SwitchReset = FALSE;
  34. BOOLEAN SwitchAll = FALSE;
  35. #ifndef SHIFT
  36. #define SHIFT(c,v) {c--; v++;}
  37. #endif //SHIFT
  38. //
  39. // Function definitions...
  40. //
  41. VOID
  42. Usage ( VOID );
  43. BOOLEAN
  44. OpenAppropriateToken(
  45. OUT PHANDLE Token
  46. );
  47. VOID
  48. EnableAllPrivileges( VOID );
  49. VOID
  50. ResetAllPrivileges( VOID );
  51. VOID
  52. DisableAllPrivileges( VOID );
  53. int
  54. PrivMain (
  55. IN int c,
  56. IN PCHAR v[]
  57. );
  58. VOID
  59. Usage (
  60. VOID
  61. )
  62. /*++
  63. Routine Description:
  64. This routine prints the "Usage:" message.
  65. Arguments:
  66. None.
  67. Return Value:
  68. None.
  69. --*/
  70. {
  71. printf( "\n");
  72. printf( "\n");
  73. printf( "Usage: priv [/EDRA] {PrivilegeName}\n");
  74. printf( " /E - Enable Privilege(s)\n");
  75. printf( " /D - Disable Privilege(s)\n");
  76. printf( " /R - Reset to default setting(s)\n");
  77. printf( " /A - Apply To All Privileges\n");
  78. printf( "\n");
  79. printf( " The qualifiers /E and /D are mutually exclusive and can not\n");
  80. printf( " be used in the same command.\n");
  81. printf( " If /A is specified, then the PrivilegeName is ignored.\n");
  82. printf( "\n");
  83. printf( "\n");
  84. printf( "Examples:\n");
  85. printf( "\n");
  86. printf( " priv /ae\n");
  87. printf( " (enables all held privileges.\n");
  88. printf( "\n");
  89. printf( " priv /ad\n");
  90. printf( " disables all held privileges.\n");
  91. printf( "\n");
  92. printf( " priv /ar\n");
  93. printf( " (returns all privileges to their default setting.\n");
  94. printf( "\n");
  95. printf( " priv /e SeSetTimePrivilege\n");
  96. printf( " (enables the privileges called: SeSetTimePrivilege\n");
  97. printf( "\n");
  98. printf( "\n");
  99. return;
  100. }
  101. BOOLEAN
  102. OpenAppropriateToken(
  103. OUT PHANDLE Token
  104. )
  105. /*++
  106. Routine Description:
  107. This routine opens the appropriate TOKEN object. For an internal
  108. command, this is the current process's token. If this command is
  109. ever made external, then it will be the parent process's token.
  110. If the token can't be openned, then a messages is printed indicating
  111. a problem has been encountered.
  112. The caller is expected to close this token when no longer needed.
  113. Arguments:
  114. Token - Receives the handle value of the openned token.
  115. Return Value:
  116. TRUE - Indicates the token was successfully openned.
  117. FALSE - Indicates the token was NOT successfully openned.
  118. --*/
  119. {
  120. NTSTATUS Status, IgnoreStatus;
  121. OBJECT_ATTRIBUTES ProcessAttributes;
  122. HANDLE Process;
  123. PTEB CurrentTeb;
  124. CurrentTeb = NtCurrentTeb();
  125. InitializeObjectAttributes(&ProcessAttributes, NULL, 0, NULL, NULL);
  126. Status = NtOpenProcess(
  127. &Process, // TargetHandle
  128. PROCESS_QUERY_INFORMATION, // DesiredAccess
  129. &ProcessAttributes, // ObjectAttributes
  130. &CurrentTeb->ClientId // ClientId
  131. );
  132. if (NT_SUCCESS(Status)) {
  133. Status = NtOpenProcessToken(
  134. Process,
  135. TOKEN_ADJUST_PRIVILEGES |
  136. TOKEN_QUERY,
  137. Token
  138. );
  139. IgnoreStatus = NtClose( Process );
  140. if ( NT_SUCCESS(Status) ) {
  141. return TRUE;
  142. }
  143. }
  144. printf( "\n");
  145. printf( "\n");
  146. printf( "You are not allowed to change your own privilege settings.\n");
  147. printf( "Operation failed.\n");
  148. return FALSE;
  149. }
  150. VOID
  151. EnableAllPrivileges(
  152. VOID
  153. )
  154. /*++
  155. Routine Description:
  156. This routine enables all privileges in the token.
  157. Arguments:
  158. None.
  159. Return Value:
  160. None.
  161. --*/
  162. {
  163. NTSTATUS Status;
  164. HANDLE Token;
  165. ULONG ReturnLength, Index;
  166. PTOKEN_PRIVILEGES NewState;
  167. if ( !OpenAppropriateToken(&Token) ) {
  168. return;
  169. }
  170. //
  171. // Get the size needed to query current privilege settings...
  172. //
  173. Status = NtQueryInformationToken(
  174. Token, // TokenHandle
  175. TokenPrivileges, // TokenInformationClass
  176. NewState, // TokenInformation
  177. 0, // TokenInformationLength
  178. &ReturnLength // ReturnLength
  179. );
  180. ASSERT( Status == STATUS_BUFFER_TOO_SMALL );
  181. NewState = RtlAllocateHeap( RtlProcessHeap(), 0, ReturnLength );
  182. ASSERT( NewState != NULL );
  183. Status = NtQueryInformationToken(
  184. Token, // TokenHandle
  185. TokenPrivileges, // TokenInformationClass
  186. NewState, // TokenInformation
  187. ReturnLength, // TokenInformationLength
  188. &ReturnLength // ReturnLength
  189. );
  190. ASSERT( NT_SUCCESS(Status) || NT_INFORMATION(Status) );
  191. //
  192. // Set the state settings so that all privileges are enabled...
  193. //
  194. if (NewState->PrivilegeCount > 0) {
  195. Index = NewState->PrivilegeCount;
  196. while (Index < NewState->PrivilegeCount) {
  197. NewState->Privileges[Index].Attributes = SE_PRIVILEGE_ENABLED;
  198. Index += 1;
  199. }
  200. }
  201. //
  202. // Change the settings in the token...
  203. //
  204. Status = NtAdjustPrivilegesToken(
  205. Token, // TokenHandle
  206. FALSE, // DisableAllPrivileges
  207. NewState, // NewState (OPTIONAL)
  208. ReturnLength, // BufferLength
  209. NULL, // PreviousState (OPTIONAL)
  210. &ReturnLength // ReturnLength
  211. );
  212. ASSERT( NT_SUCCESS(Status) || NT_INFORMATION(Status) );
  213. RtlFreeHeap( RtlProcessHeap(), 0, NewState );
  214. Status = NtClose( Token );
  215. return;
  216. }
  217. VOID
  218. ResetAllPrivileges(
  219. VOID
  220. )
  221. /*++
  222. Routine Description:
  223. This routine resets all privileges in the token to their default state.
  224. Arguments:
  225. None.
  226. Return Value:
  227. None.
  228. --*/
  229. {
  230. NTSTATUS Status;
  231. HANDLE Token;
  232. ULONG ReturnLength, Index;
  233. PTOKEN_PRIVILEGES NewState;
  234. if ( !OpenAppropriateToken(&Token) ) {
  235. printf( "\n");
  236. printf( "\n");
  237. printf( "You are not allowed to change your own privilege settings.\n");
  238. printf( "Operation failed.\n");
  239. return;
  240. }
  241. //
  242. // Get the size needed to query current privilege settings...
  243. //
  244. Status = NtQueryInformationToken(
  245. Token, // TokenHandle
  246. TokenPrivileges, // TokenInformationClass
  247. NewState, // TokenInformation
  248. 0, // TokenInformationLength
  249. &ReturnLength // ReturnLength
  250. );
  251. ASSERT( STATUS_BUFFER_TOO_SMALL );
  252. NewState = RtlAllocateHeap( RtlProcessHeap(), 0, ReturnLength );
  253. ASSERT( NewState != NULL );
  254. Status = NtQueryInformationToken(
  255. Token, // TokenHandle
  256. TokenPrivileges, // TokenInformationClass
  257. NewState, // TokenInformation
  258. ReturnLength, // TokenInformationLength
  259. &ReturnLength // ReturnLength
  260. );
  261. ASSERT( NT_SUCCESS(Status) || NT_INFORMATION(Status) );
  262. //
  263. // Set the state settings so that all privileges are reset to
  264. // their default settings...
  265. //
  266. if (NewState->PrivilegeCount > 0) {
  267. Index = NewState->PrivilegeCount;
  268. while (Index < NewState->PrivilegeCount) {
  269. if (NewState->Privileges[Index].Attributes ==
  270. SE_PRIVILEGE_ENABLED_BY_DEFAULT) {
  271. NewState->Privileges[Index].Attributes = SE_PRIVILEGE_ENABLED;
  272. }
  273. else {
  274. NewState->Privileges[Index].Attributes = 0;
  275. }
  276. Index += 1;
  277. }
  278. }
  279. //
  280. // Change the settings in the token...
  281. //
  282. Status = NtAdjustPrivilegesToken(
  283. Token, // TokenHandle
  284. FALSE, // DisableAllPrivileges
  285. NewState, // NewState (OPTIONAL)
  286. ReturnLength, // BufferLength
  287. NULL, // PreviousState (OPTIONAL)
  288. &ReturnLength // ReturnLength
  289. );
  290. ASSERT( NT_SUCCESS(Status) || NT_INFORMATION(Status) );
  291. RtlFreeHeap( RtlProcessHeap(), 0, NewState );
  292. Status = NtClose( Token );
  293. return;
  294. }
  295. VOID
  296. DisableAllPrivileges(
  297. VOID
  298. )
  299. /*++
  300. Routine Description:
  301. This routine disables all privileges in the token.
  302. Arguments:
  303. None.
  304. Return Value:
  305. None.
  306. --*/
  307. {
  308. ULONG IgnoredReturnLength;
  309. HANDLE Token;
  310. NTSTATUS Status;
  311. if ( !OpenAppropriateToken(&Token) ) {
  312. printf( "\n");
  313. printf( "\n");
  314. printf( "You are not allowed to change your own privilege settings.\n");
  315. printf( "Operation failed.\n");
  316. return;
  317. }
  318. //
  319. // Disable all the privileges.
  320. //
  321. Status = NtAdjustPrivilegesToken(
  322. Token, // TokenHandle
  323. TRUE, // DisableAllPrivileges
  324. NULL, // NewState (OPTIONAL)
  325. 0, // BufferLength
  326. NULL, // PreviousState (OPTIONAL)
  327. &IgnoredReturnLength // ReturnLength
  328. );
  329. ASSERT( NT_SUCCESS(Status) || NT_INFORMATION(Status) );
  330. Status = NtClose( Token );
  331. return;
  332. }
  333. int
  334. PrivMain (
  335. IN int c,
  336. IN PCHAR v[]
  337. )
  338. /*++
  339. Routine Description:
  340. This routine is the main entry routine for the "priv" command.
  341. Arguments:
  342. TBS
  343. Return Value:
  344. TBS
  345. --*/
  346. {
  347. PCHAR p;
  348. CHAR ch;
  349. ULONG DispositionDirectives;
  350. try {
  351. DispositionDirectives = 0;
  352. SHIFT (c,v);
  353. while ((c > 0) && ((ch = *v[0]))) {
  354. p = *v;
  355. if (ch == '/') {
  356. while (*++p != '\0') {
  357. if (*p == 'E') {
  358. SwitchEnable = TRUE;
  359. DispositionDirectives += 1;
  360. }
  361. if (*p == 'D') {
  362. SwitchDisable = TRUE;
  363. DispositionDirectives += 1;
  364. }
  365. if (*p == 'R') {
  366. SwitchReset = TRUE;
  367. DispositionDirectives += 1;
  368. }
  369. else if (*p == 'A') {
  370. SwitchAll = TRUE;
  371. }
  372. else {
  373. Usage();
  374. }
  375. }
  376. SHIFT(c,v);
  377. }
  378. }
  379. //
  380. // Make sure we don't have conflicting parameters
  381. //
  382. // Rules:
  383. //
  384. // If /A isn't specified, then a privilege name must be.
  385. // Exactly one of /E, /D, and /R must be specified.
  386. //
  387. //
  388. if (!SwitchAll && (c == 0)) {
  389. printf( "\n");
  390. printf( "\n");
  391. printf( "You must provide privilege name or use the /A switch.\n");
  392. Usage();
  393. return ( 0 );
  394. }
  395. if (DispositionDirectives != 1) {
  396. printf( "\n");
  397. printf( "\n");
  398. printf( "You must provide one and only one of the following");
  399. printf( "switches: /E, /D, /R\n");
  400. Usage();
  401. return ( 0 );
  402. }
  403. //
  404. // Everything appears legitimate
  405. //
  406. if (SwitchAll) {
  407. //
  408. // /A switch specified
  409. //
  410. if (SwitchEnable) {
  411. EnableAllPrivileges();
  412. }
  413. else if (SwitchDisable) {
  414. DisableAllPrivileges();
  415. }
  416. else {
  417. ResetAllPrivileges();
  418. }
  419. }
  420. //
  421. // privilege name specified...
  422. //
  423. else {
  424. printf( "\n");
  425. printf( "I'm sorry, but due to the lack of time and interest,\n");
  426. printf( "individual privilege selection is not yet supported.\n");
  427. printf( "Please use the /A qualifier for the time being.\n");
  428. printf( "\n");
  429. }
  430. } finally {
  431. return ( 0 );
  432. }
  433. return( 0 );
  434. }