Author: tkreuzer Date: Tue Feb 18 17:51:45 2014 New Revision: 62245
URL: http://svn.reactos.org/svn/reactos?rev=62245&view=rev Log: [NTOSKRNL] - Implement SeCheckAuditPrivilege and use it instead of SeSinglePrivilegeCheck, because the latter uses the effective token and we want the primary token - Implement SePrivilegedServiceAuditAlarm - Add and initialize missing SeLocalServiceSid and SeNetworkServiceSid
Modified: trunk/reactos/ntoskrnl/include/internal/se.h trunk/reactos/ntoskrnl/se/audit.c trunk/reactos/ntoskrnl/se/priv.c trunk/reactos/ntoskrnl/se/semgr.c trunk/reactos/ntoskrnl/se/sid.c
Modified: trunk/reactos/ntoskrnl/include/internal/se.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/s... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/se.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/se.h [iso-8859-1] Tue Feb 18 17:51:45 2014 @@ -143,6 +143,8 @@ extern PSID SeAuthenticatedUsersSid; extern PSID SeRestrictedSid; extern PSID SeAnonymousLogonSid; +extern PSID SeLocalServiceSid; +extern PSID SeNetworkServiceSid;
/* Privileges */ extern const LUID SeCreateTokenPrivilege; @@ -531,6 +533,20 @@ IN ACCESS_MASK DesiredAccess, IN KPROCESSOR_MODE AccessMode);
+BOOLEAN +NTAPI +SeCheckAuditPrivilege( + _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, + _In_ KPROCESSOR_MODE PreviousMode); + +VOID +NTAPI +SePrivilegedServiceAuditAlarm( + _In_opt_ PUNICODE_STRING ServiceName, + _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, + _In_ PPRIVILEGE_SET PrivilegeSet, + _In_ BOOLEAN AccessGranted); + #endif
/* EOF */
Modified: trunk/reactos/ntoskrnl/se/audit.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/audit.c?rev=622... ============================================================================== --- trunk/reactos/ntoskrnl/se/audit.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/se/audit.c [iso-8859-1] Tue Feb 18 17:51:45 2014 @@ -15,6 +15,8 @@ #include <debug.h>
#define SEP_PRIVILEGE_SET_MAX_COUNT 60 + +UNICODE_STRING SeSubsystemName = RTL_CONSTANT_STRING(L"Security");
/* PRIVATE FUNCTIONS***********************************************************/
@@ -202,10 +204,58 @@ _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 @@ -477,7 +527,7 @@ }
/* 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"); @@ -811,6 +861,7 @@ PVOID HandleId, BOOLEAN GenerateOnClose) { + SECURITY_SUBJECT_CONTEXT SubjectContext; UNICODE_STRING CapturedSubsystemName; KPROCESSOR_MODE PreviousMode; BOOLEAN UseImpersonationToken; @@ -832,11 +883,15 @@ 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 */ @@ -846,7 +901,7 @@ 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 */ @@ -887,7 +942,14 @@ PsDereferencePrimaryToken(Token); }
- return STATUS_SUCCESS; + Status = STATUS_SUCCESS; + +Cleanup: + + /* Release the security subject context */ + SeReleaseSubjectContext(&SubjectContext); + + return Status; }
@@ -986,6 +1048,9 @@ return Status; }
+ /* Capture the security subject context */ + SeCaptureSubjectContext(&SubjectContext); + /* Validate the token's impersonation level */ if ((ClientToken->TokenType == TokenImpersonation) && (ClientToken->ImpersonationLevel < SecurityIdentification)) @@ -996,7 +1061,7 @@ }
/* Check for audit privilege */ - if (!SeSinglePrivilegeCheck(SeAuditPrivilege, UserMode)) + if (!SeCheckAuditPrivilege(&SubjectContext, UserMode)) { DPRINT1("Caller does not have SeAuditPrivilege\n"); Status = STATUS_PRIVILEGE_NOT_HELD; @@ -1105,9 +1170,6 @@ DPRINT1("Failed to capture object name!\n"); goto Cleanup; } - - /* Capture the security subject context */ - SeCaptureSubjectContext(&SubjectContext);
/* Call the internal function */ SepOpenObjectAuditAlarm(&SubjectContext, @@ -1124,39 +1186,39 @@ AccessGranted, &LocalGenerateOnClose);
+ Status = STATUS_SUCCESS; + + /* Enter SEH to copy the data back to user mode */ + _SEH2_TRY + { + *GenerateOnClose = LocalGenerateOnClose; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + DPRINT1("Exception while copying back data: 0x%lx\n", Status); + } + _SEH2_END; + +Cleanup: + + if (CapturedObjectName.Buffer != NULL) + ReleaseCapturedUnicodeString(&CapturedObjectName, UserMode); + + if (CapturedObjectTypeName.Buffer != NULL) + ReleaseCapturedUnicodeString(&CapturedObjectTypeName, UserMode); + + if (CapturedSubsystemName.Buffer != NULL) + ReleaseCapturedUnicodeString(&CapturedSubsystemName, UserMode); + + if (CapturedSecurityDescriptor != NULL) + SeReleaseSecurityDescriptor(CapturedSecurityDescriptor, UserMode, FALSE); + + if (CapturedPrivilegeSet != NULL) + ExFreePoolWithTag(CapturedPrivilegeSet, 'rPeS'); + /* Release the security subject context */ SeReleaseSubjectContext(&SubjectContext); - - Status = STATUS_SUCCESS; - - /* Enter SEH to copy the data back to user mode */ - _SEH2_TRY - { - *GenerateOnClose = LocalGenerateOnClose; - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - Status = _SEH2_GetExceptionCode(); - DPRINT1("Exception while copying back data: 0x%lx\n", Status); - } - _SEH2_END; - -Cleanup: - - if (CapturedObjectName.Buffer != NULL) - ReleaseCapturedUnicodeString(&CapturedObjectName, UserMode); - - if (CapturedObjectTypeName.Buffer != NULL) - ReleaseCapturedUnicodeString(&CapturedObjectTypeName, UserMode); - - if (CapturedSubsystemName.Buffer != NULL) - ReleaseCapturedUnicodeString(&CapturedSubsystemName, UserMode); - - if (CapturedSecurityDescriptor != NULL) - SeReleaseSecurityDescriptor(CapturedSecurityDescriptor, UserMode, FALSE); - - if (CapturedPrivilegeSet != NULL) - ExFreePoolWithTag(CapturedPrivilegeSet, 'rPeS');
ObDereferenceObject(ClientToken);
@@ -1213,12 +1275,15 @@ 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? */ @@ -1290,9 +1355,6 @@ } _SEH2_END;
- /* Capture the security subject context */ - SeCaptureSubjectContext(&SubjectContext); - /* Call the internal function */ SepAdtPrivilegedServiceAuditAlarm(&SubjectContext, SubsystemName ? &CapturedSubsystemName : NULL, @@ -1302,9 +1364,6 @@ CapturedPrivileges, AccessGranted);
- /* Release the security subject context */ - SeReleaseSubjectContext(&SubjectContext); - Status = STATUS_SUCCESS;
Cleanup: @@ -1317,6 +1376,9 @@
if (CapturedPrivileges != NULL) ExFreePoolWithTag(CapturedPrivileges, 'rPeS'); + + /* Release the security subject context */ + SeReleaseSubjectContext(&SubjectContext);
ObDereferenceObject(ClientToken);
Modified: trunk/reactos/ntoskrnl/se/priv.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/priv.c?rev=6224... ============================================================================== --- trunk/reactos/ntoskrnl/se/priv.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/se/priv.c [iso-8859-1] Tue Feb 18 17:51:45 2014 @@ -252,6 +252,40 @@ 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, @@ -506,11 +540,11 @@
if (PreviousMode != KernelMode) { -#if 0 - SePrivilegedServiceAuditAlarm(0, + SePrivilegedServiceAuditAlarm(NULL, &SubjectContext, - &PrivilegeValue); -#endif + &Priv, + Result); + }
SeReleaseSubjectContext(&SubjectContext);
Modified: trunk/reactos/ntoskrnl/se/semgr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/semgr.c?rev=622... ============================================================================== --- trunk/reactos/ntoskrnl/se/semgr.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/se/semgr.c [iso-8859-1] Tue Feb 18 17:51:45 2014 @@ -74,10 +74,15 @@ SepExports.SeAuthenticatedUsersSid = SeAuthenticatedUsersSid; SepExports.SeRestrictedSid = SeRestrictedSid; SepExports.SeAnonymousLogonSid = SeAnonymousLogonSid; + SepExports.SeLocalServiceSid = SeLocalServiceSid; + SepExports.SeNetworkServiceSid = SeNetworkServiceSid;
SepExports.SeUndockPrivilege = SeUndockPrivilege; SepExports.SeSyncAgentPrivilege = SeSyncAgentPrivilege; SepExports.SeEnableDelegationPrivilege = SeEnableDelegationPrivilege; + SepExports.SeManageVolumePrivilege = SeManageVolumePrivilege; + SepExports.SeImpersonatePrivilege = SeImpersonatePrivilege; + SepExports.SeCreateGlobalPrivilege = SeCreateGlobalPrivilege;
SeExports = &SepExports; return TRUE;
Modified: trunk/reactos/ntoskrnl/se/sid.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/sid.c?rev=62245... ============================================================================== --- trunk/reactos/ntoskrnl/se/sid.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/se/sid.c [iso-8859-1] Tue Feb 18 17:51:45 2014 @@ -55,6 +55,8 @@ PSID SeAuthenticatedUsersSid = NULL; PSID SeRestrictedSid = NULL; PSID SeAnonymousLogonSid = NULL; +PSID SeLocalServiceSid = NULL; +PSID SeNetworkServiceSid = NULL;
/* FUNCTIONS ******************************************************************/
@@ -135,6 +137,8 @@ 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 || @@ -149,7 +153,8 @@ SeAliasAccountOpsSid == NULL || SeAliasSystemOpsSid == NULL || SeAliasPrintOpsSid == NULL || SeAliasBackupOpsSid == NULL || SeAuthenticatedUsersSid == NULL || SeRestrictedSid == NULL || - SeAnonymousLogonSid == NULL) + SeAnonymousLogonSid == NULL || SeLocalServiceSid == NULL || + SeNetworkServiceSid == NULL) { FreeInitializedSids(); return FALSE; @@ -183,6 +188,8 @@ 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; @@ -254,6 +261,10 @@ *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; }