- NDK 0.98, now with versionned headers. Too many changes to list, see the TinyKRNL...
[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 PROS_OBJECT_HEADER Header = BODY_TO_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 /*
420 * @implemented
421 */
422 VOID STDCALL
423 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
424 {
425 PETHREAD Thread;
426 BOOLEAN CopyOnOpen;
427 BOOLEAN EffectiveOnly;
428
429 PAGED_CODE();
430
431 Thread = PsGetCurrentThread();
432 if (Thread == NULL)
433 {
434 SubjectContext->ProcessAuditId = 0;
435 SubjectContext->PrimaryToken = NULL;
436 SubjectContext->ClientToken = NULL;
437 SubjectContext->ImpersonationLevel = 0;
438 }
439 else
440 {
441 SubjectContext->ProcessAuditId = Thread->ThreadsProcess;
442 SubjectContext->ClientToken =
443 PsReferenceImpersonationToken(Thread,
444 &CopyOnOpen,
445 &EffectiveOnly,
446 &SubjectContext->ImpersonationLevel);
447 SubjectContext->PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
448 }
449 }
450
451
452 /*
453 * @implemented
454 */
455 VOID STDCALL
456 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
457 {
458 PAGED_CODE();
459
460 KeEnterCriticalRegion();
461 ExAcquireResourceExclusiveLite(&SepSubjectContextLock, TRUE);
462 }
463
464
465 /*
466 * @implemented
467 */
468 VOID STDCALL
469 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
470 {
471 PAGED_CODE();
472
473 ExReleaseResourceLite(&SepSubjectContextLock);
474 KeLeaveCriticalRegion();
475 }
476
477
478 /*
479 * @implemented
480 */
481 VOID STDCALL
482 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
483 {
484 PAGED_CODE();
485
486 if (SubjectContext->PrimaryToken != NULL)
487 {
488 ObDereferenceObject(SubjectContext->PrimaryToken);
489 }
490
491 if (SubjectContext->ClientToken != NULL)
492 {
493 ObDereferenceObject(SubjectContext->ClientToken);
494 }
495 }
496
497
498 /*
499 * @implemented
500 */
501 NTSTATUS STDCALL
502 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
503 {
504 PAGED_CODE();
505
506 if (*SecurityDescriptor != NULL)
507 {
508 ExFreePool(*SecurityDescriptor);
509 *SecurityDescriptor = NULL;
510 }
511
512 return STATUS_SUCCESS;
513 }
514
515
516 /*
517 * @unimplemented
518 */
519 NTSTATUS STDCALL
520 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
521 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
522 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
523 IN GUID *ObjectType OPTIONAL,
524 IN BOOLEAN IsDirectoryObject,
525 IN ULONG AutoInheritFlags,
526 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
527 IN PGENERIC_MAPPING GenericMapping,
528 IN POOL_TYPE PoolType)
529 {
530 UNIMPLEMENTED;
531 return STATUS_NOT_IMPLEMENTED;
532 }
533
534
535 /*
536 * FUNCTION: Creates a security descriptor for a new object.
537 * ARGUMENTS:
538 * ParentDescriptor =
539 * ExplicitDescriptor =
540 * NewDescriptor =
541 * IsDirectoryObject =
542 * SubjectContext =
543 * GeneralMapping =
544 * PoolType =
545 * RETURNS: Status
546 *
547 * @implemented
548 */
549 NTSTATUS STDCALL
550 SeAssignSecurity(PSECURITY_DESCRIPTOR _ParentDescriptor OPTIONAL,
551 PSECURITY_DESCRIPTOR _ExplicitDescriptor OPTIONAL,
552 PSECURITY_DESCRIPTOR *NewDescriptor,
553 BOOLEAN IsDirectoryObject,
554 PSECURITY_SUBJECT_CONTEXT SubjectContext,
555 PGENERIC_MAPPING GenericMapping,
556 POOL_TYPE PoolType)
557 {
558 PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor;
559 PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor;
560 PISECURITY_DESCRIPTOR Descriptor;
561 PTOKEN Token;
562 ULONG OwnerLength = 0;
563 ULONG GroupLength = 0;
564 ULONG DaclLength = 0;
565 ULONG SaclLength = 0;
566 ULONG Length = 0;
567 ULONG Control = 0;
568 ULONG_PTR Current;
569 PSID Owner = NULL;
570 PSID Group = NULL;
571 PACL Dacl = NULL;
572 PACL Sacl = NULL;
573
574 PAGED_CODE();
575
576 /* Lock subject context */
577 SeLockSubjectContext(SubjectContext);
578
579 if (SubjectContext->ClientToken != NULL)
580 {
581 Token = SubjectContext->ClientToken;
582 }
583 else
584 {
585 Token = SubjectContext->PrimaryToken;
586 }
587
588
589 /* Inherit the Owner SID */
590 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
591 {
592 DPRINT("Use explicit owner sid!\n");
593 Owner = ExplicitDescriptor->Owner;
594
595 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
596 {
597 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
598
599 }
600 }
601 else
602 {
603 if (Token != NULL)
604 {
605 DPRINT("Use token owner sid!\n");
606 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
607 }
608 else
609 {
610 DPRINT("Use default owner sid!\n");
611 Owner = SeLocalSystemSid;
612 }
613
614 Control |= SE_OWNER_DEFAULTED;
615 }
616
617 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
618
619
620 /* Inherit the Group SID */
621 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
622 {
623 DPRINT("Use explicit group sid!\n");
624 Group = ExplicitDescriptor->Group;
625 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
626 {
627 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
628 }
629 }
630 else
631 {
632 if (Token != NULL)
633 {
634 DPRINT("Use token group sid!\n");
635 Group = Token->PrimaryGroup;
636 }
637 else
638 {
639 DPRINT("Use default group sid!\n");
640 Group = SeLocalSystemSid;
641 }
642
643 Control |= SE_OWNER_DEFAULTED;
644 }
645
646 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
647
648
649 /* Inherit the DACL */
650 if (ExplicitDescriptor != NULL &&
651 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
652 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
653 {
654 DPRINT("Use explicit DACL!\n");
655 Dacl = ExplicitDescriptor->Dacl;
656 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
657 {
658 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
659 }
660
661 Control |= SE_DACL_PRESENT;
662 }
663 else if (ParentDescriptor != NULL &&
664 (ParentDescriptor->Control & SE_DACL_PRESENT))
665 {
666 DPRINT("Use parent DACL!\n");
667 /* FIXME: Inherit */
668 Dacl = ParentDescriptor->Dacl;
669 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
670 {
671 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
672 }
673 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
674 }
675 else if (Token != NULL && Token->DefaultDacl != NULL)
676 {
677 DPRINT("Use token default DACL!\n");
678 /* FIXME: Inherit */
679 Dacl = Token->DefaultDacl;
680 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
681 }
682 else
683 {
684 DPRINT("Use NULL DACL!\n");
685 Dacl = NULL;
686 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
687 }
688
689 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
690
691
692 /* Inherit the SACL */
693 if (ExplicitDescriptor != NULL &&
694 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
695 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
696 {
697 DPRINT("Use explicit SACL!\n");
698 Sacl = ExplicitDescriptor->Sacl;
699 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
700 {
701 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
702 }
703
704 Control |= SE_SACL_PRESENT;
705 }
706 else if (ParentDescriptor != NULL &&
707 (ParentDescriptor->Control & SE_SACL_PRESENT))
708 {
709 DPRINT("Use parent SACL!\n");
710 /* FIXME: Inherit */
711 Sacl = ParentDescriptor->Sacl;
712 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
713 {
714 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
715 }
716 Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
717 }
718
719 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
720
721
722 /* Allocate and initialize the new security descriptor */
723 Length = sizeof(SECURITY_DESCRIPTOR) +
724 OwnerLength + GroupLength + DaclLength + SaclLength;
725
726 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
727 sizeof(SECURITY_DESCRIPTOR),
728 OwnerLength,
729 GroupLength,
730 DaclLength,
731 SaclLength);
732
733 Descriptor = ExAllocatePool(PagedPool,
734 Length);
735 if (Descriptor == NULL)
736 {
737 DPRINT1("ExAlloctePool() failed\n");
738 /* FIXME: Unlock subject context */
739 return STATUS_INSUFFICIENT_RESOURCES;
740 }
741
742 RtlZeroMemory( Descriptor, Length );
743 RtlCreateSecurityDescriptor(Descriptor,
744 SECURITY_DESCRIPTOR_REVISION);
745
746 Descriptor->Control = Control | SE_SELF_RELATIVE;
747
748 Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
749
750 if (SaclLength != 0)
751 {
752 RtlCopyMemory((PVOID)Current,
753 Sacl,
754 SaclLength);
755 Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
756 Current += SaclLength;
757 }
758
759 if (DaclLength != 0)
760 {
761 RtlCopyMemory((PVOID)Current,
762 Dacl,
763 DaclLength);
764 Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
765 Current += DaclLength;
766 }
767
768 if (OwnerLength != 0)
769 {
770 RtlCopyMemory((PVOID)Current,
771 Owner,
772 OwnerLength);
773 Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
774 Current += OwnerLength;
775 DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
776 }
777 else
778 DPRINT("Owner of %x is zero length\n", Descriptor);
779
780 if (GroupLength != 0)
781 {
782 memmove((PVOID)Current,
783 Group,
784 GroupLength);
785 Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
786 }
787
788 /* Unlock subject context */
789 SeUnlockSubjectContext(SubjectContext);
790
791 *NewDescriptor = Descriptor;
792
793 DPRINT("Descrptor %x\n", Descriptor);
794 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
795
796 return STATUS_SUCCESS;
797 }
798
799
800 static BOOLEAN
801 SepSidInToken(PACCESS_TOKEN _Token,
802 PSID Sid)
803 {
804 ULONG i;
805 PTOKEN Token = (PTOKEN)_Token;
806
807 PAGED_CODE();
808
809 if (Token->UserAndGroupCount == 0)
810 {
811 return FALSE;
812 }
813
814 for (i=0; i<Token->UserAndGroupCount; i++)
815 {
816 if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
817 {
818 if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
819 {
820 return TRUE;
821 }
822
823 return FALSE;
824 }
825 }
826
827 return FALSE;
828 }
829
830
831 /*
832 * FUNCTION: Determines whether the requested access rights can be granted
833 * to an object protected by a security descriptor and an object owner
834 * ARGUMENTS:
835 * SecurityDescriptor = Security descriptor protecting the object
836 * SubjectSecurityContext = Subject's captured security context
837 * SubjectContextLocked = Indicates the user's subject context is locked
838 * DesiredAccess = Access rights the caller is trying to acquire
839 * PreviouslyGrantedAccess = Specified the access rights already granted
840 * Privileges = ?
841 * GenericMapping = Generic mapping associated with the object
842 * AccessMode = Access mode used for the check
843 * GrantedAccess (OUT) = On return specifies the access granted
844 * AccessStatus (OUT) = Status indicating why access was denied
845 * RETURNS: If access was granted, returns TRUE
846 *
847 * @implemented
848 */
849 BOOLEAN STDCALL
850 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
851 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
852 IN BOOLEAN SubjectContextLocked,
853 IN ACCESS_MASK DesiredAccess,
854 IN ACCESS_MASK PreviouslyGrantedAccess,
855 OUT PPRIVILEGE_SET* Privileges,
856 IN PGENERIC_MAPPING GenericMapping,
857 IN KPROCESSOR_MODE AccessMode,
858 OUT PACCESS_MASK GrantedAccess,
859 OUT PNTSTATUS AccessStatus)
860 {
861 LUID_AND_ATTRIBUTES Privilege;
862 ACCESS_MASK CurrentAccess;
863 PACCESS_TOKEN Token;
864 ULONG i;
865 PACL Dacl;
866 BOOLEAN Present;
867 BOOLEAN Defaulted;
868 PACE CurrentAce;
869 PSID Sid;
870 NTSTATUS Status;
871
872 PAGED_CODE();
873
874 CurrentAccess = PreviouslyGrantedAccess;
875
876 if (SubjectContextLocked == FALSE)
877 {
878 SeLockSubjectContext(SubjectSecurityContext);
879 }
880
881 Token = SubjectSecurityContext->ClientToken ?
882 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
883
884 /* Get the DACL */
885 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
886 &Present,
887 &Dacl,
888 &Defaulted);
889 if (!NT_SUCCESS(Status))
890 {
891 if (SubjectContextLocked == FALSE)
892 {
893 SeUnlockSubjectContext(SubjectSecurityContext);
894 }
895
896 *AccessStatus = Status;
897 return FALSE;
898 }
899
900 /* RULE 1: Grant desired access if the object is unprotected */
901 if (Present == TRUE && Dacl == NULL)
902 {
903 if (SubjectContextLocked == FALSE)
904 {
905 SeUnlockSubjectContext(SubjectSecurityContext);
906 }
907
908 *GrantedAccess = DesiredAccess;
909 *AccessStatus = STATUS_SUCCESS;
910 return TRUE;
911 }
912
913 CurrentAccess = PreviouslyGrantedAccess;
914
915 /* RULE 2: Check token for 'take ownership' privilege */
916 Privilege.Luid = SeTakeOwnershipPrivilege;
917 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
918
919 if (SepPrivilegeCheck(Token,
920 &Privilege,
921 1,
922 PRIVILEGE_SET_ALL_NECESSARY,
923 AccessMode))
924 {
925 CurrentAccess |= WRITE_OWNER;
926 if (DesiredAccess == CurrentAccess)
927 {
928 if (SubjectContextLocked == FALSE)
929 {
930 SeUnlockSubjectContext(SubjectSecurityContext);
931 }
932
933 *GrantedAccess = CurrentAccess;
934 *AccessStatus = STATUS_SUCCESS;
935 return TRUE;
936 }
937 }
938
939 /* RULE 3: Check whether the token is the owner */
940 Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
941 &Sid,
942 &Defaulted);
943 if (!NT_SUCCESS(Status))
944 {
945 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
946 if (SubjectContextLocked == FALSE)
947 {
948 SeUnlockSubjectContext(SubjectSecurityContext);
949 }
950
951 *AccessStatus = Status;
952 return FALSE;
953 }
954
955 if (SepSidInToken(Token, Sid))
956 {
957 CurrentAccess |= (READ_CONTROL | WRITE_DAC);
958 if (DesiredAccess == CurrentAccess)
959 {
960 if (SubjectContextLocked == FALSE)
961 {
962 SeUnlockSubjectContext(SubjectSecurityContext);
963 }
964
965 *GrantedAccess = CurrentAccess;
966 *AccessStatus = STATUS_SUCCESS;
967 return TRUE;
968 }
969 }
970
971 /* Fail if DACL is absent */
972 if (Present == FALSE)
973 {
974 if (SubjectContextLocked == FALSE)
975 {
976 SeUnlockSubjectContext(SubjectSecurityContext);
977 }
978
979 *GrantedAccess = 0;
980 *AccessStatus = STATUS_ACCESS_DENIED;
981 return TRUE;
982 }
983
984 /* RULE 4: Grant rights according to the DACL */
985 CurrentAce = (PACE)(Dacl + 1);
986 for (i = 0; i < Dacl->AceCount; i++)
987 {
988 Sid = (PSID)(CurrentAce + 1);
989 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
990 {
991 if (SepSidInToken(Token, Sid))
992 {
993 if (SubjectContextLocked == FALSE)
994 {
995 SeUnlockSubjectContext(SubjectSecurityContext);
996 }
997
998 *GrantedAccess = 0;
999 *AccessStatus = STATUS_ACCESS_DENIED;
1000 return TRUE;
1001 }
1002 }
1003
1004 if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
1005 {
1006 if (SepSidInToken(Token, Sid))
1007 {
1008 CurrentAccess |= CurrentAce->AccessMask;
1009 }
1010 }
1011 }
1012
1013 if (SubjectContextLocked == FALSE)
1014 {
1015 SeUnlockSubjectContext(SubjectSecurityContext);
1016 }
1017
1018 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
1019 CurrentAccess, DesiredAccess);
1020
1021 *GrantedAccess = CurrentAccess & DesiredAccess;
1022
1023 *AccessStatus =
1024 (*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
1025
1026 return TRUE;
1027 }
1028
1029
1030 NTSTATUS STDCALL
1031 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1032 IN HANDLE TokenHandle,
1033 IN ACCESS_MASK DesiredAccess,
1034 IN PGENERIC_MAPPING GenericMapping,
1035 OUT PPRIVILEGE_SET PrivilegeSet,
1036 OUT PULONG ReturnLength,
1037 OUT PACCESS_MASK GrantedAccess,
1038 OUT PNTSTATUS AccessStatus)
1039 {
1040 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext = {0};
1041 KPROCESSOR_MODE PreviousMode;
1042 PTOKEN Token;
1043 NTSTATUS Status;
1044
1045 PAGED_CODE();
1046
1047 DPRINT("NtAccessCheck() called\n");
1048
1049 PreviousMode = KeGetPreviousMode();
1050 if (PreviousMode == KernelMode)
1051 {
1052 *GrantedAccess = DesiredAccess;
1053 *AccessStatus = STATUS_SUCCESS;
1054 return STATUS_SUCCESS;
1055 }
1056
1057 Status = ObReferenceObjectByHandle(TokenHandle,
1058 TOKEN_QUERY,
1059 SepTokenObjectType,
1060 PreviousMode,
1061 (PVOID*)&Token,
1062 NULL);
1063 if (!NT_SUCCESS(Status))
1064 {
1065 DPRINT1("Failed to reference token (Status %lx)\n", Status);
1066 return Status;
1067 }
1068
1069 /* Check token type */
1070 if (Token->TokenType != TokenImpersonation)
1071 {
1072 DPRINT1("No impersonation token\n");
1073 ObDereferenceObject(Token);
1074 return STATUS_ACCESS_VIOLATION;
1075 }
1076
1077 /* Check impersonation level */
1078 if (Token->ImpersonationLevel < SecurityAnonymous)
1079 {
1080 DPRINT1("Invalid impersonation level\n");
1081 ObDereferenceObject(Token);
1082 return STATUS_ACCESS_VIOLATION;
1083 }
1084
1085 SubjectSecurityContext.ClientToken = Token;
1086 SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
1087
1088 /* Lock subject context */
1089 SeLockSubjectContext(&SubjectSecurityContext);
1090
1091 if (SeAccessCheck(SecurityDescriptor,
1092 &SubjectSecurityContext,
1093 TRUE,
1094 DesiredAccess,
1095 0,
1096 &PrivilegeSet,
1097 GenericMapping,
1098 PreviousMode,
1099 GrantedAccess,
1100 AccessStatus))
1101 {
1102 Status = *AccessStatus;
1103 }
1104 else
1105 {
1106 Status = STATUS_ACCESS_DENIED;
1107 }
1108
1109 /* Unlock subject context */
1110 SeUnlockSubjectContext(&SubjectSecurityContext);
1111
1112 ObDereferenceObject(Token);
1113
1114 DPRINT("NtAccessCheck() done\n");
1115
1116 return Status;
1117 }
1118
1119 VOID STDCALL
1120 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
1121 OUT PACCESS_MASK DesiredAccess)
1122 {
1123 if (SecurityInformation & (OWNER_SECURITY_INFORMATION |
1124 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION))
1125 {
1126 *DesiredAccess |= READ_CONTROL;
1127 }
1128 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1129 {
1130 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
1131 }
1132 }
1133
1134 VOID STDCALL
1135 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
1136 OUT PACCESS_MASK DesiredAccess)
1137 {
1138 if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
1139 {
1140 *DesiredAccess |= WRITE_OWNER;
1141 }
1142 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1143 {
1144 *DesiredAccess |= WRITE_DAC;
1145 }
1146 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1147 {
1148 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
1149 }
1150 }
1151
1152 /* EOF */