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

📄 tdi_fw_svc.c

📁 非常使用的基于TDI驱动开发的应用程序过滤 防火墙的例子
💻 C
📖 第 1 页 / 共 2 页
字号:
		if (tm == NULL) {
#ifdef _DEBUG
			MessageBeep(0);
			OutputDebugString("log_msg: localtime\n");
#endif
			return;
		}

		if (g_logfile == NULL || tm->tm_mday != file_day) {
			char fname[MAX_PATH];

			if (g_logfile != NULL) {
				// wow! we're working at midnight! change log file!
				fprintf(g_logfile, "--- midnight ---\n");
				fclose(g_logfile);
				g_logfile = NULL;
			}

			file_day = tm->tm_mday;
			
			// open logfile
			
			if (_snprintf(fname, sizeof(fname),
				"%s\\system32\\LogFiles\\tdi_fw\\%04d%02d%02d.log",
				getenv("SystemRoot"),
				tm->tm_year + 1900,
				tm->tm_mon + 1,
				tm->tm_mday) == -1) {

#ifdef _DEBUG
				MessageBeep(0);
				OutputDebugString("log_msg: _snprintf overflow!\n");
#endif
				return;
			}

			g_logfile = fopen(fname, "a");
			if (g_logfile == NULL) {
#ifdef _DEBUG
				MessageBeep(0);
				OutputDebugString("log_msg: fopen error!\n");
#endif
				return;
			}

			fprintf(g_logfile, "--- begin ---\n");
		}

		if (_snprintf(tm_msg, sizeof(tm_msg),
			"%010u %02d:%02d:%02d\t%s",
			event_num++, tm->tm_hour, tm->tm_min, tm->tm_sec, msg) == -1)
			tm_msg[sizeof(tm_msg) - 1] = '\0';

		// write it to log file
		fprintf(g_logfile, "%s\n", tm_msg);
		fflush(g_logfile);
	
	}
}

#define MAX_SECTION_SIZE	(16 * 1024)

