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