summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkali <kali@win>2021-04-05 16:15:29 +0200
committerkali kaneko (leap communications) <kali@leap.se>2022-07-06 01:57:45 +0200
commitd1252ef5b90870e55389188d351aabfe55a932f6 (patch)
tree7994263d56cbbecfe6ab77eff76346c18732ff6c
parent048e2914a7e646b7fd8bb6b024c7839259aaecc9 (diff)
[feat] use named pipe to launch openvpn
- Resolves: #339
-rw-r--r--Makefile23
-rw-r--r--branding/templates/qtinstaller/packages/bitmaskvpn/meta/install.js20
-rw-r--r--pkg/helper/windows.go3
-rw-r--r--pkg/vpn/launcher_linux.go1
-rw-r--r--pkg/vpn/launcher_osx.go (renamed from pkg/vpn/launcher.go)5
-rw-r--r--pkg/vpn/launcher_windows.go158
-rw-r--r--pkg/vpn/openvpn.go12
7 files changed, 186 insertions, 36 deletions
diff --git a/Makefile b/Makefile
index 5d20832..b6fbaa4 100644
--- a/Makefile
+++ b/Makefile
@@ -43,7 +43,7 @@ endif
SCRIPTS = branding/scripts
TEMPLATES = branding/templates
-TAP_WINDOWS = https://build.openvpn.net/downloads/releases/tap-windows-9.24.2-I601-Win10.exe
+OPENVPN_WINDOWS_INSTALLER = https://build.openvpn.net/downloads/releases/OpenVPN-2.5.1-I601-amd64.msi
HAS_QTIFW != which binarycreator.exe 2>/dev/null || PATH=$(PATH) which binarycreator
OPENVPN_BIN != echo -n "$(HOME)/openvpn_build/sbin/$$(grep OPENVPN branding/thirdparty/openvpn/build_openvpn.sh | head -n 1 | cut -d = -f 2 | tr -d '"')"
@@ -160,21 +160,11 @@ ifeq (${PLATFORM}, windows)
"c:\windows\system32\rcedit.exe" ${QTBUILD}/release/${TARGET}.exe --set-version-string CompanyName "LEAP Encryption Access Project"
"c:\windows\system32\rcedit.exe" ${QTBUILD}/release/${TARGET}.exe --set-version-string FileDescription "${APPNAME}"
"c:\windows\system32\signtool.exe" sign -debug -f "z:\leap\LEAP.pfx" -p ${WINCERTPASS} ${QTBUILD}/release/${TARGET}.exe
- # XXX need to deprecate helper and embrace interactive service
- cp build/bin/${PLATFORM}/bitmask-helper build/bin/${PLATFORM}/bitmask-helper.exe
- "c:\windows\system32\rcedit.exe" build/bin/${PLATFORM}/bitmask-helper.exe --set-file-version ${VERSION}
- "c:\windows\system32\rcedit.exe" build/bin/${PLATFORM}/bitmask-helper.exe --set-product-version ${VERSION}
- "c:\windows\system32\rcedit.exe" build/bin/${PLATFORM}/bitmask-helper.exe --set-version-string ProductName "bitmask-helper-v2"
- "c:\windows\system32\rcedit.exe" build/bin/${PLATFORM}/bitmask-helper.exe --set-version-string CompanyName "LEAP Encryption Access Project"
- "c:\windows\system32\rcedit.exe" build/bin/${PLATFORM}/bitmask-helper.exe --set-version-string FileDescription "Administrative helper for ${APPNAME}"
- "c:\windows\system32\signtool.exe" sign -debug -f "z:\leap\LEAP.pfx" -p ${WINCERTPASS} build/bin/${PLATFORM}/bitmask-helper.exe
endif
checksign:
ifeq (${PLATFORM}, windows)
@"c:\windows\system32\sigcheck.exe" ${QTBUILD}/release/${TARGET}.exe
- @"c:\windows\system32\sigcheck.exe" build/bin/${PLATFORM}/bitmask-helper.exe
- @"c:\windows\system32\sigcheck.exe" "/c/Program Files/OpenVPN/bin/openvpn.exe"
endif
installer: check_qtifw checksign
@@ -207,29 +197,24 @@ endif
endif
ifeq (${PLATFORM}, windows)
@VERSION=${VERSION} VENDOR_PATH=${VENDOR_PATH} ${SCRIPTS}/gen-qtinstaller windows ${INSTALLER}
- @cp build/bin/${PLATFORM}/bitmask-helper.exe ${INST_DATA}helper.exe
ifeq (${VENDOR_PATH}, providers)
@cp ${VENDOR_PATH}/${PROVIDER}/assets/icon.ico ${INST_DATA}/icon.ico
else
@cp ${VENDOR_PATH}/assets/icon.ico ${INST_DATA}/icon.ico
endif
@cp ${QTBUILD}/release/${TARGET}.exe ${INST_DATA}${TARGET}.exe
- @cp "/c/Program Files/OpenVPN/bin/openvpn.exe" ${INST_DATA}
- @cp "/c/Program Files/OpenVPN/bin/"*.dll ${INST_DATA}
ifeq (${RELEASE}, yes)
- #@windeployqt --release --qmldir gui/components ${INST_DATA}${TARGET}.exe
- #FIXME -- cannot find platform plugin
- @windeployqt --qmldir gui/components ${INST_DATA}${TARGET}.exe
+ @windeployqt --qmldir gui/qml ${INST_DATA}${TARGET}.exe # FIXME --release flag cannot find platform plugin
else
@windeployqt --qmldir gui/components ${INST_DATA}${TARGET}.exe
endif
- # TODO stage it to shave some time
- @wget ${TAP_WINDOWS} -O ${INST_DATA}/tap-windows.exe
# XXX this is a workaround for missing libs after windeployqt ---
@cp /c/Qt/5.15.2/mingw81_64/bin/libgcc_s_seh-1.dll ${INST_DATA}
@cp /c/Qt/5.15.2/mingw81_64/bin/libstdc++-6.dll ${INST_DATA}
@cp /c/Qt/5.15.2/mingw81_64/bin/libwinpthread-1.dll ${INST_DATA}
@cp -r /c/Qt/5.15.2/mingw81_64/qml ${INST_DATA}
+ # TODO stage it
+ @wget ${OPENVPN_WINDOWS_INSTALLER} -O ${INST_DATA}openvpn-installer.msi
endif
ifeq (${PLATFORM}, linux)
@VERSION=${VERSION} ${SCRIPTS}/gen-qtinstaller linux ${INSTALLER}
diff --git a/branding/templates/qtinstaller/packages/bitmaskvpn/meta/install.js b/branding/templates/qtinstaller/packages/bitmaskvpn/meta/install.js
index aa3da1f..fcdb61c 100644
--- a/branding/templates/qtinstaller/packages/bitmaskvpn/meta/install.js
+++ b/branding/templates/qtinstaller/packages/bitmaskvpn/meta/install.js
@@ -99,24 +99,18 @@ function preInstallWindows() {
}
function postInstallWindows() {
- // TODO - check if we're on Windows10 or older, and use the needed tap-windows installer accordingly.
- console.log("Installing OpenVPN tap driver");
- component.addElevatedOperation("Execute", "@TargetDir@/tap-windows.exe", "/S", "/SELECT_UTILITIES=1"); /* TODO uninstall */
- /* remove an existing service, if it is stopped. Remove-Service is only in PS>6, and sc.exe delete leaves some garbage on the registry, so let's use the binary itself */
- console.log("Removing any previously installer helper...");
- component.addElevatedOperation("Execute", "{0,1}", "@TargetDir@/helper.exe", "remove");
- console.log("Now trying to install latest helper");
- component.addElevatedOperation("Execute", "@TargetDir@/helper.exe", "install", "UNDOEXECUTE", "@TargetDir@/helper.exe", "remove");
- component.addElevatedOperation("Execute", "@TargetDir@/helper.exe", "start", "UNDOEXECUTE", "@TargetDir@/helper.exe", "stop");
- console.log("Adding shortcut entries/...");
+ // TODO - we probably need to package different flavors of the installer for windows 8, arm, i386 etc, and change the installer we ship too.
+ console.log("Installing OpenVPN binaries and service");
+ component.addElevatedOperation("Execute", "{0}", "msiexec", "/i", "@TargetDir@\\openvpn-installer.msi", "ADDLOCAL=OpenVPN.Service,OpenVPN,Drivers,Drivers.TAPWindows6,Drivers.Wintun", "/passive")
+ console.log("Adding shortcut entries...");
component.addElevatedOperation("Mkdir", "@StartMenuDir@");
- component.addElevatedOperation("CreateShortcut", "@TargetDir@/$BINNAME.exe", "@StartMenuDir@/$APPNAME.lnk", "workingDirectory=@TargetDir@", "iconPath=@TargetDir@/icon.ico", "description=Start $APPNAME");
+ component.addElevatedOperation("CreateShortcut", "@TargetDir@\\$BINNAME.exe", "@StartMenuDir@\\$APPNAME.lnk", "workingDirectory=@TargetDir@", "iconPath=@TargetDir@\\icon.ico", "description=Start $APPNAME");
// TODO I think this one is not being created because the path doesn't exist yet. We might want to do this by hooking on the installation finished signal instead.
component.addElevatedOperation(
"CreateShortcut",
- "@TargetDir@/Uninstall-$APPNAME.exe",
- "@StartMenuDir@/Uninstall.lnk"
+ "@TargetDir@\\Uninstall-$APPNAME.exe",
+ "@StartMenuDir@\\Uninstall.lnk"
);
}
diff --git a/pkg/helper/windows.go b/pkg/helper/windows.go
index ca1642e..f7e035d 100644
--- a/pkg/helper/windows.go
+++ b/pkg/helper/windows.go
@@ -42,8 +42,9 @@ var (
func getPlatformOpenvpnFlags() []string {
return []string{
- "--script-security", "1",
+ "--script-security", "0",
"--block-outside-dns",
+ "--redirect-gateway",
}
}
diff --git a/pkg/vpn/launcher_linux.go b/pkg/vpn/launcher_linux.go
index 1fbcd6f..4925a17 100644
--- a/pkg/vpn/launcher_linux.go
+++ b/pkg/vpn/launcher_linux.go
@@ -40,6 +40,7 @@ var bitmaskRootPaths = []string{
type launcher struct {
openvpnCh chan []string
failed bool
+ mngPass string
}
func newLauncher() (*launcher, error) {
diff --git a/pkg/vpn/launcher.go b/pkg/vpn/launcher_osx.go
index f6e08eb..b676c24 100644
--- a/pkg/vpn/launcher.go
+++ b/pkg/vpn/launcher_osx.go
@@ -1,5 +1,5 @@
-// +build !linux
-// Copyright (C) 2018-2020 LEAP
+// +build osx
+// Copyright (C) 2018-2021 LEAP
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -36,6 +36,7 @@ import (
type launcher struct {
helperAddr string
failed bool
+ mngPass string
}
const initialHelperPort = 7171
diff --git a/pkg/vpn/launcher_windows.go b/pkg/vpn/launcher_windows.go
new file mode 100644
index 0000000..be5ef83
--- /dev/null
+++ b/pkg/vpn/launcher_windows.go
@@ -0,0 +1,158 @@
+// +build windows
+// Copyright (C) 2018-2021 LEAP
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package vpn
+
+import (
+ "errors"
+ "log"
+ "os"
+ "strings"
+ "bufio"
+ "fmt"
+ "unicode/utf16"
+ "bytes"
+ "time"
+ "encoding/binary"
+
+ "github.com/natefinch/npipe"
+ "0xacab.org/leap/bitmask-vpn/pkg/vpn/bonafide"
+)
+
+const pipeName = `\\.\pipe\openvpn\service`
+
+type launcher struct {
+ mngPass string
+}
+
+func newLauncher() (*launcher, error) {
+ l := launcher{}
+ return &l, nil
+}
+
+func (l *launcher) close() error {
+ return nil
+}
+
+func (l *launcher) check() (helpers bool, privilege bool, err error) {
+ // TODO check if the named pipe exists
+ return true, true, nil
+}
+
+func (l *launcher) openvpnStart(flags ...string) error {
+ var b bytes.Buffer
+ var filtered []string
+ for _, v := range flags {
+ if v != "--tun-ipv6" {
+ filtered = append(filtered, v)
+ }
+ }
+
+ cwd, _ := os.Getwd()
+ opts := `--client --dev tun --block-outside-dns --redirect-gateway --script-security 0 ` + strings.Join(filtered, " ")
+ log.Println("openvpn start: ", opts)
+
+ timeout := 3 * time.Second
+ conn, err := npipe.DialTimeout(pipeName, timeout)
+ if err != nil {
+ fmt.Println("ERROR opening pipe")
+ return errors.New("cannot open openvpn pipe")
+
+ }
+ defer conn.Close()
+
+ writeUTF16Bytes(&b, cwd)
+ writeUTF16Bytes(&b, opts)
+ writeUTF16Bytes(&b, `\n`)
+ encoded := b.Bytes()
+
+ rw := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
+
+ _, err = rw.Write(encoded)
+ if err != nil {
+ fmt.Println("ERROR writing to pipe")
+ return errors.New("cannot write to openvpn pipe")
+ }
+ rw.Flush()
+ pid, err := getCommandResponse(rw)
+ if err != nil {
+ fmt.Println("ERROR getting pid")
+ }
+ fmt.Println("OpenVPN PID:", pid)
+ return nil
+}
+
+func (l *launcher) openvpnStop() error {
+ return nil
+}
+
+// TODO we will have to bring our helper back to do firewall
+
+func (l *launcher) firewallStart(gateways []bonafide.Gateway) error {
+ log.Println("NO firewall in windows")
+ return nil
+}
+
+func (l *launcher) firewallStop() error {
+ log.Println("NO firewall in windows")
+ return nil
+}
+
+func (l *launcher) firewallIsUp() bool {
+ log.Println("NO firewall in windows")
+ return true
+}
+
+
+func writeUTF16Bytes(b *bytes.Buffer, in string) {
+ var u16 []uint16 = utf16.Encode([]rune(in + "\x00"))
+ binary.Write(b, binary.LittleEndian, u16)
+}
+
+func decodeUTF16String(s string) int {
+ var code int
+ var dec []byte
+ for _, v := range []byte(s) {
+ if byte(v) != byte(0) {
+ dec = append(dec, v)
+ }
+ }
+ _, err := fmt.Sscanf(string(dec), "%v", &code)
+ if err != nil {
+ fmt.Println("ERROR decoding")
+ }
+ return code
+}
+
+func getCommandResponse(rw *bufio.ReadWriter) (int, error) {
+ msg, err := rw.ReadString('\n')
+ if err != nil {
+ fmt.Println("ERROR reading")
+ }
+ ok := decodeUTF16String(msg)
+ if ok != 0 {
+ return -1, errors.New("command failed")
+ }
+ msg, err = rw.ReadString('\n')
+ if err != nil {
+ fmt.Println("ERROR reading")
+ }
+ pid := decodeUTF16String(msg)
+ if pid == 0 {
+ return -1, errors.New("command failed")
+ }
+ return pid, nil
+}
diff --git a/pkg/vpn/openvpn.go b/pkg/vpn/openvpn.go
index a114980..ee0e2f7 100644
--- a/pkg/vpn/openvpn.go
+++ b/pkg/vpn/openvpn.go
@@ -265,7 +265,17 @@ func (b *Bitmask) StopVPN() error {
b.obfsvpnProxy.Stop()
b.obfsvpnProxy = nil
}
- return b.launch.openvpnStop()
+ b.stopFromManagement()
+ b.launch.openvpnStop()
+ return nil
+}
+
+func (b *Bitmask) stopFromManagement() error {
+ if b.managementClient == nil {
+ return fmt.Errorf("No management connected")
+ }
+ b.managementClient.SendSignal("SIGTERM")
+ return nil
}
// Reconnect to the VPN