📄 disp_obj.c
字号:
/* Copyright (c) 2002-2005 Vladislav Goncharov.
*
* Redistribution and use in source forms, with and without modification,
* are permitted provided that this entire comment appears intact.
*
* Redistribution in binary form may occur without any restrictions.
*
* This software is provided ``AS IS'' without any warranties of any kind.
*/
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
//
// $Id: disp_obj.c,v 1.10 2003/09/04 15:20:09 dev Exp $
/*
* This file contains TDI_CREATE, TDI_CLEANUP, TDI_ASSOCIATE_ADDRESS and
* TDI_DISASSOCIATE_ADDRESS handlers
*/
#include <ntddk.h>
#include <tdikrnl.h>
#include "sock.h"
#include "conn_state.h"
#include "dispatch.h"
#include "events.h"
#include "memtrack.h"
#include "obj_tbl.h"
#include "pid_pname.h"
#include "sids.h"
#include "tdi_fw.h"
/* IRP completion routines and their contexts */
static NTSTATUS tdi_create_addrobj_complete(
IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
// context for tdi_create_addrobj_complete2
typedef struct
{
TDI_ADDRESS_INFO *tai; /* address info -- result of TDI_QUERY_ADDRESS_INFO */
PFILE_OBJECT fileobj; /* FileObject from IO_STACK_LOCATION */
} TDI_CREATE_ADDROBJ2_CTX;
static NTSTATUS tdi_create_addrobj_complete2(
IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
//----------------------------------------------------------------------------
/*
* TDI_CREATE handler
*/
int
tdi_create(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion)
{
NTSTATUS status;
FILE_FULL_EA_INFORMATION *ea = (FILE_FULL_EA_INFORMATION *)irp->AssociatedIrp.SystemBuffer;
/* pid resolving stuff: a good place for it (PASSIVE level, begin of working with TDI-objects) */
ULONG pid = (ULONG)PsGetCurrentProcessId();
// if process name is unknown try to resolve it
if (!pid_pname_resolve(pid, NULL, 0))
{
KEVENT event;
struct flt_request request;
KeInitializeEvent(&event, NotificationEvent, FALSE);
pid_pname_set_event(pid, &event);
memset(&request, 0, sizeof(request));
request.struct_size = sizeof(request);
request.type = TYPE_RESOLVE_PID;
request.pid = pid;
// get user SID & attributes!
request.sid_a = get_current_sid_a(&request.sid_a_size);
if (log_request(&request))
{
// wait a little for reply from user-mode application
LARGE_INTEGER li;
li.QuadPart = 5000 * -10000; // 5 sec
status = KeWaitForSingleObject(&event, UserRequest, KernelMode, FALSE, &li);
}
else {
// check all rulesets: we've got the only _default_ ruleset active
status = default_chain_only() ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
if (request.sid_a != NULL)
free(request.sid_a);
// reset wait event
pid_pname_set_event(pid, NULL);
if (status != STATUS_SUCCESS)
return FILTER_DENY; // deny it!
}
/* TDI_CREATE related stuff */
if (ea != NULL)
{
/*
* We have FILE_FULL_EA_INFORMATION
*/
PDEVICE_OBJECT devobj;
int ipproto;
devobj = get_original_devobj(irps->DeviceObject, &ipproto);
if (devobj == NULL)
{
KdPrint(("[tdi_fw] tdi_create: unknown device object 0x%x!\n", irps->DeviceObject));
return FILTER_DENY;
}
// NOTE: for RawIp you can extract protocol number from irps->FileObject->FileName
if (ea->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH &&
memcmp(ea->EaName, TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH) == 0)
{
PIRP query_irp;
/*
* This is creation of address object
*/
KdPrint(("[tdi_fw] tdi_create: devobj 0x%x; addrobj 0x%x\n",
irps->DeviceObject,
irps->FileObject));
status = ot_add_fileobj(irps->DeviceObject, irps->FileObject, FILEOBJ_ADDROBJ, ipproto, NULL);
if (status != STATUS_SUCCESS)
{
KdPrint(("[tdi_fw] tdi_create: ot_add_fileobj: 0x%x\n", status));
return FILTER_DENY;
}
// while we're on PASSIVE_LEVEL build control IRP for completion
query_irp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION,
devobj, irps->FileObject, NULL, NULL);
if (query_irp == NULL)
{
KdPrint(("[tdi_fw] tdi_create: TdiBuildInternalDeviceControlIrp\n"));
return FILTER_DENY;
}
/* set IRP completion & context for completion */
completion->routine = tdi_create_addrobj_complete;
completion->context = query_irp;
}
else if (ea->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH &&
memcmp(ea->EaName, TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH) == 0)
{
/*
* This is creation of connection object
*/
CONNECTION_CONTEXT conn_ctx = *(CONNECTION_CONTEXT *)
(ea->EaName + ea->EaNameLength + 1);
KdPrint(("[tdi_fw] tdi_create: devobj 0x%x; connobj 0x%x; conn_ctx 0x%x\n",
irps->DeviceObject,
irps->FileObject,
conn_ctx));
status = ot_add_fileobj(irps->DeviceObject, irps->FileObject,
FILEOBJ_CONNOBJ, ipproto, conn_ctx);
if (status != STATUS_SUCCESS)
{
KdPrint(("[tdi_fw] tdi_create: ot_add_fileobj: 0x%x\n", status));
return FILTER_DENY;
}
}
}
else {
/*
* This is creation of control object
*/
KdPrint(("[tdi_fw] tdi_create(pid:%u): devobj 0x%x; Control Object: 0x%x\n",
pid, irps->DeviceObject, irps->FileObject));
}
return FILTER_ALLOW;
}
/* this completion routine queries address and port from address object */
NTSTATUS tdi_create_addrobj_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
{
NTSTATUS status;
PIO_STACK_LOCATION irps = IoGetCurrentIrpStackLocation(Irp);
PIRP query_irp = (PIRP)Context;
PDEVICE_OBJECT devobj;
TDI_CREATE_ADDROBJ2_CTX *ctx = NULL;
PMDL mdl = NULL;
KdPrint(("[tdi_fw] tdi_create_addrobj_complete: devobj 0x%x; addrobj 0x%x\n",
DeviceObject, irps->FileObject));
if (Irp->IoStatus.Status != STATUS_SUCCESS)
{
KdPrint(("[tdi_fw] tdi_create_addrobj_complete: status 0x%x\n", Irp->IoStatus.Status));
status = Irp->IoStatus.Status;
goto done;
}
// query addrobj address:port
ctx = (TDI_CREATE_ADDROBJ2_CTX *)malloc_np(sizeof(TDI_CREATE_ADDROBJ2_CTX));
if (ctx == NULL)
{
KdPrint(("[tdi_fw] tdi_create_addrobj_complete: malloc_np\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
ctx->fileobj = irps->FileObject;
ctx->tai = (TDI_ADDRESS_INFO *)malloc_np(TDI_ADDRESS_INFO_MAX);
if (ctx->tai == NULL)
{
KdPrint(("[tdi_fw] tdi_create_addrobj_complete: malloc_np!\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
mdl = IoAllocateMdl(ctx->tai, TDI_ADDRESS_INFO_MAX, FALSE, FALSE, NULL);
if (mdl == NULL)
{
KdPrint(("[tdi_fw] tdi_create_addrobj_complete: IoAllocateMdl!\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
MmBuildMdlForNonPagedPool(mdl);
devobj = get_original_devobj(DeviceObject, NULL); // use original devobj!
if (devobj == NULL)
{
KdPrint(("[tdi_fw] tdi_create_addrobj_complete: get_original_devobj!\n"));
status = STATUS_INVALID_PARAMETER;
goto done;
}
TdiBuildQueryInformation(query_irp, devobj, irps->FileObject,
tdi_create_addrobj_complete2, ctx,
TDI_QUERY_ADDRESS_INFO, mdl);
status = IoCallDriver(devobj, query_irp);
query_irp = NULL;
mdl = NULL;
ctx = NULL;
if (status != STATUS_SUCCESS)
{
KdPrint(("[tdi_fw] tdi_create_addrobj_complete: IoCallDriver: 0x%x\n", status));
goto done;
}
status = STATUS_SUCCESS;
done:
// cleanup
if (mdl != NULL)
IoFreeMdl(mdl);
if (ctx != NULL)
{
if (ctx->tai != NULL)
free(ctx->tai);
free(ctx);
}
if (query_irp != NULL)
IoCompleteRequest(query_irp, IO_NO_INCREMENT);
Irp->IoStatus.Status = status;
if (status != STATUS_SUCCESS)
{
// tdi_create failed - remove fileobj from hash
ot_del_fileobj(irps->FileObject, NULL);
}
return tdi_generic_complete(DeviceObject, Irp, Context);
}
/* this completion routine gets address and port from reply to TDI_QUERY_ADDRESS_INFO */
NTSTATUS tdi_create_addrobj_complete2(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
{
NTSTATUS status;
TDI_CREATE_ADDROBJ2_CTX *ctx = (TDI_CREATE_ADDROBJ2_CTX *)Context;
TA_ADDRESS *addr = ctx->tai->Address.Address;
struct ot_entry *ote_addr;
KIRQL irql;
int ipproto;
KdPrint(("[tdi_fw] tdi_create_addrobj_complete2: address: %x:%u\n",
ntohl(((TDI_ADDRESS_IP *)(addr->Address))->in_addr),
ntohs(((TDI_ADDRESS_IP *)(addr->Address))->sin_port)));
// save address
ote_addr = ot_find_fileobj(ctx->fileobj, &irql);
if (ote_addr == NULL)
{
KdPrint(("[tdi_fw] tdi_create_addrobj_complete2: ot_find_fileobj(0x%x)\n",
ctx->fileobj));
status = STATUS_OBJECT_NAME_NOT_FOUND;
goto done;
}
if (addr->AddressLength > sizeof(ote_addr->local_addr))
{
KdPrint(("[tdi_fw] tdi_create_addrobj_complete2: address too long! (%u)\n",
addr->AddressLength));
status = STATUS_BUFFER_OVERFLOW;
goto done;
}
memcpy(ote_addr->local_addr, addr, addr->AddressLength);
if (ote_addr->ipproto != IPPROTO_TCP)
{
// set "LISTEN" state for this addrobj
status = add_listen(ote_addr);
if (status != STATUS_SUCCESS)
{
KdPrint(("[tdi_fw] tdi_create_addrobj_complete2: add_listen: 0x%x!\n", status));
goto done;
}
}
status = STATUS_SUCCESS;
done:
if (ote_addr != NULL)
KeReleaseSpinLock(&g_ot_hash_guard, irql);
// cleanup MDL to avoid unlocking pages from NonPaged pool
if (Irp->MdlAddress != NULL)
{
IoFreeMdl(Irp->MdlAddress);
Irp->MdlAddress = NULL;
}
free(ctx->tai);
free(ctx);
// success anyway
return STATUS_SUCCESS;
}
//----------------------------------------------------------------------------
/*
* TDI_CLEANUP handler
*/
int tdi_cleanup(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion)
{
NTSTATUS status;
int type;
// delete fileobj
status = ot_del_fileobj(irps->FileObject, &type);
if (status != STATUS_SUCCESS)
KdPrint(("[tdi_fw] tdi_cleanup: del_fileobj: 0x%x!\n", status));
else
KdPrint(("[tdi_fw] tdi_cleanup: fileobj 0x%x, type %d\n", irps->FileObject, type));
// success anyway
return FILTER_ALLOW;
}
//----------------------------------------------------------------------------
/*
* TDI_ASSOCIATE_ADDRESS handler
*
* With help of this routine we can get address object by connection object
* and get connection object by connection context and address object
*/
int tdi_associate_address(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion)
{
HANDLE addr_handle = ((TDI_REQUEST_KERNEL_ASSOCIATE *)(&irps->Parameters))->AddressHandle;
PFILE_OBJECT addrobj = NULL;
NTSTATUS status;
struct ot_entry *ote_conn = NULL;
KIRQL irql;
int result = FILTER_DENY;
KdPrint(("[tdi_fw] tdi_associate_address: devobj 0x%x; connobj 0x%x\n",
irps->DeviceObject, irps->FileObject));
status = ObReferenceObjectByHandle(addr_handle, GENERIC_READ, NULL, KernelMode, &addrobj, NULL);
if (status != STATUS_SUCCESS)
{
KdPrint(("[tdi_fw] tdi_associate_address: ObReferenceObjectByHandle: 0x%x\n", status));
goto done;
}
KdPrint(("[tdi_fw] tdi_associate_address: connobj = 0x%x ---> addrobj = 0x%x\n",
irps->FileObject, addrobj));
// associate addrobj with connobj
ote_conn = ot_find_fileobj(irps->FileObject, &irql);
if (ote_conn == NULL)
{
KdPrint(("[tdi_fw] tdi_associate_address: ot_find_fileobj(0x%x)\n", irps->FileObject));
goto done;
}
ote_conn->associated_fileobj = addrobj;
// add (conn_ctx, addrobj)->connobj
status = ot_add_conn_ctx(addrobj, ote_conn->conn_ctx, irps->FileObject);
if (status != STATUS_SUCCESS)
{
KdPrint(("[tdi_fw] tdi_associate_address: ot_add_conn_ctx: 0x%x\n", status));
goto done;
}
result = FILTER_ALLOW;
done:
if (addrobj != NULL)
ObDereferenceObject(addrobj);
// cleanup
if (ote_conn != NULL)
KeReleaseSpinLock(&g_ot_hash_guard, irql);
return result;
}
//----------------------------------------------------------------------------
/*
* TDI_DISASSOCIATE_ADDRESS handler
*/
int tdi_disassociate_address(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion)
{
struct ot_entry *ote_conn = NULL;
KIRQL irql;
NTSTATUS status;
KdPrint(("[tdi_fw] tdi_disassociate_address: connobj 0x%x\n", irps->FileObject));
// delete connnection object
ote_conn = ot_find_fileobj(irps->FileObject, &irql);
if (ote_conn == NULL)
{
KdPrint(("[tdi_fw] tdi_disassociate_address: ot_find_fileobj(0x%x)\n", irps->FileObject));
goto done;
}
// delete link of (addrobj, conn_ctx)->connobj
status = ot_del_conn_ctx(ote_conn->associated_fileobj, ote_conn->conn_ctx);
if (status != STATUS_SUCCESS)
{
KdPrint(("[tdi_fw] tdi_disassociate_address: ot_del_conn_ctx: 0x%x\n", status));
goto done;
}
done:
if (ote_conn != NULL)
KeReleaseSpinLock(&g_ot_hash_guard, irql);
// success anyway
return FILTER_ALLOW;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -