1
0
mirror of https://github.com/solemnwarning/ipxwrapper synced 2024-12-30 16:45:37 +01:00

Automatically add exceptions to Windows Firewall

If enabled (default is off) and running as an admin, add the running executable
to the Windows Firewall exception list during DLL initialisation.
This commit is contained in:
Daniel Collins 2013-12-11 00:53:30 +00:00
parent 7cbde56f1a
commit 223bfeb35a
11 changed files with 4182 additions and 14 deletions

View File

@ -1,5 +1,5 @@
# IPXWrapper - Makefile
# Copyright (C) 2011 Daniel Collins <solemnwarning@solemnwarning.net>
# Copyright (C) 2011-2013 Daniel Collins <solemnwarning@solemnwarning.net>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 as published by
@ -20,8 +20,10 @@ else
DBG_OPT := -Wl,-s
endif
CFLAGS := -Wall -D_WIN32_WINNT=0x0500 $(DBG_OPT) -I./include/
CXXFLAGS := $(CFLAGS)
INCLUDE := -I./include/
CFLAGS := -std=c99 -Wall -D_WIN32_WINNT=0x0500 $(DBG_OPT) $(INCLUDE)
CXXFLAGS := -Wall $(DBG_OPT) $(INCLUDE)
# Used by mkdeps.pl
#
@ -34,7 +36,7 @@ VERSION := git
IPXWRAPPER_DEPS := src/ipxwrapper.o src/winsock.o src/ipxwrapper_stubs.o src/log.o src/common.o \
src/interface.o src/router.o src/ipxwrapper.def src/addrcache.o src/config.o src/addr.o \
src/addrtable.o
src/addrtable.o src/firewall.o
BIN_FILES := $(shell cat manifest.bin.txt)
SRC_FILES := $(shell cat manifest.src.txt)
@ -80,7 +82,7 @@ Makefile.dep: src/*.c src/*.cpp
ipxwrapper.dll: $(IPXWRAPPER_DEPS)
echo 'const char *version_string = "$(VERSION)", *compile_time = "'`date`'";' | $(CC) -c -x c -o version.o -
$(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -shared -o ipxwrapper.dll $(IPXWRAPPER_DEPS) version.o -liphlpapi
$(CC) $(CFLAGS) -Wl,--enable-stdcall-fixup -shared -o ipxwrapper.dll $(IPXWRAPPER_DEPS) version.o -liphlpapi -lversion -lole32 -loleaut32
ipxconfig.exe: src/ipxconfig.cpp icons/ipxconfig.o src/addr.o src/interface.o src/common.o src/config.o
$(CXX) $(CXXFLAGS) -static-libgcc -static-libstdc++ -D_WIN32_IE=0x0400 -mwindows -o ipxconfig.exe $^ -liphlpapi -lcomctl32 -lws2_32

View File

@ -1,3 +1,9 @@
Version 0.4.1:
Feature: Added workaround for point-to-point links.
Feature: Added option to automatically add Windows Firewall exceptions
during DLL initialisation. Disabled by default.
Version 0.4.0:
Bugfix: Fixed a crash in closesocket.

117
include/icftypes.h Normal file
View File

@ -0,0 +1,117 @@
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
/* File created by MIDL compiler version 6.00.0366 */
/* Compiler settings for icftypes.idl:
Oicf, W1, Zp8, env=Win32 (32b run)
protocol : dce , ms_ext, c_ext, robust
error checks: allocation ref bounds_check enum stub_data
VC __declspec() decoration level:
__declspec(uuid()), __declspec(selectany), __declspec(novtable)
DECLSPEC_UUID(), MIDL_INTERFACE()
*/
//@@MIDL_FILE_HEADING( )
#pragma warning( disable: 4049 ) /* more than 64k source lines */
/* verify that the <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 475
#endif
#include "rpc.h"
#include "rpcndr.h"
#ifndef __RPCNDR_H_VERSION__
#error this stub requires an updated version of <rpcndr.h>
#endif // __RPCNDR_H_VERSION__
#ifndef __icftypes_h__
#define __icftypes_h__
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
/* Forward Declarations */
/* header files for imported files */
#include "wtypes.h"
#ifdef __cplusplus
extern "C"{
#endif
void * __RPC_USER MIDL_user_allocate(size_t);
void __RPC_USER MIDL_user_free( void * );
/* interface __MIDL_itf_icftypes_0000 */
/* [local] */
typedef
enum NET_FW_POLICY_TYPE_
{ NET_FW_POLICY_GROUP = 0,
NET_FW_POLICY_LOCAL = NET_FW_POLICY_GROUP + 1,
NET_FW_POLICY_EFFECTIVE = NET_FW_POLICY_LOCAL + 1,
NET_FW_POLICY_TYPE_MAX = NET_FW_POLICY_EFFECTIVE + 1
} NET_FW_POLICY_TYPE;
typedef
enum NET_FW_PROFILE_TYPE_
{ NET_FW_PROFILE_DOMAIN = 0,
NET_FW_PROFILE_STANDARD = NET_FW_PROFILE_DOMAIN + 1,
NET_FW_PROFILE_CURRENT = NET_FW_PROFILE_STANDARD + 1,
NET_FW_PROFILE_TYPE_MAX = NET_FW_PROFILE_CURRENT + 1
} NET_FW_PROFILE_TYPE;
typedef
enum NET_FW_IP_VERSION_
{ NET_FW_IP_VERSION_V4 = 0,
NET_FW_IP_VERSION_V6 = NET_FW_IP_VERSION_V4 + 1,
NET_FW_IP_VERSION_ANY = NET_FW_IP_VERSION_V6 + 1,
NET_FW_IP_VERSION_MAX = NET_FW_IP_VERSION_ANY + 1
} NET_FW_IP_VERSION;
typedef
enum NET_FW_SCOPE_
{ NET_FW_SCOPE_ALL = 0,
NET_FW_SCOPE_LOCAL_SUBNET = NET_FW_SCOPE_ALL + 1,
NET_FW_SCOPE_CUSTOM = NET_FW_SCOPE_LOCAL_SUBNET + 1,
NET_FW_SCOPE_MAX = NET_FW_SCOPE_CUSTOM + 1
} NET_FW_SCOPE;
typedef
enum NET_FW_IP_PROTOCOL_
{ NET_FW_IP_PROTOCOL_TCP = 6,
NET_FW_IP_PROTOCOL_UDP = 17
} NET_FW_IP_PROTOCOL;
typedef
enum NET_FW_SERVICE_TYPE_
{ NET_FW_SERVICE_FILE_AND_PRINT = 0,
NET_FW_SERVICE_UPNP = NET_FW_SERVICE_FILE_AND_PRINT + 1,
NET_FW_SERVICE_REMOTE_DESKTOP = NET_FW_SERVICE_UPNP + 1,
NET_FW_SERVICE_NONE = NET_FW_SERVICE_REMOTE_DESKTOP + 1,
NET_FW_SERVICE_TYPE_MAX = NET_FW_SERVICE_NONE + 1
} NET_FW_SERVICE_TYPE;
extern RPC_IF_HANDLE __MIDL_itf_icftypes_0000_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_icftypes_0000_v0_0_s_ifspec;
/* Additional Prototypes for ALL interfaces */
/* end of Additional Prototypes */
#ifdef __cplusplus
}
#endif
#endif

