⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tdi_fw_svc.c

📁 基于TDI驱动编写的个人防火墙程序。包括驱动模块、应用层规则配置及加载模块。
💻 C
📖 第 1 页 / 共 2 页
字号:
// $Id: tdi_fw_svc.c,v 1.12 2002/12/05 13:03:27 dev Exp $

#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <winioctl.h>
#include <psapi.h>

#include "flt_rule.h"
#include "ipc.h"
#include "tdi_fw_svc.h"
#include "thread.h"

#include "msg.h"

#define DISP_BUF_SIZE	0x10000

HANDLE g_device = INVALID_HANDLE_VALUE;

static HANDLE g_event = NULL;
static HANDLE g_exit_event = NULL;

static HANDLE g_pipe = INVALID_HANDLE_VALUE;

static HANDLE g_dispatcher = NULL;
static char *g_disp_buf = NULL;

static DWORD WINAPI dispatcher(LPVOID param);
static DWORD WINAPI restart_thread(LPVOID param);

static void dispatch_request(struct flt_request *request);

static FILE *g_logfile = NULL;

static BOOL		load_config(const char *config);
static BOOL		read_config(const char *config);
static BOOL		add_rules_name(const char *main_name, const char *config, int chain);
static void		add_rules(char *buf, const char *name, int chain);
static BOOL		get_pname_by_pid(u_long pid, char *buf, int buf_size);
static void		prepare_addr(char *buf, int size, u_long addr);

static void		my_GetLongPathName(LPCSTR lpszShortPath, LPSTR lpszLongPath,
								   DWORD cchBuffer);

// some config switches
static BOOL g_eventlog_allow = FALSE;
static BOOL g_eventlog_deny = FALSE;
static BOOL g_eventlog_error = FALSE;

// used in flt_rule.c
BOOL g_rules_resolve_addr = FALSE;

static BOOL g_logs_resolve_addr = FALSE;

static void log_msg(const char *msg, int type);

enum {
	MSGTYPE_ALLOW,
	MSGTYPE_DENY,
	MSGTYPE_ERROR
};

int
start(const char *config)
{
	static char device_name[] = "\\\\.\\tdi_fw";

	int result = FALSE;
	WSADATA wsd;
	DWORD thread_id;

	// startup sockets for names resolution
	WSAStartup(MAKEWORD(1, 1), &wsd);

	/* connect with driver */
	
	g_device = CreateFile(device_name, GENERIC_READ | GENERIC_WRITE, 
		FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
	if (g_device == INVALID_HANDLE_VALUE) {
		winerr(device_name);
		goto done;
	}

	/* open event for driver communication */

	g_event = OpenEvent(SYNCHRONIZE, FALSE, "tdi_fw_request");
	if (g_event == NULL) {
		winerr("start: OpenEvent");
		goto done;
	}

	/* load config & rules */

	if (!load_config(config))
		goto done;

	/* start dispatcher thread */

	g_exit_event = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (g_exit_event == NULL) {
		winerr("start: CreateEvent");
		goto done;
	}

	g_disp_buf = (char *)malloc(DISP_BUF_SIZE);
	if (g_disp_buf == NULL) {
		liberr("start: malloc");
		goto done;
	}

	g_dispatcher = lib_CreateThread(NULL, 0, dispatcher, (LPVOID)config, 0, &thread_id);
	if (g_dispatcher == NULL) {
		winerr("start: lib_CreateThread");
		goto done;
	}
	
	result = TRUE;

done:
	if (!result)
		stop();

	return result;
}

void
stop(void)
{
	// disconnect from driver
	if (g_device != INVALID_HANDLE_VALUE) {
		HANDLE old_h = g_device;
		g_device = INVALID_HANDLE_VALUE;
		CancelIo(old_h);
		CloseHandle(old_h);
	}

	// stop dispatcher thread

	if (g_exit_event != NULL)
		SetEvent(g_exit_event);
	
	if (g_dispatcher != NULL) {
		WaitForSingleObject(g_dispatcher, INFINITE);
		g_dispatcher = NULL;
	}

	// close logfile
	if (g_logfile != NULL) {
		fprintf(g_logfile, "--- end ---\n");
		fclose(g_logfile);
		g_logfile = NULL;
	}

	if (g_exit_event != NULL)
		CloseHandle(g_exit_event);
	if (g_event != NULL)
		CloseHandle(g_event);

	if (g_disp_buf != NULL) {
		free(g_disp_buf);
		g_disp_buf = NULL;
	}
}

void
wait(void)
{
	if (g_exit_event != NULL)
		WaitForSingleObject(g_exit_event, INFINITE);
}

/* output functions */

void
error(const char *fmt, ...)
{
	va_list ap;
	char message[1024];

	// prepare message

	va_start(ap, fmt);

	if (_vsnprintf(message, sizeof(message), fmt, ap) == -1)
		message[sizeof(message) - 1] = '\0';

	va_end(ap);

	// got message
	log_msg(message, MSGTYPE_ERROR);
}

void
winerr(const char *fn)
{
	char *win_msg = NULL;
	DWORD code = GetLastError();

	if (code == 0)
		error("WINERR\t%s:", fn);
	else {
		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
			FORMAT_MESSAGE_FROM_SYSTEM,NULL,code,
			MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPTSTR)&win_msg,0,NULL);

		if (win_msg != NULL) {
			// kill \r\n
			int len = strlen(win_msg);
			
			if (len >= 1)
				win_msg[len-1]=0;
			if (len >= 2)
				win_msg[len-2]=0;
			
			error("WINERR\t%s: %s", fn, win_msg);

			LocalFree(win_msg);
		} else
			error("WINERR\t%s: %d (0x%x)", fn, code, code);
	}

	// save error code
	SetLastError(code);
}

