]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
wintun: Plugin implementing Wintun TUN device wintun
authorAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 2 Feb 2023 19:39:38 +0000 (20:39 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 5 Feb 2023 13:18:12 +0000 (14:18 +0100)
configure.ac
src/libcharon/plugins/kernel_libipsec/kernel_libipsec_router.c
src/libstrongswan/Makefile.am
src/libstrongswan/plugins/wintun/Makefile.am [new file with mode: 0644]
src/libstrongswan/plugins/wintun/wintun_device.c [new file with mode: 0644]
src/libstrongswan/plugins/wintun/wintun_device.h [new file with mode: 0644]
src/libstrongswan/plugins/wintun/wintun_plugin.c [new file with mode: 0644]
src/libstrongswan/plugins/wintun/wintun_plugin.h [new file with mode: 0644]

index 7bca05a83273e8242857160a6a5a6623777709ac..b27146176ec8ebc311faa3934485c3acf69fb44b 100644 (file)
@@ -226,6 +226,7 @@ ARG_ENABL_SET([xauth-eap],      [enable XAuth backend using EAP methods to verif
 ARG_ENABL_SET([xauth-pam],      [enable XAuth backend using PAM to verify passwords.])
 ARG_ENABL_SET([xauth-noauth],   [enable XAuth pseudo-backend that does not actually verify or even request any credentials.])
 # kernel interfaces / sockets
+ARG_ENABL_SET([wintun],         [enables the Windows TUN device plugin.])
 ARG_DISBL_SET([kernel-netlink], [disable the netlink kernel interface.])
 ARG_ENABL_SET([kernel-pfkey],   [enable the PF_KEY kernel interface.])
 ARG_ENABL_SET([kernel-pfroute], [enable the PF_ROUTE kernel interface.])
@@ -1587,6 +1588,7 @@ ADD_PLUGIN([winhttp],              [s charon pki scripts])
 ADD_PLUGIN([soup],                 [s charon pki scripts nm cmd])
 ADD_PLUGIN([mysql],                [s charon pool manager medsrv attest])
 ADD_PLUGIN([sqlite],               [s charon pool manager medsrv attest])
+ADD_PLUGIN([wintun],               [s charon])
 ADD_PLUGIN([attr],                 [c charon])
 ADD_PLUGIN([attr-sql],             [c charon])
 ADD_PLUGIN([load-tester],          [c charon])
@@ -1750,6 +1752,7 @@ AM_CONDITIONAL(USE_NTRU, test x$ntru = xtrue)
 AM_CONDITIONAL(USE_NEWHOPE, test x$newhope = xtrue)
 AM_CONDITIONAL(USE_BLISS, test x$bliss = xtrue)
 AM_CONDITIONAL(USE_DRBG, test x$drbg = xtrue)
+AM_CONDITIONAL(USE_WINTUN, test x$wintun = xtrue)
 
 #  charon plugins
 # ----------------
@@ -2034,6 +2037,7 @@ AC_CONFIG_FILES([
        src/libstrongswan/plugins/newhope/Makefile
        src/libstrongswan/plugins/newhope/tests/Makefile
        src/libstrongswan/plugins/test_vectors/Makefile
+       src/libstrongswan/plugins/wintun/Makefile
        src/libstrongswan/tests/Makefile
        src/libipsec/Makefile
        src/libipsec/tests/Makefile
index 884616345f8a05052226a5fa9e11f7c2523faf56..476eb2bc7992de10e3dee55ad93bc4a11a0348ac 100644 (file)
@@ -307,6 +307,7 @@ METHOD(kernel_libipsec_router_t, destroy, void,
        free(this);
 }
 
+#ifndef WIN32
 /**
  * Set O_NONBLOCK on the given socket.
  */
@@ -315,6 +316,7 @@ static bool set_nonblock(int socket)
        int flags = fcntl(socket, F_GETFL);
        return flags != -1 && fcntl(socket, F_SETFL, flags | O_NONBLOCK) != -1;
 }
+#endif
 
 /*
  * See header file
@@ -322,6 +324,9 @@ static bool set_nonblock(int socket)
 kernel_libipsec_router_t *kernel_libipsec_router_create()
 {
        private_kernel_libipsec_router_t *this;
+#ifdef WIN32
+       u_long on = 1;
+#endif
 
        INIT(this,
                .public = {
@@ -336,8 +341,13 @@ kernel_libipsec_router_t *kernel_libipsec_router_create()
                }
        );
 
+#ifdef WIN32
+       if (socketpair(AF_INET, SOCK_STREAM, 0, this->notify) != 0 ||
+               ioctlsocket(this->notify[0], FIONBIO, &on) != 0)
+#else /* !WIN32 */
        if (pipe(this->notify) != 0 ||
                !set_nonblock(this->notify[0]) || !set_nonblock(this->notify[1]))
+#endif /* !WIN332 */
        {
                DBG1(DBG_KNL, "creating notify pipe for kernel-libipsec router failed");
                free(this);
index b3e4f777d798c0da8080e22aeb05b50c7af5bfb4..f3a9c3e0fa2ce2ab4117d1d861cfef68085c726d 100644 (file)
@@ -697,6 +697,13 @@ if MONOLITHIC
 endif
 endif
 
+if USE_WINTUN
+  SUBDIRS += plugins/wintun
+if MONOLITHIC
+  libstrongswan_la_LIBADD += plugins/wintun/libstrongswan-wintun.la
+endif
+endif
+
 if MONOLITHIC
   SUBDIRS += .
 endif
diff --git a/src/libstrongswan/plugins/wintun/Makefile.am b/src/libstrongswan/plugins/wintun/Makefile.am
new file mode 100644 (file)
index 0000000..2a80d01
--- /dev/null
@@ -0,0 +1,19 @@
+AM_CPPFLAGS = \
+       -I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = \
+       $(PLUGIN_CFLAGS)
+
+noinst_LTLIBRARIES =
+if MONOLITHIC
+noinst_LTLIBRARIES += libstrongswan-wintun.la
+else
+plugin_LTLIBRARIES = libstrongswan-wintun.la
+endif
+
+libstrongswan_wintun_la_SOURCES = \
+       wintun_plugin.h wintun_plugin.c \
+       wintun_device.h wintun_device.c
+
+libstrongswan_wintun_la_LDFLAGS = -module -avoid-version
+
diff --git a/src/libstrongswan/plugins/wintun/wintun_device.c b/src/libstrongswan/plugins/wintun/wintun_device.c
new file mode 100644 (file)
index 0000000..8b35fd1
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2023 Andreas Steffen
+ *
+ * Copyright (C) secunet Security Networks AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifdef WIN32
+#include <wintun.h>
+#endif
+
+#include "wintun_device.h"
+
+#include <utils/debug.h>
+
+#ifndef WIN32
+
+wintun_device_t *wintun_device_create(const char *name_tmpl)
+{
+       DBG1(DBG_LIB, "Wintun devices not supported");
+       return NULL;
+}
+
+bool wintun_library_init()
+{
+       DBG1(DBG_LIB, "Wintun library not supported");
+       return TRUE;
+}
+
+void wintun_library_deinit()
+{
+}
+
+#else /* WIN32 */
+
+/**
+  * Functions offered by the Wintun dynamic library
+  */
+static WINTUN_CREATE_ADAPTER_FUNC *WintunCreateAdapter;
+static WINTUN_CLOSE_ADAPTER_FUNC *WintunCloseAdapter;
+static WINTUN_OPEN_ADAPTER_FUNC *WintunOpenAdapter;
+static WINTUN_GET_ADAPTER_LUID_FUNC *WintunGetAdapterLUID;
+static WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC *WintunGetRunningDriverVersion;
+static WINTUN_DELETE_DRIVER_FUNC *WintunDeleteDriver;
+static WINTUN_SET_LOGGER_FUNC *WintunSetLogger;
+static WINTUN_START_SESSION_FUNC *WintunStartSession;
+static WINTUN_END_SESSION_FUNC *WintunEndSession;
+static WINTUN_GET_READ_WAIT_EVENT_FUNC *WintunGetReadWaitEvent;
+static WINTUN_RECEIVE_PACKET_FUNC *WintunReceivePacket;
+static WINTUN_RELEASE_RECEIVE_PACKET_FUNC *WintunReleaseReceivePacket;
+static WINTUN_ALLOCATE_SEND_PACKET_FUNC *WintunAllocateSendPacket;
+static WINTUN_SEND_PACKET_FUNC *WintunSendPacket;
+
+static HMODULE Wintun;
+
+#define IFNAMSIZ         16
+#define TUN_DEFAULT_MTU  1500
+
+typedef struct private_wintun_device_t private_wintun_device_t;
+
+struct private_wintun_device_t {
+
+       /**
+        * Public interface
+        */
+       wintun_device_t public;
+
+       /**
+        * The Wintun device's file descriptor
+        */
+       int tunfd;
+
+       /**
+        * Name of the Wintun device
+        */
+       char if_name[IFNAMSIZ];
+
+       /**
+        * The current MTU
+        */
+       int mtu;
+
+       /**
+        * Associated address
+        */
+       host_t *address;
+
+       /**
+        * Netmask for address
+        */
+       uint8_t netmask;
+
+       /*
+        * Wintun adapter handle
+        */
+    WINTUN_ADAPTER_HANDLE Adapter;
+
+};
+
+METHOD(tun_device_t, set_address, bool,
+       private_wintun_device_t *this, host_t *addr, uint8_t netmask)
+{
+       this->address = addr->clone(addr);
+       this->netmask = netmask;
+
+       return TRUE;
+}
+
+METHOD(tun_device_t, get_address, host_t*,
+       private_wintun_device_t *this, uint8_t *netmask)
+{
+       if (netmask && this->address)
+       {
+               *netmask = this->netmask;
+       }
+       return this->address;
+}
+
+METHOD(tun_device_t, up, bool,
+       private_wintun_device_t *this)
+{
+       return TRUE;
+}
+
+METHOD(tun_device_t, set_mtu, bool,
+       private_wintun_device_t *this, int mtu)
+{
+       this->mtu = mtu;
+
+       return TRUE;
+}
+
+METHOD(tun_device_t, get_mtu, int,
+       private_wintun_device_t *this)
+{
+       return this->mtu;
+}
+
+METHOD(tun_device_t, get_name, char*,
+       private_wintun_device_t *this)
+{
+       return this->if_name;
+}
+
+METHOD(tun_device_t, get_fd, int,
+       private_wintun_device_t *this)
+{
+       return this->tunfd;
+}
+
+METHOD(tun_device_t, write_packet, bool,
+       private_wintun_device_t *this, chunk_t packet)
+{
+       return TRUE;
+}
+
+METHOD(tun_device_t, read_packet, bool,
+       private_wintun_device_t *this, chunk_t *packet)
+{
+       return TRUE;
+}
+
+METHOD(tun_device_t, destroy, void,
+       private_wintun_device_t *this)
+{
+       WintunCloseAdapter(this->Adapter);
+       free(this);
+}
+
+/**
+ * Initialize the Windows TUN device
+ */
+static bool init_wintun(private_wintun_device_t *this, const char *name_tmpl)
+{
+       DWORD Version;
+       GUID Guid;
+
+       Guid = { 0xdeadbabe, 0xcafe, 0xbeef, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef } };
+       this->Adapter = WintunCreateAdapter(L"strongSwan", L"Wintun", &Guid);
+       if (!Adapter)
+       {
+               DBG1(DBG_LIB,"could not create Wintun adapter");
+               return FALSE;
+       }
+       this->ifname = "strongSwan";
+       Version = WintunGetRunningDriverVersion();
+       DBG1(DBG_LIB, "Wintun adapter v%u.%u loaded",
+               (Version >> 16) & 0xff, (Version >> 0) & 0xff);
+    return TRUE;
+}
+
+/*
+ * Described in header
+ */
+wintun_device_t *wintun_device_create(const char *name_tmpl)
+{
+       private_wintun_device_t *this;
+
+       INIT(this,
+               .public = {
+                       .tun = {
+                               .read_packet = _read_packet,
+                               .write_packet = _write_packet,
+                               .get_mtu = _get_mtu,
+                               .set_mtu = _set_mtu,
+                               .get_name = _get_name,
+                               .get_fd = _get_fd,
+                               .set_address = _set_address,
+                               .get_address = _get_address,
+                               .up = _up,
+                               .destroy = _destroy,
+                       },
+               },
+       );
+
+       if (!init_wintun(this, name_tmpl))
+       {
+               free(this);
+               return NULL;
+       }
+       DBG1(DBG_LIB, "created Wintun device: %s", this->if_name);
+
+       return &this->public;
+}
+
+/*
+ * Described in header
+ */
+bool wintun_library_init()
+{
+       Wintun = LoadLibraryExW(L"wintun.dll", NULL,
+                               LOAD_LIBRARY_SEARCH_APPLICATION_DIR |
+                               LOAD_LIBRARY_SEARCH_SYSTEM32);
+       if (!Wintun)
+       {
+               DBG1(DBG_LIB, "failed to load Wintun library");
+               return FALSE;
+       }
+
+#define X(Name) ((*(FARPROC *)&Name = GetProcAddress(Wintun, #Name)) == NULL)
+       if (X(WintunCreateAdapter)           || X(WintunCloseAdapter)         ||
+               X(WintunOpenAdapter)             || X(WintunGetAdapterLUID)       ||
+               X(WintunGetRunningDriverVersion) || X(WintunDeleteDriver)         ||
+               X(WintunSetLogger)               || X(WintunStartSession)         ||
+               X(WintunEndSession)              || X(WintunGetReadWaitEvent)     ||
+               X(WintunReceivePacket)           || X(WintunReleaseReceivePacket) ||
+               X(WintunAllocateSendPacket)      || X(WintunSendPacket))
+#undef X
+       {
+               FreeLibrary(Wintun);
+               DBG1(DBG_LIB, "failed to initialize Wintun library");
+               return FALSE;
+       }
+       DBG1(DBG_LIB, "Wintun library loaded and initialized");
+       return TRUE;
+}
+
+/*
+ * Described in header
+ */
+void wintun_library_deinit()
+{
+       FreeLibrary(Wintun);
+}
+
+#endif /* WIN32 */
diff --git a/src/libstrongswan/plugins/wintun/wintun_device.h b/src/libstrongswan/plugins/wintun/wintun_device.h
new file mode 100644 (file)
index 0000000..871c5b4
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 Andreas Steffen
+ *
+ * Copyright (C) secunet Security Networks AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup wintun_device wintun_device
+ * @{ @ingroup wintun_p
+ */
+
+#ifndef WINTUN_DEVICE_H_
+#define WINTUN_DEVICE_H_
+
+#include <networking/tun_device.h>
+
+typedef struct wintun_device_t wintun_device_t;
+
+/**
+ * Windows TUN device implementation
+  */
+struct wintun_device_t {
+
+       /**
+        * Generic tun_device_t interface.
+        */
+       tun_device_t tun;
+};
+
+/**
+ * Create a Windows TUN device using the given name template.
+ *
+ * @param name_tmpl         name template, defaults to "tun%d" if not given
+ * @return                  Windows TUN device
+ */
+wintun_device_t *wintun_device_create(const char *name_tmpl);
+
+/**
+ * Initialize wintun library.
+ *
+ * @return              FALSE if library initialization failed
+ */
+bool wintun_library_init();
+
+/**
+ * Deinitialize wintun library.
+ */
+void wintun_library_deinit();
+
+#endif /** WINTUN_DEVICE_H_ @}*/
diff --git a/src/libstrongswan/plugins/wintun/wintun_plugin.c b/src/libstrongswan/plugins/wintun/wintun_plugin.c
new file mode 100644 (file)
index 0000000..479a885
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2023 Andreas Steffen
+ *
+ * Copyright (C) secunet Security Networks AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#include "wintun_plugin.h"
+#include "wintun_device.h"
+
+#include <library.h>
+
+typedef struct private_wintun_plugin_t private_wintun_plugin_t;
+
+/**
+ * Private data of a wintun_plugin_t object.
+ */
+struct private_wintun_plugin_t {
+
+       /**
+        * Public interface.
+        */
+       wintun_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+       private_wintun_plugin_t *this)
+{
+       return "wintun";
+}
+
+METHOD(plugin_t, get_features, int,
+       private_wintun_plugin_t *this, plugin_feature_t *features[])
+{
+       static plugin_feature_t f[] = {
+               PLUGIN_REGISTER(TUN_DEVICE, wintun_device_create),
+                       PLUGIN_PROVIDE(TUN_DEVICE),
+       };
+       *features = f;
+       return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+       private_wintun_plugin_t *this)
+{
+       wintun_library_deinit();
+       free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *wintun_plugin_create(void)
+{
+       private_wintun_plugin_t *this;
+
+       if (!wintun_library_init())
+       {
+               return NULL;
+       }
+
+       INIT(this,
+               .public = {
+                       .plugin = {
+                               .get_name = _get_name,
+                               .get_features = _get_features,
+                               .destroy = _destroy,
+                       },
+               },
+       );
+
+       return &this->public.plugin;
+}
+
diff --git a/src/libstrongswan/plugins/wintun/wintun_plugin.h b/src/libstrongswan/plugins/wintun/wintun_plugin.h
new file mode 100644 (file)
index 0000000..ea693fc
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 Andreas Steffen
+ *
+ * Copyright (C) secunet Security Networks AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup wintun_p wintun
+ * @ingroup plugins
+ *
+ * @defgroup wintun_plugin wintun_plugin
+ * @{ @ingroup wintun_p
+ */
+
+#ifndef WINTUN_PLUGIN_H_
+#define WINTUN_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct wintun_plugin_t wintun_plugin_t;
+
+/**
+ * Plugin providing a Windows TUN device
+ */
+struct wintun_plugin_t {
+
+       /**
+        * Implements plugin interface.
+        */
+       plugin_t plugin;
+};
+
+#endif /** WINTUN_PLUGIN_H_ @}*/