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.

446 lines
9.7 KiB

  1. /*
  2. * AclNt.c
  3. *
  4. * Author: BreenH
  5. *
  6. * Acl utilities in the NT flavor.
  7. */
  8. /*
  9. * Includes
  10. */
  11. #include "precomp.h"
  12. #include "tsutilnt.h"
  13. /*
  14. * Function Implementations
  15. */
  16. NTSTATUS NTAPI
  17. NtConvertAbsoluteToSelfRelative(
  18. PSECURITY_DESCRIPTOR *ppSelfRelativeSd,
  19. PSECURITY_DESCRIPTOR pAbsoluteSd,
  20. PULONG pcbSelfRelativeSd
  21. )
  22. {
  23. #if DBG
  24. BOOLEAN fAbsoluteSd;
  25. #endif
  26. NTSTATUS Status;
  27. PSECURITY_DESCRIPTOR pSd;
  28. ULONG cbSd;
  29. ASSERT(ppSelfRelativeSd != NULL);
  30. ASSERT(pAbsoluteSd != NULL);
  31. ASSERT(NT_SUCCESS(NtIsSecurityDescriptorAbsolute(pAbsoluteSd,
  32. &fAbsoluteSd)));
  33. ASSERT(fAbsoluteSd);
  34. //
  35. // Determine the buffer size needed to convert the security descriptor.
  36. // Catch any exceptions due to an invalid descriptor.
  37. //
  38. cbSd = 0;
  39. __try
  40. {
  41. Status = RtlAbsoluteToSelfRelativeSD(
  42. pAbsoluteSd,
  43. NULL,
  44. &cbSd
  45. );
  46. }
  47. __except(EXCEPTION_EXECUTE_HANDLER)
  48. {
  49. return(STATUS_INVALID_SECURITY_DESCR);
  50. }
  51. //
  52. // Allocate memory for the self-relative security descriptor.
  53. //
  54. pSd = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, cbSd);
  55. if (pSd != NULL)
  56. {
  57. //
  58. // Now convert the security descriptor using the allocated buffer.
  59. // Catch any exceptions due to an invalid descriptor.
  60. //
  61. __try
  62. {
  63. Status = RtlAbsoluteToSelfRelativeSD(
  64. pAbsoluteSd,
  65. pSd,
  66. &cbSd
  67. );
  68. }
  69. __except(EXCEPTION_EXECUTE_HANDLER)
  70. {
  71. Status = STATUS_INVALID_SECURITY_DESCR;
  72. }
  73. }
  74. else
  75. {
  76. return(STATUS_NO_MEMORY);
  77. }
  78. if (NT_SUCCESS(Status))
  79. {
  80. //
  81. // If the conversion succeeded, save the pointer to the security
  82. // descriptor and return the size.
  83. //
  84. *ppSelfRelativeSd = pSd;
  85. if (pcbSelfRelativeSd != NULL)
  86. {
  87. *pcbSelfRelativeSd = cbSd;
  88. }
  89. }
  90. else
  91. {
  92. //
  93. // If the conversion failed, free the memory and leave the input
  94. // parameters alone.
  95. //
  96. LocalFree(pSd);
  97. }
  98. return(Status);
  99. }
  100. NTSTATUS NTAPI
  101. NtConvertSelfRelativeToAbsolute(
  102. PSECURITY_DESCRIPTOR *ppAbsoluteSd,
  103. PSECURITY_DESCRIPTOR pSelfRelativeSd
  104. )
  105. {
  106. #if DBG
  107. BOOLEAN fAbsoluteSd;
  108. #endif
  109. NTSTATUS Status;
  110. PACL pDacl;
  111. PACL pSacl;
  112. PSID pGroup;
  113. PSID pOwner;
  114. PSECURITY_DESCRIPTOR pSd;
  115. ULONG cbDacl;
  116. ULONG cbGroup;
  117. ULONG cbOwner;
  118. ULONG cbSacl;
  119. ULONG cbSd;
  120. ASSERT(ppAbsoluteSd != NULL);
  121. ASSERT(pSelfRelativeSd != NULL);
  122. ASSERT(NT_SUCCESS(NtIsSecurityDescriptorAbsolute(pSelfRelativeSd,
  123. &fAbsoluteSd)));
  124. ASSERT(!fAbsoluteSd);
  125. //
  126. // Determine the size of each buffer needed to convert the security
  127. // descriptor. Catch any exceptions due to an invalid descriptor.
  128. //
  129. cbDacl = 0;
  130. cbGroup = 0;
  131. cbOwner = 0;
  132. cbSacl = 0;
  133. cbSd = 0;
  134. __try
  135. {
  136. Status = RtlSelfRelativeToAbsoluteSD(
  137. pSelfRelativeSd,
  138. NULL, &cbSd,
  139. NULL, &cbDacl,
  140. NULL, &cbSacl,
  141. NULL, &cbOwner,
  142. NULL, &cbGroup
  143. );
  144. }
  145. __except(EXCEPTION_EXECUTE_HANDLER)
  146. {
  147. return(STATUS_INVALID_SECURITY_DESCR);
  148. }
  149. //
  150. // Allocate memory for the security descriptor and its components.
  151. //
  152. pDacl = NULL;
  153. pGroup = NULL;
  154. pOwner = NULL;
  155. pSacl = NULL;
  156. if (cbDacl > 0)
  157. {
  158. pDacl = (PACL)LocalAlloc(LMEM_FIXED, cbDacl);
  159. if (pDacl == NULL)
  160. {
  161. Status = STATUS_NO_MEMORY;
  162. goto allocerror;
  163. }
  164. }
  165. if (cbGroup > 0)
  166. {
  167. pGroup = (PSID)LocalAlloc(LMEM_FIXED, cbGroup);
  168. if (pGroup == NULL)
  169. {
  170. Status = STATUS_NO_MEMORY;
  171. goto allocerror;
  172. }
  173. }
  174. if (cbOwner > 0)
  175. {
  176. pOwner = (PSID)LocalAlloc(LMEM_FIXED, cbOwner);
  177. if (pOwner == NULL)
  178. {
  179. Status = STATUS_NO_MEMORY;
  180. goto allocerror;
  181. }
  182. }
  183. if (cbSacl > 0)
  184. {
  185. pSacl = (PACL)LocalAlloc(LMEM_FIXED, cbSacl);
  186. if (pSacl == NULL)
  187. {
  188. Status = STATUS_NO_MEMORY;
  189. goto allocerror;
  190. }
  191. }
  192. ASSERT(cbSd > 0);
  193. pSd = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, cbSd);
  194. if (pSd == NULL)
  195. {
  196. Status = STATUS_NO_MEMORY;
  197. goto allocerror;
  198. }
  199. //
  200. // Now convert the security descriptor using the allocated buffer.
  201. // Catch any exceptions due to an invalid descriptor.
  202. //
  203. __try
  204. {
  205. Status = RtlSelfRelativeToAbsoluteSD(
  206. pSelfRelativeSd,
  207. pSd, &cbSd,
  208. pDacl, &cbDacl,
  209. pSacl, &cbSacl,
  210. pOwner, &cbOwner,
  211. pGroup, &cbGroup
  212. );
  213. }
  214. __except(EXCEPTION_EXECUTE_HANDLER)
  215. {
  216. Status = STATUS_INVALID_SECURITY_DESCR;
  217. }
  218. if (NT_SUCCESS(Status))
  219. {
  220. *ppAbsoluteSd = pSd;
  221. return(Status);
  222. }
  223. LocalFree(pSd);
  224. allocerror:
  225. if (pSacl != NULL)
  226. {
  227. LocalFree(pSacl);
  228. }
  229. if (pOwner != NULL)
  230. {
  231. LocalFree(pOwner);
  232. }
  233. if (pGroup != NULL)
  234. {
  235. LocalFree(pGroup);
  236. }
  237. if (pDacl != NULL)
  238. {
  239. LocalFree(pDacl);
  240. }
  241. return(Status);
  242. }
  243. NTSTATUS NTAPI
  244. NtDestroySecurityDescriptor(
  245. PSECURITY_DESCRIPTOR *ppSd
  246. )
  247. {
  248. BOOLEAN fAbsolute;
  249. NTSTATUS Status;
  250. ASSERT(ppSd != NULL);
  251. ASSERT(*ppSd != NULL);
  252. Status = NtIsSecurityDescriptorAbsolute(*ppSd, &fAbsolute);
  253. if (NT_SUCCESS(Status))
  254. {
  255. if (fAbsolute)
  256. {
  257. PISECURITY_DESCRIPTOR pSd;
  258. PULONG_PTR pBeginning;
  259. PULONG_PTR pDacl;
  260. PULONG_PTR pEnd;
  261. PULONG_PTR pGroup;
  262. PULONG_PTR pOwner;
  263. PULONG_PTR pSacl;
  264. //
  265. // An absolute security descriptor is much more complicated. The
  266. // descriptor contains pointers to the other items (instead of
  267. // offsets). This does not mean, however, that it is made up of
  268. // more than one allocation. In fact, almost all absolute
  269. // descriptors from the NT RTL are made of one allocation, with
  270. // the internal pointers set to areas of memory inside the one
  271. // allocation. This makes completely freeing a security
  272. // descriptor a heinous effort. (As an aside, whats the point of
  273. // creating an absolute security descriptor out of one chunk of
  274. // memory? Just make it relative!)
  275. //
  276. // Each component of the security descriptor may be NULL. For the
  277. // Dacl and the Sacl, the f[D,S]aclPresent variable may be TRUE
  278. // with a NULL [D,S]acl. Therefore, compare all pointers to NULL
  279. // and against the security descriptor allocation before freeing.
  280. //
  281. // The check to NtIsSecurityDescriptorAbsolute verifies that this
  282. // is a valid security descriptor. Therefore it is safe to type
  283. // cast here instead of making several RtlGetXSecurityDescriptor
  284. // calls.
  285. //
  286. pSd = (PISECURITY_DESCRIPTOR)(*ppSd);
  287. pBeginning = (PULONG_PTR)(pSd);
  288. pEnd = (PULONG_PTR)((PBYTE)pBeginning + LocalSize(pSd));
  289. pDacl = (PULONG_PTR)(pSd->Dacl);
  290. pGroup = (PULONG_PTR)(pSd->Group);
  291. pOwner = (PULONG_PTR)(pSd->Owner);
  292. pSacl = (PULONG_PTR)(pSd->Sacl);
  293. //
  294. // Handle the Dacl.
  295. //
  296. if (pDacl != NULL)
  297. {
  298. if ((pDacl > pEnd) || (pDacl < pBeginning))
  299. {
  300. LocalFree(pDacl);
  301. }
  302. }
  303. //
  304. // Handle the Group.
  305. //
  306. if (pGroup != NULL)
  307. {
  308. if ((pGroup > pEnd) || (pGroup < pBeginning))
  309. {
  310. LocalFree(pGroup);
  311. }
  312. }
  313. //
  314. // Handle the Owner.
  315. //
  316. if (pOwner != NULL)
  317. {
  318. if ((pOwner > pEnd) || (pOwner < pBeginning))
  319. {
  320. LocalFree(pOwner);
  321. }
  322. }
  323. //
  324. // Handle the Sacl.
  325. //
  326. if (pSacl != NULL)
  327. {
  328. if ((pSacl > pEnd) || (pSacl < pBeginning))
  329. {
  330. LocalFree(pSacl);
  331. }
  332. }
  333. }
  334. }
  335. else
  336. {
  337. return(Status);
  338. }
  339. //
  340. // If the security descriptor was absolute, the individual components
  341. // have been freed, and now the security descriptor itself can be freed.
  342. // If the security descriptor was self-relative, all the components are
  343. // stored in the same block of memory, so free it all at once.
  344. //
  345. LocalFree(*ppSd);
  346. *ppSd = NULL;
  347. return(STATUS_SUCCESS);
  348. }
  349. NTSTATUS NTAPI
  350. NtIsSecurityDescriptorAbsolute(
  351. PSECURITY_DESCRIPTOR pSd,
  352. PBOOLEAN pfAbsolute
  353. )
  354. {
  355. NTSTATUS Status;
  356. ULONG ulRevision;
  357. SECURITY_DESCRIPTOR_CONTROL wSdControl;
  358. ASSERT(pSd != NULL);
  359. ASSERT(pfAbsolute != NULL);
  360. Status = RtlGetControlSecurityDescriptor(pSd, &wSdControl, &ulRevision);
  361. if (NT_SUCCESS(Status))
  362. {
  363. //
  364. // Don't cast away the TRUE into a FALSE when dropping from a DWORD
  365. // to a UCHAR.
  366. //
  367. *pfAbsolute = (BOOLEAN)((wSdControl & SE_SELF_RELATIVE) ? TRUE : FALSE);
  368. }
  369. return(Status);
  370. }