windows-nt/Source/XPSP1/NT/net/sockets/winsock2/wsp/afdsys/create.c
2020-09-26 16:20:57 +08:00

333 lines
8.8 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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;
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)) ||
//
// Check for overflow
//
(FIELD_OFFSET(AFD_OPEN_PACKET,
TransportDeviceName[openPacket->TransportDeviceNameLength/2+1])
<FIELD_OFFSET(AFD_OPEN_PACKET, TransportDeviceName[1])) ||
(eaBuffer->EaValueLength <
FIELD_OFFSET(AFD_OPEN_PACKET,
TransportDeviceName[openPacket->TransportDeviceNameLength/2+1])) ) {
return STATUS_ACCESS_VIOLATION;
}
//
// Validate parameters in the open packet.
//
if (openPacket->afdEndpointFlags&(~AFD_ENDPOINT_VALID_FLAGS)) {
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 =
transportDeviceName.Length + sizeof(WCHAR);
//
// 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 to know whether to allow exclusive
// address use when allocating transport address in bind
// as well as giving access to raw sockets.
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;
}