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.

436 lines
9.4 KiB

  1. // ----------------------------------------------------------------------------
  2. //
  3. // SecDescr.c
  4. //
  5. //
  6. // Author: Jost Eckhardt
  7. //
  8. // This code was written for ECO Kommunikation Insight
  9. // Copyright (c) 1997-1999 Microsoft Corporation
  10. // ----------------------------------------------------------------------------
  11. #include <windows.h>
  12. #include <stdlib.h>
  13. #include <malloc.h>
  14. #include <TCHAR.h>
  15. #include <WinSvc.h>
  16. #include "_UMTool.h"
  17. static PSECURITY_DESCRIPTOR GetObjectSecurityDescr(
  18. obj_sec_descr_tsp obj,
  19. DWORD dwAccessMaskOwner,
  20. DWORD dwAccessMaskLoggedOnUser);
  21. static BOOL GetUserSidFromToken(HANDLE hToken, PSID *ppSid);
  22. static BOOL GetGroupSidFromToken(HANDLE hToken, PSID *ppSid);
  23. // ---------------------------
  24. // InitSecurityAttributes - initialize the security descriptor in the
  25. // obj_sec_attr_tsp struct using a null DACL.
  26. //
  27. // Caller must call ClearSecurityAttributes when done with the struct.
  28. //
  29. void InitSecurityAttributes(obj_sec_attr_tsp psa)
  30. {
  31. memset(psa,0,sizeof(obj_sec_attr_ts));
  32. psa->sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  33. psa->sa.bInheritHandle = TRUE;
  34. psa->sa.lpSecurityDescriptor = GetObjectSecurityDescr(&psa->objsd, 0, 0);
  35. }
  36. // ---------------------------
  37. // InitSecurityAttributesEx - initialize the security descriptor in the
  38. // obj_sec_attr_tsp struct using a non-null DACL
  39. //
  40. // dwAccessMaskOwner - If non-zero specifies the access allowed to the creator
  41. // dwAccessMaskLoggedOnUser - If non-zero specifies the access allowed to the current user
  42. //
  43. // If dwAccessMaskOwner and dwAccessMaskLoggedOnUser are zero the security descriptor
  44. // will have a NULL DACL. Caller must call ClearSecurityAttributes when done
  45. // with the struct.
  46. //
  47. void InitSecurityAttributesEx(obj_sec_attr_tsp psa, DWORD dwAccessMaskOwner, DWORD dwAccessMaskLoggedOnUser)
  48. {
  49. memset(psa,0,sizeof(obj_sec_attr_ts));
  50. psa->sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  51. psa->sa.bInheritHandle = TRUE;
  52. psa->sa.lpSecurityDescriptor = GetObjectSecurityDescr(&psa->objsd, dwAccessMaskOwner, dwAccessMaskLoggedOnUser);
  53. }
  54. // ---------------------------
  55. // ClearSecurityAttributes - free memory from the security descriptor
  56. //
  57. void ClearSecurityAttributes(obj_sec_attr_tsp psa)
  58. {
  59. if (psa->sa.lpSecurityDescriptor)
  60. free(psa->sa.lpSecurityDescriptor);
  61. if (psa->objsd.psidUser)
  62. free(psa->objsd.psidUser);
  63. if (psa->objsd.psidGroup)
  64. free(psa->objsd.psidGroup);
  65. memset(psa,0,sizeof(obj_sec_attr_ts));
  66. }
  67. // ---------------------------
  68. static PSECURITY_DESCRIPTOR GetObjectSecurityDescr(
  69. obj_sec_descr_tsp obj,
  70. DWORD dwAccessMaskOwner,
  71. DWORD dwAccessMaskLoggedOnUser)
  72. {
  73. PSECURITY_DESCRIPTOR psd = NULL;
  74. HANDLE hToken;
  75. GENERIC_MAPPING gm = {1, 2, 4, 8};
  76. DWORD dwDesired = 1;
  77. BOOL fAccess = FALSE;
  78. DWORD dwGranted;
  79. PRIVILEGE_SET ps;
  80. DWORD cbPriv = sizeof (ps);
  81. PACL pAcl;
  82. ULONG cbAcl;
  83. PSID psidCurUser;
  84. obj->psidUser = obj->psidGroup = NULL;
  85. // Get the user's SID
  86. if (!ImpersonateSelf(SecurityImpersonation))
  87. return NULL;
  88. if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken))
  89. goto GSSD_ERROR;
  90. if (!GetUserSidFromToken(hToken, &obj->psidUser))
  91. goto GSSD_ERROR;
  92. // assumption: if either access masks are given
  93. // then the owner access mask must be given
  94. if (dwAccessMaskLoggedOnUser && !dwAccessMaskOwner)
  95. goto GSSD_ERROR;
  96. // Figure the size of an access-allowed ACL (if an
  97. // access mask is supplied there will be one ACE)
  98. cbAcl = 0;
  99. if (dwAccessMaskOwner)
  100. {
  101. cbAcl = sizeof(ACL)
  102. + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)
  103. + GetLengthSid(obj->psidUser);
  104. }
  105. psidCurUser = 0;
  106. if (dwAccessMaskLoggedOnUser)
  107. {
  108. psidCurUser = InteractiveUserSid(TRUE);
  109. if (psidCurUser)
  110. {
  111. cbAcl += sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)
  112. + GetLengthSid(psidCurUser);
  113. }
  114. }
  115. // Allocate space for the SD and the ACL
  116. psd = malloc(SECURITY_DESCRIPTOR_MIN_LENGTH + cbAcl);
  117. if (!psd)
  118. goto GSSD_ERROR;
  119. // Add ACEs to the ACL if specified
  120. pAcl = NULL;
  121. if (dwAccessMaskOwner)
  122. {
  123. // Point to the ACL in the security descriptor
  124. pAcl = (ACL *)((BYTE *)psd + SECURITY_DESCRIPTOR_MIN_LENGTH);
  125. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION))
  126. goto GSSD_ERROR;
  127. // Set access allowed for creator
  128. if (!AddAccessAllowedAce(pAcl,
  129. ACL_REVISION,
  130. dwAccessMaskOwner,
  131. obj->psidUser))
  132. goto GSSD_ERROR;
  133. // Set access allowed for everyone else
  134. if (psidCurUser)
  135. {
  136. if (!AddAccessAllowedAce(pAcl,
  137. ACL_REVISION,
  138. dwAccessMaskLoggedOnUser,
  139. psidCurUser))
  140. goto GSSD_ERROR;
  141. }
  142. }
  143. // Initialize the security descriptor etc...
  144. if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
  145. goto GSSD_ERROR;
  146. if (!SetSecurityDescriptorDacl(psd, TRUE, (dwAccessMaskOwner)?pAcl:NULL, FALSE))
  147. goto GSSD_ERROR;
  148. if (!SetSecurityDescriptorOwner(psd, obj->psidUser, FALSE))
  149. goto GSSD_ERROR;
  150. if (!GetGroupSidFromToken(hToken, &obj->psidGroup))
  151. goto GSSD_ERROR;
  152. if (!SetSecurityDescriptorGroup(psd, obj->psidGroup, FALSE))
  153. goto GSSD_ERROR;
  154. if (!AccessCheck(psd, hToken, dwDesired, &gm, &ps, &cbPriv,&dwGranted, &fAccess))
  155. goto GSSD_ERROR;
  156. RevertToSelf();
  157. return psd;
  158. GSSD_ERROR:
  159. if (psd)
  160. free(psd);
  161. if (obj->psidUser)
  162. free(obj->psidUser);
  163. if (obj->psidGroup)
  164. free(obj->psidGroup);
  165. RevertToSelf();
  166. return NULL;
  167. }
  168. // ----------------------------------------
  169. static BOOL GetGroupSidFromToken(HANDLE hToken, PSID *ppSid)
  170. {
  171. TOKEN_PRIMARY_GROUP *pGroup = NULL;
  172. PSID psidGroup = NULL;
  173. DWORD cbSid;
  174. DWORD cbRequired;
  175. if (GetTokenInformation(hToken, TokenPrimaryGroup, NULL, 0, &cbRequired))
  176. return FALSE;
  177. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  178. return FALSE;
  179. pGroup = malloc(cbRequired);
  180. if (!pGroup)
  181. return FALSE;
  182. if (!GetTokenInformation(hToken, TokenPrimaryGroup, pGroup,cbRequired, &cbRequired))
  183. goto GGSFT_ERROR;
  184. cbSid = GetLengthSid(pGroup->PrimaryGroup);
  185. psidGroup = malloc(cbSid);
  186. if (!psidGroup)
  187. goto GGSFT_ERROR;
  188. if (!CopySid(cbSid, psidGroup, pGroup->PrimaryGroup))
  189. goto GGSFT_ERROR;
  190. *ppSid = psidGroup;
  191. psidGroup = NULL;
  192. return TRUE;
  193. GGSFT_ERROR:
  194. if (psidGroup)
  195. free(psidGroup);
  196. free(pGroup);
  197. return FALSE;
  198. }
  199. // ----------------------------------------
  200. static BOOL GetUserSidFromToken(HANDLE hToken, PSID *ppSid)
  201. {
  202. TOKEN_USER *pUser = NULL;
  203. PSID psidUser = NULL;
  204. DWORD cbSid;
  205. DWORD cbRequired;
  206. if (GetTokenInformation(hToken, TokenUser, NULL, 0, &cbRequired))
  207. return FALSE;
  208. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  209. return FALSE;
  210. pUser = malloc(cbRequired);
  211. if (!pUser)
  212. return FALSE;
  213. if (!GetTokenInformation(hToken, TokenUser, pUser, cbRequired,&cbRequired))
  214. goto GUSFT_ERROR;
  215. cbSid = GetLengthSid(pUser->User.Sid);
  216. psidUser = malloc(cbSid);
  217. if (!psidUser)
  218. goto GUSFT_ERROR;
  219. if (!CopySid(cbSid, psidUser, pUser->User.Sid))
  220. goto GUSFT_ERROR;
  221. *ppSid = psidUser;
  222. psidUser = NULL;
  223. return TRUE;
  224. GUSFT_ERROR:
  225. if (psidUser)
  226. free(psidUser);
  227. free(pUser);
  228. return FALSE;
  229. }
  230. PSID EveryoneSid(BOOL fFetch)
  231. {
  232. static PSID psidEverybody = 0;
  233. SID_IDENTIFIER_AUTHORITY siaEverybody = SECURITY_WORLD_SID_AUTHORITY;
  234. BOOL fRv = FALSE;
  235. if (!fFetch)
  236. {
  237. if (psidEverybody)
  238. {
  239. FreeSid(psidEverybody);
  240. psidEverybody = 0;
  241. }
  242. return 0;
  243. }
  244. if (!psidEverybody)
  245. {
  246. if (!AllocateAndInitializeSid(
  247. &siaEverybody,
  248. 1,
  249. SECURITY_WORLD_RID,
  250. 0, 0, 0, 0, 0, 0, 0,
  251. &psidEverybody
  252. ))
  253. {
  254. psidEverybody = 0;
  255. }
  256. }
  257. return psidEverybody;
  258. }
  259. PSID AdminSid(BOOL fFetch)
  260. {
  261. static PSID psidAdmin = 0;
  262. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  263. BOOL fRv = FALSE;
  264. if (!fFetch)
  265. {
  266. if (psidAdmin)
  267. {
  268. FreeSid(psidAdmin);
  269. psidAdmin = 0;
  270. }
  271. return 0;
  272. }
  273. if (!psidAdmin)
  274. {
  275. if (!AllocateAndInitializeSid(&siaNtAuthority,
  276. 2,
  277. SECURITY_BUILTIN_DOMAIN_RID,
  278. DOMAIN_ALIAS_RID_ADMINS,
  279. 0, 0, 0, 0, 0, 0,
  280. &psidAdmin))
  281. {
  282. psidAdmin = 0;
  283. }
  284. }
  285. return psidAdmin;
  286. }
  287. PSID InteractiveUserSid(BOOL fFetch)
  288. {
  289. static PSID psidInteractiveUser = 0;
  290. SID_IDENTIFIER_AUTHORITY siaLocalSystem = SECURITY_NT_AUTHORITY;
  291. BOOL fRv = FALSE;
  292. if (!fFetch)
  293. {
  294. if (psidInteractiveUser)
  295. {
  296. FreeSid(psidInteractiveUser);
  297. psidInteractiveUser = 0;
  298. }
  299. return 0;
  300. }
  301. if (!psidInteractiveUser)
  302. {
  303. if (!AllocateAndInitializeSid(&siaLocalSystem,
  304. 1,
  305. SECURITY_INTERACTIVE_RID,
  306. 0, 0, 0, 0, 0, 0, 0,
  307. &psidInteractiveUser))
  308. {
  309. psidInteractiveUser = 0;
  310. }
  311. }
  312. return psidInteractiveUser;
  313. }
  314. PSID SystemSid(BOOL fFetch)
  315. {
  316. static PSID psidSystem = 0;
  317. SID_IDENTIFIER_AUTHORITY siaLocalSystem = SECURITY_NT_AUTHORITY;
  318. BOOL fRv = FALSE;
  319. if (!fFetch)
  320. {
  321. if (psidSystem)
  322. {
  323. FreeSid(psidSystem);
  324. psidSystem = 0;
  325. }
  326. return 0;
  327. }
  328. if (!psidSystem)
  329. {
  330. if (!AllocateAndInitializeSid(&siaLocalSystem,
  331. 1,
  332. SECURITY_LOCAL_SYSTEM_RID,
  333. 0, 0, 0, 0, 0, 0, 0,
  334. &psidSystem))
  335. {
  336. psidSystem = 0;
  337. }
  338. }
  339. return psidSystem;
  340. }
  341. void InitWellknownSids()
  342. {
  343. EveryoneSid(TRUE);
  344. AdminSid(TRUE);
  345. InteractiveUserSid(TRUE);
  346. SystemSid(TRUE);
  347. }
  348. void UninitWellknownSids()
  349. {
  350. EveryoneSid(FALSE);
  351. AdminSid(FALSE);
  352. InteractiveUserSid(FALSE);
  353. SystemSid(FALSE);
  354. }