3768
include/netfw.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
-- LICENSE --
Copyright (C) 2008-2012 Daniel Collins <solemnwarning@solemnwarning.net>
Copyright (C) 2008-2013 Daniel Collins <solemnwarning@solemnwarning.net>
Read license.txt for licensing terms.
-- INTRODUCTION --

View File

@ -1,5 +1,5 @@
/* ipxwrapper - Configuration header
* Copyright (C) 2011 Daniel Collins <solemnwarning@solemnwarning.net>
* Copyright (C) 2011-2013 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
@ -29,6 +29,7 @@ main_config_t get_main_config(void)
config.udp_port = DEFAULT_PORT;
config.w95_bug = true;
config.fw_except = false;
config.log_level = LOG_INFO;
HKEY reg = reg_open_main(false);
@ -47,8 +48,9 @@ main_config_t get_main_config(void)
/* Overlay with any 0.4.x config values. */
config.udp_port = reg_get_dword(reg, "port", config.udp_port);
config.w95_bug = reg_get_dword(reg, "w95_bug", config.w95_bug);
config.udp_port = reg_get_dword(reg, "port", config.udp_port);
config.w95_bug = reg_get_dword(reg, "w95_bug", config.w95_bug);
config.fw_except = reg_get_dword(reg, "fw_except", config.fw_except);
config.log_level = reg_get_dword(reg, "log_level", config.log_level);
reg_close(reg);
@ -62,6 +64,7 @@ bool set_main_config(const main_config_t *config)
bool ok = reg_set_dword(reg, "port", config->udp_port)
&& reg_set_dword(reg, "w95_bug", config->w95_bug)
&& reg_set_dword(reg, "fw_except", config->fw_except)
&& reg_set_dword(reg, "log_level", config->log_level);
reg_close(reg);

View File

