Revert the sync.
[reactos.git] / 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 ACCESS_MASK DesiredAccess,
359 IN ACCESS_MASK PreviouslyGrantedAccess,
360 OUT PPRIVILEGE_SET* Privileges,
361 IN PGENERIC_MAPPING GenericMapping,
362 IN KPROCESSOR_MODE AccessMode,
363 OUT PACCESS_MASK GrantedAccess,
364 OUT PNTSTATUS AccessStatus)
365 {
366 LUID_AND_ATTRIBUTES Privilege;
367 ACCESS_MASK CurrentAccess, AccessMask;
368 PACCESS_TOKEN Token;
369 ULONG i;
370 PACL Dacl;
371 BOOLEAN Present;
372 BOOLEAN Defaulted;
373 PACE CurrentAce;
374 PSID Sid;
375 NTSTATUS Status;
376 PAGED_CODE();
377
378 /* Check for no access desired */
379 if (!DesiredAccess)
380 {
381 /* Check if we had no previous access */
382 if (!PreviouslyGrantedAccess)
383 {
384 /* Then there's nothing to give */
385 *AccessStatus = STATUS_ACCESS_DENIED;
386 return FALSE;
387 }
388
389 /* Return the previous access only */
390 *GrantedAccess = PreviouslyGrantedAccess;
391 *AccessStatus = STATUS_SUCCESS;
392 *Privileges = NULL;
393 return TRUE;
394 }
395
396 /* Map given accesses */
397 RtlMapGenericMask(&DesiredAccess, GenericMapping);
398 if (PreviouslyGrantedAccess)
399 RtlMapGenericMask(&PreviouslyGrantedAccess, GenericMapping);
400
401
402
403 CurrentAccess = PreviouslyGrantedAccess;
404
405
406
407 Token = SubjectSecurityContext->ClientToken ?
408 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
409
410 /* Get the DACL */
411 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
412 &Present,
413 &Dacl,
414 &Defaulted);
415 if (!NT_SUCCESS(Status))
416 {
417 *AccessStatus = Status;
418 return FALSE;
419 }
420
421 /* RULE 1: Grant desired access if the object is unprotected */
422 if (Present == FALSE || Dacl == NULL)
423 {
424 if (DesiredAccess & MAXIMUM_ALLOWED)
425 {
426 *GrantedAccess = GenericMapping->GenericAll;
427 *GrantedAccess |= (DesiredAccess & ~MAXIMUM_ALLOWED);
428 }
429 else
430 {
431 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
432 }
433
434 *AccessStatus = STATUS_SUCCESS;
435 return TRUE;
436 }
437
438 CurrentAccess = PreviouslyGrantedAccess;
439
440 /* RULE 2: Check token for 'take ownership' privilege */
441 Privilege.Luid = SeTakeOwnershipPrivilege;
442 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
443
444 if (SepPrivilegeCheck(Token,
445 &Privilege,
446 1,
447 PRIVILEGE_SET_ALL_NECESSARY,
448 AccessMode))
449 {
450 CurrentAccess |= WRITE_OWNER;
451 if ((DesiredAccess & ~VALID_INHERIT_FLAGS) ==
452 (CurrentAccess & ~VALID_INHERIT_FLAGS))
453 {
454 *GrantedAccess = CurrentAccess;
455 *AccessStatus = STATUS_SUCCESS;
456 return TRUE;
457 }
458 }
459
460 /* Deny access if the DACL is empty */
461 if (Dacl->AceCount == 0)
462 {
463 *GrantedAccess = 0;
464 *AccessStatus = STATUS_ACCESS_DENIED;
465 return FALSE;
466 }
467
468 /* RULE 3: Check whether the token is the owner */
469 Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
470 &Sid,
471 &Defaulted);
472 if (!NT_SUCCESS(Status))
473 {
474 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
475 *AccessStatus = Status;
476 return FALSE;
477 }
478
479 if (Sid && SepSidInToken(Token, Sid))
480 {
481 CurrentAccess |= (READ_CONTROL | WRITE_DAC);
482 if ((DesiredAccess & ~VALID_INHERIT_FLAGS) ==
483 (CurrentAccess & ~VALID_INHERIT_FLAGS))
484 {
485 *GrantedAccess = CurrentAccess;
486 *AccessStatus = STATUS_SUCCESS;
487 return TRUE;
488 }
489 }
490
491 /* Fail if DACL is absent */
492 if (Present == FALSE)
493 {
494 *GrantedAccess = 0;
495 *AccessStatus = STATUS_ACCESS_DENIED;
496 return FALSE;
497 }
498
499 /* RULE 4: Grant rights according to the DACL */
500 CurrentAce = (PACE)(Dacl + 1);
501 for (i = 0; i < Dacl->AceCount; i++)
502 {
503 Sid = (PSID)(CurrentAce + 1);
504 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
505 {
506 if (SepSidInToken(Token, Sid))
507 {
508 *GrantedAccess = 0;
509 *AccessStatus = STATUS_ACCESS_DENIED;
510 return FALSE;
511 }
512 }
513
514 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
515 {
516 if (SepSidInToken(Token, Sid))
517 {
518 AccessMask = CurrentAce->AccessMask;
519 RtlMapGenericMask(&AccessMask, GenericMapping);
520 CurrentAccess |= AccessMask;
521 }
522 }
523 else
524 {
525 DPRINT1("Unknown Ace type 0x%lx\n", CurrentAce->Header.AceType);
526 }
527 CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
528 }
529
530 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
531 CurrentAccess, DesiredAccess);
532
533 *GrantedAccess = CurrentAccess & DesiredAccess;
534
535 if (DesiredAccess & MAXIMUM_ALLOWED)
536 {
537 *GrantedAccess = CurrentAccess;
538 *AccessStatus = STATUS_SUCCESS;
539 return TRUE;
540 }
541 else if ((*GrantedAccess & ~VALID_INHERIT_FLAGS) ==
542 (DesiredAccess & ~VALID_INHERIT_FLAGS))
543 {
544 *AccessStatus = STATUS_SUCCESS;
545 return TRUE;
546 }
547 else
548 {
549 DPRINT1("HACK: Should deny access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p).\n",
550 *GrantedAccess, DesiredAccess, GenericMapping);
551 //*AccessStatus = STATUS_ACCESS_DENIED;
552 //return FALSE;
553 *AccessStatus = STATUS_SUCCESS;
554 return TRUE;
555 }
556 }
557
558 static PSID
559 SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
560 {
561 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
562 PSID Owner;
563
564 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
565 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
566 (ULONG_PTR)SecurityDescriptor);
567 else
568 Owner = (PSID)SecurityDescriptor->Owner;
569
570 return Owner;
571 }
572
573 static PSID
574 SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
575 {
576 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
577 PSID Group;
578
579 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
580 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
581 (ULONG_PTR)SecurityDescriptor);
582 else
583 Group = (PSID)SecurityDescriptor->Group;
584
585 return Group;
586 }
587
588
589 /* PUBLIC FUNCTIONS ***********************************************************/
590
591 /*
592 * @implemented
593 */
594 BOOLEAN NTAPI
595 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
596 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
597 IN BOOLEAN SubjectContextLocked,
598 IN ACCESS_MASK DesiredAccess,
599 IN ACCESS_MASK PreviouslyGrantedAccess,
600 OUT PPRIVILEGE_SET* Privileges,
601 IN PGENERIC_MAPPING GenericMapping,
602 IN KPROCESSOR_MODE AccessMode,
603 OUT PACCESS_MASK GrantedAccess,
604 OUT PNTSTATUS AccessStatus)
605 {
606 BOOLEAN ret;
607
608 PAGED_CODE();
609
610 /* Check if this is kernel mode */
611 if (AccessMode == KernelMode)
612 {
613 /* Check if kernel wants everything */
614 if (DesiredAccess & MAXIMUM_ALLOWED)
615 {
616 /* Give it */
617 *GrantedAccess = GenericMapping->GenericAll;
618 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
619 *GrantedAccess |= PreviouslyGrantedAccess;
620 }
621 else
622 {
623 /* Give the desired and previous access */
624 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
625 }
626
627 /* Success */
628 *AccessStatus = STATUS_SUCCESS;
629 return TRUE;
630 }
631
632 /* Check if we didn't get an SD */
633 if (!SecurityDescriptor)
634 {
635 /* Automatic failure */
636 *AccessStatus = STATUS_ACCESS_DENIED;
637 return FALSE;
638 }
639
640 /* Check for invalid impersonation */
641 if ((SubjectSecurityContext->ClientToken) &&
642 (SubjectSecurityContext->ImpersonationLevel < SecurityImpersonation))
643 {
644 *AccessStatus = STATUS_BAD_IMPERSONATION_LEVEL;
645 return FALSE;
646 }
647
648 /* Acquire the lock if needed */
649 if (!SubjectContextLocked)
650 SeLockSubjectContext(SubjectSecurityContext);
651
652 /* Call the internal function */
653 ret = SepAccessCheck(SecurityDescriptor,
654 SubjectSecurityContext,
655 DesiredAccess,
656 PreviouslyGrantedAccess,
657 Privileges,
658 GenericMapping,
659 AccessMode,
660 GrantedAccess,
661 AccessStatus);
662
663 /* Release the lock if needed */
664 if (!SubjectContextLocked)
665 SeUnlockSubjectContext(SubjectSecurityContext);
666
667 return ret;
668 }
669
670 /* SYSTEM CALLS ***************************************************************/
671
672 /*
673 * @implemented
674 */
675 NTSTATUS
676 NTAPI
677 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
678 IN HANDLE TokenHandle,
679 IN ACCESS_MASK DesiredAccess,
680 IN PGENERIC_MAPPING GenericMapping,
681 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
682 IN OUT PULONG PrivilegeSetLength,
683 OUT PACCESS_MASK GrantedAccess,
684 OUT PNTSTATUS AccessStatus)
685 {
686 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
687 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
688 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
689 PTOKEN Token;
690 NTSTATUS Status;
691 PAGED_CODE();
692
693 /* Check if this is kernel mode */
694 if (PreviousMode == KernelMode)
695 {
696 /* Check if kernel wants everything */
697 if (DesiredAccess & MAXIMUM_ALLOWED)
698 {
699 /* Give it */
700 *GrantedAccess = GenericMapping->GenericAll;
701 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
702 }
703 else
704 {
705 /* Just give the desired access */
706 *GrantedAccess = DesiredAccess;
707 }
708
709 /* Success */
710 *AccessStatus = STATUS_SUCCESS;
711 return STATUS_SUCCESS;
712 }
713
714 /* Protect probe in SEH */
715 _SEH2_TRY
716 {
717 /* Probe all pointers */
718 ProbeForRead(GenericMapping, sizeof(GENERIC_MAPPING), sizeof(ULONG));
719 ProbeForRead(PrivilegeSetLength, sizeof(ULONG), sizeof(ULONG));
720 ProbeForWrite(PrivilegeSet, *PrivilegeSetLength, sizeof(ULONG));
721 ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
722 ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
723 }
724 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
725 {
726 /* Return the exception code */
727 _SEH2_YIELD(return _SEH2_GetExceptionCode());
728 }
729 _SEH2_END;
730
731 /* Check for unmapped access rights */
732 if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
733 return STATUS_GENERIC_NOT_MAPPED;
734
735 /* Reference the token */
736 Status = ObReferenceObjectByHandle(TokenHandle,
737 TOKEN_QUERY,
738 SepTokenObjectType,
739 PreviousMode,
740 (PVOID*)&Token,
741 NULL);
742 if (!NT_SUCCESS(Status))
743 {
744 DPRINT("Failed to reference token (Status %lx)\n", Status);
745 return Status;
746 }
747
748 /* Check token type */
749 if (Token->TokenType != TokenImpersonation)
750 {
751 DPRINT("No impersonation token\n");
752 ObDereferenceObject(Token);
753 return STATUS_NO_IMPERSONATION_TOKEN;
754 }
755
756 /* Check the impersonation level */
757 if (Token->ImpersonationLevel < SecurityIdentification)
758 {
759 DPRINT("Impersonation level < SecurityIdentification\n");
760 ObDereferenceObject(Token);
761 return STATUS_BAD_IMPERSONATION_LEVEL;
762 }
763
764 /* Capture the security descriptor */
765 Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
766 PreviousMode,
767 PagedPool,
768 FALSE,
769 &CapturedSecurityDescriptor);
770 if (!NT_SUCCESS(Status))
771 {
772 DPRINT("Failed to capture the Security Descriptor\n");
773 ObDereferenceObject(Token);
774 return Status;
775 }
776
777 /* Check the captured security descriptor */
778 if (CapturedSecurityDescriptor == NULL)
779 {
780 DPRINT("Security Descriptor is NULL\n");
781 ObDereferenceObject(Token);
782 return STATUS_INVALID_SECURITY_DESCR;
783 }
784
785 /* Check security descriptor for valid owner and group */
786 if (SepGetSDOwner(SecurityDescriptor) == NULL || // FIXME: use CapturedSecurityDescriptor
787 SepGetSDGroup(SecurityDescriptor) == NULL) // FIXME: use CapturedSecurityDescriptor
788 {
789 DPRINT("Security Descriptor does not have a valid group or owner\n");
790 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
791 PreviousMode,
792 FALSE);
793 ObDereferenceObject(Token);
794 return STATUS_INVALID_SECURITY_DESCR;
795 }
796
797 /* Set up the subject context, and lock it */
798 SubjectSecurityContext.ClientToken = Token;
799 SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
800 SubjectSecurityContext.PrimaryToken = NULL;
801 SubjectSecurityContext.ProcessAuditId = NULL;
802 SeLockSubjectContext(&SubjectSecurityContext);
803
804 /* Now perform the access check */
805 SepAccessCheck(SecurityDescriptor, // FIXME: use CapturedSecurityDescriptor
806 &SubjectSecurityContext,
807 DesiredAccess,
808 0,
809 &PrivilegeSet, //FIXME
810 GenericMapping,
811 PreviousMode,
812 GrantedAccess,
813 AccessStatus);
814
815 /* Unlock subject context */
816 SeUnlockSubjectContext(&SubjectSecurityContext);
817
818 /* Release the captured security descriptor */
819 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
820 PreviousMode,
821 FALSE);
822
823 /* Dereference the token */
824 ObDereferenceObject(Token);
825
826 /* Check succeeded */
827 return STATUS_SUCCESS;
828 }
829
830
831 NTSTATUS
832 NTAPI
833 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
834 IN PSID PrincipalSelfSid,
835 IN HANDLE ClientToken,
836 IN ACCESS_MASK DesiredAccess,
837 IN POBJECT_TYPE_LIST ObjectTypeList,
838 IN ULONG ObjectTypeLength,
839 IN PGENERIC_MAPPING GenericMapping,
840 IN PPRIVILEGE_SET PrivilegeSet,
841 IN ULONG PrivilegeSetLength,
842 OUT PACCESS_MASK GrantedAccess,
843 OUT PNTSTATUS AccessStatus)
844 {
845 UNIMPLEMENTED;
846 return STATUS_NOT_IMPLEMENTED;
847 }
848
849 NTSTATUS
850 NTAPI
851 NtAccessCheckByTypeAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
852 IN HANDLE HandleId,
853 IN PUNICODE_STRING ObjectTypeName,
854 IN PUNICODE_STRING ObjectName,
855 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
856 IN PSID PrincipalSelfSid,
857 IN ACCESS_MASK DesiredAccess,
858 IN AUDIT_EVENT_TYPE AuditType,
859 IN ULONG Flags,
860 IN POBJECT_TYPE_LIST ObjectTypeList,
861 IN ULONG ObjectTypeLength,
862 IN PGENERIC_MAPPING GenericMapping,
863 IN BOOLEAN ObjectCreation,
864 OUT PACCESS_MASK GrantedAccess,
865 OUT PNTSTATUS AccessStatus,
866 OUT PBOOLEAN GenerateOnClose)
867 {
868 UNIMPLEMENTED;
869 return STATUS_NOT_IMPLEMENTED;
870 }
871
872 NTSTATUS
873 NTAPI
874 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
875 IN PSID PrincipalSelfSid,
876 IN HANDLE ClientToken,
877 IN ACCESS_MASK DesiredAccess,
878 IN POBJECT_TYPE_LIST ObjectTypeList,
879 IN ULONG ObjectTypeLength,
880 IN PGENERIC_MAPPING GenericMapping,
881 IN PPRIVILEGE_SET PrivilegeSet,
882 IN ULONG PrivilegeSetLength,
883 OUT PACCESS_MASK GrantedAccess,
884 OUT PNTSTATUS AccessStatus)
885 {
886 UNIMPLEMENTED;
887 return STATUS_NOT_IMPLEMENTED;
888 }
889
890 NTSTATUS
891 NTAPI
892 NtAccessCheckByTypeResultListAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
893 IN HANDLE HandleId,
894 IN PUNICODE_STRING ObjectTypeName,
895 IN PUNICODE_STRING ObjectName,
896 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
897 IN PSID PrincipalSelfSid,
898 IN ACCESS_MASK DesiredAccess,
899 IN AUDIT_EVENT_TYPE AuditType,
900 IN ULONG Flags,
901 IN POBJECT_TYPE_LIST ObjectTypeList,
902 IN ULONG ObjectTypeLength,
903 IN PGENERIC_MAPPING GenericMapping,
904 IN BOOLEAN ObjectCreation,
905 OUT PACCESS_MASK GrantedAccess,
906 OUT PNTSTATUS AccessStatus,
907 OUT PBOOLEAN GenerateOnClose)
908 {
909 UNIMPLEMENTED;
910 return STATUS_NOT_IMPLEMENTED;
911 }
912
913 NTSTATUS
914 NTAPI
915 NtAccessCheckByTypeResultListAndAuditAlarmByHandle(IN PUNICODE_STRING SubsystemName,
916 IN HANDLE HandleId,
917 IN HANDLE ClientToken,
918 IN PUNICODE_STRING ObjectTypeName,
919 IN PUNICODE_STRING ObjectName,
920 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
921 IN PSID PrincipalSelfSid,
922 IN ACCESS_MASK DesiredAccess,
923 IN AUDIT_EVENT_TYPE AuditType,
924 IN ULONG Flags,
925 IN POBJECT_TYPE_LIST ObjectTypeList,
926 IN ULONG ObjectTypeLength,
927 IN PGENERIC_MAPPING GenericMapping,
928 IN BOOLEAN ObjectCreation,
929 OUT PACCESS_MASK GrantedAccess,
930 OUT PNTSTATUS AccessStatus,
931 OUT PBOOLEAN GenerateOnClose)
932 {
933 UNIMPLEMENTED;
934 return STATUS_NOT_IMPLEMENTED;
935 }
936
937 /* EOF */