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