void
liberr(const char *fn)
{
	int code = errno;
	if (code != 0)
		error("LIBERR\t%s: %s", fn, strerror(code));
	else
		error("LIBERR\t%s:", fn);
}

/* dispatcher thread */
DWORD WINAPI
dispatcher(LPVOID param)
{
	char *config = (char *)param;
	HANDLE handles[2];
	DWORD i, n;

	handles[0] = g_event;
	handles[1] = g_exit_event;

	for (;;) {
		if (!DeviceIoControl(g_device, IOCTL_CMD_GETREQUEST, NULL, 0,
			g_disp_buf, DISP_BUF_SIZE, &n, NULL)) {
			winerr("dispatcher: DeviceIoControl");
			break;
		}

		if (n == 0) {
			// wait for data
			DWORD wait = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
			
			if (wait == WAIT_OBJECT_0 + 1)
				break;
			else if (wait != WAIT_OBJECT_0) {
				winerr("dispatcher: WaitForSingleObject");
				break;
			}
			continue;
		}

		for (i = 0; i < n;) {
			struct flt_request *request;
			
			if (n - i < sizeof(*request))
				break;

			request = (struct flt_request *)(g_disp_buf + i);

			dispatch_request(request);
			
			i += request->struct_size;
		}
	}

	if (g_device != INVALID_HANDLE_VALUE) {
		DWORD thread_id;

		error("dispatcher: unexpected exit!");
		
		// restart tdi_fw_svc
		lib_CreateThread(NULL, 0, restart_thread, config, 0, &thread_id);
	}

	return 0;
}

DWORD
WINAPI restart_thread(LPVOID param)
{
	char *config = (char *)param;

	error("restarting...");
	
	stop();
	start(config);
	
	return 0;
}

