- NDK 0.98, now with versionned headers. Too many changes to list, see the TinyKRNL...
[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 STDCALL
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 = (DWORD)((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 = (DWORD)((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 = (DWORD)((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 = (ULONG)((ULONG_PTR)&OriginalSecurityDescriptor->Control -
415 (ULONG_PTR)OriginalSecurityDescriptor) +
416 sizeof(OriginalSecurityDescriptor->Control);
417 ProbeForRead(OriginalSecurityDescriptor,
418 DescriptorSize,
419 sizeof(ULONG));
420
421 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
422 {
423 Status = STATUS_UNKNOWN_REVISION;
424 _SEH_LEAVE;
425 }
426
427 /* make a copy on the stack */
428 DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
429 DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
430 DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
431 DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
432 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR));
433
434 /* probe and copy the entire security descriptor structure. The SIDs
435 and ACLs will be probed and copied later though */
436 ProbeForRead(OriginalSecurityDescriptor,
437 DescriptorSize,
438 sizeof(ULONG));
439 if(DescriptorCopy.Control & SE_SELF_RELATIVE)
440 {
441 PISECURITY_DESCRIPTOR_RELATIVE RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
442
443 DescriptorCopy.Owner = (PSID)RelSD->Owner;
444 DescriptorCopy.Group = (PSID)RelSD->Group;
445 DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
446 DescriptorCopy.Dacl = (PACL)RelSD->Dacl;
447 }
448 else
449 {
450 DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
451 DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
452 DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
453 DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
454 }
455 }
456 _SEH_HANDLE
457 {
458 Status = _SEH_GetExceptionCode();
459 }
460 _SEH_END;
461
462 if(!NT_SUCCESS(Status))
463 {
464 return Status;
465 }
466 }
467 else if(!CaptureIfKernel)
468 {
469 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
470 {
471 return STATUS_UNKNOWN_REVISION;
472 }
473
474 *CapturedSecurityDescriptor = OriginalSecurityDescriptor;
475 return STATUS_SUCCESS;
476 }
477 else
478 {
479 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
480 {
481 return STATUS_UNKNOWN_REVISION;
482 }
483
484 /* make a copy on the stack */
485 DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
486 DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
487 DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
488 DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
489 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR));
490 if(DescriptorCopy.Control & SE_SELF_RELATIVE)
491 {
492 PISECURITY_DESCRIPTOR_RELATIVE RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
493
494 DescriptorCopy.Owner = (PSID)RelSD->Owner;
495 DescriptorCopy.Group = (PSID)RelSD->Group;
496 DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
497 DescriptorCopy.Dacl = (PACL)RelSD->Dacl;
498 }
499 else
500 {
501 DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
502 DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
503 DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
504 DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
505 }
506 }
507
508 if(DescriptorCopy.Control & SE_SELF_RELATIVE)
509 {
510 /* in case we're dealing with a self-relative descriptor, do a basic convert
511 to an absolute descriptor. We do this so we can simply access the data
512 using the pointers without calculating them again. */
513 DescriptorCopy.Control &= ~SE_SELF_RELATIVE;
514 if(DescriptorCopy.Owner != NULL)
515 {
516 DescriptorCopy.Owner = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Owner);
517 }
518 if(DescriptorCopy.Group != NULL)
519 {
520 DescriptorCopy.Group = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Group);
521 }
522 if(DescriptorCopy.Dacl != NULL)
523 {
524 DescriptorCopy.Dacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Dacl);
525 }
526 if(DescriptorCopy.Sacl != NULL)
527 {
528 DescriptorCopy.Sacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Sacl);
529 }
530 }
531
532 /* determine the size of the SIDs */
533 #define DetermineSIDSize(SidType) \
534 do { \
535 if(DescriptorCopy.SidType != NULL) \
536 { \
537 SID *SidType = (SID*)DescriptorCopy.SidType; \
538 \
539 if(CurrentMode != KernelMode) \
540 { \
541 /* securely access the buffers! */ \
542 _SEH_TRY \
543 { \
544 ProbeForRead(&SidType->SubAuthorityCount, \
545 sizeof(SidType->SubAuthorityCount), \
546 1); \
547 SidType##SAC = SidType->SubAuthorityCount; \
548 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
549 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
550 ProbeForRead(SidType, \
551 SidType##Size, \
552 sizeof(ULONG)); \
553 } \
554 _SEH_HANDLE \
555 { \
556 Status = _SEH_GetExceptionCode(); \
557 } \
558 _SEH_END; \
559 \
560 if(!NT_SUCCESS(Status)) \
561 { \
562 return Status; \
563 } \
564 } \
565 else \
566 { \
567 SidType##SAC = SidType->SubAuthorityCount; \
568 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
569 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
570 } \
571 } \
572 } while(0)
573
574 DetermineSIDSize(Owner);
575 DetermineSIDSize(Group);
576
577 /* determine the size of the ACLs */
578 #define DetermineACLSize(AclType, AclFlag) \
579 do { \
580 if((DescriptorCopy.Control & SE_##AclFlag##_PRESENT) && \
581 DescriptorCopy.AclType != NULL) \
582 { \
583 PACL AclType = (PACL)DescriptorCopy.AclType; \
584 \
585 if(CurrentMode != KernelMode) \
586 { \
587 /* securely access the buffers! */ \
588 _SEH_TRY \
589 { \
590 ProbeForRead(&AclType->AclSize, \
591 sizeof(AclType->AclSize), \
592 1); \
593 AclType##Size = AclType->AclSize; \
594 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
595 ProbeForRead(AclType, \
596 AclType##Size, \
597 sizeof(ULONG)); \
598 } \
599 _SEH_HANDLE \
600 { \
601 Status = _SEH_GetExceptionCode(); \
602 } \
603 _SEH_END; \
604 \
605 if(!NT_SUCCESS(Status)) \
606 { \
607 return Status; \
608 } \
609 } \
610 else \
611 { \
612 AclType##Size = AclType->AclSize; \
613 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
614 } \
615 } \
616 else \
617 { \
618 DescriptorCopy.AclType = NULL; \
619 } \
620 } while(0)
621
622 DetermineACLSize(Sacl, SACL);
623 DetermineACLSize(Dacl, DACL);
624
625 /* allocate enough memory to store a complete copy of a self-relative
626 security descriptor */
627 NewDescriptor = ExAllocatePool(PoolType,
628 DescriptorSize);
629 if(NewDescriptor != NULL)
630 {
631 ULONG_PTR Offset = sizeof(SECURITY_DESCRIPTOR);
632
633 RtlZeroMemory(NewDescriptor, DescriptorSize);
634 NewDescriptor->Revision = DescriptorCopy.Revision;
635 NewDescriptor->Sbz1 = DescriptorCopy.Sbz1;
636 NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE;
637
638 _SEH_TRY
639 {
640 /* setup the offsets and copy the SIDs and ACLs to the new
641 self-relative security descriptor. Probing the pointers is not
642 neccessary anymore as we did that when collecting the sizes!
643 Make sure to validate the SIDs and ACLs *again* as they could have
644 been modified in the meanwhile! */
645 #define CopySID(Type) \
646 do { \
647 if(DescriptorCopy.Type != NULL) \
648 { \
649 NewDescriptor->Type = (PVOID)Offset; \
650 RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
651 (ULONG_PTR)NewDescriptor->Type), \
652 DescriptorCopy.Type, \
653 Type##Size); \
654 if (!RtlValidSid((PSID)((ULONG_PTR)NewDescriptor + \
655 (ULONG_PTR)NewDescriptor->Type))) \
656 { \
657 RtlRaiseStatus(STATUS_INVALID_SID); \
658 } \
659 Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
660 } \
661 } while(0)
662
663 CopySID(Owner);
664 CopySID(Group);
665
666 #define CopyACL(Type) \
667 do { \
668 if(DescriptorCopy.Type != NULL) \
669 { \
670 NewDescriptor->Type = (PVOID)Offset; \
671 RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
672 (ULONG_PTR)NewDescriptor->Type), \
673 DescriptorCopy.Type, \
674 Type##Size); \
675 if (!RtlValidAcl((PACL)((ULONG_PTR)NewDescriptor + \
676 (ULONG_PTR)NewDescriptor->Type))) \
677 { \
678 RtlRaiseStatus(STATUS_INVALID_ACL); \
679 } \
680 Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
681 } \
682 } while(0)
683
684 CopyACL(Sacl);
685 CopyACL(Dacl);
686 }
687 _SEH_HANDLE
688 {
689 Status = _SEH_GetExceptionCode();
690 }
691 _SEH_END;
692
693 if(NT_SUCCESS(Status))
694 {
695 /* we're finally done! copy the pointer to the captured descriptor to
696 to the caller */
697 *CapturedSecurityDescriptor = NewDescriptor;
698 return STATUS_SUCCESS;
699 }
700 else
701 {
702 /* we failed to copy the data to the new descriptor */
703 ExFreePool(NewDescriptor);
704 }
705 }
706 else
707 {
708 Status = STATUS_INSUFFICIENT_RESOURCES;
709 }
710 }
711 else
712 {
713 /* nothing to do... */
714 *CapturedSecurityDescriptor = NULL;
715 }
716
717 return Status;
718 }
719
720 /*
721 * @implemented
722 */
723 NTSTATUS STDCALL
724 SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation,
725 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
726 IN OUT PULONG Length,
727 IN PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor OPTIONAL)
728 {
729 PISECURITY_DESCRIPTOR ObjectSd;
730 PISECURITY_DESCRIPTOR_RELATIVE RelSD;
731 PSID Owner = NULL;
732 PSID Group = NULL;
733 PACL Dacl = NULL;
734 PACL Sacl = NULL;
735 ULONG OwnerLength = 0;
736 ULONG GroupLength = 0;
737 ULONG DaclLength = 0;
738 ULONG SaclLength = 0;
739 ULONG Control = 0;
740 ULONG_PTR Current;
741 ULONG SdLength;
742
743 RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
744
745 if (*ObjectsSecurityDescriptor == NULL)
746 {
747 if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE))
748 {
749 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
750 return STATUS_BUFFER_TOO_SMALL;
751 }
752
753 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
754 RtlCreateSecurityDescriptorRelative(RelSD,
755 SECURITY_DESCRIPTOR_REVISION);
756 return STATUS_SUCCESS;
757 }
758
759 ObjectSd = *ObjectsSecurityDescriptor;
760
761 /* Calculate the required security descriptor length */
762 Control = SE_SELF_RELATIVE;
763 if ((*SecurityInformation & OWNER_SECURITY_INFORMATION) &&
764 (ObjectSd->Owner != NULL))
765 {
766 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
767 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
768 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
769 }
770
771 if ((*SecurityInformation & GROUP_SECURITY_INFORMATION) &&
772 (ObjectSd->Group != NULL))
773 {
774 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
775 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
776 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
777 }
778
779 if ((*SecurityInformation & DACL_SECURITY_INFORMATION) &&
780 (ObjectSd->Control & SE_DACL_PRESENT))
781 {
782 if (ObjectSd->Dacl != NULL)
783 {
784 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
785 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
786 }
787 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
788 }
789
790 if ((*SecurityInformation & SACL_SECURITY_INFORMATION) &&
791 (ObjectSd->Control & SE_SACL_PRESENT))
792 {
793 if (ObjectSd->Sacl != NULL)
794 {
795 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
796 SaclLength = ROUND_UP(Sacl->AclSize, 4);
797 }
798 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
799 }
800
801 SdLength = OwnerLength + GroupLength + DaclLength +
802 SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE);
803 if (*Length < SdLength)
804 {
805 *Length = SdLength;
806 return STATUS_BUFFER_TOO_SMALL;
807 }
808
809 /* Build the new security descrtiptor */
810 RtlCreateSecurityDescriptorRelative(RelSD,
811 SECURITY_DESCRIPTOR_REVISION);
812 RelSD->Control = Control;
813
814 Current = (ULONG_PTR)(RelSD + 1);
815
816 if (OwnerLength != 0)
817 {
818 RtlCopyMemory((PVOID)Current,
819 Owner,
820 OwnerLength);
821 RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
822 Current += OwnerLength;
823 }
824
825 if (GroupLength != 0)
826 {
827 RtlCopyMemory((PVOID)Current,
828 Group,
829 GroupLength);
830 RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
831 Current += GroupLength;
832 }
833
834 if (DaclLength != 0)
835 {
836 RtlCopyMemory((PVOID)Current,
837 Dacl,
838 DaclLength);
839 RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
840 Current += DaclLength;
841 }
842
843 if (SaclLength != 0)
844 {
845 RtlCopyMemory((PVOID)Current,
846 Sacl,
847 SaclLength);
848 RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
849 Current += SaclLength;
850 }
851
852 *Length = SdLength;
853
854 return STATUS_SUCCESS;
855 }
856
857 /*
858 * @implemented
859 */
860 NTSTATUS
861 STDCALL
862 SeReleaseSecurityDescriptor(
863 IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor,
864 IN KPROCESSOR_MODE CurrentMode,
865 IN BOOLEAN CaptureIfKernelMode
866 )
867 {
868 PAGED_CODE();
869
870 /* WARNING! You need to call this function with the same value for CurrentMode
871 and CaptureIfKernelMode that you previously passed to
872 SeCaptureSecurityDescriptor() in order to avoid memory leaks! */
873 if(CapturedSecurityDescriptor != NULL &&
874 (CurrentMode != KernelMode ||
875 (CurrentMode == KernelMode && CaptureIfKernelMode)))
876 {
877 /* only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
878 ExFreePool(CapturedSecurityDescriptor);
879 }
880
881 return STATUS_SUCCESS;
882 }
883
884 /*
885 * @unimplemented
886 */
887 NTSTATUS STDCALL
888 SeSetSecurityDescriptorInfo(IN PVOID Object OPTIONAL,
889 IN PSECURITY_INFORMATION SecurityInformation,
890 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
891 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
892 IN POOL_TYPE PoolType,
893 IN PGENERIC_MAPPING GenericMapping)
894 {
895 UNIMPLEMENTED;
896 return STATUS_NOT_IMPLEMENTED;
897 }
898
899 /*
900 * @unimplemented
901 */
902 NTSTATUS
903 STDCALL
904 SeSetSecurityDescriptorInfoEx(
905 IN PVOID Object OPTIONAL,
906 IN PSECURITY_INFORMATION SecurityInformation,
907 IN PSECURITY_DESCRIPTOR ModificationDescriptor,
908 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
909 IN ULONG AutoInheritFlags,
910 IN POOL_TYPE PoolType,
911 IN PGENERIC_MAPPING GenericMapping
912 )
913 {
914 UNIMPLEMENTED;
915 return STATUS_NOT_IMPLEMENTED;
916 }
917
918
919 /*
920 * @implemented
921 */
922 BOOLEAN STDCALL
923 SeValidSecurityDescriptor(IN ULONG Length,
924 IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
925 {
926 ULONG SdLength;
927 PISID Sid;
928 PACL Acl;
929 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
930
931 if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
932 {
933 DPRINT1("Invalid Security Descriptor revision\n");
934 return FALSE;
935 }
936
937 if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
938 {
939 DPRINT1("Invalid Security Descriptor revision\n");
940 return FALSE;
941 }
942
943 if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE))
944 {
945 DPRINT1("No self-relative Security Descriptor\n");
946 return FALSE;
947 }
948
949 SdLength = sizeof(SECURITY_DESCRIPTOR);
950
951 /* Check Owner SID */
952 if (SecurityDescriptor->Owner == NULL)
953 {
954 DPRINT1("No Owner SID\n");
955 return FALSE;
956 }
957
958 if ((ULONG_PTR)SecurityDescriptor->Owner % sizeof(ULONG))
959 {
960 DPRINT1("Invalid Owner SID alignment\n");
961 return FALSE;
962 }
963
964 Sid = (PISID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Owner);
965 if (Sid->Revision != SID_REVISION)
966 {
967 DPRINT1("Invalid Owner SID revision\n");
968 return FALSE;
969 }
970
971 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
972 if (Length < SdLength)
973 {
974 DPRINT1("Invalid Owner SID size\n");
975 return FALSE;
976 }
977
978 /* Check Group SID */
979 if (SecurityDescriptor->Group != NULL)
980 {
981 if ((ULONG_PTR)SecurityDescriptor->Group % sizeof(ULONG))
982 {
983 DPRINT1("Invalid Group SID alignment\n");
984 return FALSE;
985 }
986
987 Sid = (PSID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Group);
988 if (Sid->Revision != SID_REVISION)
989 {
990 DPRINT1("Invalid Group SID revision\n");
991 return FALSE;
992 }
993
994 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
995 if (Length < SdLength)
996 {
997 DPRINT1("Invalid Group SID size\n");
998 return FALSE;
999 }
1000 }
1001
1002 /* Check DACL */
1003 if (SecurityDescriptor->Dacl != NULL)
1004 {
1005 if ((ULONG_PTR)SecurityDescriptor->Dacl % sizeof(ULONG))
1006 {
1007 DPRINT1("Invalid DACL alignment\n");
1008 return FALSE;
1009 }
1010
1011 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Dacl);
1012 if ((Acl->AclRevision < MIN_ACL_REVISION) &&
1013 (Acl->AclRevision > MAX_ACL_REVISION))
1014 {
1015 DPRINT1("Invalid DACL revision\n");
1016 return FALSE;
1017 }
1018
1019 SdLength += Acl->AclSize;
1020 if (Length < SdLength)
1021 {
1022 DPRINT1("Invalid DACL size\n");
1023 return FALSE;
1024 }
1025 }
1026
1027 /* Check SACL */
1028 if (SecurityDescriptor->Sacl != NULL)
1029 {
1030 if ((ULONG_PTR)SecurityDescriptor->Sacl % sizeof(ULONG))
1031 {
1032 DPRINT1("Invalid SACL alignment\n");
1033 return FALSE;
1034 }
1035
1036 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Sacl);
1037 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1038 (Acl->AclRevision > MAX_ACL_REVISION))
1039 {
1040 DPRINT1("Invalid SACL revision\n");
1041 return FALSE;
1042 }
1043
1044 SdLength += Acl->AclSize;
1045 if (Length < SdLength)
1046 {
1047 DPRINT1("Invalid SACL size\n");
1048 return FALSE;
1049 }
1050 }
1051
1052 return TRUE;
1053 }
1054
1055 /* EOF */