|
|
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
ntinit.c
Abstract:
NT specific routines for loading and configuring the TCP/UDP driver.
Author:
Mike Massa (mikemas) Aug 13, 1993
Revision History:
Who When What -------- -------- ---------------------------------------------- mikemas 08-13-93 created
Notes:
--*/
#include "precomp.h"
#if !MILLEN
#include <ipfilter.h>
#include <ipsec.h>
#endif // !MILLEN
#include "tdint.h"
#include "addr.h"
#include "tcp.h"
#include "tcb.h"
#include "udp.h"
#include "raw.h"
#include "tcpconn.h"
#include "mdlpool.h"
#include "pplasl.h"
#include "tcprcv.h"
#include "tcpsend.h"
#include "tlcommon.h"
#include "tcpcfg.h"
#include "secfltr.h"
#include "info.h"
#if GPC
#include <qos.h>
#include <traffic.h>
#include "gpcifc.h"
#include "ntddtc.h"
GPC_HANDLE hGpcClient[GPC_CF_MAX] = {0}; ulong GpcCfCounts[GPC_CF_MAX] = {0}; GPC_EXPORTED_CALLS GpcEntries; GPC_CLIENT_FUNC_LIST GpcHandlers;
ulong GPCcfInfo = 0;
GPC_STATUS GPCcfInfoAddNotifyIpsec(GPC_CLIENT_HANDLE ClCtxt, GPC_HANDLE GpcHandle, PTC_INTERFACE_ID InterfaceInfo, ULONG CfInfoSize, PVOID CfInfo, PGPC_CLIENT_HANDLE pClInfoCxt);
GPC_STATUS GPCcfInfoRemoveNotifyIpsec(GPC_CLIENT_HANDLE ClCtxt, GPC_CLIENT_HANDLE ClInfoCxt);
GPC_STATUS GPCcfInfoAddNotifyQoS(GPC_CLIENT_HANDLE ClCtxt, GPC_HANDLE GpcHandle, PTC_INTERFACE_ID InterfaceInfo, ULONG CfInfoSize, PVOID CfInfo, PGPC_CLIENT_HANDLE pClInfoCxt);
GPC_STATUS GPCcfInfoRemoveNotifyQoS(GPC_CLIENT_HANDLE ClCtxt, GPC_CLIENT_HANDLE ClInfoCxt);
#endif
ReservedPortListEntry *PortRangeList = NULL;
VOID GetReservedPortList( NDIS_HANDLE ConfigHandle );
//
// Global variables.
//
PDRIVER_OBJECT TCPDriverObject = NULL; PDEVICE_OBJECT TCPDeviceObject = NULL; PDEVICE_OBJECT UDPDeviceObject = NULL; PDEVICE_OBJECT RawIPDeviceObject = NULL;
extern PDEVICE_OBJECT IPDeviceObject;
TCPXSUM_ROUTINE tcpxsum_routine = tcpxsum;
#if ACC
PSECURITY_DESCRIPTOR TcpAdminSecurityDescriptor; extern uint AllowUserRawAccess;
typedef ULONG SECURITY_INFORMATION;
BOOLEAN IsRunningOnPersonal ( VOID );
#endif
extern uint DisableLargeSendOffload;
//
//Place holder for Maximum duplicate acks we would like
//to see before we do fast retransmit
//
extern uint MaxDupAcks;
MM_SYSTEMSIZE systemSize;
extern uint MaxHashTableSize; extern uint NumTcbTablePartitions; extern uint PerPartitionSize; extern uint LogPerPartitionSize; #define CACHE_LINE_SIZE 64
#define CACHE_ALIGN_MASK (~(CACHE_LINE_SIZE-1))
CTELock *pTWTCBTableLock; CTELock *pTCBTableLock;
CTELock *pSynTCBTableLock;
extern Queue *TWQueue;
extern Queue *TWTCBTable; extern TCB **TCBTable; extern Queue *SYNTCBTable;
extern PTIMER_WHEEL TimerWheel; PTIMER_WHEEL OrgTimerWheel;
extern TCPConn **ConnTable; extern uint MaxConnBlocks; extern uint ConnPerBlock;
extern uint GlobalMaxRcvWin;
extern uint TcpHostOpts; extern uint TcpHostSendOpts;
HANDLE TCPRegistrationHandle; HANDLE UDPRegistrationHandle; HANDLE IPRegistrationHandle;
//SynAttackProtect=0 no syn flood attack protection
//SynAttackProtect !0 syn flood attack protection
//SynAttackProtect !0 syn flood attack protection+forced(non-dynamic)
// delayed connect acceptance
uint SynAttackProtect; // SYN-attack protection checks are made
uint TCPMaxHalfOpen; //Max # of half-open connections allowed
// before we dec. the syn-ack retries
uint TCPMaxHalfOpenRetried; //Max # of half-open conn. that have
// been retried at least 1 time
uint TCPMaxHalfOpenRetriedLW; //Low-watermark of the above. When
// go down to it, we revert to normal
// # of retries for syn-acks
uint TCPHalfOpen; //# of half-open connections
uint TCPHalfOpenRetried; //# of half-open conn. that have been
//retried at least once
PDEVICE_OBJECT IPSECDeviceObject; PFILE_OBJECT IPSECFileObject;
extern uint Time_Proc;
extern HANDLE TcbPool; extern HANDLE TimewaitTcbPool; extern HANDLE SynTcbPool;
extern void ArpUnload(PDRIVER_OBJECT); extern CTETimer TCBTimer[]; extern BOOLEAN fTCBTimerStopping; extern CTEBlockStruc TcpipUnloadBlock; HANDLE AddressChangeHandle;
extern ulong DefaultTOSValue; extern ulong DisableUserTOSSetting; extern uint MaxSendSegments;
//
// External function prototypes
//
int tlinit( void );
NTSTATUS TCPDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS TCPDispatchInternalDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS IPDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS IPDriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath );
NTSTATUS IPPostDriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath );
NTSTATUS GetRegMultiSZValue( HANDLE KeyHandle, PWCHAR ValueName, PUNICODE_STRING ValueData );
PWCHAR EnumRegMultiSz( IN PWCHAR MszString, IN ULONG MszStringLength, IN ULONG StringIndex );
uint InitIsnGenerator(); #if !MILLEN
extern ulong g_cRandIsnStore; #endif // !MILLEN
#if MILLEN
extern VOID InitializeWDebDebug(); #endif // MILLEN
//
// Local funcion prototypes
//
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath );
void * TLRegisterProtocol( uchar Protocol, void *RcvHandler, void *XmitHandler, void *StatusHandler, void *RcvCmpltHandler, void *PnPHandler, void *ElistHandler );
IP_STATUS TLGetIPInfo( IPInfo * Buffer, int Size );
uchar TCPGetConfigInfo( void );
NTSTATUS TCPInitializeParameter( HANDLE KeyHandle, PWCHAR ValueName, PULONG Value );
#if !MILLEN
NTSTATUS IpsecInitialize( void );
NTSTATUS IpsecDeinitialize( void ); #endif
#if !MILLEN
#ifdef i386
NTSTATUS TCPSetChecksumRoutine( VOID ); #endif
#endif // !MILLEN
uint EnumSecurityFilterValue( PNDIS_STRING FilterList, ulong Index, ulong * FilterValue );
VOID TCPAcdBind();
#ifdef ACC
typedef ULONG SECURITY_INFORMATION;
NTSTATUS TcpBuildDeviceAcl( OUT PACL * DeviceAcl );
NTSTATUS TcpCreateAdminSecurityDescriptor( VOID );
NTSTATUS AddNetConfigOpsAce(IN PACL Dacl, OUT PACL * DeviceAcl ); NTSTATUS CreateDeviceDriverSecurityDescriptor(PVOID DeviceOrDriverObject );
#endif // ACC
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(INIT, TLRegisterProtocol)
#pragma alloc_text(INIT, TLGetIPInfo)
#pragma alloc_text(INIT, TCPGetConfigInfo)
#pragma alloc_text(INIT, TCPInitializeParameter)
#if !MILLEN
#pragma alloc_text(INIT, IpsecInitialize)
#endif
#if !MILLEN
#ifdef i386
#pragma alloc_text(INIT, TCPSetChecksumRoutine)
#endif
#endif // !MILLEN
#pragma alloc_text(PAGE, EnumSecurityFilterValue)
#pragma alloc_text(INIT, TCPAcdBind)
#ifdef ACC
#pragma alloc_text(INIT, TcpBuildDeviceAcl)
#pragma alloc_text(INIT, TcpCreateAdminSecurityDescriptor)
#pragma alloc_text(INIT, AddNetConfigOpsAce)
#pragma alloc_text(INIT, CreateDeviceDriverSecurityDescriptor)
#endif // ACC
#endif
//
// Function definitions
//
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) /*++
Routine Description:
Initialization routine for the TCP/UDP driver.
Arguments:
DriverObject - Pointer to the TCP driver object created by the system. DeviceDescription - The name of TCP's node in the registry.
Return Value:
The final status from the initialization operation.
--*/
{ NTSTATUS status; UNICODE_STRING deviceName; UNICODE_STRING SymbolicDeviceName; USHORT i; int initStatus;
DEBUGMSGINIT();
DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("+DriverEntry(%x, %x)\n"), DriverObject, RegistryPath));
TdiInitialize();
//
// IP calls the security filter code, so initialize it first.
//
InitializeSecurityFilters();
//
// Initialize IP
//
status = IPDriverEntry(DriverObject, RegistryPath);
if (!NT_SUCCESS(status)) { DEBUGMSG(DBG_ERROR && DBG_INIT, (DTEXT("TCPIP: IP Initialization failure %x\n"), status)); DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-DriverEntry [%x]\n"), status)); return (status); }
#if !MILLEN
//
// Initialize IPSEC
//
status = IpsecInitialize();
if (!NT_SUCCESS(status)) { DEBUGMSG(DBG_ERROR && DBG_INIT, (DTEXT("TCPIP: IPSEC Initialization failure %x\n"), status)); DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-DriverEntry [%x]\n"), status));
goto init_failed; } #endif
//
// Initialize TCP, UDP, and RawIP
//
TCPDriverObject = DriverObject;
//
// Create the device objects. IoCreateDevice zeroes the memory
// occupied by the object.
//
RtlInitUnicodeString(&deviceName, DD_TCP_DEVICE_NAME); RtlInitUnicodeString(&SymbolicDeviceName, DD_TCP_SYMBOLIC_DEVICE_NAME);
status = IoCreateDevice( DriverObject, 0, &deviceName, FILE_DEVICE_NETWORK, FILE_DEVICE_SECURE_OPEN, FALSE, &TCPDeviceObject );
if (!NT_SUCCESS(status)) { CTELogEvent( DriverObject, EVENT_TCPIP_CREATE_DEVICE_FAILED, 1, 1, &deviceName.Buffer, 0, NULL );
DEBUGMSG(DBG_ERROR && DBG_INIT, (DTEXT("DriverEntry: failure %x to create TCP device object %ws\n"), status, DD_TCP_DEVICE_NAME));
goto init_failed; }
status = IoCreateSymbolicLink(&SymbolicDeviceName, &deviceName);
if (!NT_SUCCESS(status)) { CTELogEvent( DriverObject, EVENT_TCPIP_CREATE_DEVICE_FAILED, 1, 1, &deviceName.Buffer, 0, NULL );
DEBUGMSG(DBG_ERROR && DBG_INIT, (DTEXT("DriverEntry: failure %x to create TCP symbolic device link %ws\n"), status, DD_TCP_SYMBOLIC_DEVICE_NAME));
goto init_failed; }
RtlInitUnicodeString(&deviceName, DD_UDP_DEVICE_NAME);
status = IoCreateDevice( DriverObject, 0, &deviceName, FILE_DEVICE_NETWORK, FILE_DEVICE_SECURE_OPEN, FALSE, &UDPDeviceObject );
if (!NT_SUCCESS(status)) { CTELogEvent( DriverObject, EVENT_TCPIP_CREATE_DEVICE_FAILED, 1, 1, &deviceName.Buffer, 0, NULL );
TCPTRACE(( "TCP: Failed to create UDP device object, status %lx\n", status )); goto init_failed; } RtlInitUnicodeString(&deviceName, DD_RAW_IP_DEVICE_NAME);
status = IoCreateDevice( DriverObject, 0, &deviceName, FILE_DEVICE_NETWORK, FILE_DEVICE_SECURE_OPEN, FALSE, &RawIPDeviceObject );
if (!NT_SUCCESS(status)) { CTELogEvent( DriverObject, EVENT_TCPIP_CREATE_DEVICE_FAILED, 1, 1, &deviceName.Buffer, 0, NULL );
TCPTRACE(( "TCP: Failed to create Raw IP device object, status %lx\n", status )); goto init_failed; } //
// Initialize the driver object
//
DriverObject->DriverUnload = ArpUnload;
DriverObject->FastIoDispatch = NULL; for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { DriverObject->MajorFunction[i] = TCPDispatch; }
//
// We special case Internal Device Controls because they are the
// hot path for kernel-mode clients.
//
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = TCPDispatchInternalDeviceControl;
//
// Intialize the device objects.
//
TCPDeviceObject->Flags |= DO_DIRECT_IO; UDPDeviceObject->Flags |= DO_DIRECT_IO; RawIPDeviceObject->Flags |= DO_DIRECT_IO;
#ifdef ACC
// Change the different devices and Objects to allow access to Network Configuration Operators
if (!IsRunningOnPersonal()) {
status = CreateDeviceDriverSecurityDescriptor(IPDeviceObject); if (!NT_SUCCESS(status)) { goto init_failed; }
status = CreateDeviceDriverSecurityDescriptor(TCPDeviceObject); if (!NT_SUCCESS(status)) { goto init_failed; }
status = CreateDeviceDriverSecurityDescriptor(IPSECDeviceObject); if (!NT_SUCCESS(status)) { goto init_failed; } }
//
// Create the security descriptor used for raw socket access checks.
//
status = TcpCreateAdminSecurityDescriptor();
if (!NT_SUCCESS(status)) { goto init_failed; } #endif // ACC
#if !MILLEN
#ifdef i386
//
// Set the checksum routine pointer according to the processor available
//
TCPSetChecksumRoutine(); #endif
#endif // !MILLEN
//
// Finally, initialize the stack.
//
initStatus = tlinit();
if (initStatus == TRUE) { //
// Get the automatic connection driver
// entry points.
//
TCPAcdBind();
RtlInitUnicodeString(&deviceName, DD_TCP_DEVICE_NAME); (void)TdiRegisterDeviceObject(&deviceName, &TCPRegistrationHandle);
RtlInitUnicodeString(&deviceName, DD_UDP_DEVICE_NAME); (void)TdiRegisterDeviceObject(&deviceName, &UDPRegistrationHandle);
RtlInitUnicodeString(&deviceName, DD_RAW_IP_DEVICE_NAME); (void)TdiRegisterDeviceObject(&deviceName, &IPRegistrationHandle);
#if GPC
status = GpcInitialize(&GpcEntries);
if (!NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"GpcInitialize Failed! Status: 0x%x\n", status));
//return status;
} else { //
// Need to register as GPC client. Try it now.
// we register clients for QOS and IPSEC
//
memset(&GpcHandlers, 0, sizeof(GPC_CLIENT_FUNC_LIST));
GpcHandlers.ClAddCfInfoNotifyHandler = GPCcfInfoAddNotifyQoS; GpcHandlers.ClRemoveCfInfoNotifyHandler = GPCcfInfoRemoveNotifyQoS;
status = GpcEntries.GpcRegisterClientHandler( GPC_CF_QOS, // classification family
0, // flags
1, // default max priority
&GpcHandlers, // client notification vector - no notifications to TCPIP required
0, // client context, not needed
&hGpcClient[GPC_CF_QOS]);
if (!NT_SUCCESS(status)) { KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"GPC registerclient QOS status %x hGpcClient %p\n", status, hGpcClient[GPC_CF_QOS])); hGpcClient[GPC_CF_QOS] = NULL; } GpcHandlers.ClAddCfInfoNotifyHandler = GPCcfInfoAddNotifyIpsec; GpcHandlers.ClRemoveCfInfoNotifyHandler = GPCcfInfoRemoveNotifyIpsec;
status = GpcEntries.GpcRegisterClientHandler( GPC_CF_IPSEC, // classification family
0, // flags
GPC_PRIORITY_IPSEC, // default max priority
&GpcHandlers, // client notification vector - no notifications to TCPIP required
0, // client context, not needed
&hGpcClient[GPC_CF_IPSEC]);
if (!NT_SUCCESS(status)) { KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"GPC registerclient IPSEC status %x hGpcClient %p\n", status, hGpcClient[GPC_CF_IPSEC])); hGpcClient[GPC_CF_IPSEC] = NULL; } } #endif
if (InitIsnGenerator() == FALSE) { DEBUGMSG(DBG_ERROR && DBG_INIT, (DTEXT("InitIsnGenerator failure. TCP/IP failing to start.\n"))); DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-DriverEntry [%x]\n"), status)); return (STATUS_UNSUCCESSFUL); }
// do the ndis register protocol now after all the intialization
// is complete, o/w we get bindadapter even before we r fully
// initialized.
status = IPPostDriverEntry(DriverObject, RegistryPath); if (!NT_SUCCESS(status)) {
DEBUGMSG(DBG_ERROR && DBG_INIT, (DTEXT("TCPIP: IP post-init failure %x\n"), status)); DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-DriverEntry [%x]\n"), status)); return (status); }
// Millennium TCPIP has debugger extensions built in!
#if MILLEN
InitializeWDebDebug(); #endif // MILLEN
#if TRACE_EVENT
//
// Register with WMI for Enable/Disable Notification
// of Trace Logging
//
TCPCPHandlerRoutine = NULL;
IoWMIRegistrationControl( TCPDeviceObject, WMIREG_ACTION_REGISTER | WMIREG_FLAG_TRACE_PROVIDER | WMIREG_NOTIFY_TDI_IO ); #endif
//
// Initialize the connection callback object. We do not treat its
// failure as fatal, and continue to function even in case of failure.
// We may log it in the future.
//
TcpInitCcb();
DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-DriverEntry [SUCCESS]\n"))); return (STATUS_SUCCESS); }
DEBUGMSG(DBG_ERROR && DBG_INIT, (DTEXT("TCPIP: TCP initialization failed, IP still available.\n")));
CTELogEvent( DriverObject, EVENT_TCPIP_TCP_INIT_FAILED, 1, 0, NULL, 0, NULL ); status = STATUS_UNSUCCESSFUL;
init_failed:
DEBUGMSG(DBG_ERROR && DBG_INIT, (DTEXT("TCPIP DriverEntry initialization failure!\n"))); //
// IP has successfully started, but TCP & UDP failed. Set the
// Dispatch routine to point to IP only, since the TCP and UDP
// devices don't exist.
//
if (TCPDeviceObject != NULL) { IoDeleteDevice(TCPDeviceObject); } if (UDPDeviceObject != NULL) { IoDeleteDevice(UDPDeviceObject); } if (RawIPDeviceObject != NULL) { IoDeleteDevice(RawIPDeviceObject); } for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { DriverObject->MajorFunction[i] = IPDispatch; }
#if !MILLEN
if (IPSECFileObject) { IpsecDeinitialize(); } #endif
return (status); }
#if !MILLEN
#ifdef i386
NTSTATUS TCPSetChecksumRoutine( VOID ) /*++
Routine Description:
This routine sets the checksum routine function pointer to the appropriate routine based on the processor features available
Arguments:
None
Return Value:
STATUS_SUCCESS - if successful
--*/
{
NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
if (ExIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) { tcpxsum_routine = tcpxsum_xmmi; KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip: Loading XMMI Prefetch Checksum\n")); Status = STATUS_SUCCESS; } return Status;
}
#endif
#endif // !MILLEN
IP_STATUS TLGetIPInfo( IPInfo * Buffer, int Size ) /*++
Routine Description:
Returns information necessary for TCP to call into IP.
Arguments:
Buffer - A pointer to the IP information structure.
Size - The size of Buffer.
Return Value:
The IP status of the operation.
--*/
{ return (IPGetInfo(Buffer, Size)); }
void * TLRegisterProtocol( uchar Protocol, void *RcvHandler, void *XmitHandler, void *StatusHandler, void *RcvCmpltHandler, void *PnPHandler, void *ElistHandler ) /*++
Routine Description:
Calls the IP driver's protocol registration function.
Arguments:
Protocol - The protocol number to register.
RcvHandler - Transport's packet receive handler.
XmitHandler - Transport's packet transmit complete handler.
StatusHandler - Transport's status update handler.
RcvCmpltHandler - Transport's receive complete handler
Return Value:
A context value for the protocol to pass to IP when transmitting.
--*/
{ return (IPRegisterProtocol( Protocol, RcvHandler, XmitHandler, StatusHandler, RcvCmpltHandler, PnPHandler, ElistHandler)); }
//
// Interval in milliseconds between keepalive transmissions until a
// response is received.
//
#define DEFAULT_KEEPALIVE_INTERVAL 1000
//
// time to first keepalive transmission. 2 hours == 7,200,000 milliseconds
//
#define DEFAULT_KEEPALIVE_TIME 7200000
#define MIN_THRESHOLD_MAX_HO 1
#define MIN_THRESHOLD_MAX_HO_RETRIED 80
uchar TCPGetConfigInfo( void ) /*++
Routine Description:
Initializes TCP global configuration parameters.
Arguments:
None.
Return Value:
Zero on failure, nonzero on success.
--*/
{ HANDLE keyHandle; NTSTATUS status; OBJECT_ATTRIBUTES objectAttributes; UNICODE_STRING UKeyName; ULONG maxConnectRexmits = 0; ULONG maxConnectResponseRexmits = 0; ULONG maxDataRexmits = 0; ULONG pptpmaxDataRexmits = 0; ULONG useRFC1122UrgentPointer = 0; ULONG tcp1323opts = 3; //turning off 1323 options by default
ULONG SackOpts; ULONG i, j;
DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("+TCPGetConfigInfo()\n")));
//
// Initialize to the defaults in case an error occurs somewhere.
//
KAInterval = DEFAULT_KEEPALIVE_INTERVAL; KeepAliveTime = DEFAULT_KEEPALIVE_TIME; PMTUDiscovery = TRUE; PMTUBHDetect = FALSE; DeadGWDetect = TRUE; DefaultRcvWin = 0; // Automagically pick a reasonable one.
MaxConnections = DEFAULT_MAX_CONNECTIONS; maxConnectRexmits = MAX_CONNECT_REXMIT_CNT; maxConnectResponseRexmits = MAX_CONNECT_RESPONSE_REXMIT_CNT; pptpmaxDataRexmits = maxDataRexmits = MAX_REXMIT_CNT; BSDUrgent = TRUE; FinWait2TO = FIN_WAIT2_TO; NTWMaxConnectCount = NTW_MAX_CONNECT_COUNT; NTWMaxConnectTime = NTW_MAX_CONNECT_TIME; MaxUserPort = DEFAULT_MAX_USER_PORT;
// Default number of duplicate acks
MaxDupAcks = 2;
SynAttackProtect = 0; //by default it is always off
#if MILLEN
TCPMaxHalfOpen = 100; TCPMaxHalfOpenRetried = 80; #else // MILLEN
if (!MmIsThisAnNtAsSystem()) { TCPMaxHalfOpen = 100; TCPMaxHalfOpenRetried = 80; } else { TCPMaxHalfOpen = 500; TCPMaxHalfOpenRetried = 400; } #endif // !MILLEN
SecurityFilteringEnabled = FALSE;
#ifdef ACC
AllowUserRawAccess = FALSE; #endif
//
// Read the TCP optional (hidden) registry parameters.
//
#if !MILLEN
RtlInitUnicodeString( &UKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tcpip\\Parameters" ); #else // !MILLEN
RtlInitUnicodeString( &UKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\VxD\\MSTCP" ); #endif // MILLEN
DEBUGMSG(DBG_INFO && DBG_INIT, (DTEXT("TCPGetConfigInfo: Opening key %ws\n"), UKeyName.Buffer));
memset(&objectAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
InitializeObjectAttributes( &objectAttributes, &UKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL );
status = ZwOpenKey( &keyHandle, KEY_READ, &objectAttributes );
DEBUGMSG(!NT_SUCCESS(status) && DBG_ERROR, (DTEXT("TCPGetConfigInfo: failed to open TCP registry configuration: %ws\n"), UKeyName.Buffer));
if (NT_SUCCESS(status)) {
DEBUGMSG(DBG_INFO && DBG_INIT, (DTEXT("TCPGetConfigInfo: successfully opened registry to read.\n"))); #if !MILLEN
TCPInitializeParameter( keyHandle, L"IsnStoreSize", &g_cRandIsnStore ); #endif // !MILLEN
TCPInitializeParameter( keyHandle, L"KeepAliveInterval", (PULONG)&KAInterval );
TCPInitializeParameter( keyHandle, L"KeepAliveTime", (PULONG)&KeepAliveTime );
status = TCPInitializeParameter( keyHandle, L"EnablePMTUBHDetect", (PULONG)&PMTUBHDetect );
#if MILLEN
//
// Backwards compatibility. If 'EnablePMTUBHDetect' value does not exist,
// then attempt to read legacy 'PMTUBlackHoleDetect'.
//
if (!NT_SUCCESS(status)) { TCPInitializeParameter( keyHandle, L"PMTUBlackHoleDetect", &PMTUBHDetect ); } #endif // MILLEN
status = TCPInitializeParameter( keyHandle, L"TcpWindowSize", (PULONG)&DefaultRcvWin );
#if MILLEN
//
// Backwards compatibility. If 'TcpWindowSize' value does not exist,
// then attempt to read legacy 'DefaultRcvWindow'.
//
if (!NT_SUCCESS(status)) { TCPInitializeParameter( keyHandle, L"DefaultRcvWindow", &DefaultRcvWin ); } #endif // MILLEN
// We can not have negative size windows
if ( (LONG) DefaultRcvWin < 0 ) { DefaultRcvWin = TCP_MAX_SCALED_WIN; }
status = TCPInitializeParameter( keyHandle, L"TcpNumConnections", (PULONG)&MaxConnections );
#if MILLEN
//
// Backwards compatibility. If 'TcpNumConnections' value does not exist,
// then attempt to read legacy 'MaxConnections'.
//
if (!NT_SUCCESS(status)) { TCPInitializeParameter( keyHandle, L"MaxConnections", &MaxConnections ); } #endif // MILLEN
status = TCPInitializeParameter( keyHandle, L"TcpMaxConnectRetransmissions", &maxConnectRexmits );
#if MILLEN
//
// Backwards compatibility. If 'TcpMaxConnectRetransmissions' value does not exist,
// then attempt to read legacty 'MaxConnectRetries'.
//
if (!NT_SUCCESS(status)) { TCPInitializeParameter( keyHandle, L"MaxConnectRetries", &maxConnectRexmits ); } #endif // MILLEN
if (maxConnectRexmits > 255) { maxConnectRexmits = 255; } TCPInitializeParameter( keyHandle, L"TcpMaxConnectResponseRetransmissions", &maxConnectResponseRexmits );
if (maxConnectResponseRexmits > 255) { maxConnectResponseRexmits = 255; }
status = TCPInitializeParameter( keyHandle, L"TcpMaxDataRetransmissions", &maxDataRexmits );
#if MILLEN
//
// Backwards compatibility. If 'TcpMaxDataRetransmissions' value does not exist,
// then attempt to read legacy 'MaxDataRetries'.
//
if (!NT_SUCCESS(status)) { TCPInitializeParameter( keyHandle, L"MaxDataRetries", &maxDataRexmits ); } #endif // MILLEN
if (maxDataRexmits > 255) { maxDataRexmits = 255; } // Limit the MaxDupAcks to 3
status = TCPInitializeParameter( keyHandle, L"TcpMaxDupAcks", (PULONG)&MaxDupAcks );
#if MILLEN
//
// Backwards compatibility. If 'TcpMaxDupAcks' value does not exist,
// then attempt to read legacy 'MaxDupAcks'.
//
if (!NT_SUCCESS(status)) { TCPInitializeParameter( keyHandle, L"MaxDupAcks", &MaxDupAcks ); } #endif // MILLEN
if (MaxDupAcks > 3) { MaxDupAcks = 3; } if (MaxDupAcks == 0) { MaxDupAcks = 1; }
#if MILLEN
MaxConnBlocks = 16; #else // MILLEN
systemSize = MmQuerySystemSize();
if (MmIsThisAnNtAsSystem()) {
if (systemSize == MmSmallSystem) { MaxConnBlocks = 128; } else if (systemSize == MmMediumSystem) { MaxConnBlocks = 256; } else { #if defined(_WIN64)
MaxConnBlocks = 4096; #else
MaxConnBlocks = 1024; #endif
} } else { //for workstation, small system limit default number of connections to 4K.
// medium system 8k
// Large system 32k connections
if (systemSize == MmSmallSystem) { MaxConnBlocks = 16; } else if (systemSize == MmMediumSystem) { MaxConnBlocks = 32; } else { MaxConnBlocks = 128; } } #endif // !MILLEN
#if MILLEN
NumTcbTablePartitions = 1; #else
NumTcbTablePartitions = (KeNumberProcessors * KeNumberProcessors); #endif
TCPInitializeParameter( keyHandle, L"NumTcbTablePartitions", (PULONG)&NumTcbTablePartitions ); if (NumTcbTablePartitions > (MAXIMUM_PROCESSORS * MAXIMUM_PROCESSORS)) { NumTcbTablePartitions = (MAXIMUM_PROCESSORS * MAXIMUM_PROCESSORS); } NumTcbTablePartitions = ComputeLargerOrEqualPowerOfTwo(NumTcbTablePartitions);
// Default to 128 buckets per partition
MaxHashTableSize = 128 * NumTcbTablePartitions;
TCPInitializeParameter( keyHandle, L"MaxHashTableSize", (PULONG)&MaxHashTableSize );
if (MaxHashTableSize < 64) { MaxHashTableSize = 64; } else if (MaxHashTableSize > 0xffff) { MaxHashTableSize = 0x10000; } MaxHashTableSize = ComputeLargerOrEqualPowerOfTwo(MaxHashTableSize); if (MaxHashTableSize < NumTcbTablePartitions) { MaxHashTableSize = 128 * NumTcbTablePartitions; } ASSERT(IsPowerOfTwo(MaxHashTableSize));
//since hash table size is power of 2 and cache line size
//is power of 2 and number of partion is even,
//entries per partions will be power of 2 and multiple of
//cache line size.
PerPartitionSize = MaxHashTableSize / NumTcbTablePartitions; ASSERT(IsPowerOfTwo(PerPartitionSize)); LogPerPartitionSize = ComputeShiftForLargerOrEqualPowerOfTwo(PerPartitionSize);
status = TCPInitializeParameter( keyHandle, L"Tcp1323Opts", &tcp1323opts );
if (status == STATUS_SUCCESS) {
// Check if TS and/or WS options
// are enabled.
TcpHostOpts = TCP_FLAG_WS | TCP_FLAG_TS;
if (!(tcp1323opts & TCP_FLAG_TS)) { TcpHostOpts &= ~TCP_FLAG_TS; } if (!(tcp1323opts & TCP_FLAG_WS)) { TcpHostOpts &= ~TCP_FLAG_WS;
}
TcpHostSendOpts = TcpHostOpts;
} else { TcpHostSendOpts = 0; }
TcpHostOpts |= TCP_FLAG_SACK;
status = TCPInitializeParameter( keyHandle, L"SackOpts", &SackOpts );
if (status == STATUS_SUCCESS) { //Check if Sack option is enabled
//If so, set it in global options variable
KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Sackopts %x\n", SackOpts));
if (!SackOpts) { TcpHostOpts &= ~TCP_FLAG_SACK; } }
TCPInitializeParameter( keyHandle, L"GlobalMaxTcpWindowSize", (PULONG)&GlobalMaxRcvWin );
TCPInitializeParameter( keyHandle, L"SynAttackProtect", (unsigned long *)&SynAttackProtect );
if (SynAttackProtect) {
TCPInitializeParameter( keyHandle, L"TCPMaxHalfOpen", (PULONG)&TCPMaxHalfOpen );
if (TCPMaxHalfOpen < MIN_THRESHOLD_MAX_HO) { TCPMaxHalfOpen = MIN_THRESHOLD_MAX_HO; } TCPInitializeParameter( keyHandle, L"TCPMaxHalfOpenRetried", (PULONG)&TCPMaxHalfOpenRetried );
if ((TCPMaxHalfOpenRetried > TCPMaxHalfOpen) || (TCPMaxHalfOpenRetried < MIN_THRESHOLD_MAX_HO_RETRIED)) { TCPMaxHalfOpenRetried = MIN_THRESHOLD_MAX_HO_RETRIED; } TCPMaxHalfOpenRetriedLW = (TCPMaxHalfOpenRetried >> 1) + (TCPMaxHalfOpenRetried >> 2); } //
// If we fail, then set to same value as maxDataRexmit so that the
// max(pptpmaxDataRexmit,maxDataRexmit) is a decent value
// Need this since TCPInitializeParameter no longer "initializes"
// to a default value
//
if (TCPInitializeParameter(keyHandle, L"PPTPTcpMaxDataRetransmissions", &pptpmaxDataRexmits) != STATUS_SUCCESS) { pptpmaxDataRexmits = maxDataRexmits; } if (pptpmaxDataRexmits > 255) { pptpmaxDataRexmits = 255; }
status = TCPInitializeParameter( keyHandle, L"TcpUseRFC1122UrgentPointer", &useRFC1122UrgentPointer );
#if MILLEN
//
// Backwards compatibility. If TcpUseRFC1122UrgentPointer does not exist,
// then check for BSDUrgent. These values are logical opposites.
//
if (!NT_SUCCESS(status)) { ULONG tmpBsdUrgent = TRUE;
status = TCPInitializeParameter( keyHandle, L"BSDUrgent", &tmpBsdUrgent);
if (NT_SUCCESS(status)) { useRFC1122UrgentPointer = !tmpBsdUrgent; } } #endif
if (useRFC1122UrgentPointer) { BSDUrgent = FALSE; } TCPInitializeParameter( keyHandle, L"TcpTimedWaitDelay", (PULONG)&FinWait2TO );
if (FinWait2TO > 300) { FinWait2TO = 300; } FinWait2TO = MS_TO_TICKS(FinWait2TO * 1000);
NTWMaxConnectTime = MS_TO_TICKS(NTWMaxConnectTime * 1000);
TCPInitializeParameter( keyHandle, L"MaxUserPort", (PULONG)&MaxUserPort );
if (MaxUserPort < 5000) { MaxUserPort = 5000; } if (MaxUserPort > 65534) { MaxUserPort = 65534; } GetReservedPortList(keyHandle);
//Reserve ports if
//
// Read a few IP optional (hidden) registry parameters that TCP
// cares about.
//
status = TCPInitializeParameter( keyHandle, L"EnablePMTUDiscovery", (PULONG)&PMTUDiscovery );
#if MILLEN
//
// Backwards compatibility. If 'EnablePMTUDiscovery' value does not exist,
// then attempt to read legacy 'PMTUDiscovery'.
//
if (!NT_SUCCESS(status)) { TCPInitializeParameter( keyHandle, L"PMTUDiscovery", &PMTUDiscovery ); } #endif // MILLEN
TCPInitializeParameter( keyHandle, L"EnableDeadGWDetect", (PULONG)&DeadGWDetect );
TCPInitializeParameter( keyHandle, L"EnableSecurityFilters", (PULONG)&SecurityFilteringEnabled );
#ifdef ACC
TCPInitializeParameter( keyHandle, L"AllowUserRawAccess", (PULONG)&AllowUserRawAccess ); #endif // ACC
status = TCPInitializeParameter( keyHandle, L"DefaultTOSValue", &DefaultTOSValue );
#if MILLEN
//
// Backwards compatibility. Read 'DefaultTOS' if 'DefaultTOSValue' is
// not present.
//
if (!NT_SUCCESS(status)) { TCPInitializeParameter( keyHandle, L"DefaultTOS", &DefaultTOSValue ); } #endif // MILLEN
TCPInitializeParameter( keyHandle, L"DisableUserTOSSetting", &DisableUserTOSSetting );
TCPInitializeParameter( keyHandle, L"MaxSendSegments", (PULONG)&MaxSendSegments );
TCPInitializeParameter( keyHandle, L"DisableLargeSendOffload", (PULONG)&DisableLargeSendOffload );
ZwClose(keyHandle); } MaxConnectRexmitCount = maxConnectRexmits; MaxConnectResponseRexmitCount = maxConnectResponseRexmits; MaxConnectResponseRexmitCountTmp = MaxConnectResponseRexmitCount;
//
// Use the greater of the two, hence both values should be valid
//
MaxDataRexmitCount = (maxDataRexmits > pptpmaxDataRexmits ? maxDataRexmits : pptpmaxDataRexmits);
TWTCBTable = CTEAllocMemBoot(MaxHashTableSize * sizeof(*TWTCBTable)); if (TWTCBTable == NULL) { ZwClose(keyHandle); KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate tw tcb table of size %x\n", MaxHashTableSize)); DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n"))); return (0); } for (i = 0; i < MaxHashTableSize; i++) { INITQ(&TWTCBTable[i]); }
TCBTable = CTEAllocMemBoot(MaxHashTableSize * sizeof(*TCBTable)); if (TCBTable == NULL) { ExFreePool(TWTCBTable); ZwClose(keyHandle); KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate tcb table of size %x\n", MaxHashTableSize)); DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n"))); return (0); }
NdisZeroMemory(TCBTable, MaxHashTableSize * sizeof(*TCBTable));
SYNTCBTable = CTEAllocMemBoot(MaxHashTableSize * sizeof(*SYNTCBTable)); if (SYNTCBTable == NULL) { ExFreePool(TWTCBTable); ExFreePool(TCBTable); ZwClose(keyHandle); KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate syn tcb table of size %x\n", MaxHashTableSize)); DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n"))); return (0); }
for (i = 0; i < MaxHashTableSize; i++) { INITQ(&SYNTCBTable[i]); }
pSynTCBTableLock = CTEAllocMemBoot(NumTcbTablePartitions * sizeof(CTELock)); if (pSynTCBTableLock == NULL) { ExFreePool(TCBTable); ExFreePool(TWTCBTable); ExFreePool(SYNTCBTable); ZwClose(keyHandle); KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate twtcb lock table \n")); DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n"))); return (0); }
pTWTCBTableLock = CTEAllocMemBoot(NumTcbTablePartitions * sizeof(CTELock)); if (pTWTCBTableLock == NULL) { ExFreePool(TCBTable); ExFreePool(TWTCBTable); ExFreePool(SYNTCBTable); ExFreePool(pSynTCBTableLock); ZwClose(keyHandle); KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate twtcb lock table \n")); DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n"))); return (0); }
pTCBTableLock = CTEAllocMemBoot(NumTcbTablePartitions * sizeof(CTELock)); if (pTCBTableLock == NULL) { ExFreePool(TCBTable); ExFreePool(TWTCBTable); ExFreePool(pTWTCBTableLock); ExFreePool(SYNTCBTable); ExFreePool(pSynTCBTableLock); ZwClose(keyHandle); KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate tcb lock table \n")); DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n"))); return (0); }
TWQueue = CTEAllocMemBoot(NumTcbTablePartitions * sizeof(Queue)); if (TWQueue == NULL) { ExFreePool(TCBTable); ExFreePool(TWTCBTable); ExFreePool(pTWTCBTableLock); ExFreePool(SYNTCBTable); ExFreePool(pSynTCBTableLock); ExFreePool(pTCBTableLock); ZwClose(keyHandle); KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate Twqueue \n")); DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n"))); return (0);
}
TimerWheel = CTEAllocMemBoot(NumTcbTablePartitions * sizeof(TIMER_WHEEL) + CACHE_LINE_SIZE); if (TimerWheel == NULL) { ExFreePool(TCBTable); ExFreePool(TWTCBTable); ExFreePool(pTWTCBTableLock); ExFreePool(SYNTCBTable); ExFreePool(pSynTCBTableLock); ExFreePool(pTCBTableLock); ExFreePool(TWQueue); ZwClose(keyHandle); KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate Twqueue \n")); DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n"))); return (0); } OrgTimerWheel = TimerWheel; TimerWheel = (PTIMER_WHEEL)(((ULONG_PTR) TimerWheel + CACHE_LINE_SIZE) & CACHE_ALIGN_MASK);
for (i = 0; i < NumTcbTablePartitions; i++) { CTEInitLock(&pTCBTableLock[i]); CTEInitLock(&pTWTCBTableLock[i]); CTEInitLock(&pSynTCBTableLock[i]); INITQ(&TWQueue[i])
// Init the timer wheel
CTEInitLock(&TimerWheel[i].tw_lock);
#ifdef TIMER_TEST
TimerWheel[i].tw_starttick = 0xfffff000; #else
TimerWheel[i].tw_starttick = 0; #endif
for(j = 0; j < TIMER_WHEEL_SIZE; j++) { INITQ(&TimerWheel[i].tw_timerslot[j]) } }
if (MaxConnections != DEFAULT_MAX_CONNECTIONS) { //make it even
MaxConnBlocks = ((MaxConnections >> 1) << 1);
//allow minimum of 1k level 1 conn blocks.
//this gives minimum of 256K connections capability
if (MaxConnBlocks < 1024) { MaxConnBlocks = 1024; } }
ConnTable = CTEAllocMemBoot(MaxConnBlocks * sizeof(TCPConnBlock *)); if (ConnTable == NULL) { ExFreePool(OrgTimerWheel); ExFreePool(TWQueue); ExFreePool(TCBTable); ExFreePool(TWTCBTable); ExFreePool(pTWTCBTableLock); ExFreePool(pTCBTableLock); ExFreePool(SYNTCBTable); ExFreePool(pSynTCBTableLock); ZwClose(keyHandle); KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not allocate ConnTable \n")); DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [failure]\n"))); return (0); }
DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-TCPGetConfigInfo [SUCCESS]\n"))); return (1); }
#define WORK_BUFFER_SIZE 256
extern NTSTATUS GetRegDWORDValue( HANDLE KeyHandle, PWCHAR ValueName, PULONG ValueData );
NTSTATUS TCPInitializeParameter( HANDLE KeyHandle, PWCHAR ValueName, PULONG Value ) /*++
Routine Description:
Initializes a ULONG parameter from the registry or to a default parameter if accessing the registry value fails.
Arguments:
KeyHandle - An open handle to the registry key for the parameter. ValueName - The UNICODE name of the registry value to read. Value - The ULONG into which to put the data. DefaultValue - The default to assign if reading the registry fails.
Return Value:
None.
--*/
{ return (GetRegDWORDValue(KeyHandle, ValueName, Value)); }
VOID GetReservedPortList( NDIS_HANDLE ConfigHandle ) { UNICODE_STRING PortList; PWCHAR nextRange;
TDI_STATUS status;
PortList.Buffer = CTEAllocMemBoot(WORK_BUFFER_SIZE * sizeof(WCHAR));
if (!PortList.Buffer) { return; } PortList.Buffer[0] = UNICODE_NULL; PortList.Length = 0; PortList.MaximumLength = WORK_BUFFER_SIZE * sizeof(WCHAR);
PortRangeList = NULL;
if (PortList.Buffer) {
NdisZeroMemory(PortList.Buffer, WORK_BUFFER_SIZE * sizeof(WCHAR));
status = GetRegMultiSZValue( ConfigHandle, L"ReservedPorts", &PortList );
if (NT_SUCCESS(status)) {
for (nextRange = PortList.Buffer; *nextRange != L'\0'; nextRange += wcslen(nextRange) + 1) {
PWCHAR tmps = nextRange; USHORT upval = 0, loval = 0, tmpval = 0; BOOLEAN error = FALSE; ReservedPortListEntry *ListEntry;
while (*tmps != L'\0') { if (*tmps == L'-') { tmps++; loval = tmpval; tmpval = 0; } if (*tmps >= L'0' && *tmps <= L'9') { tmpval = tmpval * 10 + (*tmps - L'0'); } else { error = TRUE; break; } tmps++; } upval = tmpval; KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"loval %d upval %d\n", loval, upval)); if (!error && (loval > 0) && (upval > 0) && (loval <= upval) && (upval <= MaxUserPort) && (loval <= MaxUserPort)) {
ListEntry = CTEAllocMemBoot(sizeof(ReservedPortListEntry));
if (ListEntry) {
//Insert this range.
//No need to take locks
//since we are at initialization.
ListEntry->UpperRange = upval; ListEntry->LowerRange = loval;
ListEntry->next = PortRangeList; PortRangeList = ListEntry;
} } } } CTEFreeMem(PortList.Buffer);
} }
TDI_STATUS GetSecurityFilterList( NDIS_HANDLE ConfigHandle, ulong Protocol, PNDIS_STRING FilterList ) { PWCHAR parameterName; TDI_STATUS status;
if (Protocol == PROTOCOL_TCP) { parameterName = L"TcpAllowedPorts"; } else if (Protocol == PROTOCOL_UDP) { parameterName = L"UdpAllowedPorts"; } else { parameterName = L"RawIpAllowedProtocols"; }
status = GetRegMultiSZValue( ConfigHandle, parameterName, FilterList );
if (!NT_SUCCESS(status)) { FilterList->Length = 0; } return (status); }
uint EnumSecurityFilterValue( PNDIS_STRING FilterList, ulong Index, ulong * FilterValue ) { PWCHAR valueString; UNICODE_STRING unicodeString; NTSTATUS status;
PAGED_CODE();
valueString = EnumRegMultiSz( FilterList->Buffer, FilterList->Length, Index );
if ((valueString == NULL) || (valueString[0] == UNICODE_NULL)) { return (FALSE); } RtlInitUnicodeString(&unicodeString, valueString);
status = RtlUnicodeStringToInteger(&unicodeString, 0, FilterValue);
if (!(NT_SUCCESS(status))) { TCPTRACE(("TCP: Invalid filter value %ws\n", valueString)); return (FALSE); } return (TRUE); }
VOID TCPFreeupMemory() /*++
Routine Description:
This routine frees up the memory at the TCP layer
Arguments:
NULL
Return Value:
None.
--*/ {
//
// Walk various lists and free assoc blocks
//
// DG header list
KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Freeing DG headers....\n"));
MdpDestroyPool(DgHeaderPool);
if (AddrObjTable) { CTEFreeMem(AddrObjTable); }
PplDestroyPool(TcbPool); PplDestroyPool(SynTcbPool);
#ifdef ACC
if (TcpAdminSecurityDescriptor) { ExFreePool(TcpAdminSecurityDescriptor); } #endif
}
VOID TCPUnload( IN PDRIVER_OBJECT DriverObject ) /*++
Routine Description:
This routine cleans up the TCP layer.
Arguments:
DriverObject - Pointer to driver object created by the system.
Return Value:
None. When the function returns, the driver is unloaded.
--*/ { NTSTATUS status; uint i;
TcpUnInitCcb();
#if !MILLEN
//
// Deinitialize IPSEC first
//
status = IpsecDeinitialize(); #endif
//
// Shut down all timers/events
//
CTEInitBlockStrucEx(&TcpipUnloadBlock); fTCBTimerStopping = TRUE;
for (i = 0; i < Time_Proc; i++) { if (!CTEStopTimer(&TCBTimer[i])) { KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not stop TCB timer - waiting on unload event\n"));
#if !MILLEN
if (KeReadStateEvent(&(TcpipUnloadBlock.cbs_event))) { KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Event is signaled...\n")); } #endif // !MILLEN
(VOID) CTEBlock(&TcpipUnloadBlock); KeClearEvent(&TcpipUnloadBlock.cbs_event); } } #if GPC
//
if (hGpcClient[GPC_CF_QOS]) {
status = GpcEntries.GpcDeregisterClientHandler(hGpcClient[GPC_CF_QOS]); hGpcClient[GPC_CF_QOS] = NULL;
} if (hGpcClient[GPC_CF_IPSEC]) {
status = GpcEntries.GpcDeregisterClientHandler(hGpcClient[GPC_CF_IPSEC]); hGpcClient[GPC_CF_IPSEC] = NULL;
} KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Deregistering GPC\n"));
status = GpcDeinitialize(&GpcEntries);
#endif
//
// Clean up all residual memory
//
TCPFreeupMemory();
//
// Deregister address notifn handler with TDI
//
(void)TdiDeregisterPnPHandlers(AddressChangeHandle);
//
// Deregister our devices with TDI
//
(void)TdiDeregisterDeviceObject(TCPRegistrationHandle);
(void)TdiDeregisterDeviceObject(UDPRegistrationHandle);
(void)TdiDeregisterDeviceObject(IPRegistrationHandle);
#if TRACE_EVENT
//
// Deregister with WMI
//
IoWMIRegistrationControl(TCPDeviceObject, WMIREG_ACTION_DEREGISTER); #endif
//
// Delete devices
//
IoDeleteDevice(TCPDeviceObject); IoDeleteDevice(UDPDeviceObject); IoDeleteDevice(RawIPDeviceObject); }
#if GPC
GPC_STATUS GPCcfInfoAddNotifyIpsec(GPC_CLIENT_HANDLE ClCtxt, GPC_HANDLE GpcHandle, PTC_INTERFACE_ID InterfaceInfo, ULONG CfInfoSize, PVOID CfInfo, PGPC_CLIENT_HANDLE pClInfoCxt) { InterlockedIncrement((PLONG)&GPCcfInfo);
IF_TCPDBG(TCP_DEBUG_GPC) KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo Add notification %x\n", GPCcfInfo));
InterlockedIncrement((PLONG)&GpcCfCounts[GPC_CF_IPSEC]);
IF_TCPDBG(TCP_DEBUG_GPC) KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo Add notification IPSEC:%x\n", GpcCfCounts[GPC_CF_IPSEC]));
return (STATUS_SUCCESS); }
GPC_STATUS GPCcfInfoRemoveNotifyIpsec(GPC_CLIENT_HANDLE ClCtxt, GPC_CLIENT_HANDLE ClInfoCxt) { InterlockedDecrement((PLONG)&GPCcfInfo);
IF_TCPDBG(TCP_DEBUG_GPC) KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo remove notification %x\n", GPCcfInfo));
InterlockedDecrement((PLONG)&GpcCfCounts[GPC_CF_IPSEC]);
IF_TCPDBG(TCP_DEBUG_GPC) KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo Add notification IPSEC: %x\n", GpcCfCounts[GPC_CF_IPSEC]));
return (STATUS_SUCCESS); }
GPC_STATUS GPCcfInfoAddNotifyQoS(GPC_CLIENT_HANDLE ClCtxt, GPC_HANDLE GpcHandle, PTC_INTERFACE_ID InterfaceInfo, ULONG CfInfoSize, PVOID CfInfo, PGPC_CLIENT_HANDLE pClInfoCxt) { InterlockedIncrement((PLONG)&GPCcfInfo);
IF_TCPDBG(TCP_DEBUG_GPC) KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo Add notification %x\n", GPCcfInfo));
InterlockedIncrement((PLONG)&GpcCfCounts[GPC_CF_QOS]);
IF_TCPDBG(TCP_DEBUG_GPC) KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo Add notification QOS: %x\n", GpcCfCounts[GPC_CF_QOS]));
return (STATUS_SUCCESS); }
GPC_STATUS GPCcfInfoRemoveNotifyQoS(GPC_CLIENT_HANDLE ClCtxt, GPC_CLIENT_HANDLE ClInfoCxt) { InterlockedDecrement((PLONG)&GPCcfInfo);
IF_TCPDBG(TCP_DEBUG_GPC) KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo remove notification %x\n", GPCcfInfo));
InterlockedDecrement((PLONG)&GpcCfCounts[GPC_CF_QOS]);
IF_TCPDBG(TCP_DEBUG_GPC) KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcpip - Cfinfo Add notification %x\n", GpcCfCounts[GPC_CF_QOS]));
return (STATUS_SUCCESS); } #endif
#if ACC
NTSTATUS TcpBuildDeviceAcl( OUT PACL * DeviceAcl ) /*++
Routine Description:
(Lifted from AFD - AfdBuildDeviceAcl) This routine builds an ACL which gives Administrators and LocalSystem principals full access. All other principals have no access.
Arguments:
DeviceAcl - Output pointer to the new ACL.
Return Value:
STATUS_SUCCESS or an appropriate error code.
--*/
{ PGENERIC_MAPPING GenericMapping; PSID AdminsSid; PSID SystemSid; PSID NetworkSid; ULONG AclLength; NTSTATUS Status; ACCESS_MASK AccessMask = GENERIC_ALL; PACL NewAcl;
//
// Enable access to all the globally defined SIDs
//
GenericMapping = IoGetFileObjectGenericMapping();
RtlMapGenericMask(&AccessMask, GenericMapping);
AdminsSid = SeExports->SeAliasAdminsSid; SystemSid = SeExports->SeLocalSystemSid; NetworkSid = SeExports->SeNetworkServiceSid;
AclLength = sizeof(ACL) + 3 * FIELD_OFFSET(ACCESS_ALLOWED_ACE,SidStart) + RtlLengthSid(AdminsSid) + RtlLengthSid(SystemSid) + RtlLengthSid(NetworkSid);
NewAcl = CTEAllocMemBoot(AclLength);
if (NewAcl == NULL) { return (STATUS_INSUFFICIENT_RESOURCES); }
Status = RtlCreateAcl(NewAcl, AclLength, ACL_REVISION); if (!NT_SUCCESS(Status)) { CTEFreeMem(NewAcl); return (Status); }
Status = RtlAddAccessAllowedAce( NewAcl, ACL_REVISION, AccessMask, AdminsSid );
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAce( NewAcl, ACL_REVISION, AccessMask, SystemSid );
ASSERT(NT_SUCCESS(Status));
// Add acl for NetworkSid!
Status = RtlAddAccessAllowedAce( NewAcl, ACL_REVISION, AccessMask, NetworkSid );
ASSERT(NT_SUCCESS(Status));
*DeviceAcl = NewAcl;
return (STATUS_SUCCESS);
} // TcpBuildDeviceAcl
NTSTATUS TcpCreateAdminSecurityDescriptor( VOID ) /*++
Routine Description:
(Lifted from AFD - AfdCreateAdminSecurityDescriptor) This routine creates a security descriptor which gives access only to Administrtors and LocalSystem. This descriptor is used to access check raw endpoint opens and exclisive access to transport addresses.
Arguments:
None.
Return Value:
STATUS_SUCCESS or an appropriate error code.
--*/
{ PACL rawAcl = NULL; NTSTATUS status; BOOLEAN memoryAllocated = FALSE; PSECURITY_DESCRIPTOR tcpSecurityDescriptor; ULONG tcpSecurityDescriptorLength; CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH]; PSECURITY_DESCRIPTOR localSecurityDescriptor = (PSECURITY_DESCRIPTOR) & buffer; PSECURITY_DESCRIPTOR localTcpAdminSecurityDescriptor; SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
//
// Get a pointer to the security descriptor from the TCP device object.
//
status = ObGetObjectSecurity( TCPDeviceObject, &tcpSecurityDescriptor, &memoryAllocated );
if (!NT_SUCCESS(status)) { KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "TCP: Unable to get security descriptor, error: %x\n", status )); ASSERT(memoryAllocated == FALSE); return (status); } //
// Build a local security descriptor with an ACL giving only
// administrators and system access.
//
status = TcpBuildDeviceAcl(&rawAcl);
if (!NT_SUCCESS(status)) { KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"TCP: Unable to create Raw ACL, error: %x\n", status)); goto error_exit; } (VOID) RtlCreateSecurityDescriptor( localSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
(VOID) RtlSetDaclSecurityDescriptor( localSecurityDescriptor, TRUE, rawAcl, FALSE );
//
// Make a copy of the TCP descriptor. This copy will be the raw descriptor.
//
tcpSecurityDescriptorLength = RtlLengthSecurityDescriptor( tcpSecurityDescriptor );
localTcpAdminSecurityDescriptor = ExAllocatePool( PagedPool, tcpSecurityDescriptorLength );
if (localTcpAdminSecurityDescriptor == NULL) { KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"TCP: couldn't allocate security descriptor\n")); goto error_exit; } RtlMoveMemory( localTcpAdminSecurityDescriptor, tcpSecurityDescriptor, tcpSecurityDescriptorLength );
TcpAdminSecurityDescriptor = localTcpAdminSecurityDescriptor;
//
// Now apply the local descriptor to the raw descriptor.
//
status = SeSetSecurityDescriptorInfo( NULL, &securityInformation, localSecurityDescriptor, &TcpAdminSecurityDescriptor, PagedPool, IoGetFileObjectGenericMapping() );
if (!NT_SUCCESS(status)) { KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"TCP: SeSetSecurity failed, %lx\n", status)); ASSERT(TcpAdminSecurityDescriptor == localTcpAdminSecurityDescriptor); ExFreePool(TcpAdminSecurityDescriptor); TcpAdminSecurityDescriptor = NULL; goto error_exit; } if (TcpAdminSecurityDescriptor != localTcpAdminSecurityDescriptor) { ExFreePool(localTcpAdminSecurityDescriptor); } status = STATUS_SUCCESS;
error_exit:
ObReleaseObjectSecurity( tcpSecurityDescriptor, memoryAllocated );
if (rawAcl != NULL) { CTEFreeMem(rawAcl); } return (status); }
#endif // ACC
#if !MILLEN
NTSTATUS IpsecInitialize( void ) /*++
Routine Description:
Initialize IPSEC.SYS.
Arguments:
None.
Return Value:
None.
--*/
{ UNICODE_STRING IPSECDeviceName; IPSEC_SET_TCPIP_STATUS SetTcpipStatus; PIRP Irp; IO_STATUS_BLOCK StatusBlock; KEVENT Event; NTSTATUS status;
IPSECDeviceObject = NULL; IPSECFileObject = NULL;
RtlInitUnicodeString(&IPSECDeviceName, DD_IPSEC_DEVICE_NAME);
//
// Keep a reference to the IPSec driver so it won't unload before us.
//
status = IoGetDeviceObjectPointer( &IPSECDeviceName, FILE_ALL_ACCESS, &IPSECFileObject, &IPSECDeviceObject);
if (!NT_SUCCESS(status)) { IPSECFileObject = NULL;
return (status); }
SetTcpipStatus.TcpipStatus = TRUE;
SetTcpipStatus.TcpipFreeBuff = FreeIprBuff; SetTcpipStatus.TcpipAllocBuff = IPAllocBuff; SetTcpipStatus.TcpipGetInfo = IPGetInfo; SetTcpipStatus.TcpipNdisRequest = IPProxyNdisRequest; SetTcpipStatus.TcpipSetIPSecStatus = IPSetIPSecStatus; SetTcpipStatus.TcpipSetIPSecPtr = SetIPSecPtr; SetTcpipStatus.TcpipUnSetIPSecPtr = UnSetIPSecPtr; SetTcpipStatus.TcpipUnSetIPSecSendPtr = UnSetIPSecSendPtr; SetTcpipStatus.TcpipTCPXsum = tcpxsum; SetTcpipStatus.TcpipSendICMPErr = SendICMPErr;
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest( IOCTL_IPSEC_SET_TCPIP_STATUS, IPSECDeviceObject, &SetTcpipStatus, sizeof(IPSEC_SET_TCPIP_STATUS), NULL, 0, FALSE, &Event, &StatusBlock);
if (Irp) { status = IoCallDriver(IPSECDeviceObject, Irp);
if (status == STATUS_PENDING) { KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL); status = StatusBlock.Status; } } else { status = STATUS_INSUFFICIENT_RESOURCES; }
return (status); }
NTSTATUS IpsecDeinitialize( void ) /*++
Routine Description:
Deinitialize IPSEC.SYS.
Arguments:
None.
Return Value:
None.
--*/
{ IPSEC_SET_TCPIP_STATUS SetTcpipStatus; PIRP Irp; IO_STATUS_BLOCK StatusBlock; KEVENT Event; NTSTATUS status;
if (!IPSECFileObject) { return (STATUS_SUCCESS); }
RtlZeroMemory(&SetTcpipStatus, sizeof(IPSEC_SET_TCPIP_STATUS));
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest( IOCTL_IPSEC_SET_TCPIP_STATUS, IPSECDeviceObject, &SetTcpipStatus, sizeof(IPSEC_SET_TCPIP_STATUS), NULL, 0, FALSE, &Event, &StatusBlock);
if (Irp) { status = IoCallDriver(IPSECDeviceObject, Irp);
if (status == STATUS_PENDING) { KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL); status = StatusBlock.Status; } } else { status = STATUS_INSUFFICIENT_RESOURCES; }
ObDereferenceObject(IPSECFileObject); IPSECFileObject = NULL;
return (status); }
NTSTATUS AddNetConfigOpsAce(IN PACL Dacl, OUT PACL * DeviceAcl ) /*++
Routine Description:
This routine builds an ACL which gives adds the Network Configuration Operators group to the principals allowed to control the driver.
Arguments:
Dacl - Existing DACL. DeviceAcl - Output pointer to the new ACL.
Return Value:
STATUS_SUCCESS or an appropriate error code.
--*/
{ PGENERIC_MAPPING GenericMapping; PSID NetworkSid = NULL; PSID NetConfigOpsSid = NULL; ULONG AclLength; NTSTATUS Status; ACCESS_MASK AccessMask = GENERIC_ALL; PACL NewAcl = NULL; ULONG SidSize; SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY; PACE_HEADER AceTemp; int i; //
// Enable access to all the globally defined SIDs
//
GenericMapping = IoGetFileObjectGenericMapping();
RtlMapGenericMask(&AccessMask, GenericMapping);
NetworkSid = SeExports->SeNetworkServiceSid; SidSize = RtlLengthRequiredSid(3); NetConfigOpsSid = (PSID)(CTEAllocMemBoot(SidSize));
if (NULL == NetConfigOpsSid) { return STATUS_INSUFFICIENT_RESOURCES; }
Status = RtlInitializeSid(NetConfigOpsSid, &sidAuth, 2); if (Status != STATUS_SUCCESS) { goto clean_up; }
*RtlSubAuthoritySid(NetConfigOpsSid, 0) = SECURITY_BUILTIN_DOMAIN_RID; *RtlSubAuthoritySid(NetConfigOpsSid, 1) = DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS;
AclLength = Dacl->AclSize;
AclLength = Dacl->AclSize + 2*FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + RtlLengthSid(NetConfigOpsSid) + RtlLengthSid(NetworkSid);
NewAcl = CTEAllocMemBoot(AclLength);
if (NewAcl == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto clean_up; }
Status = RtlCreateAcl(NewAcl, AclLength, ACL_REVISION);
if (!NT_SUCCESS(Status)) { goto clean_up; }
for (i = 0; i < Dacl->AceCount; i++) { Status = RtlGetAce(Dacl, i, &AceTemp);
if (NT_SUCCESS(Status)) { Status = RtlAddAce(NewAcl, ACL_REVISION, MAXULONG, AceTemp, AceTemp->AceSize); }
if (!NT_SUCCESS(Status)) { goto clean_up; } }
// Add Net Config Operators Ace
Status = RtlAddAccessAllowedAce(NewAcl, ACL_REVISION, AccessMask, NetConfigOpsSid);
if (!NT_SUCCESS(Status)) { goto clean_up; }
// Add Network Services Ace
Status = RtlAddAccessAllowedAce(NewAcl, ACL_REVISION, AccessMask, NetworkSid);
if (!NT_SUCCESS(Status)) { goto clean_up; }
*DeviceAcl = NewAcl;
clean_up: if (NetConfigOpsSid) { CTEFreeMem(NetConfigOpsSid); } if (!NT_SUCCESS(Status) && NewAcl) { CTEFreeMem(NewAcl); }
return (Status); }
NTSTATUS CreateDeviceDriverSecurityDescriptor(PVOID DeviceOrDriverObject)
/*++
Routine Description:
Creates the SD responsible for giving access to different users.
Arguments:
DeviceOrDriverObject - Object to which to assign the Access Rights.
Return Value:
STATUS_SUCCESS or an appropriate error code.
--*/
{ NTSTATUS status; BOOLEAN memoryAllocated = FALSE; PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; PACL Dacl = NULL; BOOLEAN HasDacl = FALSE; BOOLEAN DaclDefaulted = FALSE; PACL NewAcl = NULL;
//
// Get a pointer to the security descriptor from the driver/device object.
//
status = ObGetObjectSecurity( DeviceOrDriverObject, &SecurityDescriptor, &memoryAllocated );
if (!NT_SUCCESS(status)) { KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "TCP: Unable to get security descriptor, error: %x\n", status )); ASSERT(memoryAllocated == FALSE); return (status); }
status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, &HasDacl, &Dacl, &DaclDefaulted);
if (NT_SUCCESS(status) && HasDacl && Dacl != NULL) { status = AddNetConfigOpsAce(Dacl, &NewAcl);
if (NT_SUCCESS(status)) {
PSECURITY_DESCRIPTOR SecDesc = NULL; ULONG SecDescSize = 0; PACL AbsDacl = NULL; ULONG DaclSize = 0; PACL AbsSacl = NULL; ULONG ulSacl = 0; PSID Owner = NULL; ULONG OwnerSize = 0; PSID PrimaryGroup = NULL; ULONG PrimaryGroupSize = 0; BOOLEAN OwnerDefault = FALSE; BOOLEAN GroupDefault = FALSE; BOOLEAN HasSacl = FALSE; BOOLEAN SaclDefaulted = FALSE;
SECURITY_INFORMATION secInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
SecDescSize = sizeof(SecDesc) + NewAcl->AclSize; SecDesc = CTEAllocMemBoot(SecDescSize);
if (SecDesc) { DaclSize = NewAcl->AclSize; AbsDacl = CTEAllocMemBoot(DaclSize);
if (AbsDacl) { status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor, &Owner, &OwnerDefault);
if (NT_SUCCESS(status)) { OwnerSize = RtlLengthSid(Owner);
status = RtlGetGroupSecurityDescriptor(SecurityDescriptor, &PrimaryGroup, &GroupDefault);
if (NT_SUCCESS(status)) { PrimaryGroupSize = RtlLengthSid(PrimaryGroup);
status = RtlGetSaclSecurityDescriptor(SecurityDescriptor, &HasSacl, &AbsSacl, &SaclDefaulted);
if (NT_SUCCESS(status)) {
if (HasSacl) { ulSacl = AbsSacl->AclSize; secInfo |= SACL_SECURITY_INFORMATION; }
status = RtlSelfRelativeToAbsoluteSD(SecurityDescriptor, SecDesc, &SecDescSize, AbsDacl, &DaclSize, AbsSacl, &ulSacl, Owner, &OwnerSize, PrimaryGroup, &PrimaryGroupSize);
if (NT_SUCCESS(status)) { status = RtlSetDaclSecurityDescriptor(SecDesc, TRUE, NewAcl, FALSE);
if (NT_SUCCESS(status)) { status = ObSetSecurityObjectByPointer(DeviceOrDriverObject, secInfo, SecDesc); } } } }
} else { status = STATUS_INSUFFICIENT_RESOURCES; } } else { status = STATUS_INSUFFICIENT_RESOURCES; }
if (SecDesc) { // Since this is a Self-Relative security descriptor, freeing it also frees
// Owner and PrimaryGroup.
CTEFreeMem(SecDesc); }
if (AbsDacl) { CTEFreeMem(AbsDacl); } }
if (NewAcl) { CTEFreeMem(NewAcl); }
} } else { KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"TCP: No Dacl: %x\n", status)); }
ObReleaseObjectSecurity( SecurityDescriptor, memoryAllocated ); return (status); }
//
// Function: IsRunningOnPersonal
//
// Purpose: Determines whether running on Whistler Personal
//
// Returns: Returns true if running on Personal - FALSE otherwise
BOOLEAN IsRunningOnPersonal( VOID ) { OSVERSIONINFOEXW OsVer = {0}; ULONGLONG ConditionMask = 0; BOOLEAN IsPersonal = TRUE;
OsVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); OsVer.wSuiteMask = VER_SUITE_PERSONAL; OsVer.wProductType = VER_NT_WORKSTATION;
VER_SET_CONDITION(ConditionMask, VER_PRODUCT_TYPE, VER_EQUAL); VER_SET_CONDITION(ConditionMask, VER_SUITENAME, VER_AND);
if (RtlVerifyVersionInfo(&OsVer, VER_PRODUCT_TYPE | VER_SUITENAME, ConditionMask) == STATUS_REVISION_MISMATCH) { IsPersonal = FALSE; }
return IsPersonal; }
#endif
|