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

📄 tdifw_svc.c

📁 开源的防火墙代码
💻 C
📖 第 1 页 / 共 3 页
字号:
				{
				case DIRECTION_IN:
					direction = "IN";
					break;
				case DIRECTION_OUT:
					direction = "OUT";
					break;
				case DIRECTION_ANY:
					direction = "*";
					break;
				default:
					direction = "?";
				}
			
			if (_snprintf(msg, sizeof(msg),
				"%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
				tdi_msg,
				(request->proto == IPPROTO_TCP) ? "TCP" :
				(request->proto == IPPROTO_UDP ? "UDP" : "RawIP"),
				direction,
				addr_from, addr_to, size_str, pname, uname) == -1)
				msg[sizeof(msg) - 1] = '\0';
			
			// sound it!
			if (request->result == FILTER_DENY)
				{
				
				// TODO: try to sound it by voice of user!
				
				if (request->direction == DIRECTION_IN && wave_deny_in[0] != '\0')
					PlaySound(wave_deny_in, NULL, SND_FILENAME | SND_ASYNC);
				if (request->direction == DIRECTION_OUT && wave_deny_out[0] != '\0')
					PlaySound(wave_deny_out, NULL, SND_FILENAME | SND_ASYNC);
				}
			
			log_msg(msg, request->result == FILTER_ALLOW ? MSGTYPE_ALLOW : MSGTYPE_DENY);
			
			}
		else if (request->result == FILTER_PACKET_LOG || request->result == FILTER_PACKET_BAD)
			{
			char flags[50], proto[50];
			
			// prepare TCP flags or ICMP type
			if (request->result == FILTER_PACKET_LOG)
				{
				if (request->proto == IPPROTO_TCP)
					{
					UCHAR th_flags = request->packet.tcp_flags;
					
					flags[0] = (th_flags & TH_FIN) ? 'F' : '-';
					flags[1] = (th_flags & TH_SYN) ? 'S' : '-';
					flags[2] = (th_flags & TH_RST) ? 'R' : '-';
					flags[3] = (th_flags & TH_PUSH) ? 'P' : '-';
					flags[4] = (th_flags & TH_ACK) ? 'A' : '-';
					flags[5] = (th_flags & TH_URG) ? 'U' : '-';
					flags[6] = '\0';
					
					}
				else if (request->proto == IPPROTO_ICMP)
					sprintf(flags, "%d.%d", request->packet.icmp_type, request->packet.icmp_code);
				else
					flags[0] = '\0';
				}
			else
				flags[0] = '\0';
			
			switch (request->proto)
				{
				case IPPROTO_TCP:
					if (request->packet.tcp_state > TCP_STATE_NONE &&
						request->packet.tcp_state < TCP_STATE_MAX)
						sprintf(proto, "TCP(%s)", g_tcp_states[request->packet.tcp_state]);
					else
						strcpy(proto, "TCP");
					break;
				case IPPROTO_UDP:
					strcpy(proto, "UDP");
					break;
				case IPPROTO_ICMP:
					strcpy(proto, "ICMP");
					break;
				default:
					sprintf(proto, "%d", request->proto);
				}
			
			
			// log it! (packet filter message)
			if (_snprintf(msg, sizeof(msg),
				"%s\t%s\t%s\t%s\t%s\t%u\t%s",
				(request->result == FILTER_PACKET_LOG) ? "PACKET" : "BAD_PACKET",
				proto,
				(request->direction == DIRECTION_IN) ? "IN" : "OUT",
				addr_from, addr_to,
				(request->direction == DIRECTION_IN) ? request->log_bytes_in : request->log_bytes_out,
				flags) == -1)
				msg[sizeof(msg) - 1] = '\0';
			
			log_msg(msg, request->result == FILTER_PACKET_LOG ? MSGTYPE_ALLOW : MSGTYPE_DENY);
			
			}
		}
}

