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