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