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
 | 
					# Android studio 3.1+ serialized cache file
 | 
				
			||||||
.idea/caches/build_file_checksums.ser
 | 
					.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 {
 | 
					plugins {
 | 
				
			||||||
    id 'java'
 | 
					    id 'java'
 | 
				
			||||||
    id 'com.github.johnrengelman.shadow' version '8.1.1'
 | 
					    id 'com.github.johnrengelman.shadow' version '8.1.1'
 | 
				
			||||||
 | 
					    id 'edu.sc.seis.launch4j' version '3.0.6'
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
group = 'tech.nevets'
 | 
					group = 'tech.nevets'
 | 
				
			||||||
version = '0.2.0'
 | 
					version = '0.3.0'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
repositories {
 | 
					repositories {
 | 
				
			||||||
    mavenCentral()
 | 
					    mavenCentral()
 | 
				
			||||||
 | 
					    maven {
 | 
				
			||||||
 | 
					        name = "Gitea"
 | 
				
			||||||
 | 
					        url = uri("https://git.nevets.tech/api/packages/Steven/maven")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dependencies {
 | 
					dependencies {
 | 
				
			||||||
@ -18,6 +23,8 @@ dependencies {
 | 
				
			|||||||
    //implementation "com.formdev:flatlaf:3.5.1"
 | 
					    //implementation "com.formdev:flatlaf:3.5.1"
 | 
				
			||||||
    implementation files("libs/gson-2.11.0.jar")
 | 
					    implementation files("libs/gson-2.11.0.jar")
 | 
				
			||||||
    //implementation "com.google.code.gson:gson:2.11.0"
 | 
					    //implementation "com.google.code.gson:gson:2.11.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    implementation "tech.nevets:JConf:0.1.0:no-deps"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tasks.withType(JavaCompile).configureEach {
 | 
					tasks.withType(JavaCompile).configureEach {
 | 
				
			||||||
@ -33,4 +40,17 @@ jar {
 | 
				
			|||||||
                'Main-Class': 'tech.nevets.tvpn.Main'
 | 
					                'Main-Class': 'tech.nevets.tvpn.Main'
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(wireguard_wrapper PRIVATE Rpcrt4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Optionally, you can specify output directory for the compiled library
 | 
					# Optionally, you can specify output directory for the compiled library
 | 
				
			||||||
set_target_properties(wireguard_wrapper PROPERTIES
 | 
					set_target_properties(wireguard_wrapper PROPERTIES
 | 
				
			||||||
        LIBRARY_OUTPUT_DIRECTORY build/lib
 | 
					        LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
 | 
				
			||||||
        OUTPUT_NAME "wireguard_wrapper"
 | 
					        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 <jni.h>
 | 
				
			||||||
 | 
					#include <rpc.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <wchar.h>
 | 
				
			||||||
#include <winsock2.h>
 | 
					#include <winsock2.h>
 | 
				
			||||||
#include <windows.h>
 | 
					#include <windows.h>
 | 
				
			||||||
#include "wireguard.h"
 | 
					#include "wireguard.h"
 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include "tech_nevets_tvpn_wg_WireGuardJNI.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 wchar_t *APP_DIR =  L"C:\\Program Files\\TVPN\\";
 | 
				
			||||||
    const char *tunnelCharArr = (*env)->GetStringUTFChars(env, tunnelName, NULL);
 | 
					
 | 
				
			||||||
    if (tunnelCharArr == NULL) {
 | 
					static WIREGUARD_CREATE_ADAPTER_FUNC *WireGuardCreateAdapter;
 | 
				
			||||||
        return 1;
 | 
					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$";
 | 
					    // Copy the generated UUID into a GUID struct
 | 
				
			||||||
    char *tnlName = malloc(strlen(initialServiceName) + strlen(tunnelCharArr) + 1);
 | 
					    GUID guid = { uuid.Data1, uuid.Data2, uuid.Data3 };
 | 
				
			||||||
    strcpy(tnlName, initialServiceName);
 | 
					    for (int i = 0; i < 8; i++) {
 | 
				
			||||||
    strcat(tnlName, tunnelCharArr);
 | 
					        guid.Data4[i] = uuid.Data4[i];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char *initialDisplayName = "WireGuard Tunnel: ";
 | 
					    return guid;
 | 
				
			||||||
    char *displayName = malloc(strlen(initialDisplayName) + strlen(tunnelCharArr) + 1);
 | 
					}
 | 
				
			||||||
    strcpy(displayName, initialDisplayName);
 | 
					
 | 
				
			||||||
    strcat(displayName, tunnelCharArr);
 | 
					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(
 | 
					    SC_HANDLE hSCManager = OpenSCManager(
 | 
				
			||||||
            NULL,
 | 
					            NULL,
 | 
				
			||||||
@ -30,21 +135,23 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_createTunnel(JNIEnv
 | 
				
			|||||||
            SC_MANAGER_ALL_ACCESS
 | 
					            SC_MANAGER_ALL_ACCESS
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    if (hSCManager == NULL) {
 | 
					    if (hSCManager == NULL) {
 | 
				
			||||||
        printf("OpenSCManager failed (%lu)\n", GetLastError());
 | 
					        printf("[C] OpenSCManager failed (%lu)\n", GetLastError());
 | 
				
			||||||
        return 2;
 | 
					        return 3;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char *params = "TVPN.exe /installtunnelservice ";
 | 
					    wchar_t *params = L"TVPN.exe /installtunnelservice ";
 | 
				
			||||||
    char *conf = ".conf";
 | 
					    wchar_t *conf = L".conf";
 | 
				
			||||||
    char *exePath = malloc(strlen(APP_DIR) + strlen(params) + strlen(tunnelCharArr) + strlen(conf) + 1);
 | 
					    wchar_t *exePath = malloc(sizeof(wchar_t) * (wcslen(APP_DIR) + wcslen(params) + wcslen(tnlName) + wcslen(conf) + 1)); //TODO mem cleanup
 | 
				
			||||||
    strcpy(exePath, APP_DIR);
 | 
					    wcscpy(exePath, APP_DIR);
 | 
				
			||||||
    strcat(exePath, params);
 | 
					    wcscat(exePath, params);
 | 
				
			||||||
    strcat(exePath, tunnelCharArr);
 | 
					    wcscat(exePath, tnlName);
 | 
				
			||||||
    strcat(exePath, conf);
 | 
					    wcscat(exePath, conf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SC_HANDLE hService = CreateServiceA(
 | 
					    wprintf(L"[C] Creating Service: %ls\n", exePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SC_HANDLE hService = CreateServiceW(
 | 
				
			||||||
            hSCManager,
 | 
					            hSCManager,
 | 
				
			||||||
            tnlName,
 | 
					            serviceName,
 | 
				
			||||||
            displayName,
 | 
					            displayName,
 | 
				
			||||||
            SERVICE_ALL_ACCESS,
 | 
					            SERVICE_ALL_ACCESS,
 | 
				
			||||||
            SERVICE_WIN32_OWN_PROCESS,
 | 
					            SERVICE_WIN32_OWN_PROCESS,
 | 
				
			||||||
@ -53,42 +160,62 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_createTunnel(JNIEnv
 | 
				
			|||||||
            exePath,
 | 
					            exePath,
 | 
				
			||||||
            NULL,
 | 
					            NULL,
 | 
				
			||||||
            NULL,
 | 
					            NULL,
 | 
				
			||||||
            "Nsi\0TcpIp\0\0",
 | 
					            L"Nsi\0TcpIp\0\0",
 | 
				
			||||||
            NULL,
 | 
					            NULL,
 | 
				
			||||||
            NULL
 | 
					            NULL
 | 
				
			||||||
            );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DWORD sid_info = SERVICE_SID_TYPE_UNRESTRICTED;
 | 
					    DWORD sid_info = SERVICE_SID_TYPE_UNRESTRICTED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!ChangeServiceConfig2A(hService, SERVICE_CONFIG_SERVICE_SID_INFO, &sid_info)) {
 | 
					    printf("[C] Changing Service Config\n");
 | 
				
			||||||
        printf("ChangeServiceConfig2W failed (%lu)\n", GetLastError());
 | 
					
 | 
				
			||||||
        (*env)->ReleaseStringUTFChars(env, tunnelName, tunnelCharArr);
 | 
					    if (!ChangeServiceConfig2W(hService, SERVICE_CONFIG_SERVICE_SID_INFO, &sid_info)) {
 | 
				
			||||||
        free(tnlName);
 | 
					        printf("[C] ChangeServiceConfig2W failed (%lu)\n", GetLastError());
 | 
				
			||||||
 | 
					        (*env)->ReleaseStringChars(env, tunnelName, rawStr);
 | 
				
			||||||
 | 
					        free(serviceName);
 | 
				
			||||||
        free(displayName);
 | 
					        free(displayName);
 | 
				
			||||||
        free(exePath);
 | 
					        free(exePath);
 | 
				
			||||||
        CloseServiceHandle(hSCManager);
 | 
					        CloseServiceHandle(hSCManager);
 | 
				
			||||||
        CloseServiceHandle(hService);
 | 
					        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(hSCManager);
 | 
				
			||||||
    CloseServiceHandle(hService);
 | 
					    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) {
 | 
					JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_removeTunnel(JNIEnv *env, jobject obj, jstring tunnelName) {
 | 
				
			||||||
    const char *nativeString = (*env)->GetStringUTFChars(env, tunnelName, NULL);
 | 
					    const jchar *nativeString = (*env)->GetStringChars(env, tunnelName, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char *initialServiceName = "WireGuardTunnel$";
 | 
					    wchar_t *initialServiceName = L"WireGuardTunnel$";
 | 
				
			||||||
    char *tnlName = malloc(strlen(initialServiceName) + strlen(nativeString) + 1);
 | 
					    wchar_t *tnlName = malloc(sizeof(wchar_t) * (wcslen(initialServiceName) + wcslen(nativeString) + 1));
 | 
				
			||||||
    strcpy(tnlName, initialServiceName);
 | 
					    wcscpy(tnlName, initialServiceName);
 | 
				
			||||||
    strcat(tnlName, nativeString);
 | 
					    wcscat(tnlName, nativeString);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SC_HANDLE hSCManager = OpenSCManager(
 | 
					    SC_HANDLE hSCManager = OpenSCManager(
 | 
				
			||||||
            NULL,
 | 
					            NULL,
 | 
				
			||||||
@ -100,7 +227,7 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_deleteTunnel(JNIEnv
 | 
				
			|||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SC_HANDLE hService = OpenServiceA(hSCManager, tnlName, DELETE);
 | 
					    SC_HANDLE hService = OpenServiceW(hSCManager, tnlName, DELETE);
 | 
				
			||||||
    if (hService != NULL) {
 | 
					    if (hService != NULL) {
 | 
				
			||||||
        if (!DeleteService(hService)) {
 | 
					        if (!DeleteService(hService)) {
 | 
				
			||||||
            // Handle error
 | 
					            // Handle error
 | 
				
			||||||
@ -113,49 +240,8 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_deleteTunnel(JNIEnv
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CloseServiceHandle(hSCManager);
 | 
					    CloseServiceHandle(hSCManager);
 | 
				
			||||||
    (*env)->ReleaseStringUTFChars(env, tunnelName, nativeString);
 | 
					    (*env)->ReleaseStringChars(env, tunnelName, nativeString);
 | 
				
			||||||
    free(tnlName);
 | 
					    free(tnlName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    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;
 | 
					package tech.nevets.tvpn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.formdev.flatlaf.FlatDarkLaf;
 | 
					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.ui.UIManager;
 | 
				
			||||||
import tech.nevets.tvpn.wg.WireGuardJNI;
 | 
					import tech.nevets.tvpn.wg.WireGuardJNI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -9,11 +11,16 @@ import java.io.File;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
public class Main {
 | 
					public class Main {
 | 
				
			||||||
    private static final Logger LOGGER = new Logger(Main.class);
 | 
					    private static final Logger LOGGER = new Logger(Main.class);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static void main(String[] args) {
 | 
					    public static void main(String[] args) {
 | 
				
			||||||
        LogOutputStream logOut = new LogOutputStream();
 | 
					        LogOutputStream logOut = new LogOutputStream();
 | 
				
			||||||
        Logger.loadLogOutStream(logOut);
 | 
					        Logger.loadLogOutStream(logOut);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        JsonConfig conf = new JsonConfig("");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (args.length > 0) {
 | 
				
			||||||
 | 
					            new CommandBrigadier().execute(args);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            javax.swing.UIManager.setLookAndFeel(new FlatDarkLaf());
 | 
					            javax.swing.UIManager.setLookAndFeel(new FlatDarkLaf());
 | 
				
			||||||
        } catch (UnsupportedLookAndFeelException e) {
 | 
					        } catch (UnsupportedLookAndFeelException e) {
 | 
				
			||||||
@ -26,9 +33,8 @@ public class Main {
 | 
				
			|||||||
        UIManager uim = new UIManager(logOut);
 | 
					        UIManager uim = new UIManager(logOut);
 | 
				
			||||||
        uim.startLoginFrame();
 | 
					        uim.startLoginFrame();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        WireGuardJNI wgjni = new WireGuardJNI();
 | 
					        //WireGuardJNI wgjni = new WireGuardJNI();
 | 
				
			||||||
        //System.out.println(wgjni.createTunnel("test"));
 | 
					        //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;
 | 
					package tech.nevets.tvpn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import tech.nevets.jconf.JsonConfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.File;
 | 
					import java.io.File;
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
import java.net.URI;
 | 
					import java.net.URI;
 | 
				
			||||||
@ -10,14 +12,24 @@ import java.util.Map;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
public class Utils {
 | 
					public class Utils {
 | 
				
			||||||
    private static final Logger LOGGER = new Logger(Utils.class);
 | 
					    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 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 {
 | 
					    static {
 | 
				
			||||||
        if (!APP_DIR.exists()) APP_DIR.mkdirs();
 | 
					        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) {
 | 
					    public static String get(URI url, Map<String, String> headers) {
 | 
				
			||||||
        HttpClient client = HttpClient.newHttpClient();
 | 
					        HttpClient client = HttpClient.newHttpClient();
 | 
				
			||||||
        HttpRequest.Builder reqBuilder = HttpRequest.newBuilder()
 | 
					        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) {
 | 
					    public UIManager(LogOutputStream logOut) {
 | 
				
			||||||
        frame = new JFrame();
 | 
					        frame = new JFrame();
 | 
				
			||||||
        tabPane = new JTabbedPane();
 | 
					        tabPane = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        homePanel = new HomePanel();
 | 
					        homePanel = new HomePanel();
 | 
				
			||||||
        tabPane.addTab("Home", homePanel);
 | 
					        tabPane.addTab("Home", homePanel);
 | 
				
			||||||
 | 
				
			|||||||
@ -10,10 +10,14 @@ public class WireGuardJNI {
 | 
				
			|||||||
    public native int installAdapter();
 | 
					    public native int installAdapter();
 | 
				
			||||||
    public native int removeAdapter();
 | 
					    public native int removeAdapter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public native int startTunnel(String tunnelName);
 | 
					    /**
 | 
				
			||||||
    public native int stopTunnel(String tunnelName);
 | 
					     * Creates and starts the WireGuard service
 | 
				
			||||||
    public native int createTunnel(String tunnelName);
 | 
					     * @param tunnelName Name of the tunnel
 | 
				
			||||||
    public native int deleteTunnel(String tunnelName);
 | 
					     * @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 String getConfig(String tunnelName);
 | 
				
			||||||
    public native int updateConfig(String tunnelName, String newConfig);
 | 
					    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