423 lines
9.7 KiB
C
423 lines
9.7 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
SecurSup.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the Named Pipe Security support routines
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Gary Kimura [GaryKi] 06-May-1991
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "NpProcs.h"
|
|||
|
|
|||
|
//
|
|||
|
// The debug trace level
|
|||
|
//
|
|||
|
|
|||
|
#define Dbg (DEBUG_TRACE_SECURSUP)
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, NpCopyClientContext)
|
|||
|
#pragma alloc_text(PAGE, NpImpersonateClientContext)
|
|||
|
#pragma alloc_text(PAGE, NpInitializeSecurity)
|
|||
|
#pragma alloc_text(PAGE, NpGetClientSecurityContext)
|
|||
|
#pragma alloc_text(PAGE, NpUninitializeSecurity)
|
|||
|
#pragma alloc_text(PAGE, NpFreeClientSecurityContext)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NpInitializeSecurity (
|
|||
|
IN PCCB Ccb,
|
|||
|
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
|
|||
|
IN PETHREAD UserThread
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine initializes the security (impersonation) fields
|
|||
|
in the ccb. It is called when the client end gets opened.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Ccb - Supplies the ccb being initialized
|
|||
|
|
|||
|
SecurityQos - Supplies the clients quality of service parameter
|
|||
|
|
|||
|
UserThread - Supplise the client's user thread
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Returns the result of the operation
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
DebugTrace(+1, Dbg, "NpInitializeSecurity, Ccb = %08lx\n", Ccb);
|
|||
|
|
|||
|
//
|
|||
|
// Either copy the security qos parameter, if it is not null or
|
|||
|
// create a dummy qos
|
|||
|
//
|
|||
|
|
|||
|
if (SecurityQos != NULL) {
|
|||
|
|
|||
|
RtlCopyMemory( &Ccb->SecurityQos,
|
|||
|
SecurityQos,
|
|||
|
sizeof(SECURITY_QUALITY_OF_SERVICE) );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
Ccb->SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
|
|||
|
Ccb->SecurityQos.ImpersonationLevel = SecurityImpersonation;
|
|||
|
Ccb->SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
|||
|
Ccb->SecurityQos.EffectiveOnly = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Because we might be asked to reinitialize the ccb we need
|
|||
|
// to first check if the security client context is not null and if so then
|
|||
|
// free its pool and zero out the context pointer so that if we raise out
|
|||
|
// this time then a second time through the code we won't try and free the
|
|||
|
// pool twice.
|
|||
|
//
|
|||
|
|
|||
|
if (Ccb->SecurityClientContext != NULL) {
|
|||
|
|
|||
|
SeDeleteClientSecurity( Ccb->SecurityClientContext );
|
|||
|
NpFreePool( Ccb->SecurityClientContext );
|
|||
|
Ccb->SecurityClientContext = NULL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the tracking mode is static then we need to capture the
|
|||
|
// client context now otherwise we set the client context field
|
|||
|
// to null
|
|||
|
//
|
|||
|
|
|||
|
if (Ccb->SecurityQos.ContextTrackingMode == SECURITY_STATIC_TRACKING) {
|
|||
|
|
|||
|
//
|
|||
|
// Allocate a client context record, and then initialize it
|
|||
|
//
|
|||
|
|
|||
|
Ccb->SecurityClientContext = NpAllocatePagedPoolWithQuota ( sizeof(SECURITY_CLIENT_CONTEXT), 'sFpN' );
|
|||
|
if (Ccb->SecurityClientContext == NULL) {
|
|||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
} else {
|
|||
|
DebugTrace(0, Dbg, "Static tracking, ClientContext = %08lx\n", Ccb->SecurityClientContext);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status = SeCreateClientSecurity( UserThread,
|
|||
|
&Ccb->SecurityQos,
|
|||
|
FALSE,
|
|||
|
Ccb->SecurityClientContext ))) {
|
|||
|
|
|||
|
DebugTrace(0, Dbg, "Not successful at creating client security, %08lx\n", Status);
|
|||
|
|
|||
|
NpFreePool( Ccb->SecurityClientContext );
|
|||
|
Ccb->SecurityClientContext = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
DebugTrace(0, Dbg, "Dynamic tracking\n", 0);
|
|||
|
|
|||
|
Ccb->SecurityClientContext = NULL;
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "NpInitializeSecurity -> %08lx\n", Status);
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
NpUninitializeSecurity (
|
|||
|
IN PCCB Ccb
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine deletes the client context referenced by the ccb
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Ccb - Supplies the ccb being uninitialized
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
DebugTrace(+1, Dbg, "NpUninitializeSecurity, Ccb = %08lx\n", Ccb);
|
|||
|
|
|||
|
//
|
|||
|
// We only have work to do if the client context field is not null
|
|||
|
// and then we need to delete the client context, and free the memory.
|
|||
|
//
|
|||
|
|
|||
|
if (Ccb->SecurityClientContext != NULL) {
|
|||
|
|
|||
|
DebugTrace(0, Dbg, "Delete client context, %08lx\n", Ccb->SecurityClientContext);
|
|||
|
|
|||
|
SeDeleteClientSecurity( Ccb->SecurityClientContext );
|
|||
|
|
|||
|
NpFreePool( Ccb->SecurityClientContext );
|
|||
|
Ccb->SecurityClientContext = NULL;
|
|||
|
}
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "NpUninitializeSecurity -> VOID\n", 0);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
NpFreeClientSecurityContext (
|
|||
|
IN PSECURITY_CLIENT_CONTEXT SecurityContext
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine frees previously captured security context.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SecurityContext - Previously captured security context.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
if (SecurityContext != NULL) {
|
|||
|
SeDeleteClientSecurity (SecurityContext);
|
|||
|
NpFreePool (SecurityContext );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NpGetClientSecurityContext (
|
|||
|
IN NAMED_PIPE_END NamedPipeEnd,
|
|||
|
IN PCCB Ccb,
|
|||
|
IN PETHREAD UserThread,
|
|||
|
OUT PSECURITY_CLIENT_CONTEXT *ppSecurityContext
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine captures a new client context and stores it in the indicated
|
|||
|
data entry, but only if the tracking mode is dynamic and only for the
|
|||
|
client end of the named pipe.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NamedPipeEnd - Indicates the client or server end of the named pipe.
|
|||
|
Only the client end does anything.
|
|||
|
|
|||
|
Ccb - Supplies the ccb for this instance of the named pipe.
|
|||
|
|
|||
|
DataEntry - Supplies the data entry to use to store the client context
|
|||
|
|
|||
|
UserThread - Supplies the thread of the client
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Returns our success code.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PSECURITY_CLIENT_CONTEXT SecurityContext;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
DebugTrace(+1, Dbg, "NpSetDataEntryClientContext, Ccb = %08lx\n", Ccb);
|
|||
|
|
|||
|
//
|
|||
|
// Only do the work if this is the client end and tracking is dynamic
|
|||
|
//
|
|||
|
|
|||
|
if ((NamedPipeEnd == FILE_PIPE_CLIENT_END) &&
|
|||
|
(Ccb->SecurityQos.ContextTrackingMode == SECURITY_DYNAMIC_TRACKING)) {
|
|||
|
|
|||
|
//
|
|||
|
// Allocate a client context record, and then initialize it
|
|||
|
//
|
|||
|
|
|||
|
SecurityContext = NpAllocatePagedPoolWithQuota (sizeof(SECURITY_CLIENT_CONTEXT), 'sFpN');
|
|||
|
if (SecurityContext == NULL) {
|
|||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
}
|
|||
|
|
|||
|
DebugTrace(0, Dbg, "Client End, Dynamic Tracking, ClientContext = %08lx\n", DataEntry->SecurityClientContext);
|
|||
|
|
|||
|
if (!NT_SUCCESS (Status = SeCreateClientSecurity (UserThread,
|
|||
|
&Ccb->SecurityQos,
|
|||
|
FALSE,
|
|||
|
SecurityContext))) {
|
|||
|
|
|||
|
DebugTrace(0, Dbg, "Not successful at creating client security, %08lx\n", Status);
|
|||
|
|
|||
|
NpFreePool (SecurityContext);
|
|||
|
SecurityContext = NULL;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
DebugTrace(0, Dbg, "Static Tracking or Not Client End\n", 0);
|
|||
|
|
|||
|
SecurityContext = NULL;
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "NpSetDataEntryClientContext -> %08lx\n", Status);
|
|||
|
|
|||
|
*ppSecurityContext = SecurityContext;
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
NpCopyClientContext (
|
|||
|
IN PCCB Ccb,
|
|||
|
IN PDATA_ENTRY DataEntry
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine copies the client context stored in the data entry into
|
|||
|
the ccb, but only for dynamic tracking.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Ccb - Supplies the ccb to update.
|
|||
|
|
|||
|
DataEntry - Supplies the DataEntry to copy from.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
DebugTrace(+1, Dbg, "NpCopyClientContext, Ccb = %08lx\n", Ccb);
|
|||
|
|
|||
|
//
|
|||
|
// Only do the copy if the data entries client context field is not null
|
|||
|
// which means that we are doing dynamic tracking. Note we will
|
|||
|
// not be called with a server write data entry that has a non null
|
|||
|
// client context.
|
|||
|
//
|
|||
|
|
|||
|
if (DataEntry->SecurityClientContext != NULL) {
|
|||
|
|
|||
|
DebugTrace(0, Dbg, "have something to copy %08lx\n", DataEntry->SecurityClientContext);
|
|||
|
|
|||
|
//
|
|||
|
// First check if we need to delete and deallocate the client
|
|||
|
// context in the nonpaged ccb
|
|||
|
//
|
|||
|
|
|||
|
if (Ccb->SecurityClientContext != NULL) {
|
|||
|
|
|||
|
DebugTrace(0, Dbg, "Remove current client context %08lx\n", Ccb->SecurityClientContext);
|
|||
|
|
|||
|
SeDeleteClientSecurity (Ccb->SecurityClientContext);
|
|||
|
|
|||
|
NpFreePool (Ccb->SecurityClientContext);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now copy over the reference to the client context, and zero
|
|||
|
// out the reference in the data entry.
|
|||
|
//
|
|||
|
|
|||
|
Ccb->SecurityClientContext = DataEntry->SecurityClientContext;
|
|||
|
DataEntry->SecurityClientContext = NULL;
|
|||
|
}
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "NpCopyClientContext -> VOID\n", 0 );
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NpImpersonateClientContext (
|
|||
|
IN PCCB Ccb
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine impersonates the current client context stored in the
|
|||
|
ccb
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Ccb - Supplies the ccb for the named pipe
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - returns our status code.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
DebugTrace(+1, Dbg, "NpImpersonateClientContext, Ccb = %08lx\n", Ccb);
|
|||
|
|
|||
|
if (Ccb->SecurityClientContext == NULL) {
|
|||
|
|
|||
|
DebugTrace(0, Dbg, "Cannot impersonate\n", 0);
|
|||
|
|
|||
|
Status = STATUS_CANNOT_IMPERSONATE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
Status = SeImpersonateClientEx( Ccb->SecurityClientContext, NULL );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "NpImpersonateClientContext -> %08lx\n", Status);
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|