[CI SKIP] Added kotlin 😢
Some checks failed
TVPN Actions Workflow / build (push) Has been cancelled

This commit is contained in:
2024-10-28 18:15:23 -04:00
parent d5e1142bce
commit dd8970758a
29 changed files with 557 additions and 236 deletions

View File

@@ -15,9 +15,11 @@ set(JNI_INCLUDE_DIR2 "${JAVA_HOME}/include/win32")
include_directories(${JNI_INCLUDE_DIR} ${JNI_INCLUDE_DIR2})
# Add the source file that includes your JNI C wrapper code
add_library(wireguard_wrapper SHARED wireguard_wrapper.c)
add_library(wireguard_wrapper SHARED wireguard_wrapper.c
example.c)
target_link_libraries(wireguard_wrapper PRIVATE Rpcrt4)
#target_link_libraries(wireguard_wrapper PRIVATE Rpcrt4)
target_link_libraries(wireguard_wrapper ws2_32 rpcrt4)
# Optionally, you can specify output directory for the compiled library
set_target_properties(wireguard_wrapper PROPERTIES

4
src/main/cpp/build.ps1 Normal file
View File

@@ -0,0 +1,4 @@
Get-ChildItem -Path build -Recurse | Remove-Item -force -recurse
if (Test-Path -Path .\build) { Remove-Item -Path .\build -Recurse -Force }
cmake -DCMAKE_BUILD_TYPE=Release -G "CodeBlocks - MinGW Makefiles" -S . -B .\build
cmake --build .\build --target wireguard_wrapper -- -j 14

View File

@@ -276,10 +276,19 @@ int __cdecl main(void)
WIREGUARD_INTERFACE Interface;
WIREGUARD_PEER DemoServer;
WIREGUARD_ALLOWED_IP AllV4;
} Config = { .Interface = { .Flags = WIREGUARD_INTERFACE_HAS_PRIVATE_KEY, .PeersCount = 1 },
.DemoServer = { .Flags = WIREGUARD_PEER_HAS_PUBLIC_KEY | WIREGUARD_PEER_HAS_ENDPOINT,
.AllowedIPsCount = 1 },
.AllV4 = { .AddressFamily = AF_INET } };
} Config = {
.Interface = {
.Flags = WIREGUARD_INTERFACE_HAS_PRIVATE_KEY,
.PeersCount = 1
},
.DemoServer = {
.Flags = WIREGUARD_PEER_HAS_PUBLIC_KEY | WIREGUARD_PEER_HAS_ENDPOINT,
.AllowedIPsCount = 1
},
.AllV4 = {
.AddressFamily = AF_INET
}
};
Log(WIREGUARD_LOG_INFO, L"Generating keypair");
BYTE PublicKey[WIREGUARD_KEY_LENGTH];

View File

