Files

107 lines
4.1 KiB
C

// Kernel security contexts. Contexts are immutable authority sets carried by processes and delegated only by attenuation.
#include <string.h>
#include <kernel/se_security.h>
#include <kernel/ke_id.h>
#include <kernel/ke_process.h>
#include <kernel/ob_object.h>
static KE_ID_ALLOCATOR gSecurityIds = KE_ID_ALLOCATOR_INIT(1u);
static SECURITY_CONTEXT* gRootSecurityContext;
// Destroys one non-root security context after its last object reference disappears.
static void KiSecurityContextDestroy(OBJECT* object) {
(void)object;
}
// Allocates and initializes one immutable security context object.
static KSTATUS KiCreateSecurityContext(SYS_PRIVILEGES effectivePrivileges,
SYS_PRIVILEGES delegablePrivileges,
SECURITY_CONTEXT** contextOut) {
if (!contextOut)
return NTLSTATUS_INVALID_PARAMETER;
*contextOut = (SECURITY_CONTEXT*)0;
if ((effectivePrivileges & ~SYS_PRIV_ALL) != 0 ||
(delegablePrivileges & ~SYS_PRIV_ALL) != 0)
return NTLSTATUS_INVALID_PARAMETER;
if ((delegablePrivileges & ~effectivePrivileges) != 0)
return NTLSTATUS_ACCESS_DENIED;
SECURITY_CONTEXT* context = (SECURITY_CONTEXT*)ObAllocateObject(ObjectTypeSecurityContext,
sizeof(SECURITY_CONTEXT));
if (!context)
return NTLSTATUS_NO_MEMORY;
context->Header.Destroy = KiSecurityContextDestroy;
KSTATUS status = KeAllocateId32(&gSecurityIds, &context->SecurityId);
if (!KSUCCESS(status)) {
ObDereferenceObject(&context->Header);
return status;
}
context->EffectivePrivileges = effectivePrivileges;
context->DelegablePrivileges = delegablePrivileges;
context->Flags = SYS_SECURITY_CONTEXT_FLAG_NONE;
*contextOut = context;
return NTLSTATUS_SUCCESS;
}
// Initializes the root context exactly once before any process is created.
KSTATUS SeInitializeSecurity(void) {
if (gRootSecurityContext)
return NTLSTATUS_SUCCESS;
SECURITY_CONTEXT* context = (SECURITY_CONTEXT*)0;
KSTATUS status = KiCreateSecurityContext(SYS_PRIV_ALL,
SYS_PRIV_ALL,
&context);
if (!KSUCCESS(status))
return status;
gRootSecurityContext = context;
return NTLSTATUS_SUCCESS;
}
// Returns the permanently referenced bootstrap root context.
SECURITY_CONTEXT* SeGetRootSecurityContext(void) {
return gRootSecurityContext;
}
// Derives one child context whose effective and delegable authority are subsets of the source delegable sets.
KSTATUS SeDeriveSecurityContext(SECURITY_CONTEXT* source,
SYS_PRIVILEGES effectivePrivileges,
SYS_PRIVILEGES delegablePrivileges,
SECURITY_CONTEXT** contextOut) {
if (!source || !contextOut)
return NTLSTATUS_INVALID_PARAMETER;
if ((effectivePrivileges & ~source->DelegablePrivileges) != 0 ||
(delegablePrivileges & ~source->DelegablePrivileges) != 0)
return NTLSTATUS_ACCESS_DENIED;
return KiCreateSecurityContext(effectivePrivileges,
delegablePrivileges,
contextOut);
}
// Tests one process's immutable effective privilege mask.
bool SeProcessHasPrivilege(const struct PROCESS* process, SYS_PRIVILEGES privileges) {
if (!process || !process->SecurityContext)
return false;
return (process->SecurityContext->EffectivePrivileges & privileges) == privileges;
}
// Exports immutable context metadata to one public structure.
void SeQuerySecurityContext(const SECURITY_CONTEXT* context, SYS_SECURITY_CONTEXT_INFO* infoOut) {
if (!context || !infoOut)
return;
memset(infoOut, 0, sizeof(*infoOut));
infoOut->Size = sizeof(*infoOut);
infoOut->SecurityId = context->SecurityId;
infoOut->EffectivePrivileges = context->EffectivePrivileges;
infoOut->DelegablePrivileges = context->DelegablePrivileges;
infoOut->Flags = context->Flags;
}