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