- If SeCaptureSubjectContextEx is called without a process, at least NULL-initialize...
[reactos.git] / reactos / ntoskrnl / se / semgr.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/semgr.c
6 * PURPOSE: Security manager
7 *
8 * PROGRAMMERS: No programmer listed.
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS ******************************************************************/
18
19 PSE_EXPORTS SeExports = NULL;
20 SE_EXPORTS SepExports;
21
22 static ERESOURCE SepSubjectContextLock;
23
24
25 /* PROTOTYPES ***************************************************************/
26
27 static BOOLEAN SepInitExports(VOID);
28
29 #if defined (ALLOC_PRAGMA)
30 #pragma alloc_text(INIT, SeInit1)
31 #pragma alloc_text(INIT, SeInit2)
32 #pragma alloc_text(INIT, SepInitExports)
33 #endif
34
35 /* FUNCTIONS ****************************************************************/
36
37 BOOLEAN
38 INIT_FUNCTION
39 NTAPI
40 SeInit1(VOID)
41 {
42 SepInitLuid();
43
44 if (!SepInitSecurityIDs())
45 return FALSE;
46
47 if (!SepInitDACLs())
48 return FALSE;
49
50 if (!SepInitSDs())
51 return FALSE;
52
53 SepInitPrivileges();
54
55 if (!SepInitExports())
56 return FALSE;
57
58 /* Initialize the subject context lock */
59 ExInitializeResource(&SepSubjectContextLock);
60
61 return TRUE;
62 }
63
64
65 BOOLEAN
66 INIT_FUNCTION
67 NTAPI
68 SeInit2(VOID)
69 {
70 SepInitializeTokenImplementation();
71
72 return TRUE;
73 }
74
75
76 BOOLEAN
77 NTAPI
78 SeInitSRM(VOID)
79 {
80 OBJECT_ATTRIBUTES ObjectAttributes;
81 UNICODE_STRING Name;
82 HANDLE DirectoryHandle;
83 HANDLE EventHandle;
84 NTSTATUS Status;
85
86 /* Create '\Security' directory */
87 RtlInitUnicodeString(&Name,
88 L"\\Security");
89 InitializeObjectAttributes(&ObjectAttributes,
90 &Name,
91 OBJ_PERMANENT,
92 0,
93 NULL);
94 Status = ZwCreateDirectoryObject(&DirectoryHandle,
95 DIRECTORY_ALL_ACCESS,
96 &ObjectAttributes);
97 if (!NT_SUCCESS(Status))
98 {
99 DPRINT1("Failed to create 'Security' directory!\n");
100 return FALSE;
101 }
102
103 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
104 RtlInitUnicodeString(&Name,
105 L"\\LSA_AUTHENTICATION_INITALIZED");
106 InitializeObjectAttributes(&ObjectAttributes,
107 &Name,
108 OBJ_PERMANENT,
109 DirectoryHandle,
110 SePublicDefaultSd);
111 Status = ZwCreateEvent(&EventHandle,
112 EVENT_ALL_ACCESS,
113 &ObjectAttributes,
114 SynchronizationEvent,
115 FALSE);
116 if (!NT_SUCCESS(Status))
117 {
118 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
119 NtClose(DirectoryHandle);
120 return FALSE;
121 }
122
123 ZwClose(EventHandle);
124 ZwClose(DirectoryHandle);
125
126 /* FIXME: Create SRM port and listener thread */
127
128 return TRUE;
129 }
130
131
132 static BOOLEAN INIT_FUNCTION
133 SepInitExports(VOID)
134 {
135 SepExports.SeCreateTokenPrivilege = SeCreateTokenPrivilege;
136 SepExports.SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
137 SepExports.SeLockMemoryPrivilege = SeLockMemoryPrivilege;
138 SepExports.SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
139 SepExports.SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
140 SepExports.SeTcbPrivilege = SeTcbPrivilege;
141 SepExports.SeSecurityPrivilege = SeSecurityPrivilege;
142 SepExports.SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
143 SepExports.SeLoadDriverPrivilege = SeLoadDriverPrivilege;
144 SepExports.SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
145 SepExports.SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
146 SepExports.SeSystemProfilePrivilege = SeSystemProfilePrivilege;
147 SepExports.SeSystemtimePrivilege = SeSystemtimePrivilege;
148 SepExports.SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
149 SepExports.SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
150 SepExports.SeBackupPrivilege = SeBackupPrivilege;
151 SepExports.SeRestorePrivilege = SeRestorePrivilege;
152 SepExports.SeShutdownPrivilege = SeShutdownPrivilege;
153 SepExports.SeDebugPrivilege = SeDebugPrivilege;
154 SepExports.SeAuditPrivilege = SeAuditPrivilege;
155 SepExports.SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
156 SepExports.SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
157 SepExports.SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
158
159 SepExports.SeNullSid = SeNullSid;
160 SepExports.SeWorldSid = SeWorldSid;
161 SepExports.SeLocalSid = SeLocalSid;
162 SepExports.SeCreatorOwnerSid = SeCreatorOwnerSid;
163 SepExports.SeCreatorGroupSid = SeCreatorGroupSid;
164 SepExports.SeNtAuthoritySid = SeNtAuthoritySid;
165 SepExports.SeDialupSid = SeDialupSid;
166 SepExports.SeNetworkSid = SeNetworkSid;
167 SepExports.SeBatchSid = SeBatchSid;
168 SepExports.SeInteractiveSid = SeInteractiveSid;
169 SepExports.SeLocalSystemSid = SeLocalSystemSid;
170 SepExports.SeAliasAdminsSid = SeAliasAdminsSid;
171 SepExports.SeAliasUsersSid = SeAliasUsersSid;
172 SepExports.SeAliasGuestsSid = SeAliasGuestsSid;
173 SepExports.SeAliasPowerUsersSid = SeAliasPowerUsersSid;
174 SepExports.SeAliasAccountOpsSid = SeAliasAccountOpsSid;
175 SepExports.SeAliasSystemOpsSid = SeAliasSystemOpsSid;
176 SepExports.SeAliasPrintOpsSid = SeAliasPrintOpsSid;
177 SepExports.SeAliasBackupOpsSid = SeAliasBackupOpsSid;
178 SepExports.SeAuthenticatedUsersSid = SeAuthenticatedUsersSid;
179 SepExports.SeRestrictedSid = SeRestrictedSid;
180 SepExports.SeAnonymousLogonSid = SeAnonymousLogonSid;
181
182 SepExports.SeUndockPrivilege = SeUndockPrivilege;
183 SepExports.SeSyncAgentPrivilege = SeSyncAgentPrivilege;
184 SepExports.SeEnableDelegationPrivilege = SeEnableDelegationPrivilege;
185
186 SeExports = &SepExports;
187 return TRUE;
188 }
189
190
191 VOID SepReferenceLogonSession(PLUID AuthenticationId)
192 {
193 UNIMPLEMENTED;
194 }
195
196 VOID SepDeReferenceLogonSession(PLUID AuthenticationId)
197 {
198 UNIMPLEMENTED;
199 }
200
201 NTSTATUS
202 STDCALL
203 SeDefaultObjectMethod(PVOID Object,
204 SECURITY_OPERATION_CODE OperationType,
205 SECURITY_INFORMATION SecurityInformation,
206 PSECURITY_DESCRIPTOR _SecurityDescriptor,
207 PULONG ReturnLength,
208 PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
209 POOL_TYPE PoolType,
210 PGENERIC_MAPPING GenericMapping)
211 {
212 PISECURITY_DESCRIPTOR ObjectSd;
213 PISECURITY_DESCRIPTOR NewSd;
214 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
215 POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Object);
216 PSID Owner = 0;
217 PSID Group = 0;
218 PACL Dacl = 0;
219 PACL Sacl = 0;
220 ULONG OwnerLength = 0;
221 ULONG GroupLength = 0;
222 ULONG DaclLength = 0;
223 ULONG SaclLength = 0;
224 ULONG Control = 0;
225 ULONG_PTR Current;
226 NTSTATUS Status;
227
228 if (OperationType == SetSecurityDescriptor)
229 {
230 ObjectSd = Header->SecurityDescriptor;
231
232 /* Get owner and owner size */
233 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
234 {
235 if (SecurityDescriptor->Owner != NULL)
236 {
237 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
238 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
239 (ULONG_PTR)SecurityDescriptor);
240 else
241 Owner = (PSID)SecurityDescriptor->Owner;
242 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
243 }
244 Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
245 }
246 else
247 {
248 if (ObjectSd->Owner != NULL)
249 {
250 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
251 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
252 }
253 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
254 }
255
256 /* Get group and group size */
257 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
258 {
259 if (SecurityDescriptor->Group != NULL)
260 {
261 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
262 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
263 (ULONG_PTR)SecurityDescriptor);
264 else
265 Group = (PSID)SecurityDescriptor->Group;
266 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
267 }
268 Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
269 }
270 else
271 {
272 if (ObjectSd->Group != NULL)
273 {
274 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
275 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
276 }
277 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
278 }
279
280 /* Get DACL and DACL size */
281 if (SecurityInformation & DACL_SECURITY_INFORMATION)
282 {
283 if ((SecurityDescriptor->Control & SE_DACL_PRESENT) &&
284 (SecurityDescriptor->Dacl != NULL))
285 {
286 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
287 Dacl = (PACL)((ULONG_PTR)SecurityDescriptor->Dacl +
288 (ULONG_PTR)SecurityDescriptor);
289 else
290 Dacl = (PACL)SecurityDescriptor->Dacl;
291
292 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
293 }
294 Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
295 }
296 else
297 {
298 if ((ObjectSd->Control & SE_DACL_PRESENT) &&
299 (ObjectSd->Dacl != NULL))
300 {
301 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
302 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
303 }
304 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
305 }
306
307 /* Get SACL and SACL size */
308 if (SecurityInformation & SACL_SECURITY_INFORMATION)
309 {
310 if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
311 (SecurityDescriptor->Sacl != NULL))
312 {
313 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
314 Sacl = (PACL)((ULONG_PTR)SecurityDescriptor->Sacl +
315 (ULONG_PTR)SecurityDescriptor);
316 else
317 Sacl = (PACL)SecurityDescriptor->Sacl;
318 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
319 }
320 Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
321 }
322 else
323 {
324 if ((ObjectSd->Control & SE_SACL_PRESENT) &&
325 (ObjectSd->Sacl != NULL))
326 {
327 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
328 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
329 }
330 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
331 }
332
333 NewSd = ExAllocatePool(NonPagedPool,
334 sizeof(SECURITY_DESCRIPTOR) + OwnerLength + GroupLength +
335 DaclLength + SaclLength);
336 if (NewSd == NULL)
337 {
338 ObDereferenceObject(Object);
339 return STATUS_INSUFFICIENT_RESOURCES;
340 }
341
342 RtlCreateSecurityDescriptor(NewSd,
343 SECURITY_DESCRIPTOR_REVISION1);
344 /* We always build a self-relative descriptor */
345 NewSd->Control = Control | SE_SELF_RELATIVE;
346
347 Current = (ULONG_PTR)NewSd + sizeof(SECURITY_DESCRIPTOR);
348
349 if (OwnerLength != 0)
350 {
351 RtlCopyMemory((PVOID)Current,
352 Owner,
353 OwnerLength);
354 NewSd->Owner = (PSID)(Current - (ULONG_PTR)NewSd);
355 Current += OwnerLength;
356 }
357
358 if (GroupLength != 0)
359 {
360 RtlCopyMemory((PVOID)Current,
361 Group,
362 GroupLength);
363 NewSd->Group = (PSID)(Current - (ULONG_PTR)NewSd);
364 Current += GroupLength;
365 }
366
367 if (DaclLength != 0)
368 {
369 RtlCopyMemory((PVOID)Current,
370 Dacl,
371 DaclLength);
372 NewSd->Dacl = (PACL)(Current - (ULONG_PTR)NewSd);
373 Current += DaclLength;
374 }
375
376 if (SaclLength != 0)
377 {
378 RtlCopyMemory((PVOID)Current,
379 Sacl,
380 SaclLength);
381 NewSd->Sacl = (PACL)(Current - (ULONG_PTR)NewSd);
382 Current += SaclLength;
383 }
384
385 /* Add the new SD */
386 Status = ObpAddSecurityDescriptor(NewSd,
387 &Header->SecurityDescriptor);
388 if (NT_SUCCESS(Status))
389 {
390 /* Remove the old security descriptor */
391 ObpRemoveSecurityDescriptor(ObjectSd);
392 }
393 else
394 {
395 /* Restore the old security descriptor */
396 Header->SecurityDescriptor = ObjectSd;
397 }
398
399 ExFreePool(NewSd);
400 }
401 else if (OperationType == QuerySecurityDescriptor)
402 {
403 Status = SeQuerySecurityDescriptorInfo(&SecurityInformation,
404 SecurityDescriptor,
405 ReturnLength,
406 &Header->SecurityDescriptor);
407 }
408 else if (OperationType == AssignSecurityDescriptor)
409 {
410 /* Assign the security descriptor to the object header */
411 Status = ObpAddSecurityDescriptor(SecurityDescriptor,
412 &Header->SecurityDescriptor);
413 }
414
415
416 return STATUS_SUCCESS;
417 }
418
419 VOID
420 NTAPI
421 SeCaptureSubjectContextEx(IN PETHREAD Thread,
422 IN PEPROCESS Process,
423 OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
424 {
425 BOOLEAN CopyOnOpen, EffectiveOnly;
426 PAGED_CODE();
427
428 /* ROS HACK */
429 if (!Process)
430 {
431 SubjectContext->PrimaryToken = NULL;
432 SubjectContext->ProcessAuditId = 0;
433 SubjectContext->ClientToken = NULL;
434 return;
435 }
436
437 /* Save the unique ID */
438 SubjectContext->ProcessAuditId = Process->UniqueProcessId;
439
440 /* Check if we have a thread */
441 if (!Thread)
442 {
443 /* We don't, so no token */
444 SubjectContext->ClientToken = NULL;
445 }
446 else
447 {
448 /* Get the impersonation token */
449 SubjectContext->ClientToken =
450 PsReferenceImpersonationToken(Thread,
451 &CopyOnOpen,
452 &EffectiveOnly,
453 &SubjectContext->ImpersonationLevel);
454 }
455
456 /* Get the primary token */
457 SubjectContext->PrimaryToken = PsReferencePrimaryToken(Process);
458 }
459
460 /*
461 * @implemented
462 */
463 VOID
464 NTAPI
465 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
466 {
467 /* Call the internal API */
468 SeCaptureSubjectContextEx(PsGetCurrentThread(),
469 PsGetCurrentProcess(),
470 SubjectContext);
471 }
472
473
474 /*
475 * @implemented
476 */
477 VOID STDCALL
478 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
479 {
480 PAGED_CODE();
481
482 KeEnterCriticalRegion();
483 ExAcquireResourceExclusiveLite(&SepSubjectContextLock, TRUE);
484 }
485
486
487 /*
488 * @implemented
489 */
490 VOID STDCALL
491 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
492 {
493 PAGED_CODE();
494
495 ExReleaseResourceLite(&SepSubjectContextLock);
496 KeLeaveCriticalRegion();
497 }
498
499
500 /*
501 * @implemented
502 */
503 VOID STDCALL
504 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
505 {
506 PAGED_CODE();
507
508 if (SubjectContext->PrimaryToken != NULL)
509 {
510 ObFastDereferenceObject(&PsGetCurrentProcess()->Token, SubjectContext->PrimaryToken);
511 }
512
513 if (SubjectContext->ClientToken != NULL)
514 {
515 ObDereferenceObject(SubjectContext->ClientToken);
516 }
517 }
518
519
520 /*
521 * @implemented
522 */
523 NTSTATUS STDCALL
524 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
525 {
526 PAGED_CODE();
527
528 if (*SecurityDescriptor != NULL)
529 {
530 ExFreePool(*SecurityDescriptor);
531 *SecurityDescriptor = NULL;
532 }
533
534 return STATUS_SUCCESS;
535 }
536
537
538 /*
539 * @unimplemented
540 */
541 NTSTATUS STDCALL
542 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
543 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
544 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
545 IN GUID *ObjectType OPTIONAL,
546 IN BOOLEAN IsDirectoryObject,
547 IN ULONG AutoInheritFlags,
548 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
549 IN PGENERIC_MAPPING GenericMapping,
550 IN POOL_TYPE PoolType)
551 {
552 UNIMPLEMENTED;
553 return STATUS_NOT_IMPLEMENTED;
554 }
555
556
557 /*
558 * FUNCTION: Creates a security descriptor for a new object.
559 * ARGUMENTS:
560 * ParentDescriptor =
561 * ExplicitDescriptor =
562 * NewDescriptor =
563 * IsDirectoryObject =
564 * SubjectContext =
565 * GeneralMapping =
566 * PoolType =
567 * RETURNS: Status
568 *
569 * @implemented
570 */
571 NTSTATUS STDCALL
572 SeAssignSecurity(PSECURITY_DESCRIPTOR _ParentDescriptor OPTIONAL,
573 PSECURITY_DESCRIPTOR _ExplicitDescriptor OPTIONAL,
574 PSECURITY_DESCRIPTOR *NewDescriptor,
575 BOOLEAN IsDirectoryObject,
576 PSECURITY_SUBJECT_CONTEXT SubjectContext,
577 PGENERIC_MAPPING GenericMapping,
578 POOL_TYPE PoolType)
579 {
580 PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor;
581 PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor;
582 PISECURITY_DESCRIPTOR Descriptor;
583 PTOKEN Token;
584 ULONG OwnerLength = 0;
585 ULONG GroupLength = 0;
586 ULONG DaclLength = 0;
587 ULONG SaclLength = 0;
588 ULONG Length = 0;
589 ULONG Control = 0;
590 ULONG_PTR Current;
591 PSID Owner = NULL;
592 PSID Group = NULL;
593 PACL Dacl = NULL;
594 PACL Sacl = NULL;
595
596 PAGED_CODE();
597
598 /* Lock subject context */
599 SeLockSubjectContext(SubjectContext);
600
601 if (SubjectContext->ClientToken != NULL)
602 {
603 Token = SubjectContext->ClientToken;
604 }
605 else
606 {
607 Token = SubjectContext->PrimaryToken;
608 }
609
610
611 /* Inherit the Owner SID */
612 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
613 {
614 DPRINT("Use explicit owner sid!\n");
615 Owner = ExplicitDescriptor->Owner;
616
617 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
618 {
619 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
620
621 }
622 }
623 else
624 {
625 if (Token != NULL)
626 {
627 DPRINT("Use token owner sid!\n");
628 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
629 }
630 else
631 {
632 DPRINT("Use default owner sid!\n");
633 Owner = SeLocalSystemSid;
634 }
635
636 Control |= SE_OWNER_DEFAULTED;
637 }
638
639 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
640
641
642 /* Inherit the Group SID */
643 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
644 {
645 DPRINT("Use explicit group sid!\n");
646 Group = ExplicitDescriptor->Group;
647 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
648 {
649 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
650 }
651 }
652 else
653 {
654 if (Token != NULL)
655 {
656 DPRINT("Use token group sid!\n");
657 Group = Token->PrimaryGroup;
658 }
659 else
660 {
661 DPRINT("Use default group sid!\n");
662 Group = SeLocalSystemSid;
663 }
664
665 Control |= SE_OWNER_DEFAULTED;
666 }
667
668 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
669
670
671 /* Inherit the DACL */
672 if (ExplicitDescriptor != NULL &&
673 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
674 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
675 {
676 DPRINT("Use explicit DACL!\n");
677 Dacl = ExplicitDescriptor->Dacl;
678 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
679 {
680 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
681 }
682
683 Control |= SE_DACL_PRESENT;
684 }
685 else if (ParentDescriptor != NULL &&
686 (ParentDescriptor->Control & SE_DACL_PRESENT))
687 {
688 DPRINT("Use parent DACL!\n");
689 /* FIXME: Inherit */
690 Dacl = ParentDescriptor->Dacl;
691 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
692 {
693 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
694 }
695 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
696 }
697 else if (Token != NULL && Token->DefaultDacl != NULL)
698 {
699 DPRINT("Use token default DACL!\n");
700 /* FIXME: Inherit */
701 Dacl = Token->DefaultDacl;
702 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
703 }
704 else
705 {
706 DPRINT("Use NULL DACL!\n");
707 Dacl = NULL;
708 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
709 }
710
711 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
712
713
714 /* Inherit the SACL */
715 if (ExplicitDescriptor != NULL &&
716 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
717 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
718 {
719 DPRINT("Use explicit SACL!\n");
720 Sacl = ExplicitDescriptor->Sacl;
721 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
722 {
723 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
724 }
725
726 Control |= SE_SACL_PRESENT;
727 }
728 else if (ParentDescriptor != NULL &&
729 (ParentDescriptor->Control & SE_SACL_PRESENT))
730 {
731 DPRINT("Use parent SACL!\n");
732 /* FIXME: Inherit */
733 Sacl = ParentDescriptor->Sacl;
734 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
735 {
736 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
737 }
738 Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
739 }
740
741 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
742
743
744 /* Allocate and initialize the new security descriptor */
745 Length = sizeof(SECURITY_DESCRIPTOR) +
746 OwnerLength + GroupLength + DaclLength + SaclLength;
747
748 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
749 sizeof(SECURITY_DESCRIPTOR),
750 OwnerLength,
751 GroupLength,
752 DaclLength,
753 SaclLength);
754
755 Descriptor = ExAllocatePool(PagedPool,
756 Length);
757 if (Descriptor == NULL)
758 {
759 DPRINT1("ExAlloctePool() failed\n");
760 /* FIXME: Unlock subject context */
761 return STATUS_INSUFFICIENT_RESOURCES;
762 }
763
764 RtlZeroMemory( Descriptor, Length );
765 RtlCreateSecurityDescriptor(Descriptor,
766 SECURITY_DESCRIPTOR_REVISION);
767
768 Descriptor->Control = Control | SE_SELF_RELATIVE;
769
770 Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
771
772 if (SaclLength != 0)
773 {
774 RtlCopyMemory((PVOID)Current,
775 Sacl,
776 SaclLength);
777 Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
778 Current += SaclLength;
779 }
780
781 if (DaclLength != 0)
782 {
783 RtlCopyMemory((PVOID)Current,
784 Dacl,
785 DaclLength);
786 Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
787 Current += DaclLength;
788 }
789
790 if (OwnerLength != 0)
791 {
792 RtlCopyMemory((PVOID)Current,
793 Owner,
794 OwnerLength);
795 Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
796 Current += OwnerLength;
797 DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
798 }
799 else
800 DPRINT("Owner of %x is zero length\n", Descriptor);
801
802 if (GroupLength != 0)
803 {
804 memmove((PVOID)Current,
805 Group,
806 GroupLength);
807 Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
808 }
809
810 /* Unlock subject context */
811 SeUnlockSubjectContext(SubjectContext);
812
813 *NewDescriptor = Descriptor;
814
815 DPRINT("Descrptor %x\n", Descriptor);
816 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
817
818 return STATUS_SUCCESS;
819 }
820
821
822 static BOOLEAN
823 SepSidInToken(PACCESS_TOKEN _Token,
824 PSID Sid)
825 {
826 ULONG i;
827 PTOKEN Token = (PTOKEN)_Token;
828
829 PAGED_CODE();
830
831 if (Token->UserAndGroupCount == 0)
832 {
833 return FALSE;
834 }
835
836 for (i=0; i<Token->UserAndGroupCount; i++)
837 {
838 if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
839 {
840 if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
841 {
842 return TRUE;
843 }
844
845 return FALSE;
846 }
847 }
848
849 return FALSE;
850 }
851
852
853 /*
854 * FUNCTION: Determines whether the requested access rights can be granted
855 * to an object protected by a security descriptor and an object owner
856 * ARGUMENTS:
857 * SecurityDescriptor = Security descriptor protecting the object
858 * SubjectSecurityContext = Subject's captured security context
859 * SubjectContextLocked = Indicates the user's subject context is locked
860 * DesiredAccess = Access rights the caller is trying to acquire
861 * PreviouslyGrantedAccess = Specified the access rights already granted
862 * Privileges = ?
863 * GenericMapping = Generic mapping associated with the object
864 * AccessMode = Access mode used for the check
865 * GrantedAccess (OUT) = On return specifies the access granted
866 * AccessStatus (OUT) = Status indicating why access was denied
867 * RETURNS: If access was granted, returns TRUE
868 *
869 * @implemented
870 */
871 BOOLEAN STDCALL
872 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
873 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
874 IN BOOLEAN SubjectContextLocked,
875 IN ACCESS_MASK DesiredAccess,
876 IN ACCESS_MASK PreviouslyGrantedAccess,
877 OUT PPRIVILEGE_SET* Privileges,
878 IN PGENERIC_MAPPING GenericMapping,
879 IN KPROCESSOR_MODE AccessMode,
880 OUT PACCESS_MASK GrantedAccess,
881 OUT PNTSTATUS AccessStatus)
882 {
883 LUID_AND_ATTRIBUTES Privilege;
884 ACCESS_MASK CurrentAccess;
885 PACCESS_TOKEN Token;
886 ULONG i;
887 PACL Dacl;
888 BOOLEAN Present;
889 BOOLEAN Defaulted;
890 PACE CurrentAce;
891 PSID Sid;
892 NTSTATUS Status;
893
894 PAGED_CODE();
895
896 /* Check if we didn't get an SD */
897 if (!SecurityDescriptor)
898 {
899 /* Automatic failure */
900 *AccessStatus = STATUS_ACCESS_DENIED;
901 return FALSE;
902 }
903
904 CurrentAccess = PreviouslyGrantedAccess;
905
906 if (SubjectContextLocked == FALSE)
907 {
908 SeLockSubjectContext(SubjectSecurityContext);
909 }
910
911 Token = SubjectSecurityContext->ClientToken ?
912 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
913
914 /* Get the DACL */
915 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
916 &Present,
917 &Dacl,
918 &Defaulted);
919 if (!NT_SUCCESS(Status))
920 {
921 if (SubjectContextLocked == FALSE)
922 {
923 SeUnlockSubjectContext(SubjectSecurityContext);
924 }
925
926 *AccessStatus = Status;
927 return FALSE;
928 }
929
930 /* RULE 1: Grant desired access if the object is unprotected */
931 if (Present == TRUE && Dacl == NULL)
932 {
933 if (SubjectContextLocked == FALSE)
934 {
935 SeUnlockSubjectContext(SubjectSecurityContext);
936 }
937
938 *GrantedAccess = DesiredAccess;
939 *AccessStatus = STATUS_SUCCESS;
940 return TRUE;
941 }
942
943 CurrentAccess = PreviouslyGrantedAccess;
944
945 /* RULE 2: Check token for 'take ownership' privilege */
946 Privilege.Luid = SeTakeOwnershipPrivilege;
947 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
948
949 if (SepPrivilegeCheck(Token,
950 &Privilege,
951 1,
952 PRIVILEGE_SET_ALL_NECESSARY,
953 AccessMode))
954 {
955 CurrentAccess |= WRITE_OWNER;
956 if (DesiredAccess == CurrentAccess)
957 {
958 if (SubjectContextLocked == FALSE)
959 {
960 SeUnlockSubjectContext(SubjectSecurityContext);
961 }
962
963 *GrantedAccess = CurrentAccess;
964 *AccessStatus = STATUS_SUCCESS;
965 return TRUE;
966 }
967 }
968
969 /* RULE 3: Check whether the token is the owner */
970 Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
971 &Sid,
972 &Defaulted);
973 if (!NT_SUCCESS(Status))
974 {
975 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
976 if (SubjectContextLocked == FALSE)
977 {
978 SeUnlockSubjectContext(SubjectSecurityContext);
979 }
980
981 *AccessStatus = Status;
982 return FALSE;
983 }
984
985 if (SepSidInToken(Token, Sid))
986 {
987 CurrentAccess |= (READ_CONTROL | WRITE_DAC);
988 if (DesiredAccess == CurrentAccess)
989 {
990 if (SubjectContextLocked == FALSE)
991 {
992 SeUnlockSubjectContext(SubjectSecurityContext);
993 }
994
995 *GrantedAccess = CurrentAccess;
996 *AccessStatus = STATUS_SUCCESS;
997 return TRUE;
998 }
999 }
1000
1001 /* Fail if DACL is absent */
1002 if (Present == FALSE)
1003 {
1004 if (SubjectContextLocked == FALSE)
1005 {
1006 SeUnlockSubjectContext(SubjectSecurityContext);
1007 }
1008
1009 *GrantedAccess = 0;
1010 *AccessStatus = STATUS_ACCESS_DENIED;
1011 return TRUE;
1012 }
1013
1014 /* RULE 4: Grant rights according to the DACL */
1015 CurrentAce = (PACE)(Dacl + 1);
1016 for (i = 0; i < Dacl->AceCount; i++)
1017 {
1018 Sid = (PSID)(CurrentAce + 1);
1019 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
1020 {
1021 if (SepSidInToken(Token, Sid))
1022 {
1023 if (SubjectContextLocked == FALSE)
1024 {
1025 SeUnlockSubjectContext(SubjectSecurityContext);
1026 }
1027
1028 *GrantedAccess = 0;
1029 *AccessStatus = STATUS_ACCESS_DENIED;
1030 return TRUE;
1031 }
1032 }
1033
1034 if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
1035 {
1036 if (SepSidInToken(Token, Sid))
1037 {
1038 CurrentAccess |= CurrentAce->AccessMask;
1039 }
1040 }
1041 }
1042
1043 if (SubjectContextLocked == FALSE)
1044 {
1045 SeUnlockSubjectContext(SubjectSecurityContext);
1046 }
1047
1048 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
1049 CurrentAccess, DesiredAccess);
1050
1051 *GrantedAccess = CurrentAccess & DesiredAccess;
1052
1053 *AccessStatus =
1054 (*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
1055
1056 return TRUE;
1057 }
1058
1059
1060 NTSTATUS STDCALL
1061 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1062 IN HANDLE TokenHandle,
1063 IN ACCESS_MASK DesiredAccess,
1064 IN PGENERIC_MAPPING GenericMapping,
1065 OUT PPRIVILEGE_SET PrivilegeSet,
1066 OUT PULONG ReturnLength,
1067 OUT PACCESS_MASK GrantedAccess,
1068 OUT PNTSTATUS AccessStatus)
1069 {
1070 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext = {0};
1071 KPROCESSOR_MODE PreviousMode;
1072 PTOKEN Token;
1073 NTSTATUS Status;
1074
1075 PAGED_CODE();
1076
1077 DPRINT("NtAccessCheck() called\n");
1078
1079 PreviousMode = KeGetPreviousMode();
1080 if (PreviousMode == KernelMode)
1081 {
1082 *GrantedAccess = DesiredAccess;
1083 *AccessStatus = STATUS_SUCCESS;
1084 return STATUS_SUCCESS;
1085 }
1086
1087 Status = ObReferenceObjectByHandle(TokenHandle,
1088 TOKEN_QUERY,
1089 SepTokenObjectType,
1090 PreviousMode,
1091 (PVOID*)&Token,
1092 NULL);
1093 if (!NT_SUCCESS(Status))
1094 {
1095 DPRINT1("Failed to reference token (Status %lx)\n", Status);
1096 return Status;
1097 }
1098
1099 /* Check token type */
1100 if (Token->TokenType != TokenImpersonation)
1101 {
1102 DPRINT1("No impersonation token\n");
1103 ObDereferenceObject(Token);
1104 return STATUS_ACCESS_VIOLATION;
1105 }
1106
1107 /* Check impersonation level */
1108 if (Token->ImpersonationLevel < SecurityAnonymous)
1109 {
1110 DPRINT1("Invalid impersonation level\n");
1111 ObDereferenceObject(Token);
1112 return STATUS_ACCESS_VIOLATION;
1113 }
1114
1115 SubjectSecurityContext.ClientToken = Token;
1116 SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
1117
1118 /* Lock subject context */
1119 SeLockSubjectContext(&SubjectSecurityContext);
1120
1121 if (SeAccessCheck(SecurityDescriptor,
1122 &SubjectSecurityContext,
1123 TRUE,
1124 DesiredAccess,
1125 0,
1126 &PrivilegeSet,
1127 GenericMapping,
1128 PreviousMode,
1129 GrantedAccess,
1130 AccessStatus))
1131 {
1132 Status = *AccessStatus;
1133 }
1134 else
1135 {
1136 Status = STATUS_ACCESS_DENIED;
1137 }
1138
1139 /* Unlock subject context */
1140 SeUnlockSubjectContext(&SubjectSecurityContext);
1141
1142 ObDereferenceObject(Token);
1143
1144 DPRINT("NtAccessCheck() done\n");
1145
1146 return Status;
1147 }
1148
1149 VOID STDCALL
1150 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
1151 OUT PACCESS_MASK DesiredAccess)
1152 {
1153 if (SecurityInformation & (OWNER_SECURITY_INFORMATION |
1154 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION))
1155 {
1156 *DesiredAccess |= READ_CONTROL;
1157 }
1158 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1159 {
1160 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
1161 }
1162 }
1163
1164 VOID STDCALL
1165 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
1166 OUT PACCESS_MASK DesiredAccess)
1167 {
1168 if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
1169 {
1170 *DesiredAccess |= WRITE_OWNER;
1171 }
1172 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1173 {
1174 *DesiredAccess |= WRITE_DAC;
1175 }
1176 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1177 {
1178 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
1179 }
1180 }
1181
1182 /* EOF */