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