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