Minor simplification
[reactos.git] / reactos / ntoskrnl / se / sd.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/sd.c
6 * PURPOSE: Security manager
7 *
8 * PROGRAMMERS: David Welch <welch@cwcom.net>
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #include <internal/debug.h>
15
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, SepInitSDs)
18 #endif
19
20
21 /* GLOBALS ******************************************************************/
22
23 PSECURITY_DESCRIPTOR SePublicDefaultSd = NULL;
24 PSECURITY_DESCRIPTOR SePublicDefaultUnrestrictedSd = NULL;
25 PSECURITY_DESCRIPTOR SePublicOpenSd = NULL;
26 PSECURITY_DESCRIPTOR SePublicOpenUnrestrictedSd = NULL;
27 PSECURITY_DESCRIPTOR SeSystemDefaultSd = NULL;
28 PSECURITY_DESCRIPTOR SeUnrestrictedSd = NULL;
29
30 /* FUNCTIONS ***************************************************************/
31
32 BOOLEAN
33 INIT_FUNCTION
34 NTAPI
35 SepInitSDs(VOID)
36 {
37 /* Create PublicDefaultSd */
38 SePublicDefaultSd = ExAllocatePoolWithTag(PagedPool,
39 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
40 if (SePublicDefaultSd == NULL)
41 return FALSE;
42
43 RtlCreateSecurityDescriptor(SePublicDefaultSd,
44 SECURITY_DESCRIPTOR_REVISION);
45 RtlSetDaclSecurityDescriptor(SePublicDefaultSd,
46 TRUE,
47 SePublicDefaultDacl,
48 FALSE);
49
50 /* Create PublicDefaultUnrestrictedSd */
51 SePublicDefaultUnrestrictedSd = ExAllocatePoolWithTag(PagedPool,
52 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
53 if (SePublicDefaultUnrestrictedSd == NULL)
54 return FALSE;
55
56 RtlCreateSecurityDescriptor(SePublicDefaultUnrestrictedSd,
57 SECURITY_DESCRIPTOR_REVISION);
58 RtlSetDaclSecurityDescriptor(SePublicDefaultUnrestrictedSd,
59 TRUE,
60 SePublicDefaultUnrestrictedDacl,
61 FALSE);
62
63 /* Create PublicOpenSd */
64 SePublicOpenSd = ExAllocatePoolWithTag(PagedPool,
65 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
66 if (SePublicOpenSd == NULL)
67 return FALSE;
68
69 RtlCreateSecurityDescriptor(SePublicOpenSd,
70 SECURITY_DESCRIPTOR_REVISION);
71 RtlSetDaclSecurityDescriptor(SePublicOpenSd,
72 TRUE,
73 SePublicOpenDacl,
74 FALSE);
75
76 /* Create PublicOpenUnrestrictedSd */
77 SePublicOpenUnrestrictedSd = ExAllocatePoolWithTag(PagedPool,
78 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
79 if (SePublicOpenUnrestrictedSd == NULL)
80 return FALSE;
81
82 RtlCreateSecurityDescriptor(SePublicOpenUnrestrictedSd,
83 SECURITY_DESCRIPTOR_REVISION);
84 RtlSetDaclSecurityDescriptor(SePublicOpenUnrestrictedSd,
85 TRUE,
86 SePublicOpenUnrestrictedDacl,
87 FALSE);
88
89 /* Create SystemDefaultSd */
90 SeSystemDefaultSd = ExAllocatePoolWithTag(PagedPool,
91 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
92 if (SeSystemDefaultSd == NULL)
93 return FALSE;
94
95 RtlCreateSecurityDescriptor(SeSystemDefaultSd,
96 SECURITY_DESCRIPTOR_REVISION);
97 RtlSetDaclSecurityDescriptor(SeSystemDefaultSd,
98 TRUE,
99 SeSystemDefaultDacl,
100 FALSE);
101
102 /* Create UnrestrictedSd */
103 SeUnrestrictedSd = ExAllocatePoolWithTag(PagedPool,
104 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
105 if (SeUnrestrictedSd == NULL)
106 return FALSE;
107
108 RtlCreateSecurityDescriptor(SeUnrestrictedSd,
109 SECURITY_DESCRIPTOR_REVISION);
110 RtlSetDaclSecurityDescriptor(SeUnrestrictedSd,
111 TRUE,
112 SeUnrestrictedDacl,
113 FALSE);
114
115 return TRUE;
116 }
117
118 NTSTATUS
119 NTAPI
120 SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation,
121 PISECURITY_DESCRIPTOR SecurityDescriptor,
122 PULONG BufferLength)
123 {
124 ULONG_PTR Current;
125 ULONG SidSize;
126 ULONG SdSize;
127 NTSTATUS Status;
128 PISECURITY_DESCRIPTOR_RELATIVE SdRel = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
129
130 DPRINT("SeSetWorldSecurityDescriptor() called\n");
131
132 if (SecurityInformation == 0)
133 {
134 return STATUS_ACCESS_DENIED;
135 }
136
137 /* calculate the minimum size of the buffer */
138 SidSize = RtlLengthSid(SeWorldSid);
139 SdSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
140 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
141 SdSize += SidSize;
142 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
143 SdSize += SidSize;
144 if (SecurityInformation & DACL_SECURITY_INFORMATION)
145 {
146 SdSize += sizeof(ACL) + sizeof(ACE) + SidSize;
147 }
148
149 if (*BufferLength < SdSize)
150 {
151 *BufferLength = SdSize;
152 return STATUS_BUFFER_TOO_SMALL;
153 }
154
155 *BufferLength = SdSize;
156
157 Status = RtlCreateSecurityDescriptorRelative(SdRel,
158 SECURITY_DESCRIPTOR_REVISION);
159 if (!NT_SUCCESS(Status))
160 {
161 return Status;
162 }
163
164 Current = (ULONG_PTR)(SdRel + 1);
165
166 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
167 {
168 RtlCopyMemory((PVOID)Current,
169 SeWorldSid,
170 SidSize);
171 SdRel->Owner = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)SdRel);
172 Current += SidSize;
173 }
174
175 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
176 {
177 RtlCopyMemory((PVOID)Current,
178 SeWorldSid,
179 SidSize);
180 SdRel->Group = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)SdRel);
181 Current += SidSize;
182 }
183
184 if (SecurityInformation & DACL_SECURITY_INFORMATION)
185 {
186 PACL Dacl = (PACL)Current;
187 SdRel->Control |= SE_DACL_PRESENT;
188
189 Status = RtlCreateAcl(Dacl,
190 sizeof(ACL) + sizeof(ACE) + SidSize,
191 ACL_REVISION);
192 if (!NT_SUCCESS(Status))
193 return Status;
194
195 Status = RtlAddAccessAllowedAce(Dacl,
196 ACL_REVISION,
197 GENERIC_ALL,
198 SeWorldSid);
199 if (!NT_SUCCESS(Status))
200 return Status;
201
202 SdRel->Dacl = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)SdRel);
203 }
204
205 if (SecurityInformation & SACL_SECURITY_INFORMATION)
206 {
207 /* FIXME - SdRel->Control |= SE_SACL_PRESENT; */
208 }
209
210 return STATUS_SUCCESS;
211 }
212
213
214 NTSTATUS
215 NTAPI
216 SepCaptureSecurityQualityOfService(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
217 IN KPROCESSOR_MODE AccessMode,
218 IN POOL_TYPE PoolType,
219 IN BOOLEAN CaptureIfKernel,
220 OUT PSECURITY_QUALITY_OF_SERVICE *CapturedSecurityQualityOfService,
221 OUT PBOOLEAN Present)
222 {
223 PSECURITY_QUALITY_OF_SERVICE CapturedQos;
224 NTSTATUS Status = STATUS_SUCCESS;
225
226 PAGED_CODE();
227
228 ASSERT(CapturedSecurityQualityOfService);
229 ASSERT(Present);
230
231 if(ObjectAttributes != NULL)
232 {
233 if(AccessMode != KernelMode)
234 {
235 SECURITY_QUALITY_OF_SERVICE SafeQos;
236
237 _SEH_TRY
238 {
239 ProbeForRead(ObjectAttributes,
240 sizeof(ObjectAttributes),
241 sizeof(ULONG));
242 if(ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
243 {
244 if(ObjectAttributes->SecurityQualityOfService != NULL)
245 {
246 ProbeForRead(ObjectAttributes->SecurityQualityOfService,
247 sizeof(SECURITY_QUALITY_OF_SERVICE),
248 sizeof(ULONG));
249
250 if(((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length ==
251 sizeof(SECURITY_QUALITY_OF_SERVICE))
252 {
253 /* don't allocate memory here because ExAllocate should bugcheck
254 the system if it's buggy, SEH would catch that! So make a local
255 copy of the qos structure.*/
256 RtlCopyMemory(&SafeQos,
257 ObjectAttributes->SecurityQualityOfService,
258 sizeof(SECURITY_QUALITY_OF_SERVICE));
259 *Present = TRUE;
260 }
261 else
262 {
263 Status = STATUS_INVALID_PARAMETER;
264 }
265 }
266 else
267 {
268 *CapturedSecurityQualityOfService = NULL;
269 *Present = FALSE;
270 }
271 }
272 else
273 {
274 Status = STATUS_INVALID_PARAMETER;
275 }
276 }
277 _SEH_HANDLE
278 {
279 Status = _SEH_GetExceptionCode();
280 }
281 _SEH_END;
282
283 if(NT_SUCCESS(Status))
284 {
285 if(*Present)
286 {
287 CapturedQos = ExAllocatePool(PoolType,
288 sizeof(SECURITY_QUALITY_OF_SERVICE));
289 if(CapturedQos != NULL)
290 {
291 RtlCopyMemory(CapturedQos,
292 &SafeQos,
293 sizeof(SECURITY_QUALITY_OF_SERVICE));
294 *CapturedSecurityQualityOfService = CapturedQos;
295 }
296 else
297 {
298 Status = STATUS_INSUFFICIENT_RESOURCES;
299 }
300 }
301 else
302 {
303 *CapturedSecurityQualityOfService = NULL;
304 }
305 }
306 }
307 else
308 {
309 if(ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
310 {
311 if(CaptureIfKernel)
312 {
313 if(ObjectAttributes->SecurityQualityOfService != NULL)
314 {
315 if(((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length ==
316 sizeof(SECURITY_QUALITY_OF_SERVICE))
317 {
318 CapturedQos = ExAllocatePool(PoolType,
319 sizeof(SECURITY_QUALITY_OF_SERVICE));
320 if(CapturedQos != NULL)
321 {
322 RtlCopyMemory(CapturedQos,
323 ObjectAttributes->SecurityQualityOfService,
324 sizeof(SECURITY_QUALITY_OF_SERVICE));
325 *CapturedSecurityQualityOfService = CapturedQos;
326 *Present = TRUE;
327 }
328 else
329 {
330 Status = STATUS_INSUFFICIENT_RESOURCES;
331 }
332 }
333 else
334 {
335 Status = STATUS_INVALID_PARAMETER;
336 }
337 }
338 else
339 {
340 *CapturedSecurityQualityOfService = NULL;
341 *Present = FALSE;
342 }
343 }
344 else
345 {
346 *CapturedSecurityQualityOfService = (PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService;
347 *Present = (ObjectAttributes->SecurityQualityOfService != NULL);
348 }
349 }
350 else
351 {
352 Status = STATUS_INVALID_PARAMETER;
353 }
354 }
355 }
356 else
357 {
358 *CapturedSecurityQualityOfService = NULL;
359 *Present = FALSE;
360 }
361
362 return Status;
363 }
364
365
366 VOID
367 NTAPI
368 SepReleaseSecurityQualityOfService(IN PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService OPTIONAL,
369 IN KPROCESSOR_MODE AccessMode,
370 IN BOOLEAN CaptureIfKernel)
371 {
372 PAGED_CODE();
373
374 if(CapturedSecurityQualityOfService != NULL &&
375 (AccessMode != KernelMode || CaptureIfKernel))
376 {
377 ExFreePool(CapturedSecurityQualityOfService);
378 }
379 }
380
381
382 /*
383 * @implemented
384 */
385 NTSTATUS
386 STDCALL
387 SeCaptureSecurityDescriptor(
388 IN PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor,
389 IN KPROCESSOR_MODE CurrentMode,
390 IN POOL_TYPE PoolType,
391 IN BOOLEAN CaptureIfKernel,
392 OUT PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor
393 )
394 {
395 PISECURITY_DESCRIPTOR OriginalSecurityDescriptor = _OriginalSecurityDescriptor;
396 SECURITY_DESCRIPTOR DescriptorCopy;
397 PISECURITY_DESCRIPTOR NewDescriptor;
398 ULONG OwnerSAC = 0, GroupSAC = 0;
399 ULONG OwnerSize = 0, GroupSize = 0;
400 ULONG SaclSize = 0, DaclSize = 0;
401 ULONG DescriptorSize = 0;
402 NTSTATUS Status = STATUS_SUCCESS;
403
404 if(OriginalSecurityDescriptor != NULL)
405 {
406 if(CurrentMode != KernelMode)
407 {
408 RtlZeroMemory(&DescriptorCopy, sizeof(DescriptorCopy));
409
410 _SEH_TRY
411 {
412 /* first only probe and copy until the control field of the descriptor
413 to determine whether it's a self-relative descriptor */
414 DescriptorSize = FIELD_OFFSET(SECURITY_DESCRIPTOR,
415 Owner);
416 ProbeForRead(OriginalSecurityDescriptor,
417 DescriptorSize,
418 sizeof(ULONG));
419
420 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
421 {
422 Status = STATUS_UNKNOWN_REVISION;
423 _SEH_LEAVE;
424 }
425
426 /* make a copy on the stack */
427 DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
428 DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
429 DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
430 DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
431 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR));
432
433 /* probe and copy the entire security descriptor structure. The SIDs
434 and ACLs will be probed and copied later though */
435 ProbeForRead(OriginalSecurityDescriptor,
436 DescriptorSize,
437 sizeof(ULONG));
438 if(DescriptorCopy.Control & SE_SELF_RELATIVE)
439 {
440 PISECURITY_DESCRIPTOR_RELATIVE RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
441
442 DescriptorCopy.Owner = (PSID)RelSD->Owner;
443 DescriptorCopy.Group = (PSID)RelSD->Group;
444 DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
445 DescriptorCopy.Dacl = (PACL)RelSD->Dacl;
446 }
447 else
448 {
449 DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
450 DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
451 DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
452 DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
453 }
454 }
455 _SEH_HANDLE
456 {
457 Status = _SEH_GetExceptionCode();
458 }
459 _SEH_END;
460
461 if(!NT_SUCCESS(Status))
462 {
463 return Status;
464 }
465 }
466 else if(!CaptureIfKernel)
467 {
468 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
469 {
470 return STATUS_UNKNOWN_REVISION;
471 }
472
473 *CapturedSecurityDescriptor = OriginalSecurityDescriptor;
474 return STATUS_SUCCESS;
475 }
476 else
477 {
478 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
479 {
480 return STATUS_UNKNOWN_REVISION;
481 }
482
483 /* make a copy on the stack */
484 DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
485 DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
486 DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
487 DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
488 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR));
489 if(DescriptorCopy.Control & SE_SELF_RELATIVE)
490 {
491 PISECURITY_DESCRIPTOR_RELATIVE RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
492
493 DescriptorCopy.Owner = (PSID)RelSD->Owner;
494 DescriptorCopy.Group = (PSID)RelSD->Group;
495 DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
496 DescriptorCopy.Dacl = (PACL)RelSD->Dacl;
497 }
498 else
499 {
500 DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
501 DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
502 DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
503 DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
504 }
505 }
506
507 if(DescriptorCopy.Control & SE_SELF_RELATIVE)
508 {
509 /* in case we're dealing with a self-relative descriptor, do a basic convert
510 to an absolute descriptor. We do this so we can simply access the data
511 using the pointers without calculating them again. */
512 DescriptorCopy.Control &= ~SE_SELF_RELATIVE;
513 if(DescriptorCopy.Owner != NULL)
514 {
515 DescriptorCopy.Owner = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Owner);
516 }
517 if(DescriptorCopy.Group != NULL)
518 {
519 DescriptorCopy.Group = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Group);
520 }
521 if(DescriptorCopy.Dacl != NULL)
522 {
523 DescriptorCopy.Dacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Dacl);
524 }
525 if(DescriptorCopy.Sacl != NULL)
526 {
527 DescriptorCopy.Sacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Sacl);
528 }
529 }
530
531 /* determine the size of the SIDs */
532 #define DetermineSIDSize(SidType) \
533 do { \
534 if(DescriptorCopy.SidType != NULL) \
535 { \
536 SID *SidType = (SID*)DescriptorCopy.SidType; \
537 \
538 if(CurrentMode != KernelMode) \
539 { \
540 /* securely access the buffers! */ \
541 _SEH_TRY \
542 { \
543 SidType##SAC = ProbeForReadUchar(&SidType->SubAuthorityCount); \
544 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
545 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
546 ProbeForRead(SidType, \
547 SidType##Size, \
548 sizeof(ULONG)); \
549 } \
550 _SEH_HANDLE \
551 { \
552 Status = _SEH_GetExceptionCode(); \
553 } \
554 _SEH_END; \
555 \
556 if(!NT_SUCCESS(Status)) \
557 { \
558 return Status; \
559 } \
560 } \
561 else \
562 { \
563 SidType##SAC = SidType->SubAuthorityCount; \
564 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
565 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
566 } \
567 } \
568 } while(0)
569
570 DetermineSIDSize(Owner);
571 DetermineSIDSize(Group);
572
573 #undef DetermineSIDSize
574
575 /* determine the size of the ACLs */
576 #define DetermineACLSize(AclType, AclFlag) \
577 do { \
578 if((DescriptorCopy.Control & SE_##AclFlag##_PRESENT) && \
579 DescriptorCopy.AclType != NULL) \
580 { \
581 PACL AclType = (PACL)DescriptorCopy.AclType; \
582 \
583 if(CurrentMode != KernelMode) \
584 { \
585 /* securely access the buffers! */ \
586 _SEH_TRY \
587 { \
588 AclType##Size = ProbeForReadUshort(&AclType->AclSize); \
589 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
590 ProbeForRead(AclType, \
591 AclType##Size, \
592 sizeof(ULONG)); \
593 } \
594 _SEH_HANDLE \
595 { \
596 Status = _SEH_GetExceptionCode(); \
597 } \
598 _SEH_END; \
599 \
600 if(!NT_SUCCESS(Status)) \
601 { \
602 return Status; \
603 } \
604 } \
605 else \
606 { \
607 AclType##Size = AclType->AclSize; \
608 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
609 } \
610 } \
611 else \
612 { \
613 DescriptorCopy.AclType = NULL; \
614 } \
615 } while(0)
616
617 DetermineACLSize(Sacl, SACL);
618 DetermineACLSize(Dacl, DACL);
619
620 #undef DetermineACLSize
621
622 /* allocate enough memory to store a complete copy of a self-relative
623 security descriptor */
624 NewDescriptor = ExAllocatePool(PoolType,
625 DescriptorSize);
626 if(NewDescriptor != NULL)
627 {
628 ULONG_PTR Offset = sizeof(SECURITY_DESCRIPTOR);
629
630 RtlZeroMemory(NewDescriptor, DescriptorSize);
631 NewDescriptor->Revision = DescriptorCopy.Revision;
632 NewDescriptor->Sbz1 = DescriptorCopy.Sbz1;
633 NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE;
634
635 _SEH_TRY
636 {
637 /* setup the offsets and copy the SIDs and ACLs to the new
638 self-relative security descriptor. Probing the pointers is not
639 neccessary anymore as we did that when collecting the sizes!
640 Make sure to validate the SIDs and ACLs *again* as they could have
641 been modified in the meanwhile! */
642 #define CopySID(Type) \
643 do { \
644 if(DescriptorCopy.Type != NULL) \
645 { \
646 NewDescriptor->Type = (PVOID)Offset; \
647 RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
648 (ULONG_PTR)NewDescriptor->Type), \
649 DescriptorCopy.Type, \
650 Type##Size); \
651 if (!RtlValidSid((PSID)((ULONG_PTR)NewDescriptor + \
652 (ULONG_PTR)NewDescriptor->Type))) \
653 { \
654 RtlRaiseStatus(STATUS_INVALID_SID); \
655 } \
656 Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
657 } \
658 } while(0)
659
660 CopySID(Owner);
661 CopySID(Group);
662
663 #undef CopySID
664
665 #define CopyACL(Type) \
666 do { \
667 if(DescriptorCopy.Type != NULL) \
668 { \
669 NewDescriptor->Type = (PVOID)Offset; \
670 RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
671 (ULONG_PTR)NewDescriptor->Type), \
672 DescriptorCopy.Type, \
673 Type##Size); \
674 if (!RtlValidAcl((PACL)((ULONG_PTR)NewDescriptor + \
675 (ULONG_PTR)NewDescriptor->Type))) \
676 { \
677 RtlRaiseStatus(STATUS_INVALID_ACL); \
678 } \
679 Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
680 } \
681 } while(0)
682
683 CopyACL(Sacl);
684 CopyACL(Dacl);
685
686 #undef CopyACL
687 }
688 _SEH_HANDLE
689 {
690 Status = _SEH_GetExceptionCode();
691 }
692 _SEH_END;
693
694 if(NT_SUCCESS(Status))
695 {
696 /* we're finally done! copy the pointer to the captured descriptor to
697 to the caller */
698 *CapturedSecurityDescriptor = NewDescriptor;
699 return STATUS_SUCCESS;
700 }
701 else
702 {
703 /* we failed to copy the data to the new descriptor */
704 ExFreePool(NewDescriptor);
705 }
706 }
707 else
708 {
709 Status = STATUS_INSUFFICIENT_RESOURCES;
710 }
711 }
712 else
713 {
714 /* nothing to do... */
715 *CapturedSecurityDescriptor = NULL;
716 }
717
718 return Status;
719 }
720
721 /*
722 * @implemented
723 */
724 NTSTATUS STDCALL
725 SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation,
726 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
727 IN OUT PULONG Length,
728 IN PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor OPTIONAL)
729 {
730 PISECURITY_DESCRIPTOR ObjectSd;
731 PISECURITY_DESCRIPTOR_RELATIVE RelSD;
732 PSID Owner = NULL;
733 PSID Group = NULL;
734 PACL Dacl = NULL;
735 PACL Sacl = NULL;
736 ULONG OwnerLength = 0;
737 ULONG GroupLength = 0;
738 ULONG DaclLength = 0;
739 ULONG SaclLength = 0;
740 ULONG Control = 0;
741 ULONG_PTR Current;
742 ULONG SdLength;
743
744 RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
745
746 if (*ObjectsSecurityDescriptor == NULL)
747 {
748 if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE))
749 {
750 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
751 return STATUS_BUFFER_TOO_SMALL;
752 }
753
754 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
755 RtlCreateSecurityDescriptorRelative(RelSD,
756 SECURITY_DESCRIPTOR_REVISION);
757 return STATUS_SUCCESS;
758 }
759
760 ObjectSd = *ObjectsSecurityDescriptor;
761
762 /* Calculate the required security descriptor length */
763 Control = SE_SELF_RELATIVE;
764 if ((*SecurityInformation & OWNER_SECURITY_INFORMATION) &&
765 (ObjectSd->Owner != NULL))
766 {
767 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
768 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
769 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
770 }
771
772 if ((*SecurityInformation & GROUP_SECURITY_INFORMATION) &&
773 (ObjectSd->Group != NULL))
774 {
775 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
776 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
777 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
778 }
779
780 if ((*SecurityInformation & DACL_SECURITY_INFORMATION) &&
781 (ObjectSd->Control & SE_DACL_PRESENT))
782 {
783 if (ObjectSd->Dacl != NULL)
784 {
785 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
786 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
787 }
788 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
789 }
790
791 if ((*SecurityInformation & SACL_SECURITY_INFORMATION) &&
792 (ObjectSd->Control & SE_SACL_PRESENT))
793 {
794 if (ObjectSd->Sacl != NULL)
795 {
796 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
797 SaclLength = ROUND_UP(Sacl->AclSize, 4);
798 }
799 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
800 }
801
802 SdLength = OwnerLength + GroupLength + DaclLength +
803 SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE);
804 if (*Length < SdLength)
805 {
806 *Length = SdLength;
807 return STATUS_BUFFER_TOO_SMALL;
808 }
809
810 /* Build the new security descrtiptor */
811 RtlCreateSecurityDescriptorRelative(RelSD,
812 SECURITY_DESCRIPTOR_REVISION);
813 RelSD->Control = Control;
814
815 Current = (ULONG_PTR)(RelSD + 1);
816
817 if (OwnerLength != 0)
818 {
819 RtlCopyMemory((PVOID)Current,
820 Owner,
821 OwnerLength);
822 RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
823 Current += OwnerLength;
824 }
825
826 if (GroupLength != 0)
827 {
828 RtlCopyMemory((PVOID)Current,
829 Group,
830 GroupLength);
831 RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
832 Current += GroupLength;
833 }
834
835 if (DaclLength != 0)
836 {
837 RtlCopyMemory((PVOID)Current,
838 Dacl,
839 DaclLength);
840 RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
841 Current += DaclLength;
842 }
843
844 if (SaclLength != 0)
845 {
846 RtlCopyMemory((PVOID)Current,
847 Sacl,
848 SaclLength);
849 RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
850 Current += SaclLength;
851 }
852
853 *Length = SdLength;
854
855 return STATUS_SUCCESS;
856 }
857
858 /*
859 * @implemented
860 */
861 NTSTATUS
862 STDCALL
863 SeReleaseSecurityDescriptor(
864 IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor,
865 IN KPROCESSOR_MODE CurrentMode,
866 IN BOOLEAN CaptureIfKernelMode
867 )
868 {
869 PAGED_CODE();
870
871 /* WARNING! You need to call this function with the same value for CurrentMode
872 and CaptureIfKernelMode that you previously passed to
873 SeCaptureSecurityDescriptor() in order to avoid memory leaks! */
874 if(CapturedSecurityDescriptor != NULL &&
875 (CurrentMode != KernelMode ||
876 (CurrentMode == KernelMode && CaptureIfKernelMode)))
877 {
878 /* only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
879 ExFreePool(CapturedSecurityDescriptor);
880 }
881
882 return STATUS_SUCCESS;
883 }
884
885 /*
886 * @unimplemented
887 */
888 NTSTATUS STDCALL
889 SeSetSecurityDescriptorInfo(IN PVOID Object OPTIONAL,
890 IN PSECURITY_INFORMATION SecurityInformation,
891 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
892 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
893 IN POOL_TYPE PoolType,
894 IN PGENERIC_MAPPING GenericMapping)
895 {
896 UNIMPLEMENTED;
897 return STATUS_NOT_IMPLEMENTED;
898 }
899
900 /*
901 * @unimplemented
902 */
903 NTSTATUS
904 STDCALL
905 SeSetSecurityDescriptorInfoEx(
906 IN PVOID Object OPTIONAL,
907 IN PSECURITY_INFORMATION SecurityInformation,
908 IN PSECURITY_DESCRIPTOR ModificationDescriptor,
909 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
910 IN ULONG AutoInheritFlags,
911 IN POOL_TYPE PoolType,
912 IN PGENERIC_MAPPING GenericMapping
913 )
914 {
915 UNIMPLEMENTED;
916 return STATUS_NOT_IMPLEMENTED;
917 }
918
919
920 /*
921 * @implemented
922 */
923 BOOLEAN STDCALL
924 SeValidSecurityDescriptor(IN ULONG Length,
925 IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
926 {
927 ULONG SdLength;
928 PISID Sid;
929 PACL Acl;
930 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
931
932 if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
933 {
934 DPRINT1("Invalid Security Descriptor revision\n");
935 return FALSE;
936 }
937
938 if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
939 {
940 DPRINT1("Invalid Security Descriptor revision\n");
941 return FALSE;
942 }
943
944 if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE))
945 {
946 DPRINT1("No self-relative Security Descriptor\n");
947 return FALSE;
948 }
949
950 SdLength = sizeof(SECURITY_DESCRIPTOR);
951
952 /* Check Owner SID */
953 if (SecurityDescriptor->Owner == NULL)
954 {
955 DPRINT1("No Owner SID\n");
956 return FALSE;
957 }
958
959 if ((ULONG_PTR)SecurityDescriptor->Owner % sizeof(ULONG))
960 {
961 DPRINT1("Invalid Owner SID alignment\n");
962 return FALSE;
963 }
964
965 Sid = (PISID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Owner);
966 if (Sid->Revision != SID_REVISION)
967 {
968 DPRINT1("Invalid Owner SID revision\n");
969 return FALSE;
970 }
971
972 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
973 if (Length < SdLength)
974 {
975 DPRINT1("Invalid Owner SID size\n");
976 return FALSE;
977 }
978
979 /* Check Group SID */
980 if (SecurityDescriptor->Group != NULL)
981 {
982 if ((ULONG_PTR)SecurityDescriptor->Group % sizeof(ULONG))
983 {
984 DPRINT1("Invalid Group SID alignment\n");
985 return FALSE;
986 }
987
988 Sid = (PSID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Group);
989 if (Sid->Revision != SID_REVISION)
990 {
991 DPRINT1("Invalid Group SID revision\n");
992 return FALSE;
993 }
994
995 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
996 if (Length < SdLength)
997 {
998 DPRINT1("Invalid Group SID size\n");
999 return FALSE;
1000 }
1001 }
1002
1003 /* Check DACL */
1004 if (SecurityDescriptor->Dacl != NULL)
1005 {
1006 if ((ULONG_PTR)SecurityDescriptor->Dacl % sizeof(ULONG))
1007 {
1008 DPRINT1("Invalid DACL alignment\n");
1009 return FALSE;
1010 }
1011
1012 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Dacl);
1013 if ((Acl->AclRevision < MIN_ACL_REVISION) &&
1014 (Acl->AclRevision > MAX_ACL_REVISION))
1015 {
1016 DPRINT1("Invalid DACL revision\n");
1017 return FALSE;
1018 }
1019
1020 SdLength += Acl->AclSize;
1021 if (Length < SdLength)
1022 {
1023 DPRINT1("Invalid DACL size\n");
1024 return FALSE;
1025 }
1026 }
1027
1028 /* Check SACL */
1029 if (SecurityDescriptor->Sacl != NULL)
1030 {
1031 if ((ULONG_PTR)SecurityDescriptor->Sacl % sizeof(ULONG))
1032 {
1033 DPRINT1("Invalid SACL alignment\n");
1034 return FALSE;
1035 }
1036
1037 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Sacl);
1038 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1039 (Acl->AclRevision > MAX_ACL_REVISION))
1040 {
1041 DPRINT1("Invalid SACL revision\n");
1042 return FALSE;
1043 }
1044
1045 SdLength += Acl->AclSize;
1046 if (Length < SdLength)
1047 {
1048 DPRINT1("Invalid SACL size\n");
1049 return FALSE;
1050 }
1051 }
1052
1053 return TRUE;
1054 }
1055
1056 /* EOF */