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.

472 lines
12 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: security.c
  3. *
  4. * Copyright (c) 1992, Microsoft Corporation
  5. *
  6. * Handles security aspects of progman operation.
  7. *
  8. * History:
  9. * 01-16-92 JohanneC Created - mostly taken from old winlogon.c
  10. \***************************************************************************/
  11. #include "sec.h"
  12. #include <string.h>
  13. #include <fcntl.h>
  14. #include <io.h>
  15. #include <stdio.h>
  16. #include <lm.h>
  17. /***************************************************************************\
  18. * SetMyAce
  19. *
  20. * Helper routine that fills in a MYACE structure.
  21. *
  22. * History:
  23. * 02-06-92 Davidc Created
  24. \***************************************************************************/
  25. VOID
  26. SetMyAce(
  27. PMYACE MyAce,
  28. PSID Sid,
  29. ACCESS_MASK Mask,
  30. UCHAR InheritFlags
  31. )
  32. {
  33. MyAce->Sid = Sid;
  34. MyAce->AccessMask= Mask;
  35. MyAce->InheritFlags = InheritFlags;
  36. }
  37. /***************************************************************************\
  38. * SetWorldSecurity
  39. *
  40. * Sets the security given the logon sid passed.
  41. *
  42. * If the UserSid = NULL, no access is given to anyone other than world
  43. * Users will have read access and if bWriteAccess is TRUE, they will also
  44. * have write access.
  45. *
  46. * Returns TRUE on success, FALSE on failure
  47. *
  48. * History:
  49. * 04-16-91 Johannec Created
  50. \***************************************************************************/
  51. BOOL
  52. SetWorldSecurity(
  53. PSID UserSid,
  54. PSECURITY_DESCRIPTOR *pSecDesc,
  55. BOOL bWriteAccess
  56. )
  57. {
  58. MYACE Ace[4];
  59. ACEINDEX AceCount = 0;
  60. PSECURITY_DESCRIPTOR SecurityDescriptor;
  61. PSID WorldSid = NULL;
  62. PSID AdminAliasSid = NULL;
  63. PSID PowerUserAliasSid = NULL;
  64. PSID SystemOpsAliasSid = NULL;
  65. SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
  66. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  67. NTSTATUS Status;
  68. ACCESS_MASK AccessMask;
  69. // Create the world Sid
  70. Status = RtlAllocateAndInitializeSid(
  71. &WorldSidAuthority,
  72. 1, // Sub authority count
  73. SECURITY_WORLD_RID, // Sub authorities
  74. 0, 0, 0, 0, 0, 0, 0,
  75. &WorldSid);
  76. if (!NT_SUCCESS(Status)) {
  77. DbgOnlyPrint("progman failed to allocate memory for world sid\n");
  78. return(FALSE);
  79. }
  80. Status = RtlAllocateAndInitializeSid(
  81. &NtAuthority,
  82. 2, // Sub authority count
  83. SECURITY_BUILTIN_DOMAIN_RID, // Sub authority[0]
  84. DOMAIN_ALIAS_RID_ADMINS, // Sub authority[1]
  85. 0, 0, 0, 0, 0, 0,
  86. &AdminAliasSid);
  87. Status = RtlAllocateAndInitializeSid(
  88. &NtAuthority,
  89. 2, // Sub authority count
  90. SECURITY_BUILTIN_DOMAIN_RID, // Sub authority[0]
  91. DOMAIN_ALIAS_RID_POWER_USERS, // Sub authority[1]
  92. 0, 0, 0, 0, 0, 0,
  93. &PowerUserAliasSid);
  94. Status = RtlAllocateAndInitializeSid(
  95. &NtAuthority,
  96. 2, // Sub authority count
  97. SECURITY_BUILTIN_DOMAIN_RID, // Sub authority[0]
  98. DOMAIN_ALIAS_RID_SYSTEM_OPS, // Sub authority[1]
  99. 0, 0, 0, 0, 0, 0,
  100. &SystemOpsAliasSid);
  101. if (!NT_SUCCESS(Status)) {
  102. DbgOnlyPrint("progman failed to allocate memory for admin sid\n");
  103. return(FALSE);
  104. }
  105. //
  106. // Define the World ACEs
  107. //
  108. if (bWriteAccess) {
  109. AccessMask = KEY_READ | KEY_WRITE | DELETE;
  110. }
  111. else {
  112. AccessMask = KEY_READ;
  113. }
  114. SetMyAce(&(Ace[AceCount++]),
  115. WorldSid,
  116. AccessMask,
  117. NO_PROPAGATE_INHERIT_ACE
  118. );
  119. //
  120. // Define the Admins ACEs
  121. //
  122. SetMyAce(&(Ace[AceCount++]),
  123. AdminAliasSid,
  124. GENERIC_ALL,
  125. NO_PROPAGATE_INHERIT_ACE
  126. );
  127. //
  128. // Define the Power Users ACEs
  129. //
  130. SetMyAce(&(Ace[AceCount++]),
  131. PowerUserAliasSid,
  132. GENERIC_ALL,
  133. NO_PROPAGATE_INHERIT_ACE
  134. );
  135. //
  136. // Define the System Operators ACEs
  137. //
  138. SetMyAce(&(Ace[AceCount++]),
  139. SystemOpsAliasSid,
  140. GENERIC_ALL,
  141. NO_PROPAGATE_INHERIT_ACE
  142. );
  143. // Check we didn't goof
  144. ASSERT((sizeof(Ace) / sizeof(MYACE)) >= AceCount);
  145. //
  146. // Create the security descriptor
  147. //
  148. SecurityDescriptor = CreateSecurityDescriptor(Ace, AceCount);
  149. if (SecurityDescriptor == NULL) {
  150. DbgOnlyPrint("Progman failed to create security descriptor\n\r");
  151. return(FALSE);
  152. }
  153. #if 0
  154. // Keep security descriptor global
  155. // delete only when exiting the program
  156. //
  157. // Free up the security descriptor
  158. //
  159. DeleteSecurityDescriptor(SecurityDescriptor);
  160. #endif
  161. //
  162. // Return success status
  163. //
  164. *pSecDesc = SecurityDescriptor;
  165. return(TRUE);
  166. }
  167. /***************************************************************************\
  168. * InitializeSecurityAttributes
  169. *
  170. *
  171. * Returns TRUE on success, FALSE on failure
  172. *
  173. * History:
  174. * 04-14-92 JohanneC Created
  175. \***************************************************************************/
  176. BOOL InitializeSecurityAttributes(PSECURITY_ATTRIBUTES pSecurityAttributes,
  177. BOOL bWriteAccess)
  178. {
  179. PSECURITY_DESCRIPTOR pSecDesc;
  180. if (!SetWorldSecurity(NULL, &pSecDesc, bWriteAccess)) {
  181. return(FALSE);
  182. }
  183. pSecurityAttributes->nLength = sizeof(SECURITY_ATTRIBUTES);
  184. pSecurityAttributes->lpSecurityDescriptor = pSecDesc;
  185. pSecurityAttributes->bInheritHandle = TRUE;
  186. return(TRUE);
  187. }
  188. BOOL
  189. TestTokenForAdmin(
  190. HANDLE Token
  191. );
  192. /***************************************************************************\
  193. * TestUserForAdmin
  194. *
  195. *
  196. * Returns TRUE if the current user is part of the ADMIN group,
  197. * FALSE otherwise
  198. *
  199. * History:
  200. * 07-15-92 JohanneC Created
  201. \***************************************************************************/
  202. BOOL TestUserForAdmin()
  203. {
  204. BOOL UserIsAdmin = FALSE;
  205. HANDLE Token;
  206. #if 0
  207. ACCESS_MASK GrantedAccess;
  208. GENERIC_MAPPING GenericMapping;
  209. PPRIVILEGE_SET pPrivilegeSet;
  210. DWORD dwPrivilegeSetLength;
  211. MYACE Ace[1];
  212. PSECURITY_DESCRIPTOR pSecDesc;
  213. NTSTATUS Status;
  214. #endif
  215. PSID AdminAliasSid = NULL;
  216. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  217. //
  218. // Get the token of the current process.
  219. //
  220. if (!OpenProcessToken(
  221. GetCurrentProcess(),
  222. TOKEN_QUERY,
  223. &Token
  224. ) ) {
  225. DbgOnlyPrint("Progman: Can't open own process token for token_query access\n\r");
  226. return(FALSE);
  227. }
  228. #if 0
  229. // not working because of error = STATUS_NO_IMPERSONATION_TOKEN
  230. so use the code from winlogon instead (see #else)
  231. Status = RtlAllocateAndInitializeSid(
  232. &NtAuthority,
  233. 2, // Sub authority count
  234. SECURITY_BUILTIN_DOMAIN_RID, // Sub authority[0]
  235. DOMAIN_ALIAS_RID_ADMINS, // Sub authority[1]
  236. 0, 0, 0, 0, 0, 0,
  237. &AdminAliasSid);
  238. if (!NT_SUCCESS(Status)) {
  239. DbgOnlyPrint(TEXT("progman failed to allocate memory for admin sid\n"));
  240. goto Exit;
  241. }
  242. //
  243. // Define the Admins ACEs
  244. //
  245. SetMyAce(&(Ace[0]),
  246. AdminAliasSid,
  247. GENERIC_ALL,
  248. NO_PROPAGATE_INHERIT_ACE
  249. );
  250. //
  251. // Create the security descriptor
  252. //
  253. pSecDesc = CreateSecurityDescriptor(Ace, 1);
  254. if (pSecDesc == NULL) {
  255. DbgOnlyPrint(TEXT("Progman failed to create security descriptor\n\r"));
  256. goto Exit;
  257. }
  258. //
  259. // Allocate memory for the PrivilegeSet buffer
  260. //
  261. dwPrivilegeSetLength = 256;
  262. pPrivilegeSet = Alloc(dwPrivilegeSetLength);
  263. if (!pPrivilegeSet) {
  264. DbgOnlyPrint(TEXT("Progman: Can't alloc memory for privilege set\n\r"));
  265. goto FreeSecDesc;
  266. }
  267. //
  268. // Test if user has admin privileges.
  269. //
  270. if(!AccessCheck(pSecDesc,
  271. Token,
  272. STANDARD_RIGHTS_ALL,
  273. &GenericMapping,
  274. pPrivilegeSet,
  275. &dwPrivilegeSetLength,
  276. &GrantedAccess,
  277. &UserIsAdmin) ){
  278. DbgOnlyPrint(TEXT("Progman: AccessCheck failed, error = %d\n\r"), GetLastError());
  279. }
  280. //
  281. // Free up the the PrivilegeSet
  282. //
  283. Free(pPrivilegeSet);
  284. FreeSecDesc:
  285. //
  286. // Free up the security descriptor
  287. //
  288. DeleteSecurityDescriptor(pSecDesc);
  289. #else
  290. UserIsAdmin = TestTokenForAdmin(Token);
  291. #endif
  292. //Exit:
  293. //
  294. // We are finished with the token.
  295. //
  296. CloseHandle(Token);
  297. return(UserIsAdmin);
  298. }
  299. /***************************************************************************\
  300. * TestTokenForAdmin
  301. *
  302. * Returns TRUE if the token passed represents an admin user, otherwise FALSE
  303. *
  304. * The token handle passed must have TOKEN_QUERY access.
  305. *
  306. * History:
  307. * 08-01-92 JohanneC Extracted code from winlogon
  308. * 05-06-92 Davidc Created
  309. \***************************************************************************/
  310. BOOL
  311. TestTokenForAdmin(
  312. HANDLE Token
  313. )
  314. {
  315. NTSTATUS Status;
  316. DWORD InfoLength;
  317. PTOKEN_GROUPS TokenGroupList;
  318. DWORD GroupIndex;
  319. PSID AdminSid;
  320. BOOL FoundAdmin;
  321. SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
  322. //
  323. // Get a list of groups in the token
  324. //
  325. Status = NtQueryInformationToken(
  326. Token, // Handle
  327. TokenGroups, // TokenInformationClass
  328. NULL, // TokenInformation
  329. 0, // TokenInformationLength
  330. &InfoLength // ReturnLength
  331. );
  332. if ((Status != STATUS_SUCCESS) && (Status != STATUS_BUFFER_TOO_SMALL)) {
  333. DbgOnlyPrint("Winlogon failed to get group info for admin token, status = 0x%lx\n", Status);
  334. return(FALSE);
  335. }
  336. TokenGroupList = Alloc(InfoLength);
  337. if (TokenGroupList == NULL) {
  338. DbgOnlyPrint("Winlogon unable to allocate memory for token groups\n");
  339. return(FALSE);
  340. }
  341. Status = NtQueryInformationToken(
  342. Token, // Handle
  343. TokenGroups, // TokenInformationClass
  344. TokenGroupList, // TokenInformation
  345. InfoLength, // TokenInformationLength
  346. &InfoLength // ReturnLength
  347. );
  348. if (!NT_SUCCESS(Status)) {
  349. DbgOnlyPrint("Winlogon failed to query groups for admin token, status = 0x%lx\n", Status);
  350. Free(TokenGroupList);
  351. return(FALSE);
  352. }
  353. //
  354. // Create the admin sid
  355. //
  356. Status = RtlAllocateAndInitializeSid(
  357. &SystemSidAuthority, 2,
  358. SECURITY_BUILTIN_DOMAIN_RID,
  359. DOMAIN_ALIAS_RID_ADMINS,
  360. 0, 0, 0, 0, 0, 0,
  361. &AdminSid);
  362. if (!NT_SUCCESS(Status)) {
  363. DbgOnlyPrint("Winlogon failed to initialize admin alias sid\n");
  364. Free(TokenGroupList);
  365. return(FALSE);
  366. }
  367. //
  368. // Search group list for admin alias
  369. //
  370. FoundAdmin = FALSE;
  371. for (GroupIndex=0; GroupIndex < TokenGroupList->GroupCount; GroupIndex++ ) {
  372. if (RtlEqualSid(TokenGroupList->Groups[GroupIndex].Sid, AdminSid)) {
  373. FoundAdmin = TRUE;
  374. break;
  375. }
  376. }
  377. //
  378. // Tidy up
  379. //
  380. RtlFreeSid(AdminSid);
  381. Free(TokenGroupList);
  382. return(FoundAdmin);
  383. }