BOOL
load_config(const char *config)
{
	char *section, *p;
	DWORD n, pids[100];
	BOOL result = FALSE;
	int line, chain;

	if (!read_config(config))
		return FALSE;

	// parse & add rules default and process-related

	section = (char *)malloc(MAX_SECTION_SIZE);
	if (section == NULL) {
		liberr("malloc");
		goto done;
	}

	GetPrivateProfileSection("_main_", section, MAX_SECTION_SIZE, config);
	
	// get lines
	chain = 0;
	for (p = section, line = 1; *p != '\0';p += strlen(p) + 1, line++) {
		char *p2;

		if (*p == ';')
			continue;		// comment

		p2 = strchr(p, '=');
		if (p2 == NULL) {
			error("%s:[_main_]:%d: invalid line format (no '=' character)");
			continue;
		}

		if (chain >= MAX_CHAINS_COUNT) {
			error("%s:[_main_]:%d: too many rules lines!");
			break;
		}

		*p2 = '\0';		// temporary kill '='
		add_rules_name(p, config, chain);
		*p2 = '=';		// recover '=' to make strlen(p) works right

		chain++;
	}

	// try to get names for existing processes
	if (EnumProcesses(pids, sizeof(pids), &n)) {
		DWORD i;

		n /= sizeof(DWORD);

		for (i = 0; i < n; i++) {
			char pname[MAX_PATH];
			if (get_pname_by_pid(pids[i], pname + sizeof(DWORD), sizeof(pname) - sizeof(DWORD))) {
				// send information to driver about pid and pname
				
				DWORD nn;
				
				*(DWORD *)pname = pids[i];

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

	result = TRUE;
done:
	free(section);
	return result;
}

BOOL
read_config(const char *config)
{
	static char config_name[] = "_config_";
	static char signature_name[] = "_signature_";
	static char signature_value[] = "$tdi_fw$";

	char buf[100];

	// first, check config file signature
	GetPrivateProfileString(signature_name, signature_name, "", buf, sizeof(buf), config);
	if (strcmp(buf, signature_value) != 0) {
		error("\"%s\": invalid configuration file", config);
		return FALSE;
	}

	// get g_eventlog_xxx values

	g_eventlog_allow = GetPrivateProfileInt(config_name, "eventlog_allow", FALSE, config);
	g_eventlog_deny = GetPrivateProfileInt(config_name, "eventlog_deny", FALSE, config);
	g_eventlog_error = GetPrivateProfileInt(config_name, "eventlog_error", FALSE, config);

	// get other values

	g_rules_resolve_addr = GetPrivateProfileInt(config_name, "rules_resolve_addr", FALSE, config);
	g_logs_resolve_addr = GetPrivateProfileInt(config_name, "logs_resolve_addr", FALSE, config);

	return TRUE;
}

BOOL
add_rules_name(const char *main_name, const char *config, int chain)
{
	char buf[1024], *p, *p2, *section = NULL;
	BOOL result = FALSE;
	DWORD n;

	section = (char *)malloc(MAX_SECTION_SIZE);
	if (section == NULL) {
		liberr("malloc");
		goto done;
	}

	/* 1. get ruleset string */

	GetPrivateProfileString("_main_", main_name, "", buf, sizeof(buf), config);

	if (*buf == '\0')
		goto done;		// no rules

	// reset all rules for chain
	if (!DeviceIoControl(g_device, IOCTL_CMD_CLEARCHAIN, &chain, sizeof(chain),
		NULL, 0, &n, NULL)) {
		winerr("DeviceIoControl");
		goto done;
	}

	if (chain != 0) {
		// set chain name
		int len = sizeof(int) + strlen(main_name) + 1;
		char *data = (char *)malloc(len);
		if (data == NULL) {
			liberr("malloc");
			goto done;
		}

		*(int *)data = chain;
		strcpy(data + sizeof(int), main_name);
		
		if (!DeviceIoControl(g_device, IOCTL_CMD_SETCHAINPNAME, data, len,
			NULL, 0, &n, NULL)) {
			winerr("DeviceIoControl");
			free(data);
			goto done;
		}
		free(data);
	}

	/* 2. for each word in main_name string */

	p = buf;
	
	while (p != NULL) {

		p2 = strchr(p, ' ');
		if (p2 != NULL) {
			while (*p2 == ' ')
				*(p2++) = '\0';
		}
		
		if (*p != '\0') {
			// get section by name in p
			GetPrivateProfileSection(p, section, MAX_SECTION_SIZE, config);
			if (*section == '\0')
				error("\"%s\": unexistant or empty section %s", config, p);
			else
				add_rules(section, p, chain);
		}

		p = p2;
	}

	result = TRUE;

done:
	free(section);
	return result;
}

void
add_rules(char *buf, const char *name, int chain)
{
	char *p, *p2;
	int n_str;

	for (p = buf, n_str = 1; *p != '\0'; p = p2, n_str++) {
		struct flt_rule rule;
		DWORD n;

		p2 = p + strlen(p) + 1;

		if (*buf == ';' || *buf == '\0')
			continue;		// empty line or comment

		memset(&rule, 0, sizeof(rule));
		
		if (!parse_rule(p, &rule)) {
			error("Error in line #%d of section [%s]", n_str, name);
			continue;
		}

		// set chain
		rule.chain = chain;

		// append rule
		if (!DeviceIoControl(g_device, IOCTL_CMD_APPENDRULE, &rule, sizeof(rule),
				NULL, 0, &n, NULL)) {
			winerr("start: DeviceIoControl");
			return;
		}
	}
}

BOOL
get_pname_by_pid(u_long pid, char *buf, int buf_size)
{
	BOOL result;
	HANDLE h_process;
	HMODULE h_module;
	DWORD n;

	// try to resolve pid to pname
	
	h_process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
	if (h_process != NULL)
		EnumProcessModules(h_process, &h_module, sizeof(h_module), &n);

	// on error write pid
	if (h_module == NULL ||
		GetModuleFileNameEx(h_process, h_module, buf, buf_size) == 0) {

		// for "System" process last error value is:
		// * ERROR_PARTIAL_COPY (on 2k)
		// * ERROR_NOACCESS (on NT4)
		// ??? on other (TODO: think about another way)
		if (GetLastError() == ERROR_PARTIAL_COPY ||
			GetLastError() == ERROR_NOACCESS) {
			
			strncpy(buf, "System", buf_size);
			buf[buf_size - 1] = '\0';
			
			result = TRUE;
		
		} else {
			*buf = '\0';
			result = FALSE;
		}

	} else {
		if (strchr(buf, '~') != NULL) {		// XXX is it a right way?
			// try to convert long name to short name
			char long_name[MAX_PATH];
			
			my_GetLongPathName(buf, long_name, sizeof(long_name));
				
			strncpy(buf, long_name, buf_size - 1);
			buf[buf_size - 1] = '\0';
		}

		result = TRUE;
	}

	return result;
}

void
prepare_addr(char *buf, int size, u_long addr)
{
	if (g_logs_resolve_addr) {
		// TODO: doesn't work correctly (maybe remove it?)
		struct hostent *he;

		if (addr == INADDR_ANY) {
			strcpy(buf, "ANY");
			return;
		}

		// try to resolve addr
		he = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
		if (he != NULL) {
			// set name in buffer (and reserve space for <ip>)
			size_t len = size - sizeof("<XXX.XXX.XXX.XXX>");
			strncpy(buf, he->h_name, len);
			buf[len - 1] = '\0';
		} else
			buf[0] = '\0';

		// add <ip>
		strcat(buf, "[");
		strcat(buf, inet_ntoa(*(struct in_addr *)&addr));
		strcat(buf, "]");
	} else
		strcpy(buf, inet_ntoa(*(struct in_addr *)&addr));
}

// GetLongPathName is in Windows 2000 only so make it for NT4
void
my_GetLongPathName(LPCSTR lpszShortPath, LPSTR lpszLongPath, DWORD cchBuffer)
{
	LPSTR p_l;
	LPCSTR p_s;

	lpszLongPath[0] = lpszShortPath[0];
	lpszLongPath[1] = lpszShortPath[1];
	lpszLongPath[2] = lpszShortPath[2];
	lpszLongPath[3] = '\0';
	
	p_l = &lpszLongPath[3];
	p_s = &lpszShortPath[3];

	for (;;) {
		LPSTR p_s2;
		HANDLE search;
		WIN32_FIND_DATA ffd;
		size_t len;
		BOOL overflow;

		p_s2 = strchr(p_s, '\\');

		if (p_s2 != NULL)
			len = p_s2 - p_s;
		else
			len = strlen(p_s);

		// check the buffer
		if (len + (p_l - lpszLongPath) >= cchBuffer) {
			// buffer overflow: copy and exit
			len = cchBuffer - (p_l - lpszLongPath) - 1;
			overflow = TRUE;
		} else
			overflow = FALSE;
		
		memcpy(p_l, p_s, len);
		p_l[len] = '\0';
	
		if (overflow)
			break;

		search = FindFirstFile(lpszLongPath, &ffd);
		if (search != INVALID_HANDLE_VALUE) {

			len = strlen(ffd.cFileName);
			if (p_s2 != NULL)
				len++;

			// check the buffer
			if (len + (p_l - lpszLongPath) >= cchBuffer) {
				// buffer overflow: copy and exit
				len = cchBuffer - (p_l - lpszLongPath) - 1;
				p_s2 = NULL;
			}

			memcpy(p_l, ffd.cFileName, len);
			
			if (p_s2 != NULL) {
				p_l[len - 1] = '\\';
				p_l[len] = '\0';
			} else
				p_l[len] = '\0';

			FindClose(search);
		}

		if (p_s2 == NULL)
			break;

		p_l += strlen(p_l);
		p_s = p_s2 + 1;
	}

	// ignore status
}

⌨️ 快捷键说明

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