Synchronize up to trunk's revision r57784.
[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 ULONG SidInTokenCalls = 0;
21
22 extern ULONG ExpInitializationPhase;
23 extern ERESOURCE SepSubjectContextLock;
24
25 /* PRIVATE FUNCTIONS **********************************************************/
26
27 static BOOLEAN
28 INIT_FUNCTION
29 SepInitExports(VOID)
30 {
31 SepExports.SeCreateTokenPrivilege = SeCreateTokenPrivilege;
32 SepExports.SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
33 SepExports.SeLockMemoryPrivilege = SeLockMemoryPrivilege;
34 SepExports.SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
35 SepExports.SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
36 SepExports.SeTcbPrivilege = SeTcbPrivilege;
37 SepExports.SeSecurityPrivilege = SeSecurityPrivilege;
38 SepExports.SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
39 SepExports.SeLoadDriverPrivilege = SeLoadDriverPrivilege;
40 SepExports.SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
41 SepExports.SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
42 SepExports.SeSystemProfilePrivilege = SeSystemProfilePrivilege;
43 SepExports.SeSystemtimePrivilege = SeSystemtimePrivilege;
44 SepExports.SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
45 SepExports.SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
46 SepExports.SeBackupPrivilege = SeBackupPrivilege;
47 SepExports.SeRestorePrivilege = SeRestorePrivilege;
48 SepExports.SeShutdownPrivilege = SeShutdownPrivilege;
49 SepExports.SeDebugPrivilege = SeDebugPrivilege;
50 SepExports.SeAuditPrivilege = SeAuditPrivilege;
51 SepExports.SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
52 SepExports.SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
53 SepExports.SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
54
55 SepExports.SeNullSid = SeNullSid;
56 SepExports.SeWorldSid = SeWorldSid;
57 SepExports.SeLocalSid = SeLocalSid;
58 SepExports.SeCreatorOwnerSid = SeCreatorOwnerSid;
59 SepExports.SeCreatorGroupSid = SeCreatorGroupSid;
60 SepExports.SeNtAuthoritySid = SeNtAuthoritySid;
61 SepExports.SeDialupSid = SeDialupSid;
62 SepExports.SeNetworkSid = SeNetworkSid;
63 SepExports.SeBatchSid = SeBatchSid;
64 SepExports.SeInteractiveSid = SeInteractiveSid;
65 SepExports.SeLocalSystemSid = SeLocalSystemSid;
66 SepExports.SeAliasAdminsSid = SeAliasAdminsSid;
67 SepExports.SeAliasUsersSid = SeAliasUsersSid;
68 SepExports.SeAliasGuestsSid = SeAliasGuestsSid;
69 SepExports.SeAliasPowerUsersSid = SeAliasPowerUsersSid;
70 SepExports.SeAliasAccountOpsSid = SeAliasAccountOpsSid;
71 SepExports.SeAliasSystemOpsSid = SeAliasSystemOpsSid;
72 SepExports.SeAliasPrintOpsSid = SeAliasPrintOpsSid;
73 SepExports.SeAliasBackupOpsSid = SeAliasBackupOpsSid;
74 SepExports.SeAuthenticatedUsersSid = SeAuthenticatedUsersSid;
75 SepExports.SeRestrictedSid = SeRestrictedSid;
76 SepExports.SeAnonymousLogonSid = SeAnonymousLogonSid;
77
78 SepExports.SeUndockPrivilege = SeUndockPrivilege;
79 SepExports.SeSyncAgentPrivilege = SeSyncAgentPrivilege;
80 SepExports.SeEnableDelegationPrivilege = SeEnableDelegationPrivilege;
81
82 SeExports = &SepExports;
83 return TRUE;
84 }
85
86
87 BOOLEAN
88 NTAPI
89 INIT_FUNCTION
90 SepInitializationPhase0(VOID)
91 {
92 PAGED_CODE();
93
94 ExpInitLuid();
95 if (!SepInitSecurityIDs()) return FALSE;
96 if (!SepInitDACLs()) return FALSE;
97 if (!SepInitSDs()) return FALSE;
98 SepInitPrivileges();
99 if (!SepInitExports()) return FALSE;
100
101 /* Initialize the subject context lock */
102 ExInitializeResource(&SepSubjectContextLock);
103
104 /* Initialize token objects */
105 SepInitializeTokenImplementation();
106
107 /* Clear impersonation info for the idle thread */
108 PsGetCurrentThread()->ImpersonationInfo = NULL;
109 PspClearCrossThreadFlag(PsGetCurrentThread(),
110 CT_ACTIVE_IMPERSONATION_INFO_BIT);
111
112 /* Initialize the boot token */
113 ObInitializeFastReference(&PsGetCurrentProcess()->Token, NULL);
114 ObInitializeFastReference(&PsGetCurrentProcess()->Token,
115 SepCreateSystemProcessToken());
116 return TRUE;
117 }
118
119 BOOLEAN
120 NTAPI
121 INIT_FUNCTION
122 SepInitializationPhase1(VOID)
123 {
124 NTSTATUS Status;
125
126 PAGED_CODE();
127
128 /* Insert the system token into the tree */
129 Status = ObInsertObject((PVOID)(PsGetCurrentProcess()->Token.Value &
130 ~MAX_FAST_REFS),
131 NULL,
132 0,
133 0,
134 NULL,
135 NULL);
136 ASSERT(NT_SUCCESS(Status));
137
138 /* FIXME: TODO \\ Security directory */
139 return TRUE;
140 }
141
142 BOOLEAN
143 NTAPI
144 INIT_FUNCTION
145 SeInitSystem(VOID)
146 {
147 /* Check the initialization phase */
148 switch (ExpInitializationPhase)
149 {
150 case 0:
151
152 /* Do Phase 0 */
153 return SepInitializationPhase0();
154
155 case 1:
156
157 /* Do Phase 1 */
158 return SepInitializationPhase1();
159
160 default:
161
162 /* Don't know any other phase! Bugcheck! */
163 KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL,
164 0,
165 ExpInitializationPhase,
166 0,
167 0);
168 return FALSE;
169 }
170 }
171
172 BOOLEAN
173 NTAPI
174 INIT_FUNCTION
175 SeInitSRM(VOID)
176 {
177 OBJECT_ATTRIBUTES ObjectAttributes;
178 UNICODE_STRING Name;
179 HANDLE DirectoryHandle;
180 HANDLE EventHandle;
181 NTSTATUS Status;
182
183 /* Create '\Security' directory */
184 RtlInitUnicodeString(&Name,
185 L"\\Security");
186 InitializeObjectAttributes(&ObjectAttributes,
187 &Name,
188 OBJ_PERMANENT,
189 0,
190 NULL);
191 Status = ZwCreateDirectoryObject(&DirectoryHandle,
192 DIRECTORY_ALL_ACCESS,
193 &ObjectAttributes);
194 if (!NT_SUCCESS(Status))
195 {
196 DPRINT1("Failed to create 'Security' directory!\n");
197 return FALSE;
198 }
199
200 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
201 RtlInitUnicodeString(&Name,
202 L"\\LSA_AUTHENTICATION_INITALIZED");
203 InitializeObjectAttributes(&ObjectAttributes,
204 &Name,
205 OBJ_PERMANENT,
206 DirectoryHandle,
207 SePublicDefaultSd);
208 Status = ZwCreateEvent(&EventHandle,
209 EVENT_ALL_ACCESS,
210 &ObjectAttributes,
211 SynchronizationEvent,
212 FALSE);
213 if (!NT_SUCCESS(Status))
214 {
215 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
216 NtClose(DirectoryHandle);
217 return FALSE;
218 }
219
220 ZwClose(EventHandle);
221 ZwClose(DirectoryHandle);
222
223 /* FIXME: Create SRM port and listener thread */
224
225 return TRUE;
226 }
227
228 NTSTATUS
229 NTAPI
230 SeDefaultObjectMethod(IN PVOID Object,
231 IN SECURITY_OPERATION_CODE OperationType,
232 IN PSECURITY_INFORMATION SecurityInformation,
233 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
234 IN OUT PULONG ReturnLength OPTIONAL,
235 IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
236 IN POOL_TYPE PoolType,
237 IN PGENERIC_MAPPING GenericMapping)
238 {
239 PAGED_CODE();
240
241 /* Select the operation type */
242 switch (OperationType)
243 {
244 /* Setting a new descriptor */
245 case SetSecurityDescriptor:
246
247 /* Sanity check */
248 ASSERT((PoolType == PagedPool) || (PoolType == NonPagedPool));
249
250 /* Set the information */
251 return ObSetSecurityDescriptorInfo(Object,
252 SecurityInformation,
253 SecurityDescriptor,
254 OldSecurityDescriptor,
255 PoolType,
256 GenericMapping);
257
258 case QuerySecurityDescriptor:
259
260 /* Query the information */
261 return ObQuerySecurityDescriptorInfo(Object,
262 SecurityInformation,
263 SecurityDescriptor,
264 ReturnLength,
265 OldSecurityDescriptor);
266
267 case DeleteSecurityDescriptor:
268
269 /* De-assign it */
270 return ObDeassignSecurity(OldSecurityDescriptor);
271
272 case AssignSecurityDescriptor:
273
274 /* Assign it */
275 ObAssignObjectSecurityDescriptor(Object, SecurityDescriptor, PoolType);
276 return STATUS_SUCCESS;
277
278 default:
279
280 /* Bug check */
281 KeBugCheckEx(SECURITY_SYSTEM, 0, STATUS_INVALID_PARAMETER, 0, 0);
282 }
283
284 /* Should never reach here */
285 ASSERT(FALSE);
286 return STATUS_SUCCESS;
287 }
288
289 VOID
290 NTAPI
291 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
292 OUT PACCESS_MASK DesiredAccess)
293 {
294 *DesiredAccess = 0;
295
296 if (SecurityInformation & (OWNER_SECURITY_INFORMATION |
297 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION))
298 {
299 *DesiredAccess |= READ_CONTROL;
300 }
301
302 if (SecurityInformation & SACL_SECURITY_INFORMATION)
303 {
304 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
305 }
306 }
307
308 VOID
309 NTAPI
310 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
311 OUT PACCESS_MASK DesiredAccess)
312 {
313 *DesiredAccess = 0;
314
315 if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
316 {
317 *DesiredAccess |= WRITE_OWNER;
318 }
319
320 if (SecurityInformation & DACL_SECURITY_INFORMATION)
321 {
322 *DesiredAccess |= WRITE_DAC;
323 }
324
325 if (SecurityInformation & SACL_SECURITY_INFORMATION)
326 {
327 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
328 }
329 }
330
331
332 #define OLD_ACCESS_CHECK
333
334 BOOLEAN NTAPI
335 SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
336 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
337 IN ACCESS_MASK DesiredAccess,
338 IN ACCESS_MASK PreviouslyGrantedAccess,
339 OUT PPRIVILEGE_SET* Privileges,
340 IN PGENERIC_MAPPING GenericMapping,
341 IN KPROCESSOR_MODE AccessMode,
342 OUT PACCESS_MASK GrantedAccess,
343 OUT PNTSTATUS AccessStatus)
344 {
345 LUID_AND_ATTRIBUTES Privilege;
346 #ifdef OLD_ACCESS_CHECK
347 ACCESS_MASK CurrentAccess, AccessMask;
348 #endif
349 ACCESS_MASK RemainingAccess;
350 ACCESS_MASK TempAccess;
351 ACCESS_MASK TempGrantedAccess = 0;
352 ACCESS_MASK TempDeniedAccess = 0;
353 PACCESS_TOKEN Token;
354 ULONG i;
355 PACL Dacl;
356 BOOLEAN Present;
357 BOOLEAN Defaulted;
358 PACE CurrentAce;
359 PSID Sid;
360 NTSTATUS Status;
361 PAGED_CODE();
362
363 /* Check for no access desired */
364 if (!DesiredAccess)
365 {
366 /* Check if we had no previous access */
367 if (!PreviouslyGrantedAccess)
368 {
369 /* Then there's nothing to give */
370 *AccessStatus = STATUS_ACCESS_DENIED;
371 return FALSE;
372 }
373
374 /* Return the previous access only */
375 *GrantedAccess = PreviouslyGrantedAccess;
376 *AccessStatus = STATUS_SUCCESS;
377 *Privileges = NULL;
378 return TRUE;
379 }
380
381 /* Map given accesses */
382 RtlMapGenericMask(&DesiredAccess, GenericMapping);
383 if (PreviouslyGrantedAccess)
384 RtlMapGenericMask(&PreviouslyGrantedAccess, GenericMapping);
385
386 #ifdef OLD_ACCESS_CHECK
387 CurrentAccess = PreviouslyGrantedAccess;
388 #endif
389 /* Initialize remaining access rights */
390 RemainingAccess = DesiredAccess;
391
392 Token = SubjectSecurityContext->ClientToken ?
393 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
394
395 /* Check for system security access */
396 if (RemainingAccess & ACCESS_SYSTEM_SECURITY)
397 {
398 Privilege.Luid = SeSecurityPrivilege;
399 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
400
401 /* Fail if we do not the SeSecurityPrivilege */
402 if (!SepPrivilegeCheck(Token,
403 &Privilege,
404 1,
405 PRIVILEGE_SET_ALL_NECESSARY,
406 AccessMode))
407 {
408 *AccessStatus = STATUS_PRIVILEGE_NOT_HELD;
409 return FALSE;
410 }
411
412 /* Adjust access rights */
413 RemainingAccess &= ~ACCESS_SYSTEM_SECURITY;
414 PreviouslyGrantedAccess |= ACCESS_SYSTEM_SECURITY;
415
416 /* Succeed if there are no more rights to grant */
417 if (RemainingAccess == 0)
418 {
419 *GrantedAccess = PreviouslyGrantedAccess;
420 *AccessStatus = STATUS_SUCCESS;
421 return TRUE;
422 }
423 }
424
425 /* Get the DACL */
426 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
427 &Present,
428 &Dacl,
429 &Defaulted);
430 if (!NT_SUCCESS(Status))
431 {
432 *AccessStatus = Status;
433 return FALSE;
434 }
435
436 /* RULE 1: Grant desired access if the object is unprotected */
437 if (Present == FALSE || Dacl == NULL)
438 {
439 if (DesiredAccess & MAXIMUM_ALLOWED)
440 {
441 *GrantedAccess = GenericMapping->GenericAll;
442 *GrantedAccess |= (DesiredAccess & ~MAXIMUM_ALLOWED);
443 }
444 else
445 {
446 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
447 }
448
449 *AccessStatus = STATUS_SUCCESS;
450 return TRUE;
451 }
452
453 #ifdef OLD_ACCESS_CHECK
454 CurrentAccess = PreviouslyGrantedAccess;
455 #endif
456
457 /* RULE 2: Check token for 'take ownership' privilege */
458 if (DesiredAccess & WRITE_OWNER)
459 {
460 Privilege.Luid = SeTakeOwnershipPrivilege;
461 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
462
463 if (SepPrivilegeCheck(Token,
464 &Privilege,
465 1,
466 PRIVILEGE_SET_ALL_NECESSARY,
467 AccessMode))
468 {
469 /* Adjust access rights */
470 RemainingAccess &= ~WRITE_OWNER;
471 PreviouslyGrantedAccess |= WRITE_OWNER;
472 #ifdef OLD_ACCESS_CHECK
473 CurrentAccess |= WRITE_OWNER;
474 #endif
475
476 /* Succeed if there are no more rights to grant */
477 if (RemainingAccess == 0)
478 {
479 *GrantedAccess = PreviouslyGrantedAccess;
480 *AccessStatus = STATUS_SUCCESS;
481 return TRUE;
482 }
483 }
484 }
485
486 /* Deny access if the DACL is empty */
487 if (Dacl->AceCount == 0)
488 {
489 if (RemainingAccess == MAXIMUM_ALLOWED && PreviouslyGrantedAccess != 0)
490 {
491 *GrantedAccess = PreviouslyGrantedAccess;
492 *AccessStatus = STATUS_SUCCESS;
493 return TRUE;
494 }
495 else
496 {
497 *GrantedAccess = 0;
498 *AccessStatus = STATUS_ACCESS_DENIED;
499 return FALSE;
500 }
501 }
502
503 /* Fail if DACL is absent */
504 if (Present == FALSE)
505 {
506 *GrantedAccess = 0;
507 *AccessStatus = STATUS_ACCESS_DENIED;
508 return FALSE;
509 }
510
511 /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */
512 if (DesiredAccess & MAXIMUM_ALLOWED)
513 {
514 CurrentAce = (PACE)(Dacl + 1);
515 for (i = 0; i < Dacl->AceCount; i++)
516 {
517 if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
518 {
519 Sid = (PSID)(CurrentAce + 1);
520 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
521 {
522 if (SepSidInToken(Token, Sid))
523 {
524 /* Map access rights from the ACE */
525 TempAccess = CurrentAce->AccessMask;
526 RtlMapGenericMask(&TempAccess, GenericMapping);
527
528 /* Deny access rights that have not been granted yet */
529 TempDeniedAccess |= (TempAccess & ~TempGrantedAccess);
530 }
531 }
532 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
533 {
534 if (SepSidInToken(Token, Sid))
535 {
536 /* Map access rights from the ACE */
537 TempAccess = CurrentAce->AccessMask;
538 RtlMapGenericMask(&TempAccess, GenericMapping);
539
540 /* Grant access rights that have not been denied yet */
541 TempGrantedAccess |= (TempAccess & ~TempDeniedAccess);
542 }
543 }
544 else
545 {
546 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
547 }
548 }
549
550 /* Get the next ACE */
551 CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
552 }
553
554 /* Fail if some rights have not been granted */
555 RemainingAccess &= ~(MAXIMUM_ALLOWED | TempGrantedAccess);
556 if (RemainingAccess != 0)
557 {
558 *GrantedAccess = 0;
559 *AccessStatus = STATUS_ACCESS_DENIED;
560 return FALSE;
561 }
562
563 /* Set granted access right and access status */
564 *GrantedAccess = TempGrantedAccess | PreviouslyGrantedAccess;
565 if (*GrantedAccess != 0)
566 {
567 *AccessStatus = STATUS_SUCCESS;
568 return TRUE;
569 }
570 else
571 {
572 *AccessStatus = STATUS_ACCESS_DENIED;
573 return FALSE;
574 }
575 }
576
577 /* RULE 4: Grant rights according to the DACL */
578 CurrentAce = (PACE)(Dacl + 1);
579 for (i = 0; i < Dacl->AceCount; i++)
580 {
581 if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
582 {
583 Sid = (PSID)(CurrentAce + 1);
584 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
585 {
586 if (SepSidInToken(Token, Sid))
587 {
588 #ifdef OLD_ACCESS_CHECK
589 *GrantedAccess = 0;
590 *AccessStatus = STATUS_ACCESS_DENIED;
591 return FALSE;
592 #else
593 /* Map access rights from the ACE */
594 TempAccess = CurrentAce->AccessMask;
595 RtlMapGenericMask(&TempAccess, GenericMapping);
596
597 /* Leave if a remaining right must be denied */
598 if (RemainingAccess & TempAccess)
599 break;
600 #endif
601 }
602 }
603 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
604 {
605 if (SepSidInToken(Token, Sid))
606 {
607 #ifdef OLD_ACCESS_CHECK
608 AccessMask = CurrentAce->AccessMask;
609 RtlMapGenericMask(&AccessMask, GenericMapping);
610 CurrentAccess |= AccessMask;
611 #else
612 /* Map access rights from the ACE */
613 TempAccess = CurrentAce->AccessMask;
614 RtlMapGenericMask(&TempAccess, GenericMapping);
615
616 /* Remove granted rights */
617 RemainingAccess &= ~TempAccess;
618 #endif
619 }
620 }
621 else
622 {
623 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
624 }
625 }
626
627 /* Get the next ACE */
628 CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
629 }
630
631 #ifdef OLD_ACCESS_CHECK
632 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
633 CurrentAccess, DesiredAccess);
634
635 *GrantedAccess = CurrentAccess & DesiredAccess;
636
637 if ((*GrantedAccess & ~VALID_INHERIT_FLAGS) ==
638 (DesiredAccess & ~VALID_INHERIT_FLAGS))
639 {
640 *AccessStatus = STATUS_SUCCESS;
641 return TRUE;
642 }
643 else
644 {
645 DPRINT1("HACK: Should deny access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p).\n",
646 *GrantedAccess, DesiredAccess, GenericMapping);
647 //*AccessStatus = STATUS_ACCESS_DENIED;
648 //return FALSE;
649 *GrantedAccess = DesiredAccess;
650 *AccessStatus = STATUS_SUCCESS;
651 return TRUE;
652 }
653 #else
654 DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n",
655 DesiredAccess, PreviouslyGrantedAccess, RemainingAccess);
656
657 /* Fail if some rights have not been granted */
658 if (RemainingAccess != 0)
659 {
660 *GrantedAccess = 0;
661 *AccessStatus = STATUS_ACCESS_DENIED;
662 return FALSE;
663 }
664
665 /* Set granted access rights */
666 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
667
668 DPRINT("GrantedAccess %08lx\n", *GrantedAccess);
669
670 /* Fail if no rights have been granted */
671 if (*GrantedAccess == 0)
672 {
673 *AccessStatus = STATUS_ACCESS_DENIED;
674 return FALSE;
675 }
676
677 *AccessStatus = STATUS_SUCCESS;
678 return TRUE;
679 #endif
680 }
681
682 static PSID
683 SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
684 {
685 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
686 PSID Owner;
687
688 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
689 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
690 (ULONG_PTR)SecurityDescriptor);
691 else
692 Owner = (PSID)SecurityDescriptor->Owner;
693
694 return Owner;
695 }
696
697 static PSID
698 SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
699 {
700 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
701 PSID Group;
702
703 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
704 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
705 (ULONG_PTR)SecurityDescriptor);
706 else
707 Group = (PSID)SecurityDescriptor->Group;
708
709 return Group;
710 }
711
712
713 /* PUBLIC FUNCTIONS ***********************************************************/
714
715 /*
716 * @implemented
717 */
718 BOOLEAN
719 NTAPI
720 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
721 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
722 IN BOOLEAN SubjectContextLocked,
723 IN ACCESS_MASK DesiredAccess,
724 IN ACCESS_MASK PreviouslyGrantedAccess,
725 OUT PPRIVILEGE_SET* Privileges,
726 IN PGENERIC_MAPPING GenericMapping,
727 IN KPROCESSOR_MODE AccessMode,
728 OUT PACCESS_MASK GrantedAccess,
729 OUT PNTSTATUS AccessStatus)
730 {
731 BOOLEAN ret;
732
733 PAGED_CODE();
734
735 /* Check if this is kernel mode */
736 if (AccessMode == KernelMode)
737 {
738 /* Check if kernel wants everything */
739 if (DesiredAccess & MAXIMUM_ALLOWED)
740 {
741 /* Give it */
742 *GrantedAccess = GenericMapping->GenericAll;
743 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
744 *GrantedAccess |= PreviouslyGrantedAccess;
745 }
746 else
747 {
748 /* Give the desired and previous access */
749 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
750 }
751
752 /* Success */
753 *AccessStatus = STATUS_SUCCESS;
754 return TRUE;
755 }
756
757 /* Check if we didn't get an SD */
758 if (!SecurityDescriptor)
759 {
760 /* Automatic failure */
761 *AccessStatus = STATUS_ACCESS_DENIED;
762 return FALSE;
763 }
764
765 /* Check for invalid impersonation */
766 if ((SubjectSecurityContext->ClientToken) &&
767 (SubjectSecurityContext->ImpersonationLevel < SecurityImpersonation))
768 {
769 *AccessStatus = STATUS_BAD_IMPERSONATION_LEVEL;
770 return FALSE;
771 }
772
773 /* Acquire the lock if needed */
774 if (!SubjectContextLocked)
775 SeLockSubjectContext(SubjectSecurityContext);
776
777 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
778 if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
779 {
780 PACCESS_TOKEN Token = SubjectSecurityContext->ClientToken ?
781 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
782
783 if (SepTokenIsOwner(Token,
784 SecurityDescriptor,
785 FALSE))
786 {
787 if (DesiredAccess & MAXIMUM_ALLOWED)
788 PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
789 else
790 PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
791
792 DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
793 }
794 }
795
796 if (DesiredAccess == 0)
797 {
798 *GrantedAccess = PreviouslyGrantedAccess;
799 *AccessStatus = STATUS_SUCCESS;
800 ret = TRUE;
801 }
802 else
803 {
804 /* Call the internal function */
805 ret = SepAccessCheck(SecurityDescriptor,
806 SubjectSecurityContext,
807 DesiredAccess,
808 PreviouslyGrantedAccess,
809 Privileges,
810 GenericMapping,
811 AccessMode,
812 GrantedAccess,
813 AccessStatus);
814 }
815
816 /* Release the lock if needed */
817 if (!SubjectContextLocked)
818 SeUnlockSubjectContext(SubjectSecurityContext);
819
820 return ret;
821 }
822
823 /* SYSTEM CALLS ***************************************************************/
824
825 /*
826 * @implemented
827 */
828 NTSTATUS
829 NTAPI
830 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
831 IN HANDLE TokenHandle,
832 IN ACCESS_MASK DesiredAccess,
833 IN PGENERIC_MAPPING GenericMapping,
834 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
835 IN OUT PULONG PrivilegeSetLength,
836 OUT PACCESS_MASK GrantedAccess,
837 OUT PNTSTATUS AccessStatus)
838 {
839 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
840 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
841 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
842 ACCESS_MASK PreviouslyGrantedAccess = 0;
843 PTOKEN Token;
844 NTSTATUS Status;
845 PAGED_CODE();
846
847 /* Check if this is kernel mode */
848 if (PreviousMode == KernelMode)
849 {
850 /* Check if kernel wants everything */
851 if (DesiredAccess & MAXIMUM_ALLOWED)
852 {
853 /* Give it */
854 *GrantedAccess = GenericMapping->GenericAll;
855 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
856 }
857 else
858 {
859 /* Just give the desired access */
860 *GrantedAccess = DesiredAccess;
861 }
862
863 /* Success */
864 *AccessStatus = STATUS_SUCCESS;
865 return STATUS_SUCCESS;
866 }
867
868 /* Protect probe in SEH */
869 _SEH2_TRY
870 {
871 /* Probe all pointers */
872 ProbeForRead(GenericMapping, sizeof(GENERIC_MAPPING), sizeof(ULONG));
873 ProbeForRead(PrivilegeSetLength, sizeof(ULONG), sizeof(ULONG));
874 ProbeForWrite(PrivilegeSet, *PrivilegeSetLength, sizeof(ULONG));
875 ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
876 ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
877 }
878 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
879 {
880 /* Return the exception code */
881 _SEH2_YIELD(return _SEH2_GetExceptionCode());
882 }
883 _SEH2_END;
884
885 /* Check for unmapped access rights */
886 if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
887 return STATUS_GENERIC_NOT_MAPPED;
888
889 /* Reference the token */
890 Status = ObReferenceObjectByHandle(TokenHandle,
891 TOKEN_QUERY,
892 SeTokenObjectType,
893 PreviousMode,
894 (PVOID*)&Token,
895 NULL);
896 if (!NT_SUCCESS(Status))
897 {
898 DPRINT("Failed to reference token (Status %lx)\n", Status);
899 return Status;
900 }
901
902 /* Check token type */
903 if (Token->TokenType != TokenImpersonation)
904 {
905 DPRINT("No impersonation token\n");
906 ObDereferenceObject(Token);
907 return STATUS_NO_IMPERSONATION_TOKEN;
908 }
909
910 /* Check the impersonation level */
911 if (Token->ImpersonationLevel < SecurityIdentification)
912 {
913 DPRINT("Impersonation level < SecurityIdentification\n");
914 ObDereferenceObject(Token);
915 return STATUS_BAD_IMPERSONATION_LEVEL;
916 }
917
918 /* Capture the security descriptor */
919 Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
920 PreviousMode,
921 PagedPool,
922 FALSE,
923 &CapturedSecurityDescriptor);
924 if (!NT_SUCCESS(Status))
925 {
926 DPRINT("Failed to capture the Security Descriptor\n");
927 ObDereferenceObject(Token);
928 return Status;
929 }
930
931 /* Check the captured security descriptor */
932 if (CapturedSecurityDescriptor == NULL)
933 {
934 DPRINT("Security Descriptor is NULL\n");
935 ObDereferenceObject(Token);
936 return STATUS_INVALID_SECURITY_DESCR;
937 }
938
939 /* Check security descriptor for valid owner and group */
940 if (SepGetSDOwner(SecurityDescriptor) == NULL || // FIXME: use CapturedSecurityDescriptor
941 SepGetSDGroup(SecurityDescriptor) == NULL) // FIXME: use CapturedSecurityDescriptor
942 {
943 DPRINT("Security Descriptor does not have a valid group or owner\n");
944 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
945 PreviousMode,
946 FALSE);
947 ObDereferenceObject(Token);
948 return STATUS_INVALID_SECURITY_DESCR;
949 }
950
951 /* Set up the subject context, and lock it */
952 SeCaptureSubjectContext(&SubjectSecurityContext);
953
954 /* Lock the token */
955 SepAcquireTokenLockShared(Token);
956
957 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
958 if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
959 {
960 if (SepTokenIsOwner(Token, SecurityDescriptor, FALSE)) // FIXME: use CapturedSecurityDescriptor
961 {
962 if (DesiredAccess & MAXIMUM_ALLOWED)
963 PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
964 else
965 PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
966
967 DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
968 }
969 }
970
971 if (DesiredAccess == 0)
972 {
973 *GrantedAccess = PreviouslyGrantedAccess;
974 *AccessStatus = STATUS_SUCCESS;
975 }
976 else
977 {
978 /* Now perform the access check */
979 SepAccessCheck(SecurityDescriptor, // FIXME: use CapturedSecurityDescriptor
980 &SubjectSecurityContext,
981 DesiredAccess,
982 PreviouslyGrantedAccess,
983 &PrivilegeSet, //FIXME
984 GenericMapping,
985 PreviousMode,
986 GrantedAccess,
987 AccessStatus);
988 }
989
990 /* Release subject context and unlock the token */
991 SeReleaseSubjectContext(&SubjectSecurityContext);
992 SepReleaseTokenLock(Token);
993
994 /* Release the captured security descriptor */
995 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
996 PreviousMode,
997 FALSE);
998
999 /* Dereference the token */
1000 ObDereferenceObject(Token);
1001
1002 /* Check succeeded */
1003 return STATUS_SUCCESS;
1004 }
1005
1006
1007 NTSTATUS
1008 NTAPI
1009 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1010 IN PSID PrincipalSelfSid,
1011 IN HANDLE ClientToken,
1012 IN ACCESS_MASK DesiredAccess,
1013 IN POBJECT_TYPE_LIST ObjectTypeList,
1014 IN ULONG ObjectTypeLength,
1015 IN PGENERIC_MAPPING GenericMapping,
1016 IN PPRIVILEGE_SET PrivilegeSet,
1017 IN OUT PULONG PrivilegeSetLength,
1018 OUT PACCESS_MASK GrantedAccess,
1019 OUT PNTSTATUS AccessStatus)
1020 {
1021 UNIMPLEMENTED;
1022 return STATUS_NOT_IMPLEMENTED;
1023 }
1024
1025 NTSTATUS
1026 NTAPI
1027 NtAccessCheckByTypeAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
1028 IN HANDLE HandleId,
1029 IN PUNICODE_STRING ObjectTypeName,
1030 IN PUNICODE_STRING ObjectName,
1031 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1032 IN PSID PrincipalSelfSid,
1033 IN ACCESS_MASK DesiredAccess,
1034 IN AUDIT_EVENT_TYPE AuditType,
1035 IN ULONG Flags,
1036 IN POBJECT_TYPE_LIST ObjectTypeList,
1037 IN ULONG ObjectTypeLength,
1038 IN PGENERIC_MAPPING GenericMapping,
1039 IN BOOLEAN ObjectCreation,
1040 OUT PACCESS_MASK GrantedAccess,
1041 OUT PNTSTATUS AccessStatus,
1042 OUT PBOOLEAN GenerateOnClose)
1043 {
1044 UNIMPLEMENTED;
1045 return STATUS_NOT_IMPLEMENTED;
1046 }
1047
1048 NTSTATUS
1049 NTAPI
1050 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1051 IN PSID PrincipalSelfSid,
1052 IN HANDLE ClientToken,
1053 IN ACCESS_MASK DesiredAccess,
1054 IN POBJECT_TYPE_LIST ObjectTypeList,
1055 IN ULONG ObjectTypeLength,
1056 IN PGENERIC_MAPPING GenericMapping,
1057 IN PPRIVILEGE_SET PrivilegeSet,
1058 IN OUT PULONG PrivilegeSetLength,
1059 OUT PACCESS_MASK GrantedAccess,
1060 OUT PNTSTATUS AccessStatus)
1061 {
1062 UNIMPLEMENTED;
1063 return STATUS_NOT_IMPLEMENTED;
1064 }
1065
1066 NTSTATUS
1067 NTAPI
1068 NtAccessCheckByTypeResultListAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
1069 IN HANDLE HandleId,
1070 IN PUNICODE_STRING ObjectTypeName,
1071 IN PUNICODE_STRING ObjectName,
1072 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1073 IN PSID PrincipalSelfSid,
1074 IN ACCESS_MASK DesiredAccess,
1075 IN AUDIT_EVENT_TYPE AuditType,
1076 IN ULONG Flags,
1077 IN POBJECT_TYPE_LIST ObjectTypeList,
1078 IN ULONG ObjectTypeLength,
1079 IN PGENERIC_MAPPING GenericMapping,
1080 IN BOOLEAN ObjectCreation,
1081 OUT PACCESS_MASK GrantedAccess,
1082 OUT PNTSTATUS AccessStatus,
1083 OUT PBOOLEAN GenerateOnClose)
1084 {
1085 UNIMPLEMENTED;
1086 return STATUS_NOT_IMPLEMENTED;
1087 }
1088
1089 NTSTATUS
1090 NTAPI
1091 NtAccessCheckByTypeResultListAndAuditAlarmByHandle(IN PUNICODE_STRING SubsystemName,
1092 IN HANDLE HandleId,
1093 IN HANDLE ClientToken,
1094 IN PUNICODE_STRING ObjectTypeName,
1095 IN PUNICODE_STRING ObjectName,
1096 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1097 IN PSID PrincipalSelfSid,
1098 IN ACCESS_MASK DesiredAccess,
1099 IN AUDIT_EVENT_TYPE AuditType,
1100 IN ULONG Flags,
1101 IN POBJECT_TYPE_LIST ObjectTypeList,
1102 IN ULONG ObjectTypeLength,
1103 IN PGENERIC_MAPPING GenericMapping,
1104 IN BOOLEAN ObjectCreation,
1105 OUT PACCESS_MASK GrantedAccess,
1106 OUT PNTSTATUS AccessStatus,
1107 OUT PBOOLEAN GenerateOnClose)
1108 {
1109 UNIMPLEMENTED;
1110 return STATUS_NOT_IMPLEMENTED;
1111 }
1112
1113 /* EOF */