Clear the memory after we know that the buffer was allocated.
[reactos.git] / reactos / ntoskrnl / se / semgr.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/semgr.c
6 * PURPOSE: Security manager
7 *
8 * PROGRAMMERS: No programmer listed.
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS ******************************************************************/
18
19 PSE_EXPORTS SeExports = NULL;
20 SE_EXPORTS SepExports;
21
22 static ERESOURCE SepSubjectContextLock;
23
24
25 /* PROTOTYPES ***************************************************************/
26
27 static BOOLEAN SepInitExports(VOID);
28
29
30 /* FUNCTIONS ****************************************************************/
31
32 BOOLEAN INIT_FUNCTION
33 SeInit1(VOID)
34 {
35 SepInitLuid();
36
37 if (!SepInitSecurityIDs())
38 return FALSE;
39
40 if (!SepInitDACLs())
41 return FALSE;
42
43 if (!SepInitSDs())
44 return FALSE;
45
46 SepInitPrivileges();
47
48 if (!SepInitExports())
49 return FALSE;
50
51 /* Initialize the subject context lock */
52 ExInitializeResource(&SepSubjectContextLock);
53
54 return TRUE;
55 }
56
57
58 BOOLEAN INIT_FUNCTION
59 SeInit2(VOID)
60 {
61 SepInitializeTokenImplementation();
62
63 return TRUE;
64 }
65
66
67 BOOLEAN
68 SeInitSRM(VOID)
69 {
70 OBJECT_ATTRIBUTES ObjectAttributes;
71 UNICODE_STRING Name;
72 HANDLE DirectoryHandle;
73 HANDLE EventHandle;
74 NTSTATUS Status;
75
76 /* Create '\Security' directory */
77 RtlInitUnicodeString(&Name,
78 L"\\Security");
79 InitializeObjectAttributes(&ObjectAttributes,
80 &Name,
81 OBJ_PERMANENT,
82 0,
83 NULL);
84 Status = ZwCreateDirectoryObject(&DirectoryHandle,
85 DIRECTORY_ALL_ACCESS,
86 &ObjectAttributes);
87 if (!NT_SUCCESS(Status))
88 {
89 DPRINT1("Failed to create 'Security' directory!\n");
90 return FALSE;
91 }
92
93 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
94 RtlInitUnicodeString(&Name,
95 L"\\LSA_AUTHENTICATION_INITALIZED");
96 InitializeObjectAttributes(&ObjectAttributes,
97 &Name,
98 OBJ_PERMANENT,
99 DirectoryHandle,
100 SePublicDefaultSd);
101 Status = ZwCreateEvent(&EventHandle,
102 EVENT_ALL_ACCESS,
103 &ObjectAttributes,
104 SynchronizationEvent,
105 FALSE);
106 if (!NT_SUCCESS(Status))
107 {
108 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
109 NtClose(DirectoryHandle);
110 return FALSE;
111 }
112
113 ZwClose(EventHandle);
114 ZwClose(DirectoryHandle);
115
116 /* FIXME: Create SRM port and listener thread */
117
118 return TRUE;
119 }
120
121
122 static BOOLEAN INIT_FUNCTION
123 SepInitExports(VOID)
124 {
125 SepExports.SeCreateTokenPrivilege = SeCreateTokenPrivilege;
126 SepExports.SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
127 SepExports.SeLockMemoryPrivilege = SeLockMemoryPrivilege;
128 SepExports.SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
129 SepExports.SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
130 SepExports.SeTcbPrivilege = SeTcbPrivilege;
131 SepExports.SeSecurityPrivilege = SeSecurityPrivilege;
132 SepExports.SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
133 SepExports.SeLoadDriverPrivilege = SeLoadDriverPrivilege;
134 SepExports.SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
135 SepExports.SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
136 SepExports.SeSystemProfilePrivilege = SeSystemProfilePrivilege;
137 SepExports.SeSystemtimePrivilege = SeSystemtimePrivilege;
138 SepExports.SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
139 SepExports.SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
140 SepExports.SeBackupPrivilege = SeBackupPrivilege;
141 SepExports.SeRestorePrivilege = SeRestorePrivilege;
142 SepExports.SeShutdownPrivilege = SeShutdownPrivilege;
143 SepExports.SeDebugPrivilege = SeDebugPrivilege;
144 SepExports.SeAuditPrivilege = SeAuditPrivilege;
145 SepExports.SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
146 SepExports.SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
147 SepExports.SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
148
149 SepExports.SeNullSid = SeNullSid;
150 SepExports.SeWorldSid = SeWorldSid;
151 SepExports.SeLocalSid = SeLocalSid;
152 SepExports.SeCreatorOwnerSid = SeCreatorOwnerSid;
153 SepExports.SeCreatorGroupSid = SeCreatorGroupSid;
154 SepExports.SeNtAuthoritySid = SeNtAuthoritySid;
155 SepExports.SeDialupSid = SeDialupSid;
156 SepExports.SeNetworkSid = SeNetworkSid;
157 SepExports.SeBatchSid = SeBatchSid;
158 SepExports.SeInteractiveSid = SeInteractiveSid;
159 SepExports.SeLocalSystemSid = SeLocalSystemSid;
160 SepExports.SeAliasAdminsSid = SeAliasAdminsSid;
161 SepExports.SeAliasUsersSid = SeAliasUsersSid;
162 SepExports.SeAliasGuestsSid = SeAliasGuestsSid;
163 SepExports.SeAliasPowerUsersSid = SeAliasPowerUsersSid;
164 SepExports.SeAliasAccountOpsSid = SeAliasAccountOpsSid;
165 SepExports.SeAliasSystemOpsSid = SeAliasSystemOpsSid;
166 SepExports.SeAliasPrintOpsSid = SeAliasPrintOpsSid;
167 SepExports.SeAliasBackupOpsSid = SeAliasBackupOpsSid;
168 SepExports.SeAuthenticatedUsersSid = SeAuthenticatedUsersSid;
169 SepExports.SeRestrictedSid = SeRestrictedSid;
170 SepExports.SeAnonymousLogonSid = SeAnonymousLogonSid;
171
172 SepExports.SeUndockPrivilege = SeUndockPrivilege;
173 SepExports.SeSyncAgentPrivilege = SeSyncAgentPrivilege;
174 SepExports.SeEnableDelegationPrivilege = SeEnableDelegationPrivilege;
175
176 SeExports = &SepExports;
177 return TRUE;
178 }
179
180
181 VOID SepReferenceLogonSession(PLUID AuthenticationId)
182 {
183 UNIMPLEMENTED;
184 }
185
186 VOID SepDeReferenceLogonSession(PLUID AuthenticationId)
187 {
188 UNIMPLEMENTED;
189 }
190
191 NTSTATUS
192 STDCALL
193 SeDefaultObjectMethod(PVOID Object,
194 SECURITY_OPERATION_CODE OperationType,
195 SECURITY_INFORMATION SecurityInformation,
196 PSECURITY_DESCRIPTOR SecurityDescriptor,
197 PULONG ReturnLength,
198 PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
199 POOL_TYPE PoolType,
200 PGENERIC_MAPPING GenericMapping)
201 {
202 PSECURITY_DESCRIPTOR ObjectSd;
203 PSECURITY_DESCRIPTOR NewSd;
204 POBJECT_HEADER Header = BODY_TO_HEADER(Object);
205 PSID Owner = 0;
206 PSID Group = 0;
207 PACL Dacl = 0;
208 PACL Sacl = 0;
209 ULONG OwnerLength = 0;
210 ULONG GroupLength = 0;
211 ULONG DaclLength = 0;
212 ULONG SaclLength = 0;
213 ULONG Control = 0;
214 ULONG_PTR Current;
215 NTSTATUS Status;
216
217 if (OperationType == SetSecurityDescriptor)
218 {
219 ObjectSd = Header->SecurityDescriptor;
220
221 /* Get owner and owner size */
222 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
223 {
224 if (SecurityDescriptor->Owner != NULL)
225 {
226 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
227 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
228 (ULONG_PTR)SecurityDescriptor);
229 else
230 Owner = (PSID)SecurityDescriptor->Owner;
231 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
232 }
233 Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
234 }
235 else
236 {
237 if (ObjectSd->Owner != NULL)
238 {
239 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
240 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
241 }
242 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
243 }
244
245 /* Get group and group size */
246 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
247 {
248 if (SecurityDescriptor->Group != NULL)
249 {
250 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
251 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
252 (ULONG_PTR)SecurityDescriptor);
253 else
254 Group = (PSID)SecurityDescriptor->Group;
255 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
256 }
257 Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
258 }
259 else
260 {
261 if (ObjectSd->Group != NULL)
262 {
263 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
264 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
265 }
266 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
267 }
268
269 /* Get DACL and DACL size */
270 if (SecurityInformation & DACL_SECURITY_INFORMATION)
271 {
272 if ((SecurityDescriptor->Control & SE_DACL_PRESENT) &&
273 (SecurityDescriptor->Dacl != NULL))
274 {
275 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
276 Dacl = (PACL)((ULONG_PTR)SecurityDescriptor->Dacl +
277 (ULONG_PTR)SecurityDescriptor);
278 else
279 Dacl = (PACL)SecurityDescriptor->Dacl;
280
281 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
282 }
283 Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
284 }
285 else
286 {
287 if ((ObjectSd->Control & SE_DACL_PRESENT) &&
288 (ObjectSd->Dacl != NULL))
289 {
290 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
291 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
292 }
293 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
294 }
295
296 /* Get SACL and SACL size */
297 if (SecurityInformation & SACL_SECURITY_INFORMATION)
298 {
299 if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
300 (SecurityDescriptor->Sacl != NULL))
301 {
302 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
303 Sacl = (PACL)((ULONG_PTR)SecurityDescriptor->Sacl +
304 (ULONG_PTR)SecurityDescriptor);
305 else
306 Sacl = (PACL)SecurityDescriptor->Sacl;
307 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
308 }
309 Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
310 }
311 else
312 {
313 if ((ObjectSd->Control & SE_SACL_PRESENT) &&
314 (ObjectSd->Sacl != NULL))
315 {
316 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
317 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
318 }
319 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
320 }
321
322 NewSd = ExAllocatePool(NonPagedPool,
323 sizeof(SECURITY_DESCRIPTOR) + OwnerLength + GroupLength +
324 DaclLength + SaclLength);
325 if (NewSd == NULL)
326 {
327 ObDereferenceObject(Object);
328 return STATUS_INSUFFICIENT_RESOURCES;
329 }
330
331 RtlCreateSecurityDescriptor(NewSd,
332 SECURITY_DESCRIPTOR_REVISION1);
333 /* We always build a self-relative descriptor */
334 NewSd->Control = Control | SE_SELF_RELATIVE;
335
336 Current = (ULONG_PTR)NewSd + sizeof(SECURITY_DESCRIPTOR);
337
338 if (OwnerLength != 0)
339 {
340 RtlCopyMemory((PVOID)Current,
341 Owner,
342 OwnerLength);
343 NewSd->Owner = (PSID)(Current - (ULONG_PTR)NewSd);
344 Current += OwnerLength;
345 }
346
347 if (GroupLength != 0)
348 {
349 RtlCopyMemory((PVOID)Current,
350 Group,
351 GroupLength);
352 NewSd->Group = (PSID)(Current - (ULONG_PTR)NewSd);
353 Current += GroupLength;
354 }
355
356 if (DaclLength != 0)
357 {
358 RtlCopyMemory((PVOID)Current,
359 Dacl,
360 DaclLength);
361 NewSd->Dacl = (PACL)(Current - (ULONG_PTR)NewSd);
362 Current += DaclLength;
363 }
364
365 if (SaclLength != 0)
366 {
367 RtlCopyMemory((PVOID)Current,
368 Sacl,
369 SaclLength);
370 NewSd->Sacl = (PACL)(Current - (ULONG_PTR)NewSd);
371 Current += SaclLength;
372 }
373
374 /* Add the new SD */
375 Status = ObpAddSecurityDescriptor(NewSd,
376 &Header->SecurityDescriptor);
377 if (NT_SUCCESS(Status))
378 {
379 /* Remove the old security descriptor */
380 ObpRemoveSecurityDescriptor(ObjectSd);
381 }
382 else
383 {
384 /* Restore the old security descriptor */
385 Header->SecurityDescriptor = ObjectSd;
386 }
387
388 ExFreePool(NewSd);
389 }
390 else if (OperationType == QuerySecurityDescriptor)
391 {
392 Status = SeQuerySecurityDescriptorInfo(&SecurityInformation,
393 SecurityDescriptor,
394 ReturnLength,
395 &Header->SecurityDescriptor);
396 }
397 else if (OperationType == AssignSecurityDescriptor)
398 {
399 /* Assign the security descriptor to the object header */
400 Status = ObpAddSecurityDescriptor(SecurityDescriptor,
401 &Header->SecurityDescriptor);
402 }
403
404
405 return STATUS_SUCCESS;
406 }
407
408 /*
409 * @implemented
410 */
411 VOID STDCALL
412 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
413 {
414 PETHREAD Thread;
415 BOOLEAN CopyOnOpen;
416 BOOLEAN EffectiveOnly;
417
418 PAGED_CODE();
419
420 Thread = PsGetCurrentThread();
421 if (Thread == NULL)
422 {
423 SubjectContext->ProcessAuditId = 0;
424 SubjectContext->PrimaryToken = NULL;
425 SubjectContext->ClientToken = NULL;
426 SubjectContext->ImpersonationLevel = 0;
427 }
428 else
429 {
430 SubjectContext->ProcessAuditId = Thread->ThreadsProcess;
431 SubjectContext->ClientToken =
432 PsReferenceImpersonationToken(Thread,
433 &CopyOnOpen,
434 &EffectiveOnly,
435 &SubjectContext->ImpersonationLevel);
436 SubjectContext->PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
437 }
438 }
439
440
441 /*
442 * @implemented
443 */
444 VOID STDCALL
445 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
446 {
447 PAGED_CODE();
448
449 KeEnterCriticalRegion();
450 ExAcquireResourceExclusiveLite(&SepSubjectContextLock, TRUE);
451 }
452
453
454 /*
455 * @implemented
456 */
457 VOID STDCALL
458 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
459 {
460 PAGED_CODE();
461
462 ExReleaseResourceLite(&SepSubjectContextLock);
463 KeLeaveCriticalRegion();
464 }
465
466
467 /*
468 * @implemented
469 */
470 VOID STDCALL
471 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
472 {
473 PAGED_CODE();
474
475 if (SubjectContext->PrimaryToken != NULL)
476 {
477 ObDereferenceObject(SubjectContext->PrimaryToken);
478 }
479
480 if (SubjectContext->ClientToken != NULL)
481 {
482 ObDereferenceObject(SubjectContext->ClientToken);
483 }
484 }
485
486
487 /*
488 * @implemented
489 */
490 NTSTATUS STDCALL
491 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
492 {
493 PAGED_CODE();
494
495 if (*SecurityDescriptor != NULL)
496 {
497 ExFreePool(*SecurityDescriptor);
498 *SecurityDescriptor = NULL;
499 }
500
501 return STATUS_SUCCESS;
502 }
503
504
505 /*
506 * @unimplemented
507 */
508 NTSTATUS STDCALL
509 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
510 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
511 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
512 IN GUID *ObjectType OPTIONAL,
513 IN BOOLEAN IsDirectoryObject,
514 IN ULONG AutoInheritFlags,
515 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
516 IN PGENERIC_MAPPING GenericMapping,
517 IN POOL_TYPE PoolType)
518 {
519 UNIMPLEMENTED;
520 return STATUS_NOT_IMPLEMENTED;
521 }
522
523
524 /*
525 * FUNCTION: Creates a security descriptor for a new object.
526 * ARGUMENTS:
527 * ParentDescriptor =
528 * ExplicitDescriptor =
529 * NewDescriptor =
530 * IsDirectoryObject =
531 * SubjectContext =
532 * GeneralMapping =
533 * PoolType =
534 * RETURNS: Status
535 *
536 * @implemented
537 */
538 NTSTATUS STDCALL
539 SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
540 PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
541 PSECURITY_DESCRIPTOR *NewDescriptor,
542 BOOLEAN IsDirectoryObject,
543 PSECURITY_SUBJECT_CONTEXT SubjectContext,
544 PGENERIC_MAPPING GenericMapping,
545 POOL_TYPE PoolType)
546 {
547 PSECURITY_DESCRIPTOR Descriptor;
548 PTOKEN Token;
549 ULONG OwnerLength = 0;
550 ULONG GroupLength = 0;
551 ULONG DaclLength = 0;
552 ULONG SaclLength = 0;
553 ULONG Length = 0;
554 ULONG Control = 0;
555 ULONG_PTR Current;
556 PSID Owner = NULL;
557 PSID Group = NULL;
558 PACL Dacl = NULL;
559 PACL Sacl = NULL;
560
561 PAGED_CODE();
562
563 /* Lock subject context */
564 SeLockSubjectContext(SubjectContext);
565
566 if (SubjectContext->ClientToken != NULL)
567 {
568 Token = SubjectContext->ClientToken;
569 }
570 else
571 {
572 Token = SubjectContext->PrimaryToken;
573 }
574
575
576 /* Inherit the Owner SID */
577 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
578 {
579 DPRINT("Use explicit owner sid!\n");
580 Owner = ExplicitDescriptor->Owner;
581
582 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
583 {
584 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
585
586 }
587 }
588 else
589 {
590 if (Token != NULL)
591 {
592 DPRINT("Use token owner sid!\n");
593 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
594 }
595 else
596 {
597 DPRINT("Use default owner sid!\n");
598 Owner = SeLocalSystemSid;
599 }
600
601 Control |= SE_OWNER_DEFAULTED;
602 }
603
604 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
605
606
607 /* Inherit the Group SID */
608 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
609 {
610 DPRINT("Use explicit group sid!\n");
611 Group = ExplicitDescriptor->Group;
612 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
613 {
614 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
615 }
616 }
617 else
618 {
619 if (Token != NULL)
620 {
621 DPRINT("Use token group sid!\n");
622 Group = Token->PrimaryGroup;
623 }
624 else
625 {
626 DPRINT("Use default group sid!\n");
627 Group = SeLocalSystemSid;
628 }
629
630 Control |= SE_OWNER_DEFAULTED;
631 }
632
633 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
634
635
636 /* Inherit the DACL */
637 if (ExplicitDescriptor != NULL &&
638 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
639 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
640 {
641 DPRINT("Use explicit DACL!\n");
642 Dacl = ExplicitDescriptor->Dacl;
643 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
644 {
645 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
646 }
647
648 Control |= SE_DACL_PRESENT;
649 }
650 else if (ParentDescriptor != NULL &&
651 (ParentDescriptor->Control & SE_DACL_PRESENT))
652 {
653 DPRINT("Use parent DACL!\n");
654 /* FIXME: Inherit */
655 Dacl = ParentDescriptor->Dacl;
656 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
657 {
658 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
659 }
660 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
661 }
662 else if (Token != NULL && Token->DefaultDacl != NULL)
663 {
664 DPRINT("Use token default DACL!\n");
665 /* FIXME: Inherit */
666 Dacl = Token->DefaultDacl;
667 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
668 }
669 else
670 {
671 DPRINT("Use NULL DACL!\n");
672 Dacl = NULL;
673 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
674 }
675
676 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
677
678
679 /* Inherit the SACL */
680 if (ExplicitDescriptor != NULL &&
681 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
682 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
683 {
684 DPRINT("Use explicit SACL!\n");
685 Sacl = ExplicitDescriptor->Sacl;
686 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
687 {
688 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
689 }
690
691 Control |= SE_SACL_PRESENT;
692 }
693 else if (ParentDescriptor != NULL &&
694 (ParentDescriptor->Control & SE_SACL_PRESENT))
695 {
696 DPRINT("Use parent SACL!\n");
697 /* FIXME: Inherit */
698 Sacl = ParentDescriptor->Sacl;
699 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
700 {
701 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
702 }
703 Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
704 }
705
706 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
707
708
709 /* Allocate and initialize the new security descriptor */
710 Length = sizeof(SECURITY_DESCRIPTOR) +
711 OwnerLength + GroupLength + DaclLength + SaclLength;
712
713 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
714 sizeof(SECURITY_DESCRIPTOR),
715 OwnerLength,
716 GroupLength,
717 DaclLength,
718 SaclLength);
719
720 Descriptor = ExAllocatePool(PagedPool,
721 Length);
722 if (Descriptor == NULL)
723 {
724 DPRINT1("ExAlloctePool() failed\n");
725 /* FIXME: Unlock subject context */
726 return STATUS_INSUFFICIENT_RESOURCES;
727 }
728
729 RtlZeroMemory( Descriptor, Length );
730 RtlCreateSecurityDescriptor(Descriptor,
731 SECURITY_DESCRIPTOR_REVISION);
732
733 Descriptor->Control = Control | SE_SELF_RELATIVE;
734
735 Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
736
737 if (SaclLength != 0)
738 {
739 RtlCopyMemory((PVOID)Current,
740 Sacl,
741 SaclLength);
742 Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
743 Current += SaclLength;
744 }
745
746 if (DaclLength != 0)
747 {
748 RtlCopyMemory((PVOID)Current,
749 Dacl,
750 DaclLength);
751 Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
752 Current += DaclLength;
753 }
754
755 if (OwnerLength != 0)
756 {
757 RtlCopyMemory((PVOID)Current,
758 Owner,
759 OwnerLength);
760 Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
761 Current += OwnerLength;
762 DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
763 }
764 else
765 DPRINT("Owner of %x is zero length\n", Descriptor);
766
767 if (GroupLength != 0)
768 {
769 memmove((PVOID)Current,
770 Group,
771 GroupLength);
772 Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
773 }
774
775 /* Unlock subject context */
776 SeUnlockSubjectContext(SubjectContext);
777
778 *NewDescriptor = Descriptor;
779
780 DPRINT("Descrptor %x\n", Descriptor);
781 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
782
783 return STATUS_SUCCESS;
784 }
785
786
787 static BOOLEAN
788 SepSidInToken(PACCESS_TOKEN _Token,
789 PSID Sid)
790 {
791 ULONG i;
792 PTOKEN Token = (PTOKEN)_Token;
793
794 PAGED_CODE();
795
796 if (Token->UserAndGroupCount == 0)
797 {
798 return FALSE;
799 }
800
801 for (i=0; i<Token->UserAndGroupCount; i++)
802 {
803 if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
804 {
805 if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
806 {
807 return TRUE;
808 }
809
810 return FALSE;
811 }
812 }
813
814 return FALSE;
815 }
816
817
818 /*
819 * FUNCTION: Determines whether the requested access rights can be granted
820 * to an object protected by a security descriptor and an object owner
821 * ARGUMENTS:
822 * SecurityDescriptor = Security descriptor protecting the object
823 * SubjectSecurityContext = Subject's captured security context
824 * SubjectContextLocked = Indicates the user's subject context is locked
825 * DesiredAccess = Access rights the caller is trying to acquire
826 * PreviouslyGrantedAccess = Specified the access rights already granted
827 * Privileges = ?
828 * GenericMapping = Generic mapping associated with the object
829 * AccessMode = Access mode used for the check
830 * GrantedAccess (OUT) = On return specifies the access granted
831 * AccessStatus (OUT) = Status indicating why access was denied
832 * RETURNS: If access was granted, returns TRUE
833 *
834 * @implemented
835 */
836 BOOLEAN STDCALL
837 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
838 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
839 IN BOOLEAN SubjectContextLocked,
840 IN ACCESS_MASK DesiredAccess,
841 IN ACCESS_MASK PreviouslyGrantedAccess,
842 OUT PPRIVILEGE_SET* Privileges,
843 IN PGENERIC_MAPPING GenericMapping,
844 IN KPROCESSOR_MODE AccessMode,
845 OUT PACCESS_MASK GrantedAccess,
846 OUT PNTSTATUS AccessStatus)
847 {
848 LUID_AND_ATTRIBUTES Privilege;
849 ACCESS_MASK CurrentAccess;
850 PACCESS_TOKEN Token;
851 ULONG i;
852 PACL Dacl;
853 BOOLEAN Present;
854 BOOLEAN Defaulted;
855 PACE CurrentAce;
856 PSID Sid;
857 NTSTATUS Status;
858
859 PAGED_CODE();
860
861 CurrentAccess = PreviouslyGrantedAccess;
862
863 if (SubjectContextLocked == FALSE)
864 {
865 SeLockSubjectContext(SubjectSecurityContext);
866 }
867
868 Token = SubjectSecurityContext->ClientToken ?
869 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
870
871 /* Get the DACL */
872 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
873 &Present,
874 &Dacl,
875 &Defaulted);
876 if (!NT_SUCCESS(Status))
877 {
878 if (SubjectContextLocked == FALSE)
879 {
880 SeUnlockSubjectContext(SubjectSecurityContext);
881 }
882
883 *AccessStatus = Status;
884 return FALSE;
885 }
886
887 /* RULE 1: Grant desired access if the object is unprotected */
888 if (Present == TRUE && Dacl == NULL)
889 {
890 if (SubjectContextLocked == FALSE)
891 {
892 SeUnlockSubjectContext(SubjectSecurityContext);
893 }
894
895 *GrantedAccess = DesiredAccess;
896 *AccessStatus = STATUS_SUCCESS;
897 return TRUE;
898 }
899
900 CurrentAccess = PreviouslyGrantedAccess;
901
902 /* RULE 2: Check token for 'take ownership' privilege */
903 Privilege.Luid = SeTakeOwnershipPrivilege;
904 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
905
906 if (SepPrivilegeCheck(Token,
907 &Privilege,
908 1,
909 PRIVILEGE_SET_ALL_NECESSARY,
910 AccessMode))
911 {
912 CurrentAccess |= WRITE_OWNER;
913 if (DesiredAccess == CurrentAccess)
914 {
915 if (SubjectContextLocked == FALSE)
916 {
917 SeUnlockSubjectContext(SubjectSecurityContext);
918 }
919
920 *GrantedAccess = CurrentAccess;
921 *AccessStatus = STATUS_SUCCESS;
922 return TRUE;
923 }
924 }
925
926 /* RULE 3: Check whether the token is the owner */
927 Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
928 &Sid,
929 &Defaulted);
930 if (!NT_SUCCESS(Status))
931 {
932 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
933 if (SubjectContextLocked == FALSE)
934 {
935 SeUnlockSubjectContext(SubjectSecurityContext);
936 }
937
938 *AccessStatus = Status;
939 return FALSE;
940 }
941
942 if (SepSidInToken(Token, Sid))
943 {
944 CurrentAccess |= (READ_CONTROL | WRITE_DAC);
945 if (DesiredAccess == CurrentAccess)
946 {
947 if (SubjectContextLocked == FALSE)
948 {
949 SeUnlockSubjectContext(SubjectSecurityContext);
950 }
951
952 *GrantedAccess = CurrentAccess;
953 *AccessStatus = STATUS_SUCCESS;
954 return TRUE;
955 }
956 }
957
958 /* Fail if DACL is absent */
959 if (Present == FALSE)
960 {
961 if (SubjectContextLocked == FALSE)
962 {
963 SeUnlockSubjectContext(SubjectSecurityContext);
964 }
965
966 *GrantedAccess = 0;
967 *AccessStatus = STATUS_ACCESS_DENIED;
968 return TRUE;
969 }
970
971 /* RULE 4: Grant rights according to the DACL */
972 CurrentAce = (PACE)(Dacl + 1);
973 for (i = 0; i < Dacl->AceCount; i++)
974 {
975 Sid = (PSID)(CurrentAce + 1);
976 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
977 {
978 if (SepSidInToken(Token, Sid))
979 {
980 if (SubjectContextLocked == FALSE)
981 {
982 SeUnlockSubjectContext(SubjectSecurityContext);
983 }
984
985 *GrantedAccess = 0;
986 *AccessStatus = STATUS_ACCESS_DENIED;
987 return TRUE;
988 }
989 }
990
991 if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
992 {
993 if (SepSidInToken(Token, Sid))
994 {
995 CurrentAccess |= CurrentAce->AccessMask;
996 }
997 }
998 }
999
1000 if (SubjectContextLocked == FALSE)
1001 {
1002 SeUnlockSubjectContext(SubjectSecurityContext);
1003 }
1004
1005 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
1006 CurrentAccess, DesiredAccess);
1007
1008 *GrantedAccess = CurrentAccess & DesiredAccess;
1009
1010 *AccessStatus =
1011 (*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
1012
1013 return TRUE;
1014 }
1015
1016
1017 NTSTATUS STDCALL
1018 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1019 IN HANDLE TokenHandle,
1020 IN ACCESS_MASK DesiredAccess,
1021 IN PGENERIC_MAPPING GenericMapping,
1022 OUT PPRIVILEGE_SET PrivilegeSet,
1023 OUT PULONG ReturnLength,
1024 OUT PACCESS_MASK GrantedAccess,
1025 OUT PNTSTATUS AccessStatus)
1026 {
1027 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
1028 KPROCESSOR_MODE PreviousMode;
1029 PTOKEN Token;
1030 NTSTATUS Status;
1031
1032 PAGED_CODE();
1033
1034 DPRINT("NtAccessCheck() called\n");
1035
1036 PreviousMode = KeGetPreviousMode();
1037 if (PreviousMode == KernelMode)
1038 {
1039 *GrantedAccess = DesiredAccess;
1040 *AccessStatus = STATUS_SUCCESS;
1041 return STATUS_SUCCESS;
1042 }
1043
1044 Status = ObReferenceObjectByHandle(TokenHandle,
1045 TOKEN_QUERY,
1046 SepTokenObjectType,
1047 PreviousMode,
1048 (PVOID*)&Token,
1049 NULL);
1050 if (!NT_SUCCESS(Status))
1051 {
1052 DPRINT1("Failed to reference token (Status %lx)\n", Status);
1053 return Status;
1054 }
1055
1056 /* Check token type */
1057 if (Token->TokenType != TokenImpersonation)
1058 {
1059 DPRINT1("No impersonation token\n");
1060 ObDereferenceObject(Token);
1061 return STATUS_ACCESS_VIOLATION;
1062 }
1063
1064 /* Check impersonation level */
1065 if (Token->ImpersonationLevel < SecurityAnonymous)
1066 {
1067 DPRINT1("Invalid impersonation level\n");
1068 ObDereferenceObject(Token);
1069 return STATUS_ACCESS_VIOLATION;
1070 }
1071
1072 RtlZeroMemory(&SubjectSecurityContext,
1073 sizeof(SECURITY_SUBJECT_CONTEXT));
1074 SubjectSecurityContext.ClientToken = Token;
1075 SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
1076
1077 /* Lock subject context */
1078 SeLockSubjectContext(&SubjectSecurityContext);
1079
1080 if (SeAccessCheck(SecurityDescriptor,
1081 &SubjectSecurityContext,
1082 TRUE,
1083 DesiredAccess,
1084 0,
1085 &PrivilegeSet,
1086 GenericMapping,
1087 PreviousMode,
1088 GrantedAccess,
1089 AccessStatus))
1090 {
1091 Status = *AccessStatus;
1092 }
1093 else
1094 {
1095 Status = STATUS_ACCESS_DENIED;
1096 }
1097
1098 /* Unlock subject context */
1099 SeUnlockSubjectContext(&SubjectSecurityContext);
1100
1101 ObDereferenceObject(Token);
1102
1103 DPRINT("NtAccessCheck() done\n");
1104
1105 return Status;
1106 }
1107
1108 /* EOF */