1. A few Nt vs. Zw fixes
[reactos.git] / reactos / ntoskrnl / se / semgr.c
1 /* $Id$
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 = ZwCreateDirectoryObject(&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 = ZwCreateEvent(&EventHandle,
105 EVENT_ALL_ACCESS,
106 &ObjectAttributes,
107 SynchronizationEvent,
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 ZwClose(EventHandle);
117 ZwClose(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 * @implemented
195 */
196 VOID STDCALL
197 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
198 {
199 PETHREAD Thread;
200 BOOLEAN CopyOnOpen;
201 BOOLEAN EffectiveOnly;
202
203 Thread = PsGetCurrentThread();
204 if (Thread == NULL)
205 {
206 SubjectContext->ProcessAuditId = 0;
207 SubjectContext->PrimaryToken = NULL;
208 SubjectContext->ClientToken = NULL;
209 SubjectContext->ImpersonationLevel = 0;
210 }
211 else
212 {
213 SubjectContext->ProcessAuditId = Thread->ThreadsProcess;
214 SubjectContext->ClientToken =
215 PsReferenceImpersonationToken(Thread,
216 &CopyOnOpen,
217 &EffectiveOnly,
218 &SubjectContext->ImpersonationLevel);
219 SubjectContext->PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
220 }
221 }
222
223
224 /*
225 * @implemented
226 */
227 VOID STDCALL
228 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
229 {
230 KeEnterCriticalRegion();
231 ExAcquireResourceExclusiveLite(&SepSubjectContextLock, TRUE);
232 }
233
234
235 /*
236 * @implemented
237 */
238 VOID STDCALL
239 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
240 {
241 ExReleaseResourceLite(&SepSubjectContextLock);
242 KeLeaveCriticalRegion();
243 }
244
245
246 /*
247 * @implemented
248 */
249 VOID STDCALL
250 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
251 {
252 if (SubjectContext->PrimaryToken != NULL)
253 {
254 ObDereferenceObject(SubjectContext->PrimaryToken);
255 }
256
257 if (SubjectContext->ClientToken != NULL)
258 {
259 ObDereferenceObject(SubjectContext->ClientToken);
260 }
261 }
262
263
264 /*
265 * @implemented
266 */
267 NTSTATUS STDCALL
268 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
269 {
270 if (*SecurityDescriptor != NULL)
271 {
272 ExFreePool(*SecurityDescriptor);
273 *SecurityDescriptor = NULL;
274 }
275
276 return STATUS_SUCCESS;
277 }
278
279
280 /*
281 * @unimplemented
282 */
283 NTSTATUS STDCALL
284 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
285 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
286 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
287 IN GUID *ObjectType OPTIONAL,
288 IN BOOLEAN IsDirectoryObject,
289 IN ULONG AutoInheritFlags,
290 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
291 IN PGENERIC_MAPPING GenericMapping,
292 IN POOL_TYPE PoolType)
293 {
294 UNIMPLEMENTED;
295 return STATUS_NOT_IMPLEMENTED;
296 }
297
298
299 /*
300 * FUNCTION: Creates a security descriptor for a new object.
301 * ARGUMENTS:
302 * ParentDescriptor =
303 * ExplicitDescriptor =
304 * NewDescriptor =
305 * IsDirectoryObject =
306 * SubjectContext =
307 * GeneralMapping =
308 * PoolType =
309 * RETURNS: Status
310 *
311 * @implemented
312 */
313 NTSTATUS STDCALL
314 SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
315 PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
316 PSECURITY_DESCRIPTOR *NewDescriptor,
317 BOOLEAN IsDirectoryObject,
318 PSECURITY_SUBJECT_CONTEXT SubjectContext,
319 PGENERIC_MAPPING GenericMapping,
320 POOL_TYPE PoolType)
321 {
322 PSECURITY_DESCRIPTOR Descriptor;
323 PTOKEN Token;
324 ULONG OwnerLength = 0;
325 ULONG GroupLength = 0;
326 ULONG DaclLength = 0;
327 ULONG SaclLength = 0;
328 ULONG Length = 0;
329 ULONG Control = 0;
330 ULONG_PTR Current;
331 PSID Owner = NULL;
332 PSID Group = NULL;
333 PACL Dacl = NULL;
334 PACL Sacl = NULL;
335
336 /* Lock subject context */
337 SeLockSubjectContext(SubjectContext);
338
339 if (SubjectContext->ClientToken != NULL)
340 {
341 Token = SubjectContext->ClientToken;
342 }
343 else
344 {
345 Token = SubjectContext->PrimaryToken;
346 }
347
348
349 /* Inherit the Owner SID */
350 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
351 {
352 DPRINT("Use explicit owner sid!\n");
353 Owner = ExplicitDescriptor->Owner;
354 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
355 {
356 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
357 }
358 }
359 else
360 {
361 if (Token != NULL)
362 {
363 DPRINT("Use token owner sid!\n");
364 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
365 }
366 else
367 {
368 DPRINT("Use default owner sid!\n");
369 Owner = SeLocalSystemSid;
370 }
371
372 Control |= SE_OWNER_DEFAULTED;
373 }
374
375 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
376
377
378 /* Inherit the Group SID */
379 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
380 {
381 DPRINT("Use explicit group sid!\n");
382 Group = ExplicitDescriptor->Group;
383 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
384 {
385 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
386 }
387 }
388 else
389 {
390 if (Token != NULL)
391 {
392 DPRINT("Use token group sid!\n");
393 Group = Token->PrimaryGroup;
394 }
395 else
396 {
397 DPRINT("Use default group sid!\n");
398 Group = SeLocalSystemSid;
399 }
400
401 Control |= SE_OWNER_DEFAULTED;
402 }
403
404 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
405
406
407 /* Inherit the DACL */
408 if (ExplicitDescriptor != NULL &&
409 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
410 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
411 {
412 DPRINT("Use explicit DACL!\n");
413 Dacl = ExplicitDescriptor->Dacl;
414 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
415 {
416 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
417 }
418
419 Control |= SE_DACL_PRESENT;
420 }
421 else if (ParentDescriptor != NULL &&
422 (ParentDescriptor->Control & SE_DACL_PRESENT))
423 {
424 DPRINT("Use parent DACL!\n");
425 /* FIXME: Inherit */
426 Dacl = ParentDescriptor->Dacl;
427 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
428 {
429 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
430 }
431 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
432 }
433 else if (Token != NULL && Token->DefaultDacl != NULL)
434 {
435 DPRINT("Use token default DACL!\n");
436 /* FIXME: Inherit */
437 Dacl = Token->DefaultDacl;
438 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
439 }
440 else
441 {
442 DPRINT("Use NULL DACL!\n");
443 Dacl = NULL;
444 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
445 }
446
447 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
448
449
450 /* Inherit the SACL */
451 if (ExplicitDescriptor != NULL &&
452 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
453 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
454 {
455 DPRINT("Use explicit SACL!\n");
456 Sacl = ExplicitDescriptor->Sacl;
457 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
458 {
459 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
460 }
461
462 Control |= SE_SACL_PRESENT;
463 }
464 else if (ParentDescriptor != NULL &&
465 (ParentDescriptor->Control & SE_SACL_PRESENT))
466 {
467 DPRINT("Use parent SACL!\n");
468 /* FIXME: Inherit */
469 Sacl = ParentDescriptor->Sacl;
470 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
471 {
472 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
473 }
474 Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
475 }
476
477 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
478
479
480 /* Allocate and initialize the new security descriptor */
481 Length = sizeof(SECURITY_DESCRIPTOR) +
482 OwnerLength + GroupLength + DaclLength + SaclLength;
483
484 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
485 sizeof(SECURITY_DESCRIPTOR),
486 OwnerLength,
487 GroupLength,
488 DaclLength,
489 SaclLength);
490
491 Descriptor = ExAllocatePool(NonPagedPool,
492 Length);
493 RtlZeroMemory( Descriptor, Length );
494
495 if (Descriptor == NULL)
496 {
497 DPRINT1("ExAlloctePool() failed\n");
498 /* FIXME: Unlock subject context */
499 return STATUS_INSUFFICIENT_RESOURCES;
500 }
501
502 RtlCreateSecurityDescriptor(Descriptor,
503 SECURITY_DESCRIPTOR_REVISION);
504
505 Descriptor->Control = Control | SE_SELF_RELATIVE;
506
507 Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
508
509 if (SaclLength != 0)
510 {
511 RtlCopyMemory((PVOID)Current,
512 Sacl,
513 SaclLength);
514 Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
515 Current += SaclLength;
516 }
517
518 if (DaclLength != 0)
519 {
520 RtlCopyMemory((PVOID)Current,
521 Dacl,
522 DaclLength);
523 Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
524 Current += DaclLength;
525 }
526
527 if (OwnerLength != 0)
528 {
529 RtlCopyMemory((PVOID)Current,
530 Owner,
531 OwnerLength);
532 Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
533 Current += OwnerLength;
534 DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
535 }
536 else
537 DPRINT("Owner of %x is zero length\n", Descriptor);
538
539 if (GroupLength != 0)
540 {
541 memmove((PVOID)Current,
542 Group,
543 GroupLength);
544 Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
545 }
546
547 /* Unlock subject context */
548 SeUnlockSubjectContext(SubjectContext);
549
550 *NewDescriptor = Descriptor;
551
552 DPRINT("Descrptor %x\n", Descriptor);
553 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
554
555 return STATUS_SUCCESS;
556 }
557
558
559 static BOOLEAN
560 SepSidInToken(PACCESS_TOKEN _Token,
561 PSID Sid)
562 {
563 ULONG i;
564 PTOKEN Token = (PTOKEN)_Token;
565
566 if (Token->UserAndGroupCount == 0)
567 {
568 return FALSE;
569 }
570
571 for (i=0; i<Token->UserAndGroupCount; i++)
572 {
573 if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
574 {
575 if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
576 {
577 return TRUE;
578 }
579
580 return FALSE;
581 }
582 }
583
584 return FALSE;
585 }
586
587
588 /*
589 * FUNCTION: Determines whether the requested access rights can be granted
590 * to an object protected by a security descriptor and an object owner
591 * ARGUMENTS:
592 * SecurityDescriptor = Security descriptor protecting the object
593 * SubjectSecurityContext = Subject's captured security context
594 * SubjectContextLocked = Indicates the user's subject context is locked
595 * DesiredAccess = Access rights the caller is trying to acquire
596 * PreviouslyGrantedAccess = Specified the access rights already granted
597 * Privileges = ?
598 * GenericMapping = Generic mapping associated with the object
599 * AccessMode = Access mode used for the check
600 * GrantedAccess (OUT) = On return specifies the access granted
601 * AccessStatus (OUT) = Status indicating why access was denied
602 * RETURNS: If access was granted, returns TRUE
603 *
604 * @implemented
605 */
606 BOOLEAN STDCALL
607 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
608 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
609 IN BOOLEAN SubjectContextLocked,
610 IN ACCESS_MASK DesiredAccess,
611 IN ACCESS_MASK PreviouslyGrantedAccess,
612 OUT PPRIVILEGE_SET* Privileges,
613 IN PGENERIC_MAPPING GenericMapping,
614 IN KPROCESSOR_MODE AccessMode,
615 OUT PACCESS_MASK GrantedAccess,
616 OUT PNTSTATUS AccessStatus)
617 {
618 LUID_AND_ATTRIBUTES Privilege;
619 ACCESS_MASK CurrentAccess;
620 PACCESS_TOKEN Token;
621 ULONG i;
622 PACL Dacl;
623 BOOLEAN Present;
624 BOOLEAN Defaulted;
625 PACE CurrentAce;
626 PSID Sid;
627 NTSTATUS Status;
628
629 CurrentAccess = PreviouslyGrantedAccess;
630
631 if (SubjectContextLocked == FALSE)
632 {
633 SeLockSubjectContext(SubjectSecurityContext);
634 }
635
636 Token = SubjectSecurityContext->ClientToken ?
637 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
638
639 /* Get the DACL */
640 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
641 &Present,
642 &Dacl,
643 &Defaulted);
644 if (!NT_SUCCESS(Status))
645 {
646 if (SubjectContextLocked == FALSE)
647 {
648 SeUnlockSubjectContext(SubjectSecurityContext);
649 }
650
651 *AccessStatus = Status;
652 return FALSE;
653 }
654
655 /* RULE 1: Grant desired access if the object is unprotected */
656 if (Present == TRUE && Dacl == NULL)
657 {
658 if (SubjectContextLocked == FALSE)
659 {
660 SeUnlockSubjectContext(SubjectSecurityContext);
661 }
662
663 *GrantedAccess = DesiredAccess;
664 *AccessStatus = STATUS_SUCCESS;
665 return TRUE;
666 }
667
668 CurrentAccess = PreviouslyGrantedAccess;
669
670 /* RULE 2: Check token for 'take ownership' privilege */
671 Privilege.Luid = SeTakeOwnershipPrivilege;
672 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
673
674 if (SepPrivilegeCheck(Token,
675 &Privilege,
676 1,
677 PRIVILEGE_SET_ALL_NECESSARY,
678 AccessMode))
679 {
680 CurrentAccess |= WRITE_OWNER;
681 if (DesiredAccess == CurrentAccess)
682 {
683 if (SubjectContextLocked == FALSE)
684 {
685 SeUnlockSubjectContext(SubjectSecurityContext);
686 }
687
688 *GrantedAccess = CurrentAccess;
689 *AccessStatus = STATUS_SUCCESS;
690 return TRUE;
691 }
692 }
693
694 /* RULE 3: Check whether the token is the owner */
695 Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
696 &Sid,
697 &Defaulted);
698 if (!NT_SUCCESS(Status))
699 {
700 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
701 if (SubjectContextLocked == FALSE)
702 {
703 SeUnlockSubjectContext(SubjectSecurityContext);
704 }
705
706 *AccessStatus = Status;
707 return FALSE;
708 }
709
710 if (SepSidInToken(Token, Sid))
711 {
712 CurrentAccess |= (READ_CONTROL | WRITE_DAC);
713 if (DesiredAccess == CurrentAccess)
714 {
715 if (SubjectContextLocked == FALSE)
716 {
717 SeUnlockSubjectContext(SubjectSecurityContext);
718 }
719
720 *GrantedAccess = CurrentAccess;
721 *AccessStatus = STATUS_SUCCESS;
722 return TRUE;
723 }
724 }
725
726 /* Fail if DACL is absent */
727 if (Present == FALSE)
728 {
729 if (SubjectContextLocked == FALSE)
730 {
731 SeUnlockSubjectContext(SubjectSecurityContext);
732 }
733
734 *GrantedAccess = 0;
735 *AccessStatus = STATUS_ACCESS_DENIED;
736 return TRUE;
737 }
738
739 /* RULE 4: Grant rights according to the DACL */
740 CurrentAce = (PACE)(Dacl + 1);
741 for (i = 0; i < Dacl->AceCount; i++)
742 {
743 Sid = (PSID)(CurrentAce + 1);
744 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
745 {
746 if (SepSidInToken(Token, Sid))
747 {
748 if (SubjectContextLocked == FALSE)
749 {
750 SeUnlockSubjectContext(SubjectSecurityContext);
751 }
752
753 *GrantedAccess = 0;
754 *AccessStatus = STATUS_ACCESS_DENIED;
755 return TRUE;
756 }
757 }
758
759 if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
760 {
761 if (SepSidInToken(Token, Sid))
762 {
763 CurrentAccess |= CurrentAce->AccessMask;
764 }
765 }
766 }
767
768 if (SubjectContextLocked == FALSE)
769 {
770 SeUnlockSubjectContext(SubjectSecurityContext);
771 }
772
773 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
774 CurrentAccess, DesiredAccess);
775
776 *GrantedAccess = CurrentAccess & DesiredAccess;
777
778 *AccessStatus =
779 (*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
780
781 return TRUE;
782 }
783
784
785 NTSTATUS STDCALL
786 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
787 IN HANDLE TokenHandle,
788 IN ACCESS_MASK DesiredAccess,
789 IN PGENERIC_MAPPING GenericMapping,
790 OUT PPRIVILEGE_SET PrivilegeSet,
791 OUT PULONG ReturnLength,
792 OUT PACCESS_MASK GrantedAccess,
793 OUT PNTSTATUS AccessStatus)
794 {
795 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
796 KPROCESSOR_MODE PreviousMode;
797 PTOKEN Token;
798 NTSTATUS Status;
799
800 DPRINT("NtAccessCheck() called\n");
801
802 PreviousMode = KeGetPreviousMode();
803 if (PreviousMode == KernelMode)
804 {
805 *GrantedAccess = DesiredAccess;
806 *AccessStatus = STATUS_SUCCESS;
807 return STATUS_SUCCESS;
808 }
809
810 Status = ObReferenceObjectByHandle(TokenHandle,
811 TOKEN_QUERY,
812 SepTokenObjectType,
813 PreviousMode,
814 (PVOID*)&Token,
815 NULL);
816 if (!NT_SUCCESS(Status))
817 {
818 DPRINT1("Failed to reference token (Status %lx)\n", Status);
819 return Status;
820 }
821
822 /* Check token type */
823 if (Token->TokenType != TokenImpersonation)
824 {
825 DPRINT1("No impersonation token\n");
826 ObDereferenceObject(Token);
827 return STATUS_ACCESS_VIOLATION;
828 }
829
830 /* Check impersonation level */
831 if (Token->ImpersonationLevel < SecurityAnonymous)
832 {
833 DPRINT1("Invalid impersonation level\n");
834 ObDereferenceObject(Token);
835 return STATUS_ACCESS_VIOLATION;
836 }
837
838 RtlZeroMemory(&SubjectSecurityContext,
839 sizeof(SECURITY_SUBJECT_CONTEXT));
840 SubjectSecurityContext.ClientToken = Token;
841 SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
842
843 /* Lock subject context */
844 SeLockSubjectContext(&SubjectSecurityContext);
845
846 if (SeAccessCheck(SecurityDescriptor,
847 &SubjectSecurityContext,
848 TRUE,
849 DesiredAccess,
850 0,
851 &PrivilegeSet,
852 GenericMapping,
853 PreviousMode,
854 GrantedAccess,
855 AccessStatus))
856 {
857 Status = *AccessStatus;
858 }
859 else
860 {
861 Status = STATUS_ACCESS_DENIED;
862 }
863
864 /* Unlock subject context */
865 SeUnlockSubjectContext(&SubjectSecurityContext);
866
867 ObDereferenceObject(Token);
868
869 DPRINT("NtAccessCheck() done\n");
870
871 return Status;
872 }
873
874 /* EOF */