This commit is contained in:
		
							parent
							
								
									8c484f9c23
								
							
						
					
					
						commit
						3c5ffa744e
					
				
							
								
								
									
										54
									
								
								.gitea/workflows/build.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								.gitea/workflows/build.yml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
			
		||||
name: TVPN Actions Workflow
 | 
			
		||||
run-name: Deploy to ${{ inputs.deploy_target }} by ${{ gitea.actor }}
 | 
			
		||||
on: [push]
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  build:
 | 
			
		||||
    runs-on: windows-10
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      #- name: Setup JDK 21
 | 
			
		||||
      #  uses: actions-setup-java@v4.4.0
 | 
			
		||||
      #  with:
 | 
			
		||||
      #    java-version: 21
 | 
			
		||||
      #    distribution: 'temurin'
 | 
			
		||||
      - name: Test Java
 | 
			
		||||
        run: java --version
 | 
			
		||||
      - name: Configure Git
 | 
			
		||||
        run: |
 | 
			
		||||
          git config --global user.email "git@nevets.tech"
 | 
			
		||||
          git config --global user.name "Gitea Actions"
 | 
			
		||||
      - name: Build TVPN Jar
 | 
			
		||||
        run: .\gradlew.bat clean shadowJar createExe
 | 
			
		||||
      - name: Copy Header to C Dir
 | 
			
		||||
        run: |
 | 
			
		||||
          cp build/generated/sources/headers/java/main/tech_nevets_tvpn_wg_WireGuardJNI.h src/main/cpp/
 | 
			
		||||
      - name: Build DLL
 | 
			
		||||
        run: |
 | 
			
		||||
          cmake -DCMAKE_BUILD_TYPE=Release -G "CodeBlocks - MinGW Makefiles" -S ./src/main/cpp -B ./src/main/cpp/build
 | 
			
		||||
          cmake --build ./src/main/cpp/build --target wireguard_wrapper -- -j 14
 | 
			
		||||
      #  uses: actions/cmake-action@v2.0.0
 | 
			
		||||
      #  with:
 | 
			
		||||
      #   source-dir: src/main/cpp
 | 
			
		||||
      #    output-dir: src/main/cpp/build
 | 
			
		||||
      - name: Prepare artifacts
 | 
			
		||||
        run: |
 | 
			
		||||
          Get-ChildItem -Path artifacts -Recurse | Remove-Item -force -recurse
 | 
			
		||||
          if (Test-Path -Path .\artifacts) { Remove-Item -Path .\artifacts -Recurse -Force }
 | 
			
		||||
          $version = (Select-String -Path "build.gradle" -Pattern "^\s*version\s*=\s*'([^']+)'" | ForEach-Object { $_.Matches[0].Groups[1].Value })
 | 
			
		||||
          echo Version: $version
 | 
			
		||||
          New-Item -Path "artifacts" -ItemType Directory
 | 
			
		||||
          Copy-Item -Path "./build/libs/TVPN-$version-all.jar" -Destination "./artifacts/TVPN-$version.jar" -Verbose
 | 
			
		||||
          Copy-Item -Path "./build/launch4j/TVPN.exe" -Destination "./artifacts/TVPN.exe" -Verbose
 | 
			
		||||
          Copy-Item -Path "./src/main/cpp/build/libwireguard_wrapper.dll" -Destination "./artifacts/libwireguard_wrapper.dll" -Verbose
 | 
			
		||||
          Copy-Item -Path "./libs/tunnel.dll" -Destination "./artifacts/tunnel.dll" -Verbose
 | 
			
		||||
          Copy-Item -Path "./libs/wireguard.dll" -Destination "./artifacts/wireguard.dll" -Verbose
 | 
			
		||||
      - name: Create Installer
 | 
			
		||||
        run: |
 | 
			
		||||
          git clone https://git.nevets.tech/Steven/TVPN-jre.git jre
 | 
			
		||||
          ISCC /DMyAppVersion=$version "./installer-script.iss"
 | 
			
		||||
      - name: Upload artifacts
 | 
			
		||||
        uses: actions/upload-artifact@v3
 | 
			
		||||
        with:
 | 
			
		||||
          name: artifacts
 | 
			
		||||
          path: artifacts\*
 | 
			
		||||
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -152,3 +152,8 @@ fabric.properties
 | 
			
		||||
# Android studio 3.1+ serialized cache file
 | 
			
		||||
.idea/caches/build_file_checksums.ser
 | 
			
		||||
 | 
			
		||||
src/main/cpp/tech_nevets_tvpn_wg_WireGuardJNI.h
 | 
			
		||||
 | 
			
		||||
jre/
 | 
			
		||||
src/main/cpp/build
 | 
			
		||||
inno/
 | 
			
		||||
							
								
								
									
										10
									
								
								TVPN.exe.manifest
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								TVPN.exe.manifest
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 | 
			
		||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
 | 
			
		||||
     <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
 | 
			
		||||
         <security>
 | 
			
		||||
             <requestedPrivileges>
 | 
			
		||||
                 <requestedExecutionLevel level="highestAvailable" uiAccess="False" />
 | 
			
		||||
             </requestedPrivileges>
 | 
			
		||||
         </security>
 | 
			
		||||
     </trustInfo>
 | 
			
		||||
</assembly>
 | 
			
		||||
							
								
								
									
										22
									
								
								build.gradle
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								build.gradle
									
									
									
									
									
								
							@ -1,13 +1,18 @@
 | 
			
		||||
