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