Reverted latest changes.
[reactos.git] / reactos / lib / ntdll / rtl / acl.c
1 /* $Id: acl.c,v 1.8 2002/09/08 10:23:04 chorns Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * PURPOSE: Security manager
6 * FILE: kernel/se/acl.c
7 * PROGRAMER: David Welch <welch@cwcom.net>
8 * REVISION HISTORY:
9 * 26/07/98: Added stubs for security functions
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15
16 #include <ntdll/ntdll.h>
17
18 /* FUNCTIONS ***************************************************************/
19
20 BOOLEAN STDCALL
21 RtlFirstFreeAce(PACL Acl,
22 PACE* Ace)
23 {
24 PACE Current;
25 PVOID AclEnd;
26 ULONG i;
27
28 Current = (PACE)(Acl + 1);
29 *Ace = NULL;
30 i = 0;
31 if (Acl->AceCount == 0)
32 {
33 *Ace = Current;
34 return(TRUE);
35 }
36 AclEnd = Acl->AclSize + (PVOID)Acl;
37 do
38 {
39 if ((PVOID)Current >= AclEnd)
40 {
41 return(FALSE);
42 }
43 if (Current->Header.AceType == 4)
44 {
45 if (Acl->AclRevision < 3)
46 {
47 return(FALSE);
48 }
49 }
50 Current = (PACE)((PVOID)Current + (ULONG)Current->Header.AceSize);
51 i++;
52 }
53 while (i < Acl->AceCount);
54
55 if ((PVOID)Current < AclEnd)
56 {
57 *Ace = Current;
58 }
59
60 return(TRUE);
61 }
62
63
64 NTSTATUS STDCALL
65 RtlGetAce(PACL Acl,
66 ULONG AceIndex,
67 PACE *Ace)
68 {
69 ULONG i;
70
71 *Ace = (PACE)(Acl + 1);
72
73 if (Acl->AclRevision != 2 &&
74 Acl->AclRevision != 3)
75 {
76 return(STATUS_INVALID_PARAMETER);
77 }
78
79 if (AceIndex >= Acl->AceCount)
80 {
81 return(STATUS_INVALID_PARAMETER);
82 }
83
84 for (i = 0; i < AceIndex; i++)
85 {
86 if ((PVOID)*Ace >= (PVOID)Acl + Acl->AclSize)
87 {
88 return(STATUS_INVALID_PARAMETER);
89 }
90 *Ace = (PACE)((PVOID)(*Ace) + (ULONG)(*Ace)->Header.AceSize);
91 }
92
93 if ((PVOID)*Ace >= (PVOID)Acl + Acl->AclSize)
94 {
95 return(STATUS_INVALID_PARAMETER);
96 }
97
98 return(STATUS_SUCCESS);
99 }
100
101
102 static NTSTATUS
103 RtlpAddKnownAce(PACL Acl,
104 ULONG Revision,
105 ACCESS_MASK AccessMask,
106 PSID Sid,
107 ULONG Type)
108 {
109 PACE Ace;
110
111 if (!RtlValidSid(Sid))
112 {
113 return(STATUS_INVALID_SID);
114 }
115 if (Acl->AclRevision > 3 ||
116 Revision > 3)
117 {
118 return(STATUS_UNKNOWN_REVISION);
119 }
120 if (Revision < Acl->AclRevision)
121 {
122 Revision = Acl->AclRevision;
123 }
124 if (!RtlFirstFreeAce(Acl, &Ace))
125 {
126 return(STATUS_INVALID_ACL);
127 }
128 if (Ace == NULL)
129 {
130 return(STATUS_ALLOTTED_SPACE_EXCEEDED);
131 }
132 if (((PVOID)Ace + RtlLengthSid(Sid) + sizeof(ACE)) >=
133 ((PVOID)Acl + Acl->AclSize))
134 {
135 return(STATUS_ALLOTTED_SPACE_EXCEEDED);
136 }
137 Ace->Header.AceFlags = 0;
138 Ace->Header.AceType = Type;
139 Ace->Header.AceSize = RtlLengthSid(Sid) + sizeof(ACE);
140 Ace->Header.AccessMask = AccessMask;
141 RtlCopySid(RtlLengthSid(Sid), (PSID)(Ace + 1), Sid);
142 Acl->AceCount++;
143 Acl->AclRevision = Revision;
144 return(STATUS_SUCCESS);
145 }
146
147
148 NTSTATUS STDCALL
149 RtlAddAccessAllowedAce(PACL Acl,
150 ULONG Revision,
151 ACCESS_MASK AccessMask,
152 PSID Sid)
153 {
154 return(RtlpAddKnownAce(Acl, Revision, AccessMask, Sid, 0));
155 }
156
157
158 NTSTATUS STDCALL
159 RtlAddAccessDeniedAce(PACL Acl,
160 ULONG Revision,
161 ACCESS_MASK AccessMask,
162 PSID Sid)
163 {
164 return(RtlpAddKnownAce(Acl, Revision, AccessMask, Sid, 1));
165 }
166
167
168 static VOID
169 RtlpAddData(PVOID AceList,
170 ULONG AceListLength,
171 PVOID Ace,
172 ULONG Offset)
173 {
174 if (Offset > 0)
175 {
176 memcpy((PUCHAR)Ace + AceListLength,
177 Ace,
178 Offset);
179 }
180
181 if (AceListLength != 0)
182 {
183 memcpy(Ace,
184 AceList,
185 AceListLength);
186 }
187 }
188
189
190 NTSTATUS STDCALL
191 RtlAddAce(PACL Acl,
192 ULONG AclRevision,
193 ULONG StartingIndex,
194 PACE AceList,
195 ULONG AceListLength)
196 {
197 PACE Ace;
198 ULONG i;
199 PACE Current;
200 ULONG j;
201
202 if (Acl->AclRevision != 2 &&
203 Acl->AclRevision != 3)
204 {
205 return(STATUS_INVALID_PARAMETER);
206 }
207
208 if (!RtlFirstFreeAce(Acl,&Ace))
209 {
210 return(STATUS_INVALID_PARAMETER);
211 }
212
213 if (Acl->AclRevision <= AclRevision)
214 {
215 AclRevision = Acl->AclRevision;
216 }
217
218 if (((PVOID)AceList + AceListLength) <= (PVOID)AceList)
219 {
220 return(STATUS_INVALID_PARAMETER);
221 }
222
223 i = 0;
224 Current = (PACE)(Acl + 1);
225 while ((PVOID)Current < ((PVOID)AceList + AceListLength))
226 {
227 if (AceList->Header.AceType == 4 &&
228 AclRevision < 3)
229 {
230 return(STATUS_INVALID_PARAMETER);
231 }
232 Current = (PACE)((PVOID)Current + Current->Header.AceSize);
233 }
234
235 if (Ace == NULL)
236 {
237 return(STATUS_BUFFER_TOO_SMALL);
238 }
239
240 if (((PVOID)Ace + AceListLength) >= ((PVOID)Acl + Acl->AclSize))
241 {
242 return(STATUS_BUFFER_TOO_SMALL);
243 }
244
245 if (StartingIndex != 0)
246 {
247 if (Acl->AceCount > 0)
248 {
249 Current = (PACE)(Acl + 1);
250 for (j = 0; j < StartingIndex; j++)
251 {
252 Current = (PACE)((PVOID)Current + Current->Header.AceSize);
253 }
254 }
255 }
256
257 RtlpAddData(AceList,
258 AceListLength,
259 Current,
260 (ULONG)Ace - (ULONG)Current);
261 Acl->AceCount = Acl->AceCount + i;
262 Acl->AclRevision = AclRevision;
263
264 return(STATUS_SUCCESS);
265 }
266
267
268 NTSTATUS STDCALL
269 RtlAddAuditAccessAce(PACL Acl,
270 ULONG Revision,
271 ACCESS_MASK AccessMask,
272 PSID Sid,
273 BOOLEAN Success,
274 BOOLEAN Failure)
275 {
276 PACE Ace;
277 ULONG Flags = 0;
278
279 if (Success != FALSE)
280 {
281 Flags |= SUCCESSFUL_ACCESS_ACE_FLAG;
282 }
283
284 if (Failure != FALSE)
285 {
286 Flags |= FAILED_ACCESS_ACE_FLAG;
287 }
288
289 if (!RtlValidSid(Sid))
290 {
291 return(STATUS_INVALID_SID);
292 }
293
294 if (Acl->AclRevision > 3 ||
295 Revision > 3)
296 {
297 return(STATUS_REVISION_MISMATCH);
298 }
299
300 if (Revision < Acl->AclRevision)
301 {
302 Revision = Acl->AclRevision;
303 }
304
305 if (!RtlFirstFreeAce(Acl, &Ace))
306 {
307 return(STATUS_INVALID_ACL);
308 }
309
310 if (Ace == NULL)
311 {
312 return(STATUS_ALLOTTED_SPACE_EXCEEDED);
313 }
314
315 if (((PVOID)Ace + RtlLengthSid(Sid) + sizeof(ACE)) >= ((PVOID)Acl + Acl->AclSize))
316 {
317 return(STATUS_ALLOTTED_SPACE_EXCEEDED);
318 }
319
320 Ace->Header.AceFlags = Flags;
321 Ace->Header.AceType = 2;
322 Ace->Header.AceSize = RtlLengthSid(Sid) + sizeof(ACE);
323 Ace->Header.AccessMask = AccessMask;
324 RtlCopySid(RtlLengthSid(Sid),
325 (PSID)(Ace + 1),
326 Sid);
327 Acl->AceCount++;
328 Acl->AclRevision = Revision;
329
330 return(STATUS_SUCCESS);
331 }
332
333
334 static VOID
335 RtlpDeleteData(PVOID Ace,
336 ULONG AceSize,
337 ULONG Offset)
338 {
339 if (AceSize < Offset)
340 {
341 memcpy(Ace,
342 (PUCHAR)Ace + AceSize,
343 Offset - AceSize);
344 }
345
346 if (Offset - AceSize < Offset)
347 {
348 memset((PUCHAR)Ace + Offset - AceSize,
349 0,
350 AceSize);
351 }
352 }
353
354
355 NTSTATUS STDCALL
356 RtlDeleteAce(PACL Acl,
357 ULONG AceIndex)
358 {
359 PACE Ace;
360 PACE Current;
361
362 if (Acl->AclRevision != 2 &&
363 Acl->AclRevision != 3)
364 {
365 return(STATUS_INVALID_PARAMETER);
366 }
367
368 if (Acl->AceCount <= AceIndex)
369 {
370 return(STATUS_INVALID_PARAMETER);
371 }
372
373 if (!RtlFirstFreeAce(Acl, &Ace))
374 {
375 return(STATUS_INVALID_PARAMETER);
376 }
377
378 Current = (PACE)(Acl + 1);
379
380 while(AceIndex--)
381 {
382 Current = (PACE)((PVOID)Current + Current->Header.AceSize);
383 }
384
385 RtlpDeleteData(Current,
386 Current->Header.AceSize,
387 Ace - Current);
388 Acl->AceCount++;
389
390 return(STATUS_SUCCESS);
391 }
392
393
394 NTSTATUS STDCALL
395 RtlCreateAcl(PACL Acl,
396 ULONG AclSize,
397 ULONG AclRevision)
398 {
399 if (AclSize < 8)
400 {
401 return(STATUS_BUFFER_TOO_SMALL);
402 }
403
404 if (AclRevision != 2 &&
405 AclRevision != 3)
406 {
407 return(STATUS_INVALID_PARAMETER);
408 }
409
410 if (AclSize > 0xffff)
411 {
412 return(STATUS_INVALID_PARAMETER);
413 }
414
415 AclSize = AclSize & ~(0x3);
416 Acl->AclSize = AclSize;
417 Acl->AclRevision = AclRevision;
418 Acl->AceCount = 0;
419 Acl->Sbz1 = 0;
420 Acl->Sbz2 = 0;
421
422 return(STATUS_SUCCESS);
423 }
424
425
426 NTSTATUS STDCALL
427 RtlQueryInformationAcl(PACL Acl,
428 PVOID Information,
429 ULONG InformationLength,
430 ACL_INFORMATION_CLASS InformationClass)
431 {
432 PACE Ace;
433
434 if (Acl->AclRevision != 2 &&
435 Acl->AclRevision != 3)
436 {
437 return(STATUS_INVALID_PARAMETER);
438 }
439
440 switch (InformationClass)
441 {
442 case AclRevisionInformation:
443 {
444 PACL_REVISION_INFORMATION Info = (PACL_REVISION_INFORMATION)Information;
445
446 if (InformationLength < sizeof(ACL_REVISION_INFORMATION))
447 {
448 return(STATUS_BUFFER_TOO_SMALL);
449 }
450 Info->AclRevision = Acl->AclRevision;
451 }
452 break;
453
454 case AclSizeInformation:
455 {
456 PACL_SIZE_INFORMATION Info = (PACL_SIZE_INFORMATION)Information;
457
458 if (InformationLength < sizeof(ACL_SIZE_INFORMATION))
459 {
460 return(STATUS_BUFFER_TOO_SMALL);
461 }
462
463 if (!RtlFirstFreeAce(Acl, &Ace))
464 {
465 return(STATUS_INVALID_PARAMETER);
466 }
467
468 Info->AceCount = Acl->AceCount;
469 if (Ace != NULL)
470 {
471 Info->AclBytesInUse = (PVOID)Ace - (PVOID)Acl;
472 Info->AclBytesFree = Acl->AclSize - Info->AclBytesInUse;
473 }
474 else
475 {
476 Info->AclBytesInUse = Acl->AclSize;
477 Info->AclBytesFree = 0;
478 }
479 }
480 break;
481
482 default:
483 return(STATUS_INVALID_INFO_CLASS);
484 }
485
486 return(STATUS_SUCCESS);
487 }
488
489
490 NTSTATUS STDCALL
491 RtlSetInformationAcl(PACL Acl,
492 PVOID Information,
493 ULONG InformationLength,
494 ACL_INFORMATION_CLASS InformationClass)
495 {
496 if (Acl->AclRevision != 2 &&
497 Acl->AclRevision != 3)
498 {
499 return(STATUS_INVALID_PARAMETER);
500 }
501
502 switch (InformationClass)
503 {
504 case AclRevisionInformation:
505 {
506 PACL_REVISION_INFORMATION Info = (PACL_REVISION_INFORMATION)Information;
507
508 if (InformationLength < sizeof(ACL_REVISION_INFORMATION))
509 {
510 return(STATUS_BUFFER_TOO_SMALL);
511 }
512
513 if (Acl->AclRevision >= Info->AclRevision)
514 {
515 return(STATUS_INVALID_PARAMETER);
516 }
517
518 Acl->AclRevision = Info->AclRevision;
519 }
520 break;
521
522 default:
523 return(STATUS_INVALID_INFO_CLASS);
524 }
525
526 return(STATUS_SUCCESS);
527 }
528
529
530 BOOLEAN STDCALL
531 RtlValidAcl(PACL Acl)
532 {
533 PACE Ace;
534 USHORT Size;
535
536 Size = (Acl->AclSize + 3) & ~3;
537
538 if (Acl->AclRevision != 2 &&
539 Acl->AclRevision != 3)
540 {
541 return(FALSE);
542 }
543
544 if (Size != Acl->AclSize)
545 {
546 return(FALSE);
547 }
548
549 return(RtlFirstFreeAce(Acl, &Ace));
550 }
551
552 /* EOF */