|
|
/*++
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; }
|