@ -1,5 +1,5 @@
/* ipxwrapper - Configuration header
* Copyright (C) 2011 Daniel Collins <solemnwarning@solemnwarning.net>
* Copyright (C) 2011-2013 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
@ -30,6 +30,7 @@ typedef struct main_config {
uint16_t udp_port;
bool w95_bug;
bool fw_except;
enum ipx_log_level log_level;
} main_config_t;

255
src/firewall.c Normal file
View File

@ -0,0 +1,255 @@
/* IPXWrapper - Windows Firewall fiddling
* Copyright (C) 2013 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#define COBJMACROS
#define CINTERFACE
#include <windows.h>
#include <objbase.h>
#include <netfw.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "ipxwrapper.h"
/* Define the GUIDs of the relevant COM objects here since the ones in the
* headers are just extern references to libraries that won't exist on older
* machines.
*/
static const CLSID CLSID_NetFwMgr_s = { 0x304CE942, 0x6E39, 0x40D8, { 0x94, 0x3A, 0xB9, 0x13, 0xC4, 0x0C, 0x9C, 0xD4 } };
static const IID IID_INetFwMgr_s = { 0xF7898AF5, 0xCAC4, 0x4632, { 0xA2, 0xEC, 0xDA, 0x06, 0xE5, 0x11, 0x1A, 0xF2 } };
static const CLSID CLSID_NetFwAuthorizedApplication_s = { 0xEC9846B3, 0x2762, 0x4A6B, { 0xA2, 0x14, 0x6A, 0xCB, 0x60, 0x34, 0x62, 0xD2 } };
static const IID IID_INetFwAuthorizedApplication_s = { 0xB5E64FFA, 0xC2C5, 0x444E, { 0xA3, 0x01, 0xFB, 0x5E, 0x00, 0x01, 0x80, 0x50 } };
/* Load IsUserAnAdmin at runtime since it doesn't exist before XP. */
typedef BOOL (*IsUserAnAdmin_t)(void);
static BOOL IsUserAnAdmin(void)
{
BOOL is_admin = TRUE;
HMODULE shell32 = LoadLibrary("shell32.dll");
if(!shell32)
{
return TRUE;
}
IsUserAnAdmin_t sys_IsUserAnAdmin = (IsUserAnAdmin_t)(GetProcAddress(shell32, "IsUserAnAdmin"));
if(sys_IsUserAnAdmin)
{
is_admin = sys_IsUserAnAdmin();
}
FreeLibrary(shell32);
return is_admin;
}
/* Try to get the FileDescription field from an EXE, in any language.
* Returns a BSTR on success, NULL on failure.
*/
static BSTR _get_exe_desc(const wchar_t *path)
{
DWORD vd_size = GetFileVersionInfoSizeW(path, NULL);
if(vd_size == 0)
{
/* Ignore ERROR_RESOURCE_TYPE_NOT_FOUND as it most likely means
* the executable doesn't HAVE any version information.
*/
if(GetLastError() != ERROR_RESOURCE_TYPE_NOT_FOUND)
{
log_printf(LOG_ERROR, "Cannot get version information: %s", w32_error(GetLastError()));
}
return NULL;
}
void *ver_data = malloc(vd_size);
if(!ver_data)
{
log_printf(LOG_ERROR, "Cannot allocate %u bytes for version information!", (unsigned int)(vd_size));
return NULL;
}
BSTR exe_desc = NULL;
if(GetFileVersionInfoW(path, 0, vd_size, ver_data))
{
struct {
WORD wLanguage;
WORD wCodePage;
} *tr_data;
UINT tr_size;
if(VerQueryValueW(ver_data, L"\\VarFileInfo\\Translation", (void**)(&tr_data), &tr_size))
{
for(unsigned int i = 0; i < (tr_size / sizeof(*tr_data)); ++i)
{
/* Integrate the language into the key in hex
* form?
*
* Fuck yeah!
*/
wchar_t key[64];
wsprintfW(key, L"\\StringFileInfo\\%04x%04x\\FileDescription", tr_data[i].wLanguage, tr_data[i].wCodePage);
wchar_t *desc;
UINT desc_size;
if(VerQueryValueW(ver_data, key, (void**)(&desc), &desc_size))
{
if((exe_desc = SysAllocStringLen(desc, desc_size)))
{
break;
}
}
}
}
}
else{
log_printf(LOG_ERROR, "Cannot get version information: %s", w32_error(GetLastError()));
}
free(ver_data);
return exe_desc;
}
/* Fill an instance of INetFwAuthorizedApplication with the path and name of the
* current executable.
*
* Returns true on success, false on failure.
*/
static bool _fill_this_exe(INetFwAuthorizedApplication *this_exe)
{
size_t size = 256;
wchar_t *path = NULL;
do {
size *= 2;
if(!(path = (wchar_t*)(realloc(path, sizeof(wchar_t) * size))))
{
log_printf(LOG_ERROR, "Cannot allocate %u bytes for filename!", (unsigned int)(size));
return false;
}
} while(GetModuleFileNameW(NULL, path, size) == size);
BSTR exe_path = SysAllocString(path);
BSTR exe_desc = _get_exe_desc(path);
bool ok = exe_path
&& (INetFwAuthorizedApplication_put_ProcessImageFileName(this_exe, exe_path) == S_OK)
&& (INetFwAuthorizedApplication_put_Name(this_exe, exe_desc ? exe_desc : exe_path) == S_OK);
SysFreeString(exe_desc);
SysFreeString(exe_path);
free(path);
if(!ok)
{
log_printf(LOG_ERROR, "Unknown error while populating INetFwAuthorizedApplication");
}
return ok;
}
void add_self_to_firewall(void)
{
if(!IsUserAnAdmin())
{
log_printf(LOG_ERROR, "Cannot add firewall exception, not running as an administrator");
return;
}
CoInitialize(NULL);
/* We need to go deeper. */
INetFwMgr *fw_mgr;
HRESULT err = CoCreateInstance(&CLSID_NetFwMgr_s, NULL, CLSCTX_INPROC_SERVER, &IID_INetFwMgr_s, (void**)(&fw_mgr));
if(err == S_OK)
{
INetFwPolicy *fw_policy;
if((err = INetFwMgr_get_LocalPolicy(fw_mgr, &fw_policy)) == S_OK)
{
INetFwProfile *fw_profile;
if((err = INetFwPolicy_get_CurrentProfile(fw_policy, &fw_profile)) == S_OK)
{
INetFwAuthorizedApplications *fw_apps;
if((err = INetFwProfile_get_AuthorizedApplications(fw_profile, &fw_apps)) == S_OK)
{
/* Create an instance of INetFwAuthorizedApplication and
* put the current executable in it.
*/
INetFwAuthorizedApplication *this_exe;
if((err = CoCreateInstance(&CLSID_NetFwAuthorizedApplication_s, NULL, CLSCTX_INPROC_SERVER, &IID_INetFwAuthorizedApplication_s, (void**)(&this_exe))) == S_OK)
{
if(_fill_this_exe(this_exe))
{
/* Add the new INetFwAuthorizedApplication
* to the active profile.
*/
if((err = INetFwAuthorizedApplications_Add(fw_apps, this_exe)) != S_OK)
{
log_printf(LOG_ERROR, "Could not add firewall exception (error %u)", (unsigned int)(err));
}
}
INetFwAuthorizedApplication_Release(this_exe);
}
else{
log_printf(LOG_ERROR, "Could not create INetFwAuthorizedApplication (error %u)", (unsigned int)(err));
}
INetFwAuthorizedApplications_Release(fw_apps);
}
else{
log_printf(LOG_ERROR, "Could not get INetFwAuthorizedApplications object (error %u)", (unsigned int)(err));
}
INetFwProfile_Release(fw_profile);
}
else{
log_printf(LOG_ERROR, "Could not get INetFwProfile object (error %u)", (unsigned int)(err));
}
INetFwPolicy_Release(fw_policy);
}
else{
log_printf(LOG_ERROR, "Could not get INetFwPolicy object (error %u)", (unsigned int)(err));
}
INetFwMgr_Release(fw_mgr);
}
else{
log_printf(LOG_ERROR, "Could not create INetFwMgr object (error %u)", (unsigned int)(err));
}
CoUninitialize();
}

