|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
dispatch.c
Abstract:
This module contains code for opening a handle to AFD.
Author:
David Treadwell (davidtr) 21-Feb-1992
Revision History:
--*/
#include "afdp.h"
BOOLEAN AfdPerformSecurityCheck ( PIRP Irp, PIO_STACK_LOCATION IrpSp, PNTSTATUS Status );
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, AfdCreate )
#pragma alloc_text( PAGE, AfdPerformSecurityCheck )
#endif
NTSTATUS FASTCALL AfdCreate ( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp )
/*++
Routine Description:
This is the routine that handles Create IRPs in AFD. If creates an AFD_ENDPOINT structure and fills it in with the information specified in the open packet.
Arguments:
Irp - Pointer to I/O request packet.
IrpSp - pointer to the IO stack location to use for this request.
Return Value:
NTSTATUS -- Indicates whether the request was successfully queued.
--*/
{ PAFD_ENDPOINT endpoint; PFILE_FULL_EA_INFORMATION eaBuffer; UNICODE_STRING transportDeviceName; NTSTATUS status;
PAGED_CODE( );
DEBUG endpoint = NULL;
//
// Find the open packet from the EA buffer in the system buffer of
// the associated IRP. Fail the request if there was no EA
// buffer specified.
//
eaBuffer = Irp->AssociatedIrp.SystemBuffer;
if ( eaBuffer == NULL ) {
//
// Allocate an AFD "helper" endpoint.
//
status = AfdAllocateEndpoint( &endpoint, NULL, 0 );
if( !NT_SUCCESS(status) ) { return status; }
} else { STRING EaName; STRING CString;
EaName.MaximumLength = eaBuffer->EaNameLength+1; EaName.Length = eaBuffer->EaNameLength; EaName.Buffer = eaBuffer->EaName;
if (RtlInitString (&CString, AfdOpenPacket), RtlEqualString(&CString, &EaName, FALSE)) { PAFD_OPEN_PACKET openPacket; ULONG length; openPacket = (PAFD_OPEN_PACKET)(eaBuffer->EaName + eaBuffer->EaNameLength + 1);
//
// Make sure that the transport address fits within the specified
// EA buffer.
//
if ((eaBuffer->EaValueLength<sizeof (*openPacket)) || //
// Make sure the cast to USHORT below is valid
//
(length = openPacket->TransportDeviceNameLength + sizeof (UNICODE_NULL)) > MAXUSHORT || //
// Check for overflow
//
length < openPacket->TransportDeviceNameLength || FIELD_OFFSET(AFD_OPEN_PACKET, TransportDeviceName[length/sizeof (WCHAR)]) < FIELD_OFFSET(AFD_OPEN_PACKET, TransportDeviceName[1]) ||
//
// Check if string + NULL fits into the buffer
//
eaBuffer->EaValueLength < FIELD_OFFSET(AFD_OPEN_PACKET, TransportDeviceName[length/sizeof(WCHAR)]) ) { return STATUS_ACCESS_VIOLATION; } //
// Validate parameters in the open packet.
//
if ( (openPacket->afdEndpointFlags&(~AFD_ENDPOINT_VALID_FLAGS)) || ( (length / sizeof(WCHAR))*sizeof(WCHAR) != length) // odd-value length
) {
return STATUS_INVALID_PARAMETER; }
//
// Set up a string that describes the transport device name.
//
transportDeviceName.Buffer = openPacket->TransportDeviceName; transportDeviceName.Length = (USHORT)openPacket->TransportDeviceNameLength; transportDeviceName.MaximumLength = (USHORT)length;
//
// Allocate an AFD endpoint.
//
status = AfdAllocateEndpoint( &endpoint, &transportDeviceName, openPacket->GroupID );
if( !NT_SUCCESS(status) ) { return status; } //
// Store the flags.
//
endpoint->afdEndpointFlags = openPacket->afdEndpointFlags;
//
// Remember the type of endpoint that this is. If this is a datagram
// endpoint, change the block type to reflect this.
//
if (openPacket->afdConnectionLess) {
endpoint->Type = AfdBlockTypeDatagram;
//
// Initialize lists which exist only in datagram endpoints.
//
InitializeListHead( &endpoint->ReceiveDatagramIrpListHead ); InitializeListHead( &endpoint->PeekDatagramIrpListHead ); InitializeListHead( &endpoint->ReceiveDatagramBufferListHead );
endpoint->Common.Datagram.MaxBufferredReceiveBytes = AfdReceiveWindowSize; endpoint->Common.Datagram.MaxBufferredSendBytes = AfdSendWindowSize; } } else if (RtlInitString (&CString, AfdSwitchOpenPacket), RtlEqualString(&CString, &EaName, FALSE)) { status = AfdSanCreateHelper (Irp, eaBuffer, &endpoint); if (!NT_SUCCESS (status)) return status; } else { IF_DEBUG(OPEN_CLOSE) { KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL, "AfdCreate: Invalid ea name.\n")); } return STATUS_INVALID_PARAMETER; } }
ASSERT( endpoint != NULL );
//
// Perform security check on caller.
// We need this for giving access to raw sockets (for transports
// that do not support access checks) and SAN helpers.
if (IS_SAN_HELPER(endpoint) || (endpoint->afdRaw && (!endpoint->TransportInfo->InfoValid || !IS_TDI_FORCE_ACCESS_CHECK(endpoint)) ) ) { endpoint->AdminAccessGranted = AfdPerformSecurityCheck (Irp, IrpSp, &status); }
//
// Set up a pointer to the endpoint in the file object so that we
// can find the endpoint in future calls.
//
IrpSp->FileObject->FsContext = endpoint; //
// Setting this field to non-NULL value enable fast IO code path
// for reads and writes.
//
IrpSp->FileObject->PrivateCacheMap = (PVOID)-1;
IF_DEBUG(OPEN_CLOSE) { KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL, "AfdCreate: opened file object = %p, endpoint = %p\n", IrpSp->FileObject, endpoint ));
}
//
// The open worked. Dereference the endpoint and return success.
//
DEREFERENCE_ENDPOINT( endpoint );
return STATUS_SUCCESS;
} // AfdCreate
BOOLEAN AfdPerformSecurityCheck ( PIRP Irp, PIO_STACK_LOCATION IrpSp, PNTSTATUS Status ) /*++
Routine Description:
Compares security context of the endpoint creator to that of the administrator and local system.
Arguments:
Irp - Pointer to I/O request packet.
IrpSp - pointer to the IO stack location to use for this request.
Status - returns status generated by access check on failure.
Return Value:
TRUE - the socket creator has admin or local system privilige FALSE - the socket creator is just a plain user
--*/
{ BOOLEAN accessGranted; PACCESS_STATE accessState; PIO_SECURITY_CONTEXT securityContext; PPRIVILEGE_SET privileges = NULL; ACCESS_MASK grantedAccess; PGENERIC_MAPPING GenericMapping; ACCESS_MASK AccessMask = GENERIC_ALL;
//
// Enable access to all the globally defined SIDs
//
GenericMapping = IoGetFileObjectGenericMapping();
RtlMapGenericMask( &AccessMask, GenericMapping );
securityContext = IrpSp->Parameters.Create.SecurityContext; accessState = securityContext->AccessState;
SeLockSubjectContext(&accessState->SubjectSecurityContext);
accessGranted = SeAccessCheck( AfdAdminSecurityDescriptor, &accessState->SubjectSecurityContext, TRUE, AccessMask, 0, &privileges, IoGetFileObjectGenericMapping(), (KPROCESSOR_MODE)((IrpSp->Flags & SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode), &grantedAccess, Status );
if (privileges) { (VOID) SeAppendPrivileges( accessState, privileges ); SeFreePrivileges(privileges); }
if (accessGranted) { accessState->PreviouslyGrantedAccess |= grantedAccess; accessState->RemainingDesiredAccess &= ~( grantedAccess | MAXIMUM_ALLOWED ); ASSERT (NT_SUCCESS (*Status)); } else { ASSERT (!NT_SUCCESS (*Status)); } SeUnlockSubjectContext(&accessState->SubjectSecurityContext);
return accessGranted; }
|