1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Security auditing functions
5 * COPYRIGHT: Copyright Eric Kohl
6 * Copyright Timo Kreuzer <timo.kreuzer@reactos.org>
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 #define SEP_PRIVILEGE_SET_MAX_COUNT 60
16
17 UNICODE_STRING SeSubsystemName = RTL_CONSTANT_STRING(L"Security");
18
19 /* PRIVATE FUNCTIONS ***********************************************************/
20
21 /**
22 * @unimplemented
23 * @brief
24 * Peforms a detailed security auditing with an access token.
25 *
26 * @param[in] Token
27 * A valid token object.
28 *
29 * @return
30 * To be added...
31 */
32 BOOLEAN
33 NTAPI
SeDetailedAuditingWithToken(_In_ PTOKEN Token)34 SeDetailedAuditingWithToken(
35 _In_ PTOKEN Token)
36 {
37 /* FIXME */
38 return FALSE;
39 }
40
41 /**
42 * @unimplemented
43 * @brief
44 * Peforms a security auditing against a process that is about to
45 * be created.
46 *
47 * @param[in] Process
48 * An object that points to a process which is in process of
49 * creation.
50 *
51 * @return
52 * Nothing.
53 */
54 VOID
55 NTAPI
SeAuditProcessCreate(_In_ PEPROCESS Process)56 SeAuditProcessCreate(
57 _In_ PEPROCESS Process)
58 {
59 /* FIXME */
60 }
61
62 /**
63 * @unimplemented
64 * @brief
65 * Peforms a security auditing against a process that is about to
66 * be terminated.
67 *
68 * @param[in] Process
69 * An object that points to a process which is in process of
70 * termination.
71 *
72 * @return
73 * Nothing.
74 */
75 VOID
76 NTAPI
SeAuditProcessExit(_In_ PEPROCESS Process)77 SeAuditProcessExit(
78 _In_ PEPROCESS Process)
79 {
80 /* FIXME */
81 }
82
83 /**
84 * @brief
85 * Initializes a process audit name and returns it to the caller.
86 *
87 * @param[in] FileObject
88 * File object that points to a name to be queried.
89 *
90 * @param[in] DoAudit
91 * If set to TRUE, the function will perform various security
92 * auditing onto the audit name.
93 *
94 * @param[out] AuditInfo
95 * The returned audit info data.
96 *
97 * @return
98 * Returns STATUS_SUCCESS if process audit name initialization
99 * has completed successfully. STATUS_NO_MEMORY is returned if
100 * pool allocation for object name info has failed. A failure
101 * NTSTATUS code is returned otherwise.
102 */
103 NTSTATUS
104 NTAPI
SeInitializeProcessAuditName(_In_ PFILE_OBJECT FileObject,_In_ BOOLEAN DoAudit,_Out_ POBJECT_NAME_INFORMATION * AuditInfo)105 SeInitializeProcessAuditName(
106 _In_ PFILE_OBJECT FileObject,
107 _In_ BOOLEAN DoAudit,
108 _Out_ POBJECT_NAME_INFORMATION *AuditInfo)
109 {
110 OBJECT_NAME_INFORMATION LocalNameInfo;
111 POBJECT_NAME_INFORMATION ObjectNameInfo = NULL;
112 ULONG ReturnLength = 8;
113 NTSTATUS Status;
114
115 PAGED_CODE();
116 ASSERT(AuditInfo);
117
118 /* Check if we should do auditing */
119 if (DoAudit)
120 {
121 /* FIXME: TODO */
122 }
123
124 /* Now query the name */
125 Status = ObQueryNameString(FileObject,
126 &LocalNameInfo,
127 sizeof(LocalNameInfo),
128 &ReturnLength);
129 if (((Status == STATUS_BUFFER_OVERFLOW) ||
130 (Status == STATUS_BUFFER_TOO_SMALL) ||
131 (Status == STATUS_INFO_LENGTH_MISMATCH)) &&
132 (ReturnLength != sizeof(LocalNameInfo)))
133 {
134 /* Allocate required size */
135 ObjectNameInfo = ExAllocatePoolWithTag(NonPagedPool,
136 ReturnLength,
137 TAG_SEPA);
138 if (ObjectNameInfo)
139 {
140 /* Query the name again */
141 Status = ObQueryNameString(FileObject,
142 ObjectNameInfo,
143 ReturnLength,
144 &ReturnLength);
145 }
146 }
147
148 /* Check if we got here due to failure */
149 if ((ObjectNameInfo) &&
150 (!(NT_SUCCESS(Status)) || (ReturnLength == sizeof(LocalNameInfo))))
151 {
152 /* First, free any buffer we might've allocated */
153 ASSERT(FALSE);
154 if (ObjectNameInfo) ExFreePool(ObjectNameInfo);
155
156 /* Now allocate a temporary one */
157 ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
158 ObjectNameInfo = ExAllocatePoolWithTag(NonPagedPool,
159 sizeof(OBJECT_NAME_INFORMATION),
160 TAG_SEPA);
161 if (ObjectNameInfo)
162 {
163 /* Clear it */
164 RtlZeroMemory(ObjectNameInfo, ReturnLength);
165 Status = STATUS_SUCCESS;
166 }
167 }
168
169 /* Check if memory allocation failed */
170 if (!ObjectNameInfo) Status = STATUS_NO_MEMORY;
171
172 /* Return the audit name */
173 *AuditInfo = ObjectNameInfo;
174
175 /* Return status */
176 return Status;
177 }
178
179 /**
180 * @brief
181 * Finds the process image name of a specific process.
182 *
183 * @param[in] Process
184 * Process object submitted by the caller, where the image name
185 * is to be located.
186 *
187 * @param[out] ProcessImageName
188 * An output Unicode string structure with the located process
189 * image name.
190 *
191 * @return
192 * Returns STATUS_SUCCESS if process image name has been located
193 * successfully. STATUS_NO_MEMORY is returned if pool allocation
194 * for the image name has failed. A failure NTSTATUS code is
195 * returned otherwise.
196 */
197 NTSTATUS
198 NTAPI
SeLocateProcessImageName(_In_ PEPROCESS Process,_Out_ PUNICODE_STRING * ProcessImageName)199 SeLocateProcessImageName(
200 _In_ PEPROCESS Process,
201 _Out_ PUNICODE_STRING *ProcessImageName)
202 {
203 POBJECT_NAME_INFORMATION AuditName;
204 PUNICODE_STRING ImageName;
205 PFILE_OBJECT FileObject;
206 NTSTATUS Status = STATUS_SUCCESS;
207
208 PAGED_CODE();
209
210 /* Assume failure */
211 *ProcessImageName = NULL;
212
213 /* Check if we have audit info */
214 AuditName = Process->SeAuditProcessCreationInfo.ImageFileName;
215 if (!AuditName)
216 {
217 /* Get the file object */
218 Status = PsReferenceProcessFilePointer(Process, &FileObject);
219 if (!NT_SUCCESS(Status)) return Status;
220
221 /* Initialize the audit structure */
222 Status = SeInitializeProcessAuditName(FileObject, TRUE, &AuditName);
223 if (NT_SUCCESS(Status))
224 {
225 /* Set it */
226 if (InterlockedCompareExchangePointer((PVOID*)&Process->
227 SeAuditProcessCreationInfo.ImageFileName,
228 AuditName,
229 NULL))
230 {
231 /* Someone beat us to it, deallocate our copy */
232 ExFreePool(AuditName);
233 }
234 }
235
236 /* Dereference the file object */
237 ObDereferenceObject(FileObject);
238 if (!NT_SUCCESS(Status)) return Status;
239 }
240
241 /* Get audit info again, now we have it for sure */
242 AuditName = Process->SeAuditProcessCreationInfo.ImageFileName;
243
244 /* Allocate the output string */
245 ImageName = ExAllocatePoolWithTag(NonPagedPool,
246 AuditName->Name.MaximumLength +
247 sizeof(UNICODE_STRING),
248 TAG_SEPA);
249 if (!ImageName) return STATUS_NO_MEMORY;
250
251 /* Make a copy of it */
252 RtlCopyMemory(ImageName,
253 &AuditName->Name,
254 AuditName->Name.MaximumLength + sizeof(UNICODE_STRING));
255
256 /* Fix up the buffer */
257 ImageName->Buffer = (PWSTR)(ImageName + 1);
258
259 /* Return it */
260 *ProcessImageName = ImageName;
261
262 /* Return status */
263 return Status;
264 }
265
266 /**
267 * @brief
268 * Closes an audit alarm event of an object.
269 *
270 * @param[in] SubsystemName
271 * A Unicode string pointing to the name of the subsystem where auditing
272 * alarm event has to be closed.
273 *
274 * @param[in] HandleId
275 * A handle to an ID where such ID represents the identification of the
276 * object where audit alarm is to be closed.
277 *
278 * @param[in] Sid
279 * A SID that represents the user who attempted to close the audit
280 * alarm.
281 *
282 * @return
283 * Nothing.
284 */
285 VOID
286 NTAPI
SepAdtCloseObjectAuditAlarm(_In_ PUNICODE_STRING SubsystemName,_In_ PVOID HandleId,_In_ PSID Sid)287 SepAdtCloseObjectAuditAlarm(
288 _In_ PUNICODE_STRING SubsystemName,
289 _In_ PVOID HandleId,
290 _In_ PSID Sid)
291 {
292 UNIMPLEMENTED;
293 }
294
295 /**
296 * @brief
297 * Performs an audit alarm to a privileged service request.
298 * This is a worker function.
299 *
300 * @param[in] SubjectContext
301 * A security subject context used for the auditing process.
302 *
303 * @param[in] SubsystemName
304 * A Unicode string that represents the name of a subsystem that
305 * actuated the procedure of alarm auditing of a privileged
306 * service.
307 *
308 * @param[in] ServiceName
309 * A Unicode string that represents the name of a privileged
310 * service request for auditing.
311 *
312 * @param[in] Token
313 * An access token.
314 *
315 * @param[in] PrimaryToken
316 * A primary access token.
317 *
318 * @param[in] Privileges
319 * An array set of privileges used to check if the privileged
320 * service does actually have all the required set of privileges
321 * for security access.
322 *
323 * @param[in] AccessGranted
324 * When auditing is done, the function will return TRUE to the caller
325 * if access is granted, FALSE otherwise.
326 *
327 * @return
328 * Nothing.
329 */
330 VOID
331 NTAPI
SepAdtPrivilegedServiceAuditAlarm(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,_In_opt_ PUNICODE_STRING SubsystemName,_In_opt_ PUNICODE_STRING ServiceName,_In_ PTOKEN Token,_In_ PTOKEN PrimaryToken,_In_ PPRIVILEGE_SET Privileges,_In_ BOOLEAN AccessGranted)332 SepAdtPrivilegedServiceAuditAlarm(
333 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
334 _In_opt_ PUNICODE_STRING SubsystemName,
335 _In_opt_ PUNICODE_STRING ServiceName,
336 _In_ PTOKEN Token,
337 _In_ PTOKEN PrimaryToken,
338 _In_ PPRIVILEGE_SET Privileges,
339 _In_ BOOLEAN AccessGranted)
340 {
341 DPRINT("SepAdtPrivilegedServiceAuditAlarm is unimplemented\n");
342 }
343
344 /**
345 * @brief
346 * Performs an audit alarm to a privileged service request.
347 *
348 * @param[in] ServiceName
349 * A Unicode string that represents the name of a privileged
350 * service request for auditing.
351 *
352 * @param[in] SubjectContext
353 * A security subject context used for the auditing process.
354 *
355 * @param[in] PrivilegeSet
356 * An array set of privileges used to check if the privileged
357 * service does actually have all the required set of privileges
358 * for security access.
359 *
360 * @param[in] AccessGranted
361 * When auditing is done, the function will return TRUE to the caller
362 * if access is granted, FALSE otherwise.
363 *
364 * @return
365 * Nothing.
366 */
367 VOID
368 NTAPI
SePrivilegedServiceAuditAlarm(_In_opt_ PUNICODE_STRING ServiceName,_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,_In_ PPRIVILEGE_SET PrivilegeSet,_In_ BOOLEAN AccessGranted)369 SePrivilegedServiceAuditAlarm(
370 _In_opt_ PUNICODE_STRING ServiceName,
371 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
372 _In_ PPRIVILEGE_SET PrivilegeSet,
373 _In_ BOOLEAN AccessGranted)
374 {
375 PTOKEN EffectiveToken;
376 PSID UserSid;
377 PAGED_CODE();
378
379 /* Get the effective token */
380 if (SubjectContext->ClientToken != NULL)
381 EffectiveToken = SubjectContext->ClientToken;
382 else
383 EffectiveToken = SubjectContext->PrimaryToken;
384
385 /* Get the user SID */
386 UserSid = EffectiveToken->UserAndGroups->Sid;
387
388 /* Check if this is the local system SID */
389 if (RtlEqualSid(UserSid, SeLocalSystemSid))
390 {
391 /* Nothing to do */
392 return;
393 }
394
395 /* Check if this is the network service or local service SID */
396 if (RtlEqualSid(UserSid, SeExports->SeNetworkServiceSid) ||
397 RtlEqualSid(UserSid, SeExports->SeLocalServiceSid))
398 {
399 // FIXME: should continue for a certain set of privileges
400 return;
401 }
402
403 /* Call the worker function */
404 SepAdtPrivilegedServiceAuditAlarm(SubjectContext,
405 &SeSubsystemName,
406 ServiceName,
407 SubjectContext->ClientToken,
408 SubjectContext->PrimaryToken,
409 PrivilegeSet,
410 AccessGranted);
411
412 }
413
414 /**
415 * @unimplemented
416 * @brief
417 * Worker function that serves as the main heart and brain of the whole
418 * concept and implementation of auditing in the kernel.
419 *
420 * @param[in] SubsystemName
421 * A Unicode string that represents the name of a subsystem that
422 * actuates the auditing process.
423 *
424 * @param[in] HandleId
425 * A handle to an ID used to identify an object where auditing
426 * is to be done.
427 *
428 * @param[in] SubjectContext
429 * Security subject context.
430 *
431 * @param[in] ObjectTypeName
432 * A Unicode string that represents the name of an object type.
433 *
434 * @param[in] ObjectName
435 * The name of the object.
436 *
437 * @param[in] SecurityDescriptor
438 * A security descriptor with internal security information details
439 * for audit.
440 *
441 * @param[in] PrincipalSelfSid
442 * A principal self user SID.
443 *
444 * @param[in] DesiredAccess
445 * The desired access rights masks requested by the caller.
446 *
447 * @param[in] AuditType
448 * Type of audit to start. This parameter influences how an audit
449 * should be done.
450 *
451 * @param[in] HaveAuditPrivilege
452 * If set to TRUE, the security subject context has the audit privilege thus
453 * it is allowed the ability to perform the audit.
454 *
455 * @param[in] ObjectTypeList
456 * A list of object types.
457 *
458 * @param[in] ObjectTypeListLength
459 * The length size of the list.
460 *
461 * @param[in] GenericMapping
462 * The generic mapping table of access rights used whilst performing auditing
463 * sequence procedure.
464 *
465 * @param[out] GrantedAccessList
466 * This parameter is used to return to the caller a list of actual granted access
467 * rights masks that the audited object has.
468 *
469 * @param[out] AccessStatusList
470 * This parameter is used to return to the caller a list of status return codes.
471 * The function may actually return a single NTSTATUS code if the calling thread
472 * sets UseResultList parameter to FALSE.
473 *
474 * @param[out] GenerateOnClose
475 * Returns TRUE if the function has generated a list of granted access rights and
476 * status codes on termination, FALSE otherwise.
477 *
478 * @param[in] UseResultList
479 * If set to TRUE, the caller wants that the function should only return a single
480 * NTSTATUS code.
481 *
482 * @return
483 * Returns STATUS_SUCCESS if the function has completed the whole internal
484 * auditing procedure mechanism with success.
485 */
486 _Must_inspect_result_
487 static
488 NTSTATUS
SepAccessCheckAndAuditAlarmWorker(_In_ PUNICODE_STRING SubsystemName,_In_opt_ PVOID HandleId,_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,_In_ PUNICODE_STRING ObjectTypeName,_In_ PUNICODE_STRING ObjectName,_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,_In_opt_ PSID PrincipalSelfSid,_In_ ACCESS_MASK DesiredAccess,_In_ AUDIT_EVENT_TYPE AuditType,_In_ BOOLEAN HaveAuditPrivilege,_In_reads_opt_ (ObjectTypeListLength)POBJECT_TYPE_LIST_INTERNAL ObjectTypeList,_In_ ULONG ObjectTypeListLength,_In_ PGENERIC_MAPPING GenericMapping,_Out_writes_ (ObjectTypeListLength)PACCESS_MASK GrantedAccessList,_Out_writes_ (ObjectTypeListLength)PNTSTATUS AccessStatusList,_Out_ PBOOLEAN GenerateOnClose,_In_ BOOLEAN UseResultList)489 SepAccessCheckAndAuditAlarmWorker(
490 _In_ PUNICODE_STRING SubsystemName,
491 _In_opt_ PVOID HandleId,
492 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
493 _In_ PUNICODE_STRING ObjectTypeName,
494 _In_ PUNICODE_STRING ObjectName,
495 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
496 _In_opt_ PSID PrincipalSelfSid,
497 _In_ ACCESS_MASK DesiredAccess,
498 _In_ AUDIT_EVENT_TYPE AuditType,
499 _In_ BOOLEAN HaveAuditPrivilege,
500 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST_INTERNAL ObjectTypeList,
501 _In_ ULONG ObjectTypeListLength,
502 _In_ PGENERIC_MAPPING GenericMapping,
503 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList,
504 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList,
505 _Out_ PBOOLEAN GenerateOnClose,
506 _In_ BOOLEAN UseResultList)
507 {
508 ULONG ResultListLength, i;
509
510 /* Get the length of the result list */
511 ResultListLength = UseResultList ? ObjectTypeListLength : 1;
512
513 /// FIXME: we should do some real work here...
514 UNIMPLEMENTED;
515
516 /// HACK: we just pretend all access is granted!
517 for (i = 0; i < ResultListLength; i++)
518 {
519 GrantedAccessList[i] = DesiredAccess;
520 AccessStatusList[i] = STATUS_SUCCESS;
521 }
522
523 *GenerateOnClose = FALSE;
524
525 return STATUS_SUCCESS;
526 }
527
528 /**
529 * @brief
530 * Performs security auditing, if the specific object can be granted
531 * security access or not.
532 *
533 * @param[in] SubsystemName
534 * A Unicode string that represents the name of a subsystem that
535 * actuates the auditing process.
536 *
537 * @param[in] HandleId
538 * A handle to an ID used to identify an object where auditing
539 * is to be done.
540 *
541 * @param[in] SubjectContext
542 * Security subject context.
543 *
544 * @param[in] ObjectTypeName
545 * A Unicode string that represents the name of an object type.
546 *
547 * @param[in] ObjectName
548 * The name of the object.
549 *
550 * @param[in] SecurityDescriptor
551 * A security descriptor with internal security information details
552 * for audit.
553 *
554 * @param[in] PrincipalSelfSid
555 * A principal self user SID.
556 *
557 * @param[in] DesiredAccess
558 * The desired access rights masks requested by the caller.
559 *
560 * @param[in] AuditType
561 * Type of audit to start. This parameter influences how an audit
562 * should be done.
563 *
564 * @param[in] Flags
565 * Flag bitmask parameter.
566 *
567 * @param[in] HaveAuditPrivilege
568 * If set to TRUE, the security subject context has the audit privilege thus
569 * it is allowed the ability to perform the audit.
570 *
571 * @param[in] ObjectTypeList
572 * A list of object types.
573 *
574 * @param[in] ObjectTypeListLength
575 * The length size of the list.
576 *
577 * @param[in] GenericMapping
578 * The generic mapping table of access rights used whilst performing auditing
579 * sequence procedure.
580 *
581 * @param[out] GrantedAccessList
582 * This parameter is used to return to the caller a list of actual granted access
583 * rights masks that the audited object has.
584 *
585 * @param[out] AccessStatusList
586 * This parameter is used to return to the caller a list of status return codes.
587 * The function may actually return a single NTSTATUS code if the calling thread
588 * sets UseResultList parameter to FALSE.
589 *
590 * @param[out] GenerateOnClose
591 * Returns TRUE if the function has generated a list of granted access rights and
592 * status codes on termination, FALSE otherwise.
593 *
594 * @param[in] UseResultList
595 * If set to TRUE, the caller wants that the function should only return a single
596 * NTSTATUS code.
597 *
598 * @return
599 * Returns STATUS_SUCCESS if the function has completed the whole internal
600 * auditing procedure mechanism with success. STATUS_INVALID_PARAMETER is
601 * returned if one of the parameters do not satisfy the general requirements
602 * by the function. STATUS_INSUFFICIENT_RESOURCES is returned if pool memory
603 * allocation has failed. STATUS_PRIVILEGE_NOT_HELD is returned if the current
604 * security subject context does not have the required audit privilege to actually
605 * perform auditing in the first place. STATUS_INVALID_SECURITY_DESCR is returned
606 * if the security descriptor provided by the caller is not valid, that is, such
607 * descriptor doesn't belong to the main user (owner) and current group.
608 * STATUS_GENERIC_NOT_MAPPED is returned if the access rights masks aren't actually
609 * mapped. A failure NTSTATUS code is returned otherwise.
610 */
611 _Must_inspect_result_
612 NTSTATUS
613 NTAPI
SepAccessCheckAndAuditAlarm(_In_ PUNICODE_STRING SubsystemName,_In_opt_ PVOID HandleId,_In_ PHANDLE ClientTokenHandle,_In_ PUNICODE_STRING ObjectTypeName,_In_ PUNICODE_STRING ObjectName,_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,_In_opt_ PSID PrincipalSelfSid,_In_ ACCESS_MASK DesiredAccess,_In_ AUDIT_EVENT_TYPE AuditType,_In_ ULONG Flags,_In_reads_opt_ (ObjectTypeListLength)POBJECT_TYPE_LIST ObjectTypeList,_In_ ULONG ObjectTypeListLength,_In_ PGENERIC_MAPPING GenericMapping,_Out_writes_ (ObjectTypeListLength)PACCESS_MASK GrantedAccessList,_Out_writes_ (ObjectTypeListLength)PNTSTATUS AccessStatusList,_Out_ PBOOLEAN GenerateOnClose,_In_ BOOLEAN UseResultList)614 SepAccessCheckAndAuditAlarm(
615 _In_ PUNICODE_STRING SubsystemName,
616 _In_opt_ PVOID HandleId,
617 _In_ PHANDLE ClientTokenHandle,
618 _In_ PUNICODE_STRING ObjectTypeName,
619 _In_ PUNICODE_STRING ObjectName,
620 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
621 _In_opt_ PSID PrincipalSelfSid,
622 _In_ ACCESS_MASK DesiredAccess,
623 _In_ AUDIT_EVENT_TYPE AuditType,
624 _In_ ULONG Flags,
625 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
626 _In_ ULONG ObjectTypeListLength,
627 _In_ PGENERIC_MAPPING GenericMapping,
628 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList,
629 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList,
630 _Out_ PBOOLEAN GenerateOnClose,
631 _In_ BOOLEAN UseResultList)
632 {
633 SECURITY_SUBJECT_CONTEXT SubjectContext;
634 ULONG ResultListLength;
635 GENERIC_MAPPING LocalGenericMapping;
636 PTOKEN SubjectContextToken, ClientToken;
637 BOOLEAN AllocatedResultLists;
638 BOOLEAN HaveAuditPrivilege;
639 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor;
640 UNICODE_STRING CapturedSubsystemName, CapturedObjectTypeName, CapturedObjectName;
641 ACCESS_MASK GrantedAccess, *SafeGrantedAccessList;
642 NTSTATUS AccessStatus, *SafeAccessStatusList;
643 PSID CapturedPrincipalSelfSid;
644 POBJECT_TYPE_LIST_INTERNAL CapturedObjectTypeList;
645 ULONG i;
646 BOOLEAN LocalGenerateOnClose;
647 NTSTATUS Status;
648 PAGED_CODE();
649
650 /* Only user mode is supported! */
651 ASSERT(ExGetPreviousMode() != KernelMode);
652
653 /* Start clean */
654 AllocatedResultLists = FALSE;
655 ClientToken = NULL;
656 CapturedSecurityDescriptor = NULL;
657 CapturedSubsystemName.Buffer = NULL;
658 CapturedObjectTypeName.Buffer = NULL;
659 CapturedObjectName.Buffer = NULL;
660 CapturedPrincipalSelfSid = NULL;
661 CapturedObjectTypeList = NULL;
662
663 /* Validate AuditType */
664 if ((AuditType != AuditEventObjectAccess) &&
665 (AuditType != AuditEventDirectoryServiceAccess))
666 {
667 DPRINT1("Invalid audit type: %u\n", AuditType);
668 return STATUS_INVALID_PARAMETER;
669 }
670
671 /* Capture the security subject context */
672 SeCaptureSubjectContext(&SubjectContext);
673
674 /* Did the caller pass a token handle? */
675 if (ClientTokenHandle == NULL)
676 {
677 /* Check if we have a token in the subject context */
678 if (SubjectContext.ClientToken == NULL)
679 {
680 Status = STATUS_NO_IMPERSONATION_TOKEN;
681 DPRINT1("No token\n");
682 goto Cleanup;
683 }
684
685 /* Check if we have a valid impersonation level */
686 if (SubjectContext.ImpersonationLevel < SecurityIdentification)
687 {
688 Status = STATUS_BAD_IMPERSONATION_LEVEL;
689 DPRINT1("Invalid impersonation level 0x%lx\n",
690 SubjectContext.ImpersonationLevel);
691 goto Cleanup;
692 }
693 }
694
695 /* Are we using a result list? */
696 if (UseResultList)
697 {
698 /* The list length equals the object type list length */
699 ResultListLength = ObjectTypeListLength;
700 if ((ResultListLength == 0) || (ResultListLength > 0x1000))
701 {
702 Status = STATUS_INVALID_PARAMETER;
703 DPRINT1("Invalid ResultListLength: 0x%lx\n", ResultListLength);
704 goto Cleanup;
705 }
706
707 /* Allocate a safe buffer from paged pool */
708 SafeGrantedAccessList = ExAllocatePoolWithTag(PagedPool,
709 2 * ResultListLength * sizeof(ULONG),
710 TAG_SEPA);
711 if (SafeGrantedAccessList == NULL)
712 {
713 Status = STATUS_INSUFFICIENT_RESOURCES;
714 DPRINT1("Failed to allocate access lists\n");
715 goto Cleanup;
716 }
717
718 SafeAccessStatusList = (PNTSTATUS)&SafeGrantedAccessList[ResultListLength];
719 AllocatedResultLists = TRUE;
720 }
721 else
722 {
723 /* List length is 1 */
724 ResultListLength = 1;
725 SafeGrantedAccessList = &GrantedAccess;
726 SafeAccessStatusList = &AccessStatus;
727 }
728
729 _SEH2_TRY
730 {
731 /* Probe output buffers */
732 ProbeForWrite(AccessStatusList,
733 ResultListLength * sizeof(*AccessStatusList),
734 sizeof(*AccessStatusList));
735 ProbeForWrite(GrantedAccessList,
736 ResultListLength * sizeof(*GrantedAccessList),
737 sizeof(*GrantedAccessList));
738
739 /* Probe generic mapping and make a local copy */
740 ProbeForRead(GenericMapping, sizeof(*GenericMapping), sizeof(ULONG));
741 LocalGenericMapping = * GenericMapping;
742 }
743 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
744 {
745 Status = _SEH2_GetExceptionCode();
746 DPRINT1("Exception while probing parameters: 0x%lx\n", Status);
747 _SEH2_YIELD(goto Cleanup);
748 }
749 _SEH2_END;
750
751 /* Do we have a client token? */
752 if (ClientTokenHandle != NULL)
753 {
754 /* Reference the client token */
755 Status = ObReferenceObjectByHandle(*ClientTokenHandle,
756 TOKEN_QUERY,
757 SeTokenObjectType,
758 UserMode,
759 (PVOID*)&ClientToken,
760 NULL);
761 if (!NT_SUCCESS(Status))
762 {
763 DPRINT1("Failed to reference token handle %p: %lx\n",
764 *ClientTokenHandle, Status);
765 goto Cleanup;
766 }
767
768 SubjectContextToken = SubjectContext.ClientToken;
769 SubjectContext.ClientToken = ClientToken;
770 }
771
772 /* Check for audit privilege */
773 HaveAuditPrivilege = SeCheckAuditPrivilege(&SubjectContext, UserMode);
774 if (!HaveAuditPrivilege && !(Flags & AUDIT_ALLOW_NO_PRIVILEGE))
775 {
776 DPRINT1("Caller does not have SeAuditPrivilege\n");
777 Status = STATUS_PRIVILEGE_NOT_HELD;
778 goto Cleanup;
779 }
780
781 /* Generic access must already be mapped to non-generic access types! */
782 if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
783 {
784 DPRINT1("Generic access rights requested: 0x%lx\n", DesiredAccess);
785 Status = STATUS_GENERIC_NOT_MAPPED;
786 goto Cleanup;
787 }
788
789 /* Capture the security descriptor */
790 Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
791 UserMode,
792 PagedPool,
793 FALSE,
794 &CapturedSecurityDescriptor);
795 if (!NT_SUCCESS(Status))
796 {
797 DPRINT1("Failed to capture security descriptor!\n");
798 goto Cleanup;
799 }
800
801 /* Validate the Security descriptor */
802 if ((SepGetOwnerFromDescriptor(CapturedSecurityDescriptor) == NULL) ||
803 (SepGetGroupFromDescriptor(CapturedSecurityDescriptor) == NULL))
804 {
805 Status = STATUS_INVALID_SECURITY_DESCR;
806 DPRINT1("Invalid security descriptor\n");
807 goto Cleanup;
808 }
809
810 /* Probe and capture the subsystem name */
811 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName,
812 UserMode,
813 SubsystemName);
814 if (!NT_SUCCESS(Status))
815 {
816 DPRINT1("Failed to capture subsystem name!\n");
817 goto Cleanup;
818 }
819
820 /* Probe and capture the object type name */
821 Status = ProbeAndCaptureUnicodeString(&CapturedObjectTypeName,
822 UserMode,
823 ObjectTypeName);
824 if (!NT_SUCCESS(Status))
825 {
826 DPRINT1("Failed to capture object type name!\n");
827 goto Cleanup;
828 }
829
830 /* Probe and capture the object name */
831 Status = ProbeAndCaptureUnicodeString(&CapturedObjectName,
832 UserMode,
833 ObjectName);
834 if (!NT_SUCCESS(Status))
835 {
836 DPRINT1("Failed to capture object name!\n");
837 goto Cleanup;
838 }
839
840 /* Check if we have a PrincipalSelfSid */
841 if (PrincipalSelfSid != NULL)
842 {
843 /* Capture it */
844 Status = SepCaptureSid(PrincipalSelfSid,
845 UserMode,
846 PagedPool,
847 FALSE,
848 &CapturedPrincipalSelfSid);
849 if (!NT_SUCCESS(Status))
850 {
851 DPRINT1("Failed to capture PrincipalSelfSid!\n");
852 goto Cleanup;
853 }
854 }
855
856 /* Capture the object type list */
857 Status = SeCaptureObjectTypeList(ObjectTypeList,
858 ObjectTypeListLength,
859 UserMode,
860 &CapturedObjectTypeList);
861 if (!NT_SUCCESS(Status))
862 {
863 DPRINT1("Failed to capture object type list!\n");
864 goto Cleanup;
865 }
866
867 /* Call the worker routine with the captured buffers */
868 Status = SepAccessCheckAndAuditAlarmWorker(&CapturedSubsystemName,
869 HandleId,
870 &SubjectContext,
871 &CapturedObjectTypeName,
872 &CapturedObjectName,
873 CapturedSecurityDescriptor,
874 CapturedPrincipalSelfSid,
875 DesiredAccess,
876 AuditType,
877 HaveAuditPrivilege,
878 CapturedObjectTypeList,
879 ObjectTypeListLength,
880 &LocalGenericMapping,
881 SafeGrantedAccessList,
882 SafeAccessStatusList,
883 &LocalGenerateOnClose,
884 UseResultList);
885 if (!NT_SUCCESS(Status))
886 goto Cleanup;
887
888 /* Enter SEH to copy the data back to user mode */
889 _SEH2_TRY
890 {
891 /* Loop all result entries (only 1 when no list was requested) */
892 ASSERT(UseResultList || (ResultListLength == 1));
893 for (i = 0; i < ResultListLength; i++)
894 {
895 AccessStatusList[i] = SafeAccessStatusList[i];
896 GrantedAccessList[i] = SafeGrantedAccessList[i];
897 }
898
899 *GenerateOnClose = LocalGenerateOnClose;
900 }
901 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
902 {
903 Status = _SEH2_GetExceptionCode();
904 DPRINT1("Exception while copying back data: 0x%lx\n", Status);
905 }
906 _SEH2_END;
907
908 Cleanup:
909
910 if (CapturedObjectTypeList != NULL)
911 SeReleaseObjectTypeList(CapturedObjectTypeList, UserMode);
912
913 if (CapturedPrincipalSelfSid != NULL)
914 SepReleaseSid(CapturedPrincipalSelfSid, UserMode, FALSE);
915
916 if (CapturedObjectName.Buffer != NULL)
917 ReleaseCapturedUnicodeString(&CapturedObjectName, UserMode);
918
919 if (CapturedObjectTypeName.Buffer != NULL)
920 ReleaseCapturedUnicodeString(&CapturedObjectTypeName, UserMode);
921
922 if (CapturedSubsystemName.Buffer != NULL)
923 ReleaseCapturedUnicodeString(&CapturedSubsystemName, UserMode);
924
925 if (CapturedSecurityDescriptor != NULL)
926 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor, UserMode, FALSE);
927
928 if (ClientToken != NULL)
929 {
930 ObDereferenceObject(ClientToken);
931 SubjectContext.ClientToken = SubjectContextToken;
932 }
933
934 if (AllocatedResultLists)
935 ExFreePoolWithTag(SafeGrantedAccessList, TAG_SEPA);
936
937 /* Release the security subject context */
938 SeReleaseSubjectContext(&SubjectContext);
939
940 return Status;
941 }
942
943
944 /* PUBLIC FUNCTIONS ***********************************************************/
945
946 /**
947 * @unimplemented
948 * @brief
949 * Performs an audit against a hard link creation.
950 *
951 * @param[in] FileName
952 * A Unicode string that points to the name of the file.
953 *
954 * @param[in] LinkName
955 * A Unicode string that points to a link.
956 *
957 * @param[out] bSuccess
958 * If TRUE, the function has successfully audited
959 * the hard link and security access can be granted,
960 * FALSE otherwise.
961 *
962 * @return
963 * Nothing.
964 */
965 VOID
966 NTAPI
SeAuditHardLinkCreation(_In_ PUNICODE_STRING FileName,_In_ PUNICODE_STRING LinkName,_In_ BOOLEAN bSuccess)967 SeAuditHardLinkCreation(
968 _In_ PUNICODE_STRING FileName,
969 _In_ PUNICODE_STRING LinkName,
970 _In_ BOOLEAN bSuccess)
971 {
972 UNIMPLEMENTED;
973 }
974
975 /**
976 * @unimplemented
977 * @brief
978 * Determines whether auditing against file events is being
979 * done or not.
980 *
981 * @param[in] AccessGranted
982 * If set to TRUE, the access attempt is deemed as successful
983 * otherwise set it to FALSE.
984 *
985 * @param[in] SecurityDescriptor
986 * A security descriptor.
987 *
988 * @return
989 * Returns TRUE if auditing is being currently done, FALSE otherwise.
990 */
991 BOOLEAN
992 NTAPI
SeAuditingFileEvents(_In_ BOOLEAN AccessGranted,_In_ PSECURITY_DESCRIPTOR SecurityDescriptor)993 SeAuditingFileEvents(
994 _In_ BOOLEAN AccessGranted,
995 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor)
996 {
997 UNIMPLEMENTED;
998 return FALSE;
999 }
1000
1001 /**
1002 * @unimplemented
1003 * @brief
1004 * Determines whether auditing against file events with subject context
1005 * is being done or not.
1006 *
1007 * @param[in] AccessGranted
1008 * If set to TRUE, the access attempt is deemed as successful
1009 * otherwise set it to FALSE.
1010 *
1011 * @param[in] SecurityDescriptor
1012 * A security descriptor.
1013 *
1014 * @param[in] SubjectSecurityContext
1015 * If specified, the function will check if security auditing is currently
1016 * being done with this context.
1017 *
1018 * @return
1019 * Returns TRUE if auditing is being currently done, FALSE otherwise.
1020 */
1021 BOOLEAN
1022 NTAPI
SeAuditingFileEventsWithContext(_In_ BOOLEAN AccessGranted,_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,_In_opt_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext)1023 SeAuditingFileEventsWithContext(
1024 _In_ BOOLEAN AccessGranted,
1025 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1026 _In_opt_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext)
1027 {
1028 UNIMPLEMENTED_ONCE;
1029 return FALSE;
1030 }
1031
1032 /**
1033 * @unimplemented
1034 * @brief
1035 * Determines whether auditing against hard links events is being
1036 * done or not.
1037 *
1038 * @param[in] AccessGranted
1039 * If set to TRUE, the access attempt is deemed as successful
1040 * otherwise set it to FALSE.
1041 *
1042 * @param[in] SecurityDescriptor
1043 * A security descriptor.
1044 *
1045 * @return
1046 * Returns TRUE if auditing is being currently done, FALSE otherwise.
1047 */
1048 BOOLEAN
1049 NTAPI
SeAuditingHardLinkEvents(_In_ BOOLEAN AccessGranted,_In_ PSECURITY_DESCRIPTOR SecurityDescriptor)1050 SeAuditingHardLinkEvents(
1051 _In_ BOOLEAN AccessGranted,
1052 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor)
1053 {
1054 UNIMPLEMENTED;
1055 return FALSE;
1056 }
1057
1058 /**
1059 * @unimplemented
1060 * @brief
1061 * Determines whether auditing against hard links events with subject context
1062 * is being done or not.
1063 *
1064 * @param[in] AccessGranted
1065 * If set to TRUE, the access attempt is deemed as successful
1066 * otherwise set it to FALSE.
1067 *
1068 * @param[in] SecurityDescriptor
1069 * A security descriptor.
1070 *
1071 * @param[in] SubjectSecurityContext
1072 * If specified, the function will check if security auditing is currently
1073 * being done with this context.
1074 *
1075 * @return
1076 * Returns TRUE if auditing is being currently done, FALSE otherwise.
1077 */
1078 BOOLEAN
1079 NTAPI
SeAuditingHardLinkEventsWithContext(_In_ BOOLEAN AccessGranted,_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,_In_opt_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext)1080 SeAuditingHardLinkEventsWithContext(
1081 _In_ BOOLEAN AccessGranted,
1082 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1083 _In_opt_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext)
1084 {
1085 UNIMPLEMENTED;
1086 return FALSE;
1087 }
1088
1089 /**
1090 * @unimplemented
1091 * @brief
1092 * Determines whether auditing against files or global events with
1093 * subject context is being done or not.
1094 *
1095 * @param[in] AccessGranted
1096 * If set to TRUE, the access attempt is deemed as successful
1097 * otherwise set it to FALSE.
1098 *
1099 * @param[in] SecurityDescriptor
1100 * A security descriptor.
1101 *
1102 * @param[in] SubjectSecurityContext
1103 * If specified, the function will check if security auditing is currently
1104 * being done with this context.
1105 *
1106 * @return
1107 * Returns TRUE if auditing is being currently done, FALSE otherwise.
1108 */
1109 BOOLEAN
1110 NTAPI
SeAuditingFileOrGlobalEvents(_In_ BOOLEAN AccessGranted,_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,_In_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext)1111 SeAuditingFileOrGlobalEvents(
1112 _In_ BOOLEAN AccessGranted,
1113 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1114 _In_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext)
1115 {
1116 UNIMPLEMENTED;
1117 return FALSE;
1118 }
1119
1120 /**
1121 * @unimplemented
1122 * @brief
1123 * Closes an alarm audit of an object.
1124 *
1125 * @param[in] Object
1126 * An arbitrary pointer data that points to the object.
1127 *
1128 * @param[in] Handle
1129 * A handle of the said object.
1130 *
1131 * @param[in] PerformAction
1132 * Set this to TRUE to perform any auxiliary action, otherwise
1133 * set to FALSE.
1134 *
1135 * @return
1136 * Nothing.
1137 */
1138 VOID
1139 NTAPI
SeCloseObjectAuditAlarm(_In_ PVOID Object,_In_ HANDLE Handle,_In_ BOOLEAN PerformAction)1140 SeCloseObjectAuditAlarm(
1141 _In_ PVOID Object,
1142 _In_ HANDLE Handle,
1143 _In_ BOOLEAN PerformAction)
1144 {
1145 UNIMPLEMENTED;
1146 }
1147
1148 /**
1149 * @unimplemented
1150 * @brief
1151 * Deletes an alarm audit of an object.
1152 *
1153 * @param[in] Object
1154 * An arbitrary pointer data that points to the object.
1155 *
1156 * @param[in] Handle
1157 * A handle of the said object.
1158 *
1159 * @return
1160 * Nothing.
1161 */
1162 VOID NTAPI
SeDeleteObjectAuditAlarm(_In_ PVOID Object,_In_ HANDLE Handle)1163 SeDeleteObjectAuditAlarm(
1164 _In_ PVOID Object,
1165 _In_ HANDLE Handle)
1166 {
1167 UNIMPLEMENTED;
1168 }
1169
1170 /**
1171 * @unimplemented
1172 * @brief
1173 * Creates an audit with alarm notification of an object
1174 * that is being opened.
1175 *
1176 * @param[in] ObjectTypeName
1177 * A Unicode string that points to the object type name.
1178 *
1179 * @param[in] Object
1180 * If specified, the function will use this parameter to
1181 * directly open the object.
1182 *
1183 * @param[in] AbsoluteObjectName
1184 * If specified, the function will use this parameter to
1185 * directly open the object through the absolute name
1186 * of the object.
1187 *
1188 * @param[in] SecurityDescriptor
1189 * A security descriptor.
1190 *
1191 * @param[in] AccessState
1192 * An access state right mask when opening the object.
1193 *
1194 * @param[in] ObjectCreated
1195 * Set this to TRUE if the object has been fully created,
1196 * FALSE otherwise.
1197 *
1198 * @param[in] AccessGranted
1199 * Set this to TRUE if access was deemed as granted.
1200 *
1201 * @param[in] AccessMode
1202 * Processor level access mode.
1203 *
1204 * @param[out] GenerateOnClose
1205 * A boolean flag returned to the caller once audit generation procedure
1206 * finishes.
1207 *
1208 * @return
1209 * Nothing.
1210 */
1211 VOID
1212 NTAPI
SeOpenObjectAuditAlarm(_In_ PUNICODE_STRING ObjectTypeName,_In_opt_ PVOID Object,_In_opt_ PUNICODE_STRING AbsoluteObjectName,_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,_In_ PACCESS_STATE AccessState,_In_ BOOLEAN ObjectCreated,_In_ BOOLEAN AccessGranted,_In_ KPROCESSOR_MODE AccessMode,_Out_ PBOOLEAN GenerateOnClose)1213 SeOpenObjectAuditAlarm(
1214 _In_ PUNICODE_STRING ObjectTypeName,
1215 _In_opt_ PVOID Object,
1216 _In_opt_ PUNICODE_STRING AbsoluteObjectName,
1217 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1218 _In_ PACCESS_STATE AccessState,
1219 _In_ BOOLEAN ObjectCreated,
1220 _In_ BOOLEAN AccessGranted,
1221 _In_ KPROCESSOR_MODE AccessMode,
1222 _Out_ PBOOLEAN GenerateOnClose)
1223 {
1224 PAGED_CODE();
1225
1226 /* Audits aren't done on kernel-mode access */
1227 if (AccessMode == KernelMode) return;
1228
1229 /* Otherwise, unimplemented! */
1230 //UNIMPLEMENTED;
1231 return;
1232 }
1233
1234 /**
1235 * @unimplemented
1236 * @brief
1237 * Creates an audit with alarm notification of an object
1238 * that is being opened for deletion.
1239 *
1240 * @param[in] ObjectTypeName
1241 * A Unicode string that points to the object type name.
1242 *
1243 * @param[in] Object
1244 * If specified, the function will use this parameter to
1245 * directly open the object.
1246 *
1247 * @param[in] AbsoluteObjectName
1248 * If specified, the function will use this parameter to
1249 * directly open the object through the absolute name
1250 * of the object.
1251 *
1252 * @param[in] SecurityDescriptor
1253 * A security descriptor.
1254 *
1255 * @param[in] AccessState
1256 * An access state right mask when opening the object.
1257 *
1258 * @param[in] ObjectCreated
1259 * Set this to TRUE if the object has been fully created,
1260 * FALSE otherwise.
1261 *
1262 * @param[in] AccessGranted
1263 * Set this to TRUE if access was deemed as granted.
1264 *
1265 * @param[in] AccessMode
1266 * Processor level access mode.
1267 *
1268 * @param[out] GenerateOnClose
1269 * A boolean flag returned to the caller once audit generation procedure
1270 * finishes.
1271 *
1272 * @return
1273 * Nothing.
1274 */
1275 VOID NTAPI
SeOpenObjectForDeleteAuditAlarm(_In_ PUNICODE_STRING ObjectTypeName,_In_opt_ PVOID Object,_In_opt_ PUNICODE_STRING AbsoluteObjectName,_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,_In_ PACCESS_STATE AccessState,_In_ BOOLEAN ObjectCreated,_In_ BOOLEAN AccessGranted,_In_ KPROCESSOR_MODE AccessMode,_Out_ PBOOLEAN GenerateOnClose)1276 SeOpenObjectForDeleteAuditAlarm(
1277 _In_ PUNICODE_STRING ObjectTypeName,
1278 _In_opt_ PVOID Object,
1279 _In_opt_ PUNICODE_STRING AbsoluteObjectName,
1280 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1281 _In_ PACCESS_STATE AccessState,
1282 _In_ BOOLEAN ObjectCreated,
1283 _In_ BOOLEAN AccessGranted,
1284 _In_ KPROCESSOR_MODE AccessMode,
1285 _Out_ PBOOLEAN GenerateOnClose)
1286 {
1287 UNIMPLEMENTED;
1288 }
1289
1290 /**
1291 * @unimplemented
1292 * @brief
1293 * Raises an audit with alarm notification message
1294 * when an object tries to acquire this privilege.
1295 *
1296 * @param[in] Handle
1297 * A handle to an object.
1298 *
1299 * @param[in] SubjectContext
1300 * The security subject context for auditing.
1301 *
1302 * @param[in] DesiredAccess
1303 * The desired right access masks requested by the caller.
1304 *
1305 * @param[in] Privileges
1306 * An array set of privileges for auditing.
1307 *
1308 * @param[out] AccessGranted
1309 * When the auditing procedure routine ends, it returns TRUE to the
1310 * caller if the object has the required privileges for access,
1311 * FALSE otherwise.
1312 *
1313 * @param[in] CurrentMode
1314 * Processor level access mode.
1315 *
1316 * @return
1317 * Nothing.
1318 */
1319 VOID
1320 NTAPI
SePrivilegeObjectAuditAlarm(_In_ HANDLE Handle,_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,_In_ ACCESS_MASK DesiredAccess,_In_ PPRIVILEGE_SET Privileges,_In_ BOOLEAN AccessGranted,_In_ KPROCESSOR_MODE CurrentMode)1321 SePrivilegeObjectAuditAlarm(
1322 _In_ HANDLE Handle,
1323 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
1324 _In_ ACCESS_MASK DesiredAccess,
1325 _In_ PPRIVILEGE_SET Privileges,
1326 _In_ BOOLEAN AccessGranted,
1327 _In_ KPROCESSOR_MODE CurrentMode)
1328 {
1329 UNIMPLEMENTED;
1330 }
1331
1332 /* SYSTEM CALLS ***************************************************************/
1333
1334 /**
1335 * @brief
1336 * Raises an alarm audit message when an object is about
1337 * to be closed.
1338 *
1339 * @param[in] SubsystemName
1340 * A Unicode string that points to the name of the subsystem.
1341 *
1342 * @param[in] HandleId
1343 * A handle of an ID used for identification instance for auditing.
1344 *
1345 * @param[in] GenerateOnClose
1346 * A boolean value previously created by the "open" equivalent of this
1347 * function. If the caller explicitly sets this to FALSE, the function
1348 * assumes that the object is not opened.
1349 *
1350 * @return
1351 * Returns STATUS_SUCCESS if all the operations have completed successfully.
1352 * STATUS_PRIVILEGE_NOT_HELD is returned if the security subject context
1353 * does not have the audit privilege to actually begin auditing procedures
1354 * in the first place.
1355 */
1356 NTSTATUS
1357 NTAPI
NtCloseObjectAuditAlarm(_In_ PUNICODE_STRING SubsystemName,_In_ PVOID HandleId,_In_ BOOLEAN GenerateOnClose)1358 NtCloseObjectAuditAlarm(
1359 _In_ PUNICODE_STRING SubsystemName,
1360 _In_ PVOID HandleId,
1361 _In_ BOOLEAN GenerateOnClose)
1362 {
1363 SECURITY_SUBJECT_CONTEXT SubjectContext;
1364 UNICODE_STRING CapturedSubsystemName;
1365 KPROCESSOR_MODE PreviousMode;
1366 BOOLEAN UseImpersonationToken;
1367 PETHREAD CurrentThread;
1368 BOOLEAN CopyOnOpen, EffectiveOnly;
1369 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1370 NTSTATUS Status;
1371 PTOKEN Token;
1372 PAGED_CODE();
1373
1374 /* Get the previous mode (only user mode is supported!) */
1375 PreviousMode = ExGetPreviousMode();
1376 ASSERT(PreviousMode != KernelMode);
1377
1378 /* Do we even need to do anything? */
1379 if (!GenerateOnClose)
1380 {
1381 /* Nothing to do, return success */
1382 return STATUS_SUCCESS;
1383 }
1384
1385 /* Capture the security subject context */
1386 SeCaptureSubjectContext(&SubjectContext);
1387
1388 /* Check for audit privilege */
1389 if (!SeCheckAuditPrivilege(&SubjectContext, PreviousMode))
1390 {
1391 DPRINT1("Caller does not have SeAuditPrivilege\n");
1392 Status = STATUS_PRIVILEGE_NOT_HELD;
1393 goto Cleanup;
1394 }
1395
1396 /* Probe and capture the subsystem name */
1397 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName,
1398 PreviousMode,
1399 SubsystemName);
1400 if (!NT_SUCCESS(Status))
1401 {
1402 DPRINT1("Failed to capture subsystem name!\n");
1403 goto Cleanup;
1404 }
1405
1406 /* Get the current thread and check if it's impersonating */
1407 CurrentThread = PsGetCurrentThread();
1408 if (PsIsThreadImpersonating(CurrentThread))
1409 {
1410 /* Get the impersonation token */
1411 Token = PsReferenceImpersonationToken(CurrentThread,
1412 &CopyOnOpen,
1413 &EffectiveOnly,
1414 &ImpersonationLevel);
1415 UseImpersonationToken = TRUE;
1416 }
1417 else
1418 {
1419 /* Get the primary token */
1420 Token = PsReferencePrimaryToken(PsGetCurrentProcess());
1421 UseImpersonationToken = FALSE;
1422 }
1423
1424 /* Call the internal function */
1425 SepAdtCloseObjectAuditAlarm(&CapturedSubsystemName,
1426 HandleId,
1427 Token->UserAndGroups->Sid);
1428
1429 /* Release the captured subsystem name */
1430 ReleaseCapturedUnicodeString(&CapturedSubsystemName, PreviousMode);
1431
1432 /* Check what token we used */
1433 if (UseImpersonationToken)
1434 {
1435 /* Release impersonation token */
1436 PsDereferenceImpersonationToken(Token);
1437 }
1438 else
1439 {
1440 /* Release primary token */
1441 PsDereferencePrimaryToken(Token);
1442 }
1443
1444 Status = STATUS_SUCCESS;
1445
1446 Cleanup:
1447
1448 /* Release the security subject context */
1449 SeReleaseSubjectContext(&SubjectContext);
1450
1451 return Status;
1452 }
1453
1454 /**
1455 * @unimplemented
1456 * @brief
1457 * Raises an alarm audit message when an object is about
1458 * to be deleted.
1459 *
1460 * @param[in] SubsystemName
1461 * A Unicode string that points to the name of the subsystem.
1462 *
1463 * @param[in] HandleId
1464 * A handle of an ID used for identification instance for auditing.
1465 *
1466 * @param[in] GenerateOnClose
1467 * A boolean value previously created by the "open" equivalent of this
1468 * function. If the caller explicitly sets this to FALSE, the function
1469 * assumes that the object is not opened.
1470 *
1471 * @return
1472 * To be added...
1473 */
1474 NTSTATUS NTAPI
NtDeleteObjectAuditAlarm(_In_ PUNICODE_STRING SubsystemName,_In_ PVOID HandleId,_In_ BOOLEAN GenerateOnClose)1475 NtDeleteObjectAuditAlarm(
1476 _In_ PUNICODE_STRING SubsystemName,
1477 _In_ PVOID HandleId,
1478 _In_ BOOLEAN GenerateOnClose)
1479 {
1480 UNIMPLEMENTED;
1481 return STATUS_NOT_IMPLEMENTED;
1482 }
1483
1484 /**
1485 * @unimplemented
1486 * @brief
1487 * Raises an alarm audit message when an object is about
1488 * to be opened.
1489 *
1490 * @param[in] SubjectContext
1491 * A security subject context for auditing.
1492 *
1493 * @param[in] SubsystemName
1494 * A Unicode string that points to a name of the subsystem.
1495 *
1496 * @param[in] HandleId
1497 * A handle to an ID used for identification instance for auditing.
1498 *
1499 * @param[in] ObjectTypeName
1500 * A Unicode string that points to an object type name.
1501 *
1502 * @param[in] ObjectName
1503 * The name of the object.
1504 *
1505 * @param[in] SecurityDescriptor
1506 * A security descriptor.
1507 *
1508 * @param[in] ClientToken
1509 * A client access token, representing the client we want to impersonate.
1510 *
1511 * @param[in] DesiredAccess
1512 * The desired access rights masks requested by the caller.
1513 *
1514 * @param[in] GrantedAccess
1515 * The granted access mask rights.
1516 *
1517 * @param[in] Privileges
1518 * If specified, the function will use this set of privileges to audit.
1519 *
1520 * @param[in] ObjectCreation
1521 * Set this to TRUE if the object has just been created.
1522 *
1523 * @param[in] AccessGranted
1524 * Set this to TRUE if the access attempt was deemed as granted.
1525 *
1526 * @param[out] GenerateOnClose
1527 * A boolean flag returned to the caller once audit generation procedure
1528 * finishes.
1529 *
1530 * @return
1531 * Nothing.
1532 */
1533 VOID
1534 NTAPI
SepOpenObjectAuditAlarm(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,_In_ PUNICODE_STRING SubsystemName,_In_opt_ PVOID HandleId,_In_ PUNICODE_STRING ObjectTypeName,_In_ PUNICODE_STRING ObjectName,_In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor,_In_ PTOKEN ClientToken,_In_ ACCESS_MASK DesiredAccess,_In_ ACCESS_MASK GrantedAccess,_In_opt_ PPRIVILEGE_SET Privileges,_In_ BOOLEAN ObjectCreation,_In_ BOOLEAN AccessGranted,_Out_ PBOOLEAN GenerateOnClose)1535 SepOpenObjectAuditAlarm(
1536 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
1537 _In_ PUNICODE_STRING SubsystemName,
1538 _In_opt_ PVOID HandleId,
1539 _In_ PUNICODE_STRING ObjectTypeName,
1540 _In_ PUNICODE_STRING ObjectName,
1541 _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1542 _In_ PTOKEN ClientToken,
1543 _In_ ACCESS_MASK DesiredAccess,
1544 _In_ ACCESS_MASK GrantedAccess,
1545 _In_opt_ PPRIVILEGE_SET Privileges,
1546 _In_ BOOLEAN ObjectCreation,
1547 _In_ BOOLEAN AccessGranted,
1548 _Out_ PBOOLEAN GenerateOnClose)
1549 {
1550 DBG_UNREFERENCED_PARAMETER(SubjectContext);
1551 DBG_UNREFERENCED_PARAMETER(SubsystemName);
1552 DBG_UNREFERENCED_PARAMETER(HandleId);
1553 DBG_UNREFERENCED_PARAMETER(ObjectTypeName);
1554 DBG_UNREFERENCED_PARAMETER(ObjectName);
1555 DBG_UNREFERENCED_PARAMETER(SecurityDescriptor);
1556 DBG_UNREFERENCED_PARAMETER(ClientToken);
1557 DBG_UNREFERENCED_PARAMETER(DesiredAccess);
1558 DBG_UNREFERENCED_PARAMETER(GrantedAccess);
1559 DBG_UNREFERENCED_PARAMETER(Privileges);
1560 DBG_UNREFERENCED_PARAMETER(ObjectCreation);
1561 DBG_UNREFERENCED_PARAMETER(AccessGranted);
1562 UNIMPLEMENTED;
1563 *GenerateOnClose = FALSE;
1564 }
1565
1566 /**
1567 * @brief
1568 * Raises an alarm audit message when an object is about
1569 * to be opened.
1570 *
1571 * @param[in] SubsystemName
1572 * A Unicode string that points to a name of the subsystem.
1573 *
1574 * @param[in] HandleId
1575 * A handle to an ID used for identification instance for auditing.
1576 *
1577 * @param[in] ObjectTypeName
1578 * A Unicode string that points to an object type name.
1579 *
1580 * @param[in] ObjectName
1581 * The name of the object.
1582 *
1583 * @param[in] SecurityDescriptor
1584 * A security descriptor.
1585 *
1586 * @param[in] ClientTokenHandle
1587 * A handle to a client access token.
1588 *
1589 * @param[in] DesiredAccess
1590 * The desired access rights masks requested by the caller.
1591 *
1592 * @param[in] GrantedAccess
1593 * The granted access mask rights.
1594 *
1595 * @param[in] PrivilegeSet
1596 * If specified, the function will use this set of privileges to audit.
1597 *
1598 * @param[in] ObjectCreation
1599 * Set this to TRUE if the object has just been created.
1600 *
1601 * @param[in] AccessGranted
1602 * Set this to TRUE if the access attempt was deemed as granted.
1603 *
1604 * @param[out] GenerateOnClose
1605 * A boolean flag returned to the caller once audit generation procedure
1606 * finishes.
1607 *
1608 * @return
1609 * Returns STATUS_SUCCESS if all the operations have been completed successfully.
1610 * STATUS_PRIVILEGE_NOT_HELD is returned if the given subject context does not
1611 * hold the required audit privilege to actually begin auditing in the first place.
1612 * STATUS_BAD_IMPERSONATION_LEVEL is returned if the security impersonation level
1613 * of the client token is not on par with the impersonation level that alllows
1614 * impersonation. STATUS_INVALID_PARAMETER is returned if the caller has
1615 * submitted a bogus set of privileges as such array set exceeds the maximum
1616 * count of privileges that the kernel can accept. A failure NTSTATUS code
1617 * is returned otherwise.
1618 */
1619 __kernel_entry
1620 NTSTATUS
1621 NTAPI
NtOpenObjectAuditAlarm(_In_ PUNICODE_STRING SubsystemName,_In_opt_ PVOID HandleId,_In_ PUNICODE_STRING ObjectTypeName,_In_ PUNICODE_STRING ObjectName,_In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor,_In_ HANDLE ClientTokenHandle,_In_ ACCESS_MASK DesiredAccess,_In_ ACCESS_MASK GrantedAccess,_In_opt_ PPRIVILEGE_SET PrivilegeSet,_In_ BOOLEAN ObjectCreation,_In_ BOOLEAN AccessGranted,_Out_ PBOOLEAN GenerateOnClose)1622 NtOpenObjectAuditAlarm(
1623 _In_ PUNICODE_STRING SubsystemName,
1624 _In_opt_ PVOID HandleId,
1625 _In_ PUNICODE_STRING ObjectTypeName,
1626 _In_ PUNICODE_STRING ObjectName,
1627 _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1628 _In_ HANDLE ClientTokenHandle,
1629 _In_ ACCESS_MASK DesiredAccess,
1630 _In_ ACCESS_MASK GrantedAccess,
1631 _In_opt_ PPRIVILEGE_SET PrivilegeSet,
1632 _In_ BOOLEAN ObjectCreation,
1633 _In_ BOOLEAN AccessGranted,
1634 _Out_ PBOOLEAN GenerateOnClose)
1635 {
1636 PTOKEN ClientToken;
1637 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor;
1638 UNICODE_STRING CapturedSubsystemName, CapturedObjectTypeName, CapturedObjectName;
1639 ULONG PrivilegeCount, PrivilegeSetSize;
1640 volatile PPRIVILEGE_SET CapturedPrivilegeSet;
1641 BOOLEAN LocalGenerateOnClose;
1642 PVOID CapturedHandleId;
1643 SECURITY_SUBJECT_CONTEXT SubjectContext;
1644 NTSTATUS Status;
1645 PAGED_CODE();
1646
1647 /* Only user mode is supported! */
1648 ASSERT(ExGetPreviousMode() != KernelMode);
1649
1650 /* Start clean */
1651 ClientToken = NULL;
1652 CapturedSecurityDescriptor = NULL;
1653 CapturedPrivilegeSet = NULL;
1654 CapturedSubsystemName.Buffer = NULL;
1655 CapturedObjectTypeName.Buffer = NULL;
1656 CapturedObjectName.Buffer = NULL;
1657
1658 /* Reference the client token */
1659 Status = ObReferenceObjectByHandle(ClientTokenHandle,
1660 TOKEN_QUERY,
1661 SeTokenObjectType,
1662 UserMode,
1663 (PVOID*)&ClientToken,
1664 NULL);
1665 if (!NT_SUCCESS(Status))
1666 {
1667 DPRINT1("Failed to reference token handle %p: %lx\n",
1668 ClientTokenHandle, Status);
1669 return Status;
1670 }
1671
1672 /* Capture the security subject context */
1673 SeCaptureSubjectContext(&SubjectContext);
1674
1675 /* Validate the token's impersonation level */
1676 if ((ClientToken->TokenType == TokenImpersonation) &&
1677 (ClientToken->ImpersonationLevel < SecurityIdentification))
1678 {
1679 DPRINT1("Invalid impersonation level (%u)\n", ClientToken->ImpersonationLevel);
1680 Status = STATUS_BAD_IMPERSONATION_LEVEL;
1681 goto Cleanup;
1682 }
1683
1684 /* Check for audit privilege */
1685 if (!SeCheckAuditPrivilege(&SubjectContext, UserMode))
1686 {
1687 DPRINT1("Caller does not have SeAuditPrivilege\n");
1688 Status = STATUS_PRIVILEGE_NOT_HELD;
1689 goto Cleanup;
1690 }
1691
1692 /* Check for NULL SecurityDescriptor */
1693 if (SecurityDescriptor == NULL)
1694 {
1695 /* Nothing to do */
1696 Status = STATUS_SUCCESS;
1697 goto Cleanup;
1698 }
1699
1700 /* Capture the security descriptor */
1701 Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
1702 UserMode,
1703 PagedPool,
1704 FALSE,
1705 &CapturedSecurityDescriptor);
1706 if (!NT_SUCCESS(Status))
1707 {
1708 DPRINT1("Failed to capture security descriptor!\n");
1709 goto Cleanup;
1710 }
1711
1712 _SEH2_TRY
1713 {
1714 /* Check if we have a privilege set */
1715 if (PrivilegeSet != NULL)
1716 {
1717 /* Probe the basic privilege set structure */
1718 ProbeForRead(PrivilegeSet, sizeof(PRIVILEGE_SET), sizeof(ULONG));
1719
1720 /* Validate privilege count */
1721 PrivilegeCount = PrivilegeSet->PrivilegeCount;
1722 if (PrivilegeCount > SEP_PRIVILEGE_SET_MAX_COUNT)
1723 {
1724 Status = STATUS_INVALID_PARAMETER;
1725 _SEH2_YIELD(goto Cleanup);
1726 }
1727
1728 /* Calculate the size of the PrivilegeSet structure */
1729 PrivilegeSetSize = FIELD_OFFSET(PRIVILEGE_SET, Privilege[PrivilegeCount]);
1730
1731 /* Probe the whole structure */
1732 ProbeForRead(PrivilegeSet, PrivilegeSetSize, sizeof(ULONG));
1733
1734 /* Allocate a temp buffer */
1735 CapturedPrivilegeSet = ExAllocatePoolWithTag(PagedPool,
1736 PrivilegeSetSize,
1737 TAG_PRIVILEGE_SET);
1738 if (CapturedPrivilegeSet == NULL)
1739 {
1740 DPRINT1("Failed to allocate %u bytes\n", PrivilegeSetSize);
1741 Status = STATUS_INSUFFICIENT_RESOURCES;
1742 _SEH2_YIELD(goto Cleanup);
1743 }
1744
1745 /* Copy the privileges */
1746 RtlCopyMemory(CapturedPrivilegeSet, PrivilegeSet, PrivilegeSetSize);
1747 }
1748
1749 if (HandleId != NULL)
1750 {
1751 ProbeForRead(HandleId, sizeof(PVOID), sizeof(PVOID));
1752 CapturedHandleId = *(PVOID*)HandleId;
1753 }
1754
1755 ProbeForWrite(GenerateOnClose, sizeof(BOOLEAN), sizeof(BOOLEAN));
1756 }
1757 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1758 {
1759 Status = _SEH2_GetExceptionCode();
1760 DPRINT1("Exception while probing parameters: 0x%lx\n", Status);
1761 _SEH2_YIELD(goto Cleanup);
1762 }
1763 _SEH2_END;
1764
1765 /* Probe and capture the subsystem name */
1766 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName,
1767 UserMode,
1768 SubsystemName);
1769 if (!NT_SUCCESS(Status))
1770 {
1771 DPRINT1("Failed to capture subsystem name!\n");
1772 goto Cleanup;
1773 }
1774
1775 /* Probe and capture the object type name */
1776 Status = ProbeAndCaptureUnicodeString(&CapturedObjectTypeName,
1777 UserMode,
1778 ObjectTypeName);
1779 if (!NT_SUCCESS(Status))
1780 {
1781 DPRINT1("Failed to capture object type name!\n");
1782 goto Cleanup;
1783 }
1784
1785 /* Probe and capture the object name */
1786 Status = ProbeAndCaptureUnicodeString(&CapturedObjectName,
1787 UserMode,
1788 ObjectName);
1789 if (!NT_SUCCESS(Status))
1790 {
1791 DPRINT1("Failed to capture object name!\n");
1792 goto Cleanup;
1793 }
1794
1795 /* Call the internal function */
1796 SepOpenObjectAuditAlarm(&SubjectContext,
1797 &CapturedSubsystemName,
1798 CapturedHandleId,
1799 &CapturedObjectTypeName,
1800 &CapturedObjectName,
1801 CapturedSecurityDescriptor,
1802 ClientToken,
1803 DesiredAccess,
1804 GrantedAccess,
1805 CapturedPrivilegeSet,
1806 ObjectCreation,
1807 AccessGranted,
1808 &LocalGenerateOnClose);
1809
1810 Status = STATUS_SUCCESS;
1811
1812 /* Enter SEH to copy the data back to user mode */
1813 _SEH2_TRY
1814 {
1815 *GenerateOnClose = LocalGenerateOnClose;
1816 }
1817 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1818 {
1819 Status = _SEH2_GetExceptionCode();
1820 DPRINT1("Exception while copying back data: 0x%lx\n", Status);
1821 }
1822 _SEH2_END;
1823
1824 Cleanup:
1825
1826 if (CapturedObjectName.Buffer != NULL)
1827 ReleaseCapturedUnicodeString(&CapturedObjectName, UserMode);
1828
1829 if (CapturedObjectTypeName.Buffer != NULL)
1830 ReleaseCapturedUnicodeString(&CapturedObjectTypeName, UserMode);
1831
1832 if (CapturedSubsystemName.Buffer != NULL)
1833 ReleaseCapturedUnicodeString(&CapturedSubsystemName, UserMode);
1834
1835 if (CapturedSecurityDescriptor != NULL)
1836 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor, UserMode, FALSE);
1837
1838 if (CapturedPrivilegeSet != NULL)
1839 ExFreePoolWithTag(CapturedPrivilegeSet, TAG_PRIVILEGE_SET);
1840
1841 /* Release the security subject context */
1842 SeReleaseSubjectContext(&SubjectContext);
1843
1844 ObDereferenceObject(ClientToken);
1845
1846 return Status;
1847 }
1848
1849 /**
1850 * @brief
1851 * Raises an alarm audit message when a caller attempts to request
1852 * a privileged service call.
1853 *
1854 * @param[in] SubsystemName
1855 * A Unicode string that points to a name of the subsystem.
1856 *
1857 * @param[in] ServiceName
1858 * A Unicode string that points to a name of the privileged service.
1859 *
1860 * @param[in] ClientTokenHandle
1861 * A handle to a client access token.
1862 *
1863 * @param[in] Privileges
1864 * An array set of privileges.
1865 *
1866 * @param[in] AccessGranted
1867 * Set this to TRUE if the access attempt was deemed as granted.
1868 *
1869 * @return
1870 * Returns STATUS_SUCCESS if all the operations have been completed successfully.
1871 * STATUS_PRIVILEGE_NOT_HELD is returned if the given subject context does not
1872 * hold the required audit privilege to actually begin auditing in the first place.
1873 * STATUS_BAD_IMPERSONATION_LEVEL is returned if the security impersonation level
1874 * of the client token is not on par with the impersonation level that alllows
1875 * impersonation. STATUS_INVALID_PARAMETER is returned if the caller has
1876 * submitted a bogus set of privileges as such array set exceeds the maximum
1877 * count of privileges that the kernel can accept. A failure NTSTATUS code
1878 * is returned otherwise.
1879 */
1880 __kernel_entry
1881 NTSTATUS
1882 NTAPI
NtPrivilegedServiceAuditAlarm(_In_opt_ PUNICODE_STRING SubsystemName,_In_opt_ PUNICODE_STRING ServiceName,_In_ HANDLE ClientTokenHandle,_In_ PPRIVILEGE_SET Privileges,_In_ BOOLEAN AccessGranted)1883 NtPrivilegedServiceAuditAlarm(
1884 _In_opt_ PUNICODE_STRING SubsystemName,
1885 _In_opt_ PUNICODE_STRING ServiceName,
1886 _In_ HANDLE ClientTokenHandle,
1887 _In_ PPRIVILEGE_SET Privileges,
1888 _In_ BOOLEAN AccessGranted)
1889 {
1890 KPROCESSOR_MODE PreviousMode;
1891 PTOKEN ClientToken;
1892 volatile PPRIVILEGE_SET CapturedPrivileges = NULL;
1893 UNICODE_STRING CapturedSubsystemName;
1894 UNICODE_STRING CapturedServiceName;
1895 ULONG PrivilegeCount, PrivilegesSize;
1896 SECURITY_SUBJECT_CONTEXT SubjectContext;
1897 NTSTATUS Status;
1898 PAGED_CODE();
1899
1900 /* Get the previous mode (only user mode is supported!) */
1901 PreviousMode = ExGetPreviousMode();
1902 ASSERT(PreviousMode != KernelMode);
1903
1904 CapturedSubsystemName.Buffer = NULL;
1905 CapturedServiceName.Buffer = NULL;
1906
1907 /* Reference the client token */
1908 Status = ObReferenceObjectByHandle(ClientTokenHandle,
1909 TOKEN_QUERY,
1910 SeTokenObjectType,
1911 PreviousMode,
1912 (PVOID*)&ClientToken,
1913 NULL);
1914 if (!NT_SUCCESS(Status))
1915 {
1916 DPRINT1("Failed to reference client token: 0x%lx\n", Status);
1917 return Status;
1918 }
1919
1920 /* Validate the token's impersonation level */
1921 if ((ClientToken->TokenType == TokenImpersonation) &&
1922 (ClientToken->ImpersonationLevel < SecurityIdentification))
1923 {
1924 DPRINT1("Invalid impersonation level (%u)\n", ClientToken->ImpersonationLevel);
1925 ObDereferenceObject(ClientToken);
1926 return STATUS_BAD_IMPERSONATION_LEVEL;
1927 }
1928
1929 /* Capture the security subject context */
1930 SeCaptureSubjectContext(&SubjectContext);
1931
1932 /* Check for audit privilege */
1933 if (!SeCheckAuditPrivilege(&SubjectContext, PreviousMode))
1934 {
1935 DPRINT1("Caller does not have SeAuditPrivilege\n");
1936 Status = STATUS_PRIVILEGE_NOT_HELD;
1937 goto Cleanup;
1938 }
1939
1940 /* Do we have a subsystem name? */
1941 if (SubsystemName != NULL)
1942 {
1943 /* Probe and capture the subsystem name */
1944 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName,
1945 PreviousMode,
1946 SubsystemName);
1947 if (!NT_SUCCESS(Status))
1948 {
1949 DPRINT1("Failed to capture subsystem name!\n");
1950 goto Cleanup;
1951 }
1952 }
1953
1954 /* Do we have a service name? */
1955 if (ServiceName != NULL)
1956 {
1957 /* Probe and capture the service name */
1958 Status = ProbeAndCaptureUnicodeString(&CapturedServiceName,
1959 PreviousMode,
1960 ServiceName);
1961 if (!NT_SUCCESS(Status))
1962 {
1963 DPRINT1("Failed to capture service name!\n");
1964 goto Cleanup;
1965 }
1966 }
1967
1968 _SEH2_TRY
1969 {
1970 /* Probe the basic privilege set structure */
1971 ProbeForRead(Privileges, sizeof(PRIVILEGE_SET), sizeof(ULONG));
1972
1973 /* Validate privilege count */
1974 PrivilegeCount = Privileges->PrivilegeCount;
1975 if (PrivilegeCount > SEP_PRIVILEGE_SET_MAX_COUNT)
1976 {
1977 Status = STATUS_INVALID_PARAMETER;
1978 _SEH2_YIELD(goto Cleanup);
1979 }
1980
1981 /* Calculate the size of the Privileges structure */
1982 PrivilegesSize = FIELD_OFFSET(PRIVILEGE_SET, Privilege[PrivilegeCount]);
1983
1984 /* Probe the whole structure */
1985 ProbeForRead(Privileges, PrivilegesSize, sizeof(ULONG));
1986
1987 /* Allocate a temp buffer */
1988 CapturedPrivileges = ExAllocatePoolWithTag(PagedPool,
1989 PrivilegesSize,
1990 TAG_PRIVILEGE_SET);
1991 if (CapturedPrivileges == NULL)
1992 {
1993 DPRINT1("Failed to allocate %u bytes\n", PrivilegesSize);
1994 Status = STATUS_INSUFFICIENT_RESOURCES;
1995 _SEH2_YIELD(goto Cleanup);
1996 }
1997
1998 /* Copy the privileges */
1999 RtlCopyMemory(CapturedPrivileges, Privileges, PrivilegesSize);
2000 }
2001 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2002 {
2003 Status = _SEH2_GetExceptionCode();
2004 DPRINT1("Got exception 0x%lx\n", Status);
2005 _SEH2_YIELD(goto Cleanup);
2006 }
2007 _SEH2_END;
2008
2009 /* Call the internal function */
2010 SepAdtPrivilegedServiceAuditAlarm(&SubjectContext,
2011 SubsystemName ? &CapturedSubsystemName : NULL,
2012 ServiceName ? &CapturedServiceName : NULL,
2013 ClientToken,
2014 SubjectContext.PrimaryToken,
2015 CapturedPrivileges,
2016 AccessGranted);
2017
2018 Status = STATUS_SUCCESS;
2019
2020 Cleanup:
2021 /* Cleanup resources */
2022 if (CapturedSubsystemName.Buffer != NULL)
2023 ReleaseCapturedUnicodeString(&CapturedSubsystemName, PreviousMode);
2024
2025 if (CapturedServiceName.Buffer != NULL)
2026 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
2027
2028 if (CapturedPrivileges != NULL)
2029 ExFreePoolWithTag(CapturedPrivileges, TAG_PRIVILEGE_SET);
2030
2031 /* Release the security subject context */
2032 SeReleaseSubjectContext(&SubjectContext);
2033
2034 ObDereferenceObject(ClientToken);
2035
2036 return Status;
2037 }
2038
2039 /**
2040 * @brief
2041 * Raises an alarm audit message when a caller attempts to access a
2042 * privileged object.
2043 *
2044 * @param[in] SubsystemName
2045 * A Unicode string that points to a name of the subsystem.
2046 *
2047 * @param[in] HandleId
2048 * A handle to an ID that is used as identification instance for auditing.
2049 *
2050 * @param[in] ClientToken
2051 * A handle to a client access token.
2052 *
2053 * @param[in] DesiredAccess
2054 * A handle to a client access token.
2055 *
2056 * @param[in] Privileges
2057 * An array set of privileges.
2058 *
2059 * @param[in] AccessGranted
2060 * Set this to TRUE if the access attempt was deemed as granted.
2061 *
2062 * @return
2063 * To be added...
2064 */
2065 NTSTATUS NTAPI
NtPrivilegeObjectAuditAlarm(_In_ PUNICODE_STRING SubsystemName,_In_ PVOID HandleId,_In_ HANDLE ClientToken,_In_ ULONG DesiredAccess,_In_ PPRIVILEGE_SET Privileges,_In_ BOOLEAN AccessGranted)2066 NtPrivilegeObjectAuditAlarm(
2067 _In_ PUNICODE_STRING SubsystemName,
2068 _In_ PVOID HandleId,
2069 _In_ HANDLE ClientToken,
2070 _In_ ULONG DesiredAccess,
2071 _In_ PPRIVILEGE_SET Privileges,
2072 _In_ BOOLEAN AccessGranted)
2073 {
2074 UNIMPLEMENTED;
2075 return STATUS_NOT_IMPLEMENTED;
2076 }
2077
2078 /**
2079 * @brief
2080 * Raises an alarm audit message when a caller attempts to access an
2081 * object and determine if the access can be made.
2082 *
2083 * @param[in] SubsystemName
2084 * A Unicode string that points to a name of the subsystem.
2085 *
2086 * @param[in] HandleId
2087 * A handle to an ID that is used as identification instance for auditing.
2088 *
2089 * @param[in] ObjectTypeName
2090 * The name of the object type.
2091 *
2092 * @param[in] ObjectName
2093 * The object name.
2094 *
2095 * @param[in] SecurityDescriptor
2096 * A security descriptor.
2097 *
2098 * @param[in] DesiredAccess
2099 * The desired access rights masks requested by the caller.
2100 *
2101 * @param[in] GenericMapping
2102 * The generic mapping of access mask rights.
2103 *
2104 * @param[in] ObjectCreation
2105 * Set this to TRUE if the object has just been created.
2106 *
2107 * @param[out] GrantedAccess
2108 * Returns the granted access rights.
2109 *
2110 * @param[out] AccessStatus
2111 * Returns a NTSTATUS status code indicating whether access check
2112 * can be granted or not.
2113 *
2114 * @param[out] GenerateOnClose
2115 * Returns TRUE if the function has generated a list of granted access rights and
2116 * status codes on termination, FALSE otherwise.
2117 *
2118 * @return
2119 * See SepAccessCheckAndAuditAlarm.
2120 */
2121 _Must_inspect_result_
2122 __kernel_entry
2123 NTSTATUS
2124 NTAPI
NtAccessCheckAndAuditAlarm(_In_ PUNICODE_STRING SubsystemName,_In_opt_ PVOID HandleId,_In_ PUNICODE_STRING ObjectTypeName,_In_ PUNICODE_STRING ObjectName,_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,_In_ ACCESS_MASK DesiredAccess,_In_ PGENERIC_MAPPING GenericMapping,_In_ BOOLEAN ObjectCreation,_Out_ PACCESS_MASK GrantedAccess,_Out_ PNTSTATUS AccessStatus,_Out_ PBOOLEAN GenerateOnClose)2125 NtAccessCheckAndAuditAlarm(
2126 _In_ PUNICODE_STRING SubsystemName,
2127 _In_opt_ PVOID HandleId,
2128 _In_ PUNICODE_STRING ObjectTypeName,
2129 _In_ PUNICODE_STRING ObjectName,
2130 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
2131 _In_ ACCESS_MASK DesiredAccess,
2132 _In_ PGENERIC_MAPPING GenericMapping,
2133 _In_ BOOLEAN ObjectCreation,
2134 _Out_ PACCESS_MASK GrantedAccess,
2135 _Out_ PNTSTATUS AccessStatus,
2136 _Out_ PBOOLEAN GenerateOnClose)
2137 {
2138 /* Call the internal function */
2139 return SepAccessCheckAndAuditAlarm(SubsystemName,
2140 HandleId,
2141 NULL,
2142 ObjectTypeName,
2143 ObjectName,
2144 SecurityDescriptor,
2145 NULL,
2146 DesiredAccess,
2147 AuditEventObjectAccess,
2148 0,
2149 NULL,
2150 0,
2151 GenericMapping,
2152 GrantedAccess,
2153 AccessStatus,
2154 GenerateOnClose,
2155 FALSE);
2156 }
2157
2158 /**
2159 * @brief
2160 * Raises an alarm audit message when a caller attempts to access an
2161 * object and determine if the access can be made by type.
2162 *
2163 * @param[in] SubsystemName
2164 * A Unicode string that points to a name of the subsystem.
2165 *
2166 * @param[in] HandleId
2167 * A handle to an ID that is used as identification instance for auditing.
2168 *
2169 * @param[in] ObjectTypeName
2170 * The name of the object type.
2171 *
2172 * @param[in] ObjectName
2173 * The object name.
2174 *
2175 * @param[in] SecurityDescriptor
2176 * A security descriptor.
2177 *
2178 * @param[in] PrincipalSelfSid
2179 * A principal self user SID.
2180 *
2181 * @param[in] DesiredAccess
2182 * The desired access rights masks requested by the caller.
2183 *
2184 * @param[in] AuditType
2185 * Type of audit to start, influencing how the audit should
2186 * be done.
2187 *
2188 * @param[in] Flags
2189 * Flag bitmask, used to check if auditing can be done
2190 * without privileges.
2191 *
2192 * @param[in] ObjectTypeList
2193 * A list of object types.
2194 *
2195 * @param[in] ObjectTypeLength
2196 * The length size of the list.
2197 *
2198 * @param[in] GenericMapping
2199 * The generic mapping of access mask rights.
2200 *
2201 * @param[in] ObjectCreation
2202 * Set this to TRUE if the object has just been created.
2203 *
2204 * @param[out] GrantedAccess
2205 * Returns the granted access rights.
2206 *
2207 * @param[out] AccessStatus
2208 * Returns a NTSTATUS status code indicating whether access check
2209 * can be granted or not.
2210 *
2211 * @param[out] GenerateOnClose
2212 * Returns TRUE if the function has generated a list of granted access rights and
2213 * status codes on termination, FALSE otherwise.
2214 *
2215 * @return
2216 * See SepAccessCheckAndAuditAlarm.
2217 */
2218 _Must_inspect_result_
2219 __kernel_entry
2220 NTSTATUS
2221 NTAPI
NtAccessCheckByTypeAndAuditAlarm(_In_ PUNICODE_STRING SubsystemName,_In_opt_ PVOID HandleId,_In_ PUNICODE_STRING ObjectTypeName,_In_ PUNICODE_STRING ObjectName,_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,_In_opt_ PSID PrincipalSelfSid,_In_ ACCESS_MASK DesiredAccess,_In_ AUDIT_EVENT_TYPE AuditType,_In_ ULONG Flags,_In_reads_opt_ (ObjectTypeLength)POBJECT_TYPE_LIST ObjectTypeList,_In_ ULONG ObjectTypeLength,_In_ PGENERIC_MAPPING GenericMapping,_In_ BOOLEAN ObjectCreation,_Out_ PACCESS_MASK GrantedAccess,_Out_ PNTSTATUS AccessStatus,_Out_ PBOOLEAN GenerateOnClose)2222 NtAccessCheckByTypeAndAuditAlarm(
2223 _In_ PUNICODE_STRING SubsystemName,
2224 _In_opt_ PVOID HandleId,
2225 _In_ PUNICODE_STRING ObjectTypeName,
2226 _In_ PUNICODE_STRING ObjectName,
2227 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
2228 _In_opt_ PSID PrincipalSelfSid,
2229 _In_ ACCESS_MASK DesiredAccess,
2230 _In_ AUDIT_EVENT_TYPE AuditType,
2231 _In_ ULONG Flags,
2232 _In_reads_opt_(ObjectTypeLength) POBJECT_TYPE_LIST ObjectTypeList,
2233 _In_ ULONG ObjectTypeLength,
2234 _In_ PGENERIC_MAPPING GenericMapping,
2235 _In_ BOOLEAN ObjectCreation,
2236 _Out_ PACCESS_MASK GrantedAccess,
2237 _Out_ PNTSTATUS AccessStatus,
2238 _Out_ PBOOLEAN GenerateOnClose)
2239 {
2240 /* Call the internal function */
2241 return SepAccessCheckAndAuditAlarm(SubsystemName,
2242 HandleId,
2243 NULL,
2244 ObjectTypeName,
2245 ObjectName,
2246 SecurityDescriptor,
2247 PrincipalSelfSid,
2248 DesiredAccess,
2249 AuditType,
2250 Flags,
2251 ObjectTypeList,
2252 ObjectTypeLength,
2253 GenericMapping,
2254 GrantedAccess,
2255 AccessStatus,
2256 GenerateOnClose,
2257 FALSE);
2258 }
2259
2260 /**
2261 * @brief
2262 * Raises an alarm audit message when a caller attempts to access an
2263 * object and determine if the access can be made by given type result.
2264 *
2265 * @param[in] SubsystemName
2266 * A Unicode string that points to a name of the subsystem.
2267 *
2268 * @param[in] HandleId
2269 * A handle to an ID that is used as identification instance for auditing.
2270 *
2271 * @param[in] ObjectTypeName
2272 * The name of the object type.
2273 *
2274 * @param[in] ObjectName
2275 * The object name.
2276 *
2277 * @param[in] SecurityDescriptor
2278 * A security descriptor.
2279 *
2280 * @param[in] PrincipalSelfSid
2281 * A principal self user SID.
2282 *
2283 * @param[in] DesiredAccess
2284 * The desired access rights masks requested by the caller.
2285 *
2286 * @param[in] AuditType
2287 * Type of audit to start, influencing how the audit should
2288 * be done.
2289 *
2290 * @param[in] Flags
2291 * Flag bitmask, used to check if auditing can be done
2292 * without privileges.
2293 *
2294 * @param[in] ObjectTypeList
2295 * A list of object types.
2296 *
2297 * @param[in] ObjectTypeLength
2298 * The length size of the list.
2299 *
2300 * @param[in] GenericMapping
2301 * The generic mapping of access mask rights.
2302 *
2303 * @param[in] ObjectCreation
2304 * Set this to TRUE if the object has just been created.
2305 *
2306 * @param[out] GrantedAccessList
2307 * Returns the granted access rights.
2308 *
2309 * @param[out] AccessStatusList
2310 * Returns a NTSTATUS status code indicating whether access check
2311 * can be granted or not.
2312 *
2313 * @param[out] GenerateOnClose
2314 * Returns TRUE if the function has generated a list of granted access rights and
2315 * status codes on termination, FALSE otherwise.
2316 *
2317 * @return
2318 * See SepAccessCheckAndAuditAlarm.
2319 */
2320 _Must_inspect_result_
2321 __kernel_entry
2322 NTSTATUS
2323 NTAPI
NtAccessCheckByTypeResultListAndAuditAlarm(_In_ PUNICODE_STRING SubsystemName,_In_opt_ PVOID HandleId,_In_ PUNICODE_STRING ObjectTypeName,_In_ PUNICODE_STRING ObjectName,_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,_In_opt_ PSID PrincipalSelfSid,_In_ ACCESS_MASK DesiredAccess,_In_ AUDIT_EVENT_TYPE AuditType,_In_ ULONG Flags,_In_reads_opt_ (ObjectTypeListLength)POBJECT_TYPE_LIST ObjectTypeList,_In_ ULONG ObjectTypeListLength,_In_ PGENERIC_MAPPING GenericMapping,_In_ BOOLEAN ObjectCreation,_Out_writes_ (ObjectTypeListLength)PACCESS_MASK GrantedAccessList,_Out_writes_ (ObjectTypeListLength)PNTSTATUS AccessStatusList,_Out_ PBOOLEAN GenerateOnClose)2324 NtAccessCheckByTypeResultListAndAuditAlarm(
2325 _In_ PUNICODE_STRING SubsystemName,
2326 _In_opt_ PVOID HandleId,
2327 _In_ PUNICODE_STRING ObjectTypeName,
2328 _In_ PUNICODE_STRING ObjectName,
2329 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
2330 _In_opt_ PSID PrincipalSelfSid,
2331 _In_ ACCESS_MASK DesiredAccess,
2332 _In_ AUDIT_EVENT_TYPE AuditType,
2333 _In_ ULONG Flags,
2334 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
2335 _In_ ULONG ObjectTypeListLength,
2336 _In_ PGENERIC_MAPPING GenericMapping,
2337 _In_ BOOLEAN ObjectCreation,
2338 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList,
2339 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList,
2340 _Out_ PBOOLEAN GenerateOnClose)
2341 {
2342 /* Call the internal function */
2343 return SepAccessCheckAndAuditAlarm(SubsystemName,
2344 HandleId,
2345 NULL,
2346 ObjectTypeName,
2347 ObjectName,
2348 SecurityDescriptor,
2349 PrincipalSelfSid,
2350 DesiredAccess,
2351 AuditType,
2352 Flags,
2353 ObjectTypeList,
2354 ObjectTypeListLength,
2355 GenericMapping,
2356 GrantedAccessList,
2357 AccessStatusList,
2358 GenerateOnClose,
2359 TRUE);
2360 }
2361
2362 /**
2363 * @brief
2364 * Raises an alarm audit message when a caller attempts to access an
2365 * object and determine if the access can be made by given type result
2366 * and a token handle.
2367 *
2368 * @param[in] SubsystemName
2369 * A Unicode string that points to a name of the subsystem.
2370 *
2371 * @param[in] HandleId
2372 * A handle to an ID that is used as identification instance for auditing.
2373 *
2374 * @param[in] ClientToken
2375 * A handle to a client access token.
2376 *
2377 * @param[in] ObjectTypeName
2378 * The name of the object type.
2379 *
2380 * @param[in] ObjectName
2381 * The object name.
2382 *
2383 * @param[in] SecurityDescriptor
2384 * A security descriptor.
2385 *
2386 * @param[in] PrincipalSelfSid
2387 * A principal self user SID.
2388 *
2389 * @param[in] DesiredAccess
2390 * The desired access rights masks requested by the caller.
2391 *
2392 * @param[in] AuditType
2393 * Type of audit to start, influencing how the audit should
2394 * be done.
2395 *
2396 * @param[in] Flags
2397 * Flag bitmask, used to check if auditing can be done
2398 * without privileges.
2399 *
2400 * @param[in] ObjectTypeList
2401 * A list of object types.
2402 *
2403 * @param[in] ObjectTypeLength
2404 * The length size of the list.
2405 *
2406 * @param[in] GenericMapping
2407 * The generic mapping of access mask rights.
2408 *
2409 * @param[in] ObjectCreation
2410 * Set this to TRUE if the object has just been created.
2411 *
2412 * @param[out] GrantedAccessList
2413 * Returns the granted access rights.
2414 *
2415 * @param[out] AccessStatusList
2416 * Returns a NTSTATUS status code indicating whether access check
2417 * can be granted or not.
2418 *
2419 * @param[out] GenerateOnClose
2420 * Returns TRUE if the function has generated a list of granted access rights and
2421 * status codes on termination, FALSE otherwise.
2422 *
2423 * @return
2424 * See SepAccessCheckAndAuditAlarm.
2425 */
2426 _Must_inspect_result_
2427 __kernel_entry
2428 NTSTATUS
2429 NTAPI
NtAccessCheckByTypeResultListAndAuditAlarmByHandle(_In_ PUNICODE_STRING SubsystemName,_In_opt_ PVOID HandleId,_In_ HANDLE ClientToken,_In_ PUNICODE_STRING ObjectTypeName,_In_ PUNICODE_STRING ObjectName,_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,_In_opt_ PSID PrincipalSelfSid,_In_ ACCESS_MASK DesiredAccess,_In_ AUDIT_EVENT_TYPE AuditType,_In_ ULONG Flags,_In_reads_opt_ (ObjectTypeListLength)POBJECT_TYPE_LIST ObjectTypeList,_In_ ULONG ObjectTypeListLength,_In_ PGENERIC_MAPPING GenericMapping,_In_ BOOLEAN ObjectCreation,_Out_writes_ (ObjectTypeListLength)PACCESS_MASK GrantedAccessList,_Out_writes_ (ObjectTypeListLength)PNTSTATUS AccessStatusList,_Out_ PBOOLEAN GenerateOnClose)2430 NtAccessCheckByTypeResultListAndAuditAlarmByHandle(
2431 _In_ PUNICODE_STRING SubsystemName,
2432 _In_opt_ PVOID HandleId,
2433 _In_ HANDLE ClientToken,
2434 _In_ PUNICODE_STRING ObjectTypeName,
2435 _In_ PUNICODE_STRING ObjectName,
2436 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
2437 _In_opt_ PSID PrincipalSelfSid,
2438 _In_ ACCESS_MASK DesiredAccess,
2439 _In_ AUDIT_EVENT_TYPE AuditType,
2440 _In_ ULONG Flags,
2441 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
2442 _In_ ULONG ObjectTypeListLength,
2443 _In_ PGENERIC_MAPPING GenericMapping,
2444 _In_ BOOLEAN ObjectCreation,
2445 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList,
2446 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList,
2447 _Out_ PBOOLEAN GenerateOnClose)
2448 {
2449 UNREFERENCED_PARAMETER(ObjectCreation);
2450
2451 /* Call the internal function */
2452 return SepAccessCheckAndAuditAlarm(SubsystemName,
2453 HandleId,
2454 &ClientToken,
2455 ObjectTypeName,
2456 ObjectName,
2457 SecurityDescriptor,
2458 PrincipalSelfSid,
2459 DesiredAccess,
2460 AuditType,
2461 Flags,
2462 ObjectTypeList,
2463 ObjectTypeListLength,
2464 GenericMapping,
2465 GrantedAccessList,
2466 AccessStatusList,
2467 GenerateOnClose,
2468 TRUE);
2469 }
2470
2471 /* EOF */
2472