Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

535 lines
15 KiB

/*++
Copyright (c) 1989-2001 Microsoft Corporation
Module Name:
init.c
Abstract:
Initialization
Author:
Jiandong Ruan
Revision History:
--*/
#include "precomp.h"
#include "init.tmh"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, SmbInitRegistry)
#pragma alloc_text(PAGE, SmbShutdownRegistry)
#pragma alloc_text(PAGE, SmbInitTdi)
#pragma alloc_text(PAGE, SmbShutdownTdi)
#pragma alloc_text(INIT, SmbCreateSmbDevice)
#pragma alloc_text(PAGE, SmbDestroySmbDevice)
#endif
NTSTATUS
SmbInitRegistry(
IN PUNICODE_STRING RegistryPath
)
{
OBJECT_ATTRIBUTES ObAttr;
NTSTATUS status;
HANDLE hKey = NULL;
UNICODE_STRING uncParams;
ULONG Disposition;
PAGED_CODE();
InitializeObjectAttributes (
&ObAttr,
RegistryPath,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL
);
status = ZwOpenKey (
&hKey,
KEY_READ | KEY_WRITE,
&ObAttr
);
BAIL_OUT_ON_ERROR(status);
RtlInitUnicodeString(&uncParams, L"Parameters");
InitializeObjectAttributes (
&ObAttr,
&uncParams,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
hKey,
NULL
);
status = ZwCreateKey(
&SmbCfg.ParametersKey,
KEY_READ | KEY_WRITE,
&ObAttr,
0,
NULL,
0,
&Disposition
);
BAIL_OUT_ON_ERROR(status);
RtlInitUnicodeString(&uncParams, L"Linkage");
InitializeObjectAttributes (
&ObAttr,
&uncParams,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
hKey,
NULL
);
status = ZwCreateKey(
&SmbCfg.LinkageKey,
KEY_READ | KEY_WRITE,
&ObAttr,
0,
NULL,
0,
&Disposition
);
BAIL_OUT_ON_ERROR(status);
ZwClose(hKey);
hKey = NULL;
return status;
cleanup:
if (SmbCfg.LinkageKey) {
ZwClose(SmbCfg.LinkageKey);
SmbCfg.LinkageKey = NULL;
}
if (SmbCfg.ParametersKey) {
ZwClose(SmbCfg.ParametersKey);
SmbCfg.ParametersKey = NULL;
}
if (hKey) {
ZwClose(hKey);
}
SmbTrace(SMB_TRACE_ERRORS, ("returns %!status!", status));
return status;
}
VOID
SmbShutdownRegistry(
VOID
)
{
PAGED_CODE();
if (SmbCfg.ParametersKey) {
ZwClose(SmbCfg.ParametersKey);
SmbCfg.ParametersKey = NULL;
}
if (SmbCfg.LinkageKey) {
ZwClose(SmbCfg.LinkageKey);
SmbCfg.LinkageKey = NULL;
}
}
#ifdef STANDALONE_SMB
NTSTATUS
SmbInitTdi(
VOID
)
{
UNICODE_STRING ucSmbClientName;
UNICODE_STRING ucSmbProviderName;
TDI_CLIENT_INTERFACE_INFO TdiClientInterface;
NTSTATUS status;
PAGED_CODE();
RtlInitUnicodeString(&ucSmbProviderName, WC_SMB_TDI_PROVIDER_NAME);
status = TdiRegisterProvider (&ucSmbProviderName, &SmbCfg.TdiProviderHandle);
if (NT_SUCCESS (status)) {
//
// Register our Handlers with TDI
//
RtlInitUnicodeString(&ucSmbClientName, WC_SMB_TDI_CLIENT_NAME);
RtlZeroMemory(&TdiClientInterface, sizeof(TdiClientInterface));
TdiClientInterface.MajorTdiVersion = MAJOR_TDI_VERSION;
TdiClientInterface.MinorTdiVersion = MINOR_TDI_VERSION;
TdiClientInterface.ClientName = &ucSmbClientName;
TdiClientInterface.AddAddressHandlerV2 = SmbAddressArrival;
TdiClientInterface.DelAddressHandlerV2 = SmbAddressDeletion;
TdiClientInterface.BindingHandler = SmbBindHandler;
TdiClientInterface.PnPPowerHandler = NULL;
status = TdiRegisterPnPHandlers (&TdiClientInterface, sizeof(TdiClientInterface), &SmbCfg.TdiClientHandle);
if (!NT_SUCCESS (status)) {
TdiDeregisterProvider (SmbCfg.TdiProviderHandle);
SmbCfg.TdiProviderHandle = NULL;
}
}
return status;
}
VOID
SmbShutdownTdi(
VOID
)
{
NTSTATUS status;
PAGED_CODE();
if (SmbCfg.TdiClientHandle) {
status = TdiDeregisterPnPHandlers(SmbCfg.TdiClientHandle);
SmbCfg.TdiClientHandle = NULL;
}
if (SmbCfg.TdiProviderHandle) {
status = TdiDeregisterProvider(SmbCfg.TdiProviderHandle);
SmbCfg.TdiProviderHandle = NULL;
}
}
#else
VOID
SmbSetTdiHandles(
HANDLE ProviderHandle,
HANDLE ClientHandle
)
{
SmbCfg.TdiClientHandle = ClientHandle;
SmbCfg.TdiProviderHandle = ProviderHandle;
}
#endif
NTSTATUS
SmbBuildDeviceAcl(
OUT PACL * DeviceAcl
)
/*++
Routine Description:
(Lifted from SMB - SmbBuildDeviceAcl)
This routine builds an ACL which gives Administrators, LocalService and NetworkService
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, ServiceSid, 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;
ServiceSid = SeExports->SeLocalServiceSid;
NetworkSid = SeExports->SeNetworkServiceSid;
AclLength = sizeof(ACL) +
3 * sizeof(ACCESS_ALLOWED_ACE) +
RtlLengthSid(AdminsSid) +
RtlLengthSid(ServiceSid) +
RtlLengthSid(NetworkSid) -
3 * sizeof(ULONG);
NewAcl = ExAllocatePoolWithTag(PagedPool, AclLength, 'ABMS');
if (NewAcl == NULL) {
return (STATUS_INSUFFICIENT_RESOURCES);
}
Status = RtlCreateAcl(NewAcl, AclLength, ACL_REVISION);
if (!NT_SUCCESS(Status)) {
ExFreePool(NewAcl);
return (Status);
}
Status = RtlAddAccessAllowedAce(
NewAcl,
ACL_REVISION2,
AccessMask,
AdminsSid
);
ASSERT(NT_SUCCESS(Status));
if (!NT_SUCCESS(Status)) {
ExFreePool(NewAcl);
return (Status);
}
Status = RtlAddAccessAllowedAce(
NewAcl,
ACL_REVISION2,
AccessMask,
ServiceSid
);
ASSERT(NT_SUCCESS(Status));
if (!NT_SUCCESS(Status)) {
ExFreePool(NewAcl);
return (Status);
}
Status = RtlAddAccessAllowedAce(
NewAcl,
ACL_REVISION2,
AccessMask,
NetworkSid
);
ASSERT(NT_SUCCESS(Status));
if (!NT_SUCCESS(Status)) {
ExFreePool(NewAcl);
return (Status);
}
*DeviceAcl = NewAcl;
return (STATUS_SUCCESS);
}
NTSTATUS
SmbCreateAdminSecurityDescriptor(PDEVICE_OBJECT dev)
/*++
Routine Description:
(Lifted from NETBT - SmbCreateAdminSecurityDescriptor)
This routine creates a security descriptor which gives access
only to Administrtors and LocalService. 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;
CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
PSECURITY_DESCRIPTOR localSecurityDescriptor = (PSECURITY_DESCRIPTOR) buffer;
SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
//
// Build a local security descriptor with an ACL giving only
// administrators and service access.
//
status = SmbBuildDeviceAcl(&rawAcl);
if (!NT_SUCCESS(status)) {
SmbPrint(SMB_TRACE_PNP, ("SMB: Unable to create Raw ACL, error: 0x%08lx\n", status));
return (status);
}
(VOID) RtlCreateSecurityDescriptor(
localSecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION
);
(VOID) RtlSetDaclSecurityDescriptor(
localSecurityDescriptor,
TRUE,
rawAcl,
FALSE
);
//
// Now apply the local descriptor to the raw descriptor.
//
status = SeSetSecurityDescriptorInfo(
NULL,
&securityInformation,
localSecurityDescriptor,
&dev->SecurityDescriptor,
PagedPool,
IoGetFileObjectGenericMapping()
);
if (!NT_SUCCESS(status)) {
SmbPrint(SMB_TRACE_PNP, ("SMB: SeSetSecurity failed: 0x%08lx\n", status));
}
ExFreePool(rawAcl);
return (status);
}
NTSTATUS
SmbCreateSmbDevice(
PSMB_DEVICE *ppDevice,
USHORT Port,
UCHAR EndpointName[NETBIOS_NAME_SIZE]
)
{
PSMB_DEVICE DeviceObject;
NTSTATUS status;
UNICODE_STRING ExportName, ucName;
DeviceObject = NULL;
*ppDevice = NULL;
RtlInitUnicodeString(&ExportName, DD_SMB6_EXPORT_NAME);
status = IoCreateDevice(
SmbCfg.DriverObject,
sizeof(SMB_DEVICE) - sizeof(DEVICE_OBJECT),
&ExportName,
FILE_DEVICE_NETWORK,
FILE_DEVICE_SECURE_OPEN,
FALSE,
(PDEVICE_OBJECT*)&DeviceObject
);
BAIL_OUT_ON_ERROR(status);
DeviceObject->Tag = TAG_SMB6_DEVICE;
KeInitializeSpinLock(&DeviceObject->Lock);
InitializeListHead(&DeviceObject->UnassociatedConnectionList);
InitializeListHead(&DeviceObject->ClientList);
InitializeListHead(&DeviceObject->PendingDeleteConnectionList);
InitializeListHead(&DeviceObject->PendingDeleteClientList);
DeviceObject->ClientBinding = NULL;
DeviceObject->ServerBinding = NULL;
//
// initialization for FIN attack protection
//
DeviceObject->FinAttackProtectionMode = FALSE;
DeviceObject->LeaveFAPM = SmbReadLong (SmbCfg.ParametersKey, SMB_REG_LEAVE_FAPM, 50, 5);
DeviceObject->EnterFAPM = SmbReadLong (SmbCfg.ParametersKey, SMB_REG_ENTER_FAPM,
400, DeviceObject->LeaveFAPM + 50);
ASSERT(DeviceObject->EnterFAPM > DeviceObject->LeaveFAPM);
if (DeviceObject->LeaveFAPM >= DeviceObject->EnterFAPM) {
DeviceObject->EnterFAPM = 2 * DeviceObject->LeaveFAPM;
}
if (DeviceObject->LeaveFAPM >= DeviceObject->EnterFAPM) {
//
// This means overflow above
//
DeviceObject->LeaveFAPM = 50;
DeviceObject->EnterFAPM = 400;
}
//
// initialization for synch attack protection
//
DeviceObject->MaxBackLog = SmbReadLong(SmbCfg.ParametersKey, L"MaxBackLog", 1000, 100);
InitializeListHead(&DeviceObject->DelayedDisconnectList);
InitializeListHead(&DeviceObject->DelayedDisconnectList);
InitializeListHead(&DeviceObject->PendingDisconnectList);
DeviceObject->PendingDisconnectListNumber = 0;
KeInitializeEvent(&DeviceObject->PendingDisconnectListEmptyEvent,
NotificationEvent, TRUE);
DeviceObject->DisconnectWorkerRunning = FALSE;
DeviceObject->ConnectionPoolWorkerQueued = FALSE;
DeviceObject->SmbServer = NULL;
RtlCopyMemory(DeviceObject->EndpointName, EndpointName, NETBIOS_NAME_SIZE);
ASSERT(DeviceObject->EndpointName[NETBIOS_NAME_SIZE-1] == 0x20);
DeviceObject->Port = Port;
SmbCfg.Tcp4Available = FALSE;
SmbCfg.Tcp6Available = FALSE;
SmbCreateAdminSecurityDescriptor(&DeviceObject->DeviceObject);
*ppDevice = DeviceObject;
return status;
cleanup:
if (DeviceObject) {
if (SmbCfg.Tcp4Available) {
SmbShutdownTCP(&DeviceObject->Tcp4);
SmbCfg.Tcp4Available = FALSE;
}
if (SmbCfg.Tcp6Available) {
SmbShutdownTCP(&DeviceObject->Tcp6);
SmbCfg.Tcp6Available = FALSE;
}
IoDeleteDevice((PDEVICE_OBJECT)DeviceObject);
}
return status;
}
NTSTATUS
SmbDestroySmbDevice(
PSMB_DEVICE pDevice
)
{
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE();
ASSERT(SmbCfg.Unloading);
if (NULL == pDevice) {
return STATUS_SUCCESS;
}
SmbTdiDeregister(pDevice);
status = KeWaitForSingleObject(
&pDevice->PendingDisconnectListEmptyEvent,
Executive,
KernelMode,
FALSE,
NULL
);
ASSERT(status == STATUS_WAIT_0);
ASSERT(IsListEmpty(&pDevice->DelayedDisconnectList));
ASSERT(IsListEmpty(&pDevice->PendingDisconnectList) && pDevice->PendingDisconnectListNumber == 0);
ASSERT(IsListEmpty(&pDevice->PendingDeleteConnectionList));
ASSERT(IsListEmpty(&pDevice->PendingDeleteClientList));
if (SmbCfg.Tcp4Available) {
status = SmbShutdownTCP(&pDevice->Tcp4);
ASSERT(status == STATUS_SUCCESS);
SmbCfg.Tcp4Available = FALSE;
}
if (SmbCfg.Tcp6Available) {
status = SmbShutdownTCP(&pDevice->Tcp6);
ASSERT(status == STATUS_SUCCESS);
SmbCfg.Tcp6Available = FALSE;
}
ASSERT(status == STATUS_SUCCESS);
SmbShutdownPnP();
if (pDevice->ClientBinding) {
ExFreePool(pDevice->ClientBinding);
pDevice->ClientBinding = NULL;
}
if (pDevice->ServerBinding) {
ExFreePool(pDevice->ServerBinding);
pDevice->ServerBinding = NULL;
}
IoDeleteDevice((PDEVICE_OBJECT)pDevice);
return STATUS_SUCCESS;
}