Merge from amd64-branch:
[reactos.git] / reactos / ntoskrnl / se / semgr.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/semgr.c
5 * PURPOSE: Security manager
6 *
7 * PROGRAMMERS: No programmer listed.
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS ********************************************************************/
17
18 PSE_EXPORTS SeExports = NULL;
19 SE_EXPORTS SepExports;
20
21 extern ULONG ExpInitializationPhase;
22 extern ERESOURCE SepSubjectContextLock;
23
24 /* PRIVATE FUNCTIONS **********************************************************/
25
26 static BOOLEAN INIT_FUNCTION
27 SepInitExports(VOID)
28 {
29 SepExports.SeCreateTokenPrivilege = SeCreateTokenPrivilege;
30 SepExports.SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
31 SepExports.SeLockMemoryPrivilege = SeLockMemoryPrivilege;
32 SepExports.SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
33 SepExports.SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
34 SepExports.SeTcbPrivilege = SeTcbPrivilege;
35 SepExports.SeSecurityPrivilege = SeSecurityPrivilege;
36 SepExports.SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
37 SepExports.SeLoadDriverPrivilege = SeLoadDriverPrivilege;
38 SepExports.SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
39 SepExports.SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
40 SepExports.SeSystemProfilePrivilege = SeSystemProfilePrivilege;
41 SepExports.SeSystemtimePrivilege = SeSystemtimePrivilege;
42 SepExports.SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
43 SepExports.SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
44 SepExports.SeBackupPrivilege = SeBackupPrivilege;
45 SepExports.SeRestorePrivilege = SeRestorePrivilege;
46 SepExports.SeShutdownPrivilege = SeShutdownPrivilege;
47 SepExports.SeDebugPrivilege = SeDebugPrivilege;
48 SepExports.SeAuditPrivilege = SeAuditPrivilege;
49 SepExports.SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
50 SepExports.SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
51 SepExports.SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
52
53 SepExports.SeNullSid = SeNullSid;
54 SepExports.SeWorldSid = SeWorldSid;
55 SepExports.SeLocalSid = SeLocalSid;
56 SepExports.SeCreatorOwnerSid = SeCreatorOwnerSid;
57 SepExports.SeCreatorGroupSid = SeCreatorGroupSid;
58 SepExports.SeNtAuthoritySid = SeNtAuthoritySid;
59 SepExports.SeDialupSid = SeDialupSid;
60 SepExports.SeNetworkSid = SeNetworkSid;
61 SepExports.SeBatchSid = SeBatchSid;
62 SepExports.SeInteractiveSid = SeInteractiveSid;
63 SepExports.SeLocalSystemSid = SeLocalSystemSid;
64 SepExports.SeAliasAdminsSid = SeAliasAdminsSid;
65 SepExports.SeAliasUsersSid = SeAliasUsersSid;
66 SepExports.SeAliasGuestsSid = SeAliasGuestsSid;
67 SepExports.SeAliasPowerUsersSid = SeAliasPowerUsersSid;
68 SepExports.SeAliasAccountOpsSid = SeAliasAccountOpsSid;
69 SepExports.SeAliasSystemOpsSid = SeAliasSystemOpsSid;
70 SepExports.SeAliasPrintOpsSid = SeAliasPrintOpsSid;
71 SepExports.SeAliasBackupOpsSid = SeAliasBackupOpsSid;
72 SepExports.SeAuthenticatedUsersSid = SeAuthenticatedUsersSid;
73 SepExports.SeRestrictedSid = SeRestrictedSid;
74 SepExports.SeAnonymousLogonSid = SeAnonymousLogonSid;
75
76 SepExports.SeUndockPrivilege = SeUndockPrivilege;
77 SepExports.SeSyncAgentPrivilege = SeSyncAgentPrivilege;
78 SepExports.SeEnableDelegationPrivilege = SeEnableDelegationPrivilege;
79
80 SeExports = &SepExports;
81 return TRUE;
82 }
83
84
85 BOOLEAN
86 NTAPI
87 SepInitializationPhase0(VOID)
88 {
89 PAGED_CODE();
90
91 ExpInitLuid();
92 if (!SepInitSecurityIDs()) return FALSE;
93 if (!SepInitDACLs()) return FALSE;
94 if (!SepInitSDs()) return FALSE;
95 SepInitPrivileges();
96 if (!SepInitExports()) return FALSE;
97
98 /* Initialize the subject context lock */
99 ExInitializeResource(&SepSubjectContextLock);
100
101 /* Initialize token objects */
102 SepInitializeTokenImplementation();
103
104 /* Clear impersonation info for the idle thread */
105 PsGetCurrentThread()->ImpersonationInfo = NULL;
106 PspClearCrossThreadFlag(PsGetCurrentThread(),
107 CT_ACTIVE_IMPERSONATION_INFO_BIT);
108
109 /* Initialize the boot token */
110 ObInitializeFastReference(&PsGetCurrentProcess()->Token, NULL);
111 ObInitializeFastReference(&PsGetCurrentProcess()->Token,
112 SepCreateSystemProcessToken());
113 return TRUE;
114 }
115
116 BOOLEAN
117 NTAPI
118 SepInitializationPhase1(VOID)
119 {
120 NTSTATUS Status;
121 PAGED_CODE();
122
123 /* Insert the system token into the tree */
124 Status = ObInsertObject((PVOID)(PsGetCurrentProcess()->Token.Value &
125 ~MAX_FAST_REFS),
126 NULL,
127 0,
128 0,
129 NULL,
130 NULL);
131 ASSERT(NT_SUCCESS(Status));
132
133 /* FIXME: TODO \\ Security directory */
134 return TRUE;
135 }
136
137 BOOLEAN
138 NTAPI
139 SeInitSystem(VOID)
140 {
141 /* Check the initialization phase */
142 switch (ExpInitializationPhase)
143 {
144 case 0:
145
146 /* Do Phase 0 */
147 return SepInitializationPhase0();
148
149 case 1:
150
151 /* Do Phase 1 */
152 return SepInitializationPhase1();
153
154 default:
155
156 /* Don't know any other phase! Bugcheck! */
157 KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL,
158 0,
159 ExpInitializationPhase,
160 0,
161 0);
162 return FALSE;
163 }
164 }
165
166 BOOLEAN
167 NTAPI
168 SeInitSRM(VOID)
169 {
170 OBJECT_ATTRIBUTES ObjectAttributes;
171 UNICODE_STRING Name;
172 HANDLE DirectoryHandle;
173 HANDLE EventHandle;
174 NTSTATUS Status;
175
176 /* Create '\Security' directory */
177 RtlInitUnicodeString(&Name,
178 L"\\Security");
179 InitializeObjectAttributes(&ObjectAttributes,
180 &Name,
181 OBJ_PERMANENT,
182 0,
183 NULL);
184 Status = ZwCreateDirectoryObject(&DirectoryHandle,
185 DIRECTORY_ALL_ACCESS,
186 &ObjectAttributes);
187 if (!NT_SUCCESS(Status))
188 {
189 DPRINT1("Failed to create 'Security' directory!\n");
190 return FALSE;
191 }
192
193 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
194 RtlInitUnicodeString(&Name,
195 L"\\LSA_AUTHENTICATION_INITALIZED");
196 InitializeObjectAttributes(&ObjectAttributes,
197 &Name,
198 OBJ_PERMANENT,
199 DirectoryHandle,
200 SePublicDefaultSd);
201 Status = ZwCreateEvent(&EventHandle,
202 EVENT_ALL_ACCESS,
203 &ObjectAttributes,
204 SynchronizationEvent,
205 FALSE);
206 if (!NT_SUCCESS(Status))
207 {
208 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
209 NtClose(DirectoryHandle);
210 return FALSE;
211 }
212
213 ZwClose(EventHandle);
214 ZwClose(DirectoryHandle);
215
216 /* FIXME: Create SRM port and listener thread */
217
218 return TRUE;
219 }
220
221 NTSTATUS
222 NTAPI
223 SeDefaultObjectMethod(IN PVOID Object,
224 IN SECURITY_OPERATION_CODE OperationType,
225 IN PSECURITY_INFORMATION SecurityInformation,
226 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
227 IN OUT PULONG ReturnLength OPTIONAL,
228 IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
229 IN POOL_TYPE PoolType,
230 IN PGENERIC_MAPPING GenericMapping)
231 {
232 PAGED_CODE();
233
234 /* Select the operation type */
235 switch (OperationType)
236 {
237 /* Setting a new descriptor */
238 case SetSecurityDescriptor:
239
240 /* Sanity check */
241 ASSERT((PoolType == PagedPool) || (PoolType == NonPagedPool));
242
243 /* Set the information */
244 return ObSetSecurityDescriptorInfo(Object,
245 SecurityInformation,
246 SecurityDescriptor,
247 OldSecurityDescriptor,
248 PoolType,
249 GenericMapping);
250
251 case QuerySecurityDescriptor:
252
253 /* Query the information */
254 return ObQuerySecurityDescriptorInfo(Object,
255 SecurityInformation,
256 SecurityDescriptor,
257 ReturnLength,
258 OldSecurityDescriptor);
259
260 case DeleteSecurityDescriptor:
261
262 /* De-assign it */
263 return ObDeassignSecurity(OldSecurityDescriptor);
264
265 case AssignSecurityDescriptor:
266
267 /* Assign it */
268 ObAssignObjectSecurityDescriptor(Object, SecurityDescriptor, PoolType);
269 return STATUS_SUCCESS;
270
271 default:
272
273 /* Bug check */
274 KeBugCheckEx(SECURITY_SYSTEM, 0, STATUS_INVALID_PARAMETER, 0, 0);
275 }
276
277 /* Should never reach here */
278 ASSERT(FALSE);
279 return STATUS_SUCCESS;
280 }
281
282 ULONG SidInTokenCalls = 0;
283
284 static BOOLEAN
285 SepSidInToken(PACCESS_TOKEN _Token,
286 PSID Sid)
287 {
288 ULONG i;
289 PTOKEN Token = (PTOKEN)_Token;
290
291 PAGED_CODE();
292
293 SidInTokenCalls++;
294 if (!(SidInTokenCalls % 10000)) DPRINT1("SidInToken Calls: %d\n", SidInTokenCalls);
295
296 if (Token->UserAndGroupCount == 0)
297 {
298 return FALSE;
299 }
300
301 for (i=0; i<Token->UserAndGroupCount; i++)
302 {
303 if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
304 {
305 if ((i == 0)|| (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED))
306 {
307 return TRUE;
308 }
309
310 return FALSE;
311 }
312 }
313
314 return FALSE;
315 }
316
317
318 VOID NTAPI
319 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
320 OUT PACCESS_MASK DesiredAccess)
321 {
322 *DesiredAccess = 0;
323
324 if (SecurityInformation & (OWNER_SECURITY_INFORMATION |
325 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION))
326 {
327 *DesiredAccess |= READ_CONTROL;
328 }
329 if (SecurityInformation & SACL_SECURITY_INFORMATION)
330 {
331 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
332 }
333 }
334
335 VOID NTAPI
336 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
337 OUT PACCESS_MASK DesiredAccess)
338 {
339 *DesiredAccess = 0;
340
341 if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
342 {
343 *DesiredAccess |= WRITE_OWNER;
344 }
345 if (SecurityInformation & DACL_SECURITY_INFORMATION)
346 {
347 *DesiredAccess |= WRITE_DAC;
348 }
349 if (SecurityInformation & SACL_SECURITY_INFORMATION)
350 {
351 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
352 }
353 }
354
355 BOOLEAN NTAPI
356 SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
357 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
358 IN BOOLEAN SubjectContextLocked,
359 IN ACCESS_MASK DesiredAccess,
360 IN ACCESS_MASK PreviouslyGrantedAccess,
361 OUT PPRIVILEGE_SET* Privileges,
362 IN PGENERIC_MAPPING GenericMapping,
363 IN KPROCESSOR_MODE AccessMode,
364 OUT PACCESS_MASK GrantedAccess,
365 OUT PNTSTATUS AccessStatus,
366 SECURITY_IMPERSONATION_LEVEL LowestImpersonationLevel)
367 {
368 LUID_AND_ATTRIBUTES Privilege;
369 ACCESS_MASK CurrentAccess, AccessMask;
370 PACCESS_TOKEN Token;
371 ULONG i;
372 PACL Dacl;
373 BOOLEAN Present;
374 BOOLEAN Defaulted;
375 PACE CurrentAce;
376 PSID Sid;
377 NTSTATUS Status;
378 PAGED_CODE();
379
380 /* Check if this is kernel mode */
381 if (AccessMode == KernelMode)
382 {
383 /* Check if kernel wants everything */
384 if (DesiredAccess & MAXIMUM_ALLOWED)
385 {
386 /* Give it */
387 *GrantedAccess = GenericMapping->GenericAll;
388 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
389 *GrantedAccess |= PreviouslyGrantedAccess;
390 }
391 else
392 {
393 /* Give the desired and previous access */
394 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
395 }
396
397 /* Success */
398 *AccessStatus = STATUS_SUCCESS;
399 return TRUE;
400 }
401
402 /* Check if we didn't get an SD */
403 if (!SecurityDescriptor)
404 {
405 /* Automatic failure */
406 *AccessStatus = STATUS_ACCESS_DENIED;
407 return FALSE;
408 }
409
410 /* Check for invalid impersonation */
411 if ((SubjectSecurityContext->ClientToken) &&
412 (SubjectSecurityContext->ImpersonationLevel < LowestImpersonationLevel))
413 {
414 *AccessStatus = STATUS_BAD_IMPERSONATION_LEVEL;
415 return FALSE;
416 }
417
418 /* Check for no access desired */
419 if (!DesiredAccess)
420 {
421 /* Check if we had no previous access */
422 if (!PreviouslyGrantedAccess)
423 {
424 /* Then there's nothing to give */
425 *AccessStatus = STATUS_ACCESS_DENIED;
426 return FALSE;
427 }
428
429 /* Return the previous access only */
430 *GrantedAccess = PreviouslyGrantedAccess;
431 *AccessStatus = STATUS_SUCCESS;
432 *Privileges = NULL;
433 return TRUE;
434 }
435
436 /* Acquire the lock if needed */
437 if (!SubjectContextLocked) SeLockSubjectContext(SubjectSecurityContext);
438
439 /* Map given accesses */
440 RtlMapGenericMask(&DesiredAccess, GenericMapping);
441 if (PreviouslyGrantedAccess)
442 RtlMapGenericMask(&PreviouslyGrantedAccess, GenericMapping);
443
444
445
446 CurrentAccess = PreviouslyGrantedAccess;
447
448
449
450 Token = SubjectSecurityContext->ClientToken ?
451 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
452
453 /* Get the DACL */
454 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
455 &Present,
456 &Dacl,
457 &Defaulted);
458 if (!NT_SUCCESS(Status))
459 {
460 if (SubjectContextLocked == FALSE)
461 {
462 SeUnlockSubjectContext(SubjectSecurityContext);
463 }
464
465 *AccessStatus = Status;
466 return FALSE;
467 }
468
469 /* RULE 1: Grant desired access if the object is unprotected */
470 if (Present == TRUE && Dacl == NULL)
471 {
472 if (SubjectContextLocked == FALSE)
473 {
474 SeUnlockSubjectContext(SubjectSecurityContext);
475 }
476
477 if (DesiredAccess & MAXIMUM_ALLOWED)
478 {
479 *GrantedAccess = GenericMapping->GenericAll;
480 *GrantedAccess |= (DesiredAccess & ~MAXIMUM_ALLOWED);
481 }
482 else
483 {
484 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
485 }
486
487 *AccessStatus = STATUS_SUCCESS;
488 return TRUE;
489 }
490
491 CurrentAccess = PreviouslyGrantedAccess;
492
493 /* RULE 2: Check token for 'take ownership' privilege */
494 Privilege.Luid = SeTakeOwnershipPrivilege;
495 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
496
497 if (SepPrivilegeCheck(Token,
498 &Privilege,
499 1,
500 PRIVILEGE_SET_ALL_NECESSARY,
501 AccessMode))
502 {
503 CurrentAccess |= WRITE_OWNER;
504 if ((DesiredAccess & ~VALID_INHERIT_FLAGS) ==
505 (CurrentAccess & ~VALID_INHERIT_FLAGS))
506 {
507 if (SubjectContextLocked == FALSE)
508 {
509 SeUnlockSubjectContext(SubjectSecurityContext);
510 }
511
512 *GrantedAccess = CurrentAccess;
513 *AccessStatus = STATUS_SUCCESS;
514 return TRUE;
515 }
516 }
517
518 /* RULE 3: Check whether the token is the owner */
519 Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
520 &Sid,
521 &Defaulted);
522 if (!NT_SUCCESS(Status))
523 {
524 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
525 if (SubjectContextLocked == FALSE)
526 {
527 SeUnlockSubjectContext(SubjectSecurityContext);
528 }
529
530 *AccessStatus = Status;
531 return FALSE;
532 }
533
534 if (Sid && SepSidInToken(Token, Sid))
535 {
536 CurrentAccess |= (READ_CONTROL | WRITE_DAC);
537 if ((DesiredAccess & ~VALID_INHERIT_FLAGS) ==
538 (CurrentAccess & ~VALID_INHERIT_FLAGS))
539 {
540 if (SubjectContextLocked == FALSE)
541 {
542 SeUnlockSubjectContext(SubjectSecurityContext);
543 }
544
545 *GrantedAccess = CurrentAccess;
546 *AccessStatus = STATUS_SUCCESS;
547 return TRUE;
548 }
549 }
550
551 /* Fail if DACL is absent */
552 if (Present == FALSE)
553 {
554 if (SubjectContextLocked == FALSE)
555 {
556 SeUnlockSubjectContext(SubjectSecurityContext);
557 }
558
559 *GrantedAccess = 0;
560 *AccessStatus = STATUS_ACCESS_DENIED;
561 return FALSE;
562 }
563
564 /* RULE 4: Grant rights according to the DACL */
565 CurrentAce = (PACE)(Dacl + 1);
566 for (i = 0; i < Dacl->AceCount; i++)
567 {
568 Sid = (PSID)(CurrentAce + 1);
569 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
570 {
571 if (SepSidInToken(Token, Sid))
572 {
573 if (SubjectContextLocked == FALSE)
574 {
575 SeUnlockSubjectContext(SubjectSecurityContext);
576 }
577
578 *GrantedAccess = 0;
579 *AccessStatus = STATUS_ACCESS_DENIED;
580 return FALSE;
581 }
582 }
583
584 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
585 {
586 if (SepSidInToken(Token, Sid))
587 {
588 AccessMask = CurrentAce->AccessMask;
589 RtlMapGenericMask(&AccessMask, GenericMapping);
590 CurrentAccess |= AccessMask;
591 }
592 }
593 else
594 {
595 DPRINT1("Unknown Ace type 0x%lx\n", CurrentAce->Header.AceType);
596 }
597 CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
598 }
599
600 if (SubjectContextLocked == FALSE)
601 {
602 SeUnlockSubjectContext(SubjectSecurityContext);
603 }
604
605 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
606 CurrentAccess, DesiredAccess);
607
608 *GrantedAccess = CurrentAccess & DesiredAccess;
609
610 if (DesiredAccess & MAXIMUM_ALLOWED)
611 {
612 *GrantedAccess = CurrentAccess;
613 *AccessStatus = STATUS_SUCCESS;
614 return TRUE;
615 }
616 else if ((*GrantedAccess & ~VALID_INHERIT_FLAGS) ==
617 (DesiredAccess & ~VALID_INHERIT_FLAGS))
618 {
619 *AccessStatus = STATUS_SUCCESS;
620 return TRUE;
621 }
622 else
623 {
624 DPRINT1("HACK: Should deny access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p).\n",
625 *GrantedAccess, DesiredAccess, GenericMapping);
626 //*AccessStatus = STATUS_ACCESS_DENIED;
627 //return FALSE;
628 *AccessStatus = STATUS_SUCCESS;
629 return TRUE;
630 }
631 }
632
633 /* PUBLIC FUNCTIONS ***********************************************************/
634
635 /*
636 * @implemented
637 */
638 BOOLEAN NTAPI
639 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
640 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
641 IN BOOLEAN SubjectContextLocked,
642 IN ACCESS_MASK DesiredAccess,
643 IN ACCESS_MASK PreviouslyGrantedAccess,
644 OUT PPRIVILEGE_SET* Privileges,
645 IN PGENERIC_MAPPING GenericMapping,
646 IN KPROCESSOR_MODE AccessMode,
647 OUT PACCESS_MASK GrantedAccess,
648 OUT PNTSTATUS AccessStatus)
649 {
650 /* Call the internal function */
651 return SepAccessCheck(SecurityDescriptor,
652 SubjectSecurityContext,
653 SubjectContextLocked,
654 DesiredAccess,
655 PreviouslyGrantedAccess,
656 Privileges,
657 GenericMapping,
658 AccessMode,
659 GrantedAccess,
660 AccessStatus,
661 SecurityImpersonation);
662 }
663
664 /* SYSTEM CALLS ***************************************************************/
665
666 /*
667 * @implemented
668 */
669 NTSTATUS
670 NTAPI
671 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
672 IN HANDLE TokenHandle,
673 IN ACCESS_MASK DesiredAccess,
674 IN PGENERIC_MAPPING GenericMapping,
675 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
676 IN OUT PULONG PrivilegeSetLength,
677 OUT PACCESS_MASK GrantedAccess,
678 OUT PNTSTATUS AccessStatus)
679 {
680 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
681 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
682 PTOKEN Token;
683 NTSTATUS Status;
684 PAGED_CODE();
685
686 /* Check if this is kernel mode */
687 if (PreviousMode == KernelMode)
688 {
689 /* Check if kernel wants everything */
690 if (DesiredAccess & MAXIMUM_ALLOWED)
691 {
692 /* Give it */
693 *GrantedAccess = GenericMapping->GenericAll;
694 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
695 }
696 else
697 {
698 /* Just give the desired access */
699 *GrantedAccess = DesiredAccess;
700 }
701
702 /* Success */
703 *AccessStatus = STATUS_SUCCESS;
704 return STATUS_SUCCESS;
705 }
706
707 /* Protect probe in SEH */
708 _SEH2_TRY
709 {
710 /* Probe all pointers */
711 ProbeForRead(GenericMapping, sizeof(GENERIC_MAPPING), sizeof(ULONG));
712 ProbeForRead(PrivilegeSetLength, sizeof(ULONG), sizeof(ULONG));
713 ProbeForWrite(PrivilegeSet, *PrivilegeSetLength, sizeof(ULONG));
714 ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
715 ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
716 }
717 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
718 {
719 /* Return the exception code */
720 _SEH2_YIELD(return _SEH2_GetExceptionCode());
721 }
722 _SEH2_END;
723
724 /* Check for unmapped access rights */
725 if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
726 return STATUS_GENERIC_NOT_MAPPED;
727
728 /* Reference the token */
729 Status = ObReferenceObjectByHandle(TokenHandle,
730 TOKEN_QUERY,
731 SepTokenObjectType,
732 PreviousMode,
733 (PVOID*)&Token,
734 NULL);
735 if (!NT_SUCCESS(Status))
736 {
737 DPRINT1("Failed to reference token (Status %lx)\n", Status);
738 return Status;
739 }
740
741 /* Check token type */
742 if (Token->TokenType != TokenImpersonation)
743 {
744 DPRINT1("No impersonation token\n");
745 ObDereferenceObject(Token);
746 return STATUS_NO_IMPERSONATION_TOKEN;
747 }
748
749 /* Check the impersonation level */
750 if (Token->ImpersonationLevel < SecurityIdentification)
751 {
752 DPRINT1("Impersonation level < SecurityIdentification\n");
753 ObDereferenceObject(Token);
754 return STATUS_BAD_IMPERSONATION_LEVEL;
755 }
756
757 /* Set up the subject context, and lock it */
758 SubjectSecurityContext.ClientToken = Token;
759 SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
760 SubjectSecurityContext.PrimaryToken = NULL;
761 SubjectSecurityContext.ProcessAuditId = NULL;
762 SeLockSubjectContext(&SubjectSecurityContext);
763
764 /* Now perform the access check */
765 SepAccessCheck(SecurityDescriptor,
766 &SubjectSecurityContext,
767 TRUE,
768 DesiredAccess,
769 0,
770 &PrivilegeSet, //FIXME
771 GenericMapping,
772 PreviousMode,
773 GrantedAccess,
774 AccessStatus,
775 SecurityIdentification);
776
777 /* Unlock subject context and dereference the token */
778 SeUnlockSubjectContext(&SubjectSecurityContext);
779 ObDereferenceObject(Token);
780
781 /* Check succeeded */
782 return STATUS_SUCCESS;
783 }
784
785
786 NTSTATUS
787 NTAPI
788 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
789 IN PSID PrincipalSelfSid,
790 IN HANDLE ClientToken,
791 IN ACCESS_MASK DesiredAccess,
792 IN POBJECT_TYPE_LIST ObjectTypeList,
793 IN ULONG ObjectTypeLength,
794 IN PGENERIC_MAPPING GenericMapping,
795 IN PPRIVILEGE_SET PrivilegeSet,
796 IN ULONG PrivilegeSetLength,
797 OUT PACCESS_MASK GrantedAccess,
798 OUT PNTSTATUS AccessStatus)
799 {
800 UNIMPLEMENTED;
801 return STATUS_NOT_IMPLEMENTED;
802 }
803
804 NTSTATUS
805 NTAPI
806 NtAccessCheckByTypeAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
807 IN HANDLE HandleId,
808 IN PUNICODE_STRING ObjectTypeName,
809 IN PUNICODE_STRING ObjectName,
810 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
811 IN PSID PrincipalSelfSid,
812 IN ACCESS_MASK DesiredAccess,
813 IN AUDIT_EVENT_TYPE AuditType,
814 IN ULONG Flags,
815 IN POBJECT_TYPE_LIST ObjectTypeList,
816 IN ULONG ObjectTypeLength,
817 IN PGENERIC_MAPPING GenericMapping,
818 IN BOOLEAN ObjectCreation,
819 OUT PACCESS_MASK GrantedAccess,
820 OUT PNTSTATUS AccessStatus,
821 OUT PBOOLEAN GenerateOnClose)
822 {
823 UNIMPLEMENTED;
824 return STATUS_NOT_IMPLEMENTED;
825 }
826
827 NTSTATUS
828 NTAPI
829 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
830 IN PSID PrincipalSelfSid,
831 IN HANDLE ClientToken,
832 IN ACCESS_MASK DesiredAccess,
833 IN POBJECT_TYPE_LIST ObjectTypeList,
834 IN ULONG ObjectTypeLength,
835 IN PGENERIC_MAPPING GenericMapping,
836 IN PPRIVILEGE_SET PrivilegeSet,
837 IN ULONG PrivilegeSetLength,
838 OUT PACCESS_MASK GrantedAccess,
839 OUT PNTSTATUS AccessStatus)
840 {
841 UNIMPLEMENTED;
842 return STATUS_NOT_IMPLEMENTED;
843 }
844
845 NTSTATUS
846 NTAPI
847 NtAccessCheckByTypeResultListAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
848 IN HANDLE HandleId,
849 IN PUNICODE_STRING ObjectTypeName,
850 IN PUNICODE_STRING ObjectName,
851 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
852 IN PSID PrincipalSelfSid,
853 IN ACCESS_MASK DesiredAccess,
854 IN AUDIT_EVENT_TYPE AuditType,
855 IN ULONG Flags,
856 IN POBJECT_TYPE_LIST ObjectTypeList,
857 IN ULONG ObjectTypeLength,
858 IN PGENERIC_MAPPING GenericMapping,
859 IN BOOLEAN ObjectCreation,
860 OUT PACCESS_MASK GrantedAccess,
861 OUT PNTSTATUS AccessStatus,
862 OUT PBOOLEAN GenerateOnClose)
863 {
864 UNIMPLEMENTED;
865 return STATUS_NOT_IMPLEMENTED;
866 }
867
868 NTSTATUS
869 NTAPI
870 NtAccessCheckByTypeResultListAndAuditAlarmByHandle(IN PUNICODE_STRING SubsystemName,
871 IN HANDLE HandleId,
872 IN HANDLE ClientToken,
873 IN PUNICODE_STRING ObjectTypeName,
874 IN PUNICODE_STRING ObjectName,
875 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
876 IN PSID PrincipalSelfSid,
877 IN ACCESS_MASK DesiredAccess,
878 IN AUDIT_EVENT_TYPE AuditType,
879 IN ULONG Flags,
880 IN POBJECT_TYPE_LIST ObjectTypeList,
881 IN ULONG ObjectTypeLength,
882 IN PGENERIC_MAPPING GenericMapping,
883 IN BOOLEAN ObjectCreation,
884 OUT PACCESS_MASK GrantedAccess,
885 OUT PNTSTATUS AccessStatus,
886 OUT PBOOLEAN GenerateOnClose)
887 {
888 UNIMPLEMENTED;
889 return STATUS_NOT_IMPLEMENTED;
890 }
891
892 /* EOF */