#define SEP_PRIVILEGE_SET_MAX_COUNT 60
+UNICODE_STRING SeSubsystemName = RTL_CONSTANT_STRING(L"Security");
+
/* PRIVATE FUNCTIONS***********************************************************/
BOOLEAN
_In_ PTOKEN Token,
_In_ PTOKEN PrimaryToken,
_In_ PPRIVILEGE_SET Privileges,
- _In_ BOOLEAN AccessGranted )
+ _In_ BOOLEAN AccessGranted)
{
UNIMPLEMENTED;
}
+VOID
+NTAPI
+SePrivilegedServiceAuditAlarm(
+ _In_opt_ PUNICODE_STRING ServiceName,
+ _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
+ _In_ PPRIVILEGE_SET PrivilegeSet,
+ _In_ BOOLEAN AccessGranted)
+{
+ PTOKEN EffectiveToken;
+ PSID UserSid;
+ PAGED_CODE();
+
+ /* Get the effective token */
+ if (SubjectContext->ClientToken != NULL)
+ EffectiveToken = SubjectContext->ClientToken;
+ else
+ EffectiveToken = SubjectContext->PrimaryToken;
+
+ /* Get the user SID */
+ UserSid = EffectiveToken->UserAndGroups->Sid;
+
+ /* Check if this is the local system SID */
+ if (RtlEqualSid(UserSid, SeLocalSystemSid))
+ {
+ /* Nothing to do */
+ return;
+ }
+
+ /* Check if this is the network service or local service SID */
+ if (RtlEqualSid(UserSid, SeExports->SeNetworkServiceSid) ||
+ RtlEqualSid(UserSid, SeExports->SeLocalServiceSid))
+ {
+ // FIXME: should continue for a certain set of privileges
+ return;
+ }
+
+ /* Call the worker function */
+ SepAdtPrivilegedServiceAuditAlarm(SubjectContext,
+ &SeSubsystemName,
+ ServiceName,
+ SubjectContext->ClientToken,
+ SubjectContext->PrimaryToken,
+ PrivilegeSet,
+ AccessGranted);
+
+}
+
+
static
NTSTATUS
SeCaptureObjectTypeList(
}
/* Check for audit privilege */
- HaveAuditPrivilege = SeSinglePrivilegeCheck(SeAuditPrivilege, UserMode);
+ HaveAuditPrivilege = SeCheckAuditPrivilege(&SubjectContext, UserMode);
if (!HaveAuditPrivilege && !(Flags & AUDIT_ALLOW_NO_PRIVILEGE))
{
DPRINT1("Caller does not have SeAuditPrivilege\n");
PVOID HandleId,
BOOLEAN GenerateOnClose)
{
+ SECURITY_SUBJECT_CONTEXT SubjectContext;
UNICODE_STRING CapturedSubsystemName;
KPROCESSOR_MODE PreviousMode;
BOOLEAN UseImpersonationToken;
return STATUS_SUCCESS;
}
- /* Validate privilege */
- if (!SeSinglePrivilegeCheck(SeAuditPrivilege, PreviousMode))
+ /* Capture the security subject context */
+ SeCaptureSubjectContext(&SubjectContext);
+
+ /* Check for audit privilege */
+ if (!SeCheckAuditPrivilege(&SubjectContext, PreviousMode))
{
DPRINT1("Caller does not have SeAuditPrivilege\n");
- return STATUS_PRIVILEGE_NOT_HELD;
+ Status = STATUS_PRIVILEGE_NOT_HELD;
+ goto Cleanup;
}
/* Probe and capture the subsystem name */
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to capture subsystem name!\n");
- return Status;
+ goto Cleanup;
}
/* Get the current thread and check if it's impersonating */
PsDereferencePrimaryToken(Token);
}
- return STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
+
+Cleanup:
+
+ /* Release the security subject context */
+ SeReleaseSubjectContext(&SubjectContext);
+
+ return Status;
}
return Status;
}
+ /* Capture the security subject context */
+ SeCaptureSubjectContext(&SubjectContext);
+
/* Validate the token's impersonation level */
if ((ClientToken->TokenType == TokenImpersonation) &&
(ClientToken->ImpersonationLevel < SecurityIdentification))
}
/* Check for audit privilege */
- if (!SeSinglePrivilegeCheck(SeAuditPrivilege, UserMode))
+ if (!SeCheckAuditPrivilege(&SubjectContext, UserMode))
{
DPRINT1("Caller does not have SeAuditPrivilege\n");
Status = STATUS_PRIVILEGE_NOT_HELD;
goto Cleanup;
}
- /* Capture the security subject context */
- SeCaptureSubjectContext(&SubjectContext);
-
/* Call the internal function */
SepOpenObjectAuditAlarm(&SubjectContext,
&CapturedSubsystemName,
AccessGranted,
&LocalGenerateOnClose);
- /* Release the security subject context */
- SeReleaseSubjectContext(&SubjectContext);
-
Status = STATUS_SUCCESS;
/* Enter SEH to copy the data back to user mode */
if (CapturedPrivilegeSet != NULL)
ExFreePoolWithTag(CapturedPrivilegeSet, 'rPeS');
+ /* Release the security subject context */
+ SeReleaseSubjectContext(&SubjectContext);
+
ObDereferenceObject(ClientToken);
return Status;
return STATUS_BAD_IMPERSONATION_LEVEL;
}
- /* Validate privilege */
- if (!SeSinglePrivilegeCheck(SeAuditPrivilege, PreviousMode))
+ /* Capture the security subject context */
+ SeCaptureSubjectContext(&SubjectContext);
+
+ /* Check for audit privilege */
+ if (!SeCheckAuditPrivilege(&SubjectContext, PreviousMode))
{
DPRINT1("Caller does not have SeAuditPrivilege\n");
- ObDereferenceObject(ClientToken);
- return STATUS_PRIVILEGE_NOT_HELD;
+ Status = STATUS_PRIVILEGE_NOT_HELD;
+ goto Cleanup;
}
/* Do we have a subsystem name? */
}
_SEH2_END;
- /* Capture the security subject context */
- SeCaptureSubjectContext(&SubjectContext);
-
/* Call the internal function */
SepAdtPrivilegedServiceAuditAlarm(&SubjectContext,
SubsystemName ? &CapturedSubsystemName : NULL,
CapturedPrivileges,
AccessGranted);
- /* Release the security subject context */
- SeReleaseSubjectContext(&SubjectContext);
-
Status = STATUS_SUCCESS;
Cleanup:
if (CapturedPrivileges != NULL)
ExFreePoolWithTag(CapturedPrivileges, 'rPeS');
+ /* Release the security subject context */
+ SeReleaseSubjectContext(&SubjectContext);
+
ObDereferenceObject(ClientToken);
return Status;
return STATUS_SUCCESS;
}
+BOOLEAN
+NTAPI
+SeCheckAuditPrivilege(
+ _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
+ _In_ KPROCESSOR_MODE PreviousMode)
+{
+ PRIVILEGE_SET PrivilegeSet;
+ BOOLEAN Result;
+ PAGED_CODE();
+
+ /* Initialize the privilege set with the single privilege */
+ PrivilegeSet.PrivilegeCount = 1;
+ PrivilegeSet.Control = PRIVILEGE_SET_ALL_NECESSARY;
+ PrivilegeSet.Privilege[0].Luid = SeAuditPrivilege;
+ PrivilegeSet.Privilege[0].Attributes = 0;
+
+ /* Check against the primary token! */
+ Result = SepPrivilegeCheck(SubjectContext->PrimaryToken,
+ &PrivilegeSet.Privilege[0],
+ 1,
+ PRIVILEGE_SET_ALL_NECESSARY,
+ PreviousMode);
+
+ if (PreviousMode != KernelMode)
+ {
+ SePrivilegedServiceAuditAlarm(NULL,
+ SubjectContext,
+ &PrivilegeSet,
+ Result);
+ }
+
+ return Result;
+}
+
NTSTATUS
NTAPI
SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src,
if (PreviousMode != KernelMode)
{
-#if 0
- SePrivilegedServiceAuditAlarm(0,
+ SePrivilegedServiceAuditAlarm(NULL,
&SubjectContext,
- &PrivilegeValue);
-#endif
+ &Priv,
+ Result);
+
}
SeReleaseSubjectContext(&SubjectContext);
PSID SeAuthenticatedUsersSid = NULL;
PSID SeRestrictedSid = NULL;
PSID SeAnonymousLogonSid = NULL;
+PSID SeLocalServiceSid = NULL;
+PSID SeNetworkServiceSid = NULL;
/* FUNCTIONS ******************************************************************/
SeAuthenticatedUsersSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
SeRestrictedSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
SeAnonymousLogonSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
+ SeLocalServiceSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
+ SeNetworkServiceSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
if (SeNullSid == NULL || SeWorldSid == NULL ||
SeLocalSid == NULL || SeCreatorOwnerSid == NULL ||
SeAliasAccountOpsSid == NULL || SeAliasSystemOpsSid == NULL ||
SeAliasPrintOpsSid == NULL || SeAliasBackupOpsSid == NULL ||
SeAuthenticatedUsersSid == NULL || SeRestrictedSid == NULL ||
- SeAnonymousLogonSid == NULL)
+ SeAnonymousLogonSid == NULL || SeLocalServiceSid == NULL ||
+ SeNetworkServiceSid == NULL)
{
FreeInitializedSids();
return FALSE;
RtlInitializeSid(SeAuthenticatedUsersSid, &SeNtSidAuthority, 1);
RtlInitializeSid(SeRestrictedSid, &SeNtSidAuthority, 1);
RtlInitializeSid(SeAnonymousLogonSid, &SeNtSidAuthority, 1);
+ RtlInitializeSid(SeLocalServiceSid, &SeNtSidAuthority, 1);
+ RtlInitializeSid(SeNetworkServiceSid, &SeNtSidAuthority, 1);
SubAuthority = RtlSubAuthoritySid(SeNullSid, 0);
*SubAuthority = SECURITY_NULL_RID;
*SubAuthority = SECURITY_RESTRICTED_CODE_RID;
SubAuthority = RtlSubAuthoritySid(SeAnonymousLogonSid, 0);
*SubAuthority = SECURITY_ANONYMOUS_LOGON_RID;
+ SubAuthority = RtlSubAuthoritySid(SeLocalServiceSid, 0);
+ *SubAuthority = SECURITY_LOCAL_SERVICE_RID;
+ SubAuthority = RtlSubAuthoritySid(SeNetworkServiceSid, 0);
+ *SubAuthority = SECURITY_NETWORK_SERVICE_RID;
return TRUE;
}