├── .clang-format ├── .editorconfig ├── .git-blame-ignore-revs ├── .github └── workflows │ └── msbuild.yml ├── .gitignore ├── .kateconfig ├── .pre-commit-config.yaml ├── BUILD.rst ├── CHANGES.rst ├── CMakeLists.txt ├── CMakePresets.json ├── COPYING ├── COPYRIGHT.GPL ├── Makefile.am ├── README.rst ├── access.c ├── access.h ├── as.c ├── as.h ├── bootstrap ├── chartable.h ├── config-msvc.h.in ├── config_parser.c ├── config_parser.h ├── configure.ac ├── echo.c ├── echo.h ├── env_set.c ├── env_set.h ├── localization.c ├── localization.h ├── main.c ├── main.h ├── manage.c ├── manage.h ├── misc.c ├── misc.h ├── openvpn-gui-res.h ├── openvpn.c ├── openvpn.h ├── openvpn_config.c ├── openvpn_config.h ├── options.c ├── options.h ├── pkcs11.c ├── pkcs11.h ├── plap ├── Makefile.am ├── openvpn-plap-install.reg ├── openvpn-plap-res.rc ├── openvpn-plap-uninstall.reg ├── openvpn-plap.manifest ├── openvpn_plap.def ├── plap_common.c ├── plap_common.h ├── plap_connection.c ├── plap_connection.h ├── plap_dll.c ├── plap_dll.h ├── plap_provider.c ├── resource.h ├── stub.c ├── test-plap-res.rc ├── test-plap.manifest ├── test_plap.cpp ├── ui_glue.c └── ui_glue.h ├── proxy.c ├── proxy.h ├── qr.c ├── qr.h ├── qrcodegen ├── qrcodegen.c └── qrcodegen.h ├── registry.c ├── registry.h ├── renovate.json ├── res ├── connected.ico ├── connecting.ico ├── disconnected.ico ├── eye-stroke.ico ├── eye.ico ├── openvpn-gui-res-cs.rc ├── openvpn-gui-res-de.rc ├── openvpn-gui-res-dk.rc ├── openvpn-gui-res-en.rc ├── openvpn-gui-res-es.rc ├── openvpn-gui-res-fa.rc ├── openvpn-gui-res-fi.rc ├── openvpn-gui-res-fr.rc ├── openvpn-gui-res-it.rc ├── openvpn-gui-res-jp.rc ├── openvpn-gui-res-kr.rc ├── openvpn-gui-res-nl.rc ├── openvpn-gui-res-no.rc ├── openvpn-gui-res-pl.rc ├── openvpn-gui-res-pt.rc ├── openvpn-gui-res-ru.rc ├── openvpn-gui-res-se.rc ├── openvpn-gui-res-tr.rc ├── openvpn-gui-res-ua.rc ├── openvpn-gui-res-zh-hans.rc ├── openvpn-gui-res-zh-hant.rc ├── openvpn-gui-res.rc ├── openvpn-gui.ico ├── openvpn-gui.manifest ├── reconnecting.ico └── tileimage.bmp ├── save_pass.c ├── save_pass.h ├── scripts.c ├── scripts.h ├── service.c ├── service.h ├── tray.c ├── tray.h ├── vcpkg.json ├── viewlog.c └── viewlog.h /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Mozilla 3 | AccessModifierOffset: '-4' 4 | AlignAfterOpenBracket: Align 5 | AlignConsecutiveMacros: 6 | Enabled: true 7 | AcrossEmptyLines: true 8 | AcrossComments: true 9 | AlignEscapedNewlines: Left 10 | AlignOperands: true 11 | AlignTrailingComments: 12 | Kind: Always 13 | OverEmptyLines: 1 14 | AllowAllParametersOfDeclarationOnNextLine: true 15 | AllowShortBlocksOnASingleLine: Never 16 | AllowShortCaseLabelsOnASingleLine: false 17 | AllowShortFunctionsOnASingleLine: None 18 | AllowShortIfStatementsOnASingleLine: Never 19 | AllowShortLoopsOnASingleLine: false 20 | AlwaysBreakAfterReturnType: None 21 | BreakBeforeBinaryOperators: NonAssignment 22 | BreakBeforeBraces: Allman 23 | BreakBeforeTernaryOperators: true 24 | BreakStringLiterals: false 25 | ColumnLimit: '100' 26 | ContinuationIndentWidth: '4' 27 | DerivePointerAlignment: false 28 | IndentCaseLabels: true 29 | IndentGotoLabels: false 30 | IndentWidth: '4' 31 | IndentWrappedFunctionNames: false 32 | KeepEmptyLinesAtTheStartOfBlocks: false 33 | Language: Cpp 34 | MaxEmptyLinesToKeep: '2' 35 | PointerAlignment: Right 36 | ReflowComments: true 37 | SortIncludes: false 38 | SpaceAfterCStyleCast: false 39 | SpaceBeforeAssignmentOperators: true 40 | SpaceBeforeParens: ControlStatements 41 | SpacesBeforeTrailingComments: '2' 42 | SpacesInParens: Never 43 | TabWidth: '4' 44 | UseTab: Never 45 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig: http://EditorConfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | indent_size = 4 7 | indent_style = space 8 | trim_trailing_whitespace = true 9 | 10 | [*.sh] 11 | end_of_line = lf 12 | 13 | [*.yml] 14 | indent_size = 2 15 | 16 | [{Makefile,Makefile.*}] 17 | indent_style = tab 18 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # This FILE allows git blame to ignore reformatting changes and instead 2 | # shows the previous commit that changed the line. 3 | # 4 | # To avoid manually building the list of commits this commit 5 | # adds a file with a list of reformatting commits. TO use: 6 | # 7 | # git blame --ignore-revs-file=.git-blame-ignore-revs file 8 | # 9 | # or to automatically always use the file 10 | # 11 | # git config blame.ignoreRevsFile .git-blame-ignore-revs 12 | 13 | # Initial formatting with uncrustify 14 | 2cb3c6e4173c07e08bb2d6b440ad09fa76ac4182 15 | 16 | # Switch from uncrustify to clang-format 17 | d2bcb940dcf958ea5457e158b379af60bb9cc4e2 18 | -------------------------------------------------------------------------------- /.github/workflows/msbuild.yml: -------------------------------------------------------------------------------- 1 | # The name of our workflow 2 | name: Build 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | checkformat: 7 | name: "Check code style with clang-format" 8 | runs-on: ubuntu-24.04 9 | steps: 10 | - name: Install pre-commit 11 | run: pip3 install pre-commit 12 | - name: Checkout OpenVPN-GUI 13 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 14 | - name: Run pre-commit 15 | run: pre-commit run -a || true 16 | - name: Check for changes 17 | run: git diff --output=cf-changes.patch 18 | - name: Show changes on standard output 19 | run: git diff 20 | - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4 21 | with: 22 | name: cf-changes.patch 23 | path: cf-changes.patch 24 | - name: Set job status 25 | run: test ! -s cf-changes.patch 26 | 27 | msvc: 28 | strategy: 29 | matrix: 30 | arch: [x86, x64, arm64] 31 | conf: 32 | - name: "" 33 | value: "release" 34 | ovpn3: 35 | - preset: "" 36 | name: "" 37 | upload_name: "" 38 | - preset: -ovpn3 39 | name: "- ovpn3" 40 | upload_name: "_ovpn3" 41 | include: 42 | - conf: 43 | name: " ASAN" 44 | value: "asan" 45 | arch: x64 46 | 47 | name: 'msvc - ${{matrix.arch}} ${{ matrix.ovpn3.name }}${{ matrix.conf.name }}' 48 | runs-on: windows-latest 49 | steps: 50 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 51 | - uses: lukka/get-cmake@latest 52 | 53 | - name: Restore artifacts, or setup vcpkg (do not install any package) 54 | uses: lukka/run-vcpkg@v11 55 | with: 56 | vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg' 57 | vcpkgGitCommitId: d5ec528843d29e3a52d745a64b469f810b2cedbf 58 | 59 | - name: Run CMake consuming CMakePreset.json and vcpkg.json by mean of vcpkg. 60 | uses: lukka/run-cmake@v10 61 | with: 62 | configurePreset: '${{ matrix.arch }}${{ matrix.ovpn3.preset }}' 63 | buildPreset: '${{ matrix.arch }}-${{ matrix.conf.value }}${{ matrix.ovpn3.preset }}' 64 | 65 | - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4 66 | with: 67 | name: openvpn-gui_${{ matrix.arch }}_${{ matrix.conf.value }}${{ matrix.ovpn3.upload_name }} 68 | path: | 69 | out/build/${{ matrix.arch }}${{ matrix.ovpn3.preset }}/${{ matrix.conf.value }}/*.dll 70 | out/build/${{ matrix.arch }}${{ matrix.ovpn3.preset }}/${{ matrix.conf.value }}/*.exe 71 | 72 | mingw: 73 | strategy: 74 | fail-fast: false 75 | matrix: 76 | target: [mingw64, mingw] 77 | include: 78 | - target: mingw64 79 | chost: x86_64-w64-mingw32 80 | - target: mingw 81 | chost: i686-w64-mingw32 82 | 83 | name: "gcc-mingw - ${{matrix.target}}" 84 | runs-on: ubuntu-24.04 85 | 86 | env: 87 | MAKEFLAGS: -j3 88 | 89 | steps: 90 | - name: Install dependencies 91 | run: sudo apt update && sudo apt install -y mingw-w64 libtool automake autoconf 92 | - name: Checkout 93 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 94 | 95 | - name: autoconf 96 | run: autoreconf -fvi 97 | 98 | - name: configure 99 | run: ./configure --host=${{ matrix.chost }} 100 | 101 | - name: make 102 | run: make 103 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.[oa] 2 | *.exe 3 | *.obj 4 | *.so 5 | *~ 6 | *.idb 7 | *.suo 8 | *.ncb 9 | *.vcproj.* 10 | *.log 11 | *.tar.gz 12 | *.bak 13 | 14 | .deps 15 | Makefile 16 | Makefile.in 17 | aclocal.m4 18 | autodefs.h 19 | autom4te.cache 20 | compile 21 | config.guess 22 | config.h 23 | config.h.in 24 | config.log 25 | config.status 26 | config.sub 27 | configure 28 | configure.h 29 | depcomp 30 | stamp-h1 31 | install-sh 32 | libtool 33 | ltmain.sh 34 | missing 35 | 36 | plap/credentialprovider.h 37 | 38 | .vs 39 | x64 40 | Debug 41 | out 42 | build -------------------------------------------------------------------------------- /.kateconfig: -------------------------------------------------------------------------------- 1 | kate: backspace-indents false; tab-indents true; replace-tabs true; 2 | kate: tab-width 4; indent-width 4; remove-trailing-space true; 3 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/mirrors-clang-format 3 | rev: 'v19.1.4' 4 | hooks: 5 | - id: clang-format 6 | files: \.[ch]$ 7 | -------------------------------------------------------------------------------- /BUILD.rst: -------------------------------------------------------------------------------- 1 | How to build with MSVC 2 | ====================== 3 | 4 | This is the recommended way of building openvpn-gui on Windows, which is also used when doing OpenVPN Windows releases. 5 | 6 | Prerequisites 7 | ------------- 8 | 9 | - Visual Studio 2022 (see below for details) 10 | - CMake 11 | - vcpkg (add the environment variable ``VCPKG_ROOT`` which points to vcpkg installation) 12 | 13 | Visual Studio Components 14 | ------------------------ 15 | 16 | Having the Build Tools is enough, you do not need the actual IDE. 17 | In addition to the Microsoft.VisualStudio.Workload.VCTools workload, 18 | you might also need the following additional components dependending 19 | on which architectures you build for: 20 | 21 | * Microsoft.VisualStudio.Component.VC.ATL.Spectre 22 | * Microsoft.VisualStudio.Component.VC.ATLMFC.Spectre 23 | * Microsoft.VisualStudio.Component.UWP.VC.ARM64 24 | * Microsoft.VisualStudio.Component.VC.Tools.ARM64 25 | * Microsoft.VisualStudio.Component.VC.ATL.ARM64.Spectre 26 | * Microsoft.VisualStudio.Component.VC.MFC.ARM64.Spectre 27 | * Microsoft.VisualStudio.Component.VC.Runtimes.ARM64.Spectre 28 | * Microsoft.VisualStudio.Component.VC.Runtimes.x86.x64.Spectre 29 | 30 | Build steps 31 | ----------- 32 | 33 | Run inside MSVC command prompt: 34 | 35 | .. code-block:: 36 | 37 | c:\Temp\openvpn-gui>cmake -S . --preset x64 38 | c:\Temp\openvpn-gui>cmake --build --preset x64-release 39 | 40 | To see all presets, run: 41 | 42 | .. code-block:: 43 | 44 | C:\Users\lev\Projects\openvpn-gui>cmake -S c:\Users\lev\Projects\openvpn-gui --list-presets 45 | Available configure presets: 46 | "x64" 47 | "arm64" 48 | "x86" 49 | "x64-ovpn3" 50 | "arm64-ovpn3" 51 | "x86-ovpn3" 52 | 53 | You could also open CMake project from MSVC IDE and build from there. 54 | 55 | How to build using Cygwin 56 | ========================= 57 | 58 | Cygwin provides ports of many GNU/Linux tools and a POSIX API layer. This is 59 | the most complete way to get the GNU/Linux terminal feel under Windows. 60 | Cygwin has a setup that helps you install all the tools you need. 61 | 62 | This document describes how to build openvpn-gui using Cygwin. It cross-compiles 63 | a native Windows executable, using the MinGW-w64 compilers that are available 64 | as packages in the Cygwin repository. 65 | 66 | 67 | Required packages 68 | ----------------- 69 | 70 | To build openvpn-gui you need to have these packages installed, including 71 | their dependencies. You can install these packages using the standard 72 | ``setup.exe`` of Cygwin. 73 | 74 | - autoconf 75 | - automake 76 | - pkg-config 77 | - make 78 | - mingw64-x86_64-gcc-core 79 | 80 | 81 | Build 82 | ----- 83 | 84 | To build use these commands: 85 | 86 | .. code-block:: bash 87 | 88 | autoreconf -iv 89 | ./configure --host=x86_64-w64-mingw32 90 | make 91 | 92 | 93 | 32-bit or 64-bit 94 | ---------------- 95 | 96 | The above describes how to build the 64-bit version of openvpn-gui. If you 97 | want to build the 32-bit version, simply replace ``x86_64`` with ``i686``. 98 | 99 | Both 32-bit and 64-bit version of Cygwin can build the 32-bit and 64-bit 100 | version of ``openvpn-gui.exe``. Just install the packages you need and use 101 | the right ``--host`` option. 102 | 103 | 104 | How to build using MSYS2 105 | ======================== 106 | 107 | One-time preperation 108 | -------------------- 109 | 110 | Install MSYS2. Instructions and prerequisites can be found on the official website: https://msys2.github.io/ 111 | 112 | Once installed use the ``mingw64.exe`` provided by MSYS2. 113 | 114 | Update the base MSYS2 system until no further updates are available using: 115 | 116 | .. code-block:: bash 117 | 118 | pacman -Syu 119 | 120 | You may have to restart your MINGW64 prompt between those updates. 121 | 122 | Now install the required development packages: 123 | 124 | .. code-block:: bash 125 | 126 | pacman -S base-devel mingw-w64-x86_64-{toolchain} 127 | 128 | Build 129 | ----- 130 | 131 | You can build using these commands: 132 | 133 | .. code-block:: bash 134 | 135 | autoreconf -iv 136 | ./configure 137 | make 138 | 139 | 32-bit or 64-bit 140 | ---------------- 141 | 142 | The above describes how to build the 64-bit version of openvpn-gui. 143 | If you want to build the 32-bit version, use the ``mingw32.exe`` and in the package names simply replace ``x86_64`` with ``i686``. 144 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | option(CLI_OVPN3 "Build ${PROJECT_NAME} with OpenVPN3 support" OFF) 2 | 3 | cmake_minimum_required(VERSION 3.10) 4 | 5 | project(openvpn-gui C CXX) 6 | 7 | add_executable(${PROJECT_NAME} WIN32 8 | access.c 9 | echo.c 10 | env_set.c 11 | localization.c 12 | main.c 13 | manage.c 14 | misc.c 15 | openvpn.c 16 | openvpn_config.c 17 | options.c 18 | proxy.c 19 | registry.c 20 | save_pass.c 21 | scripts.c 22 | service.c 23 | tray.c 24 | viewlog.c 25 | as.c 26 | pkcs11.c 27 | config_parser.c 28 | qr.c 29 | qrcodegen/qrcodegen.c 30 | res/openvpn-gui-res.rc 31 | ) 32 | 33 | set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG") 34 | set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} /guard:cf /Qspectre") 35 | 36 | list(APPEND CMAKE_CONFIGURATION_TYPES Asan) 37 | 38 | set(CMAKE_C_FLAGS_ASAN 39 | "${CMAKE_C_FLAGS_DEBUG} /fsanitize=address" CACHE STRING 40 | "Flags used by the C compiler during AddressSanitizer builds." FORCE) 41 | 42 | set(CMAKE_EXE_LINKER_FLAGS_ASAN 43 | "${CMAKE_EXE_LINKER_FLAGS_DEBUG}" CACHE STRING 44 | "Flags used by the linker during AddressSanitizer builds." FORCE) 45 | 46 | set(CMAKE_SHARED_LINKER_FLAGS_ASAN 47 | "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE STRING 48 | "Flags used by the linker during AddressSanitizer builds." FORCE) 49 | 50 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /guard:cf /DYNAMICBASE") 51 | 52 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4996 /wd4267 /wd4244") 53 | 54 | if(NOT (${CMAKE_C_COMPILER_ARCHITECTURE_ID} STREQUAL "ARM64")) 55 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /CETCOMPAT") 56 | endif() 57 | 58 | target_link_libraries(${PROJECT_NAME} PRIVATE 59 | Wtsapi32.lib 60 | Netapi32.lib 61 | ws2_32.lib 62 | Winhttp.lib 63 | Secur32.lib 64 | Comctl32.lib 65 | Crypt32.lib 66 | Shlwapi.lib 67 | Advapi32.lib 68 | Shell32.lib 69 | Gdi32.lib 70 | Comdlg32.lib 71 | Ole32.lib 72 | Cryptui.lib 73 | Wininet.lib) 74 | 75 | target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) 76 | 77 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO") 78 | set(CMAKE_RC_FLAGS "/D \"HAVE_CONFIG_H\" /D \"_MSC_VER\"") 79 | 80 | function(get_version_from_configure regex_arg ret) 81 | file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" VERSION_STR REGEX ${regex_arg}) 82 | string(REGEX MATCH ${regex_arg} VERSION_STR "${VERSION_STR}") 83 | set("${ret}" ${CMAKE_MATCH_1} PARENT_SCOPE) 84 | endfunction() 85 | 86 | get_version_from_configure("_GUI_VERSION_MAJOR\\], \\[([0-9]+)\\]" GUI_VERSION_MAJOR) 87 | get_version_from_configure("_GUI_VERSION_MINOR\\], \\[([0-9]+)\\]" GUI_VERSION_MINOR) 88 | 89 | configure_file(config-msvc.h.in config.h) 90 | 91 | target_compile_definitions(${PROJECT_NAME} PRIVATE 92 | _UNICODE 93 | UNICODE 94 | WIN32_LEAN_AND_MEAN 95 | HAVE_CONFIG_H) 96 | 97 | if (${CLI_OVPN3}) 98 | find_package(json-c REQUIRED) 99 | 100 | target_link_libraries(${PROJECT_NAME} PRIVATE 101 | json-c::json-c) 102 | 103 | target_compile_definitions(${PROJECT_NAME} PRIVATE 104 | ENABLE_OVPN3) 105 | endif () 106 | 107 | if (NOT PROJECT_NAME_PLAP) 108 | set(PROJECT_NAME_PLAP "libopenvpn_plap") 109 | endif() 110 | 111 | add_library(${PROJECT_NAME_PLAP} SHARED 112 | localization.c 113 | manage.c 114 | misc.c 115 | openvpn.c 116 | openvpn_config.c 117 | options.c 118 | proxy.c 119 | pkcs11.c 120 | registry.c 121 | config_parser.c 122 | service.c 123 | qr.c 124 | qrcodegen/qrcodegen.c 125 | plap/ui_glue.c 126 | plap/stub.c 127 | plap/plap_common.c 128 | plap/plap_provider.c 129 | plap/plap_connection.c 130 | plap/plap_dll.c 131 | plap/openvpn_plap.def 132 | plap/openvpn-plap-res.rc) 133 | 134 | target_link_libraries(${PROJECT_NAME_PLAP} PRIVATE 135 | ws2_32.lib 136 | Comctl32.lib 137 | Winhttp.lib 138 | Crypt32.lib 139 | Ole32.lib 140 | Shlwapi.lib 141 | Secur32.lib 142 | Gdi32.lib 143 | Cryptui.lib 144 | Rpcrt4.lib) 145 | 146 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /MANIFEST:NO") 147 | target_include_directories(${PROJECT_NAME_PLAP} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) 148 | target_compile_definitions(${PROJECT_NAME_PLAP} PRIVATE 149 | _UNICODE 150 | UNICODE 151 | WIN32_LEAN_AND_MEAN 152 | HAVE_CONFIG_H) 153 | 154 | if (NOT TEST_PLAP_EXE) 155 | set(TEST_PLAP_EXE "test_plap") 156 | endif() 157 | 158 | add_executable(${TEST_PLAP_EXE} 159 | plap/test_plap.cpp 160 | plap/plap_common.c) 161 | 162 | target_link_libraries(${TEST_PLAP_EXE} PRIVATE 163 | Rpcrt4 164 | Ole32 165 | Gdi32) 166 | 167 | target_include_directories(${TEST_PLAP_EXE} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) 168 | target_compile_definitions(${TEST_PLAP_EXE} PRIVATE 169 | _UNICODE 170 | UNICODE 171 | WIN32_LEAN_AND_MEAN 172 | HAVE_CONFIG_H) 173 | 174 | target_compile_options(${PROJECT_NAME} PRIVATE "$<$:/Zi>") 175 | target_link_options(${PROJECT_NAME} PRIVATE 176 | "$<$:/DEBUG:FULL>" 177 | "$<$:/OPT:REF>" 178 | "$<$:/OPT:ICF>") 179 | 180 | target_link_options(${TEST_PLAP_EXE} PRIVATE 181 | "/MANIFEST:EMBED" 182 | "/MANIFESTINPUT:${CMAKE_SOURCE_DIR}/plap/test-plap.manifest") 183 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "configurePresets": [ 4 | { 5 | "name": "base", 6 | "hidden": true, 7 | "binaryDir": "${sourceDir}/out/build/${presetName}", 8 | "generator": "Visual Studio 17 2022", 9 | "cacheVariables": { 10 | "CMAKE_TOOLCHAIN_FILE": { 11 | "value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", 12 | "type": "FILEPATH" 13 | } 14 | }, 15 | "vendor": { "microsoft.com/VisualStudioSettings/CMake/1.0": { "hostOS": [ "Windows" ] } } 16 | }, 17 | { 18 | "name": "x64", 19 | "inherits": "base", 20 | "architecture": { 21 | "value": "x64" 22 | } 23 | }, 24 | { 25 | "name": "arm64", 26 | "inherits": "base", 27 | "architecture": { 28 | "value": "arm64" 29 | } 30 | }, 31 | { 32 | "name": "x86", 33 | "inherits": "base", 34 | "architecture": { 35 | "value": "Win32" 36 | } 37 | }, 38 | { 39 | "name": "ovpn3", 40 | "hidden": true, 41 | "cacheVariables": { 42 | "CLI_OVPN3": "ON" 43 | } 44 | }, 45 | { 46 | "name": "x64-ovpn3", 47 | "inherits": [ "x64", "ovpn3" ] 48 | }, 49 | { 50 | "name": "arm64-ovpn3", 51 | "inherits": [ "arm64", "ovpn3" ] 52 | }, 53 | { 54 | "name": "x86-ovpn3", 55 | "inherits": [ "x86", "ovpn3" ] 56 | } 57 | ], 58 | "buildPresets": [ 59 | { 60 | "name": "x64-release", 61 | "configurePreset": "x64", 62 | "configuration": "Release" 63 | }, 64 | { 65 | "name": "x86-release", 66 | "configurePreset": "x86", 67 | "configuration": "Release" 68 | }, 69 | { 70 | "name": "arm64-release", 71 | "configurePreset": "arm64", 72 | "configuration": "Release" 73 | }, 74 | { 75 | "name": "x64-debug", 76 | "configurePreset": "x64", 77 | "configuration": "Debug" 78 | }, 79 | { 80 | "name": "x64-asan", 81 | "configurePreset": "x64", 82 | "configuration": "Asan" 83 | }, 84 | { 85 | "name": "x86-debug", 86 | "configurePreset": "x86", 87 | "configuration": "Debug" 88 | }, 89 | { 90 | "name": "arm64-debug", 91 | "configurePreset": "arm64", 92 | "configuration": "Debug" 93 | }, 94 | { 95 | "name": "x64-release-ovpn3", 96 | "configurePreset": "x64-ovpn3", 97 | "configuration": "Release" 98 | }, 99 | { 100 | "name": "x86-release-ovpn3", 101 | "configurePreset": "x86-ovpn3", 102 | "configuration": "Release" 103 | }, 104 | { 105 | "name": "arm64-release-ovpn3", 106 | "configurePreset": "arm64-ovpn3", 107 | "configuration": "Release" 108 | }, 109 | { 110 | "name": "x64-debug-ovpn3", 111 | "configurePreset": "x64-ovpn3", 112 | "configuration": "Debug" 113 | }, 114 | { 115 | "name": "x86-debug-ovpn3", 116 | "configurePreset": "x86-ovpn3", 117 | "configuration": "Debug" 118 | }, 119 | { 120 | "name": "arm64-debug-ovpn3", 121 | "configurePreset": "arm64-ovpn3", 122 | "configuration": "Debug" 123 | } 124 | ] 125 | } 126 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | OpenVPN GUI -- A Windows GUI for OpenVPN 2 | 3 | Copyright (C) 2004-2005 by Mathias Sundman 4 | 5 | 6 | OpenVPN GUI is distributed under GPL license. 7 | (see COPYRIGHT.GPL) 8 | 9 | Parts of the source code for OpenVPN GUI is taken from 10 | openvpnserv.c included with the OpenVPN [1] distribution. 11 | 12 | [1] OpenVPN is copyrighted by OpenVPN Solutions LLC , 13 | and distributed under GPL license. 14 | 15 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # OpenVPN-GUI -- A Windows GUI for OpenVPN. 2 | # 3 | # Copyright (C) 2004 Mathias Sundman 4 | # 2010 Heiko Hund 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program (see the file COPYING included with this 18 | # distribution); if not, write to the Free Software Foundation, Inc., 19 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | RCCOMPILE = $(WINDRES) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ 22 | $(AM_CPPFLAGS) $(CPPFLAGS) 23 | 24 | AUTOMAKE_OPTIONS = foreign 1.9 25 | 26 | DISTCHECK_CONFIGURE_FLAGS = --host=x86_64-w64-mingw32 27 | 28 | MAINTAINERCLEANFILES = \ 29 | config.log config.status \ 30 | $(srcdir)/Makefile.in $(srcdir)/configure \ 31 | $(srcdir)/config.h.in $(srcdir)/config.h.in~\ 32 | $(srcdir)/install-sh $(srcdir)/missing \ 33 | $(srcdir)/depcomp $(srcdir)/aclocal.m4 \ 34 | $(srcdir)/config.guess $(srcdir)/config.sub \ 35 | $(srcdir)/compile 36 | 37 | SUBDIRS = . plap 38 | bin_PROGRAMS = openvpn-gui 39 | 40 | dist_doc_DATA = \ 41 | BUILD.rst \ 42 | CHANGES.rst \ 43 | COPYRIGHT.GPL \ 44 | COPYING \ 45 | README.rst 46 | 47 | AM_CPPFLAGS = -D_UNICODE $(JSON_CFLAGS) 48 | AM_CFLAGS = -municode 49 | 50 | openvpn_gui_RESOURCES = \ 51 | res/openvpn-gui-res.rc \ 52 | res/openvpn-gui-res-cs.rc \ 53 | res/openvpn-gui-res-de.rc \ 54 | res/openvpn-gui-res-dk.rc \ 55 | res/openvpn-gui-res-en.rc \ 56 | res/openvpn-gui-res-es.rc \ 57 | res/openvpn-gui-res-fa.rc \ 58 | res/openvpn-gui-res-fi.rc \ 59 | res/openvpn-gui-res-fr.rc \ 60 | res/openvpn-gui-res-it.rc \ 61 | res/openvpn-gui-res-jp.rc \ 62 | res/openvpn-gui-res-kr.rc \ 63 | res/openvpn-gui-res-nl.rc \ 64 | res/openvpn-gui-res-no.rc \ 65 | res/openvpn-gui-res-pl.rc \ 66 | res/openvpn-gui-res-pt.rc \ 67 | res/openvpn-gui-res-ru.rc \ 68 | res/openvpn-gui-res-se.rc \ 69 | res/openvpn-gui-res-tr.rc \ 70 | res/openvpn-gui-res-ua.rc \ 71 | res/openvpn-gui-res-zh-hans.rc \ 72 | res/openvpn-gui-res-zh-hant.rc \ 73 | res/connected.ico \ 74 | res/connecting.ico \ 75 | res/disconnected.ico \ 76 | res/openvpn-gui.ico \ 77 | res/reconnecting.ico \ 78 | res/eye.ico \ 79 | res/eye-stroke.ico \ 80 | res/openvpn-gui.manifest \ 81 | res/tileimage.bmp 82 | 83 | EXTRA_DIST = $(openvpn_gui_RESOURCES) \ 84 | CMakeLists.txt \ 85 | CMakePresets.json \ 86 | config-msvc.h.in \ 87 | .editorconfig \ 88 | .kateconfig 89 | 90 | openvpn_gui_SOURCES = \ 91 | main.c main.h \ 92 | openvpn.c openvpn.h \ 93 | localization.c localization.h \ 94 | tray.c tray.h \ 95 | viewlog.c viewlog.h \ 96 | service.c service.h \ 97 | options.c options.h \ 98 | proxy.c proxy.h \ 99 | registry.c registry.h \ 100 | scripts.c scripts.h \ 101 | manage.c manage.h \ 102 | misc.c misc.h \ 103 | openvpn_config.c \ 104 | openvpn_config.h \ 105 | access.c access.h \ 106 | chartable.h \ 107 | save_pass.c save_pass.h \ 108 | env_set.c env_set.h \ 109 | echo.c echo.h \ 110 | as.c as.h \ 111 | pkcs11.c pkcs11.h \ 112 | config_parser.c config_parser.h \ 113 | qr.c qr.h \ 114 | qrcodegen/qrcodegen.c qrcodegen/qrcodegen.h 115 | openvpn-gui-res.h 116 | 117 | openvpn_gui_LDFLAGS = -mwindows 118 | openvpn_gui_LDADD = \ 119 | openvpn-gui-res.o \ 120 | -lws2_32 \ 121 | -lcomctl32 \ 122 | -lwinhttp \ 123 | -lwtsapi32 \ 124 | -lcrypt32 \ 125 | -lnetapi32 \ 126 | -lole32 \ 127 | -lshlwapi \ 128 | -lsecur32 \ 129 | -lwininet \ 130 | $(JSON_LIBS) 131 | 132 | openvpn-gui-res.o: $(openvpn_gui_RESOURCES) $(srcdir)/openvpn-gui-res.h 133 | $(RCCOMPILE) -i $< -o $@ 134 | -------------------------------------------------------------------------------- /access.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is a part of OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2016 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include 24 | #endif 25 | 26 | #ifndef SECURITY_WIN32 27 | #define SECURITY_WIN32 28 | #endif 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "main.h" 36 | #include "options.h" 37 | #include "service.h" 38 | #include "localization.h" 39 | #include "openvpn-gui-res.h" 40 | #include "misc.h" 41 | 42 | extern options_t o; 43 | 44 | #define MAX_UNAME_LEN (UNLEN + DNLEN + 2) /* UNLEN, DNLEN from lmcons.h +2 for '\' and NULL */ 45 | 46 | static BOOL GetOwnerSID(PSID sid, DWORD sid_size); 47 | 48 | static BOOL IsUserInGroup(PSID sid, PTOKEN_GROUPS token_groups, const WCHAR *group_name); 49 | 50 | static PTOKEN_GROUPS GetProcessTokenGroups(void); 51 | 52 | /* 53 | * The Administrators group may be localized or renamed by admins. 54 | * Get the local name of the group using the SID. 55 | */ 56 | static BOOL 57 | GetBuiltinAdminGroupName(WCHAR *name, DWORD nlen) 58 | { 59 | BOOL b = FALSE; 60 | PSID admin_sid = NULL; 61 | DWORD sid_size = SECURITY_MAX_SID_SIZE; 62 | SID_NAME_USE su; 63 | 64 | WCHAR domain[MAX_NAME]; 65 | DWORD dlen = _countof(domain); 66 | 67 | admin_sid = malloc(sid_size); 68 | if (!admin_sid) 69 | { 70 | return FALSE; 71 | } 72 | 73 | b = CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size); 74 | if (b) 75 | { 76 | b = LookupAccountSidW(NULL, admin_sid, name, &nlen, domain, &dlen, &su); 77 | } 78 | #ifdef DEBUG 79 | PrintDebug(L"builtin admin group name = %ls", name); 80 | #endif 81 | 82 | free(admin_sid); 83 | 84 | return b; 85 | } 86 | 87 | /* 88 | * Add current user to the specified group. Uses RunAsAdmin to elevate. 89 | * Reject if the group name contains certain illegal characters. 90 | */ 91 | static BOOL 92 | AddUserToGroup(const WCHAR *group) 93 | { 94 | WCHAR username[MAX_UNAME_LEN]; 95 | WCHAR cmd[MAX_PATH] = L"C:\\windows\\system32\\cmd.exe"; 96 | WCHAR netcmd[MAX_PATH] = L"C:\\windows\\system32\\net.exe"; 97 | WCHAR syspath[MAX_PATH]; 98 | WCHAR *params = NULL; 99 | 100 | /* command: cmd.exe, params: /c net.exe group /add & net.exe group user /add */ 101 | const WCHAR *fmt = L"/c %ls localgroup \"%ls\" /add & %ls localgroup \"%ls\" \"%ls\" /add"; 102 | DWORD size; 103 | DWORD status; 104 | BOOL retval = FALSE; 105 | WCHAR reject[] = L"\"\?\\/[]:;|=,+*<>\'&"; 106 | 107 | /* 108 | * The only unknown content in the command line is the variable group. Ensure it 109 | * does not contain any '"' character. Here we reject all characters not allowed 110 | * in group names and special characters such as '&' as well. 111 | */ 112 | if (wcspbrk(group, reject) != NULL) 113 | { 114 | #ifdef DEBUG 115 | PrintDebug(L"AddUSerToGroup: illegal characters in group name: '%ls'.", group); 116 | #endif 117 | return retval; 118 | } 119 | 120 | size = _countof(username); 121 | if (!GetUserNameExW(NameSamCompatible, username, &size)) 122 | { 123 | return retval; 124 | } 125 | 126 | size = _countof(syspath); 127 | if (GetSystemDirectory(syspath, size)) 128 | { 129 | syspath[size - 1] = L'\0'; 130 | _snwprintf_s(cmd, _countof(cmd), _TRUNCATE, L"%ls\\%ls", syspath, L"cmd.exe"); 131 | _snwprintf_s(netcmd, _countof(netcmd), _TRUNCATE, L"%ls\\%ls", syspath, L"net.exe"); 132 | } 133 | size = (wcslen(fmt) + wcslen(username) + 2 * wcslen(group) + 2 * wcslen(netcmd) + 1); 134 | if ((params = malloc(size * sizeof(WCHAR))) == NULL) 135 | { 136 | return retval; 137 | } 138 | 139 | _snwprintf_s(params, size, _TRUNCATE, fmt, netcmd, group, netcmd, group, username); 140 | 141 | status = RunAsAdmin(cmd, params); 142 | if (status == 0) 143 | { 144 | retval = TRUE; 145 | } 146 | 147 | #ifdef DEBUG 148 | if (status == (DWORD)-1) 149 | { 150 | PrintDebug(L"RunAsAdmin: failed to execute the command [%ls %ls] : error = 0x%x", 151 | cmd, 152 | params, 153 | GetLastError()); 154 | } 155 | else if (status) 156 | { 157 | PrintDebug(L"RunAsAdmin: command [%ls %ls] returned exit_code = %lu", cmd, params, status); 158 | } 159 | #endif 160 | 161 | free(params); 162 | return retval; 163 | } 164 | 165 | /* 166 | * Check whether the config location is authorized for startup through 167 | * interactive service. 168 | */ 169 | static BOOL 170 | CheckConfigPath(const WCHAR *config_dir) 171 | { 172 | BOOL ret = FALSE; 173 | int size = wcslen(o.global_config_dir); 174 | 175 | /* if interactive service is not running, no access control: return TRUE */ 176 | if (!CheckIServiceStatus(FALSE)) 177 | { 178 | ret = TRUE; 179 | } 180 | /* if config is from the global location allow it */ 181 | else if (wcsncmp(config_dir, o.global_config_dir, size) == 0 182 | && wcsstr(config_dir + size, L"..") == NULL) 183 | { 184 | ret = TRUE; 185 | } 186 | 187 | return ret; 188 | } 189 | 190 | /* 191 | * If config_dir for a connection is not in an authorized location, 192 | * and user is not in built-in Administrators or ovpn_admin groups 193 | * show a dialog to add the user to the ovpn_admin_group. 194 | */ 195 | BOOL 196 | AuthorizeConfig(const connection_t *c) 197 | { 198 | DWORD res; 199 | BOOL retval = FALSE; 200 | WCHAR *admin_group; 201 | WCHAR sysadmin_group[MAX_NAME]; 202 | BYTE sid_buf[SECURITY_MAX_SID_SIZE]; 203 | DWORD sid_size = SECURITY_MAX_SID_SIZE; 204 | PSID sid = (PSID)sid_buf; 205 | PTOKEN_GROUPS groups = NULL; 206 | 207 | if (GetBuiltinAdminGroupName(sysadmin_group, _countof(sysadmin_group))) 208 | { 209 | admin_group = sysadmin_group; 210 | } 211 | else 212 | { 213 | admin_group = L"Administrators"; 214 | } 215 | 216 | PrintDebug(L"Authorized groups: '%ls', '%ls'", admin_group, o.ovpn_admin_group); 217 | 218 | if (CheckConfigPath(c->config_dir)) 219 | { 220 | return TRUE; 221 | } 222 | 223 | if (!GetOwnerSID(sid, sid_size)) 224 | { 225 | if (!o.silent_connection) 226 | { 227 | MessageBoxW(NULL, L"Failed to determine process owner SID", L"" PACKAGE_NAME, MB_OK); 228 | } 229 | return FALSE; 230 | } 231 | groups = GetProcessTokenGroups(); 232 | if (IsUserInGroup(sid, groups, admin_group) || IsUserInGroup(sid, groups, o.ovpn_admin_group)) 233 | { 234 | free(groups); 235 | return TRUE; 236 | } 237 | free(groups); 238 | 239 | /* do not attempt to add user to sysadmin_group or a no-name group */ 240 | if (wcscmp(admin_group, o.ovpn_admin_group) == 0 || wcslen(o.ovpn_admin_group) == 0 241 | || !o.netcmd_semaphore) 242 | { 243 | ShowLocalizedMsg(IDS_ERR_CONFIG_NOT_AUTHORIZED, c->config_name, o.ovpn_admin_group); 244 | return FALSE; 245 | } 246 | 247 | if (WaitForSingleObject(o.netcmd_semaphore, 0) != WAIT_OBJECT_0) 248 | { 249 | /* Could not lock semaphore -- auth dialog already running? */ 250 | ShowLocalizedMsg(IDS_NFO_CONFIG_AUTH_PENDING, c->config_name, o.ovpn_admin_group); 251 | return FALSE; 252 | } 253 | /* semaphore locked -- relase before return */ 254 | res = ShowLocalizedMsgEx(MB_YESNO | MB_ICONWARNING, 255 | NULL, 256 | TEXT(PACKAGE_NAME), 257 | IDS_ERR_CONFIG_TRY_AUTHORIZE, 258 | c->config_name, 259 | o.ovpn_admin_group); 260 | if (res == IDYES) 261 | { 262 | AddUserToGroup(o.ovpn_admin_group); 263 | /* 264 | * Check the success of above by testing the group membership again 265 | */ 266 | if (IsUserInGroup(sid, NULL, o.ovpn_admin_group)) 267 | { 268 | retval = TRUE; 269 | } 270 | else 271 | { 272 | ShowLocalizedMsg(IDS_ERR_ADD_USER_TO_ADMIN_GROUP, o.ovpn_admin_group); 273 | } 274 | SetForegroundWindow(o.hWnd); 275 | } 276 | ReleaseSemaphore(o.netcmd_semaphore, 1, NULL); 277 | 278 | return retval; 279 | } 280 | 281 | /* 282 | * Find SID from name 283 | * 284 | * On input sid should have space for at least sid_size bytes. 285 | * Returns TRUE on success, FALSE on error. 286 | * Hint: allocate sid to hold SECURITY_MAX_SID_SIZE bytes 287 | */ 288 | static BOOL 289 | LookupSID(const WCHAR *name, PSID sid, DWORD sid_size) 290 | { 291 | SID_NAME_USE su; 292 | WCHAR domain[MAX_NAME]; 293 | DWORD dlen = _countof(domain); 294 | 295 | if (!LookupAccountName(NULL, name, sid, &sid_size, domain, &dlen, &su)) 296 | { 297 | PrintDebug(L"LookupSID failed for '%ls'", name); 298 | return FALSE; 299 | } 300 | return TRUE; 301 | } 302 | 303 | /** 304 | * Get a list of groups in the token for the current proceess. 305 | * Returns a pointer to TOKEN_GROUPS structure or NULL on error. 306 | * The caller should free the returned pointer. 307 | */ 308 | static PTOKEN_GROUPS 309 | GetProcessTokenGroups(void) 310 | { 311 | HANDLE token; 312 | PTOKEN_GROUPS groups = NULL; 313 | DWORD buf_size = 0; 314 | 315 | if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) 316 | { 317 | return NULL; 318 | } 319 | if (!GetTokenInformation(token, TokenGroups, NULL, 0, &buf_size) 320 | && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 321 | { 322 | groups = malloc(buf_size); 323 | } 324 | if (!groups) 325 | { 326 | PrintDebug(L"GetProcessTokenGroups: error = %lu", GetLastError()); 327 | goto out; 328 | } 329 | if (!GetTokenInformation(token, TokenGroups, groups, buf_size, &buf_size)) 330 | { 331 | PrintDebug(L"Failed to get Token Group Information: error = %lu", GetLastError); 332 | free(groups); 333 | groups = NULL; 334 | } 335 | 336 | out: 337 | CloseHandle(token); 338 | return groups; 339 | } 340 | 341 | /** 342 | * Check the list of token_groups include the SID of the group_name 343 | * OR the specified user SID is in a local group named group_name. 344 | * The latter check is done to recognize situations where the user is 345 | * added to the group dynamically through the GUI. 346 | * 347 | * Using sid and token groups instead of username avoids reference to 348 | * domains so that this could be completed without access to a Domain 349 | * Controller. 350 | * 351 | * Returns true if the user is in the group, false otherwise. 352 | */ 353 | static BOOL 354 | IsUserInGroup(PSID sid, const PTOKEN_GROUPS token_groups, const WCHAR *group_name) 355 | { 356 | BOOL ret = FALSE; 357 | DWORD_PTR resume = 0; 358 | DWORD err; 359 | BYTE grp_sid[SECURITY_MAX_SID_SIZE]; 360 | int nloop = 0; /* a counter used to not get stuck in the do .. while() */ 361 | 362 | /* first check in the token groups */ 363 | if (token_groups && LookupSID(group_name, (PSID)grp_sid, _countof(grp_sid))) 364 | { 365 | for (DWORD i = 0; i < token_groups->GroupCount; ++i) 366 | { 367 | if (EqualSid((PSID)grp_sid, token_groups->Groups[i].Sid)) 368 | { 369 | PrintDebug(L"Found group in token at position %lu", i); 370 | return TRUE; 371 | } 372 | } 373 | } 374 | 375 | if (!sid) 376 | { 377 | return FALSE; 378 | } 379 | 380 | do 381 | { 382 | DWORD nread, nmax; 383 | LOCALGROUP_MEMBERS_INFO_0 *members = NULL; 384 | err = NetLocalGroupGetMembers( 385 | NULL, group_name, 0, (LPBYTE *)&members, MAX_PREFERRED_LENGTH, &nread, &nmax, &resume); 386 | if (err != NERR_Success && err != ERROR_MORE_DATA) 387 | { 388 | break; 389 | } 390 | 391 | /* If a match is already found, ret = TRUE, the loop is skipped */ 392 | for (DWORD i = 0; i < nread && !ret; ++i) 393 | { 394 | ret = EqualSid(members[i].lgrmi0_sid, sid); 395 | } 396 | NetApiBufferFree(members); 397 | /* MSDN says the lookup should always iterate until err != ERROR_MORE_DATA */ 398 | } while (err == ERROR_MORE_DATA && nloop++ < 100); 399 | 400 | if (err != NERR_Success && err != NERR_GroupNotFound) 401 | { 402 | PrintDebug(L"NetLocalGroupGetMembers for group '%ls' failed: error = %lu", group_name, err); 403 | } 404 | if (ret) 405 | { 406 | PrintDebug(L"User is in group '%ls'", group_name); 407 | } 408 | return ret; 409 | } 410 | 411 | /** 412 | * Get SID of the current process owner 413 | * On input sid must have space for at least sid_size bytes 414 | * 415 | * On success return true, else return false. 416 | */ 417 | static BOOL 418 | GetOwnerSID(PSID sid, DWORD sid_size) 419 | { 420 | BOOL ret = FALSE; 421 | HANDLE token; 422 | DWORD buf_size = 0; 423 | TOKEN_USER *tu = NULL; 424 | 425 | if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) 426 | { 427 | PrintDebug(L"Failed to get current process token: error = %lu", GetLastError()); 428 | return ret; 429 | } 430 | GetTokenInformation(token, TokenUser, NULL, 0, &buf_size); 431 | PrintDebug(L"Needed buffer size for Token User = %lu", buf_size); 432 | 433 | tu = malloc(buf_size); 434 | if (!tu || !GetTokenInformation(token, TokenUser, tu, buf_size, &buf_size)) 435 | { 436 | PrintDebug(L"Failed to get Token User Information: error = %lu", GetLastError); 437 | goto out; 438 | } 439 | if (!CopySid(sid_size, sid, tu->User.Sid)) 440 | { 441 | PrintDebug(L"CopySid Failed: error = %lu", GetLastError()); 442 | goto out; 443 | } 444 | ret = TRUE; 445 | 446 | out: 447 | CloseHandle(token); 448 | free(tu); 449 | return ret; 450 | } 451 | -------------------------------------------------------------------------------- /access.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is a part of OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2016 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef ACCESS_H 23 | #define ACCESS_H 24 | 25 | #include "options.h" 26 | 27 | BOOL AuthorizeConfig(const connection_t *c); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /as.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2021 Lev Stipakov 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | void ImportConfigFromAS(); 23 | 24 | void ImportConfigFromURL(); 25 | -------------------------------------------------------------------------------- /bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | autoreconf -i 3 | -------------------------------------------------------------------------------- /chartable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2004 Mathias Sundman 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | WCHAR unicode_to_ascii[256] = { 23 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 24 | 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 25 | 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 26 | 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 27 | 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 28 | 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 29 | 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050, 0x0051, 0x0052, 0x0053, 30 | 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 31 | 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 32 | 0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 33 | 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, 0x00c7, 0x00fc, 0x00e9, 0x00e2, 34 | 0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, 35 | 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, 0x00ff, 0x00d6, 0x00dc, 0x00f8, 36 | 0x00a3, 0x00d8, 0x00d7, 0x0192, 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, 37 | 0x00bf, 0x00ae, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, 0x2591, 0x2592, 0x2593, 0x2502, 38 | 0x2524, 0x00c1, 0x00c2, 0x00c0, 0x00a9, 0x2563, 0x2551, 0x2557, 0x255d, 0x00a2, 0x00a5, 0x2510, 39 | 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x00e3, 0x00c3, 0x255a, 0x2554, 0x2569, 0x2566, 40 | 0x2560, 0x2550, 0x256c, 0x00a4, 0x00f0, 0x00d0, 0x00ca, 0x00cb, 0x00c8, 0x0131, 0x00cd, 0x00ce, 41 | 0x00cf, 0x2518, 0x250c, 0x2588, 0x2584, 0x00a6, 0x00cc, 0x2580, 0x00d3, 0x00df, 0x00d4, 0x00d2, 42 | 0x00f5, 0x00d5, 0x00b5, 0x00fe, 0x00de, 0x00da, 0x00db, 0x00d9, 0x00fd, 0x00dd, 0x00af, 0x00b4, 43 | 0x00ad, 0x00b1, 0x2017, 0x00be, 0x00b6, 0x00a7, 0x00f7, 0x00b8, 0x00b0, 0x00a8, 0x00b7, 0x00b9, 44 | 0x00b3, 0x00b2, 0x25a0, 0x00a0 45 | }; 46 | -------------------------------------------------------------------------------- /config-msvc.h.in: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* Name of package */ 4 | #define PACKAGE "openvpn-gui" 5 | 6 | /* Define to the address where bug reports for this package should be sent. */ 7 | #define PACKAGE_BUGREPORT "openvpn-devel@lists.sourceforge.net" 8 | 9 | /* Define to the full name of this package. */ 10 | #define PACKAGE_NAME "OpenVPN GUI" 11 | 12 | /* Define to the one symbol short name of this package. */ 13 | #define PACKAGE_TARNAME "openvpn-gui" 14 | 15 | /* Define to the home page for this package. */ 16 | #define PACKAGE_URL "https://github.com/openvpn/openvpn-gui/" 17 | 18 | /* Define to the version of this package. */ 19 | #define PACKAGE_VERSION "11" 20 | 21 | /* Version in windows resource format */ 22 | #define PACKAGE_VERSION_RESOURCE @GUI_VERSION_MAJOR@, @GUI_VERSION_MINOR@, 0, 0 23 | 24 | /* Version as a string */ 25 | #define PACKAGE_VERSION_RESOURCE_STR "@GUI_VERSION_MAJOR@.@GUI_VERSION_MINOR@.0.0" 26 | -------------------------------------------------------------------------------- /config_parser.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is a part of OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2016 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "main.h" 28 | #include "misc.h" 29 | #include "config_parser.h" 30 | 31 | static int 32 | legal_escape(wchar_t c) 33 | { 34 | wchar_t *escapes = L"\" \\"; /* ", space, and backslash */ 35 | return (wcschr(escapes, c) != NULL); 36 | } 37 | 38 | static int 39 | is_comment(wchar_t *s) 40 | { 41 | wchar_t *comment_chars = L";#"; 42 | return (s && (wcschr(comment_chars, s[0]) != NULL)); 43 | } 44 | 45 | static int 46 | copy_token(wchar_t **dest, wchar_t **src, wchar_t *delim) 47 | { 48 | wchar_t *p = *src; 49 | wchar_t *s = *dest; 50 | 51 | /* copy src to dest until delim character with escaped chars converted */ 52 | for (; *p != L'\0' && wcschr(delim, *p) == NULL; p++, s++) 53 | { 54 | if (*p == L'\\' && legal_escape(*(p + 1))) 55 | { 56 | *s = *(++p); 57 | } 58 | else if (*p == L'\\') 59 | { 60 | MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Parse error in copy_token: illegal backslash"); 61 | return -1; /* parse error -- illegal backslash in input */ 62 | } 63 | else 64 | { 65 | *s = *p; 66 | } 67 | } 68 | /* at this point p is one of the delimiters or null */ 69 | *s = L'\0'; 70 | *src = p; 71 | *dest = s; 72 | return 0; 73 | } 74 | 75 | static int 76 | tokenize(config_entry_t *ce) 77 | { 78 | wchar_t *p, *s; 79 | p = ce->line; 80 | s = ce->sline; 81 | unsigned int i = 0; 82 | int status = 0; 83 | 84 | for (; *p != L'\0'; p++, s++) 85 | { 86 | if (*p == L' ' || *p == L'\t') 87 | { 88 | continue; 89 | } 90 | 91 | if (_countof(ce->tokens) <= i) 92 | { 93 | return -1; 94 | } 95 | ce->tokens[i++] = s; 96 | 97 | if (*p == L'\'') 98 | { 99 | int len = wcscspn(++p, L"\'"); 100 | wcsncpy(s, p, len); 101 | s += len; 102 | p += len; 103 | } 104 | else if (*p == L'\"') 105 | { 106 | p++; 107 | status = copy_token(&s, &p, L"\""); 108 | } 109 | else if (is_comment(p)) 110 | { 111 | /* store rest of the line as comment -- remove from tokens */ 112 | ce->comment = s; 113 | wcsncpy(s, p, wcslen(p)); 114 | ce->tokens[--i] = NULL; 115 | break; 116 | } 117 | else 118 | { 119 | status = copy_token(&s, &p, L" \t"); 120 | } 121 | 122 | if (status != 0) 123 | { 124 | return status; 125 | } 126 | 127 | if (*p == L'\0') 128 | { 129 | break; 130 | } 131 | } 132 | ce->ntokens = i; 133 | return 0; 134 | } 135 | 136 | config_entry_t * 137 | config_readline(FILE *fd, int first) 138 | { 139 | int len; 140 | char tmp[MAX_LINE_LENGTH]; 141 | int offset = 0; 142 | 143 | if (fgets(tmp, _countof(tmp) - 1, fd) == NULL) 144 | { 145 | return NULL; 146 | } 147 | /* remove UTF-8 BOM */ 148 | if (first && strncmp(tmp, "\xEF\xBB\xBF", 3) == 0) 149 | { 150 | offset = 3; 151 | } 152 | 153 | config_entry_t *ce = calloc(sizeof(*ce), 1); 154 | if (!ce) 155 | { 156 | MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Out of memory in config_readline"); 157 | return NULL; 158 | } 159 | 160 | mbstowcs(ce->line, &tmp[offset], _countof(ce->line) - 1); 161 | 162 | len = wcscspn(ce->line, L"\n\r"); 163 | ce->line[len] = L'\0'; 164 | 165 | if (tokenize(ce) != 0) 166 | { 167 | free(ce); 168 | return NULL; 169 | } 170 | 171 | /* skip leading "--" in first token if any */ 172 | if (ce->ntokens > 0) 173 | { 174 | ce->tokens[0] += wcsspn(ce->tokens[0], L"--"); 175 | } 176 | 177 | return ce; 178 | } 179 | 180 | config_entry_t * 181 | config_parse(wchar_t *fname) 182 | { 183 | FILE *fd = NULL; 184 | config_entry_t *head, *tail; 185 | 186 | if (!fname || _wfopen_s(&fd, fname, L"r")) 187 | { 188 | MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Error opening <%ls> in config_parse", fname); 189 | return NULL; 190 | } 191 | head = tail = config_readline(fd, 1); 192 | 193 | while (tail) 194 | { 195 | tail->next = config_readline(fd, 0); 196 | tail = tail->next; 197 | } 198 | fclose(fd); 199 | return head; 200 | } 201 | 202 | void 203 | config_list_free(config_entry_t *head) 204 | { 205 | config_entry_t *next; 206 | while (head) 207 | { 208 | next = head->next; 209 | free(head); 210 | head = next; 211 | } 212 | return; 213 | } 214 | -------------------------------------------------------------------------------- /config_parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is a part of OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2016 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef CONFIG_PARSER_H 23 | #define CONFIG_PARSER_H 24 | 25 | #define MAX_LINE_LENGTH 256 26 | 27 | typedef struct config_entry config_entry_t; 28 | 29 | struct config_entry 30 | { 31 | wchar_t line[MAX_LINE_LENGTH]; 32 | wchar_t sline[MAX_LINE_LENGTH]; 33 | wchar_t *tokens[16]; 34 | wchar_t *comment; 35 | int ntokens; 36 | config_entry_t *next; 37 | }; 38 | 39 | /** 40 | * Parse an ovpn file into a list of tokenized 41 | * structs. 42 | * @param fname : filename of the config to parse 43 | * @returns the pointer to the head of a list of 44 | * config_entry_t structs. 45 | * The called must free it after use by calling 46 | * config_list_free() 47 | */ 48 | config_entry_t *config_parse(wchar_t *fname); 49 | 50 | /** 51 | * Free a list of config_entry_t structs 52 | * @param head : list head returned by config_parse() 53 | */ 54 | void config_list_free(config_entry_t *head); 55 | 56 | #endif /* ifndef CONFIG_PARSER_H */ 57 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | dnl OpenVPN-GUI -- A Windows GUI for OpenVPN. 2 | dnl 3 | dnl Copyright (C) 2004 Mathias Sundman 4 | dnl 2010 Heiko Hund 5 | dnl 6 | dnl This program is free software; you can redistribute it and/or modify 7 | dnl it under the terms of the GNU General Public License as published by 8 | dnl the Free Software Foundation; either version 2 of the License, or 9 | dnl (at your option) any later version. 10 | dnl 11 | dnl This program is distributed in the hope that it will be useful, 12 | dnl but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | dnl GNU General Public License for more details. 15 | dnl 16 | dnl You should have received a copy of the GNU General Public License 17 | dnl along with this program (see the file COPYING included with this 18 | dnl distribution); if not, write to the Free Software Foundation, Inc., 19 | dnl 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | AC_PREREQ(2.59) 22 | define([_GUI_VERSION_MAJOR], [11]) 23 | define([_GUI_VERSION_MINOR], [53]) 24 | AC_INIT([OpenVPN GUI],[_GUI_VERSION_MAJOR],[openvpn-devel@lists.sourceforge.net],[openvpn-gui],[https://github.com/openvpn/openvpn-gui/]) 25 | AC_DEFINE([PACKAGE_VERSION_RESOURCE], [_GUI_VERSION_MAJOR,_GUI_VERSION_MINOR,0,0], [Version in windows resource format]) 26 | AC_DEFINE([PACKAGE_VERSION_RESOURCE_STR], ["_GUI_VERSION_MAJOR._GUI_VERSION_MINOR.0.0"], [Version as a string]) 27 | AC_CONFIG_AUX_DIR([.]) 28 | AM_CONFIG_HEADER([config.h]) 29 | AC_CONFIG_SRCDIR([main.h]) 30 | AM_INIT_AUTOMAKE([subdir-objects]) 31 | AC_CANONICAL_HOST 32 | AC_USE_SYSTEM_EXTENSIONS 33 | AC_PROG_CC_C99 34 | AC_PROG_CXX 35 | AC_CHECK_TOOL([WINDRES], [windres]) 36 | LT_INIT([win32-dll]) 37 | LT_LANG([Windows Resource]) 38 | 39 | AC_ARG_ENABLE( 40 | [distonly], 41 | [AS_HELP_STRING([--enable-distonly], [enable distribute only mode @<:@default=no@:>@])], 42 | , 43 | [enable_distonly="no"] 44 | ) 45 | 46 | AC_ARG_ENABLE( 47 | [ovpn3], 48 | [AS_HELP_STRING([--enable-ovpn3], [enable openvpn3 agent and client @<:@default=no@:>@])], 49 | [ 50 | AC_DEFINE([ENABLE_OVPN3], 1, [Use openvpn3 agent instead of interactive service]) 51 | PKG_CHECK_MODULES([JSON], [json-c]) 52 | ] 53 | ) 54 | 55 | case "$host" in 56 | *-mingw*) 57 | CPPFLAGS="${CPPFLAGS} -DWIN32_LEAN_AND_MEAN" 58 | CPPFLAGS="${CPPFLAGS} -D_WIN32_WINNT=_WIN32_WINNT_WIN7 -DWINVER=_WIN32_WINNT" 59 | LDFLAGS="${LDFLAGS} -Wl,--nxcompat,--dynamicbase" 60 | 61 | dnl older mingw doesn't support `--high-entropy-va` 62 | _save_ldflags="$LDFLAGS" 63 | LDFLAGS="-Wl,--high-entropy-va" 64 | AC_LINK_IFELSE([AC_LANG_PROGRAM([])],[AS_VAR_SET(high_entropy_aslr,[yes])],) 65 | LDFLAGS="$_save_ldflags" 66 | AS_VAR_IF(high_entropy_aslr,[yes],[LDFLAGS="${LDFLAGS} -Wl,--high-entropy-va"],) 67 | ;; 68 | *) 69 | test "${enable_distonly}" = "no" && AC_MSG_ERROR([This project is supported for windows only.]) 70 | ;; 71 | esac 72 | 73 | AC_CHECK_LIB(cryptui, CryptUIDlgViewContext) 74 | 75 | AC_PROG_CPP 76 | AC_PROG_INSTALL 77 | AC_PROG_LN_S 78 | AC_PROG_MAKE_SET 79 | 80 | test "${GCC}" = "yes" && CFLAGS="${CFLAGS} -pedantic -Wall -Wextra -Wno-cast-function-type -Werror" 81 | 82 | AC_CONFIG_FILES([Makefile plap/Makefile]) 83 | AC_OUTPUT 84 | -------------------------------------------------------------------------------- /echo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2017 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef ECHO_H 23 | #define ECHO_H 24 | 25 | #include 26 | 27 | /* data structures and methods for handling echo msg */ 28 | #define HASHLEN 20 29 | 30 | /* message finger print consists of a SHA1 hash and a timestamp */ 31 | struct echo_msg_fp 32 | { 33 | BYTE digest[HASHLEN]; 34 | time_t timestamp; 35 | }; 36 | struct echo_msg_history; 37 | struct echo_msg 38 | { 39 | struct echo_msg_fp fp; /* keep this as the first element */ 40 | wchar_t *title; 41 | wchar_t *text; 42 | int txtlen; 43 | int type; 44 | struct echo_msg_history *history; 45 | }; 46 | 47 | /* init echo message -- call on program start */ 48 | void echo_msg_init(); 49 | 50 | /* Process echo msg and related commands received from mgmt iterface. */ 51 | void echo_msg_process(connection_t *c, time_t timestamp, const char *msg); 52 | 53 | /* Clear echo msg buffers and optionally history */ 54 | void echo_msg_clear(connection_t *c, BOOL clear_history); 55 | 56 | /* Load echo msg history from the registry */ 57 | void echo_msg_load(connection_t *c); 58 | 59 | #endif /* ifndef ECHO_H */ 60 | -------------------------------------------------------------------------------- /env_set.c: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2017 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include 24 | #endif 25 | 26 | #include 27 | #include 28 | #include "main.h" 29 | #include "options.h" 30 | #include "misc.h" 31 | #include "openvpn.h" 32 | #include "env_set.h" 33 | 34 | struct env_item 35 | { 36 | wchar_t *nameval; 37 | struct env_item *next; 38 | }; 39 | 40 | /* To match with openvpn we accept only :ALPHA:, :DIGIT: or '_' in names */ 41 | BOOL 42 | is_valid_env_name(const char *name) 43 | { 44 | if (name[0] == '\0') 45 | { 46 | return false; 47 | } 48 | while (*name) 49 | { 50 | const char c = *name; 51 | if (!isalnum(c) && c != '_') 52 | { 53 | return false; 54 | } 55 | name++; 56 | } 57 | return true; 58 | } 59 | 60 | /* Compare two strings of the form name1=val and name2=val 61 | * return value is -ve, 0 or +ve for name1 less than, equal 62 | * to or greater than name2. 63 | * The comparison is locale-independent and case insensitive. 64 | * If '=' is missing the whole string is used as name. 65 | */ 66 | int 67 | env_name_compare(const wchar_t *nameval1, const wchar_t *nameval2) 68 | { 69 | size_t len1 = wcscspn(nameval1, L"="); 70 | size_t len2 = wcscspn(nameval2, L"="); 71 | 72 | /* For env variable names we want locale independent case-insensitive 73 | * unicode string comparsion. Use CompareStringOrdinal following 74 | * https://msdn.microsoft.com/en-us/library/windows/desktop/dd318144(v=vs.85).aspx 75 | */ 76 | BOOL ignore_case = true; 77 | int cmp = CompareStringOrdinal(nameval1, (int)len1, nameval2, (int)len2, ignore_case); 78 | 79 | return cmp - 2; /* -2 to bring the result match strcmp semantics */ 80 | } 81 | 82 | static void 83 | env_item_free(struct env_item *item) 84 | { 85 | free(item->nameval); 86 | free(item); 87 | } 88 | 89 | /* Delete an env var item with matching name: if name is of the 90 | * form xxx=yyy, only the part xxx is used for matching. 91 | * Returns the head of the list. 92 | */ 93 | static struct env_item * 94 | env_item_del(struct env_item *head, const wchar_t *name) 95 | { 96 | struct env_item *item, *prev = NULL; 97 | 98 | if (!name) 99 | { 100 | return head; 101 | } 102 | 103 | for (item = head; item; item = item->next) 104 | { 105 | if (env_name_compare(name, item->nameval) == 0) 106 | { 107 | /* matching item found */ 108 | if (prev) 109 | { 110 | prev->next = item->next; 111 | } 112 | else /* head is going to be deleted */ 113 | { 114 | head = item->next; 115 | } 116 | env_item_free(item); 117 | break; 118 | } 119 | prev = item; 120 | continue; 121 | } 122 | 123 | return head; 124 | } 125 | 126 | /* Insert a env var item to an env set: any existing item 127 | * with same name is replaced by the new entry. Else 128 | * the item is added at an alphabetically sorted location. 129 | * Returns the new head of the list. 130 | */ 131 | struct env_item * 132 | env_item_insert(struct env_item *head, struct env_item *item) 133 | { 134 | struct env_item *tmp, *prev = NULL; 135 | int cmp = -1; 136 | 137 | /* find location of new item in sorted order: head == NULL is ok */ 138 | for (tmp = head; tmp; tmp = tmp->next) 139 | { 140 | cmp = env_name_compare(item->nameval, tmp->nameval); 141 | if (cmp <= 0) /* found the position to add */ 142 | { 143 | break; 144 | } 145 | prev = tmp; 146 | continue; 147 | } 148 | if (cmp == 0) /* name already set -- replace */ 149 | { 150 | item->next = tmp->next; 151 | env_item_free(tmp); 152 | } 153 | else /* add item at this point */ 154 | { 155 | item->next = tmp; 156 | } 157 | 158 | if (prev) 159 | { 160 | prev->next = item; 161 | } 162 | else 163 | { 164 | head = item; 165 | } 166 | 167 | return head; 168 | } 169 | 170 | void 171 | env_item_del_all(struct env_item *head) 172 | { 173 | struct env_item *next; 174 | for (; head; head = next) 175 | { 176 | next = head->next; 177 | env_item_free(head); 178 | } 179 | } 180 | 181 | /* convenience functions for create, add and delete an item 182 | * given nameval as a utf8 string. 183 | */ 184 | 185 | /* Create a new env item given nameval name=val */ 186 | struct env_item * 187 | env_item_new_utf8(const char *nameval) 188 | { 189 | struct env_item *new = malloc(sizeof(struct env_item)); 190 | 191 | if (!new) 192 | { 193 | return NULL; 194 | } 195 | new->nameval = Widen(nameval); 196 | new->next = NULL; 197 | 198 | if (!new->nameval) 199 | { 200 | free(new); 201 | return NULL; 202 | } 203 | return new; 204 | } 205 | 206 | /* Insert an env item to the set given nameval: name=val. 207 | * Returns new head of the list. 208 | */ 209 | static struct env_item * 210 | env_item_insert_utf8(struct env_item *head, const char *nameval) 211 | { 212 | struct env_item *item = env_item_new_utf8(nameval); 213 | 214 | if (!item) 215 | { 216 | return head; 217 | } 218 | 219 | return env_item_insert(head, item); 220 | } 221 | 222 | /* Delete an env item from the list with matching name. Returns the 223 | * new head of the list. If name is given as name=val, only the 224 | * name part is used for matching. 225 | */ 226 | static struct env_item * 227 | env_item_del_utf8(struct env_item *head, const char *name) 228 | { 229 | wchar_t *wname = Widen(name); 230 | 231 | if (wname) 232 | { 233 | head = env_item_del(head, wname); 234 | free(wname); 235 | } 236 | return head; 237 | } 238 | 239 | /* 240 | * Make an env block by merging items in es to the process env block 241 | * retaining alphabetical order as necessary on Windows. 242 | * Returns NULL on error or a newly allocated string that may be passed 243 | * to CreateProcess as the env block. The caller must free the returned 244 | * pointer. 245 | */ 246 | wchar_t * 247 | merge_env_block(const struct env_item *es) 248 | { 249 | size_t len = 0; 250 | /* e should be treated as read-only though cannot be defined as const 251 | * due to the need to call FreeEnvironmentStrings in the end. 252 | */ 253 | wchar_t *e = GetEnvironmentStringsW(); 254 | const struct env_item *item; 255 | const wchar_t *pe; 256 | 257 | if (!e) 258 | { 259 | return NULL; 260 | } 261 | 262 | for (pe = e; *pe; pe += wcslen(pe) + 1) 263 | { 264 | } 265 | len = (pe + 1 - e); /* including the extra '\0' at the end */ 266 | 267 | for (item = es; item; item = item->next) 268 | { 269 | len += wcslen(item->nameval) + 1; 270 | } 271 | 272 | wchar_t *env = malloc(sizeof(wchar_t) * len); 273 | if (!env) 274 | { 275 | /* no memory -- return NULL */ 276 | FreeEnvironmentStringsW(e); 277 | return NULL; 278 | } 279 | 280 | wchar_t *p = env; 281 | item = es; 282 | pe = e; 283 | len = wcslen(pe) + 1; 284 | 285 | /* Merge two sroted collections env set and process env. 286 | * In case of duplicates the env set entry replaces that in the 287 | * process env. 288 | */ 289 | while (item && *pe) 290 | { 291 | int cmp = env_name_compare(item->nameval, pe); 292 | if (cmp <= 0) /* add entry from env set */ 293 | { 294 | wcscpy(p, item->nameval); 295 | p += wcslen(item->nameval) + 1; 296 | item = item->next; 297 | } 298 | else /* add entry from process env */ 299 | { 300 | wcscpy(p, pe); 301 | p += len; 302 | } 303 | if (cmp >= 0) /* pe was added (cmp >0) or has to be skipped (cmp==0) */ 304 | { 305 | pe += len; 306 | if (*pe) /* update len */ 307 | { 308 | len = wcslen(pe) + 1; 309 | } 310 | } 311 | } 312 | /* Add any remaining entries -- either item or *pe is NULL at this point. 313 | * So only one of the two following loops will run. 314 | */ 315 | for (; item; item = item->next) 316 | { 317 | wcscpy(p, item->nameval); 318 | p += wcslen(item->nameval) + 1; 319 | } 320 | for (; *pe; pe += len, p += len) 321 | { 322 | wcscpy(p, pe); 323 | len = wcslen(pe) + 1; 324 | } 325 | *p = L'\0'; 326 | 327 | FreeEnvironmentStringsW(e); 328 | 329 | return env; 330 | } 331 | 332 | /* Expect "setenv name value" and add name=value 333 | * to a private env set with name prefixed by OPENVPN_. 334 | * If value is missing we delete name from the env set. 335 | */ 336 | void 337 | process_setenv(connection_t *c, UNUSED time_t timestamp, const char *msg) 338 | { 339 | const char *prefix = "OPENVPN_"; 340 | char *p; 341 | char *nameval; 342 | 343 | if (!strbegins(msg, "setenv ")) 344 | { 345 | return; 346 | } 347 | 348 | msg += strlen("setenv "); /* character following "setenv" */ 349 | msg += strspn(msg, " \t"); /* skip leading space */ 350 | if (msg[0] == '\0') 351 | { 352 | WriteStatusLog(c, L"GUI> ", L"Error: Name empty in echo setenv", false); 353 | return; 354 | } 355 | 356 | nameval = malloc(strlen(prefix) + strlen(msg) + 1); 357 | if (!nameval) 358 | { 359 | WriteStatusLog(c, L"GUI> ", L"Error: Out of memory for adding env var", false); 360 | return; 361 | } 362 | 363 | strcpy(nameval, prefix); 364 | strcat(nameval, msg); 365 | 366 | if ((p = strchr(nameval, ' ')) != NULL) 367 | { 368 | *p = '\0'; /* temporary null termination */ 369 | if (is_valid_env_name(nameval)) 370 | { 371 | *p = '='; 372 | c->es = env_item_insert_utf8(c->es, nameval); 373 | } 374 | else 375 | { 376 | *p = ' '; 377 | WriteStatusLog(c, L"GUI> ", L"Error: empty or illegal name in echo setenv", false); 378 | } 379 | } 380 | /* if only name is specified and valid, delete the value from env set */ 381 | else if (is_valid_env_name(nameval)) 382 | { 383 | c->es = env_item_del_utf8(c->es, nameval); 384 | } 385 | free(nameval); /* env_item keeps a private wide string copy */ 386 | } 387 | -------------------------------------------------------------------------------- /env_set.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2017 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef ENV_SET_H 23 | #define ENV_SET_H 24 | 25 | #include 26 | #include "options.h" 27 | 28 | /* 29 | * data structures and methods for config specific env set and echo setenv 30 | */ 31 | struct env_item; 32 | /* free all env set resources -- to be called when a connection thread exits */ 33 | void env_item_del_all(struct env_item *head); 34 | /* parse setenv name val to add name=val to the connection env set */ 35 | void process_setenv(connection_t *c, time_t timestamp, const char *msg); 36 | 37 | /** 38 | * Make an env block by merging items in es to the process env block 39 | * retaining alphabetical order as necessary on Windows. 40 | * Returns a newly allocated string that may be passed to CreateProcess 41 | * as the env block or NULL on error. The caller must free the returned 42 | * pointer. 43 | */ 44 | wchar_t *merge_env_block(const struct env_item *es); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /localization.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2009 Heiko Hund 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef LOCALIZATION_H 23 | #define LOCALIZATION_H 24 | 25 | int LocalizedTime(const time_t, LPTSTR, size_t); 26 | 27 | wchar_t *LocalizedFileTime(const FILETIME *ft); 28 | 29 | PTSTR LoadLocalizedString(const UINT, ...); 30 | 31 | int LoadLocalizedStringBuf(PTSTR, const int, const UINT, ...); 32 | 33 | void ShowLocalizedMsg(const UINT, ...); 34 | 35 | int ShowLocalizedMsgEx(const UINT, HANDLE, LPCTSTR, const UINT, ...); 36 | 37 | HICON LoadLocalizedIconEx(const UINT, int cx, int cy); 38 | 39 | HICON LoadLocalizedIcon(const UINT); 40 | 41 | HICON LoadLocalizedSmallIcon(const UINT); 42 | 43 | LPCDLGTEMPLATE LocalizedDialogResource(const UINT); 44 | 45 | INT_PTR LocalizedDialogBoxParam(const UINT, DLGPROC, const LPARAM); 46 | 47 | INT_PTR LocalizedDialogBoxParamEx(const UINT, HWND parent, DLGPROC, const LPARAM); 48 | 49 | HWND CreateLocalizedDialogParam(const UINT, DLGPROC, const LPARAM); 50 | 51 | HWND CreateLocalizedDialog(const UINT, DLGPROC); 52 | 53 | INT_PTR CALLBACK GeneralSettingsDlgProc(HWND, UINT, WPARAM, LPARAM); 54 | 55 | LANGID GetGUILanguage(void); 56 | 57 | /* 58 | * Detect whether the selected UI language is LTR or RTL. 59 | * Returns 0 for LTR, 1 for RTL, 2 or 3 for vertical 60 | */ 61 | int LangFlowDirection(void); 62 | 63 | #define MBOX_RTL_FLAGS ((LangFlowDirection() == 1) ? MB_RIGHT | MB_RTLREADING : 0) 64 | 65 | #endif /* ifndef LOCALIZATION_H */ 66 | -------------------------------------------------------------------------------- /main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2004 Mathias Sundman 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef MAIN_H 23 | #define MAIN_H 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | /* Define this to enable DEBUG build */ 32 | /*#define DEBUG */ 33 | #define DEBUG_FILE L"openvpngui_debug.txt" /* will be created in GetTempPath() directory */ 34 | 35 | /* Registry key for User Settings */ 36 | #define GUI_REGKEY_HKCU _T("Software\\OpenVPN-GUI") 37 | 38 | #define MAX_LOG_LENGTH 1024 /* Max number of characters per log line */ 39 | #define MAX_LOG_LINES 500 /* Max number of lines in LogWindow */ 40 | #define DEL_LOG_LINES 10 /* Number of lines to delete from LogWindow */ 41 | #define USAGE_BUF_SIZE 3000 /* Size of buffer used to display usage message */ 42 | 43 | /* Authorized group who can use any options and config locations */ 44 | #define OVPN_ADMIN_GROUP TEXT("OpenVPN Administrators") /* May be reset in registry */ 45 | 46 | /* Application defined message IDs */ 47 | #define WM_NOTIFYICONTRAY (WM_APP + 1) 48 | #define WM_MANAGEMENT (WM_APP + 2) 49 | 50 | #define WM_OVPN_STOP (WM_APP + 10) 51 | #define WM_OVPN_SUSPEND (WM_APP + 11) 52 | #define WM_OVPN_RESTART (WM_APP + 12) 53 | #define WM_OVPN_START (WM_APP + 13) 54 | #define WM_OVPN_STOPALL (WM_APP + 14) 55 | #define WM_OVPN_SHOWSTATUS (WM_APP + 15) 56 | #define WM_OVPN_NOTIFY (WM_APP + 16) 57 | #define WM_OVPN_EXIT (WM_APP + 17) 58 | #define WM_OVPN_SILENT (WM_APP + 18) 59 | #define WM_OVPN_RELEASE (WM_APP + 19) 60 | #define WM_OVPN_IMPORT (WM_APP + 20) 61 | #define WM_OVPN_RESCAN (WM_APP + 21) 62 | #define WM_OVPN_ECHOMSG (WM_APP + 22) 63 | #define WM_OVPN_STATE (WM_APP + 23) 64 | #define WM_OVPN_DETACH (WM_APP + 24) 65 | 66 | #define MSGF_OVPN_WAIT (MSGF_USER + 1) 67 | 68 | /* GCC function attributes */ 69 | #ifdef _MSC_VER 70 | #define UNUSED 71 | #define NORETURN 72 | #else 73 | #define UNUSED __attribute__((unused)) 74 | #define NORETURN __attribute__((noreturn)) 75 | #endif 76 | 77 | #define PACKVERSION(major, minor) MAKELONG(minor, major) 78 | struct security_attributes 79 | { 80 | SECURITY_ATTRIBUTES sa; 81 | SECURITY_DESCRIPTOR sd; 82 | }; 83 | 84 | /* clear an object */ 85 | #define CLEAR(x) memset(&(x), 0, sizeof(x)) 86 | 87 | /* _sntprintf with guaranteed \0 termination */ 88 | #define _sntprintf_0(buf, ...) \ 89 | do \ 90 | { \ 91 | __sntprintf_0(buf, _countof(buf), __VA_ARGS__); \ 92 | } while (0); 93 | 94 | static inline int 95 | __sntprintf_0(TCHAR *buf, size_t size, TCHAR *format, ...) 96 | { 97 | int i; 98 | va_list args; 99 | va_start(args, format); 100 | i = _vsntprintf(buf, size, format, args); 101 | buf[size - 1] = _T('\0'); 102 | va_end(args); 103 | return i; 104 | } 105 | 106 | /* _snprintf with guaranteed \0 termination */ 107 | #define _snprintf_0(buf, ...) \ 108 | do \ 109 | { \ 110 | __snprintf_0(buf, sizeof(buf), __VA_ARGS__); \ 111 | } while (0); 112 | static inline int 113 | __snprintf_0(char *buf, size_t size, char *format, ...) 114 | { 115 | int i; 116 | va_list args; 117 | va_start(args, format); 118 | i = _vsnprintf(buf, size, format, args); 119 | buf[size - 1] = '\0'; 120 | va_end(args); 121 | return i; 122 | } 123 | 124 | #ifdef DEBUG 125 | /* Print Debug Message */ 126 | #define PrintDebug(...) \ 127 | do \ 128 | { \ 129 | TCHAR x_msg[256]; \ 130 | _sntprintf_0(x_msg, __VA_ARGS__); \ 131 | PrintDebugMsg(x_msg); \ 132 | } while (0) 133 | 134 | void PrintDebugMsg(TCHAR *msg); 135 | 136 | #else /* ifdef DEBUG */ 137 | #define PrintDebug(...) \ 138 | do \ 139 | { \ 140 | } while (0) 141 | #endif 142 | 143 | DWORD GetDllVersion(LPCTSTR lpszDllName); 144 | 145 | void ErrorExit(int exit_code, const wchar_t *msg); 146 | 147 | #endif /* ifndef MAIN_H */ 148 | -------------------------------------------------------------------------------- /manage.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2010 Heiko Hund 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef MANAGE_H 23 | #define MANAGE_H 24 | 25 | #include 26 | 27 | typedef enum 28 | { 29 | ready_, 30 | stop_, 31 | bytecount_, 32 | echo_, 33 | hold_, 34 | log_, 35 | password_, 36 | proxy_, 37 | state_, 38 | needok_, 39 | needstr_, 40 | pkcs11_id_count_, 41 | infomsg_, 42 | timeout_, 43 | mgmt_rtmsg_type_max 44 | } mgmt_rtmsg_type; 45 | 46 | typedef enum 47 | { 48 | regular, 49 | combined 50 | } mgmt_cmd_type; 51 | 52 | typedef void (*mgmt_msg_func)(connection_t *, char *); 53 | 54 | typedef struct 55 | { 56 | mgmt_rtmsg_type type; 57 | mgmt_msg_func handler; 58 | } mgmt_rtmsg_handler; 59 | 60 | typedef struct mgmt_cmd 61 | { 62 | struct mgmt_cmd *prev, *next; 63 | char *command; 64 | int size; 65 | mgmt_msg_func handler; 66 | mgmt_cmd_type type; 67 | } mgmt_cmd_t; 68 | 69 | 70 | void InitManagement(const mgmt_rtmsg_handler *handler); 71 | 72 | BOOL OpenManagement(connection_t *); 73 | 74 | BOOL ManagementCommand(connection_t *, char *, mgmt_msg_func, mgmt_cmd_type); 75 | 76 | void OnManagement(SOCKET, LPARAM); 77 | 78 | void CloseManagement(connection_t *); 79 | 80 | #endif /* ifndef MANAGE_H */ 81 | -------------------------------------------------------------------------------- /misc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2013 Heiko Hund 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef MISC_H 23 | #define MISC_H 24 | 25 | #include 26 | 27 | #include "options.h" 28 | 29 | BOOL ManagementCommandFromInput(connection_t *, LPCSTR, HWND, int); 30 | 31 | BOOL ManagementCommandFromTwoInputsBase64(connection_t *, LPCSTR, HWND, int, int); 32 | 33 | BOOL ManagementCommandFromInputBase64(connection_t *, LPCSTR, HWND, int); 34 | 35 | BOOL EnsureDirExists(LPTSTR); 36 | 37 | BOOL streq(LPCSTR, LPCSTR); 38 | 39 | BOOL strbegins(const char *str, const char *begin); 40 | 41 | BOOL wcsbegins(LPCWSTR, LPCWSTR); 42 | 43 | BOOL ForceForegroundWindow(HWND); 44 | 45 | void DpiSetScale(options_t *, UINT dpix); 46 | 47 | BOOL IsUserAdmin(VOID); 48 | 49 | HANDLE InitSemaphore(WCHAR *); 50 | 51 | BOOL CheckFileAccess(const TCHAR *path, int access); 52 | 53 | BOOL Base64Encode(const char *input, int input_len, char **output); 54 | 55 | int Base64Decode(const char *input, char **output); 56 | 57 | WCHAR *Widen(const char *utf8); 58 | 59 | WCHAR *WidenEx(UINT codepage, const char *utf8); 60 | 61 | /** 62 | * Convert a wide string to a UTF-8 string. The caller must 63 | * free the returned pointer. Return NULL on error. 64 | */ 65 | char *WCharToUTF8(const WCHAR *wstr); 66 | 67 | BOOL validate_input(const WCHAR *input, const WCHAR *exclude); 68 | 69 | /* Concatenate two wide strings with a separator */ 70 | void wcs_concat2(WCHAR *dest, int len, const WCHAR *src1, const WCHAR *src2, const WCHAR *sep); 71 | 72 | void CloseSemaphore(HANDLE sem); 73 | 74 | /* Close a handle if not null or invalid */ 75 | void CloseHandleEx(LPHANDLE h); 76 | 77 | /* Decode url encoded charcters in src and return the result as a newly 78 | * allocated string. Returns NULL on error. 79 | */ 80 | char *url_decode(const char *src); 81 | 82 | /* digest functions */ 83 | typedef struct md_ctx 84 | { 85 | HCRYPTPROV prov; 86 | HCRYPTHASH hash; 87 | } md_ctx; 88 | 89 | DWORD md_init(md_ctx *ctx, ALG_ID hash_type); 90 | 91 | DWORD md_update(md_ctx *ctx, const BYTE *data, size_t size); 92 | 93 | DWORD md_final(md_ctx *ctx, BYTE *md); 94 | 95 | /* Open specified http/https URL using ShellExecute. */ 96 | BOOL open_url(const wchar_t *url); 97 | 98 | void ImportConfigFile(const TCHAR *path, bool prompt_user); 99 | 100 | /* 101 | * Helper function to convert UCS-2 text from a dialog item to UTF-8. 102 | * Caller must free *str if *len != 0. 103 | */ 104 | BOOL GetDlgItemTextUtf8(HWND hDlg, int id, LPSTR *str, int *len); 105 | 106 | /* Return escaped copy of a string */ 107 | char *escape_string(const char *str); 108 | 109 | /** 110 | * Find a free port to bind to 111 | * @param addr : Address to bind to -- if port >0 it's tried first. 112 | * On return the port is set to the one found. 113 | * @returns true on success, false on error. In case of error 114 | * addr is unchanged. 115 | */ 116 | BOOL find_free_tcp_port(SOCKADDR_IN *addr); 117 | 118 | /** 119 | * Parse the config file of a connection profile for 120 | * Managegment address and password. 121 | * @param c : Pointer to connection profile 122 | * On return c->manage.skaddr and c->manage.password 123 | * are populated. 124 | * @returns true on success false on error. 125 | * Password not specified in the config file is not an error. 126 | */ 127 | BOOL ParseManagementAddress(connection_t *c); 128 | 129 | /** 130 | * Get dpi of the system and set the scale factor. 131 | * @param o : pointer to the options struct 132 | * On return initializes o.dpi_scale using the logical pixels 133 | * per inch value of the system. 134 | */ 135 | #define DPI_SCALE(x) MulDiv(x, o.dpi_scale, 100) 136 | void dpi_initialize(options_t *o); 137 | 138 | /** 139 | * Write a message to the event log 140 | * @param type : event log type 141 | * @param format : message format in printf style 142 | * @param ... : extra args 143 | */ 144 | void MsgToEventLog(WORD type, wchar_t *format, ...); 145 | 146 | /** 147 | * Check PLAP COM object is is registered 148 | * @returns 1 if yes, 0 if no, or -1 if PLAP dll not installed. 149 | */ 150 | int GetPLAPRegistrationStatus(void); 151 | 152 | /** 153 | * Register/Unregister PLAP COM object 154 | * @param action TRUE to register, FALSE to unregister 155 | * @returns 0 on success or a non-zero error code on error. 156 | * Requires admin privileges -- user will prompted for admin 157 | * credentials or UAC consent if required. 158 | */ 159 | DWORD SetPLAPRegistration(BOOL action); 160 | 161 | /** 162 | * Run a command as admin using shellexecute 163 | * @param cmd The command to run 164 | * @param params Parameters to the command 165 | * @returns 0 on success or a non-zero exit code from the 166 | * command. If the command fails to startup, -1 is returned. 167 | */ 168 | DWORD RunAsAdmin(const WCHAR *cmd, const WCHAR *params); 169 | 170 | /** 171 | * Wait for a timeout while pumping messages. If hdlg is not NULL 172 | * IsDialogMessage(hdlg, ...) is checked before dispatching messages. 173 | * caller can install a WH_MSGFILTER hook if any other special processing 174 | * is necessary. The hook will get called with ncode = MSGF_OVPN_WAIT. 175 | * @returns false if WM_QUIT was received, else returns true on timeout. 176 | */ 177 | bool OVPNMsgWait(DWORD timeout, HWND hdlg); 178 | 179 | bool GetRandomPassword(char *buf, size_t len); 180 | 181 | void ResetPasswordReveal(HWND edit, HWND btn, WPARAM wParam); 182 | 183 | void ChangePasswordVisibility(HWND edit, HWND btn, WPARAM wParam); 184 | 185 | #endif /* ifndef MISC_H */ 186 | -------------------------------------------------------------------------------- /openvpn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2004 Mathias Sundman 5 | * 2010 Heiko Hund 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program (see the file COPYING included with this 19 | * distribution); if not, write to the Free Software Foundation, Inc., 20 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | */ 22 | 23 | #ifndef OPENVPN_H 24 | #define OPENVPN_H 25 | 26 | #include "options.h" 27 | 28 | #define TRY_SETPROP(hwnd, name, p) \ 29 | do \ 30 | { \ 31 | if (SetPropW(hwnd, name, p)) \ 32 | break; \ 33 | MsgToEventLog(EVENTLOG_ERROR_TYPE, L"%hs:%d GetProp returned null", __func__, __LINE__); \ 34 | EndDialog(hwnd, IDABORT); \ 35 | return false; \ 36 | } while (0) 37 | 38 | BOOL StartOpenVPN(connection_t *); 39 | 40 | void StopOpenVPN(connection_t *); 41 | 42 | void DetachOpenVPN(connection_t *); 43 | 44 | void SuspendOpenVPN(int config); 45 | 46 | void RestartOpenVPN(connection_t *); 47 | 48 | void ReleaseOpenVPN(connection_t *); 49 | 50 | BOOL CheckVersion(); 51 | 52 | void SetStatusWinIcon(HWND hwndDlg, int IconID); 53 | 54 | void OnReady(connection_t *, char *); 55 | 56 | void OnHold(connection_t *, char *); 57 | 58 | void OnLogLine(connection_t *, char *); 59 | 60 | void OnStateChange(connection_t *, char *); 61 | 62 | void OnPassword(connection_t *, char *); 63 | 64 | void OnStop(connection_t *, char *); 65 | 66 | void OnNeedOk(connection_t *, char *); 67 | 68 | void OnNeedStr(connection_t *, char *); 69 | 70 | void OnEcho(connection_t *, char *); 71 | 72 | void OnByteCount(connection_t *, char *); 73 | 74 | void OnInfoMsg(connection_t *, char *); 75 | 76 | void OnTimeout(connection_t *, char *); 77 | 78 | void ResetSavePasswords(connection_t *); 79 | 80 | extern const TCHAR *cfgProp; 81 | 82 | /* These error codes are from openvpn service sources */ 83 | #define ERROR_OPENVPN_STARTUP 0x20000000 84 | #define ERROR_STARTUP_DATA 0x20000001 85 | #define ERROR_MESSAGE_DATA 0x20000002 86 | #define ERROR_MESSAGE_TYPE 0x20000003 87 | 88 | /* Write a line to status window and optionally to the log file */ 89 | void WriteStatusLog(connection_t *c, const WCHAR *prefix, const WCHAR *line, BOOL fileio); 90 | 91 | #define FLAG_CR_TYPE_SCRV1 0x1 /* static challenege */ 92 | #define FLAG_CR_TYPE_CRV1 0x2 /* dynamic challenege */ 93 | #define FLAG_CR_ECHO 0x4 /* echo the response */ 94 | #define FLAG_CR_RESPONSE 0x8 /* response needed */ 95 | #define FLAG_PASS_TOKEN 0x10 /* PKCS11 token password needed */ 96 | #define FLAG_STRING_PKCS11 0x20 /* PKCS11 id needed */ 97 | #define FLAG_PASS_PKEY 0x40 /* Private key password needed */ 98 | #define FLAG_CR_TYPE_CRTEXT 0x80 /* crtext */ 99 | #define FLAG_CR_TYPE_CONCAT 0x100 /* concatenate otp with password */ 100 | 101 | typedef struct 102 | { 103 | connection_t *c; 104 | unsigned int flags; 105 | char *str; 106 | char *id; 107 | char *user; 108 | char *cr_response; 109 | } auth_param_t; 110 | 111 | /* 112 | * Parse dynamic challenge string received from the server. Returns 113 | * true on success. The caller must free param->str and param->id 114 | * even on error. 115 | */ 116 | BOOL parse_dynamic_cr(const char *str, auth_param_t *param); 117 | 118 | void free_auth_param(auth_param_t *param); 119 | 120 | /* 121 | * Given an OpenVPN state as reported by the management interface 122 | * return the correspnding resource id for translation. 123 | */ 124 | int daemon_state_resid(const char *name); 125 | 126 | #endif /* ifndef OPENVPN_H */ 127 | -------------------------------------------------------------------------------- /openvpn_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2004 Mathias Sundman 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef OPENVPN_CONFIG_H 23 | #define OPENVPN_CONFIG_H 24 | 25 | #include "main.h" 26 | 27 | void BuildFileList(void); 28 | 29 | bool ConfigFileOptionExist(int, const char *); 30 | 31 | void FreeConfigList(options_t *o); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /options.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2004 Mathias Sundman 5 | * 2010 Heiko Hund 6 | * 2016 Selva Nair 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program (see the file COPYING included with this 20 | * distribution); if not, write to the Free Software Foundation, Inc., 21 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | * 23 | */ 24 | 25 | #ifndef OPTIONS_H 26 | #define OPTIONS_H 27 | 28 | typedef struct connection connection_t; 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "manage.h" 36 | #include "echo.h" 37 | #include "pkcs11.h" 38 | 39 | #define MAX_NAME (UNLEN + 1) 40 | 41 | /* 42 | * Maximum number of parameters associated with an option, 43 | * including the option name itself. 44 | */ 45 | #define MAX_PARMS 5 /* Max number of parameters per option */ 46 | 47 | typedef enum 48 | { 49 | service_noaccess = -1, 50 | service_disconnected = 0, 51 | service_connecting = 1, 52 | service_connected = 2 53 | } service_state_t; 54 | 55 | typedef enum 56 | { 57 | config, 58 | windows, 59 | manual 60 | } proxy_source_t; 61 | 62 | typedef enum 63 | { 64 | http, 65 | socks 66 | } proxy_t; 67 | 68 | /* connection states */ 69 | typedef enum 70 | { 71 | disconnected, 72 | onhold, 73 | connecting, 74 | reconnecting, 75 | connected, 76 | disconnecting, 77 | suspending, 78 | suspended, 79 | resuming, 80 | detaching, 81 | detached, 82 | } conn_state_t; 83 | 84 | /* Interactive Service IO parameters */ 85 | typedef struct 86 | { 87 | OVERLAPPED o; /* This has to be the first element */ 88 | HANDLE pipe; 89 | HANDLE hEvent; 90 | WCHAR readbuf[512]; 91 | } service_io_t; 92 | 93 | #define FLAG_ALLOW_CHANGE_PASSPHRASE (1 << 1) 94 | #define FLAG_SAVE_KEY_PASS (1 << 4) 95 | #define FLAG_SAVE_AUTH_PASS (1 << 5) 96 | #define FLAG_DISABLE_SAVE_PASS (1 << 6) 97 | #define FLAG_DISABLE_ECHO_MSG (1 << 7) 98 | #define FLAG_DAEMON_PERSISTENT (1 << 8) 99 | #define FLAG_WAIT_UNLOCK (1 << 9) 100 | #define FLAG_CONFIG_DISABLED (1 << 10) 101 | 102 | #define CONFIG_VIEW_AUTO (0) 103 | #define CONFIG_VIEW_FLAT (1) 104 | #define CONFIG_VIEW_NESTED (2) 105 | 106 | #define OPENVPN_ENGINE_OVPN2 (0) 107 | #define OPENVPN_ENGINE_OVPN3 (1) 108 | 109 | typedef struct 110 | { 111 | unsigned short major, minor, build, revision; 112 | } version_t; 113 | 114 | /* A node of config groups tree that can be navigated from the end 115 | * node (where config file is attached) to the root. The nodes are stored 116 | * as array (o.groups[]) with each node linked to its parent. 117 | * Not a complete tree: only navigation from child to parent is supported 118 | * which is enough for our purposes. 119 | */ 120 | typedef struct config_group 121 | { 122 | int id; /* A unique id for the group >= 0*/ 123 | wchar_t name[40]; /* Name of the group -- possibly truncated */ 124 | int parent; /* Id of parent group. -1 implies no parent */ 125 | BOOL active; /* Displayed in the menu if true -- used to prune empty groups */ 126 | int children; /* Number of children groups and configs */ 127 | int pos; /* Index within the parent group -- used for rendering */ 128 | HMENU menu; /* Handle to menu entry for this group */ 129 | } config_group_t; 130 | 131 | /* short hand for pointer to the group a config belongs to */ 132 | #define CONFIG_GROUP(c) (&o.groups[(c)->group]) 133 | #define PARENT_GROUP(cg) ((cg)->parent < 0 ? NULL : &o.groups[(cg)->parent]) 134 | #define PERSISTENT_ROOT_GROUP (&o.groups[1]) 135 | 136 | /* Connections parameters */ 137 | struct connection 138 | { 139 | TCHAR config_file[MAX_PATH]; /* Name of the config file */ 140 | TCHAR config_name[MAX_PATH]; /* Name of the connection */ 141 | TCHAR config_dir[MAX_PATH]; /* Path to this configs dir */ 142 | TCHAR log_path[MAX_PATH]; /* Path to Logfile */ 143 | TCHAR ip[16]; /* Assigned IP address for this connection */ 144 | TCHAR ipv6[46]; /* Assigned IPv6 address */ 145 | BOOL auto_connect; /* AutoConnect at startup id TRUE */ 146 | conn_state_t state; /* State the connection currently is in */ 147 | int failed_psw_attempts; /* # of failed attempts entering password(s) */ 148 | int failed_auth_attempts; /* # of failed user-auth attempts */ 149 | time_t connected_since; /* Time when the connection was established */ 150 | proxy_t proxy_type; /* Set during querying proxy credentials */ 151 | int group; /* ID of the group this config belongs to */ 152 | int pos; /* Index of the config within its group */ 153 | 154 | struct 155 | { 156 | SOCKET sk; 157 | SOCKADDR_IN skaddr; 158 | time_t timeout; 159 | char password[4096]; /* match with largest possible passwd in openvpn.exe */ 160 | char *saved_data; 161 | size_t saved_size; 162 | mgmt_cmd_t *cmd_queue; 163 | DWORD connected; /* 1: management interface connected, 2: connected and ready */ 164 | } manage; 165 | 166 | HANDLE hProcess; /* Handle of openvpn process if directly started */ 167 | service_io_t iserv; 168 | 169 | HANDLE exit_event; 170 | DWORD threadId; 171 | HWND hwndStatus; 172 | int flags; 173 | char *dynamic_cr; /* Pointer to buffer for dynamic challenge string received */ 174 | unsigned long long int bytes_in; 175 | unsigned long long int bytes_out; 176 | struct env_item *es; /* Pointer to the head of config-specific env variables list */ 177 | struct echo_msg echo_msg; /* Message echo-ed from server or client config and related data */ 178 | struct pkcs11_list pkcs11_list; 179 | char daemon_state[20]; /* state of openvpn.ex: WAIT, AUTH, GET_CONFIG etc.. */ 180 | int id; /* index of config -- treat as immutable once assigned */ 181 | connection_t *next; 182 | }; 183 | 184 | /* All options used within OpenVPN GUI */ 185 | typedef struct 186 | { 187 | /* Array of configs to autostart */ 188 | const TCHAR **auto_connect; 189 | 190 | /* Connection parameters */ 191 | connection_t *chead; /* Head of connection list */ 192 | connection_t *ctail; /* Tail of connection list */ 193 | config_group_t *groups; /* Array of nodes defining the config groups tree */ 194 | int num_configs; /* Number of configs */ 195 | int num_auto_connect; /* Number of auto-connect configs */ 196 | int num_groups; /* Number of config groups */ 197 | int max_configs; /* Current capacity of conn array */ 198 | int max_auto_connect; /* Current capacity of auto_connect array */ 199 | int max_groups; /* Current capacity of groups array */ 200 | 201 | service_state_t service_state; /* State of the OpenVPN Service */ 202 | 203 | /* Proxy Settings */ 204 | proxy_source_t proxy_source; /* Where to get proxy information from */ 205 | proxy_t proxy_type; /* The type of proxy to use */ 206 | TCHAR proxy_http_address[100]; /* HTTP Proxy Address */ 207 | TCHAR proxy_http_port[6]; /* HTTP Proxy Port */ 208 | TCHAR proxy_socks_address[100]; /* SOCKS Proxy Address */ 209 | TCHAR proxy_socks_port[6]; /* SOCKS Proxy Address */ 210 | 211 | /* HKLM Registry values */ 212 | TCHAR exe_path[MAX_PATH]; 213 | TCHAR install_path[MAX_PATH]; 214 | TCHAR global_config_dir[MAX_PATH]; 215 | TCHAR config_auto_dir[MAX_PATH]; 216 | TCHAR global_log_dir[MAX_PATH]; 217 | TCHAR priority_string[64]; 218 | TCHAR ovpn_admin_group[MAX_NAME]; 219 | DWORD disable_save_passwords; 220 | DWORD auth_pass_concat_otp; 221 | /* HKCU registry values */ 222 | TCHAR config_dir[MAX_PATH]; 223 | TCHAR ext_string[16]; 224 | TCHAR log_dir[MAX_PATH]; 225 | DWORD log_append; 226 | TCHAR log_viewer[MAX_PATH]; 227 | TCHAR editor[MAX_PATH]; 228 | DWORD silent_connection; 229 | DWORD iservice_admin; 230 | DWORD show_balloon; 231 | DWORD show_script_window; 232 | DWORD connectscript_timeout; /* Connect Script execution timeout (sec) */ 233 | DWORD disconnectscript_timeout; /* Disconnect Script execution timeout (sec) */ 234 | DWORD preconnectscript_timeout; /* Preconnect Script execution timeout (sec) */ 235 | DWORD config_menu_view; /* 0 for auto, 1 for original flat menu, 2 for hierarchical */ 236 | DWORD disable_popup_messages; /* set nonzero to suppress all echo msg messages */ 237 | DWORD popup_mute_interval; /* Interval in hours to suppress repeated echo messages */ 238 | DWORD mgmt_port_offset; /* management interface port = this offset + index of connection profile 239 | */ 240 | 241 | DWORD ovpn_engine; /* 0 - openvpn2, 1 - openvpn3 */ 242 | DWORD enable_persistent; /* 0 - disabled, 1 - enabled, 2 - enabled & auto attach */ 243 | DWORD enable_auto_restart; /* 0 - disabled, >0 enabled */ 244 | DWORD disable_password_reveal; /* read from group policy */ 245 | #ifdef DEBUG 246 | FILE *debug_fp; 247 | #endif 248 | 249 | HWND hWnd; 250 | HINSTANCE hInstance; 251 | BOOL session_locked; 252 | HANDLE netcmd_semaphore; 253 | version_t version; 254 | char ovpn_version[16]; /* OpenVPN version string: 2.3.12, 2.4_alpha2 etc.. */ 255 | unsigned int dpi_scale; 256 | COLORREF clr_warning; 257 | COLORREF clr_error; 258 | int action; /* action to send to a running instance */ 259 | TCHAR *action_arg; 260 | HANDLE session_semaphore; 261 | HANDLE event_log; 262 | DWORD use_qr_for_url; /* display QR code instead of opening a web browser with a URL, used by 263 | PLAP */ 264 | } options_t; 265 | 266 | void InitOptions(options_t *); 267 | 268 | void ProcessCommandLine(options_t *, TCHAR *); 269 | 270 | int CountConnState(conn_state_t); 271 | 272 | connection_t *GetConnByManagement(SOCKET); 273 | 274 | connection_t *GetConnByName(const WCHAR *config_name); 275 | 276 | INT_PTR CALLBACK ScriptSettingsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); 277 | 278 | INT_PTR CALLBACK ConnectionSettingsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); 279 | 280 | INT_PTR CALLBACK AdvancedSettingsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); 281 | 282 | void DisableSavePasswords(connection_t *); 283 | 284 | void DisablePopupMessages(connection_t *); 285 | 286 | void ExpandOptions(void); 287 | 288 | int CompareStringExpanded(const WCHAR *str1, const WCHAR *str2); 289 | 290 | #endif /* ifndef OPTIONS_H */ 291 | -------------------------------------------------------------------------------- /pkcs11.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2022 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef PKCS11_H 23 | #define PKCS11_H 24 | 25 | struct pkcs11_list 26 | { 27 | unsigned int count; /* number of pkcs11 entries */ 28 | unsigned int selected; /* entry selected by user: -1 if no selection */ 29 | unsigned int state; /* a flag indicating list filling status */ 30 | struct pkcs11_entry *pe; /* array of pkcs11-id entries */ 31 | }; 32 | 33 | struct connection; 34 | /** 35 | * Callback for Need 'pkcs11-id-request' notification from management 36 | * @param c pointer to connection profile 37 | * @param msg string received from the management 38 | */ 39 | void OnPkcs11(struct connection *c, char *msg); 40 | 41 | /** 42 | * Clear pkcs11 entry list and release memory. 43 | * @param l pointer to the list 44 | * 45 | */ 46 | void pkcs11_list_clear(struct pkcs11_list *l); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /plap/Makefile.am: -------------------------------------------------------------------------------- 1 | # OpenVPN-PLAP-Provider 2 | # 3 | # Copyright (C) 2021-2022 Selva Nair 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program (see the file COPYING included with this 17 | # distribution); if not, write to the Free Software Foundation, Inc., 18 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | RCCOMPILE = $(WINDRES) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ 21 | $(AM_CPPFLAGS) $(CPPFLAGS) 22 | LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RCCOMPILE) 23 | 24 | .rc.lo: 25 | $(LTRCCOMPILE) -i "$<" -o "$@" 26 | 27 | .rc.o: 28 | $(RCCOMPILE) -i "$<" -o "$@" 29 | 30 | MAINTAINERCLEANFILES = \ 31 | $(srcdir)/Makefile.in $(srcdir)/credentialprovider.h 32 | 33 | #if ENABLE_OPENVPN_PLAP_TEST 34 | bin_PROGRAMS = test_plap 35 | #endif 36 | lib_LTLIBRARIES = libopenvpn_plap.la 37 | 38 | AM_CPPFLAGS = -I$(srcdir)/.. 39 | 40 | libopenvpn_plap_la_CFLAGS = -D_UNICODE -municode 41 | test_plap_CXXFLAGS = -DDEBUG -D_UNICODE -municode 42 | 43 | libopenvpn_plap_la_RESOURCES = \ 44 | $(top_srcdir)/res/openvpn-gui-res-cs.rc \ 45 | $(top_srcdir)/res/openvpn-gui-res-de.rc \ 46 | $(top_srcdir)/res/openvpn-gui-res-dk.rc \ 47 | $(top_srcdir)/res/openvpn-gui-res-en.rc \ 48 | $(top_srcdir)/res/openvpn-gui-res-es.rc \ 49 | $(top_srcdir)/res/openvpn-gui-res-fa.rc \ 50 | $(top_srcdir)/res/openvpn-gui-res-fi.rc \ 51 | $(top_srcdir)/res/openvpn-gui-res-fr.rc \ 52 | $(top_srcdir)/res/openvpn-gui-res-it.rc \ 53 | $(top_srcdir)/res/openvpn-gui-res-jp.rc \ 54 | $(top_srcdir)/res/openvpn-gui-res-kr.rc \ 55 | $(top_srcdir)/res/openvpn-gui-res-nl.rc \ 56 | $(top_srcdir)/res/openvpn-gui-res-no.rc \ 57 | $(top_srcdir)/res/openvpn-gui-res-pl.rc \ 58 | $(top_srcdir)/res/openvpn-gui-res-pt.rc \ 59 | $(top_srcdir)/res/openvpn-gui-res-ru.rc \ 60 | $(top_srcdir)/res/openvpn-gui-res-se.rc \ 61 | $(top_srcdir)/res/openvpn-gui-res-tr.rc \ 62 | $(top_srcdir)/res/openvpn-gui-res-ua.rc \ 63 | $(top_srcdir)/res/openvpn-gui-res-zh-hans.rc \ 64 | $(top_srcdir)/res/openvpn-gui-res-zh-hant.rc \ 65 | $(top_srcdir)/res/connected.ico \ 66 | $(top_srcdir)/res/connecting.ico \ 67 | $(top_srcdir)/res/disconnected.ico \ 68 | $(top_srcdir)/res/openvpn-gui.ico \ 69 | $(top_srcdir)/res/reconnecting.ico \ 70 | $(top_srcdir)/res/eye.ico \ 71 | $(top_srcdir)/res/eye-stroke.ico \ 72 | openvpn-plap-res.rc \ 73 | openvpn-plap.manifest 74 | 75 | openvpn-plap-res.lo: $(libopenvpn_plap_la_RESOURCES) $(top_srcdir)/openvpn-gui-res.h 76 | EXTRA_DIST = \ 77 | openvpn_plap.def \ 78 | openvpn-plap-install.reg \ 79 | openvpn-plap-res.rc \ 80 | openvpn-plap-uninstall.reg \ 81 | openvpn-plap.manifest 82 | 83 | BUILT_SOURCES = credentialprovider.h 84 | libopenvpn_plap_la_SOURCES = \ 85 | credentialprovider.h \ 86 | stub.c plap_provider.c \ 87 | plap_connection.h plap_connection.c \ 88 | plap_common.h plap_common.c \ 89 | plap_dll.h plap_dll.c \ 90 | resource.h \ 91 | ui_glue.h ui_glue.c \ 92 | $(top_srcdir)/openvpn.c \ 93 | $(top_srcdir)/localization.h\ 94 | $(top_srcdir)/localization.c\ 95 | $(top_srcdir)/options.h \ 96 | $(top_srcdir)/options.c \ 97 | $(top_srcdir)/proxy.c \ 98 | $(top_srcdir)/registry.c \ 99 | $(top_srcdir)/manage.c \ 100 | $(top_srcdir)/misc.c \ 101 | $(top_srcdir)/openvpn_config.c \ 102 | $(top_srcdir)/config_parser.c \ 103 | $(top_srcdir)/pkcs11.c \ 104 | $(top_srcdir)/service.c \ 105 | $(top_srcdir)/qr.c \ 106 | $(top_srcdir)/qr.h \ 107 | $(top_srcdir)/qrcodegen/qrcodegen.c \ 108 | $(top_srcdir)/qrcodegen/qrcodegen.h \ 109 | openvpn-plap-res.rc 110 | 111 | libopenvpn_plap_la_LIBADD = \ 112 | -lws2_32 \ 113 | -lcomctl32 \ 114 | -lwinhttp \ 115 | -lcrypt32 \ 116 | -lole32 \ 117 | -lshlwapi \ 118 | -lgdi32 \ 119 | -lrpcrt4 120 | 121 | libopenvpn_plap_la_LDFLAGS = -no-undefined -avoid-version -static-libgcc 122 | 123 | credentialprovider.h: 124 | wget https://raw.githubusercontent.com/mirror/mingw-w64/master/mingw-w64-headers/include/credentialprovider.h 125 | 126 | test_plap_SOURCES = test_plap.cpp test-plap-res.rc test-plap.manifest plap_common.c credentialprovider.h 127 | test_plap_LDFLAGS = -static-libgcc -static-libstdc++ 128 | test_plap_LDADD = -lrpcrt4 -lole32 -lgdi32 -lcomctl32 129 | -------------------------------------------------------------------------------- /plap/openvpn-plap-install.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\PLAP Providers\{4fbb8b67-cf02-4982-a7a8-3dd06a2c2ebd}] 4 | @="OpenVPNProvider" 5 | 6 | [HKEY_CLASSES_ROOT\CLSID\{4fbb8b67-cf02-4982-a7a8-3dd06a2c2ebd}] 7 | @="OpenVPNProvider" 8 | 9 | [HKEY_CLASSES_ROOT\CLSID\{4fbb8b67-cf02-4982-a7a8-3dd06a2c2ebd}\InprocServer32] 10 | @="C:\\Program Files\\OpenVPN\\bin\\libopenvpn_plap.dll" 11 | "ThreadingModel"="Apartment" 12 | -------------------------------------------------------------------------------- /plap/openvpn-plap-res.rc: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2009 Heiko Hund 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include 24 | #endif 25 | 26 | #include 27 | #include 28 | #include "../openvpn-gui-res.h" 29 | #include "resource.h" 30 | 31 | /* Language resource files are UTF-8 encoded */ 32 | #pragma code_page(65001) 33 | 34 | /* Manifest for version 6 common controls */ 35 | ISOLATIONAWARE_MANIFEST_RESOURCE_ID RT_MANIFEST "openvpn-plap.manifest" 36 | 37 | /* Application Icons */ 38 | ID_ICO_APP ICON DISCARDABLE "../res/openvpn-gui.ico" 39 | ID_ICO_CONNECTED ICON DISCARDABLE "../res/connected.ico" 40 | ID_ICO_CONNECTING ICON DISCARDABLE "../res/connecting.ico" 41 | ID_ICO_DISCONNECTED ICON DISCARDABLE "../res/disconnected.ico" 42 | ID_ICO_EYE ICON DISCARDABLE "../res/eye.ico" 43 | ID_ICO_EYESTROKE ICON DISCARDABLE "../res/eye-stroke.ico" 44 | 45 | IDB_TILE_IMAGE BITMAP DISCARDABLE "../res/tileimage.bmp" 46 | 47 | #ifdef ENABLE_OVPN3 48 | #define ADVANCED_DIALOG_HEIGHT 320 49 | #else 50 | #define ADVANCED_DIALOG_HEIGHT 280 51 | #endif 52 | 53 | #include "../res/openvpn-gui-res-cs.rc" 54 | #include "../res/openvpn-gui-res-de.rc" 55 | #include "../res/openvpn-gui-res-dk.rc" 56 | #include "../res/openvpn-gui-res-en.rc" 57 | #include "../res/openvpn-gui-res-es.rc" 58 | #include "../res/openvpn-gui-res-fa.rc" 59 | #include "../res/openvpn-gui-res-fi.rc" 60 | #include "../res/openvpn-gui-res-fr.rc" 61 | #include "../res/openvpn-gui-res-it.rc" 62 | #include "../res/openvpn-gui-res-jp.rc" 63 | #include "../res/openvpn-gui-res-kr.rc" 64 | #include "../res/openvpn-gui-res-nl.rc" 65 | #include "../res/openvpn-gui-res-no.rc" 66 | #include "../res/openvpn-gui-res-pl.rc" 67 | #include "../res/openvpn-gui-res-pt.rc" 68 | #include "../res/openvpn-gui-res-ru.rc" 69 | #include "../res/openvpn-gui-res-se.rc" 70 | #include "../res/openvpn-gui-res-tr.rc" 71 | #include "../res/openvpn-gui-res-ua.rc" 72 | #include "../res/openvpn-gui-res-zh-hans.rc" 73 | #include "../res/openvpn-gui-res-zh-hant.rc" 74 | 75 | /* Version information and such */ 76 | VS_VERSION_INFO VERSIONINFO 77 | FILEVERSION PACKAGE_VERSION_RESOURCE 78 | PRODUCTVERSION PACKAGE_VERSION_RESOURCE 79 | FILEOS VOS_NT 80 | FILETYPE VFT_DLL 81 | BEGIN 82 | BLOCK "VarFileInfo" 83 | BEGIN 84 | VALUE "Translation" 85 | , LANG_CZECH, 1200 86 | , LANG_GERMAN, 1200 87 | , LANG_DANISH, 1200 88 | , LANG_ENGLISH, 1200 89 | , LANG_SPANISH, 1200 90 | , LANG_FARSI, 1200 91 | , LANG_FINNISH, 1200 92 | , LANG_FRENCH, 1200 93 | , LANG_ITALIAN, 1200 94 | , LANG_JAPANESE, 1200 95 | , LANG_DUTCH, 1200 96 | , LANG_NORWEGIAN, 1200 97 | , LANG_POLISH, 1200 98 | , LANG_PORTUGUESE, 1200 99 | , LANG_RUSSIAN, 1200 100 | , LANG_SWEDISH, 1200 101 | , LANG_TURKISH, 1200 102 | , LANG_UKRAINIAN, 1200 103 | , LANG_CHINESE, 1200 104 | , LANG_KOREAN, 1200 105 | END 106 | 107 | BLOCK "StringFileInfo" 108 | BEGIN 109 | BLOCK "040904B0" /* en_US, Unicode */ 110 | BEGIN 111 | VALUE "FileDescription", "OpenVPN PLAP for Windows" 112 | VALUE "FileVersion", PACKAGE_VERSION_RESOURCE_STR 113 | VALUE "InternalName", "openvpn-plap" 114 | VALUE "OriginalFilename", "libopenvpn_plap.dll" 115 | VALUE "ProductName", "OpenVPN PLAP" 116 | VALUE "ProductVersion", PACKAGE_VERSION_RESOURCE_STR 117 | VALUE "Website", PACKAGE_URL 118 | VALUE "LegalCopyright", "Selva Nair and other " PACKAGE_NAME " developers" 119 | VALUE "CompanyName", "OpenVPN Community" 120 | END 121 | END 122 | END 123 | -------------------------------------------------------------------------------- /plap/openvpn-plap-uninstall.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\PLAP Providers\{4fbb8b67-cf02-4982-a7a8-3dd06a2c2ebd}] 4 | 5 | [-HKEY_CLASSES_ROOT\CLSID\{4fbb8b67-cf02-4982-a7a8-3dd06a2c2ebd}] 6 | -------------------------------------------------------------------------------- /plap/openvpn-plap.manifest: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 9 | 10 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /plap/openvpn_plap.def: -------------------------------------------------------------------------------- 1 | LIBRARY libopenvpn_plap.dll 2 | 3 | EXPORTS 4 | DllCanUnloadNow PRIVATE 5 | DllGetClassObject PRIVATE 6 | -------------------------------------------------------------------------------- /plap/plap_common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-PLAP-Provider 3 | * 4 | * Copyright (C) 2017-2022 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include 24 | #endif 25 | 26 | #include "plap_common.h" 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "localization.h" 33 | static FILE *fp; 34 | static CRITICAL_SECTION log_write; 35 | 36 | void 37 | init_debug() 38 | { 39 | if (!fp) 40 | { 41 | _wfopen_s(&fp, L"C:\\Windows\\Temp\\openvpn-plap-debug.txt", L"a+,ccs=UTF-8"); 42 | } 43 | InitializeCriticalSection(&log_write); 44 | } 45 | 46 | void 47 | uninit_debug() 48 | { 49 | if (fp) 50 | { 51 | fclose(fp); 52 | } 53 | DeleteCriticalSection(&log_write); 54 | } 55 | 56 | void 57 | x_dmsg(const char *file, const char *func, const wchar_t *fmt, ...) 58 | { 59 | wchar_t buf[1024]; 60 | if (!fp) 61 | { 62 | return; 63 | } 64 | 65 | va_list args; 66 | va_start(args, fmt); 67 | vswprintf(buf, _countof(buf), fmt, args); 68 | va_end(args); 69 | 70 | wchar_t date[30]; 71 | time_t log_time = time(NULL); 72 | struct tm *time_struct = localtime(&log_time); 73 | _snwprintf_s(date, 74 | _countof(date), 75 | _TRUNCATE, 76 | L"%d-%.2d-%.2d %.2d:%.2d:%.2d", 77 | time_struct->tm_year + 1900, 78 | time_struct->tm_mon + 1, 79 | time_struct->tm_mday, 80 | time_struct->tm_hour, 81 | time_struct->tm_min, 82 | time_struct->tm_sec); 83 | 84 | EnterCriticalSection(&log_write); 85 | 86 | if (file && func) 87 | { 88 | fwprintf(fp, L"%ls %hs:%hs: %ls\n", date, file, func, buf); 89 | } 90 | else 91 | { 92 | fwprintf(fp, L"%ls %ls\n", date, buf); 93 | } 94 | fflush(fp); 95 | 96 | LeaveCriticalSection(&log_write); 97 | } 98 | 99 | void 100 | debug_print_guid(const GUID *riid, const wchar_t *context) 101 | { 102 | RPC_CSTR str = NULL; 103 | if (UuidToStringA((GUID *)riid, &str) == RPC_S_OK) 104 | { 105 | x_dmsg(NULL, NULL, L"%ls %hs", context, str); 106 | RpcStringFreeA(&str); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /plap/plap_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-PLAP-Provider 3 | * 4 | * Copyright (C) 2017-2022 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef PLAP_HELPER_H 23 | #define PLAP_HELPER_H 24 | 25 | #include /* avoids warning about winsock2 not included first */ 26 | #include 27 | 28 | #ifdef __GNUC__ 29 | #define UNUSED __attribute__((unused)) 30 | #else 31 | #define UNUSED 32 | #endif 33 | 34 | #ifdef __cplusplus 35 | extern "C" 36 | { 37 | #endif 38 | 39 | #ifdef DEBUG 40 | #define dmsg(fmt, ...) x_dmsg(__FILE__, __func__, fmt, ##__VA_ARGS__) 41 | #else 42 | #define dmsg(...) \ 43 | do \ 44 | { \ 45 | ; \ 46 | } while (0) 47 | #endif 48 | 49 | void x_dmsg(const char *file, const char *func, const wchar_t *fmt, ...); 50 | 51 | void init_debug(); 52 | 53 | void uninit_debug(); 54 | 55 | void debug_print_guid(const GUID *riid, const wchar_t *context); 56 | 57 | /* Shortcuts for cumbersome calls to COM methods of an object through its v-table */ 58 | #define ADDREF(p) (p)->lpVtbl->AddRef(p) 59 | #define RELEASE(p) (p)->lpVtbl->Release(p) 60 | #define QUERY_INTERFACE(p, riid, ppv) (p)->lpVtbl->QueryInterface(p, riid, ppv) 61 | 62 | #ifdef __cplusplus 63 | } 64 | #endif 65 | 66 | #endif /* PLAP_HELPER_H */ 67 | 68 | /* GUID for a OpenVPNProvider -- created using uuidgen -r 69 | * The following must be outside any include guards. Include 70 | * before including this file in one location where this GUID has to be created. 71 | * In other places this will get defined as an extern. 72 | */ 73 | #ifdef DEFINE_GUID 74 | DEFINE_GUID(CLSID_OpenVPNProvider, 75 | 0x4fbb8b67, 76 | 0xcf02, 77 | 0x4982, 78 | 0xa7, 79 | 0xa8, 80 | 0x3d, 81 | 0xd0, 82 | 0x6a, 83 | 0x2c, 84 | 0x2e, 85 | 0xbd); 86 | #endif 87 | -------------------------------------------------------------------------------- /plap/plap_connection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-PLAP-Provider 3 | * 4 | * Copyright (C) 2017-2022 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef PLAP_CONNECTION_H 23 | #define PLAP_CONNECTION_H 24 | 25 | #include "plap_common.h" 26 | #include "ui_glue.h" 27 | #include 28 | #include 29 | 30 | /** 31 | * Field descriptors for the connection tiles shown to user. 32 | * array of {index, type, name, guid } -- guid unused here. 33 | */ 34 | static const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR field_desc[] = { 35 | { 0, CPFT_TILE_IMAGE, (wchar_t *)L"Image", { 0 } }, 36 | { 1, CPFT_LARGE_TEXT, (wchar_t *)L"VPN Profile", { 0 } }, 37 | { 2, CPFT_SUBMIT_BUTTON, (wchar_t *)L"Connect", { 0 } }, 38 | { 3, CPFT_SMALL_TEXT, (wchar_t *)L"Status", { 0 } }, 39 | }; 40 | 41 | #define STATUS_FIELD_INDEX 3 /* index to the status text in the above array */ 42 | 43 | /** Field states -- show image and name always, rest when selected */ 44 | static const CREDENTIAL_PROVIDER_FIELD_STATE field_states[] = { 45 | CPFS_DISPLAY_IN_BOTH, /* image */ 46 | CPFS_DISPLAY_IN_BOTH, /* profile name */ 47 | CPFS_DISPLAY_IN_SELECTED_TILE, /* button */ 48 | CPFS_DISPLAY_IN_SELECTED_TILE, /* status text */ 49 | }; 50 | 51 | /** Helper to deep copy field descriptor */ 52 | HRESULT CopyFieldDescriptor(CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR *fd_out, 53 | const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR *fd_in); 54 | 55 | typedef struct OpenVPNConnection OpenVPNConnection; 56 | 57 | HRESULT WINAPI OVPNConnection_Initialize(OpenVPNConnection *, 58 | connection_t *conn, 59 | const wchar_t *display_name); 60 | 61 | OpenVPNConnection *OpenVPNConnection_new(void); 62 | 63 | #endif /* PLAP_CONNECTION_H */ 64 | -------------------------------------------------------------------------------- /plap/plap_dll.c: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-PLAP-Provider 3 | * 4 | * Copyright (C) 2017-2022 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include 24 | #endif 25 | 26 | #include /* needed to define (not extern) the GUIDs */ 27 | #include 28 | #include 29 | #include "plap_common.h" 30 | #include "plap_dll.h" 31 | 32 | static LONG dll_ref_count = 0; 33 | 34 | HINSTANCE hinst_global = NULL; 35 | 36 | /* 37 | * Dll Entry Point 38 | */ 39 | BOOL WINAPI 40 | DllMain(HINSTANCE hinstDll, DWORD dwReason, UNUSED LPVOID pReserved) 41 | { 42 | dmsg(L"Entry with dwReason = %lu", dwReason); 43 | 44 | switch (dwReason) 45 | { 46 | case DLL_PROCESS_ATTACH: 47 | /* as per MSDN, this reduces the size of application */ 48 | DisableThreadLibraryCalls(hinstDll); 49 | init_debug(); 50 | break; 51 | 52 | case DLL_PROCESS_DETACH: 53 | uninit_debug(); 54 | break; 55 | 56 | case DLL_THREAD_ATTACH: 57 | case DLL_THREAD_DETACH: 58 | break; 59 | } 60 | 61 | hinst_global = hinstDll; /* global */ 62 | return TRUE; 63 | } 64 | 65 | void 66 | dll_addref() 67 | { 68 | InterlockedIncrement(&dll_ref_count); 69 | dmsg(L"ref_count after increment = %lu", dll_ref_count); 70 | } 71 | 72 | void 73 | dll_release() 74 | { 75 | InterlockedDecrement(&dll_ref_count); 76 | dmsg(L"ref_count after decrement = %lu", dll_ref_count); 77 | } 78 | 79 | /* A class factory that can create instances of OpenVPNProvider 80 | * This is returned in the exported function DllGetClassObject 81 | * We use a static instance. 82 | */ 83 | 84 | /* ClassFactory methods we have to implement */ 85 | static ULONG WINAPI AddRef(IClassFactory *this); 86 | 87 | static ULONG WINAPI Release(IClassFactory *this); 88 | 89 | static HRESULT WINAPI QueryInterface(IClassFactory *this, REFIID riid, void **ppv); 90 | 91 | static HRESULT WINAPI CreateInstance(IClassFactory *this, IUnknown *iunk, REFIID riid, void **ppv); 92 | 93 | static HRESULT WINAPI LockServer(IClassFactory *this, BOOL lock); 94 | 95 | /* template object for creation */ 96 | static IClassFactoryVtbl cf_vtbl = { 97 | .QueryInterface = QueryInterface, 98 | .AddRef = AddRef, 99 | .Release = Release, 100 | .CreateInstance = CreateInstance, 101 | .LockServer = LockServer, 102 | }; 103 | 104 | static IClassFactory cf = { .lpVtbl = &cf_vtbl }; 105 | 106 | /* Implementation */ 107 | static ULONG WINAPI 108 | AddRef(UNUSED IClassFactory *this) 109 | { 110 | dll_addref(); 111 | return 1; /* we have just 1 static object */ 112 | } 113 | 114 | static ULONG WINAPI 115 | Release(UNUSED IClassFactory *this) 116 | { 117 | dll_release(); 118 | return 1; 119 | } 120 | 121 | static HRESULT WINAPI 122 | QueryInterface(IClassFactory *this, REFIID riid, void **ppv) 123 | { 124 | HRESULT hr; 125 | dmsg(L"Entry"); 126 | 127 | #ifdef DEBUG 128 | debug_print_guid(riid, L"In CF_Queryinterface with iid = "); 129 | #endif 130 | 131 | if (ppv != NULL && riid) 132 | { 133 | if (IsEqualIID(&IID_IClassFactory, riid) || IsEqualIID(&IID_IUnknown, riid)) 134 | { 135 | *ppv = this; 136 | ADDREF(this); 137 | hr = S_OK; 138 | } 139 | else 140 | { 141 | *ppv = NULL; 142 | hr = E_NOINTERFACE; 143 | } 144 | } 145 | else 146 | { 147 | hr = E_POINTER; 148 | } 149 | return hr; 150 | } 151 | 152 | /* Create an instance of OpenVPNProvider and return it in *ppv */ 153 | static HRESULT WINAPI 154 | CreateInstance(UNUSED IClassFactory *this, IUnknown *iunk, REFIID riid, void **ppv) 155 | { 156 | HRESULT hr; 157 | dmsg(L"Entry"); 158 | 159 | #ifdef DEBUG 160 | debug_print_guid(riid, L"In Provider CreateInstance with iid = "); 161 | #endif 162 | 163 | *ppv = NULL; 164 | if (!iunk) 165 | { 166 | hr = OpenVPNProvider_CreateInstance(riid, ppv); 167 | } 168 | else 169 | { 170 | hr = CLASS_E_NOAGGREGATION; 171 | } 172 | return hr; 173 | } 174 | 175 | /* Windows calls this to keep the server in memory: 176 | * we just increment dll-ref-count so that the dll will not get unloaded. 177 | */ 178 | static HRESULT WINAPI 179 | LockServer(UNUSED IClassFactory *this, BOOL lock) 180 | { 181 | if (lock) 182 | { 183 | dll_addref(); 184 | } 185 | else 186 | { 187 | dll_release(); 188 | } 189 | return S_OK; 190 | } 191 | 192 | /* exported methods */ 193 | STDAPI 194 | DllCanUnloadNow() 195 | { 196 | HRESULT hr; 197 | 198 | dmsg(L"ref_count = %lu", dll_ref_count); 199 | if (dll_ref_count > 0) 200 | { 201 | hr = S_FALSE; 202 | } 203 | else 204 | { 205 | hr = S_OK; 206 | } 207 | 208 | return hr; 209 | } 210 | 211 | /* Windows calls this on loading the dll and expects a 212 | * ClassFactory instance in *ppv which can be used to 213 | * create class of type rclsid. We support only OpenVPNProvider 214 | * class and check it here. 215 | */ 216 | STDAPI 217 | DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) 218 | { 219 | dmsg(L"Entry"); 220 | HRESULT hr; 221 | 222 | *ppv = NULL; 223 | if (IsEqualIID(&CLSID_OpenVPNProvider, rclsid)) 224 | { 225 | ADDREF(&cf); /* though we are reusing a static instance, follow the usual COM semantics */ 226 | hr = QUERY_INTERFACE((IClassFactory *)&cf, riid, ppv); 227 | RELEASE((IClassFactory *)&cf); 228 | } 229 | else 230 | { 231 | hr = CLASS_E_CLASSNOTAVAILABLE; 232 | } 233 | return hr; 234 | } 235 | -------------------------------------------------------------------------------- /plap/plap_dll.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-PLAP-Provider 3 | * 4 | * Copyright (C) 2017-2022 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef PLAP_DLL_H 23 | #define PLAP_DLL_H 24 | 25 | #include 26 | 27 | #ifdef __cplusplus 28 | extern "C" 29 | { 30 | #endif 31 | 32 | extern HINSTANCE hinst_global; 33 | HRESULT OpenVPNProvider_CreateInstance(REFIID riid, void **ppv); 34 | 35 | void dll_addref(); 36 | 37 | void dll_release(); 38 | 39 | STDAPI DllCanUnloadNow(); 40 | 41 | STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv); 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif /* PLAP_DLL_H */ 48 | -------------------------------------------------------------------------------- /plap/resource.h: -------------------------------------------------------------------------------- 1 | #define IDB_TILE_IMAGE 101 2 | -------------------------------------------------------------------------------- /plap/stub.c: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-PLAP-Provider 3 | * 4 | * Copyright (C) 2017-2022 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include 24 | #endif 25 | #include "plap_common.h" 26 | #include 27 | #include 28 | #include 29 | #include "options.h" 30 | #include "main.h" 31 | #include "localization.h" 32 | #include "ui_glue.h" 33 | 34 | void 35 | PrintDebugMsg(wchar_t *msg) 36 | { 37 | x_dmsg("GUI-source", "", msg); 38 | } 39 | 40 | void 41 | ErrorExit(UNUSED int exit_code, const wchar_t *msg) 42 | { 43 | if (msg) 44 | { 45 | MessageBoxExW(NULL, 46 | msg, 47 | TEXT(PACKAGE_NAME), 48 | MB_OK | MB_SETFOREGROUND | MB_ICONERROR, 49 | GetGUILanguage()); 50 | } 51 | DetachAllOpenVPN(); 52 | /* do not exit */ 53 | } 54 | 55 | void 56 | RecreatePopupMenus(void) 57 | { 58 | return; 59 | } 60 | 61 | void 62 | CreatePopupMenus(void) 63 | { 64 | return; 65 | } 66 | 67 | void 68 | OnNotifyTray(UNUSED LPARAM lp) 69 | { 70 | return; 71 | } 72 | void 73 | OnDestroyTray(void) 74 | { 75 | return; 76 | } 77 | void 78 | ShowTrayIcon(void) 79 | { 80 | return; 81 | } 82 | void 83 | SetTrayIcon(UNUSED conn_state_t state) 84 | { 85 | return; 86 | } 87 | void 88 | SetMenuStatus(UNUSED connection_t *c, UNUSED conn_state_t state) 89 | { 90 | return; 91 | } 92 | void 93 | SetServiceMenuStatus(void) 94 | { 95 | return; 96 | } 97 | void 98 | ShowTrayBalloon(UNUSED wchar_t *s1, UNUSED wchar_t *s2) 99 | { 100 | return; 101 | } 102 | void 103 | CheckAndSetTrayIcon(void) 104 | { 105 | return; 106 | } 107 | void 108 | RunPreconnectScript(UNUSED connection_t *c) 109 | { 110 | return; 111 | } 112 | void 113 | RunConnectScript(UNUSED connection_t *ic, UNUSED int run_as_service) 114 | { 115 | return; 116 | } 117 | void 118 | RunDisconnectScript(UNUSED connection_t *c, UNUSED int run_as_service) 119 | { 120 | return; 121 | } 122 | int 123 | SaveKeyPass(UNUSED const WCHAR *config_name, UNUSED const WCHAR *password) 124 | { 125 | return 1; 126 | } 127 | int 128 | SaveAuthPass(UNUSED const WCHAR *config_name, UNUSED const WCHAR *password) 129 | { 130 | return 1; 131 | } 132 | int 133 | SaveUsername(UNUSED const WCHAR *config_name, UNUSED const WCHAR *username) 134 | { 135 | return 1; 136 | } 137 | 138 | int 139 | RecallKeyPass(UNUSED const WCHAR *config_name, UNUSED WCHAR *password) 140 | { 141 | return 0; 142 | } 143 | int 144 | RecallAuthPass(UNUSED const WCHAR *config_name, UNUSED WCHAR *password) 145 | { 146 | return 0; 147 | } 148 | int 149 | RecallUsername(UNUSED const WCHAR *config_name, UNUSED WCHAR *username) 150 | { 151 | return 0; 152 | } 153 | 154 | void 155 | DeleteSavedAuthPass(UNUSED const WCHAR *config_name) 156 | { 157 | return; 158 | } 159 | 160 | void 161 | DeleteSavedKeyPass(UNUSED const WCHAR *config_name) 162 | { 163 | return; 164 | } 165 | void 166 | DeleteSavedPasswords(UNUSED const WCHAR *config_name) 167 | { 168 | return; 169 | } 170 | 171 | BOOL 172 | IsAuthPassSaved(UNUSED const WCHAR *config_name) 173 | { 174 | return 0; 175 | } 176 | BOOL 177 | IsKeyPassSaved(UNUSED const WCHAR *config_name) 178 | { 179 | return 0; 180 | } 181 | void 182 | env_item_del_all(UNUSED struct env_item *head) 183 | { 184 | return; 185 | } 186 | void 187 | process_setenv(UNUSED connection_t *c, UNUSED time_t timestamp, UNUSED const char *msg) 188 | { 189 | return; 190 | } 191 | BOOL 192 | AuthorizeConfig(UNUSED const connection_t *c) 193 | { 194 | return 1; 195 | } 196 | 197 | void 198 | echo_msg_process(UNUSED connection_t *c, UNUSED time_t timestamp, UNUSED const char *msg) 199 | { 200 | return; 201 | } 202 | 203 | void 204 | echo_msg_clear(UNUSED connection_t *c, UNUSED BOOL clear_history) 205 | { 206 | return; 207 | } 208 | 209 | void 210 | echo_msg_load(UNUSED connection_t *c) 211 | { 212 | return; 213 | } 214 | 215 | BOOL 216 | CheckKeyFileWriteAccess(UNUSED connection_t *c) 217 | { 218 | return 0; 219 | } 220 | -------------------------------------------------------------------------------- /plap/test-plap-res.rc: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2009 Heiko Hund 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | /* Manifest for visual styles */ 23 | CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "test-plap.manifest" 24 | -------------------------------------------------------------------------------- /plap/test-plap.manifest: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | OpenVPN GUI PLAP DLL Test Program 9 | 10 | 11 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 48 | true/PM 49 | 51 | 53 | PerMonitorV2, PerMonitor 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /plap/test_plap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-PLAP-Provider 3 | * 4 | * Copyright (C) 2019-2022 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #undef WIN32_LEAN_AND_MEAN 23 | 24 | #include 25 | #include "plap_common.h" 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #define error_return(fname, hr) do { fwprintf(stdout, L"Error in %ls: status = 0x%08x", fname, hr);\ 35 | return 1;} while (0) 36 | typedef HRESULT (WINAPI * f_func)(REFCLSID rclsid, REFIID riid, LPVOID* ppv); 37 | 38 | class MyQueryContinue : public IQueryContinueWithStatus 39 | { 40 | public: 41 | STDMETHODIMP_(ULONG) AddRef() { 42 | return InterlockedIncrement(&ref_count); 43 | } 44 | STDMETHODIMP_(ULONG) Release() { 45 | int count = InterlockedDecrement(&ref_count); 46 | if (ref_count == 0) delete this; 47 | return count; 48 | } 49 | STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { return E_FAIL; } 50 | STDMETHODIMP QueryContinue() {return time(NULL) > timeout ? S_FALSE : S_OK;} 51 | STDMETHODIMP SetStatusMessage(const wchar_t *ws) { wprintf(L"%ls\r", ws); return S_OK; } 52 | MyQueryContinue() : ref_count(1) {}; 53 | time_t timeout; 54 | 55 | private: 56 | ~MyQueryContinue()=default; 57 | LONG ref_count; 58 | }; 59 | 60 | static int test_provider(IClassFactory *cf) 61 | { 62 | assert(cf != NULL); 63 | ICredentialProvider *o = NULL; 64 | HRESULT hr; 65 | 66 | hr = cf->CreateInstance(NULL, IID_ICredentialProvider, (void**) &o); 67 | 68 | if (!SUCCEEDED(hr)) error_return(L"IID_ICredentialProvider", hr); 69 | 70 | hr = o->SetUsageScenario(CPUS_PLAP, 0); 71 | if (!SUCCEEDED(hr)) error_return(L"SetUsageScenario", hr); 72 | 73 | DWORD count, def; 74 | BOOL auto_def; 75 | hr = o->GetCredentialCount(&count, &def, &auto_def); 76 | if (!SUCCEEDED(hr)) error_return(L"GetCredentialCount", hr); 77 | 78 | fwprintf(stdout, L"credential count = %lu, default = %d, autologon = %d\n", count, (int) def, auto_def); 79 | if (count < 1) fwprintf(stdout, L"No persistent configs found!\n"); 80 | 81 | ICredentialProviderCredential *c = NULL; 82 | MyQueryContinue *qc = new MyQueryContinue(); 83 | for (DWORD i = 0; i < count; i++) 84 | { 85 | hr = o->GetCredentialAt(i, &c); 86 | if (!SUCCEEDED(hr)) error_return(L"GetCredentialAt", hr); 87 | 88 | fwprintf(stdout, L"credential # = %lu: ", i); 89 | wchar_t *ws; 90 | 91 | for (DWORD j = 0; j < 4; j++) 92 | { 93 | hr = c->GetStringValue(j, &ws); 94 | if (!SUCCEEDED(hr)) error_return(L"GetStringValue", hr); 95 | CoTaskMemFree(ws); 96 | } 97 | 98 | /* test getbitmap */ 99 | HBITMAP bmp; 100 | hr = c->GetBitmapValue(0, &bmp); 101 | if (!SUCCEEDED(hr)) 102 | fwprintf(stdout, L"Warning: could not get bitmap"); /* not fatal */ 103 | else 104 | DeleteObject(bmp); 105 | 106 | /* set a time out so that we can move to next config in case */ 107 | qc->timeout = time(NULL) + 20; 108 | 109 | /* get a connection instance and call connect on it */ 110 | IConnectableCredentialProviderCredential *c1 = NULL; 111 | hr = c->QueryInterface(IID_IConnectableCredentialProviderCredential, (void**)&c1); 112 | 113 | fwprintf(stdout, L"\nConnecting connection # <%lu>\n", i); 114 | c1->Connect(qc); /* this will return when connected/failed or qc timesout */ 115 | 116 | fwprintf(stdout, L"\nsleep for 2 sec\n"); 117 | Sleep(2000); 118 | c1->Release(); 119 | } 120 | 121 | assert(o->Release() == 0); /* check refcount */ 122 | assert(qc->Release() == 0); 123 | return 0; 124 | } 125 | 126 | int wmain() 127 | { 128 | HRESULT hr; 129 | _setmode(_fileno(stdout), _O_U16TEXT); 130 | _setmode(_fileno(stderr), _O_U16TEXT); 131 | 132 | IClassFactory *cf = NULL; 133 | DWORD ctx = CLSCTX_INPROC_SERVER; 134 | hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 135 | if (!SUCCEEDED(hr)) error_return(L"CoIntialize", hr); 136 | 137 | /* Test by loading the dll */ 138 | fwprintf(stdout, L"Test plap dll direct loading\n"); 139 | 140 | HMODULE lib = LoadLibraryW(L"C:\\Program Files\\OpenVPN\\bin\\libopenvpn_plap.dll"); 141 | f_func func = NULL; 142 | if (lib == NULL) 143 | { 144 | fwprintf(stderr, L"Failed to load the dll: error = 0x%08x\n", GetLastError()); 145 | } 146 | else { 147 | func = (f_func) GetProcAddress(lib, "DllGetClassObject"); 148 | if (!func) 149 | fwprintf(stderr, L"Failed to find DllGetClassObject in dll: error = 0x%08x\n", GetLastError()); 150 | } 151 | if (func) { 152 | hr = func(CLSID_OpenVPNProvider, IID_IClassFactory, (void **)&cf); 153 | if (!SUCCEEDED(hr)) fwprintf(stdout, L"Error in DllGetClassObject: status = 0x%08x\n", hr); 154 | else { 155 | fwprintf(stdout, L"Success: found ovpn provider class factory by direct access\n"); 156 | cf->Release(); 157 | } 158 | } 159 | 160 | /* Test by finding the class through COM's registration mechanism */ 161 | fwprintf(stdout, L"Testing plap using CoGetclassobject -- requires proper dll registration\n"); 162 | 163 | hr = CoGetClassObject(CLSID_OpenVPNProvider, ctx, NULL, IID_IClassFactory, (void **)&cf); 164 | if (SUCCEEDED(hr)) { 165 | test_provider(cf); 166 | cf->Release(); 167 | } 168 | else { 169 | fwprintf(stdout, L"CoGetClassObject (class not registered?): error = 0x%08x\n", hr); 170 | } 171 | 172 | CoUninitialize(); 173 | if (lib) { 174 | FreeLibrary(lib); 175 | } 176 | return 0; 177 | } 178 | -------------------------------------------------------------------------------- /plap/ui_glue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-PLAP-Provider 3 | * 4 | * Copyright (C) 2017-2022 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef UI_LINK_H 23 | #define UI_LINK_H 24 | 25 | #ifdef __cplusplus 26 | extern "C" 27 | { 28 | #endif 29 | #include /* suppress warning about order of includes */ 30 | #include 31 | 32 | typedef struct connection connection_t; 33 | /* access to GUI states without exposing the options header */ 34 | extern int state_connected, state_disconnected, state_onhold; 35 | 36 | /** 37 | * Initialize GUI data structures 38 | * @param hinstance of the calling process/dll context 39 | * @return 0 on success > 0 on error 40 | */ 41 | DWORD InitializeUI(HINSTANCE hinstance); 42 | 43 | /** 44 | * Close threads, cleanup resources created by Initialize 45 | */ 46 | void DeleteUI(void); 47 | 48 | /** 49 | * Enumerate PLAP enabled connection profiles. 50 | * 51 | * @param conn[] On output this contains an array of connection_t 52 | * structs for PLAP enabled profiles 53 | * @param max_count size of conn[] array on input 54 | * @returns the number of connection profiles found. 55 | */ 56 | DWORD FindPLAPConnections(connection_t *conn[], size_t max_count); 57 | 58 | /** 59 | * Display name of a connection profile. 60 | * 61 | * @param c connection_t struct for the profile (input) 62 | * @returns a constant wide char string 63 | */ 64 | const wchar_t *ConfigDisplayName(connection_t *c); 65 | 66 | /** 67 | * State of a connection 68 | */ 69 | int ConnectionState(connection_t *c); 70 | 71 | /** 72 | * Textual description of current connection state 73 | * 74 | * @param status On input must have space of at least len wide characters 75 | * On output contains the NUL-terminated status text 76 | * @param len Capacity of memory pointed to by status 77 | */ 78 | void GetConnectionStatusText(connection_t *c, WCHAR *status, DWORD len); 79 | 80 | /** 81 | * Set hwnd as the parent window handle for dialogs 82 | */ 83 | void SetParentWindow(HWND hwnd); 84 | 85 | void DetachAllOpenVPN(); 86 | 87 | /** 88 | * Enable/Disable display of status Window for connection c 89 | */ 90 | void ShowStatusWindow(connection_t *c, BOOL show); 91 | 92 | /** 93 | * Start or Release OpenVPN connection for c 94 | * The connection is completed asynchronously. 95 | */ 96 | void ConnectHelper(connection_t *c); 97 | 98 | /** 99 | * Stop OpenVPN connection for c 100 | * After initiating a disconnection, this polls for the connection status 101 | * and waits for the disconnection to complete for a max of 5 seconds. 102 | */ 103 | void DisconnectHelper(connection_t *c); 104 | 105 | /** 106 | * Set c as the currently active profile selected for user interaction 107 | * UI dialogs are suppressed for non-active profiles 108 | */ 109 | void SetActiveProfile(connection_t *c); 110 | 111 | /** 112 | * A helper function to run a dialog showing progress of a connection process. 113 | * 114 | * @param c Connection to monitor 115 | * @param cb_fn A callback function that is called back every 200 msec 116 | * @param cb_data Data passed to the callback function 117 | */ 118 | int RunProgressDialog(connection_t *c, PFTASKDIALOGCALLBACK cb_fn, LONG_PTR cb_data); 119 | 120 | #ifdef __cplusplus 121 | } 122 | #endif 123 | 124 | #endif /* UI_LINK_H */ 125 | -------------------------------------------------------------------------------- /proxy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2004 Mathias Sundman 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef PROXY_H 23 | #define PROXY_H 24 | 25 | INT_PTR CALLBACK ProxySettingsDialogFunc(HWND, UINT, WPARAM, LPARAM); 26 | 27 | void QueryProxyAuth(connection_t *, proxy_t); 28 | 29 | void OnProxy(connection_t *, char *); 30 | 31 | int CheckProxySettings(HWND); 32 | 33 | void LoadProxySettings(HWND); 34 | 35 | void SaveProxySettings(HWND); 36 | 37 | void GetProxyRegistrySettings(); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /qr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2025 Lev Stipakov 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include "qrcodegen/qrcodegen.h" 24 | 25 | #include 26 | 27 | #include "main.h" 28 | #include "qr.h" 29 | #include "misc.h" 30 | 31 | #include "openvpn-gui-res.h" 32 | 33 | struct url_and_config_name 34 | { 35 | const wchar_t *url; 36 | const wchar_t *config_name; 37 | }; 38 | 39 | typedef struct url_and_config_name url_and_config_name_t; 40 | 41 | /* global handle to be able to close the dialog from outside */ 42 | static HWND g_hwndQR = NULL; 43 | 44 | /* Generate QR bitmap from wide string */ 45 | HBITMAP 46 | CreateQRBitmapFromWchar(const wchar_t *wtext, int scale) 47 | { 48 | char *utf8_text = WCharToUTF8(wtext); 49 | if (!utf8_text) 50 | return NULL; 51 | 52 | uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX]; 53 | uint8_t temp[qrcodegen_BUFFER_LEN_MAX]; 54 | 55 | bool ok = qrcodegen_encodeText(utf8_text, 56 | temp, 57 | qrcode, 58 | qrcodegen_Ecc_LOW, 59 | qrcodegen_VERSION_MIN, 60 | qrcodegen_VERSION_MAX, 61 | qrcodegen_Mask_AUTO, 62 | true); 63 | free(utf8_text); 64 | if (!ok) 65 | return NULL; 66 | 67 | int size = qrcodegen_getSize(qrcode); 68 | int imgSize = size * scale; 69 | 70 | HDC hdcScreen = GetDC(NULL); 71 | HDC hdcMem = CreateCompatibleDC(hdcScreen); 72 | HBITMAP hBitmap = CreateCompatibleBitmap(hdcScreen, imgSize, imgSize); 73 | SelectObject(hdcMem, hBitmap); 74 | 75 | RECT rc = { 0, 0, imgSize, imgSize }; 76 | FillRect(hdcMem, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH)); 77 | 78 | HBRUSH blackBrush = (HBRUSH)GetStockObject(BLACK_BRUSH); 79 | for (int y = 0; y < size; ++y) 80 | { 81 | for (int x = 0; x < size; ++x) 82 | { 83 | if (qrcodegen_getModule(qrcode, x, y)) 84 | { 85 | RECT pixelRect = { x * scale, y * scale, (x + 1) * scale, (y + 1) * scale }; 86 | FillRect(hdcMem, &pixelRect, blackBrush); 87 | } 88 | } 89 | } 90 | 91 | DeleteDC(hdcMem); 92 | ReleaseDC(NULL, hdcScreen); 93 | return hBitmap; 94 | } 95 | 96 | INT_PTR CALLBACK 97 | QrDialogProc(HWND hwnd, UINT msg, UNUSED WPARAM wp, LPARAM lp) 98 | { 99 | static HBITMAP hQRBitmap = NULL; 100 | static UINT_PTR timerId = 1; 101 | static UINT timerElapse = 20000; /* must be less than 30 sec pre-logon timeout */ 102 | 103 | switch (msg) 104 | { 105 | case WM_INITDIALOG: 106 | { 107 | url_and_config_name_t *uc = (url_and_config_name_t *)lp; 108 | 109 | const int padding = 15; 110 | const int qrMaxSize = 300; /* max QR bitmap size in pixels */ 111 | 112 | /* Generate QR initially at largest acceptable size */ 113 | int scale = 6; 114 | HBITMAP hQRBitmap = CreateQRBitmapFromWchar(uc->url, scale); 115 | if (!hQRBitmap) 116 | { 117 | MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Failed to generate QR"); 118 | EndDialog(hwnd, 0); 119 | return TRUE; 120 | } 121 | 122 | BITMAP bm; 123 | GetObject(hQRBitmap, sizeof(BITMAP), &bm); 124 | 125 | /* Adjust scale down if bitmap too big */ 126 | while ((bm.bmWidth > qrMaxSize) && scale > 1) 127 | { 128 | DeleteObject(hQRBitmap); 129 | scale--; 130 | hQRBitmap = CreateQRBitmapFromWchar(uc->url, scale); 131 | if (!hQRBitmap) 132 | { 133 | MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Failed to generate QR"); 134 | EndDialog(hwnd, 0); 135 | return TRUE; 136 | } 137 | GetObject(hQRBitmap, sizeof(BITMAP), &bm); 138 | } 139 | 140 | int qrWidth = bm.bmWidth; 141 | int qrHeight = bm.bmHeight; 142 | 143 | HWND hwndStaticQR = GetDlgItem(hwnd, ID_STATIC_QR); 144 | SetWindowPos(hwndStaticQR, NULL, padding, padding, qrWidth, qrHeight, SWP_NOZORDER); 145 | SendMessage(hwndStaticQR, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hQRBitmap); 146 | 147 | /* Position text control below QR bitmap */ 148 | HWND hwndStaticText = GetDlgItem(hwnd, ID_TXT_QR); 149 | int textWidth = qrWidth; 150 | int textHeight = 50; 151 | SetWindowPos(hwndStaticText, 152 | NULL, 153 | padding, 154 | qrHeight + padding + 10, 155 | textWidth, 156 | textHeight, 157 | SWP_NOZORDER); 158 | 159 | /* Calculate total dialog size */ 160 | int dialogWidth = qrWidth + padding * 2; 161 | int dialogHeight = qrHeight + textHeight + padding * 3; 162 | 163 | RECT rcDialog = { 0, 0, dialogWidth, dialogHeight }; 164 | AdjustWindowRectEx( 165 | &rcDialog, GetWindowLong(hwnd, GWL_STYLE), FALSE, GetWindowLong(hwnd, GWL_EXSTYLE)); 166 | int dlgWidth = rcDialog.right - rcDialog.left; 167 | int dlgHeight = rcDialog.bottom - rcDialog.top; 168 | 169 | /* Center the dialog on the screen */ 170 | int posX = (GetSystemMetrics(SM_CXSCREEN) - dlgWidth) / 2; 171 | int posY = (GetSystemMetrics(SM_CYSCREEN) - dlgHeight) / 2; 172 | SetWindowPos(hwnd, NULL, posX, posY, dlgWidth, dlgHeight, SWP_NOZORDER); 173 | 174 | SetWindowText(hwnd, uc->config_name); 175 | 176 | g_hwndQR = hwnd; 177 | 178 | SetTimer(hwnd, timerId, timerElapse, NULL); 179 | } 180 | return TRUE; 181 | 182 | case WM_CLOSE: 183 | EndDialog(hwnd, 0); 184 | return TRUE; 185 | 186 | case WM_TIMER: 187 | if (wp == timerId) 188 | { 189 | /* Simulate mouse movement to keep Winlogon from dismissing the PLAP dialog */ 190 | INPUT input = { 0 }; 191 | input.type = INPUT_MOUSE; 192 | input.mi.dwFlags = MOUSEEVENTF_MOVE; 193 | input.mi.dx = 0; 194 | input.mi.dy = 0; 195 | SendInput(1, &input, sizeof(INPUT)); 196 | } 197 | return TRUE; 198 | 199 | case WM_DESTROY: 200 | if (hQRBitmap) 201 | DeleteObject(hQRBitmap); 202 | g_hwndQR = NULL; 203 | 204 | KillTimer(hwnd, timerId); 205 | return TRUE; 206 | } 207 | return FALSE; 208 | } 209 | 210 | void 211 | CloseQRDialog() 212 | { 213 | if (g_hwndQR && IsWindow(g_hwndQR)) 214 | PostMessage(g_hwndQR, WM_CLOSE, 0, 0); 215 | } 216 | 217 | extern options_t o; 218 | 219 | void 220 | OpenQRDialog(const wchar_t *url, const wchar_t *config_name) 221 | { 222 | url_and_config_name_t uc; 223 | uc.url = url; 224 | uc.config_name = config_name; 225 | DialogBoxParam(o.hInstance, MAKEINTRESOURCE(ID_DLG_QR), o.hWnd, QrDialogProc, (LPARAM)&uc); 226 | } 227 | -------------------------------------------------------------------------------- /qr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2025 Lev Stipakov 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | void CloseQRDialog(); 23 | 24 | void OpenQRDialog(const wchar_t *url, const wchar_t *config_name); 25 | -------------------------------------------------------------------------------- /registry.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2004 Mathias Sundman 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef REGISTRY_H 23 | #define REGISTRY_H 24 | 25 | int GetRegistryKeys(void); 26 | 27 | int SaveRegistryKeys(void); 28 | 29 | int UpdateRegistry(void); 30 | 31 | int GetRegKey(const TCHAR name[], TCHAR data[], const TCHAR default_data[], DWORD len); 32 | 33 | LONG GetRegistryValue(HKEY regkey, const TCHAR *name, TCHAR *data, DWORD len); 34 | 35 | LONG GetRegistryValueNumeric(HKEY regkey, const TCHAR *name, DWORD *data); 36 | 37 | int SetRegistryValue(HKEY regkey, const TCHAR *name, const TCHAR *data); 38 | 39 | int SetRegistryValueNumeric(HKEY regkey, const TCHAR *name, DWORD data); 40 | 41 | int SetConfigRegistryValueBinary(const WCHAR *config_name, 42 | const WCHAR *name, 43 | const BYTE *data, 44 | DWORD len); 45 | 46 | DWORD GetConfigRegistryValue(const WCHAR *config_name, const WCHAR *name, BYTE *data, DWORD len); 47 | 48 | int DeleteConfigRegistryValue(const WCHAR *config_name, const WCHAR *name); 49 | 50 | #endif /* ifndef REGISTRY_H */ 51 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "packageRules": [ 4 | { 5 | "matchDepTypes": [ 6 | "action" 7 | ], 8 | "groupName": "github actions", 9 | "pinDigests": true, 10 | "extends": [ 11 | "schedule:monthly" 12 | ] 13 | }, 14 | { 15 | "matchDepNames": [ 16 | "vcpkg" 17 | ], 18 | "extends": [ 19 | "schedule:monthly" 20 | ] 21 | } 22 | ], 23 | "customManagers": [ 24 | { 25 | "customType": "regex", 26 | "fileMatch": ["^\\.github/workflows/.+\\.yml$"], 27 | "matchStrings": ["vcpkgGitCommitId:\\s*(?.*?)\\n"], 28 | "currentValueTemplate": "master", 29 | "depNameTemplate": "vcpkg", 30 | "packageNameTemplate": "https://github.com/microsoft/vcpkg", 31 | "datasourceTemplate": "git-refs" 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /res/connected.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVPN/openvpn-gui/501f88726614765c453302a660c877854915e7f8/res/connected.ico -------------------------------------------------------------------------------- /res/connecting.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVPN/openvpn-gui/501f88726614765c453302a660c877854915e7f8/res/connecting.ico -------------------------------------------------------------------------------- /res/disconnected.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVPN/openvpn-gui/501f88726614765c453302a660c877854915e7f8/res/disconnected.ico -------------------------------------------------------------------------------- /res/eye-stroke.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVPN/openvpn-gui/501f88726614765c453302a660c877854915e7f8/res/eye-stroke.ico -------------------------------------------------------------------------------- /res/eye.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVPN/openvpn-gui/501f88726614765c453302a660c877854915e7f8/res/eye.ico -------------------------------------------------------------------------------- /res/openvpn-gui-res.rc: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2009 Heiko Hund 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include 24 | #endif 25 | 26 | #include 27 | #include 28 | #include "../openvpn-gui-res.h" 29 | 30 | /* Language resource files are UTF-8 encoded */ 31 | #pragma code_page(65001) 32 | 33 | /* Manifest for XP visual styles */ 34 | CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "openvpn-gui.manifest" 35 | 36 | /* Application Icons */ 37 | ID_ICO_APP ICON DISCARDABLE "openvpn-gui.ico" 38 | ID_ICO_CONNECTED ICON DISCARDABLE "connected.ico" 39 | ID_ICO_CONNECTING ICON DISCARDABLE "connecting.ico" 40 | ID_ICO_DISCONNECTED ICON DISCARDABLE "disconnected.ico" 41 | ID_ICO_EYE ICON DISCARDABLE "eye.ico" 42 | ID_ICO_EYESTROKE ICON DISCARDABLE "eye-stroke.ico" 43 | 44 | #ifdef ENABLE_OVPN3 45 | #define ADVANCED_DIALOG_HEIGHT 320 46 | #else 47 | #define ADVANCED_DIALOG_HEIGHT 280 48 | #endif 49 | 50 | #include "openvpn-gui-res-cs.rc" 51 | #include "openvpn-gui-res-de.rc" 52 | #include "openvpn-gui-res-dk.rc" 53 | #include "openvpn-gui-res-en.rc" 54 | #include "openvpn-gui-res-es.rc" 55 | #include "openvpn-gui-res-fa.rc" 56 | #include "openvpn-gui-res-fi.rc" 57 | #include "openvpn-gui-res-fr.rc" 58 | #include "openvpn-gui-res-it.rc" 59 | #include "openvpn-gui-res-jp.rc" 60 | #include "openvpn-gui-res-kr.rc" 61 | #include "openvpn-gui-res-nl.rc" 62 | #include "openvpn-gui-res-no.rc" 63 | #include "openvpn-gui-res-pl.rc" 64 | #include "openvpn-gui-res-pt.rc" 65 | #include "openvpn-gui-res-ru.rc" 66 | #include "openvpn-gui-res-se.rc" 67 | #include "openvpn-gui-res-tr.rc" 68 | #include "openvpn-gui-res-ua.rc" 69 | #include "openvpn-gui-res-zh-hans.rc" 70 | #include "openvpn-gui-res-zh-hant.rc" 71 | 72 | /* Version information and such */ 73 | VS_VERSION_INFO VERSIONINFO 74 | FILEVERSION PACKAGE_VERSION_RESOURCE 75 | PRODUCTVERSION PACKAGE_VERSION_RESOURCE 76 | FILEOS VOS_NT 77 | FILETYPE VFT_APP 78 | BEGIN 79 | BLOCK "VarFileInfo" 80 | BEGIN 81 | VALUE "Translation" 82 | , LANG_CZECH, 1200 83 | , LANG_GERMAN, 1200 84 | , LANG_DANISH, 1200 85 | , LANG_ENGLISH, 1200 86 | , LANG_SPANISH, 1200 87 | , LANG_FARSI, 1200 88 | , LANG_FINNISH, 1200 89 | , LANG_FRENCH, 1200 90 | , LANG_ITALIAN, 1200 91 | , LANG_JAPANESE, 1200 92 | , LANG_DUTCH, 1200 93 | , LANG_NORWEGIAN, 1200 94 | , LANG_POLISH, 1200 95 | , LANG_PORTUGUESE, 1200 96 | , LANG_RUSSIAN, 1200 97 | , LANG_SWEDISH, 1200 98 | , LANG_TURKISH, 1200 99 | , LANG_UKRAINIAN, 1200 100 | , LANG_CHINESE, 1200 101 | , LANG_KOREAN, 1200 102 | END 103 | 104 | BLOCK "StringFileInfo" 105 | BEGIN 106 | BLOCK "040904B0" /* en_US, Unicode */ 107 | BEGIN 108 | VALUE "FileDescription", PACKAGE_NAME " for Windows" 109 | VALUE "FileVersion", PACKAGE_VERSION_RESOURCE_STR 110 | VALUE "InternalName", PACKAGE_TARNAME 111 | VALUE "OriginalFilename", PACKAGE_TARNAME ".exe" 112 | VALUE "ProductName", PACKAGE_NAME 113 | VALUE "ProductVersion", PACKAGE_VERSION_RESOURCE_STR 114 | VALUE "Website", PACKAGE_URL 115 | VALUE "LegalCopyright", "The " PACKAGE_NAME " developers" 116 | VALUE "CompanyName", PACKAGE_NAME 117 | END 118 | END 119 | END 120 | -------------------------------------------------------------------------------- /res/openvpn-gui.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVPN/openvpn-gui/501f88726614765c453302a660c877854915e7f8/res/openvpn-gui.ico -------------------------------------------------------------------------------- /res/openvpn-gui.manifest: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | OpenVPN GUI for Windows 9 | 10 | 11 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 48 | true/PM 49 | 51 | 53 | PerMonitorV2, PerMonitor 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /res/reconnecting.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVPN/openvpn-gui/501f88726614765c453302a660c877854915e7f8/res/reconnecting.ico -------------------------------------------------------------------------------- /res/tileimage.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVPN/openvpn-gui/501f88726614765c453302a660c877854915e7f8/res/tileimage.bmp -------------------------------------------------------------------------------- /save_pass.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is a part of OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2016 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include "config.h" 24 | #endif 25 | 26 | #include 27 | #include 28 | 29 | #include "main.h" 30 | #include "registry.h" 31 | #include "save_pass.h" 32 | #include "misc.h" 33 | 34 | #define KEY_PASS_DATA L"key-data" 35 | #define AUTH_PASS_DATA L"auth-data" 36 | #define ENTROPY_DATA L"entropy" 37 | #define AUTH_USER_DATA L"username" 38 | #define ENTROPY_LEN 16 39 | 40 | static DWORD 41 | crypt_protect(BYTE *data, int szdata, char *entropy, BYTE **out) 42 | { 43 | DATA_BLOB data_out; 44 | DATA_BLOB data_in; 45 | DATA_BLOB e; 46 | 47 | data_in.pbData = data; 48 | data_in.cbData = szdata; 49 | e.pbData = (BYTE *)entropy; 50 | e.cbData = entropy ? strlen(entropy) : 0; 51 | 52 | if (CryptProtectData(&data_in, NULL, &e, NULL, NULL, 0, &data_out)) 53 | { 54 | *out = data_out.pbData; 55 | return data_out.cbData; 56 | } 57 | PrintDebug(L"CryptProtectData failed (error = %lu)", GetLastError()); 58 | return 0; 59 | } 60 | 61 | static DWORD 62 | crypt_unprotect(BYTE *data, int szdata, char *entropy, BYTE **out) 63 | { 64 | DATA_BLOB data_in; 65 | DATA_BLOB data_out = { 0, 0 }; 66 | DATA_BLOB e; 67 | 68 | data_in.pbData = data; 69 | data_in.cbData = szdata; 70 | e.pbData = (BYTE *)entropy; 71 | e.cbData = entropy ? strlen(entropy) : 0; 72 | 73 | if (CryptUnprotectData(&data_in, NULL, &e, NULL, NULL, 0, &data_out)) 74 | { 75 | *out = data_out.pbData; 76 | return data_out.cbData; 77 | } 78 | else 79 | { 80 | PrintDebug(L"CryptUnprotectData: decryption failed"); 81 | LocalFree(data_out.pbData); 82 | return 0; 83 | } 84 | } 85 | 86 | /* 87 | * If not found in registry and generate is true, a new nul terminated 88 | * random string is generated and saved in registry. 89 | * Else a zero-length string is returned and registry is not updated. 90 | */ 91 | static void 92 | get_entropy(const WCHAR *config_name, char *e, int sz, BOOL generate) 93 | { 94 | int len; 95 | 96 | len = GetConfigRegistryValue(config_name, ENTROPY_DATA, (BYTE *)e, sz); 97 | if (len > 0) 98 | { 99 | e[len - 1] = '\0'; 100 | PrintDebug(L"Got entropy from registry: %hs (len = %d)", e, len); 101 | return; 102 | } 103 | else if (generate && GetRandomPassword(e, sz)) 104 | { 105 | e[sz - 1] = '\0'; 106 | PrintDebug(L"Created new entropy string : %hs", e); 107 | if (SetConfigRegistryValueBinary(config_name, ENTROPY_DATA, (BYTE *)e, sz)) 108 | { 109 | return; 110 | } 111 | } 112 | if (generate) 113 | { 114 | PrintDebug(L"Failed to generate or save new entropy string -- using null string"); 115 | } 116 | *e = '\0'; 117 | return; 118 | } 119 | /* 120 | * Given a nul terminated string password, encrypt it and save in 121 | * a config specific registry key with specified name. 122 | * Returns 1 on success. 123 | */ 124 | static int 125 | save_encrypted(const WCHAR *config_name, const WCHAR *password, const WCHAR *name) 126 | { 127 | BYTE *out; 128 | DWORD len = (wcslen(password) + 1) * sizeof(WCHAR); 129 | char entropy[ENTROPY_LEN + 1]; 130 | 131 | get_entropy(config_name, entropy, sizeof(entropy), true); 132 | len = crypt_protect((BYTE *)password, len, entropy, &out); 133 | if (len > 0) 134 | { 135 | SetConfigRegistryValueBinary(config_name, name, out, len); 136 | LocalFree(out); 137 | return 1; 138 | } 139 | else 140 | { 141 | return 0; 142 | } 143 | } 144 | 145 | /* 146 | * Encrypt the nul terminated string password and store it in the 147 | * registry with key name KEY_PASS_DATA. Returns 1 on success. 148 | */ 149 | int 150 | SaveKeyPass(const WCHAR *config_name, const WCHAR *password) 151 | { 152 | return save_encrypted(config_name, password, KEY_PASS_DATA); 153 | } 154 | 155 | /* 156 | * Encrypt the nul terminated string password and store it in the 157 | * registry with key name AUTH_PASS_DATA. Returns 1 on success. 158 | */ 159 | int 160 | SaveAuthPass(const WCHAR *config_name, const WCHAR *password) 161 | { 162 | return save_encrypted(config_name, password, AUTH_PASS_DATA); 163 | } 164 | 165 | /* 166 | * Returns 1 on success, 0 on failure. password should have space 167 | * for up to capacity wide chars incluing nul termination 168 | */ 169 | static int 170 | recall_encrypted(const WCHAR *config_name, WCHAR *password, DWORD capacity, const WCHAR *name) 171 | { 172 | BYTE in[2048]; 173 | BYTE *out; 174 | DWORD len; 175 | int retval = 0; 176 | char entropy[ENTROPY_LEN + 1]; 177 | 178 | get_entropy(config_name, entropy, sizeof(entropy), false); 179 | 180 | memset(password, 0, capacity); 181 | 182 | len = GetConfigRegistryValue(config_name, name, in, sizeof(in)); 183 | if (len == 0) 184 | { 185 | return 0; 186 | } 187 | 188 | len = crypt_unprotect(in, len, entropy, &out); 189 | if (len == 0) 190 | { 191 | return 0; 192 | } 193 | 194 | if (len <= capacity * sizeof(*password)) 195 | { 196 | memcpy(password, out, len); 197 | password[capacity - 1] = L'\0'; /* in case the data was corrupted */ 198 | retval = 1; 199 | } 200 | else 201 | { 202 | PrintDebug(L"recall_encrypted: saved '%ls' too long (len = %d bytes)", name, len); 203 | } 204 | 205 | SecureZeroMemory(out, len); 206 | LocalFree(out); 207 | 208 | return retval; 209 | } 210 | 211 | /* 212 | * Reccall saved private key password. The buffer password should be 213 | * have space for up to KEY_PASS_LEN WCHARs including nul. 214 | * Returns 1 on success, 0 on failure. 215 | */ 216 | int 217 | RecallKeyPass(const WCHAR *config_name, WCHAR *password) 218 | { 219 | return recall_encrypted(config_name, password, KEY_PASS_LEN, KEY_PASS_DATA); 220 | } 221 | 222 | /* 223 | * Reccall saved auth password. The buffer password should be 224 | * have space for up to USER_PASS_LEN WCHARs including nul. 225 | * Returns 1 on success, 0 on failure. 226 | */ 227 | int 228 | RecallAuthPass(const WCHAR *config_name, WCHAR *password) 229 | { 230 | return recall_encrypted(config_name, password, USER_PASS_LEN, AUTH_PASS_DATA); 231 | } 232 | 233 | int 234 | SaveUsername(const WCHAR *config_name, const WCHAR *username) 235 | { 236 | DWORD len = (wcslen(username) + 1) * sizeof(*username); 237 | SetConfigRegistryValueBinary(config_name, AUTH_USER_DATA, (BYTE *)username, len); 238 | return 1; 239 | } 240 | /* 241 | * The buffer username should be have space for up to USER_PASS_LEN 242 | * WCHARs including nul. 243 | */ 244 | int 245 | RecallUsername(const WCHAR *config_name, WCHAR *username) 246 | { 247 | DWORD capacity = USER_PASS_LEN * sizeof(WCHAR); 248 | DWORD len; 249 | 250 | len = GetConfigRegistryValue(config_name, AUTH_USER_DATA, (BYTE *)username, capacity); 251 | if (len == 0) 252 | { 253 | return 0; 254 | } 255 | username[USER_PASS_LEN - 1] = L'\0'; 256 | return 1; 257 | } 258 | 259 | void 260 | DeleteSavedKeyPass(const WCHAR *config_name) 261 | { 262 | DeleteConfigRegistryValue(config_name, KEY_PASS_DATA); 263 | } 264 | 265 | void 266 | DeleteSavedAuthPass(const WCHAR *config_name) 267 | { 268 | DeleteConfigRegistryValue(config_name, AUTH_PASS_DATA); 269 | } 270 | 271 | /* delete saved config-specific auth password and private key passphrase */ 272 | void 273 | DeleteSavedPasswords(const WCHAR *config_name) 274 | { 275 | DeleteConfigRegistryValue(config_name, KEY_PASS_DATA); 276 | DeleteConfigRegistryValue(config_name, AUTH_PASS_DATA); 277 | DeleteConfigRegistryValue(config_name, ENTROPY_DATA); 278 | } 279 | 280 | /* check if auth password is saved */ 281 | BOOL 282 | IsAuthPassSaved(const WCHAR *config_name) 283 | { 284 | DWORD len = 0; 285 | len = GetConfigRegistryValue(config_name, AUTH_PASS_DATA, NULL, 0); 286 | PrintDebug(L"checking auth-pass-data in registry returned len = %d", len); 287 | return (len > 0); 288 | } 289 | 290 | /* check if key password is saved */ 291 | BOOL 292 | IsKeyPassSaved(const WCHAR *config_name) 293 | { 294 | DWORD len = 0; 295 | len = GetConfigRegistryValue(config_name, KEY_PASS_DATA, NULL, 0); 296 | PrintDebug(L"checking key-pass-data in registry returned len = %d", len); 297 | return (len > 0); 298 | } 299 | -------------------------------------------------------------------------------- /save_pass.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is a part of OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2016 Selva Nair 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef SAVEPASS_H 23 | #define SAVEPASS_H 24 | 25 | #include 26 | 27 | #define USER_PASS_LEN 128 28 | #define KEY_PASS_LEN 128 29 | 30 | int SaveKeyPass(const WCHAR *config_name, const WCHAR *password); 31 | 32 | int SaveAuthPass(const WCHAR *config_name, const WCHAR *password); 33 | 34 | int SaveUsername(const WCHAR *config_name, const WCHAR *username); 35 | 36 | int RecallKeyPass(const WCHAR *config_name, WCHAR *password); 37 | 38 | int RecallAuthPass(const WCHAR *config_name, WCHAR *password); 39 | 40 | int RecallUsername(const WCHAR *config_name, WCHAR *username); 41 | 42 | void DeleteSavedAuthPass(const WCHAR *config_name); 43 | 44 | void DeleteSavedKeyPass(const WCHAR *config_name); 45 | 46 | void DeleteSavedPasswords(const WCHAR *config_name); 47 | 48 | BOOL IsAuthPassSaved(const WCHAR *config_name); 49 | 50 | BOOL IsKeyPassSaved(const WCHAR *config_name); 51 | 52 | #endif /* ifndef SAVEPASS_H */ 53 | -------------------------------------------------------------------------------- /scripts.c: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2004 Mathias Sundman 5 | * 2011 Heiko Hund 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program (see the file COPYING included with this 19 | * distribution); if not, write to the Free Software Foundation, Inc., 20 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | */ 22 | 23 | #ifdef HAVE_CONFIG_H 24 | #include 25 | #endif 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "main.h" 35 | #include "openvpn-gui-res.h" 36 | #include "options.h" 37 | #include "misc.h" 38 | #include "localization.h" 39 | #include "env_set.h" 40 | 41 | extern options_t o; 42 | 43 | 44 | void 45 | RunPreconnectScript(connection_t *c) 46 | { 47 | STARTUPINFO si; 48 | PROCESS_INFORMATION pi; 49 | TCHAR cmdline[256]; 50 | DWORD exit_code; 51 | struct _stat st; 52 | int i; 53 | 54 | CLEAR(si); 55 | CLEAR(pi); 56 | 57 | /* Cut off extention from config filename and add "_pre.bat" */ 58 | int len = _tcslen(c->config_file) - _tcslen(o.ext_string) - 1; 59 | _sntprintf_0(cmdline, _T("%ls\\%.*ls_pre.bat"), c->config_dir, len, c->config_file); 60 | 61 | /* Return if no script exists */ 62 | if (_tstat(cmdline, &st) == -1) 63 | { 64 | return; 65 | } 66 | 67 | /* Create the filename of the logfile */ 68 | TCHAR script_log_filename[MAX_PATH]; 69 | _sntprintf_0(script_log_filename, _T("%ls\\%ls_pre.log"), o.log_dir, c->config_name); 70 | 71 | /* Create the log file */ 72 | SECURITY_ATTRIBUTES sa; 73 | CLEAR(sa); 74 | sa.nLength = sizeof(SECURITY_ATTRIBUTES); 75 | sa.lpSecurityDescriptor = NULL; 76 | sa.bInheritHandle = TRUE; 77 | 78 | HANDLE logfile_handle = CreateFile(script_log_filename, 79 | GENERIC_WRITE, 80 | FILE_SHARE_READ | FILE_SHARE_WRITE, 81 | &sa, 82 | CREATE_ALWAYS, 83 | FILE_ATTRIBUTE_NORMAL, 84 | NULL); 85 | 86 | /* fill in STARTUPINFO struct */ 87 | GetStartupInfo(&si); 88 | si.cb = sizeof(si); 89 | si.dwFlags = STARTF_USESTDHANDLES; 90 | si.wShowWindow = SW_SHOWDEFAULT; 91 | si.hStdInput = NULL; 92 | si.hStdOutput = logfile_handle; 93 | si.hStdError = logfile_handle; 94 | 95 | /* Preconnect script is run too early for config env to be available 96 | * so we use the default process env here. 97 | */ 98 | 99 | if (!CreateProcess(NULL, 100 | cmdline, 101 | NULL, 102 | NULL, 103 | TRUE, 104 | (o.show_script_window ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW), 105 | NULL, 106 | c->config_dir, 107 | &si, 108 | &pi)) 109 | { 110 | goto out; 111 | } 112 | 113 | /* Wait process without blocking msg pump */ 114 | for (i = 0; i <= (int)o.preconnectscript_timeout; i++) 115 | { 116 | if (!GetExitCodeProcess(pi.hProcess, &exit_code) || exit_code != STILL_ACTIVE 117 | || !OVPNMsgWait(1000, NULL)) 118 | { 119 | break; 120 | } 121 | } 122 | 123 | out: 124 | CloseHandleEx(&pi.hThread); 125 | CloseHandleEx(&pi.hProcess); 126 | CloseHandleEx(&logfile_handle); 127 | } 128 | 129 | 130 | void 131 | RunConnectScript(connection_t *c, int run_as_service) 132 | { 133 | STARTUPINFO si; 134 | PROCESS_INFORMATION pi; 135 | TCHAR cmdline[256]; 136 | DWORD exit_code; 137 | struct _stat st; 138 | int i; 139 | 140 | CLEAR(si); 141 | CLEAR(pi); 142 | 143 | /* Cut off extention from config filename and add "_up.bat" */ 144 | int len = _tcslen(c->config_file) - _tcslen(o.ext_string) - 1; 145 | _sntprintf_0(cmdline, _T("%ls\\%.*ls_up.bat"), c->config_dir, len, c->config_file); 146 | 147 | /* Return if no script exists */ 148 | if (_tstat(cmdline, &st) == -1) 149 | { 150 | return; 151 | } 152 | 153 | if (!run_as_service) 154 | { 155 | SetDlgItemText( 156 | c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_CONN_SCRIPT)); 157 | } 158 | 159 | /* Create the filename of the logfile */ 160 | TCHAR script_log_filename[MAX_PATH]; 161 | _sntprintf_0(script_log_filename, _T("%ls\\%ls_up.log"), o.log_dir, c->config_name); 162 | 163 | /* Create the log file */ 164 | SECURITY_ATTRIBUTES sa; 165 | CLEAR(sa); 166 | sa.nLength = sizeof(SECURITY_ATTRIBUTES); 167 | sa.lpSecurityDescriptor = NULL; 168 | sa.bInheritHandle = TRUE; 169 | 170 | HANDLE logfile_handle = CreateFile(script_log_filename, 171 | GENERIC_WRITE, 172 | FILE_SHARE_READ | FILE_SHARE_WRITE, 173 | &sa, 174 | CREATE_ALWAYS, 175 | FILE_ATTRIBUTE_NORMAL, 176 | NULL); 177 | 178 | /* fill in STARTUPINFO struct */ 179 | GetStartupInfo(&si); 180 | si.cb = sizeof(si); 181 | si.dwFlags = STARTF_USESTDHANDLES; 182 | si.wShowWindow = SW_SHOWDEFAULT; 183 | si.hStdInput = NULL; 184 | si.hStdOutput = logfile_handle; 185 | si.hStdError = logfile_handle; 186 | 187 | /* make an env array with confg specific env appended to the process's env */ 188 | WCHAR *env = c->es ? merge_env_block(c->es) : NULL; 189 | DWORD flags = CREATE_UNICODE_ENVIRONMENT; 190 | 191 | if (!CreateProcess( 192 | NULL, 193 | cmdline, 194 | NULL, 195 | NULL, 196 | TRUE, 197 | (o.show_script_window ? flags | CREATE_NEW_CONSOLE : flags | CREATE_NO_WINDOW), 198 | env, 199 | c->config_dir, 200 | &si, 201 | &pi)) 202 | { 203 | PrintDebug(L"CreateProcess: error = %lu", GetLastError()); 204 | ShowLocalizedMsgEx(MB_OK | MB_ICONERROR, 205 | c->hwndStatus, 206 | TEXT(PACKAGE_NAME), 207 | IDS_ERR_RUN_CONN_SCRIPT, 208 | cmdline); 209 | goto out; 210 | } 211 | 212 | if (o.connectscript_timeout == 0) 213 | { 214 | goto out; 215 | } 216 | 217 | for (i = 0; i <= (int)o.connectscript_timeout; i++) 218 | { 219 | if (!GetExitCodeProcess(pi.hProcess, &exit_code)) 220 | { 221 | ShowLocalizedMsgEx(MB_OK | MB_ICONERROR, 222 | c->hwndStatus, 223 | TEXT(PACKAGE_NAME), 224 | IDS_ERR_GET_EXIT_CODE, 225 | cmdline); 226 | goto out; 227 | } 228 | 229 | if (exit_code != STILL_ACTIVE) 230 | { 231 | if (exit_code != 0) 232 | { 233 | ShowLocalizedMsgEx(MB_OK | MB_ICONERROR, 234 | c->hwndStatus, 235 | TEXT(PACKAGE_NAME), 236 | IDS_ERR_CONN_SCRIPT_FAILED, 237 | exit_code); 238 | } 239 | goto out; 240 | } 241 | 242 | if (!OVPNMsgWait(1000, c->hwndStatus)) /* WM_QUIT -- do not popup error */ 243 | { 244 | goto out; 245 | } 246 | } 247 | 248 | ShowLocalizedMsgEx(MB_OK | MB_ICONERROR, 249 | c->hwndStatus, 250 | TEXT(PACKAGE_NAME), 251 | IDS_ERR_RUN_CONN_SCRIPT_TIMEOUT, 252 | o.connectscript_timeout); 253 | 254 | out: 255 | free(env); 256 | CloseHandleEx(&pi.hThread); 257 | CloseHandleEx(&pi.hProcess); 258 | CloseHandleEx(&logfile_handle); 259 | } 260 | 261 | 262 | void 263 | RunDisconnectScript(connection_t *c, int run_as_service) 264 | { 265 | STARTUPINFO si; 266 | PROCESS_INFORMATION pi; 267 | TCHAR cmdline[256]; 268 | DWORD exit_code; 269 | struct _stat st; 270 | int i; 271 | 272 | CLEAR(si); 273 | CLEAR(pi); 274 | 275 | /* Cut off extention from config filename and add "_down.bat" */ 276 | int len = _tcslen(c->config_file) - _tcslen(o.ext_string) - 1; 277 | _sntprintf_0(cmdline, _T("%ls\\%.*ls_down.bat"), c->config_dir, len, c->config_file); 278 | 279 | /* Return if no script exists */ 280 | if (_tstat(cmdline, &st) == -1) 281 | { 282 | return; 283 | } 284 | 285 | if (!run_as_service) 286 | { 287 | SetDlgItemText( 288 | c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_DISCONN_SCRIPT)); 289 | } 290 | 291 | /* Create the filename of the logfile */ 292 | TCHAR script_log_filename[MAX_PATH]; 293 | _sntprintf_0(script_log_filename, _T("%ls\\%ls_down.log"), o.log_dir, c->config_name); 294 | 295 | /* Create the log file */ 296 | SECURITY_ATTRIBUTES sa; 297 | CLEAR(sa); 298 | sa.nLength = sizeof(SECURITY_ATTRIBUTES); 299 | sa.lpSecurityDescriptor = NULL; 300 | sa.bInheritHandle = TRUE; 301 | 302 | HANDLE logfile_handle = CreateFile(script_log_filename, 303 | GENERIC_WRITE, 304 | FILE_SHARE_READ | FILE_SHARE_WRITE, 305 | &sa, 306 | CREATE_ALWAYS, 307 | FILE_ATTRIBUTE_NORMAL, 308 | NULL); 309 | 310 | /* fill in STARTUPINFO struct */ 311 | GetStartupInfo(&si); 312 | si.cb = sizeof(si); 313 | si.dwFlags = STARTF_USESTDHANDLES; 314 | si.wShowWindow = SW_SHOWDEFAULT; 315 | si.hStdInput = NULL; 316 | si.hStdOutput = logfile_handle; 317 | si.hStdError = logfile_handle; 318 | 319 | /* make an env array with confg specific env appended to the process's env */ 320 | WCHAR *env = c->es ? merge_env_block(c->es) : NULL; 321 | DWORD flags = CREATE_UNICODE_ENVIRONMENT; 322 | 323 | if (!CreateProcess( 324 | NULL, 325 | cmdline, 326 | NULL, 327 | NULL, 328 | TRUE, 329 | (o.show_script_window ? flags | CREATE_NEW_CONSOLE : flags | CREATE_NO_WINDOW), 330 | NULL, 331 | c->config_dir, 332 | &si, 333 | &pi)) 334 | { 335 | goto out; 336 | } 337 | 338 | for (i = 0; i <= (int)o.disconnectscript_timeout; i++) 339 | { 340 | if (!GetExitCodeProcess(pi.hProcess, &exit_code) || exit_code != STILL_ACTIVE 341 | || !OVPNMsgWait(1000, c->hwndStatus)) /* WM_QUIT -- do not popup error */ 342 | { 343 | goto out; 344 | } 345 | } 346 | out: 347 | free(env); 348 | CloseHandleEx(&pi.hThread); 349 | CloseHandleEx(&pi.hProcess); 350 | CloseHandleEx(&logfile_handle); 351 | } 352 | -------------------------------------------------------------------------------- /scripts.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2004 Mathias Sundman 5 | * 2010 Heiko Hund 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program (see the file COPYING included with this 19 | * distribution); if not, write to the Free Software Foundation, Inc., 20 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | */ 22 | 23 | #ifndef SCRIPTS_H 24 | #define SCRIPTS_H 25 | 26 | void RunPreconnectScript(connection_t *); 27 | 28 | void RunConnectScript(connection_t *, int run_as_service); 29 | 30 | void RunDisconnectScript(connection_t *, int run_as_service); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /service.c: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2004 Mathias Sundman 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include 24 | #endif 25 | 26 | #include 27 | #include 28 | 29 | #include "service.h" 30 | #include "options.h" 31 | #include "main.h" 32 | #include "misc.h" 33 | #include "openvpn-gui-res.h" 34 | #include "localization.h" 35 | 36 | #define OPENVPN_SERVICE_NAME_OVPN3 L"ovpnagent" 37 | #define OPENVPN_SERVICE_NAME_OVPN2 L"OpenVPNServiceInteractive" 38 | 39 | extern options_t o; 40 | 41 | BOOL 42 | CheckIServiceStatus(BOOL warn) 43 | { 44 | SC_HANDLE schSCManager = NULL; 45 | SC_HANDLE schService = NULL; 46 | SERVICE_STATUS ssStatus; 47 | BOOL ret = false; 48 | 49 | /* Open a handle to the SC Manager database. */ 50 | schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); 51 | 52 | if (NULL == schSCManager) 53 | { 54 | return (false); 55 | } 56 | 57 | schService = OpenService(schSCManager, 58 | o.ovpn_engine == OPENVPN_ENGINE_OVPN3 ? OPENVPN_SERVICE_NAME_OVPN3 59 | : OPENVPN_SERVICE_NAME_OVPN2, 60 | SERVICE_QUERY_STATUS); 61 | 62 | if (schService == NULL && GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) 63 | { 64 | /* warn that iservice is not installed */ 65 | if (warn) 66 | { 67 | ShowLocalizedMsg(IDS_ERR_INSTALL_ISERVICE); 68 | } 69 | goto out; 70 | } 71 | 72 | if (!QueryServiceStatus(schService, &ssStatus)) 73 | { 74 | goto out; 75 | } 76 | 77 | if (ssStatus.dwCurrentState != SERVICE_RUNNING) 78 | { 79 | /* warn that iservice is not started */ 80 | if (warn) 81 | { 82 | if (IsUserAdmin()) 83 | { 84 | ShowLocalizedMsg(IDS_ERR_NOTSTARTED_ISERVICE_ADM); 85 | } 86 | else 87 | { 88 | ShowLocalizedMsg(IDS_ERR_NOTSTARTED_ISERVICE); 89 | } 90 | } 91 | goto out; 92 | } 93 | ret = true; 94 | 95 | out: 96 | if (schService) 97 | { 98 | CloseServiceHandle(schService); 99 | } 100 | if (schSCManager) 101 | { 102 | CloseServiceHandle(schSCManager); 103 | } 104 | return ret; 105 | } 106 | 107 | VOID 108 | CheckServiceStatus() 109 | { 110 | SC_HANDLE schSCManager = NULL; 111 | SC_HANDLE schService = NULL; 112 | SERVICE_STATUS ssStatus; 113 | 114 | /* Open a handle to the SC Manager database. */ 115 | schSCManager = OpenSCManager(NULL, /* local machine */ 116 | NULL, /* ServicesActive database */ 117 | SC_MANAGER_CONNECT); /* Connect rights */ 118 | 119 | if (NULL == schSCManager) 120 | { 121 | o.service_state = service_noaccess; 122 | goto out; 123 | } 124 | 125 | schService = OpenService(schSCManager, /* SCM database */ 126 | _T("OpenVPNService"), /* service name */ 127 | SERVICE_QUERY_STATUS); 128 | 129 | if (schService == NULL) 130 | { 131 | o.service_state = service_noaccess; 132 | goto out; 133 | } 134 | 135 | if (!QueryServiceStatus(schService, /* handle to service */ 136 | &ssStatus)) /* address of status information structure */ 137 | { 138 | /* query failed */ 139 | o.service_state = service_noaccess; 140 | MsgToEventLog(EVENTLOG_ERROR_TYPE, LoadLocalizedString(IDS_ERR_QUERY_SERVICE)); 141 | goto out; 142 | } 143 | 144 | if (ssStatus.dwCurrentState == SERVICE_RUNNING) 145 | { 146 | o.service_state = service_connected; 147 | goto out; 148 | } 149 | else 150 | { 151 | o.service_state = service_disconnected; 152 | goto out; 153 | } 154 | 155 | out: 156 | if (schService) 157 | { 158 | CloseServiceHandle(schService); 159 | } 160 | if (schSCManager) 161 | { 162 | CloseServiceHandle(schSCManager); 163 | } 164 | } 165 | 166 | /* Attempt to start OpenVPN Automatc Service */ 167 | void 168 | StartAutomaticService(void) 169 | { 170 | SC_HANDLE schSCManager = NULL; 171 | SC_HANDLE schService = NULL; 172 | 173 | schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); 174 | 175 | if (schSCManager) 176 | { 177 | schService = OpenService(schSCManager, L"OpenVPNService", SERVICE_START); 178 | 179 | if (schService) 180 | { 181 | StartService(schService, 0, NULL); 182 | CloseServiceHandle(schService); 183 | } 184 | 185 | CloseServiceHandle(schSCManager); 186 | } 187 | return; 188 | } 189 | 190 | /* 191 | * Returns the processId of the Interactive Service or zero on error 192 | * which includes service not running. 193 | */ 194 | ULONG 195 | GetServicePid(void) 196 | { 197 | SC_HANDLE schManager; 198 | SC_HANDLE schService; 199 | ULONG pid = 0; 200 | 201 | schManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); 202 | if (schManager) 203 | { 204 | schService = OpenService(schManager, 205 | o.ovpn_engine == OPENVPN_ENGINE_OVPN3 ? OPENVPN_SERVICE_NAME_OVPN3 206 | : OPENVPN_SERVICE_NAME_OVPN2, 207 | SERVICE_QUERY_STATUS); 208 | if (schService) 209 | { 210 | SERVICE_STATUS_PROCESS ssp = { 0 }; 211 | DWORD nbytes = 0; 212 | if (QueryServiceStatusEx( 213 | schService, SC_STATUS_PROCESS_INFO, (BYTE *)&ssp, sizeof(ssp), &nbytes) 214 | && ssp.dwCurrentState == SERVICE_RUNNING) 215 | { 216 | pid = ssp.dwProcessId; 217 | } 218 | CloseServiceHandle(schService); 219 | } 220 | CloseServiceHandle(schManager); 221 | } 222 | if (pid == 0) 223 | { 224 | MsgToEventLog(EVENTLOG_ERROR_TYPE, 225 | L"%hs:%d Failed to get service process id: (error = 0x%08x)", 226 | __func__, 227 | __LINE__, 228 | GetLastError()); 229 | } 230 | return pid; 231 | } 232 | -------------------------------------------------------------------------------- /service.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2004 Mathias Sundman 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | VOID CheckServiceStatus(); 23 | 24 | BOOL CheckIServiceStatus(BOOL warn); 25 | 26 | /* Attempt to start OpenVPN Automatc Service */ 27 | void StartAutomaticService(void); 28 | 29 | /* Get the processId of the Interactive Service */ 30 | ULONG GetServicePid(void); 31 | -------------------------------------------------------------------------------- /tray.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2004 Mathias Sundman 5 | * 2010 Heiko Hund 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program (see the file COPYING included with this 19 | * distribution); if not, write to the Free Software Foundation, Inc., 20 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | */ 22 | 23 | #ifndef TRAY_H 24 | #define TRAY_H 25 | 26 | #include "options.h" 27 | 28 | #define IDM_SERVICE_START 100 29 | #define IDM_SERVICE_STOP 101 30 | #define IDM_SERVICE_RESTART 102 31 | 32 | #define IDM_SETTINGS 221 33 | #define IDM_CLOSE 223 34 | #define IDM_IMPORT 224 35 | #define IDM_IMPORT_FILE 225 36 | #define IDM_IMPORT_AS 226 37 | #define IDM_IMPORT_URL 227 38 | 39 | #define IDM_CONNECTMENU 300 40 | #define IDM_DISCONNECTMENU (1 + IDM_CONNECTMENU) 41 | #define IDM_STATUSMENU (1 + IDM_DISCONNECTMENU) 42 | #define IDM_VIEWLOGMENU (1 + IDM_STATUSMENU) 43 | #define IDM_EDITMENU (1 + IDM_VIEWLOGMENU) 44 | #define IDM_PASSPHRASEMENU (1 + IDM_EDITMENU) 45 | #define IDM_CLEARPASSMENU (1 + IDM_PASSPHRASEMENU) 46 | #define IDM_RECONNECTMENU (1 + IDM_CLEARPASSMENU) 47 | 48 | void RecreatePopupMenus(void); 49 | 50 | void CreatePopupMenus(); 51 | 52 | void OnNotifyTray(LPARAM); 53 | 54 | void OnDestroyTray(void); 55 | 56 | void ShowTrayIcon(); 57 | 58 | void RemoveTrayIcon(); 59 | 60 | void SetTrayIcon(conn_state_t); 61 | 62 | void SetMenuStatus(connection_t *, conn_state_t); 63 | 64 | void SetServiceMenuStatus(); 65 | 66 | void ShowTrayBalloon(TCHAR *, TCHAR *); 67 | 68 | void CheckAndSetTrayIcon(); 69 | 70 | #endif /* ifndef TRAY_H */ 71 | -------------------------------------------------------------------------------- /vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "openvpn-gui", 3 | "version-string": "0.0.1", 4 | "dependencies": [ 5 | "json-c" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /viewlog.c: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2004 Mathias Sundman 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include 24 | #endif 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "tray.h" 32 | #include "openvpn.h" 33 | #include "main.h" 34 | #include "options.h" 35 | #include "openvpn-gui-res.h" 36 | #include "localization.h" 37 | 38 | extern options_t o; 39 | 40 | void 41 | ViewLog(connection_t *c) 42 | { 43 | TCHAR filename[2 * MAX_PATH]; 44 | 45 | STARTUPINFO start_info; 46 | PROCESS_INFORMATION proc_info; 47 | SECURITY_ATTRIBUTES sa; 48 | SECURITY_DESCRIPTOR sd; 49 | HINSTANCE status; 50 | 51 | CLEAR(start_info); 52 | CLEAR(proc_info); 53 | CLEAR(sa); 54 | CLEAR(sd); 55 | 56 | /* Try first using file association */ 57 | CoInitializeEx(NULL, 58 | COINIT_APARTMENTTHREADED 59 | | COINIT_DISABLE_OLE1DDE); /* Safe to init COM multiple times */ 60 | status = ShellExecuteW(o.hWnd, L"open", c->log_path, NULL, o.log_dir, SW_SHOWNORMAL); 61 | 62 | if (status > (HINSTANCE)32) /* Success */ 63 | { 64 | return; 65 | } 66 | else 67 | { 68 | PrintDebug(L"Opening log file using ShellExecute with verb = open failed" 69 | " for config '%ls' (status = %lu)", 70 | c->config_name, 71 | status); 72 | } 73 | 74 | _sntprintf_0(filename, _T("%ls \"%ls\""), o.log_viewer, c->log_path); 75 | 76 | /* fill in STARTUPINFO struct */ 77 | GetStartupInfo(&start_info); 78 | start_info.cb = sizeof(start_info); 79 | start_info.dwFlags = 0; 80 | start_info.wShowWindow = SW_SHOWDEFAULT; 81 | start_info.hStdInput = NULL; 82 | start_info.hStdOutput = NULL; 83 | 84 | if (!CreateProcess(NULL, 85 | filename, /*commandline */ 86 | NULL, 87 | NULL, 88 | TRUE, 89 | CREATE_NEW_CONSOLE, 90 | NULL, 91 | o.log_dir, /*start-up dir */ 92 | &start_info, 93 | &proc_info)) 94 | { 95 | /* could not start log viewer */ 96 | ShowLocalizedMsg(IDS_ERR_START_LOG_VIEWER, o.log_viewer); 97 | } 98 | 99 | CloseHandle(proc_info.hThread); 100 | CloseHandle(proc_info.hProcess); 101 | } 102 | 103 | 104 | void 105 | EditConfig(connection_t *c) 106 | { 107 | TCHAR filename[2 * MAX_PATH]; 108 | 109 | STARTUPINFO start_info; 110 | PROCESS_INFORMATION proc_info; 111 | SECURITY_ATTRIBUTES sa; 112 | SECURITY_DESCRIPTOR sd; 113 | HINSTANCE status; 114 | 115 | CLEAR(start_info); 116 | CLEAR(proc_info); 117 | CLEAR(sa); 118 | CLEAR(sd); 119 | 120 | /* Try first using file association */ 121 | _sntprintf_0(filename, L"%ls\\%ls", c->config_dir, c->config_file); 122 | 123 | CoInitializeEx(NULL, 124 | COINIT_APARTMENTTHREADED 125 | | COINIT_DISABLE_OLE1DDE); /* Safe to init COM multiple times */ 126 | status = ShellExecuteW(o.hWnd, L"open", filename, NULL, c->config_dir, SW_SHOWNORMAL); 127 | if (status > (HINSTANCE)32) 128 | { 129 | return; 130 | } 131 | else 132 | { 133 | PrintDebug(L"Opening config file using ShellExecute with verb = open failed" 134 | " for config '%ls' (status = %lu)", 135 | c->config_name, 136 | status); 137 | } 138 | 139 | _sntprintf_0(filename, _T("%ls \"%ls\\%ls\""), o.editor, c->config_dir, c->config_file); 140 | 141 | /* fill in STARTUPINFO struct */ 142 | GetStartupInfo(&start_info); 143 | start_info.cb = sizeof(start_info); 144 | start_info.dwFlags = 0; 145 | start_info.wShowWindow = SW_SHOWDEFAULT; 146 | start_info.hStdInput = NULL; 147 | start_info.hStdOutput = NULL; 148 | 149 | if (!CreateProcess(NULL, 150 | filename, /*commandline */ 151 | NULL, 152 | NULL, 153 | TRUE, 154 | CREATE_NEW_CONSOLE, 155 | NULL, 156 | c->config_dir, /*start-up dir */ 157 | &start_info, 158 | &proc_info)) 159 | { 160 | /* could not start editor */ 161 | ShowLocalizedMsg(IDS_ERR_START_CONF_EDITOR, o.editor); 162 | } 163 | 164 | CloseHandle(proc_info.hThread); 165 | CloseHandle(proc_info.hProcess); 166 | } 167 | -------------------------------------------------------------------------------- /viewlog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenVPN-GUI -- A Windows GUI for OpenVPN. 3 | * 4 | * Copyright (C) 2004 Mathias Sundman 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program (see the file COPYING included with this 18 | * distribution); if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | struct connection; 23 | 24 | void ViewLog(struct connection *c); 25 | void EditConfig(struct connection *c); 26 | --------------------------------------------------------------------------------