/*
* write message to console, log file or probably to eventlog
* don't call any error functions! avoid 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, "tdifw_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)
			{
#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\\tdifw\\%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 = NULL, *p;
	DWORD n, pids[100];
	BOOL result = FALSE;
	int line, chain, i;
	
	if (!read_config(config))
		return FALSE;
	
	// save config to global variable (for get_host_by_name)
	g_config_file = config;
	
	// load information about users
	if (!load_users(config))
		{
		error("start: Fatal error! Can't load users information!\n");
		goto done;
		}
	
	// 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 == ';' || *p == '#')
		continue;		// comment
		
		p2 = strchr(p, '=');
		if (p2 == NULL)
			{
			error("%s:[_main_]:%d: invalid line format (no '=' character)", config, line);
			continue;
			}
		
		if (chain >= MAX_CHAINS_COUNT)
			{
			error("%s:[_main_]:%d: too many rules lines!", config, line);
			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 (pEnumProcesses != NULL && pEnumProcesses(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");
				}
			}
		}
	
	// activate all chains!
	for (i = 0; i < chain; i++)
		{
		// activate chain #i
		if (!DeviceIoControl(g_device, IOCTL_CMD_ACTIVATECHAIN, &i, sizeof(i),
			NULL, 0, &n, NULL))
			winerr("start: 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);
	
	// read wave_deny_in/out values
	
	GetPrivateProfileString(config_name, "wave_deny_in", "", wave_deny_in, sizeof(wave_deny_in), config);
	GetPrivateProfileString(config_name, "wave_deny_out", "", wave_deny_out, sizeof(wave_deny_out), 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) + MAX_PATH;
		char *data = (char *)malloc(len);
		if (data == NULL)
			{
			liberr("malloc");
			goto done;
			}
		
		*(int *)data = chain;
		
		// try to extract environment variables from p to main_name
		ExpandEnvironmentStrings(main_name, data + sizeof(int), MAX_PATH);
		
		len = sizeof(int) + strlen(data + sizeof(int)) + 1;
		
		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(config, section, p, chain);
			}
		
		p = p2;
		}
	
	result = TRUE;
	
	done:
	free(section);
	return result;
}

void	add_rules(const char *config, char *buf, const char *name, int chain)
{
	char *p, *p2;
	int n_str;
	DWORD n;
	UCHAR sid_mask[MAX_SIDS_COUNT / 8];
	
	get_sid_mask(config, name, sid_mask);
	
	for (p = buf, n_str = 1; *p != '\0'; p = p2, n_str++)
		{
		struct flt_rule rule;
		char num[10];
		
		p2 = p + strlen(p) + 1;
		
		if (*buf == ';' || *buf == '\0')
		continue;		// empty line or comment
		
		memset(&rule, 0, sizeof(rule));
		
		// parse it!
		if (!parse_rule(p, &rule))
			{
			error("Error in line #%d of section [%s]", n_str, name);
			continue;
			}
		
		// set chain
		rule.chain = chain;
		
		// set SID mask
		memcpy(rule.sid_mask, sid_mask, sizeof(rule.sid_mask));
		
		if (rule.rule_id[0] == '\0')
			{
			// set default rule name: name of section + n_str
			strncpy(rule.rule_id, name, RULE_ID_SIZE);	// string can be not zero-terminated
			sprintf(num, ":%d", n_str);
			if (strlen(name) + strlen(num) < RULE_ID_SIZE)
				memcpy(rule.rule_id + strlen(name), num, strlen(num));	// string can be not zero-terminated
			else
				memcpy(rule.rule_id + RULE_ID_SIZE - strlen(num), num, strlen(num));
			}
		
		// append rule
		if (!DeviceIoControl(g_device, IOCTL_CMD_APPENDRULE, &rule, sizeof(rule),
			NULL, 0, &n, NULL))
			{
			winerr("start: DeviceIoControl");
			break;
			}
		}
}

BOOL	get_pname_by_pid(u_long pid, char *buf, int buf_size)
{
	BOOL result;
	HANDLE h_process;
	HMODULE h_module = NULL;
	DWORD n;
	
	if (g_psapi == NULL)
		return FALSE;			// failed to load psapi.dll
	
	// try to resolve pid to pname
	
	h_process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
	if (h_process != NULL)
		pEnumProcessModules(h_process, &h_module, sizeof(h_module), &n);
	
	// on error write pid
	if (h_module == NULL ||
		pGetModuleFileNameEx(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;
		}
	
	if (h_process != NULL)
		CloseHandle(h_process);
	return result;
}

void	prepare_addr(char *buf, int size, u_long addr)
{
	// XXX do we need resolving?
	strcpy(buf, inet_ntoa(*(struct in_addr *)&addr));
}

ULONG	get_host_by_name(const char *hostname, char *net_mask)
{
	// resolve address using config file (DNS way is insecure)
	char addr[100], *p;
	
	GetPrivateProfileString("_hosts_", hostname, "", addr, sizeof(addr), g_config_file);
	
	if (*addr == '\0')
		return INADDR_NONE;
	
	p = strchr(addr, '/');
	if (p != NULL)
		{
		// got net_mask!
		*(p++) = '\0';
		
		// max size is 2 characters! (/xx)
		strncpy(net_mask, p, 2);
		net_mask[2] = '\0';
		}
	else
		*net_mask = '\0';

⌨️ 快捷键说明

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