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