View File

@ -1,5 +1,5 @@
/* IPXWrapper - Configuration tool
* Copyright (C) 2011 Daniel Collins <solemnwarning@solemnwarning.net>
* Copyright (C) 2011-2013 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
@ -40,6 +40,7 @@
#define ID_OPT_W95 22
#define ID_OPT_LOG_DEBUG 25
#define ID_OPT_LOG_TRACE 26
#define ID_OPT_FW_EXCEPT 27
#define ID_OK 31
#define ID_CANCEL 32
@ -103,6 +104,7 @@ static struct {
HWND opt_w95;
HWND opt_log_debug;
HWND opt_log_trace;
HWND opt_fw_except;
HWND ok_btn;
HWND can_btn;
@ -216,7 +218,7 @@ static LRESULT CALLBACK main_wproc(HWND window, UINT msg, WPARAM wp, LPARAM lp)
int lbl_w = get_text_width(windows.nic_net_lbl, "Network number");
int edit_w = get_text_width(windows.nic_node, "000000");
int opt_h = 4 * text_h + edit_h + 16;
int opt_h = 5 * text_h + edit_h + 18;
MoveWindow(windows.opt_group, 0, height - opt_h - btn_h - 12, width, opt_h, TRUE);
@ -228,6 +230,7 @@ static LRESULT CALLBACK main_wproc(HWND window, UINT msg, WPARAM wp, LPARAM lp)
MoveWindow(windows.opt_w95, 10, y += edit_h + 4, width - 20, text_h, TRUE);
MoveWindow(windows.opt_log_debug, 10, y += text_h + 2, width - 20, text_h, TRUE);
MoveWindow(windows.opt_log_trace, 10, y += text_h + 2, width - 20, text_h, TRUE);
MoveWindow(windows.opt_fw_except, 10, y += text_h + 2, width - 20, text_h, TRUE);
/* NIC groupbox */
@ -381,6 +384,7 @@ static bool save_config()
main_config.udp_port = port;
main_config.w95_bug = Button_GetCheck(windows.opt_w95) == BST_CHECKED;
main_config.fw_except = Button_GetCheck(windows.opt_fw_except) == BST_CHECKED;
main_config.log_level = LOG_INFO;
if(Button_GetCheck(windows.opt_log_debug) == BST_CHECKED)
@ -541,10 +545,12 @@ static void init_windows() {
windows.opt_w95 = create_child(windows.opt_group, 0, 0, 0, 0, "BUTTON", "Enable Windows 95 SO_BROADCAST bug", BS_AUTOCHECKBOX | WS_TABSTOP, 0, ID_OPT_W95);
windows.opt_log_debug = create_child(windows.opt_group, 0, 0, 0, 0, "BUTTON", "Log debugging messages", BS_AUTOCHECKBOX | WS_TABSTOP, 0, ID_OPT_LOG_DEBUG);
windows.opt_log_trace = create_child(windows.opt_group, 0, 0, 0, 0, "BUTTON", "Log WinSock API calls", BS_AUTOCHECKBOX | WS_TABSTOP, 0, ID_OPT_LOG_TRACE);
windows.opt_fw_except = create_child(windows.opt_group, 0, 0, 0, 0, "BUTTON", "Automatically create Windows Firewall exceptions", BS_AUTOCHECKBOX | WS_TABSTOP, 0, ID_OPT_FW_EXCEPT);
Button_SetCheck(windows.opt_w95, main_config.w95_bug ? BST_CHECKED : BST_UNCHECKED);
Button_SetCheck(windows.opt_log_debug, main_config.log_level <= LOG_DEBUG ? BST_CHECKED : BST_UNCHECKED);
Button_SetCheck(windows.opt_log_trace, main_config.log_level <= LOG_CALL ? BST_CHECKED : BST_UNCHECKED);
Button_SetCheck(windows.opt_fw_except, main_config.fw_except ? BST_CHECKED : BST_UNCHECKED);
EnableWindow(windows.opt_log_trace, Button_GetCheck(windows.opt_log_debug) == BST_CHECKED);
}

View File

@ -1,5 +1,5 @@
/* ipxwrapper - Library functions
* Copyright (C) 2008 Daniel Collins <solemnwarning@solemnwarning.net>
* Copyright (C) 2008-2013 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
@ -33,6 +33,8 @@
#include "addrcache.h"
#include "addrtable.h"
int _putenv(const char *envstring);
extern const char *version_string;
extern const char *compile_time;
@ -78,6 +80,12 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res)
main_config = get_main_config();
min_log_level = main_config.log_level;
if(main_config.fw_except)
{
log_printf(LOG_INFO, "Adding exception to Windows Firewall");
add_self_to_firewall();
}
addr_cache_init();
ipx_interfaces_init();

View File

@ -1,5 +1,5 @@
/* ipxwrapper - Library header
* Copyright (C) 2008-2011 Daniel Collins <solemnwarning@solemnwarning.net>
* Copyright (C) 2008-2013 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
@ -88,6 +88,8 @@ ipx_socket *get_socket(SOCKET sockfd);
void lock_sockets(void);
void unlock_sockets(void);
void add_self_to_firewall(void);
INT APIENTRY r_EnumProtocolsA(LPINT,LPVOID,LPDWORD);
INT APIENTRY r_EnumProtocolsW(LPINT,LPVOID,LPDWORD);
int PASCAL FAR r_WSARecvEx(SOCKET,char*,int,int*);