Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • m1ghtfr3e/bitmask-vpn
  • leap/bitmask-vpn
  • meskio/bitmask-vpn
  • kali/bitmask-vpn
  • nsheep/bitmask-vpn
  • nilesh/bitmask-vpn
  • micah/bitmask-vpn
  • kwadronaut/bitmask-vpn
  • th/bitmask-vpn
  • wxl/bitmask-vpn
  • Nowa-Ammerlaan/bitmask-vpn
  • elijah/bitmask-vpn
  • happysalada/bitmask-vpn
  • JUZZZEE/bitmask-vpn
  • jkito/bitmask-vpn
  • panetone/bitmask-vpn
  • hsilva/bitmask-vpn
  • S0b0tkaZ11gy/bitmask-vpn
  • polster/bitmask-vpn-pahoeohe
  • Kulibin/bitmask-vpn
  • TheMimoGz/bitmask-vpn
  • fifi/bitmask-vpn
  • fly/bitmask-vpn
  • VlKozlove/bitmask-vpn
  • DonMephedrone/bitmask-vpn
  • Arti/bitmask-vpn
  • annxxxxx/bitmask-vpn
  • Arti/arti-bitmask-vpn-fork
  • peanut2/bitmask-vpn
29 results
Show changes
Showing
with 643 additions and 129 deletions
......@@ -8,7 +8,7 @@ import sys
import configparser
from provider import getDefaultProvider
from provider import getDefaultProviders
from provider import getProviderData
......@@ -40,7 +40,7 @@ if __name__ == "__main__":
configFile = os.path.join(VENDOR_PATH, 'vendor.conf')
config = configparser.ConfigParser()
config.read(configFile)
provider = getDefaultProvider(config)
provider = getDefaultProviders(config)[0]
data = getProviderData(provider, config)
if len(sys.argv) != 2:
......
......@@ -8,7 +8,7 @@ import configparser
import os
import sys
from provider import getDefaultProvider
from provider import getDefaultProviders
from provider import getProviderData
def getData():
......@@ -20,8 +20,8 @@ def getData():
sys.exit(1)
config = configparser.ConfigParser()
config.read(configPath)
defaultProvider = getDefaultProvider(config)
return getProviderData(getDefaultProvider(config), config)
defaultProvider = getDefaultProviders(config)[0]
return getProviderData(defaultProvider, config)
if __name__ == "__main__":
param = sys.argv[1]
......
......@@ -114,6 +114,7 @@ binaryName = {provider}-vpn
providerURL = https://{providerURL}
auth = anon
apiURL = https://api.{providerURL}/
apiVersion = 3
caURL = https://{providerURL}/ca.crt
infoURL = https://{providerURL}/vpn
......
......@@ -2,14 +2,15 @@ import datetime
import os
def getDefaultProvider(config):
def getDefaultProviders(config):
# returns a list of providers
provider = os.environ.get('PROVIDER')
if provider:
print('[+] Got provider {} from environment'.format(provider))
else:
print('[+] Using default provider from config file')
provider = config['default']['provider']
return provider
return provider.split(',')
def getProviderData(provider, config):
......@@ -18,18 +19,32 @@ def getProviderData(provider, config):
c = config[provider]
except Exception:
raise ValueError('Cannot find provider')
d = dict()
keys = ('name', 'applicationName', 'binaryName', 'auth', 'authEmptyPass',
'providerURL', 'tosURL', 'helpURL',
'askForDonations', 'donateURL', 'apiURL',
'geolocationAPI', 'caCertString')
'apiVersion', 'geolocationAPI', 'caCertString',
'STUNServers', 'countryCodeLookupURL')
boolValues = ['askForDonations', 'authEmptyPass']
intValues = ['apiVersion', ]
listValues = ['STUNServers']
for value in keys:
if value not in c:
continue
d[value] = c.get(value)
if value in boolValues:
d[value] = bool(d[value])
elif value in intValues:
d[value] = int(d[value])
elif value in listValues:
if d[value].strip() == "":
d[value] = []
else:
d[value] = d[value].split(",")
# remove spaces
d[value] = [x.strip() for x in d[value]]
d['timeStamp'] = '{:%Y-%m-%d %H:%M:%S}'.format(
datetime.datetime.now())
......
......@@ -7,7 +7,7 @@ Comment[es]=VPN Facil de ${name}
Comment[de]=Easy VPN by ${name}
Exec=${binaryName} %U
Terminal=false
Icon=icon
Icon=${binaryName}
Categories=Network;Application;
StartupNotify=true
X-AppInstall-Package=${binaryName}
......
debian/${binaryName}.desktop usr/share/applications
debian/icons/scalable/${binaryName}.png usr/share/icons/hicolor/256x256/apps
${binaryName} (${version}) unstable; urgency=medium
* Initial package.
* Reduces the size of splash screen image
* Disable obfs4 and kcp checkbox in preferences for riseup
* Removes duplicate languages in the language picker in preferences
* Language picker in preferences shows languages sorted alphabetically
* Updates translation files
* Adds region to language selections menu when available
* Improves UI responsiveness when connect or disconnect fails
* Disable automatic openvpn connection during app start
* Fixes a local privilege escalation security bug when using "--install-helpers"
* Change bitmask branded app name to Bitmask from BitmaskVPN
* Fixes bug where MOTD message box was not shown for RiseupVPN
* Show bridge icon when KCP transport is selected
* Show license page during installation
* Uninstalls previous version before installing current version
* Adds accessibility hints to connection button
* Exposes KCP support in the UI
* Adds new bitmask-vpn package for Arch Linux
* Fixes a bug preventing use of the app by non-admin users on windows
* Fixes a bug on macOS preventing users from manual location selection
* Fixes a bug where the app's close routine was called twice
* Fixes a bug where log file was not closed while quitting the app
* Fixes a bug where the correct app name was not shown in installer error messages
* Updates to latest obfsvpn
* Updates to latest bitmask-core
* Updates translation files
* Adds missing iptables dependency to ubuntu package
-- LEAP Encryption Access Project <debian@leap.se> Mon, 29 Jul 2019 10:00:00 +0100
-- LEAP Encryption Access Project <debian@leap.se> Fri, 04 Oct 2024 09:16:36 +0200
riseup-vpn (0.24.5-3-geb2df9a~noble) noble; urgency=medium
* fixes missing dependencies on .deb package
* Shorten too long strings in translations
* Connection status text width trimmed to be inside parent container
* Update GUI to Qt6
* Fixes a bug where after using obfs4 it was impossible to gracefully close the app
-- LEAP Encryption Access Project <debian@leap.se> Sun, 19 May 2024 11:54:54 +0530
Source: ${binaryName}
Section: net
Priority: extra
Priority: optional
Maintainer: LEAP Encryption Access Project <debian@leap.se>
Build-Depends: debhelper-compat (= 12), golang-go (>= 2:1.9), make (>=3.80), pkg-config, g++ (>= 4:4.6.3), git,
qt5-qmake, qttools5-dev-tools, qtbase5-dev, libqt5qml5, libqt5quick5, qtdeclarative5-dev
Build-Depends: debhelper-compat (= 12), golang (>= 1.22), make (>=3.80), pkg-config, g++ (>= 4:4.6.3), git,
libqt6svg6-dev, qt6-tools-dev, qt6-tools-dev-tools, qt6-base-dev, libqt6qml6, qt6-declarative-dev,
dh-golang, libgl-dev, qt6-declarative-dev-tools, qt6-l10n-tools, python3
Standards-Version: 4.4.1
Homepage: https://0xacab.org/leap/bitmask-vpn
......@@ -11,14 +12,15 @@ Package: ${binaryName}
Architecture: any
Multi-Arch: foreign
Enhances: openvpn
Depends: ${misc:Depends}, libqt5core5a, libqt5gui5 | libqt5gui5-gles,
libqt5qml5, libqt5widgets5, libstdc++6,
qml-module-qtquick2, qml-module-qtquick-controls2, qml-module-qtquick-dialogs,
qml-module-qtquick-extras, qml-module-qt-labs-platform,
openvpn, policykit-1-gnome | polkit-1-auth-agent, python3
Depends: ${misc:Depends}, ${shlibs:Depends}, libqt6core6, libqt6gui6, libqt6qml6, libqt6widgets6, libstdc++6,
libqt6svg6, qml6-module-qtquick, qml6-module-qtquick-controls, qml6-module-qtquick-dialogs,
qml6-module-qtquick-layouts, qml6-module-qtqml-workerscript, qml6-module-qtquick-templates, qml6-module-qt-labs-settings,
qml6-module-qtquick-window, qml6-module-qt-labs-platform, qml6-module-qtcore, qml6-module-qt5compat-graphicaleffects,
openvpn, policykit-1-gnome | polkit-1-auth-agent, python3, iptables
Description: Easy, fast, and secure VPN service from ${name}.
This package is a custom build of the new Bitmask VPN client, preconfigured
to use the ${providerURL} provider.
.
The service does not require a user account, keep logs, or track you in any
way. The service is paid for entirely by donations from users.
......@@ -4,7 +4,7 @@ Source: <https://0xacab.org/leap/riseup_vpn>
Files: *
Copyright: 2018 LEAP Encryption Access Project <info@leap.se>
License: GPLv3
License: GPL
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
......
......@@ -10,7 +10,7 @@ import os
from string import Template
TEMPLATES = ('app.desktop', 'changelog', 'control', 'rules')
TEMPLATES = ('app.install', 'app.desktop', 'changelog', 'control', 'rules', 'source/include-binaries')
here = os.path.split(os.path.realpath(__file__))[0]
......
From 82e3eda5709f1f8dd6bdb898a3c6b71a41cc4e62 Mon Sep 17 00:00:00 2001
From: jkito <belter@riseup.net>
Date: Sun, 25 Aug 2024 17:18:10 +0530
Subject: [PATCH] build: use qt5compat qml module to build on qt6.4 for ubuntu
and debian
---
bitmask.pro | 2 +-
gui/components/ErrorBox.qml | 2 +-
gui/components/Footer.qml | 14 ++++++--------
gui/components/Home.qml | 2 +-
gui/components/InitErrors.qml | 2 +-
gui/components/Locations.qml | 7 +++----
gui/components/MotdBox.qml | 2 +-
gui/components/Preferences.qml | 4 ++--
gui/components/SignalIcon.qml | 7 +++----
gui/components/Splash.qml | 2 +-
gui/components/StatusBox.qml | 2 +-
11 files changed, 21 insertions(+), 25 deletions(-)
diff --git a/bitmask.pro b/bitmask.pro
index bbeacb12..58ba5f2f 100644
--- a/bitmask.pro
+++ b/bitmask.pro
@@ -1,8 +1,8 @@
TARGET = $$TARGET
QT += quickcontrols2 svg
-CONFIG += qt staticlib
CONFIG += c++17 strict_c++
+CONFIG += qt staticlib core5compat
CONFIG += qtquickcompiler
RELEASE = $$RELEASE
diff --git a/gui/components/ErrorBox.qml b/gui/components/ErrorBox.qml
index 5667ed9d..ef8f58fb 100644
--- a/gui/components/ErrorBox.qml
+++ b/gui/components/ErrorBox.qml
@@ -1,6 +1,6 @@
import QtQuick
import QtQuick.Controls
-import QtQuick.Effects
+import Qt5Compat.GraphicalEffects
import "../themes/themes.js" as Theme
Item {
diff --git a/gui/components/Footer.qml b/gui/components/Footer.qml
index d534f96a..9df6db62 100644
--- a/gui/components/Footer.qml
+++ b/gui/components/Footer.qml
@@ -2,7 +2,7 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Material
import QtQuick.Layouts
-import QtQuick.Effects
+import Qt5Compat.GraphicalEffects
import "../themes/themes.js" as Theme
ToolBar {
@@ -49,7 +49,7 @@ ToolBar {
}
Image {
- id: lightning
+ id: lightning
smooth: true
visible: ctx != undefined & root.selectedGateway == "auto"
width: 16
@@ -61,11 +61,10 @@ ToolBar {
verticalCenter: gwButton.verticalCenter
}
}
- MultiEffect {
+ ColorOverlay{
anchors.fill: lightning
source: lightning
- colorizationColor: getLocationColor()
- colorization: 1.0
+ color: getLocationColor()
antialiasing: true
}
@@ -123,11 +122,10 @@ ToolBar {
rightMargin: 20
}
}
- MultiEffect {
+ ColorOverlay{
anchors.fill: gwQuality
source: gwQuality
- colorizationColor: getSignalColor()
- colorization: 1.0
+ color: getSignalColor()
antialiasing: false
}
}
diff --git a/gui/components/Home.qml b/gui/components/Home.qml
index f3bea85a..7830f46d 100644
--- a/gui/components/Home.qml
+++ b/gui/components/Home.qml
@@ -1,6 +1,6 @@
import QtQuick
import QtQuick.Controls
-import QtQuick.Effects
+import Qt5Compat.GraphicalEffects
Page {
StatusBox {
diff --git a/gui/components/InitErrors.qml b/gui/components/InitErrors.qml
index aaf9897b..10b4755c 100644
--- a/gui/components/InitErrors.qml
+++ b/gui/components/InitErrors.qml
@@ -1,6 +1,6 @@
import QtQuick
import QtQuick.Controls
-import QtQuick.Effects
+import Qt5Compat.GraphicalEffects
ErrorBox {
diff --git a/gui/components/Locations.qml b/gui/components/Locations.qml
index 2a188738..6228a58c 100644
--- a/gui/components/Locations.qml
+++ b/gui/components/Locations.qml
@@ -1,7 +1,7 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuick.Effects
+import Qt5Compat.GraphicalEffects
import "../themes/themes.js" as Theme
@@ -81,11 +81,10 @@ ThemedPage {
//verticalCenterOffset: 3
}
}
- MultiEffect {
+ ColorOverlay{
anchors.fill: lightning
source: lightning
- colorizationColor: "black"
- colorization: 1.0
+ color: "black"
antialiasing: true
}
}
diff --git a/gui/components/MotdBox.qml b/gui/components/MotdBox.qml
index 2c8cdb8b..7b851c0c 100644
--- a/gui/components/MotdBox.qml
+++ b/gui/components/MotdBox.qml
@@ -1,6 +1,6 @@
import QtQuick
import QtQuick.Controls
-import QtQuick.Effects
+import Qt5Compat.GraphicalEffects
import "../themes/themes.js" as Theme
Item {
diff --git a/gui/components/Preferences.qml b/gui/components/Preferences.qml
index d8ed6587..a0b6bba6 100644
--- a/gui/components/Preferences.qml
+++ b/gui/components/Preferences.qml
@@ -2,8 +2,8 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Controls.Material
-import QtQuick.Effects
-import QtCore
+import Qt5Compat.GraphicalEffects
+import Qt.labs.settings
import "../themes/themes.js" as Theme
diff --git a/gui/components/SignalIcon.qml b/gui/components/SignalIcon.qml
index 8747f054..38a23710 100644
--- a/gui/components/SignalIcon.qml
+++ b/gui/components/SignalIcon.qml
@@ -1,7 +1,7 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuick.Effects
+import Qt5Compat.GraphicalEffects
import "../themes/themes.js" as Theme
@@ -41,11 +41,10 @@ Item {
]
}
}
- MultiEffect {
+ ColorOverlay{
anchors.fill: icon
source: icon
- colorizationColor: getQualityColor()
- colorization: 1.0
+ color: getQualityColor()
antialiasing: true
}
diff --git a/gui/components/Splash.qml b/gui/components/Splash.qml
index c9351804..d18cc3ba 100644
--- a/gui/components/Splash.qml
+++ b/gui/components/Splash.qml
@@ -1,6 +1,6 @@
import QtQuick
import QtQuick.Controls
-import QtQuick.Effects
+import Qt5Compat.GraphicalEffects
import "../themes/themes.js" as Theme
Page {
diff --git a/gui/components/StatusBox.qml b/gui/components/StatusBox.qml
index d17c2fe0..24a1f8f2 100644
--- a/gui/components/StatusBox.qml
+++ b/gui/components/StatusBox.qml
@@ -1,6 +1,6 @@
import QtQuick
import QtQuick.Controls
-import QtQuick.Effects
+import Qt5Compat.GraphicalEffects
import QtQuick.Layouts
import QtQuick.Templates as T
import QtQuick.Controls.impl
--
2.46.0
0001-build-use-qt5compat-qml-module-to-build-on-qt6.4-for.patch
......@@ -9,6 +9,11 @@ export GOCACHE=/tmp/gocache
export DH_GOPKG = 0xacab.org/leap/bitmask-vpn
export DH_GOLANG_EXCLUDES := vendor packages tools cmd/bitmask-helper cmd/bitmask-connect
export PATH := $(shell qmake6 -query "QT_INSTALL_BINS"):$(PATH)
export PROVIDER=${name}
export VENDOR_PATH=providers
#dh_golang doesn't do this for you
ifeq ($(DEB_HOST_ARCH), i386)
......@@ -32,12 +37,13 @@ APPNAME = ${binaryName}
override_dh_auto_test:
override_dh_auto_build:
make gen_providers_json
make build
override_dh_install:
mkdir -p $(CURDIR)/debian/${APPNAME}/usr/bin
mkdir -p $(CURDIR)/debian/${APPNAME}/usr/sbin
cp $(CURDIR)/helpers/bitmask-root $(CURDIR)/debian/${APPNAME}/usr/sbin/
cp $(CURDIR)/pkg/pickle/helpers/bitmask-root $(CURDIR)/debian/${APPNAME}/usr/sbin/
mkdir -p $(CURDIR)/debian/${APPNAME}/usr/share/polkit-1/actions
cp $(CURDIR)/helpers/se.leap.bitmask.policy $(CURDIR)/debian/${APPNAME}/usr/share/polkit-1/actions
cp build/qt/release/${APPNAME} $(CURDIR)/debian/${APPNAME}/usr/bin/${APPNAME}
......
debian/icons/scalable/${binaryName}.png
......@@ -15,7 +15,7 @@ BUILD_RELEASE?=no
WIN_CERT_PATH?=z:\leap\LEAP.pfx
WIN_CERT_PASS?=
OSX_CERT = "Developer ID Installer: LEAP Encryption Access Project"
DEB_VERSION = $(shell echo ${VERSION} | cut -d '-' -f 1,2)
DEB_VERSION = $(shell echo ${VERSION} | rev | cut -d '-' -f2- | rev)
ifeq ($(OS),Windows_NT) # is Windows_NT on XP, 2000, 7, Vista, 10...
SYSTEM = Windows
......@@ -91,7 +91,7 @@ pkg_snap:
-@rm ../../snap
@mv ../../$(BINNAME)* ../../deploy
pkg_deb:
prepare_deb:
echo "[+] building debian package version" ${DEB_VERSION}
-@mkdir -p ../../deploy
@if [ $(BUILD_RELEASE) = no ]; then\
......@@ -106,6 +106,8 @@ pkg_deb:
@rm -rf build/${BINNAME}_${DEB_VERSION} build/bitmask-vpn_${VERSION}-src
@cd build && tar xzf $(BINNAME)_${DEB_VERSION}.orig.tar.gz && mv bitmask-vpn_${VERSION}-src ${BINNAME}_${DEB_VERSION}
@cp -r debian/ build/$(BINNAME)_$(DEB_VERSION)/
pkg_deb: prepare_deb
@cd build/$(BINNAME)_$(DEB_VERSION) && debuild -us -uc
@mv build/*.deb ../../deploy
......
......@@ -8,6 +8,7 @@
<AllowNonAsciiCharacters>false</AllowNonAsciiCharacters>
<Logo>installer-logo.png</Logo>
<InstallerApplicationIcon>installer-icon</InstallerApplicationIcon>
<ControlScript>script.qs</ControlScript>
<!--
<RemoteRepositories>
......
function Controller()
{
console.log("Controller script called")
}
Controller.prototype.ComponentSelectionPageCallback = function()
{
gui.clickButton(buttons.NextButton);
}
Controller.prototype.ReadyForInstallationPageCallback = function() {
console.log("Control script being called")
try {
var page = gui.pageWidgetByObjectName("DynamicInstallForAllUsersCheckBoxForm");
if(page) {
console.log("Control script being called")
var choice = page.installForAllCheckBox.checked ? "true" : "false";
installer.setValue("installForAllUsers", choice);
}
} catch(e) {
console.log(e);
}
}
\ No newline at end of file
!defined(INSTALLER, var):INSTALLER= "BitmaskVPN-Installer-git"
!defined(INSTALLER, var):INSTALLER= "Bitmask-Installer-git"
!defined(TARGET, var):TARGET= "bitmask-vpn"
TEMPLATE = aux
CONFIG -= debug_and_release
......
package main
import (
"bytes"
"errors"
"flag"
"fmt"
"io"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
"text/template"
)
/* Outline
* runs as root and setup the bitmask-helper privileged helper on macOS
* needs to perform the following steps:
* 1. check if running as root
* 2. setup the plist file with the correct path to bitmask-helper
* 3. install plist file in location
* 4. while doing the above make sure that existing helper is not running and removed
*/
const (
plistTemplate = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>WorkingDirectory</key>
<string>{{ .Path }}</string>
<key>StandardOutPath</key>
<string>{{ .Path }}/helper/bitmask-helper.log</string>
<key>StandardErrorPath</key>
<string>{{ .Path }}/helper/bitmask-helper-err.log</string>
<key>GroupName</key>
<string>daemon</string>
<key>RunAtLoad</key>
<true/>
<key>SessionCreate</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>ThrottleInterval</key>
<integer>5</integer>
<key>Label</key>
<string>{{ .Label }}</string>
<key>ProgramArguments</key>
<array>
<string>{{ .Path }}/bitmask-helper</string>
<string>-socket-uid</string>
<string>{{.Uid}}</string>
<string>-socket-gid</string>
<string>{{.Gid}}</string>
</array>
</dict>
</plist>`
helperName = "bitmask-helper"
// -action flag values
actionPostInstall = "post-install"
actionUninstall = "uninstall"
// -stage flag values
stagePre = "preinstall"
stageUninstall = "uninstall"
// listening socket flag values
socketUid = "socket-uid"
socketGid = "socket-gid"
)
var (
curdir = func() string {
execPath, err := os.Executable()
if err != nil {
log.Printf("error getting executable path: %v", err)
return ""
}
return filepath.Dir(execPath)
}()
// flags
installerAction string
installerStage string
appName string
plistPath string
launchdDaemonLabel string
uid int
gid int
)
func init() {
const (
action = "action"
stage = "stage"
appname = "appname"
)
var usageAction = fmt.Sprintf("the installer actions: %s", strings.Join([]string{actionPostInstall, actionUninstall}, ","))
var usageStage = "the installer action stage: preinstall, uninstall"
var usageAppName = "name of the application being installed this is used to form the app bundle name by appending .app to it"
flag.StringVar(&installerAction, action, "", usageAction)
flag.StringVar(&installerStage, stage, stageUninstall, usageStage)
flag.StringVar(&appName, appname, "", usageAppName)
flag.IntVar(&uid, socketUid, 0, "Helper unix socket UID")
flag.IntVar(&gid, socketGid, 0, "Helper unix socket GID")
flag.Parse()
}
func main() {
if os.Getuid() != 0 {
log.Fatal("not running as root")
}
if appName == "" || installerAction == "" {
log.Fatal("-action and -appname flags cannot be empty")
}
plistPath = fmt.Sprintf("/Library/LaunchDaemons/se.leap.helper.%s.plist", appName)
launchdDaemonLabel = fmt.Sprintf("se.leap.Helper.%s", appName)
switch installerAction {
case actionPostInstall:
if err := setupLogFile(filepath.Join(curdir, "post-install.log")); err != nil {
log.Fatal(err)
}
log.Println("running action: post-install")
if appBundlePath() == "" {
log.Fatal("could not find path to .app bundle")
}
err := postInstall()
if err != nil {
log.Fatal(err)
}
case actionUninstall:
log.Println("running action: uninstall")
uninstall(installerStage)
default:
log.Fatalf("unknown command supplied: %s", installerAction)
}
}
func appBundlePath() string {
path := filepath.Join(curdir, appName+".app")
_, err := os.Stat(path)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
log.Printf("unable to find the app bundle path: %v", err)
return ""
}
}
return path
}
func setupLogFile(logFile string) error {
f, err := os.Create(logFile)
if err != nil {
return err
}
w := io.MultiWriter(os.Stdout, f)
log.SetOutput(w)
return nil
}
func postInstall() error {
if isHelperRunning() {
if err := unloadHelperPlist(); err != nil {
log.Println(err)
}
}
log.Println("Changing ownership of 'bitmask-helper'")
// change ownership of bitmask-helper to root
if err := os.Chown(filepath.Join(appBundlePath(), helperName), 0, 0); err != nil {
log.Println("error while changing ownership of 'bitmask-helper': ", err)
}
// copy launchd plist file to target location /Library/LaunchDaemons
log.Println("Generate plist file for helper launchd daemon")
plist, err := generatePlist()
if err != nil {
return err
}
log.Println(plist)
log.Println("Writing plist content to file")
fout, err := os.OpenFile(plistPath, os.O_CREATE|os.O_RDWR, 0644)
if err != nil {
return err
}
if n, err := io.WriteString(fout, plist); n < len(plist) || err != nil {
return fmt.Errorf("failed writing the plist file: %s: %v", fout.Name(), err)
}
// load the plist file onto launchd
log.Println("Loading plist file")
if err := loadHelperPlist(plistPath); err != nil {
log.Printf("error while loading launchd daemon: %s: %v\n", plistPath, err)
}
// change ownership of 'helper' dir
log.Println("Changing ownership of 'helper' dir")
if err := os.Chown(filepath.Join(appBundlePath(), "helper"), 0, 0); err != nil {
log.Println("error while changing ownership of dir 'helper': ", err)
}
return nil
}
func uninstall(stage string) {
switch stage {
case stagePre, stageUninstall:
if err := setupLogFile(filepath.Join("/tmp", fmt.Sprintf("bitmask-%s.log", stage))); err != nil {
log.Fatal(err)
}
if appBundlePath() == "" {
log.Fatal("could not find path to .app bundle")
}
default:
log.Fatal("unknow stage for uninstall: ", stage)
}
if isHelperRunning() {
if err := unloadHelperPlist(); err != nil {
log.Println("error while unloading launchd daemon: ", err)
}
}
if err := os.Remove(plistPath); err != nil {
log.Println("error while removing helper plist: ", err)
}
}
func isHelperRunning() bool {
cmd := exec.Command("ps", "-ceAo", "command")
out, err := cmd.Output()
if err != nil {
log.Println(err)
return false
}
processes := strings.Split(string(out), "\n")
for _, proc := range processes {
if strings.TrimSpace(proc) == "bitmask-helper" {
return true
}
}
return false
}
func loadHelperPlist(plistPath string) error {
cmd := exec.Command("launchctl", "load", plistPath)
_, err := cmd.Output()
if err != nil {
return err
}
return nil
}
func unloadHelperPlist() error {
cmd := exec.Command("launchctl", "unload", plistPath)
_, err := cmd.Output()
if err != nil {
return err
}
cmd = exec.Command("launchctl", "remove", launchdDaemonLabel)
_, _ = cmd.Output()
cmd = exec.Command("pkill", "-9", helperName)
_, err = cmd.Output()
return err
}
func generatePlist() (string, error) {
appPath := struct {
Path string
Label string
Uid int
Gid int
}{
Path: appBundlePath(),
Label: launchdDaemonLabel,
Uid: uid,
Gid: gid,
}
t, err := template.New("plist").Parse(plistTemplate)
if err != nil {
return "", err
}
plistContent := &bytes.Buffer{}
err = t.Execute(plistContent, appPath)
if err != nil {
return "", err
}
return plistContent.String(), nil
}
#!/usr/bin/env python
# Post installation script for BitmaskVPN.
# Please note that this installation will install ONE single helper with administrative privileges.
# This means that, for the time being, you can only install ONE of the BitmaskVPN derivatives at the same time.
# This might change in the future.
import glob
import os
import shutil
import sys
import subprocess
import time
HELPER = "bitmask-helper"
HELPER_PLIST = "/Library/LaunchDaemons/se.leap.bitmask-helper.plist"
_dir = os.path.dirname(os.path.realpath(__file__))
_appdir = glob.glob('{}/*VPN.app'.format(_dir))[0]
def main():
log = open(os.path.join(_dir, 'post-install.log'), 'w')
log.write('Checking for admin privileges...\n')
_id = os.getuid()
if _id != 0:
err = "ERROR: need to run as root. UID: %s\n" % str(_id)
log.write(err)
sys.exit(1)
if isHelperRunning():
log.write("Trying to stop bitmask-helper...\n")
# if this fail, we can check if the HELPER_PLIST is there
ok = unloadHelper()
log.write("success: %s \n" % str(ok))
ok = fixHelperOwner(log)
log.write("chown helper: %s \n" % str(ok))
log.write("Copy launch daemon...\n")
copyLaunchDaemon()
log.write("Trying to launch helper...\n")
out = launchHelper()
log.write("result: %s \n" % str(out))
grantPermissionsOnLogFolder()
# all done
log.write('post-install script: done\n')
sys.exit(0)
def isHelperRunning():
ps = _getProcessList()
return HELPER in ps
def unloadHelper():
out = subprocess.call(["launchctl", "unload", HELPER_PLIST])
time.sleep(0.5)
out2 = subprocess.call(["pkill", "-9", "bitmask-helper"]) # just in case
time.sleep(0.5)
return out == 0
def fixHelperOwner(log):
path = os.path.join(_appdir, HELPER)
try:
os.chown(path, 0, 0)
except OSError as exc:
log.write(str(exc))
return False
return True
def copyLaunchDaemon():
appDir = os.path.join(_dir, _appdir)
plist = "se.leap.bitmask-helper.plist"
plistFile = os.path.join(appDir, plist)
escapedPath = appDir.replace("/", "\/")
subprocess.call(["sed", "-i.back", "s/PATH/%s/g" % escapedPath, plistFile])
shutil.copy(plistFile, HELPER_PLIST)
def launchHelper():
out = subprocess.call(["launchctl", "load", HELPER_PLIST])
return out == 0
def grantPermissionsOnLogFolder():
helperDir = os.path.join(_appdir, 'helper')
try:
os.makedirs(helperDir)
except Exception:
pass
os.chown(helperDir, 0, 0)
def _getProcessList():
_out = []
output = subprocess.Popen(["ps", "-ceA"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout, stderr = output.communicate()
for line in stdout.split('\n'):
cmd = line.split(' ')[-1]
_out.append(cmd.strip())
return _out
if __name__ == "__main__":
main()