msg_del_dns_cfg,
msg_add_nbt_cfg,
msg_del_nbt_cfg,
- msg_flush_neighbors
+ msg_flush_neighbors,
+ msg_add_block_dns,
+ msg_del_block_dns
} message_type_t;
typedef struct {
int error_number;
} ack_message_t;
+typedef struct {
+ message_header_t header;
+ interface_t iface;
+} block_dns_message_t;
+
#endif
if (c->options.block_outside_dns)
{
dmsg (D_LOW, "Blocking outside DNS");
- if (!win_wfp_block_dns(c->c1.tuntap->adapter_index))
+ if (!win_wfp_block_dns(c->c1.tuntap->adapter_index, c->options.msg_channel))
msg (M_FATAL, "Blocking DNS failed!");
}
#endif
#if defined(WIN32)
if (c->options.block_outside_dns)
{
- if (!win_wfp_uninit())
+ if (!win_wfp_uninit(c->options.msg_channel))
msg (M_FATAL, "Uninitialising WFP failed!");
}
#endif
return tmpdir;
}
+static bool
+win_block_dns_service (bool add, int index, const HANDLE pipe)
+{
+ DWORD len;
+ bool ret = false;
+ ack_message_t ack;
+ struct gc_arena gc = gc_new ();
+
+ block_dns_message_t data = {
+ .header = {
+ (add ? msg_add_block_dns : msg_del_block_dns),
+ sizeof (block_dns_message_t),
+ 0 },
+ .iface = { .index = index, .name = "" }
+ };
+
+ if (!WriteFile (pipe, &data, sizeof (data), &len, NULL) ||
+ !ReadFile (pipe, &ack, sizeof (ack), &len, NULL))
+ {
+ msg (M_WARN, "Block_DNS: could not talk to service: %s [%lu]",
+ strerror_win32 (GetLastError (), &gc), GetLastError ());
+ goto out;
+ }
+
+ if (ack.error_number != NO_ERROR)
+ {
+ msg (M_WARN, "Block_DNS: %s block dns filters using service failed: %s [status=0x%x if_index=%d]",
+ (add ? "adding" : "deleting"), strerror_win32 (ack.error_number, &gc),
+ ack.error_number, data.iface.index);
+ goto out;
+ }
+
+ ret = true;
+ msg (M_INFO, "%s outside dns using service succeeded.", (add ? "Blocking" : "Unblocking"));
+out:
+ gc_free (&gc);
+ return ret;
+}
+
static void
block_dns_msg_handler (DWORD err, const char *msg)
{
}
else
{
- msg (M_WARN, "Error in add_block_dns_filters(): %s : %s [status=%lu]",
+ msg (M_WARN, "Error in add_block_dns_filters(): %s : %s [status=0x%lx]",
msg, strerror_win32 (err, &gc), err);
}
}
bool
-win_wfp_block_dns (const NET_IFINDEX index)
+win_wfp_block_dns (const NET_IFINDEX index, const HANDLE msg_channel)
{
WCHAR openvpnpath[MAX_PATH];
bool ret = false;
DWORD status;
+ if (msg_channel)
+ {
+ dmsg (D_LOW, "Using service to add block dns filters");
+ ret = win_block_dns_service (true, index, msg_channel);
+ goto out;
+ }
+
status = GetModuleFileNameW (NULL, openvpnpath, sizeof(openvpnpath));
if (status == 0 || status == sizeof(openvpnpath))
{
}
bool
-win_wfp_uninit()
+win_wfp_uninit(const HANDLE msg_channel)
{
dmsg (D_LOW, "Uninitializing WFP");
- delete_block_dns_filters (m_hEngineHandle);
+ if (msg_channel)
+ {
+ msg (D_LOW, "Using service to delete block dns filters");
+ win_block_dns_service (false, -1, msg_channel);
+ }
+ else
+ {
+ delete_block_dns_filters (m_hEngineHandle);
+ }
return true;
}
/* Convert a string from UTF-8 to UCS-2 */
WCHAR *wide_string (const char* utf8, struct gc_arena *gc);
-bool win_wfp_block_dns(const NET_IFINDEX index);
-bool win_wfp_uninit();
+bool win_wfp_block_dns(const NET_IFINDEX index, const HANDLE msg_channel);
+bool win_wfp_uninit(const HANDLE msg_channel);
#define WIN_XP 0
#define WIN_VISTA 1
openvpnserv.vcxproj.filters
AM_CPPFLAGS = \
- -I$(top_srcdir)/include
+ -I$(top_srcdir)/include -I$(top_srcdir)/src/openvpn
if WIN32
sbin_PROGRAMS = openvpnserv
-municode -D_UNICODE \
-UNTDDI_VERSION -U_WIN32_WINNT \
-D_WIN32_WINNT=_WIN32_WINNT_VISTA
-openvpnserv_LDADD = -ladvapi32 -luserenv -liphlpapi -lshlwapi -lnetapi32 -lws2_32
+openvpnserv_LDADD = -ladvapi32 -luserenv -liphlpapi -lfwpuclnt -lrpcrt4 -lshlwapi -lnetapi32 -lws2_32
endif
openvpnserv_SOURCES = \
automatic.c \
interactive.c \
service.c service.h \
- validate.c validate.h \
+ validate.c validate.h \
+ $(top_srcdir)/src/openvpn/block_dns.c $(top_srcdir)/src/openvpn/block_dns.h \
openvpnserv_resources.rc
#include "openvpn-msg.h"
#include "validate.h"
+#include "block_dns.h"
#define IO_TIMEOUT 2000 /*ms*/
typedef enum {
address,
route,
+ block_dns,
_undo_type_max
} undo_type_t;
typedef list_item_t* undo_lists_t[_undo_type_max];
return err;
}
-
static BOOL
CmpRoute (LPVOID item, LPVOID route)
{
return flush_fn (msg->family, msg->iface.index);
}
+static void
+BlockDNSErrHandler (DWORD err, const char *msg)
+{
+ TCHAR buf[256];
+ LPCTSTR err_str;
+
+ if (!err) return;
+
+ err_str = TEXT("Unknown Win32 Error");
+
+ if (FormatMessage (FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ NULL, err, 0, buf, sizeof (buf), NULL))
+ {
+ err_str = buf;
+ }
+
+#ifdef UNICODE
+ MsgToEventLog (M_ERR, L"%S (status = %lu): %s", msg, err, err_str);
+#else
+ MsgToEventLog (M_ERR, "%s (status = %lu): %s", msg, err, err_str);
+#endif
+
+}
+
+/* Use an always-true match_fn to get the head of the list */
+static BOOL
+CmpEngine (LPVOID item, LPVOID any)
+{
+ return TRUE;
+}
+
+static DWORD
+HandleBlockDNSMessage (const block_dns_message_t *msg, undo_lists_t *lists)
+{
+ DWORD err = 0;
+ HANDLE engine = NULL;
+ LPCWSTR exe_path;
+
+#ifdef UNICODE
+ exe_path = settings.exe_path;
+#else
+ WCHAR wide_path[MAX_PATH];
+ MultiByteToWideChar (CP_UTF8, 0, settings.exe_path, MAX_PATH, wide_path, MAX_PATH);
+ exe_path = wide_path;
+#endif
+
+ if (msg->header.type == msg_add_block_dns)
+ {
+ err = add_block_dns_filters (&engine, msg->iface.index, exe_path, BlockDNSErrHandler);
+ if (!err)
+ err = AddListItem (&(*lists)[block_dns], engine);
+ }
+ else
+ {
+ engine = RemoveListItem (&(*lists)[block_dns], CmpEngine, NULL);
+ if (engine)
+ {
+ err = delete_block_dns_filters (engine);
+ engine = NULL;
+ }
+ else
+ MsgToEventLog (M_ERR, TEXT("No previous block DNS filters to delete"));
+ }
+
+ if (err && engine)
+ {
+ delete_block_dns_filters (engine);
+ }
+
+ return err;
+}
static VOID
HandleMessage (HANDLE pipe, DWORD bytes, DWORD count, LPHANDLE events, undo_lists_t *lists)
address_message_t address;
route_message_t route;
flush_neighbors_message_t flush_neighbors;
+ block_dns_message_t block_dns;
} msg;
ack_message_t ack = {
.header = {
ack.error_number = HandleFlushNeighborsMessage (&msg.flush_neighbors);
break;
+ case msg_add_block_dns:
+ case msg_del_block_dns:
+ if (msg.header.size == sizeof (msg.block_dns))
+ ack.error_number = HandleBlockDNSMessage (&msg.block_dns, lists);
+ break;
+
default:
ack.error_number = ERROR_MESSAGE_TYPE;
+ MsgToEventLog (MSG_FLAGS_ERROR, TEXT("Unknown message type %d"), msg.header.type);
break;
}
case route:
DeleteRoute (item->data);
break;
+
+ case block_dns:
+ delete_block_dns_filters (item->data);
+ item->data = NULL;
+ break;
}
/* Remove from the list and free memory */