/* log filter request from filter driver */
void
dispatch_request(struct flt_request *request)
{
	u_long from_ip, to_ip;
	u_short from_port, to_port;
	char msg[1024], pname_buf[MAX_PATH], addr_from[100], addr_to[100], *pname;

	if (request->pname == NULL) {
		// try to resolve pid to pname
		if (get_pname_by_pid(request->pid, pname_buf + sizeof(DWORD), sizeof(pname_buf) - sizeof(DWORD))) {
			// send message to driver to send process name next time
			DWORD n;

			pname = pname_buf + sizeof(DWORD);
			*(DWORD *)pname_buf = request->pid;

			if (!DeviceIoControl(g_device, IOCTL_CMD_SETPNAME, pname_buf,
				sizeof(DWORD) + strlen(pname) + 1,
				NULL, 0, &n, NULL))
				winerr("DeviceIoControl");

		} else {
			error("PROCESS\tCan't resolve pid %u!\n", request->pid);
			sprintf(pname_buf, "pid:%u", request->pid);
			pname = pname_buf;
		}
	
	} else
		pname = (char *)&request[1];
	
	// check is it request type "TYPE_RESOLVE_PID"
	if (request->type == TYPE_RESOLVE_PID) {

		if (_snprintf(msg, sizeof(msg), "PROCESS\t%u\t%s", request->pid, pname) == -1)
			msg[sizeof(msg) - 1] = '\0';

		log_msg(msg, request->result == FILTER_ALLOW ? MSGTYPE_ALLOW : MSGTYPE_DENY);	
		
	} else {
	
		// prepare message
		
		from_ip = ((struct sockaddr_in *)&request->addr.from)->sin_addr.s_addr;
		from_port = ntohs(((struct sockaddr_in *)&request->addr.from)->sin_port);
		to_ip = ((struct sockaddr_in *)&request->addr.to)->sin_addr.s_addr;
		to_port = ntohs(((struct sockaddr_in *)&request->addr.to)->sin_port);

		// prepare address "from" & "to"
		prepare_addr(addr_from, sizeof(addr_from), from_ip);
		prepare_addr(addr_to, sizeof(addr_to), to_ip);

		// log it!
		if (_snprintf(msg, sizeof(msg),
			"%s\t%s\t%s\t%s:%d\t%s:%d\t%s",
			(request->result == FILTER_ALLOW) ? "ALLOW" : "DENY",
			(request->proto == IPPROTO_TCP) ? "TCP" :
				(request->proto == IPPROTO_UDP ? "UDP" : "RawIP"),
			(request->direction == DIRECTION_IN) ? "IN" : "OUT",
			addr_from, from_port,
			addr_to, to_port, pname) == -1)
			msg[sizeof(msg) - 1] = '\0';

		log_msg(msg, request->result == FILTER_ALLOW ? MSGTYPE_ALLOW : MSGTYPE_DENY);	
	}
}

/*
 * write message to console, log file or probably to eventlog
 *
 * don't call any error functions! to cause infinite recurse.
 */
void
log_msg(const char *msg, int type)
{
	static int file_day = 0;	// for midnight checking
	static ULONG event_num = 1;	// number of event in log file

	// if working in console mode write message to console
	if (g_console) {
		if (type == MSGTYPE_ERROR)
			fprintf(stderr, "%s\n", msg);
		else
			printf("%s\n", msg);
	}

	// write to eventlog if filter is set
	if ((type == MSGTYPE_ALLOW && g_eventlog_allow) ||
		(type == MSGTYPE_DENY && g_eventlog_deny) ||
		(type == MSGTYPE_ERROR && g_eventlog_error)) {

		HANDLE hEventSource;
		const char *strings;

		// write message to event log
        // Use event logging to log the error.
        //
        hEventSource = RegisterEventSource(NULL, "tdi_fw_svc");

        if (hEventSource != NULL) {
			WORD event_type;

			strings = msg;		// write message without timestamp

			event_type = (type == MSGTYPE_ALLOW) ? EVENTLOG_AUDIT_SUCCESS :
				(type == MSGTYPE_DENY ? EVENTLOG_AUDIT_FAILURE : EVENTLOG_ERROR_TYPE);

            if (!ReportEvent(hEventSource, // handle of event source
					event_type,
					0,                    // event category
					MSG,                  // event ID
					NULL,                 // current user's SID
					1,                    // strings in lpszStrings
					0,                    // no bytes of raw data
					&strings,             // array of error strings
					NULL)) {              // no raw data
				
#ifdef _DEBUG
				MessageBeep(0);
				OutputDebugString("log_msg: ReportEvent\n");
#endif
			}

            DeregisterEventSource(hEventSource);
		}
	} else {

		// write message to log

		time_t tv;
		struct tm *tm;
		char tm_msg[1024];

		time(&tv);
		tm = localtime(&tv);
		if (tm == NULL) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -