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.

419 lines
12 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. sepriv.c
  5. Abstract:
  6. Security Runtime Library Privilege Routines
  7. (Temporary copy of \nt\private\ntos\rtl\sepriv.c to allow
  8. ntdailybld version of ntdll.dll to be used)
  9. These routines perform operations with privilege sets
  10. Author:
  11. Scott Birrell (ScottBi) June 17, 1991
  12. Environment:
  13. Revision History:
  14. Pete Skelly (petesk) Modified LsapRtlAddPrivileges to work within a preallocated
  15. buffer for performance reasons
  16. --*/
  17. #include <lsapch2.h>
  18. #include <string.h>
  19. #define LsapRtlEqualPrivileges(FirstPrivilege, SecondPrivilege) \
  20. (RtlEqualLuid(&(FirstPrivilege)->Luid, &(SecondPrivilege)->Luid))
  21. #define PRIVILEGE_SET_STEP_SIZE 20
  22. NTSTATUS
  23. LsapRtlAddPrivileges(
  24. IN OUT PPRIVILEGE_SET * RunningPrivileges,
  25. IN OUT PULONG MaxRunningPrivileges,
  26. IN PPRIVILEGE_SET PrivilegesToAdd,
  27. IN ULONG Options,
  28. OUT OPTIONAL BOOLEAN * Changed
  29. )
  30. /*++
  31. Routine Description:
  32. This function adds and/or updates privileges in a privilege set. The
  33. existing privilege set is unaltered, a new privilege set being generated.
  34. Existing privileges and Udpate privilege sets may point to the same location.
  35. The memory for the new privilege set must already be allocated by the
  36. caller. To assist in calculating the size of buffer required, the
  37. routine may be called in 'query' mode by supplying buffer size of 0. In
  38. this mode, the amount of memory required is returned and no copying
  39. takes place.
  40. WARNING: Privileges within each privilege set must all be distinct, that
  41. is, there must not be two privileges in the same set having the same LUID.
  42. Arguments:
  43. RunningPrivileges - Pointer to a pointer pointing to a running privilege set.
  44. MaxRunningPrivileges - maximum number of privileges that can be copied into the current privilege set
  45. before it must be grown.
  46. PrivilegesToAdd - Pointer to privilege set specifying privileges to
  47. be added. The attributes of privileges in this set that also exist
  48. in the ExistingPrivileges set supersede the attributes therein.
  49. Options - Specifies optional actions.
  50. RTL_COMBINE_PRIVILEGE_ATTRIBUTES - If the two privilege sets have
  51. privileges in common, combine the attributes
  52. RTL_SUPERSEDE_PRIVILEGE_ATTRIBUTES - If the two privilege sets
  53. have privileges in common, supersede the existing attributes
  54. with those specified in PrivilegesToAdd.
  55. Changed - Used to indicate whether any change has been made
  56. Return Value:
  57. NTSTATUS - Standard Nt Result Code
  58. STATUS_INVALID_PARAMETER
  59. STATUS_INSUFFICIENT_RESOURCES
  60. Environment:
  61. User or Kernel modes.
  62. --*/
  63. {
  64. PLUID_AND_ATTRIBUTES Privilege;
  65. ULONG AddIndex = 0L;
  66. NTSTATUS Status = STATUS_SUCCESS;
  67. ULONG CurrentPrivilegeCount = 0;
  68. DWORD OldPrivilegeSetSize = 0;
  69. //
  70. // Verify that mandatory parameters have been specified.
  71. // specified.
  72. //
  73. if (RunningPrivileges == NULL ||
  74. MaxRunningPrivileges == NULL) {
  75. return STATUS_INVALID_PARAMETER;
  76. }
  77. //
  78. // Validate the Options parameter.
  79. //
  80. if ((Options != RTL_SUPERSEDE_PRIVILEGE_ATTRIBUTES) &&
  81. (Options != RTL_COMBINE_PRIVILEGE_ATTRIBUTES)) {
  82. return STATUS_INVALID_PARAMETER;
  83. }
  84. if ( Changed ) {
  85. *Changed = FALSE;
  86. }
  87. if((PrivilegesToAdd == NULL) || (PrivilegesToAdd->PrivilegeCount == 0))
  88. {
  89. return STATUS_SUCCESS;
  90. }
  91. if(*RunningPrivileges == NULL)
  92. {
  93. PPRIVILEGE_SET UpdatedPrivileges = NULL;
  94. ASSERT(PrivilegesToAdd->PrivilegeCount > 0);
  95. OldPrivilegeSetSize = sizeof (PRIVILEGE_SET) + sizeof(LUID_AND_ATTRIBUTES)*
  96. (PrivilegesToAdd->PrivilegeCount - ANYSIZE_ARRAY);
  97. // We need to grow our privilege set
  98. UpdatedPrivileges = (PPRIVILEGE_SET)MIDL_user_allocate( OldPrivilegeSetSize +
  99. sizeof(LUID_AND_ATTRIBUTES)* PRIVILEGE_SET_STEP_SIZE);
  100. if (UpdatedPrivileges == NULL) {
  101. return STATUS_INSUFFICIENT_RESOURCES;
  102. }
  103. RtlCopyMemory(UpdatedPrivileges, PrivilegesToAdd, OldPrivilegeSetSize);
  104. *RunningPrivileges = UpdatedPrivileges;
  105. *MaxRunningPrivileges = PrivilegesToAdd->PrivilegeCount + PRIVILEGE_SET_STEP_SIZE;
  106. if ( Changed ) {
  107. *Changed = TRUE;
  108. }
  109. return STATUS_SUCCESS;
  110. }
  111. CurrentPrivilegeCount = (*RunningPrivileges)->PrivilegeCount;
  112. //
  113. // For each privilege to add, see if it's in the running privilege list,
  114. // set the attributes if it is, append it if it isn't.
  115. //
  116. //
  117. // Note, we dont' modify the count of RunningPrivileges until the end, so we don't
  118. // inefficiently search things we are currently adding (there should be no duplicates in what
  119. // we're currently adding);
  120. //
  121. for(AddIndex = 0;
  122. AddIndex < PrivilegesToAdd->PrivilegeCount;
  123. AddIndex++) {
  124. Privilege = NULL;
  125. if ((Privilege = LsapRtlGetPrivilege(
  126. &PrivilegesToAdd->Privilege[AddIndex],
  127. *RunningPrivileges
  128. )) != NULL) {
  129. if( Options & RTL_SUPERSEDE_PRIVILEGE_ATTRIBUTES &&
  130. Privilege->Attributes != PrivilegesToAdd->Privilege[AddIndex].Attributes ) {
  131. if ( Changed ) {
  132. *Changed = TRUE;
  133. }
  134. Privilege->Attributes = PrivilegesToAdd->Privilege[AddIndex].Attributes;
  135. }
  136. }
  137. else
  138. {
  139. // This is a new privilege, so add it to the end
  140. ASSERT(*MaxRunningPrivileges >= CurrentPrivilegeCount);
  141. if((CurrentPrivilegeCount+1) > *MaxRunningPrivileges)
  142. {
  143. // We need to grow our privilege set
  144. PPRIVILEGE_SET UpdatedPrivileges = (PPRIVILEGE_SET)MIDL_user_allocate( sizeof (PRIVILEGE_SET) +
  145. sizeof(LUID_AND_ATTRIBUTES)*
  146. (*MaxRunningPrivileges +
  147. PRIVILEGE_SET_STEP_SIZE - 1));
  148. if (UpdatedPrivileges == NULL) {
  149. return STATUS_INSUFFICIENT_RESOURCES;
  150. }
  151. if(*MaxRunningPrivileges > 0)
  152. {
  153. RtlCopyMemory(UpdatedPrivileges, *RunningPrivileges, sizeof (PRIVILEGE_SET) +
  154. sizeof(LUID_AND_ATTRIBUTES)*
  155. (*MaxRunningPrivileges - 1));
  156. }
  157. else
  158. {
  159. RtlCopyMemory(UpdatedPrivileges, *RunningPrivileges, sizeof (PRIVILEGE_SET));
  160. }
  161. MIDL_user_free(*RunningPrivileges);
  162. *RunningPrivileges = UpdatedPrivileges;
  163. *MaxRunningPrivileges += PRIVILEGE_SET_STEP_SIZE;
  164. }
  165. (*RunningPrivileges)->Privilege[CurrentPrivilegeCount++] = PrivilegesToAdd->Privilege[AddIndex];
  166. if ( Changed ) {
  167. *Changed = TRUE;
  168. }
  169. }
  170. }
  171. (*RunningPrivileges)->PrivilegeCount = CurrentPrivilegeCount;
  172. return Status;
  173. }
  174. NTSTATUS
  175. LsapRtlRemovePrivileges(
  176. IN OUT PPRIVILEGE_SET ExistingPrivileges,
  177. IN PPRIVILEGE_SET PrivilegesToRemove
  178. )
  179. /*++
  180. Routine Description:
  181. This function removes privileges in a privilege set. The existing
  182. privilege set is unaltered, a new privilege set being generated.
  183. WARNING: Privileges within each privilege set must all be distinct, that
  184. is, there must not be two privileges in the same set having the same LUID.
  185. Arguments:
  186. ExistingPrivileges - Pointer to existing privilege set
  187. PrivilegesToRemove - Pointer to privilege set specifying privileges to
  188. be removed. The privilege attributes are ignored. Privileges
  189. in the PrivilegesToRemove set that are not present in the
  190. ExistingPrivileges set will be ignored.
  191. UpdatedPrivileges - Pointer to buffer that will receive the updated
  192. privilege set. Care must be taken to ensure that UpdatedPrivileges
  193. occupies memory disjoint from that occupied by ExistingPrivileges
  194. and PrivilegesToChange.
  195. UpdatedPrivilegesSize - Pointer to variable that contains a size.
  196. On input, the size is the size of the UpdatedPrivileges buffer
  197. (if any). On output, the size is the size needed/used for the
  198. updated privilege set. If the updated privilege set will be
  199. NULL, 0 is returned.
  200. Return Value:
  201. NTSTATUS - Standard Nt Result Code
  202. - STATUS_INVALID_PARAMETER - Invalid parameter(s)
  203. Mandatory parameters not specified
  204. UpdatedPrivileges buffer not specified (except on
  205. query-only calls
  206. - STATUS_INSUFFICIENT_RESOURCES - Ran out of memory
  207. Environment:
  208. User or Kernel modes.
  209. --*/
  210. {
  211. NTSTATUS Status = STATUS_SUCCESS;
  212. ULONG ExistingIndex = 0;
  213. ULONG ExistingNew = 0;
  214. ULONG RemoveIndex;
  215. //
  216. // Verify that mandatory parameters have been specified.
  217. //
  218. if (ExistingPrivileges == NULL ||
  219. PrivilegesToRemove == NULL) {
  220. return STATUS_INVALID_PARAMETER;
  221. }
  222. //
  223. // Scan through the privileges in the existing privilege set. Look up
  224. // each privilege in the list of privileges to be removed. If the
  225. // privilege is not found there, it is to be retained, so copy it
  226. // to the output buffer/count it.
  227. //
  228. for (ExistingIndex = 0, ExistingNew = 0;
  229. ExistingIndex < ExistingPrivileges->PrivilegeCount;
  230. ExistingIndex++)
  231. {
  232. //
  233. // If the next privilege is not in the set to be deleted,
  234. // copy it to output/count it
  235. //
  236. for(RemoveIndex = 0; RemoveIndex < PrivilegesToRemove->PrivilegeCount; RemoveIndex++)
  237. {
  238. if(LsapRtlEqualPrivileges(
  239. &(ExistingPrivileges->Privilege[ExistingIndex]),
  240. &(PrivilegesToRemove->Privilege[RemoveIndex])))
  241. {
  242. break;
  243. }
  244. }
  245. if(RemoveIndex == PrivilegesToRemove->PrivilegeCount)
  246. {
  247. // We don't need to remove this one, so move it if necessary
  248. if(ExistingIndex != ExistingNew)
  249. {
  250. ExistingPrivileges->Privilege[ExistingNew] = ExistingPrivileges->Privilege[ExistingIndex];
  251. }
  252. ExistingNew++;
  253. }
  254. }
  255. ExistingPrivileges->PrivilegeCount = ExistingNew;
  256. return Status;
  257. }
  258. PLUID_AND_ATTRIBUTES
  259. LsapRtlGetPrivilege(
  260. IN PLUID_AND_ATTRIBUTES Privilege,
  261. IN PPRIVILEGE_SET Privileges
  262. )
  263. /*++
  264. Routine Description:
  265. WARNING: THIS ROUTINE IS NOT YET AVAILABLE
  266. This function locates a privilege in a privilege set. If found,
  267. a pointer to the privilege wihtin the set is returned, otherwise NULL
  268. is returned.
  269. Arguments:
  270. Privilege - Pointer to the privilege to be looked up.
  271. Privileges - Pointer to the privilege set to be scanned.
  272. Return Value:
  273. PLUID_AND_ATTRIBUTES - If the privilege is found, a pointer to its
  274. LUID and ATTRIBUTES structure within the privilege set is returned,
  275. otherwise NULL is returned.
  276. Environment:
  277. User or Kernel modes.
  278. --*/
  279. {
  280. ULONG PrivilegeIndex;
  281. for (PrivilegeIndex = 0;
  282. PrivilegeIndex < Privileges->PrivilegeCount;
  283. PrivilegeIndex++) {
  284. if (LsapRtlEqualPrivileges(
  285. Privilege,
  286. &(Privileges->Privilege[PrivilegeIndex])
  287. )) {
  288. return &(Privileges->Privilege[PrivilegeIndex]);
  289. }
  290. }
  291. //
  292. // The privilege was no found. Return NULL
  293. //
  294. return NULL;
  295. }