plugins {
 | 
			
		||||
    id 'java'
 | 
			
		||||
    id 'com.github.johnrengelman.shadow' version '8.1.1'
 | 
			
		||||
    id 'edu.sc.seis.launch4j' version '3.0.6'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
group = 'tech.nevets'
 | 
			
		||||
version = '0.2.0'
 | 
			
		||||
version = '0.3.0'
 | 
			
		||||
 | 
			
		||||
repositories {
 | 
			
		||||
    mavenCentral()
 | 
			
		||||
    maven {
 | 
			
		||||
        name = "Gitea"
 | 
			
		||||
        url = uri("https://git.nevets.tech/api/packages/Steven/maven")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dependencies {
 | 
			
		||||
@ -18,6 +23,8 @@ dependencies {
 | 
			
		||||
    //implementation "com.formdev:flatlaf:3.5.1"
 | 
			
		||||
    implementation files("libs/gson-2.11.0.jar")
 | 
			
		||||
    //implementation "com.google.code.gson:gson:2.11.0"
 | 
			
		||||
 | 
			
		||||
    implementation "tech.nevets:JConf:0.1.0:no-deps"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.withType(JavaCompile).configureEach {
 | 
			
		||||
@ -34,3 +41,16 @@ jar {
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
launch4j {
 | 
			
		||||
    mainClassName = 'tech.nevets.tvpn.Main'
 | 
			
		||||
    outfile = 'TVPN.exe'
 | 
			
		||||
    jarTask = project.tasks.shadowJar
 | 
			
		||||
    fileDescription = 'TVPN Client'
 | 
			
		||||
    icon = "${projectDir}/src/main/resources/icon.ico"
 | 
			
		||||
    productName = 'TVPN'
 | 
			
		||||
    version = "$this.version"
 | 
			
		||||
    textVersion = "$this.version"
 | 
			
		||||
    bundledJrePath = './jre'
 | 
			
		||||
    manifest = "${projectDir}/TVPN.exe.manifest"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								installer-script.iss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								installer-script.iss
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
			
		||||
; Script generated by the Inno Setup Script Wizard.
 | 
			
		||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
 | 
			
		||||
 | 
			
		||||
#define MyAppName "TVPN"
 | 
			
		||||
#define MyAppPublisher "nevetS Tech"
 | 
			
		||||
#define MyAppURL "https://git.nevets.tech/Steven/TVPN"
 | 
			
		||||
#define MyAppExeName "TVPN.exe"
 | 
			
		||||
 | 
			
		||||
[Setup]
 | 
			
		||||
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
 | 
			
		||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
 | 
			
		||||
AppId={{79AFBC44-4C4B-4509-9723-5CB4F30E875F}
 | 
			
		||||
AppName={#MyAppName}
 | 
			
		||||
AppVersion={#MyAppVersion}
 | 
			
		||||
;AppVerName={#MyAppName} {#MyAppVersion}
 | 
			
		||||
AppPublisher={#MyAppPublisher}
 | 
			
		||||
AppPublisherURL={#MyAppURL}
 | 
			
		||||
AppSupportURL={#MyAppURL}
 | 
			
		||||
AppUpdatesURL={#MyAppURL}
 | 
			
		||||
DefaultDirName={autopf}\{#MyAppName}
 | 
			
		||||
DisableProgramGroupPage=yes
 | 
			
		||||
; Uncomment the following line to run in non administrative install mode (install for current user only.)
 | 
			
		||||
;PrivilegesRequired=lowest
 | 
			
		||||
OutputDir=.\artifacts
 | 
			
		||||
OutputBaseFilename=tvpn-installer
 | 
			
		||||
SetupIconFile=.\src\main\resources\icon.ico
 | 
			
		||||
Compression=lzma
 | 
			
		||||
SolidCompression=yes
 | 
			
		||||
WizardStyle=modern
 | 
			
		||||
 | 
			
		||||
[Languages]
 | 
			
		||||
Name: "english"; MessagesFile: "compiler:Default.isl"
 | 
			
		||||
 | 
			
		||||
[Tasks]
 | 
			
		||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
 | 
			
		||||
 | 
			
		||||
[Files]
 | 
			
		||||
Source: ".\artifacts\TVPN.exe"; DestDir: "{app}"; Flags: ignoreversion
 | 
			
		||||
Source: ".\jre\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
 | 
			
		||||
Source: ".\artifacts\wireguard.dll"; DestDir: "{app}"; Flags: ignoreversion
 | 
			
		||||
Source: ".\artifacts\tunnel.dll"; DestDir: "{app}"; Flags: ignoreversion
 | 
			
		||||
Source: ".\artifacts\libwireguard_wrapper.dll"; DestDir: "{app}"; Flags: ignoreversion
 | 
			
		||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
 | 
			
		||||
 | 
			
		||||
[Icons]
 | 
			
		||||
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
 | 
			
		||||
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
 | 
			
		||||
 | 
			
		||||
[Run]
 | 
			
		||||
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
 | 
			
		||||
 | 
			
		||||
@ -17,8 +17,10 @@ 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)
 | 
			
		||||
 | 
			
		||||
target_link_libraries(wireguard_wrapper PRIVATE Rpcrt4)
 | 
			
		||||
 | 
			
		||||
# Optionally, you can specify output directory for the compiled library
 | 
			
		||||
set_target_properties(wireguard_wrapper PROPERTIES
 | 
			
		||||
        LIBRARY_OUTPUT_DIRECTORY build/lib
 | 
			
		||||
        LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
 | 
			
		||||
        OUTPUT_NAME "wireguard_wrapper"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										444
									
								
								src/main/cpp/example.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										444
									
								
								src/main/cpp/example.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,444 @@
 | 
			
		||||
//
 | 
			
		||||
// Created by steven on 10/27/2024.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <winsock2.h>
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
#include <ws2ipdef.h>
 | 
			
		||||
#include <ws2tcpip.h>
 | 
			
		||||
#include <iphlpapi.h>
 | 
			
		||||
#include <bcrypt.h>
 | 
			
		||||
#include <wincrypt.h>
 | 
			
		||||
#include <sysinfoapi.h>
 | 
			
		||||
#include <winternl.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "wireguard.h"
 | 
			
		||||
 | 
			
		||||
static WIREGUARD_CREATE_ADAPTER_FUNC *WireGuardCreateAdapter;
 | 
			
		||||
static WIREGUARD_OPEN_ADAPTER_FUNC *WireGuardOpenAdapter;
 | 
			
		||||
static WIREGUARD_CLOSE_ADAPTER_FUNC *WireGuardCloseAdapter;
 | 
			
		||||
static WIREGUARD_GET_ADAPTER_LUID_FUNC *WireGuardGetAdapterLUID;
 | 
			
		||||
static WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC *WireGuardGetRunningDriverVersion;
 | 
			
		||||
static WIREGUARD_DELETE_DRIVER_FUNC *WireGuardDeleteDriver;
 | 
			
		||||
static WIREGUARD_SET_LOGGER_FUNC *WireGuardSetLogger;
 | 
			
		||||
static WIREGUARD_SET_ADAPTER_LOGGING_FUNC *WireGuardSetAdapterLogging;
 | 
			
		||||
static WIREGUARD_GET_ADAPTER_STATE_FUNC *WireGuardGetAdapterState;
 | 
			
		||||
static WIREGUARD_SET_ADAPTER_STATE_FUNC *WireGuardSetAdapterState;
 | 
			
		||||
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;
 | 
			
		||||
#define X(Name) ((*(FARPROC *)&Name = GetProcAddress(WireGuardDll, #Name)) == NULL)
 | 
			
		||||
    if (X(WireGuardCreateAdapter) || X(WireGuardOpenAdapter) || X(WireGuardCloseAdapter) ||
 | 
			
		||||
        X(WireGuardGetAdapterLUID) || X(WireGuardGetRunningDriverVersion) || X(WireGuardDeleteDriver) ||
 | 
			
		||||
        X(WireGuardSetLogger) || X(WireGuardSetAdapterLogging) || X(WireGuardGetAdapterState) ||
 | 
			
		||||
        X(WireGuardSetAdapterState) || X(WireGuardGetConfiguration) || X(WireGuardSetConfiguration))
 | 
			
		||||
#undef X
 | 
			
		||||
    {
 | 
			
		||||
        DWORD LastError = GetLastError();
 | 
			
		||||
        FreeLibrary(WireGuardDll);
 | 
			
		||||
        SetLastError(LastError);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    return WireGuardDll;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void CALLBACK
 | 
			
		||||
ConsoleLogger(_In_ WIREGUARD_LOGGER_LEVEL Level, _In_ DWORD64 Timestamp, _In_z_ const WCHAR *LogLine)
 | 
			
		||||
{
 | 
			
		||||
    SYSTEMTIME SystemTime;
 | 
			
		||||
    FileTimeToSystemTime((FILETIME *)&Timestamp, &SystemTime);
 | 
			
		||||
    WCHAR LevelMarker;
 | 
			
		||||
    switch (Level)
 | 
			
		||||
    {
 | 
			
		||||
        case WIREGUARD_LOG_INFO:
 | 
			
		||||
            LevelMarker = L'+';
 | 
			
		||||
            break;
 | 
			
		||||
        case WIREGUARD_LOG_WARN:
 | 
			
		||||
            LevelMarker = L'-';
 | 
			
		||||
            break;
 | 
			
		||||
        case WIREGUARD_LOG_ERR:
 | 
			
		||||
            LevelMarker = L'!';
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            return;
 | 
			
		||||
    }
 | 
			
		||||
    fwprintf(
 | 
			
		||||
            stderr,
 | 
			
		||||
            L"%04u-%02u-%02u %02u:%02u:%02u.%04u [%c] %s\n",
 | 
			
		||||
            SystemTime.wYear,
 | 
			
		||||
            SystemTime.wMonth,
 | 
			
		||||
            SystemTime.wDay,
 | 
			
		||||
            SystemTime.wHour,
 | 
			
		||||
            SystemTime.wMinute,
 | 
			
		||||
            SystemTime.wSecond,
 | 
			
		||||
            SystemTime.wMilliseconds,
 | 
			
		||||
            LevelMarker,
 | 
			
		||||
            LogLine);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static DWORD64 Now(VOID)
 | 
			
		||||
{
 | 
			
		||||
    LARGE_INTEGER Timestamp;
 | 
			
		||||
    NtQuerySystemTime(&Timestamp);
 | 
			
		||||
    return Timestamp.QuadPart;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static DWORD
 | 
			
		||||
LogError(_In_z_ const WCHAR *Prefix, _In_ DWORD Error)
 | 
			
		||||
{
 | 
			
		||||
    WCHAR *SystemMessage = NULL, *FormattedMessage = NULL;
 | 
			
		||||
    FormatMessageW(
 | 
			
		||||
            FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK,
 | 
			
		||||
            NULL,
 | 
			
		||||
            HRESULT_FROM_SETUPAPI(Error),
 | 
			
		||||
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 | 
			
		||||
            (void *)&SystemMessage,
 | 
			
		||||
            0,
 | 
			
		||||
            NULL);
 | 
			
		||||
    FormatMessageW(
 | 
			
		||||
            FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY |
 | 
			
		||||
            FORMAT_MESSAGE_MAX_WIDTH_MASK,
 | 
			
		||||
            SystemMessage ? L"%1: %3(Code 0x%2!08X!)" : L"%1: Code 0x%2!08X!",
 | 
			
		||||
            0,
 | 
			
		||||
            0,
 | 
			
		||||
            (void *)&FormattedMessage,
 | 
			
		||||
            0,
 | 
			
		||||
            (va_list *)(DWORD_PTR[]){ (DWORD_PTR)Prefix, (DWORD_PTR)Error, (DWORD_PTR)SystemMessage });
 | 
			
		||||
    if (FormattedMessage)
 | 
			
		||||
        ConsoleLogger(WIREGUARD_LOG_ERR, Now(), FormattedMessage);
 | 
			
		||||
    LocalFree(FormattedMessage);
 | 
			
		||||
    LocalFree(SystemMessage);
 | 
			
		||||
    return Error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static DWORD
 | 
			
		||||
LogLastError(_In_z_ const WCHAR *Prefix)
 | 
			
		||||
{
 | 
			
		||||
    DWORD LastError = GetLastError();
 | 
			
		||||
    LogError(Prefix, LastError);
 | 
			
		||||
    SetLastError(LastError);
 | 
			
		||||
    return LastError;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
Log(_In_ WIREGUARD_LOGGER_LEVEL Level, _In_z_ const WCHAR *Format, ...)
 | 
			
		||||
{
 | 
			
		||||
    WCHAR LogLine[0x200];
 | 
			
		||||
    va_list args;
 | 
			
		||||
    va_start(args, Format);
 | 
			
		||||
    _vsnwprintf_s(LogLine, _countof(LogLine), _TRUNCATE, Format, args);
 | 
			
		||||
    va_end(args);
 | 
			
		||||
    ConsoleLogger(Level, Now(), LogLine);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_Must_inspect_result_
 | 
			
		||||
_Return_type_success_(return != FALSE)
 | 
			
		||||
static BOOL
 | 
			
		||||
GenerateKeyPair(
 | 
			
		||||
        _Out_writes_bytes_all_(WIREGUARD_KEY_LENGTH) BYTE PublicKey[WIREGUARD_KEY_LENGTH],
 | 
			
		||||
        _Out_writes_bytes_all_(WIREGUARD_KEY_LENGTH) BYTE PrivateKey[WIREGUARD_KEY_LENGTH])
 | 
			
		||||
{
 | 
			
		||||
    BCRYPT_ALG_HANDLE Algorithm;
 | 
			
		||||
    BCRYPT_KEY_HANDLE Key;
 | 
			
		||||
    NTSTATUS Status;
 | 
			
		||||
    struct
 | 
			
		||||
    {
 | 
			
		||||
        BCRYPT_ECCKEY_BLOB Header;
 | 
			
		||||
        BYTE Public[32];
 | 
			
		||||
        BYTE Unused[32];
 | 
			
		||||
        BYTE Private[32];
 | 
			
		||||
    } ExportedKey;
 | 
			
		||||
    ULONG Bytes;
 | 
			
		||||
 | 
			
		||||
    Status = BCryptOpenAlgorithmProvider(&Algorithm, BCRYPT_ECDH_ALGORITHM, NULL, 0);
 | 
			
		||||
    if (!NT_SUCCESS(Status))
 | 
			
		||||
        goto out;
 | 
			
		||||
 | 
			
		||||
    Status = BCryptSetProperty(
 | 
			
		||||
            Algorithm, BCRYPT_ECC_CURVE_NAME, (PUCHAR)BCRYPT_ECC_CURVE_25519, sizeof(BCRYPT_ECC_CURVE_25519), 0);
 | 
			
		||||
    if (!NT_SUCCESS(Status))
 | 
			
		||||
        goto cleanupProvider;
 | 
			
		||||
 | 
			
		||||
    Status = BCryptGenerateKeyPair(Algorithm, &Key, 255, 0);
 | 
			
		||||
    if (!NT_SUCCESS(Status))
 | 
			
		||||
        goto cleanupProvider;
 | 
			
		||||
 | 
			
		||||
    Status = BCryptFinalizeKeyPair(Key, 0);
 | 
			
		||||
    if (!NT_SUCCESS(Status))
 | 
			
		||||
        goto cleanupKey;
 | 
			
		||||
 | 
			
		||||
    Status = BCryptExportKey(Key, NULL, BCRYPT_ECCPRIVATE_BLOB, (PUCHAR)&ExportedKey, sizeof(ExportedKey), &Bytes, 0);
 | 
			
		||||
    if (!NT_SUCCESS(Status))
 | 
			
		||||
        goto cleanupKey;
 | 
			
		||||
 | 
			
		||||
    memcpy(PublicKey, ExportedKey.Public, WIREGUARD_KEY_LENGTH);
 | 
			
		||||
    memcpy(PrivateKey, ExportedKey.Private, WIREGUARD_KEY_LENGTH);
 | 
			
		||||
    SecureZeroMemory(&ExportedKey, sizeof(ExportedKey));
 | 
			
		||||
 | 
			
		||||
    cleanupKey:
 | 
			
		||||
    BCryptDestroyKey(Key);
 | 
			
		||||
    cleanupProvider:
 | 
			
		||||
    BCryptCloseAlgorithmProvider(Algorithm, 0);
 | 
			
		||||
    out:
 | 
			
		||||
    SetLastError(RtlNtStatusToDosError(Status));
 | 
			
		||||
    return NT_SUCCESS(Status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static HANDLE QuitEvent;
 | 
			
		||||
 | 
			
		||||
static BOOL WINAPI
 | 
			
		||||
CtrlHandler(_In_ DWORD CtrlType)
 | 
			
		||||
{
 | 
			
		||||
    switch (CtrlType)
 | 
			
		||||
    {
 | 
			
		||||
        case CTRL_C_EVENT:
 | 
			
		||||
        case CTRL_BREAK_EVENT:
 | 
			
		||||
        case CTRL_CLOSE_EVENT:
 | 
			
		||||
        case CTRL_LOGOFF_EVENT:
 | 
			
		||||
        case CTRL_SHUTDOWN_EVENT:
 | 
			
		||||
            Log(WIREGUARD_LOG_INFO, L"Cleaning up and shutting down");
 | 
			
		||||
            SetEvent(QuitEvent);
 | 
			
		||||
            return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_Return_type_success_(return != FALSE)
 | 
			
		||||
static BOOL
 | 
			
		||||
TalkToDemoServer(
 | 
			
		||||
        _In_reads_bytes_(InputLength) const CHAR *Input,
 | 
			
		||||
        _In_ DWORD InputLength,
 | 
			
		||||
        _Out_writes_bytes_(*OutputLength) CHAR *Output,
 | 
			
		||||
        _Inout_ DWORD *OutputLength,
 | 
			
		||||
        _Out_ SOCKADDR_INET *ResolvedDemoServer)
 | 
			
		||||
{
 | 
			
		||||
    SOCKET Socket = INVALID_SOCKET;
 | 
			
		||||
    ADDRINFOW Hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_protocol = IPPROTO_TCP }, *Resolution;
 | 
			
		||||
    BOOL Ret = FALSE;
 | 
			
		||||
 | 
			
		||||
    if (GetAddrInfoW(L"demo.wireguard.com", L"42912", &Hints, &Resolution))
 | 
			
		||||
        return FALSE;
 | 
			
		||||
    for (ADDRINFOW *Candidate = Resolution; Candidate; Candidate = Candidate->ai_next)
 | 
			
		||||
    {
 | 
			
		||||
        if (Candidate->ai_family != AF_INET && Candidate->ai_family != AF_INET6)
 | 
			
		||||
            continue;
 | 
			
		||||
        Socket = socket(Candidate->ai_family, Candidate->ai_socktype, Candidate->ai_protocol);
 | 
			
		||||
        if (Socket == INVALID_SOCKET)
 | 
			
		||||
            goto cleanupResolution;
 | 
			
		||||
        if (connect(Socket, Candidate->ai_addr, (int)Candidate->ai_addrlen) == SOCKET_ERROR)
 | 
			
		||||
        {
 | 
			
		||||
            closesocket(Socket);
 | 
			
		||||
            Socket = INVALID_SOCKET;
 | 
			
		||||
        }
 | 
			
		||||
        memcpy(ResolvedDemoServer, Candidate->ai_addr, Candidate->ai_addrlen);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    if (Socket == INVALID_SOCKET)
 | 
			
		||||
        goto cleanupResolution;
 | 
			
		||||
    if (send(Socket, Input, InputLength, 0) == SOCKET_ERROR)
 | 
			
		||||
        goto cleanupSocket;
 | 
			
		||||
    if ((*OutputLength = recv(Socket, Output, *OutputLength, 0)) == SOCKET_ERROR)
 | 
			
		||||
        goto cleanupSocket;
 | 
			
		||||
    Ret = TRUE;
 | 
			
		||||
    cleanupSocket:
 | 
			
		||||
    closesocket(Socket);
 | 
			
		||||
    cleanupResolution:
 | 
			
		||||
    FreeAddrInfoW(Resolution);
 | 
			
		||||
    return Ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int __cdecl main(void)
 | 
			
		||||
{
 | 
			
		||||
    DWORD LastError;
 | 
			
		||||
    WSADATA WsaData;
 | 
			
		||||
    if (WSAStartup(MAKEWORD(2, 2), &WsaData))
 | 
			
		||||
        return LogError(L"Failed to initialize Winsock", GetLastError());
 | 
			
		||||
    HMODULE WireGuard = InitializeWireGuardNT();
 | 
			
		||||
    if (!WireGuard)
 | 
			
		||||
    {
 | 
			
		||||
        LastError = LogError(L"Failed to initialize WireGuardNT", GetLastError());
 | 
			
		||||
        goto cleanupWinsock;
 | 
			
		||||
    }
 | 
			
		||||
    WireGuardSetLogger(ConsoleLogger);
 | 
			
		||||
    Log(WIREGUARD_LOG_INFO, L"WireGuardNT library loaded");
 | 
			
		||||
 | 
			
		||||
    struct
 | 
			
		||||
    {
 | 
			
		||||
        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 } };
 | 
			
		||||
 | 
			
		||||
    Log(WIREGUARD_LOG_INFO, L"Generating keypair");
 | 
			
		||||
    BYTE PublicKey[WIREGUARD_KEY_LENGTH];
 | 
			
		||||
    if (!GenerateKeyPair(PublicKey, Config.Interface.PrivateKey))
 | 
			
		||||
    {
 | 
			
		||||
        LastError = LogError(L"Failed to generate keypair", GetLastError());
 | 
			
		||||
        goto cleanupWireGuard;
 | 
			
		||||
    }
 | 
			
		||||
    CHAR PublicKeyString[46] = { 0 };
 | 
			
		||||
    DWORD Bytes = sizeof(PublicKeyString);
 | 
			
		||||
    CryptBinaryToStringA(
 | 
			
		||||
            PublicKey, sizeof(PublicKey), CRYPT_STRING_BASE64 | CRYPT_STRING_NOCR, PublicKeyString, &Bytes);
 | 
			
		||||
    CHAR ServerResponse[256] = { 0 };
 | 
			
		||||
    Log(WIREGUARD_LOG_INFO, L"Talking to demo server");
 | 
			
		||||
    Bytes = sizeof(ServerResponse) - 1;
 | 
			
		||||
    if (!TalkToDemoServer(
 | 
			
		||||
            PublicKeyString, (DWORD)strlen(PublicKeyString), ServerResponse, &Bytes, &Config.DemoServer.Endpoint))
 | 
			
		||||
    {
 | 
			
		||||
        LastError = LogError(L"Failed to talk to demo server", GetLastError());
 | 
			
		||||
        goto cleanupWireGuard;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    CHAR *Colon1 = strchr(ServerResponse, ':');
 | 
			
		||||
    CHAR *Colon2 = Colon1 ? strchr(Colon1 + 1, ':') : NULL;
 | 
			
		||||
    CHAR *Colon3 = Colon2 ? strchr(Colon2 + 1, ':') : NULL;
 | 
			
		||||
    if (!Colon1 || !Colon2 || !Colon3)
 | 
			
		||||
    {
 | 
			
		||||
        LastError = LogError(L"Failed to parse demo server response", ERROR_UNDEFINED_CHARACTER);
 | 
			
		||||
        goto cleanupWireGuard;
 | 
			
		||||
    }
 | 
			
		||||
    if (Bytes && ServerResponse[--Bytes] == '\n')
 | 
			
		||||
        ServerResponse[Bytes] = '\0';
 | 
			
		||||
    *Colon1 = *Colon2 = *Colon3 = '\0';
 | 
			
		||||
 | 
			
		||||
    MIB_UNICASTIPADDRESS_ROW AddressRow;
 | 
			
		||||
    InitializeUnicastIpAddressEntry(&AddressRow);
 | 
			
		||||
    AddressRow.Address.Ipv4.sin_family = AF_INET;
 | 
			
		||||
    AddressRow.OnLinkPrefixLength = 24; /* This is a /24 network */
 | 
			
		||||
    AddressRow.DadState = IpDadStatePreferred;
 | 
			
		||||
    Bytes = sizeof(Config.DemoServer.PublicKey);
 | 
			
		||||
    if (strcmp(ServerResponse, "OK") || InetPtonA(AF_INET, Colon3 + 1, &AddressRow.Address.Ipv4.sin_addr) != 1 ||
 | 
			
		||||
        !CryptStringToBinaryA(Colon1 + 1, 0, CRYPT_STRING_BASE64, Config.DemoServer.PublicKey, &Bytes, NULL, NULL))
 | 
			
		||||
    {
 | 
			
		||||
        LastError = LogError(L"Failed to parse demo server response", ERROR_UNDEFINED_CHARACTER);
 | 
			
		||||
        goto cleanupWireGuard;
 | 
			
		||||
    }
 | 
			
		||||
    if (Config.DemoServer.Endpoint.si_family == AF_INET)
 | 
			
		||||
        Config.DemoServer.Endpoint.Ipv4.sin_port = htons((u_short)atoi(Colon2 + 1));
 | 
			
		||||
    else if (Config.DemoServer.Endpoint.si_family == AF_INET6)
 | 
			
		||||
        Config.DemoServer.Endpoint.Ipv6.sin6_port = htons((u_short)atoi(Colon2 + 1));
 | 
			
		||||
 | 
			
		||||
    QuitEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
 | 
			
		||||
    if (!QuitEvent)
 | 
			
		||||
    {
 | 
			
		||||
        LastError = LogError(L"Failed to create event", GetLastError());
 | 
			
		||||
        goto cleanupWireGuard;
 | 
			
		||||
    }
 | 
			
		||||
    if (!SetConsoleCtrlHandler(CtrlHandler, TRUE))
 | 
			
		||||
    {
 | 
			
		||||
        LastError = LogError(L"Failed to set console handler", GetLastError());
 | 
			
		||||
        goto cleanupQuit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    GUID ExampleGuid = { 0xdeadc001, 0xbeef, 0xbabe, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef } };
 | 
			
		||||
    WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardCreateAdapter(L"Demo", L"Example", &ExampleGuid);
 | 
			
		||||
    if (!Adapter)
 | 
			
		||||
    {
 | 
			
		||||
        LastError = GetLastError();
 | 
			
		||||
        LogError(L"Failed to create adapter", LastError);
 | 
			
		||||
        goto cleanupQuit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!WireGuardSetAdapterLogging(Adapter, WIREGUARD_ADAPTER_LOG_ON))
 | 
			
		||||
        LogError(L"Failed to enable adapter logging", GetLastError());
 | 
			
		||||
 | 
			
		||||
    DWORD Version = WireGuardGetRunningDriverVersion();
 | 
			
		||||
    Log(WIREGUARD_LOG_INFO, L"WireGuardNT v%u.%u loaded", (Version >> 16) & 0xff, (Version >> 0) & 0xff);
 | 
			
		||||
 | 
			
		||||
    WireGuardGetAdapterLUID(Adapter, &AddressRow.InterfaceLuid);
 | 
			
		||||
    MIB_IPFORWARD_ROW2 DefaultRoute = { 0 };
 | 
			
		||||
    InitializeIpForwardEntry(&DefaultRoute);
 | 
			
		||||
    DefaultRoute.InterfaceLuid = AddressRow.InterfaceLuid;
 | 
			
		||||
    DefaultRoute.DestinationPrefix.Prefix.si_family = AF_INET;
 | 
			
		||||
    DefaultRoute.NextHop.si_family = AF_INET;
 | 
			
		||||
    DefaultRoute.Metric = 0;
 | 
			
		||||
    LastError = CreateIpForwardEntry2(&DefaultRoute);
 | 
			
		||||
    if (LastError != ERROR_SUCCESS && LastError != ERROR_OBJECT_ALREADY_EXISTS)
 | 
			
		||||
    {
 | 
			
		||||
        LogError(L"Failed to set default route", LastError);
 | 
			
		||||
        goto cleanupAdapter;
 | 
			
		||||
    }
 | 
			
		||||
    LastError = CreateUnicastIpAddressEntry(&AddressRow);
 | 
			
		||||
    if (LastError != ERROR_SUCCESS && LastError != ERROR_OBJECT_ALREADY_EXISTS)
 | 
			
		||||
    {
 | 
			
		||||
        LogError(L"Failed to set IP address", LastError);
 | 
			
		||||
        goto cleanupAdapter;
 | 
			
		||||
    }
 | 
			
		||||
    MIB_IPINTERFACE_ROW IpInterface = { 0 };
 | 
			
		||||
    InitializeIpInterfaceEntry(&IpInterface);
 | 
			
		||||
    IpInterface.InterfaceLuid = AddressRow.InterfaceLuid;
 | 
			
		||||
    IpInterface.Family = AF_INET;
 | 
			
		||||
    LastError = GetIpInterfaceEntry(&IpInterface);
 | 
			
		||||
    if (LastError != ERROR_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
        LogError(L"Failed to get IP interface", LastError);
 | 
			
		||||
        goto cleanupAdapter;
 | 
			
		||||
    }
 | 
			
		||||
    IpInterface.UseAutomaticMetric = FALSE;
 | 
			
		||||
    IpInterface.Metric = 0;
 | 
			
		||||
    IpInterface.NlMtu = 1420;
 | 
			
		||||
    IpInterface.SitePrefixLength = 0;
 | 
			
		||||
    LastError = SetIpInterfaceEntry(&IpInterface);
 | 
			
		||||
    if (LastError != ERROR_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
        LogError(L"Failed to set metric and MTU", LastError);
 | 
			
		||||
        goto cleanupAdapter;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Log(WIREGUARD_LOG_INFO, L"Setting configuration and adapter up");
 | 
			
		||||
    if (!WireGuardSetConfiguration(Adapter, &Config.Interface, sizeof(Config)) ||
 | 
			
		||||
        !WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE_UP))
 | 
			
		||||
    {
 | 
			
		||||
        LastError = LogError(L"Failed to set configuration and adapter up", GetLastError());
 | 
			
		||||
        goto cleanupAdapter;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    do
 | 
			
		||||
    {
 | 
			
		||||
        Bytes = sizeof(Config);
 | 
			
		||||
        if (!WireGuardGetConfiguration(Adapter, &Config.Interface, &Bytes) || !Config.Interface.PeersCount)
 | 
			
		||||
        {
 | 
			
		||||
            LastError = LogError(L"Failed to get configuration", GetLastError());
 | 
			
		||||
            goto cleanupAdapter;
 | 
			
		||||
        }
 | 
			
		||||
        DWORD64 Timestamp = Now();
 | 
			
		||||
        SYSTEMTIME SystemTime;
 | 
			
		||||
        FileTimeToSystemTime((FILETIME *)&Timestamp, &SystemTime);
 | 
			
		||||
        fwprintf(
 | 
			
		||||
                stderr,
 | 
			
		||||
                L"%04u-%02u-%02u %02u:%02u:%02u.%04u [#] RX: %llu, TX: %llu\r",
 | 
			
		||||
                SystemTime.wYear,
 | 
			
		||||
                SystemTime.wMonth,
 | 
			
		||||
                SystemTime.wDay,
 | 
			
		||||
                SystemTime.wHour,
 | 
			
		||||
                SystemTime.wMinute,
 | 
			
		||||
                SystemTime.wSecond,
 | 
			
		||||
                SystemTime.wMilliseconds,
 | 
			
		||||
                Config.DemoServer.RxBytes,
 | 
			
		||||
                Config.DemoServer.TxBytes);
 | 
			
		||||
    } while (WaitForSingleObject(QuitEvent, 1000) == WAIT_TIMEOUT);
 | 
			
		||||
 | 
			
		||||
    cleanupAdapter:
 | 
			
		||||
    WireGuardCloseAdapter(Adapter);
 | 
			
		||||
    cleanupQuit:
 | 
			
		||||
    SetConsoleCtrlHandler(CtrlHandler, FALSE);
 | 
			
		||||
    CloseHandle(QuitEvent);
 | 
			
		||||
    cleanupWireGuard:
 | 
			
		||||
    FreeLibrary(WireGuard);
 | 
			
		||||
    cleanupWinsock:
 | 
			
		||||
    WSACleanup();
 | 
			
		||||
    return LastError;
 | 
			
		||||
}
 | 
			
		||||
@ -1,117 +0,0 @@
 | 
			
		||||
/* DO NOT EDIT THIS FILE - it is machine generated */
 | 
			
		||||
#include <jni.h>
 | 
			
		||||
/* Header for class tech_nevets_tvpn_wg_WireGuardJNI */
 | 
			
		||||
 | 
			
		||||
#ifndef _Included_tech_nevets_tvpn_wg_WireGuardJNI
 | 
			
		||||
#define _Included_tech_nevets_tvpn_wg_WireGuardJNI
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
/*
 | 
			
		||||
 * Class:     tech_nevets_tvpn_wg_WireGuardJNI
 | 
			
		||||
 * Method:    installAdapter
 | 
			
		||||
 * Signature: ()I
 | 
			
		||||
 */
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_installAdapter
 | 
			
		||||
  (JNIEnv *, jobject);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Class:     tech_nevets_tvpn_wg_WireGuardJNI
 | 
			
		||||
 * Method:    removeAdapter
 | 
			
		||||
 * Signature: ()I
 | 
			
		||||
 */
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_removeAdapter
 | 
			
		||||
  (JNIEnv *, jobject);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Class:     tech_nevets_tvpn_wg_WireGuardJNI
 | 
			
		||||
 * Method:    startTunnel
 | 
			
		||||
 * Signature: (Ljava/lang/String;)I
 | 
			
		||||
 */
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_startTunnel
 | 
			
		||||
  (JNIEnv *, jobject, jstring);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Class:     tech_nevets_tvpn_wg_WireGuardJNI
 | 
			
		||||
 * Method:    stopTunnel
 | 
			
		||||
 * Signature: (Ljava/lang/String;)I
 | 
			
		||||
 */
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_stopTunnel
 | 
			
		||||
  (JNIEnv *, jobject, jstring);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Class:     tech_nevets_tvpn_wg_WireGuardJNI
 | 
			
		||||
 * Method:    createTunnel
 | 
			
		||||
 * Signature: (Ljava/lang/String;)I
 | 
			
		||||
 */
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_createTunnel
 | 
			
		||||
  (JNIEnv *, jobject, jstring);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Class:     tech_nevets_tvpn_wg_WireGuardJNI
 | 
			
		||||
 * Method:    deleteTunnel
 | 
			
		||||
 * Signature: (Ljava/lang/String;)I
 | 
			
		||||
 */
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_deleteTunnel
 | 
			
		||||
  (JNIEnv *, jobject, jstring);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Class:     tech_nevets_tvpn_wg_WireGuardJNI
 | 
			
		||||
 * Method:    getConfig
 | 
			
		||||
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 | 
			
		||||
 */
 | 
			
		||||
JNIEXPORT jstring JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_getConfig
 | 
			
		||||
  (JNIEnv *, jobject, jstring);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Class:     tech_nevets_tvpn_wg_WireGuardJNI
 | 
			
		||||
 * Method:    updateConfig
 | 
			
		||||
 * Signature: (Ljava/lang/String;Ljava/lang/String;)I
 | 
			
		||||
 */
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_updateConfig
 | 
			
		||||
  (JNIEnv *, jobject, jstring, jstring);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Class:     tech_nevets_tvpn_wg_WireGuardJNI
 | 
			
		||||
 * Method:    addConfig
 | 
			
		||||
 * Signature: (Ljava/lang/String;Ljava/lang/String;)I
 | 
			
		||||
 */
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_addConfig
 | 
			
		||||
  (JNIEnv *, jobject, jstring, jstring);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Class:     tech_nevets_tvpn_wg_WireGuardJNI
 | 
			
		||||
 * Method:    getActiveTunnel
 | 
			
		||||
 * Signature: ()Ljava/lang/String;
 | 
			
		||||
 */
 | 
			
		||||
JNIEXPORT jstring JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_getActiveTunnel
 | 
			
		||||
  (JNIEnv *, jobject);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Class:     tech_nevets_tvpn_wg_WireGuardJNI
 | 
			
		||||
 * Method:    isActive
 | 
			
		||||
 * Signature: ()Z
 | 
			
		||||
 */
 | 
			
		||||
JNIEXPORT jboolean JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_isActive
 | 
			
		||||
  (JNIEnv *, jobject);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Class:     tech_nevets_tvpn_wg_WireGuardJNI
 | 
			
		||||
 * Method:    initializeWireGuard
 | 
			
		||||
 * Signature: (Ljava/lang/String;)I
 | 
			
		||||
 */
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_initializeWireGuard
 | 
			
		||||
  (JNIEnv *, jobject, jstring);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Class:     tech_nevets_tvpn_wg_WireGuardJNI
 | 
			
		||||
 * Method:    cleanup
 | 
			
		||||
 * Signature: ()V
 | 
			
		||||
 */
 | 
			
		||||
JNIEXPORT void JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_cleanup
 | 
			
		||||
  (JNIEnv *, jobject);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
@ -1,28 +1,133 @@
 | 
			
		||||
#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 "tech_nevets_tvpn_wg_WireGuardJNI.h"
 | 
			
		||||
 | 
			
		||||
const char *APP_DIR =  "C:\\Program Files\\TVPN\\";
 | 
			
		||||
#pragma comment(lib, "Rpcrt4.lib")
 | 
			
		||||
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_createTunnel(JNIEnv *env, jobject obj, jstring tunnelName) {
 | 
			
		||||
    const char *tunnelCharArr = (*env)->GetStringUTFChars(env, tunnelName, NULL);
 | 
			
		||||
    if (tunnelCharArr == NULL) {
 | 
			
		||||
        return 1;
 | 
			
		||||
const wchar_t *APP_DIR =  L"C:\\Program Files\\TVPN\\";
 | 
			
		||||
 | 
			
		||||
static WIREGUARD_CREATE_ADAPTER_FUNC *WireGuardCreateAdapter;
 | 
			
		||||
static WIREGUARD_OPEN_ADAPTER_FUNC *WireGuardOpenAdapter;
 | 
			
		||||
static WIREGUARD_CLOSE_ADAPTER_FUNC *WireGuardCloseAdapter;
 | 
			
		||||
static WIREGUARD_GET_ADAPTER_LUID_FUNC *WireGuardGetAdapterLUID;
 | 
			
		||||
static WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC *WireGuardGetRunningDriverVersion;
 | 
			
		||||
static WIREGUARD_DELETE_DRIVER_FUNC *WireGuardDeleteDriver;
 | 
			
		||||
static WIREGUARD_SET_LOGGER_FUNC *WireGuardSetLogger;
 | 
			
		||||
static WIREGUARD_SET_ADAPTER_LOGGING_FUNC *WireGuardSetAdapterLogging;
 | 
			
		||||
static WIREGUARD_GET_ADAPTER_STATE_FUNC *WireGuardGetAdapterState;
 | 
			
		||||
static WIREGUARD_SET_ADAPTER_STATE_FUNC *WireGuardSetAdapterState;
 | 
			
		||||
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;
 | 
			
		||||
#define X(Name) ((*(FARPROC *)&Name = GetProcAddress(WireGuardDll, #Name)) == NULL)
 | 
			
		||||
    if (X(WireGuardCreateAdapter) || X(WireGuardOpenAdapter) || X(WireGuardCloseAdapter) ||
 | 
			
		||||
        X(WireGuardGetAdapterLUID) || X(WireGuardGetRunningDriverVersion) || X(WireGuardDeleteDriver) ||
 | 
			
		||||
        X(WireGuardSetLogger) || X(WireGuardSetAdapterLogging) || X(WireGuardGetAdapterState) ||
 | 
			
		||||
        X(WireGuardSetAdapterState) || X(WireGuardGetConfiguration) || X(WireGuardSetConfiguration))
 | 
			
		||||
#undef X
 | 
			
		||||
    {
 | 
			
		||||
        DWORD LastError = GetLastError();
 | 
			
		||||
        FreeLibrary(WireGuardDll);
 | 
			
		||||
        SetLastError(LastError);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    return WireGuardDll;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GUID generateGUID() {
 | 
			
		||||
    UUID uuid;
 | 
			
		||||
    RPC_STATUS status = UuidCreate(&uuid);
 | 
			
		||||
 | 
			
		||||
    // Handle GUID generation error
 | 
			
		||||
    if (status != RPC_S_OK) {
 | 
			
		||||
        fprintf(stderr, "[C] Failed to create GUID\n");
 | 
			
		||||
        exit(1);  // Exiting here to indicate a critical error; you may handle differently
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    char *initialServiceName = "WireGuardTunnel$";
 | 
			
		||||
    char *tnlName = malloc(strlen(initialServiceName) + strlen(tunnelCharArr) + 1);
 | 
			
		||||
    strcpy(tnlName, initialServiceName);
 | 
			
		||||
    strcat(tnlName, tunnelCharArr);
 | 
			
		||||
    // Copy the generated UUID into a GUID struct
 | 
			
		||||
    GUID guid = { uuid.Data1, uuid.Data2, uuid.Data3 };
 | 
			
		||||
    for (int i = 0; i < 8; i++) {
 | 
			
		||||
        guid.Data4[i] = uuid.Data4[i];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    char *initialDisplayName = "WireGuard Tunnel: ";
 | 
			
		||||
    char *displayName = malloc(strlen(initialDisplayName) + strlen(tunnelCharArr) + 1);
 | 
			
		||||
    strcpy(displayName, initialDisplayName);
 | 
			
		||||
    strcat(displayName, tunnelCharArr);
 | 
			
		||||
    return guid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_installAdapter(JNIEnv *env, jobject obj) {
 | 
			
		||||
    HMODULE WireGuardDLL = InitializeWireGuardNT();
 | 
			
		||||
 | 
			
		||||
    GUID guid = generateGUID();
 | 
			
		||||
    WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardCreateAdapter(L"TVPNet", L"WireGuard", &guid);
 | 
			
		||||
 | 
			
		||||
    struct {
 | 
			
		||||
        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
 | 
			
		||||
            }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    WireGuardSetConfiguration(Adapter, &Config.Interface, sizeof(Config));
 | 
			
		||||
    WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE_UP);
 | 
			
		||||
 | 
			
		||||
    FreeLibrary(WireGuardDLL);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_removeAdapter(JNIEnv *env, jobject obj) {
 | 
			
		||||
    HMODULE WireGuardDLL = InitializeWireGuardNT();
 | 
			
		||||
 | 
			
		||||
    WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(L"TVPNet");
 | 
			
		||||
 | 
			
		||||
    printf("[C] Closing Adapter...\n");
 | 
			
		||||
    WireGuardCloseAdapter(Adapter);
 | 
			
		||||
 | 
			
		||||
    FreeLibrary(WireGuardDLL);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_installTunnel(JNIEnv *env, jobject obj, jstring tunnelName, jstring pathToConfig) {
 | 
			
		||||
    printf("[C] Started installTunnel\n");
 | 
			
		||||
 | 
			
		||||
    const jchar *rawStr = (*env)->GetStringChars(env, tunnelName, 0); //TODO mem cleanup
 | 
			
		||||
    LPWSTR tnlName = (LPWSTR) rawStr;
 | 
			
		||||
 | 
			
		||||
    wprintf(L"[C] Tunnel Name: %ls", tnlName);
 | 
			
		||||
 | 
			
		||||
    wchar_t *servicePrefix = L"WireGuardTunnel$";
 | 
			
		||||
    wchar_t *serviceName = malloc(sizeof(wchar_t) * (wcslen(servicePrefix) + wcslen(tnlName) + 1)); //TODO mem cleanup
 | 
			
		||||
    wcscpy(serviceName, servicePrefix);
 | 
			
		||||
    wcscat(serviceName, tnlName);
 | 
			
		||||
 | 
			
		||||
    wchar_t *displayNamePrefix = L"WireGuard Tunnel: ";
 | 
			
		||||
    wchar_t *displayName = malloc(sizeof(wchar_t) * (wcslen(displayNamePrefix) + wcslen(tnlName) + 1)); //TODO mem cleanup
 | 
			
		||||
    wcscpy(displayName, displayNamePrefix);
 | 
			
		||||
    wcscat(displayName, tnlName);
 | 
			
		||||
 | 
			
		||||
    printf("[C] Opening Service Manager\n");
 | 
			
		||||
 | 
			
		||||
    SC_HANDLE hSCManager = OpenSCManager(
 | 
			
		||||
            NULL,
 | 
			
		||||
@ -30,21 +135,23 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_createTunnel(JNIEnv
 | 
			
		||||
            SC_MANAGER_ALL_ACCESS
 | 
			
		||||
    );
 | 
			
		||||
    if (hSCManager == NULL) {
 | 
			
		||||
        printf("OpenSCManager failed (%lu)\n", GetLastError());
 | 
			
		||||
        return 2;
 | 
			
		||||
        printf("[C] OpenSCManager failed (%lu)\n", GetLastError());
 | 
			
		||||
        return 3;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    char *params = "TVPN.exe /installtunnelservice ";
 | 
			
		||||
    char *conf = ".conf";
 | 
			
		||||
    char *exePath = malloc(strlen(APP_DIR) + strlen(params) + strlen(tunnelCharArr) + strlen(conf) + 1);
 | 
			
		||||
    strcpy(exePath, APP_DIR);
 | 
			
		||||
    strcat(exePath, params);
 | 
			
		||||
    strcat(exePath, tunnelCharArr);
 | 
			
		||||
    strcat(exePath, conf);
 | 
			
		||||
    wchar_t *params = L"TVPN.exe /installtunnelservice ";
 | 
			
		||||
    wchar_t *conf = L".conf";
 | 
			
		||||
    wchar_t *exePath = malloc(sizeof(wchar_t) * (wcslen(APP_DIR) + wcslen(params) + wcslen(tnlName) + wcslen(conf) + 1)); //TODO mem cleanup
 | 
			
		||||
    wcscpy(exePath, APP_DIR);
 | 
			
		||||
    wcscat(exePath, params);
 | 
			
		||||
    wcscat(exePath, tnlName);
 | 
			
		||||
    wcscat(exePath, conf);
 | 
			
		||||
 | 
			
		||||
    SC_HANDLE hService = CreateServiceA(
 | 
			
		||||
    wprintf(L"[C] Creating Service: %ls\n", exePath);
 | 
			
		||||
 | 
			
		||||
    SC_HANDLE hService = CreateServiceW(
 | 
			
		||||
            hSCManager,
 | 
			
		||||
            tnlName,
 | 
			
		||||
            serviceName,
 | 
			
		||||
            displayName,
 | 
			
		||||
            SERVICE_ALL_ACCESS,
 | 
			
		||||
            SERVICE_WIN32_OWN_PROCESS,
 | 
			
		||||
@ -53,42 +160,62 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_createTunnel(JNIEnv
 | 
			
		||||
            exePath,
 | 
			
		||||
            NULL,
 | 
			
		||||
            NULL,
 | 
			
		||||
            "Nsi\0TcpIp\0\0",
 | 
			
		||||
            L"Nsi\0TcpIp\0\0",
 | 
			
		||||
            NULL,
 | 
			
		||||
            NULL
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    DWORD sid_info = SERVICE_SID_TYPE_UNRESTRICTED;
 | 
			
		||||
 | 
			
		||||
    if (!ChangeServiceConfig2A(hService, SERVICE_CONFIG_SERVICE_SID_INFO, &sid_info)) {
 | 
			
		||||
        printf("ChangeServiceConfig2W failed (%lu)\n", GetLastError());
 | 
			
		||||
        (*env)->ReleaseStringUTFChars(env, tunnelName, tunnelCharArr);
 | 
			
		||||
        free(tnlName);
 | 
			
		||||
    printf("[C] Changing Service Config\n");
 | 
			
		||||
 | 
			
		||||
    if (!ChangeServiceConfig2W(hService, SERVICE_CONFIG_SERVICE_SID_INFO, &sid_info)) {
 | 
			
		||||
        printf("[C] ChangeServiceConfig2W failed (%lu)\n", GetLastError());
 | 
			
		||||
        (*env)->ReleaseStringChars(env, tunnelName, rawStr);
 | 
			
		||||
        free(serviceName);
 | 
			
		||||
        free(displayName);
 | 
			
		||||
        free(exePath);
 | 
			
		||||
        CloseServiceHandle(hSCManager);
 | 
			
		||||
        CloseServiceHandle(hService);
 | 
			
		||||
        return 3;
 | 
			
		||||
        return 4;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    printf("[C] Cleaning up creation\n");
 | 
			
		||||
 | 
			
		||||
    (*env)->ReleaseStringUTFChars(env, tunnelName, tunnelCharArr);
 | 
			
		||||
    free(tnlName);
 | 
			
		||||
    free(displayName);
 | 
			
		||||
    free(exePath);
 | 
			
		||||
    CloseServiceHandle(hSCManager);
 | 
			
		||||
    CloseServiceHandle(hService);
 | 
			
		||||
    free(serviceName);
 | 
			
		||||
    free(displayName);
 | 
			
		||||
    free(exePath);
 | 
			
		||||
    (*env)->ReleaseStringChars(env, tunnelName, rawStr);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
    printf("[C] Loading tunnel.dll\n");
 | 
			
		||||
 | 
			
		||||
    HMODULE tunnel_lib = LoadLibrary("tunnel.dll");
 | 
			
		||||
    if (!tunnel_lib) abort();
 | 
			
		||||
 | 
			
		||||
    BOOL (_cdecl *tunnel_proc) (_In_ LPCWSTR conf_file);
 | 
			
		||||
    *(FARPROC*) &tunnel_proc = GetProcAddress(tunnel_lib, "WireGuardTunnelService");
 | 
			
		||||
    if (!tunnel_proc) abort();
 | 
			
		||||
 | 
			
		||||
    const jchar *rawString = (*env)->GetStringChars(env, pathToConfig, NULL);
 | 
			
		||||
    LPCWSTR configPath = (LPCWSTR) rawString;
 | 
			
		||||
 | 
			
		||||
    //TODO figure out how to handle this
 | 
			
		||||
    //(*env)->ReleaseStringChars(env, tunnelName, rawStr);
 | 
			
		||||
 | 
			
		||||
    wprintf(L"[C] Calling function with arg: %ls\n", configPath);
 | 
			
		||||
 | 
			
		||||
    return tunnel_proc(configPath);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_deleteTunnel(JNIEnv *env, jobject obj, jstring tunnelName) {
 | 
			
		||||
    const char *nativeString = (*env)->GetStringUTFChars(env, tunnelName, NULL);
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_removeTunnel(JNIEnv *env, jobject obj, jstring tunnelName) {
 | 
			
		||||
    const jchar *nativeString = (*env)->GetStringChars(env, tunnelName, NULL);
 | 
			
		||||
 | 
			
		||||
    char *initialServiceName = "WireGuardTunnel$";
 | 
			
		||||
    char *tnlName = malloc(strlen(initialServiceName) + strlen(nativeString) + 1);
 | 
			
		||||
    strcpy(tnlName, initialServiceName);
 | 
			
		||||
    strcat(tnlName, nativeString);
 | 
			
		||||
    wchar_t *initialServiceName = L"WireGuardTunnel$";
 | 
			
		||||
    wchar_t *tnlName = malloc(sizeof(wchar_t) * (wcslen(initialServiceName) + wcslen(nativeString) + 1));
 | 
			
		||||
    wcscpy(tnlName, initialServiceName);
 | 
			
		||||
    wcscat(tnlName, nativeString);
 | 
			
		||||
 | 
			
		||||
    SC_HANDLE hSCManager = OpenSCManager(
 | 
			
		||||
            NULL,
 | 
			
		||||
@ -100,7 +227,7 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_deleteTunnel(JNIEnv
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SC_HANDLE hService = OpenServiceA(hSCManager, tnlName, DELETE);
 | 
			
		||||
    SC_HANDLE hService = OpenServiceW(hSCManager, tnlName, DELETE);
 | 
			
		||||
    if (hService != NULL) {
 | 
			
		||||
        if (!DeleteService(hService)) {
 | 
			
		||||
            // Handle error
 | 
			
		||||
@ -113,49 +240,8 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_deleteTunnel(JNIEnv
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    CloseServiceHandle(hSCManager);
 | 
			
		||||
    (*env)->ReleaseStringUTFChars(env, tunnelName, nativeString);
 | 
			
		||||
    (*env)->ReleaseStringChars(env, tunnelName, nativeString);
 | 
			
		||||
    free(tnlName);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_initializeWireGuard(JNIEnv *env, jobject obj, jstring configFilePath) {
 | 
			
		||||
    const char *nativeString = (*env)->GetStringUTFChars(env, configFilePath, 0);
 | 
			
		||||
 | 
			
		||||
    int confLength = strlen(nativeString);
 | 
			
		||||
 | 
			
		||||
    (*env)->ReleaseStringUTFChars(env, configFilePath, nativeString);
 | 
			
		||||
 | 
			
		||||
    return confLength;
 | 
			
		||||
 | 
			
		||||
//    const char *nativeConfigFilePath = (*env)->GetStringUTFChars(env, configFilePath, 0);
 | 
			
		||||
 | 
			
		||||
    // Load the WireGuard DLL dynamically
 | 
			
		||||
//    hInstLibrary = LoadLibrary("tunnel.dll");  // Adjust with the actual DLL name
 | 
			
		||||
 | 
			
		||||
//    if (hInstLibrary) {
 | 
			
		||||
        // Example: Load the WireGuard function from DLL
 | 
			
		||||
//        wg_func_t wg_init_func = (wg_func_t) GetProcAddress(hInstLibrary, "WireGuardInitFunction"); // Adjust based on the WireGuard API
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//      if (wg_init_func) {
 | 
			
		||||
//            wg_init_func(nativeConfigFilePath);
 | 
			
		||||
//            (*env)->ReleaseStringUTFChars(env, configFilePath, nativeConfigFilePath);
 | 
			
		||||
//            return 0;  // Success
 | 
			
		||||
//      } else {
 | 
			
		||||
//            printf("Failed to get function from WireGuard DLL\n");
 | 
			
		||||
//            return -2;  // Failed to get function
 | 
			
		||||
//        }
 | 
			
		||||
//    } else {
 | 
			
		||||
//        printf("Failed to load WireGuard DLL\n");
 | 
			
		||||
//        return -1;  // Failed to load DLL
 | 
			
		||||
//    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
JNIEXPORT void JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_cleanup(JNIEnv *env, jobject obj) {
 | 
			
		||||
    printf("Silly goose, this isn't implemented yet!\n");
 | 
			
		||||
 | 
			
		||||
//    if (hInstLibrary) {
 | 
			
		||||
//        FreeLibrary(hInstLibrary);
 | 
			
		||||
//    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,8 @@
 | 
			
		||||
package tech.nevets.tvpn;
 | 
			
		||||
 | 
			
		||||
import com.formdev.flatlaf.FlatDarkLaf;
 | 
			
		||||
import tech.nevets.jconf.JsonConfig;
 | 
			
		||||
import tech.nevets.tvpn.cli.CommandBrigadier;
 | 
			
		||||
import tech.nevets.tvpn.ui.UIManager;
 | 
			
		||||
import tech.nevets.tvpn.wg.WireGuardJNI;
 | 
			
		||||
 | 
			
		||||
@ -9,11 +11,16 @@ import java.io.File;
 | 
			
		||||
 | 
			
		||||
public class Main {
 | 
			
		||||
    private static final Logger LOGGER = new Logger(Main.class);
 | 
			
		||||
 | 
			
		||||
    public static void main(String[] args) {
 | 
			
		||||
        LogOutputStream logOut = new LogOutputStream();
 | 
			
		||||
        Logger.loadLogOutStream(logOut);
 | 
			
		||||
 | 
			
		||||
        JsonConfig conf = new JsonConfig("");
 | 
			
		||||
 | 
			
		||||
        if (args.length > 0) {
 | 
			
		||||
            new CommandBrigadier().execute(args);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            javax.swing.UIManager.setLookAndFeel(new FlatDarkLaf());
 | 
			
		||||
        } catch (UnsupportedLookAndFeelException e) {
 | 
			
		||||
@ -26,9 +33,8 @@ public class Main {
 | 
			
		||||
        UIManager uim = new UIManager(logOut);
 | 
			
		||||
        uim.startLoginFrame();
 | 
			
		||||
 | 
			
		||||
        WireGuardJNI wgjni = new WireGuardJNI();
 | 
			
		||||
        //WireGuardJNI wgjni = new WireGuardJNI();
 | 
			
		||||
        //System.out.println(wgjni.createTunnel("test"));
 | 
			
		||||
        System.out.println(wgjni.deleteTunnel("test"));
 | 
			
		||||
        //System.out.println(wgjni.removeTunnel("test"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,7 @@
 | 
			
		||||
package tech.nevets.tvpn;
 | 
			
		||||
 | 
			
		||||
import tech.nevets.jconf.JsonConfig;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.net.URI;
 | 
			
		||||
@ -10,14 +12,24 @@ import java.util.Map;
 | 
			
		||||
 | 
			
		||||
public class Utils {
 | 
			
		||||
    private static final Logger LOGGER = new Logger(Utils.class);
 | 
			
		||||
    public static final File APP_DIR = new File("./tvpn/");
 | 
			
		||||
 | 
			
		||||
    public static final String WG_CONF_DIR = "C:\\Program Files\\WireGuard\\Data\\Configurations\\";
 | 
			
		||||
    public static final String API_ENDPOINT_BASE = "http://tvpn.lan/testing/";
 | 
			
		||||
    public static final File APP_DIR = new File("C:\\Program Files\\TVPN\\");
 | 
			
		||||
    public static final JsonConfig CONFIG = new JsonConfig(APP_DIR + "/config.json", getConfStr());
 | 
			
		||||
    public static final String API_ENDPOINT_BASE = CONFIG.getString("apiEndpoint");
 | 
			
		||||
 | 
			
		||||
    static {
 | 
			
		||||
        if (!APP_DIR.exists()) APP_DIR.mkdirs();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static String getConfStr() {
 | 
			
		||||
        return """
 | 
			
		||||
                {
 | 
			
		||||
                    "apiEndpoint":"http://tvpn.lan"
 | 
			
		||||
                }
 | 
			
		||||
                """;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String get(URI url, Map<String, String> headers) {
 | 
			
		||||
        HttpClient client = HttpClient.newHttpClient();
 | 
			
		||||
        HttpRequest.Builder reqBuilder = HttpRequest.newBuilder()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										12
									
								
								src/main/java/tech/nevets/tvpn/cli/Command.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/main/java/tech/nevets/tvpn/cli/Command.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
package tech.nevets.tvpn.cli;
 | 
			
		||||
 | 
			
		||||
public interface Command {
 | 
			
		||||
 | 
			
		||||
    void execute(String[] args);
 | 
			
		||||
 | 
			
		||||
    String getName();
 | 
			
		||||
 | 
			
		||||
    String getUsage();
 | 
			
		||||
 | 
			
		||||
    String getDescription();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								src/main/java/tech/nevets/tvpn/cli/CommandBrigadier.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/main/java/tech/nevets/tvpn/cli/CommandBrigadier.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
			
		||||
package tech.nevets.tvpn.cli;
 | 
			
		||||
 | 
			
		||||
import tech.nevets.tvpn.Logger;
 | 
			
		||||
import tech.nevets.tvpn.cli.commands.HelpCmd;
 | 
			
		||||
import tech.nevets.tvpn.cli.commands.InstallTunnelServiceCmd;
 | 
			
		||||
import tech.nevets.tvpn.cli.commands.UninstallTunnelServiceCmd;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public class CommandBrigadier {
 | 
			
		||||
    private static final Logger LOGGER = new Logger(CommandBrigadier.class);
 | 
			
		||||
 | 
			
		||||
    private final List<Command> registeredCommands;
 | 
			
		||||
    private final HelpCmd helpCmd;
 | 
			
		||||
 | 
			
		||||
    public CommandBrigadier() {
 | 
			
		||||
        this.registeredCommands = new ArrayList<>();
 | 
			
		||||
        helpCmd = new HelpCmd(this);
 | 
			
		||||
 | 
			
		||||
        registerCommand(helpCmd);
 | 
			
		||||
        registerCommand(new InstallTunnelServiceCmd());
 | 
			
		||||
        registerCommand(new UninstallTunnelServiceCmd());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void registerCommand(Command cmd) {
 | 
			
		||||
        for (Command c : registeredCommands) {
 | 
			
		||||
            if (c.getName().equals(cmd.getName())) {
 | 
			
		||||
                LOGGER.warn("Command with name " + cmd.getName() + " already registered, skipping.");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        registeredCommands.add(cmd);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void execute(String[] args) {
 | 
			
		||||
        for (Command c : registeredCommands) {
 | 
			
		||||
            if (c.getName().equals(args[0])) {
 | 
			
		||||
                c.execute(args);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        helpCmd.execute(new String[0]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public List<Command> getCommands() {
 | 
			
		||||
        return registeredCommands;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										52
									
								
								src/main/java/tech/nevets/tvpn/cli/commands/HelpCmd.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/main/java/tech/nevets/tvpn/cli/commands/HelpCmd.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
			
		||||
package tech.nevets.tvpn.cli.commands;
 | 
			
		||||
 | 
			
		||||
import tech.nevets.tvpn.cli.Command;
 | 
			
		||||
import tech.nevets.tvpn.cli.CommandBrigadier;
 | 
			
		||||
 | 
			
		||||
public class HelpCmd implements Command {
 | 
			
		||||
    private final CommandBrigadier cb;
 | 
			
		||||
 | 
			
		||||
    public HelpCmd(CommandBrigadier cb) {
 | 
			
		||||
        this.cb = cb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void execute(String[] args) {
 | 
			
		||||
        if (args.length > 0) {
 | 
			
		||||
            for (Command c : cb.getCommands()) {
 | 
			
		||||
                if (!(args.length == 1) && args[1].equals(c.getName())) {
 | 
			
		||||
                    System.out.println("TVPN - Usage Menu [" + c.getName() + "]");
 | 
			
		||||
                    System.out.println(c.getName() + " " + c.getUsage() + ": " + c.getDescription());
 | 
			
		||||
                    System.exit(0);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        StringBuilder sb = new StringBuilder();
 | 
			
		||||
        sb.append("TVPN - Help Menu\n");
 | 
			
		||||
        for (Command c : cb.getCommands()) {
 | 
			
		||||
            sb.append(" - ").append(c.getName())
 | 
			
		||||
                    .append(" ").append(c.getUsage())
 | 
			
		||||
                    .append(": ").append(c.getDescription())
 | 
			
		||||
                    .append("\n");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        System.out.println(sb);
 | 
			
		||||
        System.exit(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getName() {
 | 
			
		||||
        return "help";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getUsage() {
 | 
			
		||||
        return "";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getDescription() {
 | 
			
		||||
        return "Displays the help menu";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,71 @@
 | 
			
		||||
package tech.nevets.tvpn.cli.commands;
 | 
			
		||||
 | 
			
		||||
import tech.nevets.tvpn.Utils;
 | 
			
		||||
import tech.nevets.tvpn.cli.Command;
 | 
			
		||||
import tech.nevets.tvpn.wg.WireGuardJNI;
 | 
			
		||||
 | 
			
		||||
import java.util.regex.Pattern;
 | 
			
		||||
 | 
			
		||||
public class InstallTunnelServiceCmd implements Command {
 | 
			
		||||
    @Override
 | 
			
		||||
    public void execute(String[] args) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        System.out.println("Executing InstallTunnelServiceCmd");
 | 
			
		||||
        String path = Utils.APP_DIR + "/configurations/" + args[1] + ".conf";
 | 
			
		||||
        System.out.println(new WireGuardJNI().installTunnel(args[1], path));
 | 
			
		||||
        System.exit(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getName() {
 | 
			
		||||
        return "/installtunnelservice";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getUsage() {
 | 
			
		||||
        return "(/path/to/tunnel/config)";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getDescription() {
 | 
			
		||||
        return "Creates and starts a WireGuard Tunnel Service";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    String[] reservedNames = new String[]{
 | 
			
		||||
        "CON", "PRN", "AUX", "NUL",
 | 
			
		||||
                "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
 | 
			
		||||
                "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private boolean isReserved(String name) {
 | 
			
		||||
        if (name.isEmpty()) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        for (String s : reservedNames) {
 | 
			
		||||
            if (name.contains(s)) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static final String[] SPECIAL_CHARS = new String[]{"$", "\\", "/", ":", "*", "?", "\"", "'", "<", ">", "|", "\t", "\00"};
 | 
			
		||||
    private boolean hasSpecialChars(String name) {
 | 
			
		||||
        for (String s : SPECIAL_CHARS) {
 | 
			
		||||
            if (name.contains(s)) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static final Pattern PATTERN = Pattern.compile("^[a-zA-Z0-9_=+.-]{1,32}$");
 | 
			
		||||
    private boolean tunnelNameIsValid(String name) {
 | 
			
		||||
        if (isReserved(name) || hasSpecialChars(name)) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        return PATTERN.matcher(name).hasMatch();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,28 @@
 | 
			
		||||
package tech.nevets.tvpn.cli.commands;
 | 
			
		||||
 | 
			
		||||
import tech.nevets.tvpn.cli.Command;
 | 
			
		||||
import tech.nevets.tvpn.wg.WireGuardJNI;
 | 
			
		||||
 | 
			
		||||
public class UninstallTunnelServiceCmd implements Command {
 | 
			
		||||
    @Override
 | 
			
		||||
    public void execute(String[] args) {
 | 
			
		||||
        System.out.println("Executing UnInstallTunnelServiceCmd");
 | 
			
		||||
        System.out.println(new WireGuardJNI().removeTunnel(args[1]));
 | 
			
		||||
        System.exit(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getName() {
 | 
			
		||||
        return "/uninstalltunnelservice";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getUsage() {
 | 
			
		||||
        return "(tunnel name)";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getDescription() {
 | 
			
		||||
        return "Stops and removes WireGuard Tunnel Service";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -13,7 +13,7 @@ public class UIManager {
 | 
			
		||||
 | 
			
		||||
    public UIManager(LogOutputStream logOut) {
 | 
			
		||||
        frame = new JFrame();
 | 
			
		||||
        tabPane = new JTabbedPane();
 | 
			
		||||
        tabPane = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT);
 | 
			
		||||
 | 
			
		||||
        homePanel = new HomePanel();
 | 
			
		||||
        tabPane.addTab("Home", homePanel);
 | 
			
		||||
 | 
			
		||||
@ -10,10 +10,14 @@ public class WireGuardJNI {
 | 
			
		||||
    public native int installAdapter();
 | 
			
		||||
    public native int removeAdapter();
 | 
			
		||||
 | 
			
		||||
    public native int startTunnel(String tunnelName);
 | 
			
		||||
    public native int stopTunnel(String tunnelName);
 | 
			
		||||
    public native int createTunnel(String tunnelName);
 | 
			
		||||
    public native int deleteTunnel(String tunnelName);
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates and starts the WireGuard service
 | 
			
		||||
     * @param tunnelName Name of the tunnel
 | 
			
		||||
     * @param pathToConfig Full path to the tunnel's configuration file
 | 
			
		||||
     * @return 0 if successful, 1 if failed
 | 
			
		||||
     */
 | 
			
		||||
    public native int installTunnel(String tunnelName, String pathToConfig);
 | 
			
		||||
    public native int removeTunnel(String tunnelName);
 | 
			
		||||
 | 
			
		||||
    public native String getConfig(String tunnelName);
 | 
			
		||||
    public native int updateConfig(String tunnelName, String newConfig);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/main/resources/icon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/main/resources/icon.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 17 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/main/resources/icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/main/resources/icon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 216 KiB  | 
		Loading…
	
		Reference in New Issue
	
	Block a user