1e606152e4e503ceb38489cdf3a8854e11c64a77
[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 #define TAG_SXPT TAG('S', 'X', 'P', 'T')
18
19
20 /* GLOBALS ******************************************************************/
21
22 PSE_EXPORTS EXPORTED SeExports = NULL;
23
24 static ERESOURCE SepSubjectContextLock;
25
26
27 /* PROTOTYPES ***************************************************************/
28
29 static BOOLEAN SepInitExports(VOID);
30
31
32 /* FUNCTIONS ****************************************************************/
33
34 BOOLEAN INIT_FUNCTION
35 SeInit1(VOID)
36 {
37 SepInitLuid();
38
39 if (!SepInitSecurityIDs())
40 return FALSE;
41
42 if (!SepInitDACLs())
43 return FALSE;
44
45 if (!SepInitSDs())
46 return FALSE;
47
48 SepInitPrivileges();
49
50 if (!SepInitExports())
51 return FALSE;
52
53 /* Initialize the subject context lock */
54 ExInitializeResource(&SepSubjectContextLock);
55
56 return TRUE;
57 }
58
59
60 BOOLEAN INIT_FUNCTION
61 SeInit2(VOID)
62 {
63 SepInitializeTokenImplementation();
64
65 return TRUE;
66 }
67
68
69 BOOLEAN
70 SeInitSRM(VOID)
71 {
72 OBJECT_ATTRIBUTES ObjectAttributes;
73 UNICODE_STRING Name;
74 HANDLE DirectoryHandle;
75 HANDLE EventHandle;
76 NTSTATUS Status;
77
78 /* Create '\Security' directory */
79 RtlInitUnicodeString(&Name,
80 L"\\Security");
81 InitializeObjectAttributes(&ObjectAttributes,
82 &Name,
83 OBJ_PERMANENT,
84 0,
85 NULL);
86 Status = ZwCreateDirectoryObject(&DirectoryHandle,
87 DIRECTORY_ALL_ACCESS,
88 &ObjectAttributes);
89 if (!NT_SUCCESS(Status))
90 {
91 DPRINT1("Failed to create 'Security' directory!\n");
92 return FALSE;
93 }
94
95 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
96 RtlInitUnicodeString(&Name,
97 L"\\LSA_AUTHENTICATION_INITALIZED");
98 InitializeObjectAttributes(&ObjectAttributes,
99 &Name,
100 OBJ_PERMANENT,
101 DirectoryHandle,
102 SePublicDefaultSd);
103 Status = ZwCreateEvent(&EventHandle,
104 EVENT_ALL_ACCESS,
105 &ObjectAttributes,
106 SynchronizationEvent,
107 FALSE);
108 if (!NT_SUCCESS(Status))
109 {
110 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
111 NtClose(DirectoryHandle);
112 return FALSE;
113 }
114
115 ZwClose(EventHandle);
116 ZwClose(DirectoryHandle);
117
118 /* FIXME: Create SRM port and listener thread */
119
120 return TRUE;
121 }
122
123
124 static BOOLEAN INIT_FUNCTION
125 SepInitExports(VOID)
126 {
127 SeExports = ExAllocatePoolWithTag(NonPagedPool,
128 sizeof(SE_EXPORTS),
129 TAG_SXPT);
130 if (SeExports == NULL)
131 return FALSE;
132
133 SeExports->SeCreateTokenPrivilege = SeCreateTokenPrivilege;
134 SeExports->SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
135 SeExports->SeLockMemoryPrivilege = SeLockMemoryPrivilege;
136 SeExports->SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
137 SeExports->SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
138 SeExports->SeTcbPrivilege = SeTcbPrivilege;
139 SeExports->SeSecurityPrivilege = SeSecurityPrivilege;
140 SeExports->SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
141 SeExports->SeLoadDriverPrivilege = SeLoadDriverPrivilege;
142 SeExports->SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
143 SeExports->SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
144 SeExports->SeSystemProfilePrivilege = SeSystemProfilePrivilege;
145 SeExports->SeSystemtimePrivilege = SeSystemtimePrivilege;
146 SeExports->SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
147 SeExports->SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
148 SeExports->SeBackupPrivilege = SeBackupPrivilege;
149 SeExports->SeRestorePrivilege = SeRestorePrivilege;
150 SeExports->SeShutdownPrivilege = SeShutdownPrivilege;
151 SeExports->SeDebugPrivilege = SeDebugPrivilege;
152 SeExports->SeAuditPrivilege = SeAuditPrivilege;
153 SeExports->SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
154 SeExports->SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
155 SeExports->SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
156
157 SeExports->SeNullSid = SeNullSid;
158 SeExports->SeWorldSid = SeWorldSid;
159 SeExports->SeLocalSid = SeLocalSid;
160 SeExports->SeCreatorOwnerSid = SeCreatorOwnerSid;
161 SeExports->SeCreatorGroupSid = SeCreatorGroupSid;
162 SeExports->SeNtAuthoritySid = SeNtAuthoritySid;
163 SeExports->SeDialupSid = SeDialupSid;
164 SeExports->SeNetworkSid = SeNetworkSid;
165 SeExports->SeBatchSid = SeBatchSid;
166 SeExports->SeInteractiveSid = SeInteractiveSid;
167 SeExports->SeLocalSystemSid = SeLocalSystemSid;
168 SeExports->SeAliasAdminsSid = SeAliasAdminsSid;
169 SeExports->SeAliasUsersSid = SeAliasUsersSid;
170 SeExports->SeAliasGuestsSid = SeAliasGuestsSid;
171 SeExports->SeAliasPowerUsersSid = SeAliasPowerUsersSid;
172 SeExports->SeAliasAccountOpsSid = SeAliasAccountOpsSid;
173 SeExports->SeAliasSystemOpsSid = SeAliasSystemOpsSid;
174 SeExports->SeAliasPrintOpsSid = SeAliasPrintOpsSid;
175 SeExports->SeAliasBackupOpsSid = SeAliasBackupOpsSid;
176
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
192 /*
193 * @implemented
194 */
195 VOID STDCALL
196 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
197 {
198 PETHREAD Thread;
199 BOOLEAN CopyOnOpen;
200 BOOLEAN EffectiveOnly;
201
202 PAGED_CODE();
203
204 Thread = PsGetCurrentThread();
205 if (Thread == NULL)
206 {
207 SubjectContext->ProcessAuditId = 0;
208 SubjectContext->PrimaryToken = NULL;
209 SubjectContext->ClientToken = NULL;
210 SubjectContext->ImpersonationLevel = 0;
211 }
212 else
213 {
214 SubjectContext->ProcessAuditId = Thread->ThreadsProcess;
215 SubjectContext->ClientToken =
216 PsReferenceImpersonationToken(Thread,
217 &CopyOnOpen,
218 &EffectiveOnly,
219 &SubjectContext->ImpersonationLevel);
220 SubjectContext->PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
221 }
222 }
223
224
225 /*
226 * @implemented
227 */
228 VOID STDCALL
229 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
230 {
231 PAGED_CODE();
232
233 KeEnterCriticalRegion();
234 ExAcquireResourceExclusiveLite(&SepSubjectContextLock, TRUE);
235 }
236
237
238 /*
239 * @implemented
240 */
241 VOID STDCALL
242 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
243 {
244 PAGED_CODE();
245
246 ExReleaseResourceLite(&SepSubjectContextLock);
247 KeLeaveCriticalRegion();
248 }
249
250
251 /*
252 * @implemented
253 */
254 VOID STDCALL
255 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
256 {
257 PAGED_CODE();
258
259 if (SubjectContext->PrimaryToken != NULL)
260 {
261 ObDereferenceObject(SubjectContext->PrimaryToken);
262 }
263
264 if (SubjectContext->ClientToken != NULL)
265 {
266 ObDereferenceObject(SubjectContext->ClientToken);
267 }
268 }
269
270
271 /*
272 * @implemented
273 */
274 NTSTATUS STDCALL
275 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
276 {
277 PAGED_CODE();
278
279 if (*SecurityDescriptor != NULL)
280 {
281 ExFreePool(*SecurityDescriptor);
282 *SecurityDescriptor = NULL;
283 }
284
285 return STATUS_SUCCESS;
286 }
287
288
289 /*
290 * @unimplemented
291 */
292 NTSTATUS STDCALL
293 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
294 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
295 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
296 IN GUID *ObjectType OPTIONAL,
297 IN BOOLEAN IsDirectoryObject,
298 IN ULONG AutoInheritFlags,
299 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
300 IN PGENERIC_MAPPING GenericMapping,
301 IN POOL_TYPE PoolType)
302 {
303 UNIMPLEMENTED;
304 return STATUS_NOT_IMPLEMENTED;
305 }
306
307
308 /*
309 * FUNCTION: Creates a security descriptor for a new object.
310 * ARGUMENTS:
311 * ParentDescriptor =
312 * ExplicitDescriptor =
313 * NewDescriptor =
314 * IsDirectoryObject =
315 * SubjectContext =
316 * GeneralMapping =
317 * PoolType =
318 * RETURNS: Status
319 *
320 * @implemented
321 */
322 NTSTATUS STDCALL
323 SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
324 PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
325 PSECURITY_DESCRIPTOR *NewDescriptor,
326 BOOLEAN IsDirectoryObject,
327 PSECURITY_SUBJECT_CONTEXT SubjectContext,
328 PGENERIC_MAPPING GenericMapping,
329 POOL_TYPE PoolType)
330 {
331 PSECURITY_DESCRIPTOR Descriptor;
332 PTOKEN Token;
333 ULONG OwnerLength = 0;
334 ULONG GroupLength = 0;
335 ULONG DaclLength = 0;
336 ULONG SaclLength = 0;
337 ULONG Length = 0;
338 ULONG Control = 0;
339 ULONG_PTR Current;
340 PSID Owner = NULL;
341 PSID Group = NULL;
342 PACL Dacl = NULL;
343 PACL Sacl = NULL;
344
345 PAGED_CODE();
346
347 /* Lock subject context */
348 SeLockSubjectContext(SubjectContext);
349
350 if (SubjectContext->ClientToken != NULL)
351 {
352 Token = SubjectContext->ClientToken;
353 }
354 else
355 {
356 Token = SubjectContext->PrimaryToken;
357 }
358
359
360 /* Inherit the Owner SID */
361 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
362 {
363 DPRINT("Use explicit owner sid!\n");
364 Owner = ExplicitDescriptor->Owner;
365
366 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
367 {
368 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
369
370 }
371 }
372 else
373 {
374 if (Token != NULL)
375 {
376 DPRINT("Use token owner sid!\n");
377 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
378 }
379 else
380 {
381 DPRINT("Use default owner sid!\n");
382 Owner = SeLocalSystemSid;
383 }
384
385 Control |= SE_OWNER_DEFAULTED;
386 }
387
388 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
389
390
391 /* Inherit the Group SID */
392 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
393 {
394 DPRINT("Use explicit group sid!\n");
395 Group = ExplicitDescriptor->Group;
396 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
397 {
398 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
399 }
400 }
401 else
402 {
403 if (Token != NULL)
404 {
405 DPRINT("Use token group sid!\n");
406 Group = Token->PrimaryGroup;
407 }
408 else
409 {
410 DPRINT("Use default group sid!\n");
411 Group = SeLocalSystemSid;
412 }
413
414 Control |= SE_OWNER_DEFAULTED;
415 }
416
417 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
418
419
420 /* Inherit the DACL */
421 if (ExplicitDescriptor != NULL &&
422 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
423 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
424 {
425 DPRINT("Use explicit DACL!\n");
426 Dacl = ExplicitDescriptor->Dacl;
427 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
428 {
429 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
430 }
431
432 Control |= SE_DACL_PRESENT;
433 }
434 else if (ParentDescriptor != NULL &&
435 (ParentDescriptor->Control & SE_DACL_PRESENT))
436 {
437 DPRINT("Use parent DACL!\n");
438 /* FIXME: Inherit */
439 Dacl = ParentDescriptor->Dacl;
440 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
441 {
442 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
443 }
444 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
445 }
446 else if (Token != NULL && Token->DefaultDacl != NULL)
447 {
448 DPRINT("Use token default DACL!\n");
449 /* FIXME: Inherit */
450 Dacl = Token->DefaultDacl;
451 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
452 }
453 else
454 {
455 DPRINT("Use NULL DACL!\n");
456 Dacl = NULL;
457 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
458 }
459
460 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
461
462
463 /* Inherit the SACL */
464 if (ExplicitDescriptor != NULL &&
465 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
466 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
467 {
468 DPRINT("Use explicit SACL!\n");
469 Sacl = ExplicitDescriptor->Sacl;
470 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
471 {
472 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
473 }
474
475 Control |= SE_SACL_PRESENT;
476 }
477 else if (ParentDescriptor != NULL &&
478 (ParentDescriptor->Control & SE_SACL_PRESENT))
479 {
480 DPRINT("Use parent SACL!\n");
481 /* FIXME: Inherit */
482 Sacl = ParentDescriptor->Sacl;
483 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
484 {
485 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
486 }
487 Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
488 }
489
490 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
491
492
493 /* Allocate and initialize the new security descriptor */
494 Length = sizeof(SECURITY_DESCRIPTOR) +
495 OwnerLength + GroupLength + DaclLength + SaclLength;
496
497 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
498 sizeof(SECURITY_DESCRIPTOR),
499 OwnerLength,
500 GroupLength,
501 DaclLength,
502 SaclLength);
503
504 Descriptor = ExAllocatePool(NonPagedPool,
505 Length);
506 RtlZeroMemory( Descriptor, Length );
507
508 if (Descriptor == NULL)
509 {
510 DPRINT1("ExAlloctePool() failed\n");
511 /* FIXME: Unlock subject context */
512 return STATUS_INSUFFICIENT_RESOURCES;
513 }
514
515 RtlCreateSecurityDescriptor(Descriptor,
516 SECURITY_DESCRIPTOR_REVISION);
517
518 Descriptor->Control = Control | SE_SELF_RELATIVE;
519
520 Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
521
522 if (SaclLength != 0)
523 {
524 RtlCopyMemory((PVOID)Current,
525 Sacl,
526 SaclLength);
527 Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
528 Current += SaclLength;
529 }
530
531 if (DaclLength != 0)
532 {
533 RtlCopyMemory((PVOID)Current,
534 Dacl,
535 DaclLength);
536 Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
537 Current += DaclLength;
538 }
539
540 if (OwnerLength != 0)
541 {
542 RtlCopyMemory((PVOID)Current,
543 Owner,
544 OwnerLength);
545 Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
546 Current += OwnerLength;
547 DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
548 }
549 else
550 DPRINT("Owner of %x is zero length\n", Descriptor);
551
552 if (GroupLength != 0)
553 {
554 memmove((PVOID)Current,
555 Group,
556 GroupLength);
557 Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
558 }
559
560 /* Unlock subject context */
561 SeUnlockSubjectContext(SubjectContext);
562
563 *NewDescriptor = Descriptor;
564
565 DPRINT("Descrptor %x\n", Descriptor);
566 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
567
568 return STATUS_SUCCESS;
569 }
570
571
572 static BOOLEAN
573 SepSidInToken(PACCESS_TOKEN _Token,
574 PSID Sid)
575 {
576 ULONG i;
577 PTOKEN Token = (PTOKEN)_Token;
578
579 PAGED_CODE();
580
581 if (Token->UserAndGroupCount == 0)
582 {
583 return FALSE;
584 }
585
586 for (i=0; i<Token->UserAndGroupCount; i++)
587 {
588 if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
589 {
590 if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
591 {
592 return TRUE;
593 }
594
595 return FALSE;
596 }
597 }
598
599 return FALSE;
600 }
601
602
603 /*
604 * FUNCTION: Determines whether the requested access rights can be granted
605 * to an object protected by a security descriptor and an object owner
606 * ARGUMENTS:
607 * SecurityDescriptor = Security descriptor protecting the object
608 * SubjectSecurityContext = Subject's captured security context
609 * SubjectContextLocked = Indicates the user's subject context is locked
610 * DesiredAccess = Access rights the caller is trying to acquire
611 * PreviouslyGrantedAccess = Specified the access rights already granted
612 * Privileges = ?
613 * GenericMapping = Generic mapping associated with the object
614 * AccessMode = Access mode used for the check
615 * GrantedAccess (OUT) = On return specifies the access granted
616 * AccessStatus (OUT) = Status indicating why access was denied
617 * RETURNS: If access was granted, returns TRUE
618 *
619 * @implemented
620 */
621 BOOLEAN STDCALL
622 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
623 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
624 IN BOOLEAN SubjectContextLocked,
625 IN ACCESS_MASK DesiredAccess,
626 IN ACCESS_MASK PreviouslyGrantedAccess,
627 OUT PPRIVILEGE_SET* Privileges,
628 IN PGENERIC_MAPPING GenericMapping,
629 IN KPROCESSOR_MODE AccessMode,
630 OUT PACCESS_MASK GrantedAccess,
631 OUT PNTSTATUS AccessStatus)
632 {
633 LUID_AND_ATTRIBUTES Privilege;
634 ACCESS_MASK CurrentAccess;
635 PACCESS_TOKEN Token;
636 ULONG i;
637 PACL Dacl;
638 BOOLEAN Present;
639 BOOLEAN Defaulted;
640 PACE CurrentAce;
641 PSID Sid;
642 NTSTATUS Status;
643
644 PAGED_CODE();
645
646 CurrentAccess = PreviouslyGrantedAccess;
647
648 if (SubjectContextLocked == FALSE)
649 {
650 SeLockSubjectContext(SubjectSecurityContext);
651 }
652
653 Token = SubjectSecurityContext->ClientToken ?
654 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
655
656 /* Get the DACL */
657 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
658 &Present,
659 &Dacl,
660 &Defaulted);
661 if (!NT_SUCCESS(Status))
662 {
663 if (SubjectContextLocked == FALSE)
664 {
665 SeUnlockSubjectContext(SubjectSecurityContext);
666 }
667
668 *AccessStatus = Status;
669 return FALSE;
670 }
671
672 /* RULE 1: Grant desired access if the object is unprotected */
673 if (Present == TRUE && Dacl == NULL)
674 {
675 if (SubjectContextLocked == FALSE)
676 {
677 SeUnlockSubjectContext(SubjectSecurityContext);
678 }
679
680 *GrantedAccess = DesiredAccess;
681 *AccessStatus = STATUS_SUCCESS;
682 return TRUE;
683 }
684
685 CurrentAccess = PreviouslyGrantedAccess;
686
687 /* RULE 2: Check token for 'take ownership' privilege */
688 Privilege.Luid = SeTakeOwnershipPrivilege;
689 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
690
691 if (SepPrivilegeCheck(Token,
692 &Privilege,
693 1,
694 PRIVILEGE_SET_ALL_NECESSARY,
695 AccessMode))
696 {
697 CurrentAccess |= WRITE_OWNER;
698 if (DesiredAccess == CurrentAccess)
699 {
700 if (SubjectContextLocked == FALSE)
701 {
702 SeUnlockSubjectContext(SubjectSecurityContext);
703 }
704
705 *GrantedAccess = CurrentAccess;
706 *AccessStatus = STATUS_SUCCESS;
707 return TRUE;
708 }
709 }
710
711 /* RULE 3: Check whether the token is the owner */
712 Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
713 &Sid,
714 &Defaulted);
715 if (!NT_SUCCESS(Status))
716 {
717 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
718 if (SubjectContextLocked == FALSE)
719 {
720 SeUnlockSubjectContext(SubjectSecurityContext);
721 }
722
723 *AccessStatus = Status;
724 return FALSE;
725 }
726
727 if (SepSidInToken(Token, Sid))
728 {
729 CurrentAccess |= (READ_CONTROL | WRITE_DAC);
730 if (DesiredAccess == CurrentAccess)
731 {
732 if (SubjectContextLocked == FALSE)
733 {
734 SeUnlockSubjectContext(SubjectSecurityContext);
735 }
736
737 *GrantedAccess = CurrentAccess;
738 *AccessStatus = STATUS_SUCCESS;
739 return TRUE;
740 }
741 }
742
743 /* Fail if DACL is absent */
744 if (Present == FALSE)
745 {
746 if (SubjectContextLocked == FALSE)
747 {
748 SeUnlockSubjectContext(SubjectSecurityContext);
749 }
750
751 *GrantedAccess = 0;
752 *AccessStatus = STATUS_ACCESS_DENIED;
753 return TRUE;
754 }
755
756 /* RULE 4: Grant rights according to the DACL */
757 CurrentAce = (PACE)(Dacl + 1);
758 for (i = 0; i < Dacl->AceCount; i++)
759 {
760 Sid = (PSID)(CurrentAce + 1);
761 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
762 {
763 if (SepSidInToken(Token, Sid))
764 {
765 if (SubjectContextLocked == FALSE)
766 {
767 SeUnlockSubjectContext(SubjectSecurityContext);
768 }
769
770 *GrantedAccess = 0;
771 *AccessStatus = STATUS_ACCESS_DENIED;
772 return TRUE;
773 }
774 }
775
776 if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
777 {
778 if (SepSidInToken(Token, Sid))
779 {
780 CurrentAccess |= CurrentAce->AccessMask;
781 }
782 }
783 }
784
785 if (SubjectContextLocked == FALSE)
786 {
787 SeUnlockSubjectContext(SubjectSecurityContext);
788 }
789
790 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
791 CurrentAccess, DesiredAccess);
792
793 *GrantedAccess = CurrentAccess & DesiredAccess;
794
795 *AccessStatus =
796 (*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
797
798 return TRUE;
799 }
800
801
802 NTSTATUS STDCALL
803 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
804 IN HANDLE TokenHandle,
805 IN ACCESS_MASK DesiredAccess,
806 IN PGENERIC_MAPPING GenericMapping,
807 OUT PPRIVILEGE_SET PrivilegeSet,
808 OUT PULONG ReturnLength,
809 OUT PACCESS_MASK GrantedAccess,
810 OUT PNTSTATUS AccessStatus)
811 {
812 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
813 KPROCESSOR_MODE PreviousMode;
814 PTOKEN Token;
815 NTSTATUS Status;
816
817 PAGED_CODE();
818
819 DPRINT("NtAccessCheck() called\n");
820
821 PreviousMode = KeGetPreviousMode();
822 if (PreviousMode == KernelMode)
823 {
824 *GrantedAccess = DesiredAccess;
825 *AccessStatus = STATUS_SUCCESS;
826 return STATUS_SUCCESS;
827 }
828
829 Status = ObReferenceObjectByHandle(TokenHandle,
830 TOKEN_QUERY,
831 SepTokenObjectType,
832 PreviousMode,
833 (PVOID*)&Token,
834 NULL);
835 if (!NT_SUCCESS(Status))
836 {
837 DPRINT1("Failed to reference token (Status %lx)\n", Status);
838 return Status;
839 }
840
841 /* Check token type */
842 if (Token->TokenType != TokenImpersonation)
843 {
844 DPRINT1("No impersonation token\n");
845 ObDereferenceObject(Token);
846 return STATUS_ACCESS_VIOLATION;
847 }
848
849 /* Check impersonation level */
850 if (Token->ImpersonationLevel < SecurityAnonymous)
851 {
852 DPRINT1("Invalid impersonation level\n");
853 ObDereferenceObject(Token);
854 return STATUS_ACCESS_VIOLATION;
855 }
856
857 RtlZeroMemory(&SubjectSecurityContext,
858 sizeof(SECURITY_SUBJECT_CONTEXT));
859 SubjectSecurityContext.ClientToken = Token;
860 SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
861
862 /* Lock subject context */
863 SeLockSubjectContext(&SubjectSecurityContext);
864
865 if (SeAccessCheck(SecurityDescriptor,
866 &SubjectSecurityContext,
867 TRUE,
868 DesiredAccess,
869 0,
870 &PrivilegeSet,
871 GenericMapping,
872 PreviousMode,
873 GrantedAccess,
874 AccessStatus))
875 {
876 Status = *AccessStatus;
877 }
878 else
879 {
880 Status = STATUS_ACCESS_DENIED;
881 }
882
883 /* Unlock subject context */
884 SeUnlockSubjectContext(&SubjectSecurityContext);
885
886 ObDereferenceObject(Token);
887
888 DPRINT("NtAccessCheck() done\n");
889
890 return Status;
891 }
892
893 /* EOF */