@@ -1,17 +1,23 @@
#include <jni.h>
#include <rpc.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <winsock2.h>
#include <windows.h>
#include "wireguard.h"
#include <string.h>
#include <ws2tcpip.h>
#include "tech_nevets_tvpn_wg_WireGuardJNI.h"
#pragma comment(lib, "Rpcrt4.lib")
const wchar_t *APP_DIR = L"C:\\Program Files\\TVPN\\";
typedef struct {
WIREGUARD_INTERFACE Interface;
WIREGUARD_PEER Peer;
WIREGUARD_ALLOWED_IP AllowedIP;
} Config;
static WIREGUARD_CREATE_ADAPTER_FUNC *WireGuardCreateAdapter;
static WIREGUARD_OPEN_ADAPTER_FUNC *WireGuardOpenAdapter;
static WIREGUARD_CLOSE_ADAPTER_FUNC *WireGuardCloseAdapter;
@@ -26,12 +32,12 @@ static WIREGUARD_GET_CONFIGURATION_FUNC *WireGuardGetConfiguration;
static WIREGUARD_SET_CONFIGURATION_FUNC *WireGuardSetConfiguration;
static HMODULE InitializeWireGuardNT(void) {
HMODULE WireGuardDll = LoadLibraryExW(
L"wireguard.dll",
NULL,
LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32
);
if (!WireGuardDll) return NULL;
printf("[C] Starting InitializeWireGuardNT!\n");
HMODULE WireGuardDll = LoadLibraryW(L"wireguard.dll");
if (!WireGuardDll) {
printf("[C] Error loading wireguard.dll\n");
return NULL;
}
#define X(Name) ((*(FARPROC *)&Name = GetProcAddress(WireGuardDll, #Name)) == NULL)
if (X(WireGuardCreateAdapter) || X(WireGuardOpenAdapter) || X(WireGuardCloseAdapter) ||
X(WireGuardGetAdapterLUID) || X(WireGuardGetRunningDriverVersion) || X(WireGuardDeleteDriver) ||
@@ -40,14 +46,16 @@ static HMODULE InitializeWireGuardNT(void) {
#undef X
{
DWORD LastError = GetLastError();
fprintf(stderr, "[C] Failed to load wireguard.dll, error code: %lu\n", LastError);
FreeLibrary(WireGuardDll);
SetLastError(LastError);
return NULL;
}
printf("[C] Finished Init WG.dll\n");
return WireGuardDll;
}
GUID generateGUID() {
static GUID generateGUID(void) {
UUID uuid;
RPC_STATUS status = UuidCreate(&uuid);
@@ -115,7 +123,7 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_installTunnel(JNIEn
const jchar *rawStr = (*env)->GetStringChars(env, tunnelName, 0); //TODO mem cleanup
LPWSTR tnlName = (LPWSTR) rawStr;
wprintf(L"[C] Tunnel Name: %ls", tnlName);
wprintf(L"[C] Tunnel Name: %ls\n", tnlName);
wchar_t *servicePrefix = L"WireGuardTunnel$";
wchar_t *serviceName = malloc(sizeof(wchar_t) * (wcslen(servicePrefix) + wcslen(tnlName) + 1)); //TODO mem cleanup
@@ -244,4 +252,115 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_removeTunnel(JNIEnv
free(tnlName);
return 0;
}
JNIEXPORT jlong JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_getWGVersion(JNIEnv *env, jobject obj) {
WSADATA WsaData;
if (WSAStartup(MAKEWORD(2, 2), &WsaData)) {
fprintf(stderr, "[C] Failed to initialize Winsock\n");
return 0;
}
HMODULE WireGuardDLL = InitializeWireGuardNT();
printf("[C] Post Init WGNT\n");
if (WireGuardDLL == NULL) {
fprintf(stderr, "[C] Failed to initialize WireGuardNT library\n");
return 1;
}
DWORD Version = WireGuardGetRunningDriverVersion();
printf("[C] Before Printed version\n");
//printf("[C] WG Ver: %lu\n", Version);
wprintf(L"WireGuardNT v%u.%u loaded", (Version >> 16) & 0xff, (Version >> 0) & 0xff);
FreeLibrary(WireGuardDLL);
return Version;
}
JNIEXPORT jlong JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_parseConfig(JNIEnv *env, jobject obj, jobject conf) {
// Allocate memory for Config struct
Config *config = (Config *)malloc(sizeof(Config));
if (config == NULL) {
return 0; // Memory allocation failed
}
// Get WGConf class and fields
jclass wgConfClass = (*env)->GetObjectClass(env, conf);
// Step 1: Fill Interface fields
jfieldID ifaceFieldID = (*env)->GetFieldID(env, wgConfClass, "iface", "Ltech/nevets/tvpn/wg/WGConf$Interface;");
jobject ifaceObj = (*env)->GetObjectField(env, conf, ifaceFieldID);
jclass ifaceClass = (*env)->GetObjectClass(env, ifaceObj);
config->Interface.Flags = (WIREGUARD_INTERFACE_FLAG)(*env)->GetIntField(env, ifaceObj, (*env)->GetFieldID(env, ifaceClass, "flags", "I"));
config->Interface.ListenPort = (WORD)(*env)->GetIntField(env, ifaceObj, (*env)->GetFieldID(env, ifaceClass, "port", "I"));
// Get and copy privateKey
jbyteArray privateKeyArray = (jbyteArray)(*env)->GetObjectField(env, ifaceObj, (*env)->GetFieldID(env, ifaceClass, "privateKey", "[B"));
(*env)->GetByteArrayRegion(env, privateKeyArray, 0, WIREGUARD_KEY_LENGTH, (jbyte *)config->Interface.PrivateKey);
// Get and copy publicKey
jbyteArray publicKeyArray = (jbyteArray)(*env)->GetObjectField(env, ifaceObj, (*env)->GetFieldID(env, ifaceClass, "publicKey", "[B"));
(*env)->GetByteArrayRegion(env, publicKeyArray, 0, WIREGUARD_KEY_LENGTH, (jbyte *)config->Interface.PublicKey);
config->Interface.PeersCount = (DWORD)(*env)->GetIntField(env, ifaceObj, (*env)->GetFieldID(env, ifaceClass, "peersCount", "I"));
// Step 2: Fill Peer fields
jfieldID peerFieldID = (*env)->GetFieldID(env, wgConfClass, "peer", "Ltech/nevets/tvpn/wg/WGConf$Peer;");
jobject peerObj = (*env)->GetObjectField(env, conf, peerFieldID);
jclass peerClass = (*env)->GetObjectClass(env, peerObj);
config->Peer.Flags = (WIREGUARD_PEER_FLAG)(*env)->GetIntField(env, peerObj, (*env)->GetFieldID(env, peerClass, "flags", "I"));
config->Peer.Reserved = (DWORD)(*env)->GetIntField(env, peerObj, (*env)->GetFieldID(env, peerClass, "reserved", "I"));
// Get and copy publicKey
jbyteArray peerPublicKeyArray = (jbyteArray)(*env)->GetObjectField(env, peerObj, (*env)->GetFieldID(env, peerClass, "publicKey", "[B"));
(*env)->GetByteArrayRegion(env, peerPublicKeyArray, 0, WIREGUARD_KEY_LENGTH, (jbyte *)config->Peer.PublicKey);
// Get and copy presharedKey
jbyteArray presharedKeyArray = (jbyteArray)(*env)->GetObjectField(env, peerObj, (*env)->GetFieldID(env, peerClass, "presharedKey", "[B"));
(*env)->GetByteArrayRegion(env, presharedKeyArray, 0, WIREGUARD_KEY_LENGTH, (jbyte *)config->Peer.PresharedKey);
config->Peer.PersistentKeepalive = (WORD)(*env)->GetIntField(env, peerObj, (*env)->GetFieldID(env, peerClass, "persistentKeepalive", "I"));
config->Peer.AllowedIPsCount = (DWORD)(*env)->GetIntField(env, peerObj, (*env)->GetFieldID(env, peerClass, "allowedIPsCount", "I"));
// Endpoint is more complex: requires parsing from byte array and setting `SOCKADDR_INET`
jbyteArray endpointArray = (jbyteArray)(*env)->GetObjectField(env, peerObj, (*env)->GetFieldID(env, peerClass, "endpoint", "[B"));
jsize endpointLen = (*env)->GetArrayLength(env, endpointArray);
jbyte *endpointBytes = (*env)->GetByteArrayElements(env, endpointArray, NULL);
if (endpointLen == sizeof(SOCKADDR_INET)) {
memcpy(&config->Peer.Endpoint, endpointBytes, sizeof(SOCKADDR_INET));
}
(*env)->ReleaseByteArrayElements(env, endpointArray, endpointBytes, 0);
// Step 3: Fill AllowedIP fields
jfieldID allowedIPFieldID = (*env)->GetFieldID(env, wgConfClass, "allowedIP", "Ltech/nevets/tvpn/wg/WGConf$AllowedIP;");
jobject allowedIPObj = (*env)->GetObjectField(env, conf, allowedIPFieldID);
jclass allowedIPClass = (*env)->GetObjectClass(env, allowedIPObj);
jstring addressStr = (jstring)(*env)->GetObjectField(env, allowedIPObj, (*env)->GetFieldID(env, allowedIPClass, "address", "Ljava/lang/String;"));
const char *addressChars = (*env)->GetStringUTFChars(env, addressStr, NULL);
// Assuming address parsing logic here, converting to either IN_ADDR or IN6_ADDR based on `addressFamily`
jstring familyStr = (jstring)(*env)->GetObjectField(env, allowedIPObj, (*env)->GetFieldID(env, allowedIPClass, "addressFamily", "Ljava/lang/String;"));
const char *familyChars = (*env)->GetStringUTFChars(env, familyStr, NULL);
if (strcmp(familyChars, "AF_INET") == 0) {
config->AllowedIP.AddressFamily = AF_INET;
inet_pton(AF_INET, addressChars, &config->AllowedIP.Address.V4);
} else if (strcmp(familyChars, "AF_INET6") == 0) {
config->AllowedIP.AddressFamily = AF_INET6;
inet_pton(AF_INET6, addressChars, &config->AllowedIP.Address.V6);
}
(*env)->ReleaseStringUTFChars(env, familyStr, familyChars);
(*env)->ReleaseStringUTFChars(env, addressStr, addressChars);
config->AllowedIP.Cidr = (BYTE)(*env)->GetByteField(env, allowedIPObj, (*env)->GetFieldID(env, allowedIPClass, "cidr", "B"));
// Return the pointer to Config struct as jlong
return (jlong)(uintptr_t)config;
}