mirror of
https://github.com/yuezk/GlobalProtect-openconnect.git
synced 2025-05-20 07:26:58 -04:00
Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c02ad5d46d | ||
|
2319c7c49c | ||
|
e0c2c14dc3 | ||
|
8f27c92e7b | ||
|
9d6ec84c14 | ||
|
dd81ed9519 | ||
|
32bd713965 | ||
|
ba92517141 | ||
|
0e4e082594 | ||
|
3e590cab7b | ||
|
3e0e4cff12 | ||
|
692df2f2c5 | ||
|
f2b9ffddde | ||
|
ca38925066 | ||
|
8591dd7e81 |
16
.editorconfig
Normal file
16
.editorconfig
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# Unix-style newlines with a newline ending every file
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = false
|
||||||
|
trim_trailing_whitespace=true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[{VERSION,VERSION_SUFFIX}]
|
||||||
|
insert_final_newline = false
|
||||||
|
|
||||||
|
[*.sh]
|
||||||
|
indent_style = tab
|
131
.github/workflows/build.yml
vendored
131
.github/workflows/build.yml
vendored
@@ -3,7 +3,6 @@ name: Build
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
|
||||||
- develop
|
- develop
|
||||||
tags:
|
tags:
|
||||||
- "v*.*.*"
|
- "v*.*.*"
|
||||||
@@ -67,64 +66,21 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: snapshot-source-code
|
name: snapshot-source-code
|
||||||
path: artifacts
|
path: artifacts
|
||||||
|
|
||||||
- name: Import GPG key
|
|
||||||
id: import_gpg
|
|
||||||
uses: crazy-max/ghaction-import-gpg@v4
|
|
||||||
with:
|
|
||||||
gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
|
|
||||||
passphrase: ${{ secrets.PPA_GPG_PASSPHRASE }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Extract source code
|
||||||
run: |
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install debmake debhelper cmake \
|
|
||||||
libqt5websockets5-dev qtbase5-dev qtwebengine5-dev
|
|
||||||
|
|
||||||
- name: Build deb package for 18.04
|
|
||||||
run: |
|
run: |
|
||||||
cd $GITHUB_WORKSPACE/artifacts
|
cd $GITHUB_WORKSPACE/artifacts
|
||||||
mkdir build-18.04
|
mkdir deb-build && cp *.tar.gz deb-build && cd deb-build
|
||||||
cp *.tar.gz build-18.04 && cd build-18.04
|
|
||||||
tar xf *.tar.gz
|
tar xf *.tar.gz
|
||||||
cd globalprotect-openconnect-*/
|
|
||||||
|
|
||||||
PPA_GPG_PASSPHRASE=${{ secrets.PPA_GPG_PASSPHRASE }} \
|
|
||||||
PPA_GPG_KEYID=${{ steps.import_gpg.outputs.keyid }} ./scripts/ppa-publish.sh 18.04
|
|
||||||
|
|
||||||
- name: Build deb package for 20.04
|
|
||||||
run: |
|
|
||||||
cd $GITHUB_WORKSPACE/artifacts
|
|
||||||
mkdir build-20.04
|
|
||||||
cp *.tar.gz build-20.04 && cd build-20.04
|
|
||||||
tar xf *.tar.gz
|
|
||||||
cd globalprotect-openconnect-*/
|
|
||||||
|
|
||||||
PPA_GPG_PASSPHRASE=${{ secrets.PPA_GPG_PASSPHRASE }} \
|
|
||||||
PPA_GPG_KEYID=${{ steps.import_gpg.outputs.keyid }} ./scripts/ppa-publish.sh 20.04
|
|
||||||
|
|
||||||
- name: Build deb package for 21.04
|
|
||||||
run: |
|
|
||||||
cd $GITHUB_WORKSPACE/artifacts
|
|
||||||
mkdir build-21.04
|
|
||||||
cp *.tar.gz build-21.04 && cd build-21.04
|
|
||||||
tar xf *.tar.gz
|
|
||||||
cd globalprotect-openconnect-*/
|
|
||||||
|
|
||||||
PPA_GPG_PASSPHRASE=${{ secrets.PPA_GPG_PASSPHRASE }} \
|
|
||||||
PPA_GPG_KEYID=${{ steps.import_gpg.outputs.keyid }} ./scripts/ppa-publish.sh 21.04
|
|
||||||
|
|
||||||
- name: Build deb package for 21.10
|
|
||||||
run: |
|
|
||||||
cd $GITHUB_WORKSPACE/artifacts
|
|
||||||
mkdir build-21.10
|
|
||||||
cp *.tar.gz build-21.10 && cd build-21.10
|
|
||||||
tar xf *.tar.gz
|
|
||||||
cd globalprotect-openconnect-*/
|
|
||||||
|
|
||||||
PPA_GPG_PASSPHRASE=${{ secrets.PPA_GPG_PASSPHRASE }} \
|
|
||||||
PPA_GPG_KEYID=${{ steps.import_gpg.outputs.keyid }} ./scripts/ppa-publish.sh 21.10
|
|
||||||
|
|
||||||
|
- name: Publish PPA
|
||||||
|
uses: yuezk/publish-ppa-package@develop
|
||||||
|
with:
|
||||||
|
repository: 'ppa:yuezk/globalprotect-openconnect-snapshot'
|
||||||
|
gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
|
||||||
|
gpg_passphrase: ${{ secrets.PPA_GPG_PASSPHRASE }}
|
||||||
|
pkgdir: '${{ github.workspace }}/artifacts/deb-build/globalprotect-openconnect*/'
|
||||||
|
|
||||||
snapshot-aur:
|
snapshot-aur:
|
||||||
if: ${{ github.event_name != 'pull_request' && github.ref == 'refs/heads/develop' }}
|
if: ${{ github.event_name != 'pull_request' && github.ref == 'refs/heads/develop' }}
|
||||||
needs: snapshot-archive-all
|
needs: snapshot-archive-all
|
||||||
@@ -234,62 +190,19 @@ jobs:
|
|||||||
name: release-source-code
|
name: release-source-code
|
||||||
path: artifacts
|
path: artifacts
|
||||||
|
|
||||||
- name: Import GPG key
|
- name: Extract source code
|
||||||
id: import_gpg
|
run: |
|
||||||
uses: crazy-max/ghaction-import-gpg@v4
|
cd $GITHUB_WORKSPACE/artifacts
|
||||||
|
mkdir deb-build && cp *.tar.gz deb-build && cd deb-build
|
||||||
|
tar xf *.tar.gz
|
||||||
|
|
||||||
|
- name: Publish PPA
|
||||||
|
uses: yuezk/publish-ppa-package@develop
|
||||||
with:
|
with:
|
||||||
|
repository: 'ppa:yuezk/globalprotect-openconnect'
|
||||||
gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
|
gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
|
||||||
passphrase: ${{ secrets.PPA_GPG_PASSPHRASE }}
|
gpg_passphrase: ${{ secrets.PPA_GPG_PASSPHRASE }}
|
||||||
|
pkgdir: '${{ github.workspace }}/artifacts/deb-build/globalprotect-openconnect*/'
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install debmake debhelper cmake \
|
|
||||||
libqt5websockets5-dev qtbase5-dev qtwebengine5-dev
|
|
||||||
|
|
||||||
- name: Build deb package for 18.04
|
|
||||||
run: |
|
|
||||||
cd $GITHUB_WORKSPACE/artifacts
|
|
||||||
mkdir build-18.04
|
|
||||||
cp *.tar.gz build-18.04 && cd build-18.04
|
|
||||||
tar xf *.tar.gz
|
|
||||||
cd globalprotect-openconnect-*/
|
|
||||||
|
|
||||||
PPA_GPG_PASSPHRASE=${{ secrets.PPA_GPG_PASSPHRASE }} \
|
|
||||||
PPA_GPG_KEYID=${{ steps.import_gpg.outputs.keyid }} ./scripts/ppa-publish.sh 18.04 --stable
|
|
||||||
|
|
||||||
- name: Build deb package for 20.04
|
|
||||||
run: |
|
|
||||||
cd $GITHUB_WORKSPACE/artifacts
|
|
||||||
mkdir build-20.04
|
|
||||||
cp *.tar.gz build-20.04 && cd build-20.04
|
|
||||||
tar xf *.tar.gz
|
|
||||||
cd globalprotect-openconnect-*/
|
|
||||||
|
|
||||||
PPA_GPG_PASSPHRASE=${{ secrets.PPA_GPG_PASSPHRASE }} \
|
|
||||||
PPA_GPG_KEYID=${{ steps.import_gpg.outputs.keyid }} ./scripts/ppa-publish.sh 20.04 --stable
|
|
||||||
|
|
||||||
- name: Build deb package for 21.04
|
|
||||||
run: |
|
|
||||||
cd $GITHUB_WORKSPACE/artifacts
|
|
||||||
mkdir build-21.04
|
|
||||||
cp *.tar.gz build-21.04 && cd build-21.04
|
|
||||||
tar xf *.tar.gz
|
|
||||||
cd globalprotect-openconnect-*/
|
|
||||||
|
|
||||||
PPA_GPG_PASSPHRASE=${{ secrets.PPA_GPG_PASSPHRASE }} \
|
|
||||||
PPA_GPG_KEYID=${{ steps.import_gpg.outputs.keyid }} ./scripts/ppa-publish.sh 21.04 --stable
|
|
||||||
|
|
||||||
- name: Build deb package for 21.10
|
|
||||||
run: |
|
|
||||||
cd $GITHUB_WORKSPACE/artifacts
|
|
||||||
mkdir build-21.10
|
|
||||||
cp *.tar.gz build-21.10 && cd build-21.10
|
|
||||||
tar xf *.tar.gz
|
|
||||||
cd globalprotect-openconnect-*/
|
|
||||||
|
|
||||||
PPA_GPG_PASSPHRASE=${{ secrets.PPA_GPG_PASSPHRASE }} \
|
|
||||||
PPA_GPG_KEYID=${{ steps.import_gpg.outputs.keyid }} ./scripts/ppa-publish.sh 21.10 --stable
|
|
||||||
|
|
||||||
release-aur:
|
release-aur:
|
||||||
if: startsWith(github.ref, 'refs/tags/v')
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
@@ -351,4 +264,4 @@ jobs:
|
|||||||
- uses: softprops/action-gh-release@v1
|
- uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
./artifacts/*.tar.gz
|
./artifacts/*.tar.gz
|
||||||
|
58
.github/workflows/pre-release.yml
vendored
58
.github/workflows/pre-release.yml
vendored
@@ -1,58 +0,0 @@
|
|||||||
name: Pre Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
pre-release:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
|
||||||
env:
|
|
||||||
DEBFULLNAME: "Kevin Yue"
|
|
||||||
DEBEMAIL: "yuezk001@gmail.com"
|
|
||||||
|
|
||||||
steps:
|
|
||||||
# Checkout repository and submodules
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Init variables
|
|
||||||
id: vars
|
|
||||||
run: |
|
|
||||||
TAG=$(git tag --sort=-v:refname --list "v[0-9]*" | head -n 1 | cut -c 2-)
|
|
||||||
echo ::set-output name=VERSION::"${TAG}+SNAPSHOT$(date -u +"%Y%m%d%H%M%S")"
|
|
||||||
echo ::set-output name=TAG::${TAG}
|
|
||||||
|
|
||||||
- name: Update debian/changelog
|
|
||||||
run: |
|
|
||||||
sudo apt install devscripts
|
|
||||||
git log --format="%s" v${{ steps.vars.outputs.TAG }}.. | xargs -L1 dch -v ${{ steps.vars.outputs.VERSION }}-1ppa1
|
|
||||||
|
|
||||||
- name: "Archive all"
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
pip install git-archive-all
|
|
||||||
git-archive-all \
|
|
||||||
--force-submodules \
|
|
||||||
--prefix=globalprotect-openconnect-${{ steps.vars.outputs.VERSION }}/ \
|
|
||||||
./globalprotect-openconnect-${{ steps.vars.outputs.VERSION }}.full.tar.gz
|
|
||||||
- name: "Debian Packaging"
|
|
||||||
run: |
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install qtbase5-dev libqt5websockets5-dev qtwebengine5-dev qttools5-dev debhelper
|
|
||||||
mkdir build-debian && cd build-debian
|
|
||||||
cp ../*.tar.gz globalprotect-openconnect_${{ steps.vars.outputs.VERSION }}.orig.tar.gz
|
|
||||||
tar xf *.tar.gz
|
|
||||||
cd globalprotect-openconnect-${{ steps.vars.outputs.VERSION }}
|
|
||||||
fakeroot dpkg-buildpackage -uc -us -sa
|
|
||||||
- uses: "marvinpinto/action-automatic-releases@latest"
|
|
||||||
with:
|
|
||||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
|
||||||
automatic_release_tag: "latest"
|
|
||||||
prerelease: true
|
|
||||||
title: "globalprotect-openconnect_${{ steps.vars.outputs.VERSION }}"
|
|
||||||
files: |
|
|
||||||
*.tar.gz
|
|
||||||
build-debian/*.deb
|
|
61
.github/workflows/publish.yml
vendored
61
.github/workflows/publish.yml
vendored
@@ -1,61 +0,0 @@
|
|||||||
name: Publish
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Install Qt
|
|
||||||
uses: jurplel/install-qt-action@v2
|
|
||||||
with:
|
|
||||||
version: 5.12.11
|
|
||||||
modules: 'qtwebengine qtwebsockets'
|
|
||||||
|
|
||||||
# Checkout repository and submodules
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
qmake CONFIG+=release
|
|
||||||
make
|
|
||||||
|
|
||||||
aur-publish:
|
|
||||||
needs:
|
|
||||||
- build
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Get latest version
|
|
||||||
id: get-version
|
|
||||||
run: |
|
|
||||||
echo ::set-output name=VERSION::$(git tag --sort=-v:refname --list "v[0-9]*" | head -n 1 | cut -c 2-)
|
|
||||||
|
|
||||||
- name: Get the sha256sum
|
|
||||||
id: get-sha256sum
|
|
||||||
run: |
|
|
||||||
echo ::set-output name=SHA::$(curl -L https://github.com/yuezk/GlobalProtect-openconnect/archive/refs/tags/v${{ steps.get-version.outputs.VERSION }}.tar.gz | sha256sum | cut -f1 -d" ")
|
|
||||||
|
|
||||||
- name: Generate PKGBUILD
|
|
||||||
run: |
|
|
||||||
sed "s/{PKG_VERSION}/${{ steps.get-version.outputs.VERSION }}/g;s/{SOURCE_SHA}/${{ steps.get-sha256sum.outputs.SHA }}/g" PKGBUILD.template > PKGBUILD
|
|
||||||
|
|
||||||
- name: Publish AUR package
|
|
||||||
uses: KSXGitHub/github-actions-deploy-aur@v2.2.4
|
|
||||||
with:
|
|
||||||
pkgname: globalprotect-openconnect
|
|
||||||
pkgbuild: ./PKGBUILD
|
|
||||||
commit_username: ${{ secrets.AUR_USERNAME }}
|
|
||||||
commit_email: ${{ secrets.AUR_EMAIL }}
|
|
||||||
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
|
||||||
commit_message: 'Release v${{ steps.get-version.outputs.VERSION }}'
|
|
||||||
force_push: true
|
|
2
3rdparty/plog
vendored
2
3rdparty/plog
vendored
Submodule 3rdparty/plog updated: f4c22b03d5...914e799d2b
@@ -33,6 +33,11 @@ add_executable(gpclient
|
|||||||
gpclient.ui
|
gpclient.ui
|
||||||
normalloginwindow.ui
|
normalloginwindow.ui
|
||||||
settingsdialog.ui
|
settingsdialog.ui
|
||||||
|
challengedialog.h
|
||||||
|
challengedialog.cpp
|
||||||
|
challengedialog.ui
|
||||||
|
vpn_dbus.cpp
|
||||||
|
vpn_json.cpp
|
||||||
resources.qrc
|
resources.qrc
|
||||||
${gpclient_GENERATED_SOURCES}
|
${gpclient_GENERATED_SOURCES}
|
||||||
)
|
)
|
||||||
@@ -52,7 +57,7 @@ add_3rdparty(
|
|||||||
add_3rdparty(
|
add_3rdparty(
|
||||||
plog
|
plog
|
||||||
GIT_REPOSITORY https://github.com/SergiusTheBest/plog.git
|
GIT_REPOSITORY https://github.com/SergiusTheBest/plog.git
|
||||||
GIT_TAG 1.1.5
|
GIT_TAG master
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DPLOG_BUILD_SAMPLES=OFF
|
-DPLOG_BUILD_SAMPLES=OFF
|
||||||
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
|
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
|
||||||
|
38
GPClient/challengedialog.cpp
Normal file
38
GPClient/challengedialog.cpp
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#include <QtWidgets/QDialogButtonBox>
|
||||||
|
#include <QtWidgets/QPushButton>
|
||||||
|
|
||||||
|
#include "challengedialog.h"
|
||||||
|
#include "ui_challengedialog.h"
|
||||||
|
|
||||||
|
ChallengeDialog::ChallengeDialog(QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::ChallengeDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
ui->buttonBox->button(QDialogButtonBox::Ok)->setDisabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChallengeDialog::~ChallengeDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChallengeDialog::setMessage(const QString &message)
|
||||||
|
{
|
||||||
|
ui->challengeMessage->setText(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString ChallengeDialog::getChallenge()
|
||||||
|
{
|
||||||
|
return ui->challengeInput->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChallengeDialog::on_challengeInput_textChanged(const QString &value)
|
||||||
|
{
|
||||||
|
QPushButton *okBtn = ui->buttonBox->button(QDialogButtonBox::Ok);
|
||||||
|
if (value.isEmpty()) {
|
||||||
|
okBtn->setDisabled(true);
|
||||||
|
} else {
|
||||||
|
okBtn->setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
28
GPClient/challengedialog.h
Normal file
28
GPClient/challengedialog.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#ifndef CHALLENGEDIALOG_H
|
||||||
|
#define CHALLENGEDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ChallengeDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChallengeDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ChallengeDialog(QWidget *parent = nullptr);
|
||||||
|
~ChallengeDialog();
|
||||||
|
|
||||||
|
void setMessage(const QString &message);
|
||||||
|
const QString getChallenge();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_challengeInput_textChanged(const QString &arg1);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::ChallengeDialog *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CHALLENGEDIALOG_H
|
111
GPClient/challengedialog.ui
Normal file
111
GPClient/challengedialog.ui
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ChallengeDialog</class>
|
||||||
|
<widget class="QDialog" name="ChallengeDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>405</width>
|
||||||
|
<height>200</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>GlobalProtect Challenge</string>
|
||||||
|
</property>
|
||||||
|
<property name="modal">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="1,1">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>14</pointsize>
|
||||||
|
<weight>50</weight>
|
||||||
|
<bold>false</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Sign In</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="challengeMessage">
|
||||||
|
<property name="text">
|
||||||
|
<string>Duo two-factor login for [redacted] Enter a passcode or select one of the following options: 1. Duo Push to XXX-XXX-[redacted] 2. SMS passcodes to XXX-XXX-[redacted] Passcode or option (1-2): </string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="challengeInput">
|
||||||
|
<property name="echoMode">
|
||||||
|
<enum>QLineEdit::Password</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="layoutDirection">
|
||||||
|
<enum>Qt::LeftToRight</enum>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
<property name="centerButtons">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>ChallengeDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>ChallengeDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
@@ -1,14 +1,17 @@
|
|||||||
#include <QtNetwork/QNetworkReply>
|
#include <QtNetwork/QNetworkReply>
|
||||||
|
#include <QtCore/QRegularExpression>
|
||||||
|
#include <QtCore/QRegularExpressionMatch>
|
||||||
#include <plog/Log.h>
|
#include <plog/Log.h>
|
||||||
|
|
||||||
#include "gatewayauthenticator.h"
|
#include "gatewayauthenticator.h"
|
||||||
#include "gphelper.h"
|
#include "gphelper.h"
|
||||||
#include "loginparams.h"
|
#include "loginparams.h"
|
||||||
#include "preloginresponse.h"
|
#include "preloginresponse.h"
|
||||||
|
#include "challengedialog.h"
|
||||||
|
|
||||||
using namespace gpclient::helper;
|
using namespace gpclient::helper;
|
||||||
|
|
||||||
GatewayAuthenticator::GatewayAuthenticator(const QString& gateway, const GatewayAuthenticatorParams params)
|
GatewayAuthenticator::GatewayAuthenticator(const QString& gateway, GatewayAuthenticatorParams params)
|
||||||
: QObject()
|
: QObject()
|
||||||
, gateway(gateway)
|
, gateway(gateway)
|
||||||
, params(params)
|
, params(params)
|
||||||
@@ -33,6 +36,7 @@ void GatewayAuthenticator::authenticate()
|
|||||||
loginParams.setUser(params.username());
|
loginParams.setUser(params.username());
|
||||||
loginParams.setPassword(params.password());
|
loginParams.setPassword(params.password());
|
||||||
loginParams.setUserAuthCookie(params.userAuthCookie());
|
loginParams.setUserAuthCookie(params.userAuthCookie());
|
||||||
|
loginParams.setInputStr(params.inputStr());
|
||||||
|
|
||||||
login(loginParams);
|
login(loginParams);
|
||||||
}
|
}
|
||||||
@@ -48,10 +52,10 @@ void GatewayAuthenticator::login(const LoginParams &loginParams)
|
|||||||
void GatewayAuthenticator::onLoginFinished()
|
void GatewayAuthenticator::onLoginFinished()
|
||||||
{
|
{
|
||||||
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
|
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
|
||||||
QByteArray response;
|
QByteArray response = reply->readAll();
|
||||||
|
|
||||||
if (reply->error() || (response = reply->readAll()).contains("Authentication failure")) {
|
if (reply->error() || response.contains("Authentication failure")) {
|
||||||
PLOGE << QString("Failed to login the gateway at %1, %2").arg(loginUrl).arg(reply->errorString());
|
PLOGE << QString("Failed to login the gateway at %1, %2").arg(loginUrl, reply->errorString());
|
||||||
|
|
||||||
if (normalLoginWindow) {
|
if (normalLoginWindow) {
|
||||||
normalLoginWindow->setProcessing(false);
|
normalLoginWindow->setProcessing(false);
|
||||||
@@ -62,6 +66,13 @@ void GatewayAuthenticator::onLoginFinished()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2FA
|
||||||
|
if (response.contains("Challenge")) {
|
||||||
|
PLOGI << "The server need input the challenge...";
|
||||||
|
showChallenge(response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (normalLoginWindow) {
|
if (normalLoginWindow) {
|
||||||
normalLoginWindow->close();
|
normalLoginWindow->close();
|
||||||
}
|
}
|
||||||
@@ -83,7 +94,7 @@ void GatewayAuthenticator::onPreloginFinished()
|
|||||||
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
|
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
|
||||||
|
|
||||||
if (reply->error()) {
|
if (reply->error()) {
|
||||||
PLOGE << QString("Failed to prelogin the gateway at %1, %2").arg(preloginUrl).arg(reply->errorString());
|
PLOGE << QString("Failed to prelogin the gateway at %1, %2").arg(preloginUrl, reply->errorString());
|
||||||
|
|
||||||
emit fail("Error occurred on the gateway prelogin interface.");
|
emit fail("Error occurred on the gateway prelogin interface.");
|
||||||
return;
|
return;
|
||||||
@@ -98,7 +109,7 @@ void GatewayAuthenticator::onPreloginFinished()
|
|||||||
} else if (response.hasNormalAuthFields()) {
|
} else if (response.hasNormalAuthFields()) {
|
||||||
normalAuth(response.labelUsername(), response.labelPassword(), response.authMessage());
|
normalAuth(response.labelUsername(), response.labelPassword(), response.authMessage());
|
||||||
} else {
|
} else {
|
||||||
PLOGE << QString("Unknown prelogin response for %1, got %2").arg(preloginUrl).arg(QString::fromUtf8(response.rawResponse()));
|
PLOGE << QString("Unknown prelogin response for %1, got %2").arg(preloginUrl, QString::fromUtf8(response.rawResponse()));
|
||||||
emit fail("Unknown response for gateway prelogin interface.");
|
emit fail("Unknown response for gateway prelogin interface.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +118,7 @@ void GatewayAuthenticator::onPreloginFinished()
|
|||||||
|
|
||||||
void GatewayAuthenticator::normalAuth(QString labelUsername, QString labelPassword, QString authMessage)
|
void GatewayAuthenticator::normalAuth(QString labelUsername, QString labelPassword, QString authMessage)
|
||||||
{
|
{
|
||||||
PLOGI << QString("Trying to perform the normal login with %1 / %2 credentials").arg(labelUsername).arg(labelPassword);
|
PLOGI << QString("Trying to perform the normal login with %1 / %2 credentials").arg(labelUsername, labelPassword);
|
||||||
|
|
||||||
normalLoginWindow = new NormalLoginWindow;
|
normalLoginWindow = new NormalLoginWindow;
|
||||||
normalLoginWindow->setPortalAddress(gateway);
|
normalLoginWindow->setPortalAddress(gateway);
|
||||||
@@ -128,11 +139,10 @@ void GatewayAuthenticator::onPerformNormalLogin(const QString &username, const Q
|
|||||||
PLOGI << "Start to perform normal login...";
|
PLOGI << "Start to perform normal login...";
|
||||||
|
|
||||||
normalLoginWindow->setProcessing(true);
|
normalLoginWindow->setProcessing(true);
|
||||||
LoginParams loginParams { params.clientos() };
|
params.setUsername(username);
|
||||||
loginParams.setUser(username);
|
params.setPassword(password);
|
||||||
loginParams.setPassword(password);
|
|
||||||
|
|
||||||
login(loginParams);
|
authenticate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GatewayAuthenticator::onLoginWindowRejected()
|
void GatewayAuthenticator::onLoginWindowRejected()
|
||||||
@@ -179,3 +189,38 @@ void GatewayAuthenticator::onSAMLLoginFail(const QString msg)
|
|||||||
{
|
{
|
||||||
emit fail(msg);
|
emit fail(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GatewayAuthenticator::showChallenge(const QString &responseText)
|
||||||
|
{
|
||||||
|
QRegularExpression re("\"(.*?)\";");
|
||||||
|
QRegularExpressionMatchIterator i = re.globalMatch(responseText);
|
||||||
|
|
||||||
|
i.next(); // Skip the status value
|
||||||
|
QString message = i.next().captured(1);
|
||||||
|
QString inputStr = i.next().captured(1);
|
||||||
|
// update the inputSrc field
|
||||||
|
params.setInputStr(inputStr);
|
||||||
|
|
||||||
|
challengeDialog = new ChallengeDialog;
|
||||||
|
challengeDialog->setMessage(message);
|
||||||
|
|
||||||
|
connect(challengeDialog, &ChallengeDialog::accepted, this, [this] {
|
||||||
|
params.setPassword(challengeDialog->getChallenge());
|
||||||
|
PLOGI << "Challenge submitted, try to re-authenticate...";
|
||||||
|
authenticate();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(challengeDialog, &ChallengeDialog::rejected, this, [this] {
|
||||||
|
if (normalLoginWindow) {
|
||||||
|
normalLoginWindow->close();
|
||||||
|
}
|
||||||
|
emit fail();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(challengeDialog, &ChallengeDialog::finished, this, [this] {
|
||||||
|
delete challengeDialog;
|
||||||
|
challengeDialog = nullptr;
|
||||||
|
});
|
||||||
|
|
||||||
|
challengeDialog->show();
|
||||||
|
}
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
|
|
||||||
#include "normalloginwindow.h"
|
#include "normalloginwindow.h"
|
||||||
|
#include "challengedialog.h"
|
||||||
#include "loginparams.h"
|
#include "loginparams.h"
|
||||||
#include "gatewayauthenticatorparams.h"
|
#include "gatewayauthenticatorparams.h"
|
||||||
|
|
||||||
@@ -11,7 +12,7 @@ class GatewayAuthenticator : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit GatewayAuthenticator(const QString& gateway, const GatewayAuthenticatorParams params);
|
explicit GatewayAuthenticator(const QString& gateway, GatewayAuthenticatorParams params);
|
||||||
~GatewayAuthenticator();
|
~GatewayAuthenticator();
|
||||||
|
|
||||||
void authenticate();
|
void authenticate();
|
||||||
@@ -31,16 +32,18 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QString gateway;
|
QString gateway;
|
||||||
const GatewayAuthenticatorParams params;
|
GatewayAuthenticatorParams params;
|
||||||
QString preloginUrl;
|
QString preloginUrl;
|
||||||
QString loginUrl;
|
QString loginUrl;
|
||||||
|
|
||||||
NormalLoginWindow *normalLoginWindow{ nullptr };
|
NormalLoginWindow *normalLoginWindow{ nullptr };
|
||||||
|
ChallengeDialog *challengeDialog{ nullptr };
|
||||||
|
|
||||||
void login(const LoginParams& loginParams);
|
void login(const LoginParams& loginParams);
|
||||||
void doAuth();
|
void doAuth();
|
||||||
void normalAuth(QString labelUsername, QString labelPassword, QString authMessage);
|
void normalAuth(QString labelUsername, QString labelPassword, QString authMessage);
|
||||||
void samlAuth(QString samlMethod, QString samlRequest, QString preloginUrl = "");
|
void samlAuth(QString samlMethod, QString samlRequest, QString preloginUrl = "");
|
||||||
|
void showChallenge(const QString &responseText);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GATEWAYAUTHENTICATOR_H
|
#endif // GATEWAYAUTHENTICATOR_H
|
||||||
|
@@ -55,3 +55,13 @@ void GatewayAuthenticatorParams::setClientos(const QString &newClientos)
|
|||||||
m_clientos = newClientos;
|
m_clientos = newClientos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString &GatewayAuthenticatorParams::inputStr() const
|
||||||
|
{
|
||||||
|
return m_inputStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GatewayAuthenticatorParams::setInputStr(const QString &inputStr)
|
||||||
|
{
|
||||||
|
m_inputStr = inputStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -24,11 +24,15 @@ public:
|
|||||||
const QString &clientos() const;
|
const QString &clientos() const;
|
||||||
void setClientos(const QString &newClientos);
|
void setClientos(const QString &newClientos);
|
||||||
|
|
||||||
|
const QString &inputStr() const;
|
||||||
|
void setInputStr(const QString &inputStr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_username;
|
QString m_username;
|
||||||
QString m_password;
|
QString m_password;
|
||||||
QString m_userAuthCookie;
|
QString m_userAuthCookie;
|
||||||
QString m_clientos;
|
QString m_clientos;
|
||||||
|
QString m_inputStr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GATEWAYAUTHENTICATORPARAMS_H
|
#endif // GATEWAYAUTHENTICATORPARAMS_H
|
||||||
|
@@ -11,9 +11,10 @@
|
|||||||
|
|
||||||
using namespace gpclient::helper;
|
using namespace gpclient::helper;
|
||||||
|
|
||||||
GPClient::GPClient(QWidget *parent)
|
GPClient::GPClient(QWidget *parent, IVpn *vpn)
|
||||||
: QMainWindow(parent)
|
: QMainWindow(parent)
|
||||||
, ui(new Ui::GPClient)
|
, ui(new Ui::GPClient)
|
||||||
|
, vpn(vpn)
|
||||||
, settingsDialog(new SettingsDialog(this))
|
, settingsDialog(new SettingsDialog(this))
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
@@ -25,14 +26,14 @@ GPClient::GPClient(QWidget *parent)
|
|||||||
setupSettings();
|
setupSettings();
|
||||||
|
|
||||||
// Restore portal from the previous settings
|
// Restore portal from the previous settings
|
||||||
ui->portalInput->setText(settings::get("portal", "").toString());
|
this->portal(settings::get("portal", "").toString());
|
||||||
|
|
||||||
// DBus service setup
|
// DBus service setup
|
||||||
vpn = new com::yuezk::qt::GPService("com.yuezk.qt.GPService", "/", QDBusConnection::systemBus(), this);
|
QObject *ov = dynamic_cast<QObject*>(vpn);
|
||||||
connect(vpn, &com::yuezk::qt::GPService::connected, this, &GPClient::onVPNConnected);
|
connect(ov, SIGNAL(connected()), this, SLOT(onVPNConnected()));
|
||||||
connect(vpn, &com::yuezk::qt::GPService::disconnected, this, &GPClient::onVPNDisconnected);
|
connect(ov, SIGNAL(disconnected()), this, SLOT(onVPNDisconnected()));
|
||||||
connect(vpn, &com::yuezk::qt::GPService::error, this, &GPClient::onVPNError);
|
connect(ov, SIGNAL(error(const &QString)), this, SLOT(onVPNError(const QString&)));
|
||||||
connect(vpn, &com::yuezk::qt::GPService::logAvailable, this, &GPClient::onVPNLogAvailable);
|
connect(ov, SIGNAL(logAvailable(const &QString)), this, SLOT(onVPNLogAvailable(const QString&)));
|
||||||
|
|
||||||
// Initiallize the context menu of system tray.
|
// Initiallize the context menu of system tray.
|
||||||
initSystemTrayIcon();
|
initSystemTrayIcon();
|
||||||
@@ -373,7 +374,11 @@ void GPClient::onGatewaySuccess(const QString &authCookie)
|
|||||||
PLOGI << "Gateway login succeeded, got the cookie " << authCookie;
|
PLOGI << "Gateway login succeeded, got the cookie " << authCookie;
|
||||||
|
|
||||||
isQuickConnect = false;
|
isQuickConnect = false;
|
||||||
vpn->connect(currentGateway().address(), portalConfig.username(), authCookie, settings::get("extraArgs", "").toString());
|
QList<QString> gatewayAddresses;
|
||||||
|
for (GPGateway &gw : allGateways()) {
|
||||||
|
gatewayAddresses.push_back(gw.address());
|
||||||
|
}
|
||||||
|
vpn->connect(currentGateway().address(), gatewayAddresses, portalConfig.username(), authCookie, settings::get("extraArgs", "").toString());
|
||||||
ui->statusLabel->setText("Connecting...");
|
ui->statusLabel->setText("Connecting...");
|
||||||
updateConnectionStatus(VpnStatus::pending);
|
updateConnectionStatus(VpnStatus::pending);
|
||||||
}
|
}
|
||||||
@@ -410,6 +415,11 @@ QString GPClient::portal() const
|
|||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPClient::portal(QString p)
|
||||||
|
{
|
||||||
|
ui->portalInput->setText(p);
|
||||||
|
}
|
||||||
|
|
||||||
bool GPClient::connected() const
|
bool GPClient::connected() const
|
||||||
{
|
{
|
||||||
const QString statusText = ui->statusLabel->text();
|
const QString statusText = ui->statusLabel->text();
|
||||||
|
@@ -6,9 +6,9 @@
|
|||||||
#include <QtWidgets/QMenu>
|
#include <QtWidgets/QMenu>
|
||||||
#include <QtWidgets/QPushButton>
|
#include <QtWidgets/QPushButton>
|
||||||
|
|
||||||
#include "gpserviceinterface.h"
|
|
||||||
#include "portalconfigresponse.h"
|
#include "portalconfigresponse.h"
|
||||||
#include "settingsdialog.h"
|
#include "settingsdialog.h"
|
||||||
|
#include "vpn.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui { class GPClient; }
|
namespace Ui { class GPClient; }
|
||||||
@@ -19,12 +19,20 @@ class GPClient : public QMainWindow
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GPClient(QWidget *parent = nullptr);
|
GPClient(QWidget *parent, IVpn *vpn);
|
||||||
~GPClient();
|
~GPClient();
|
||||||
|
|
||||||
void activate();
|
void activate();
|
||||||
void quit();
|
void quit();
|
||||||
|
|
||||||
|
QString portal() const;
|
||||||
|
void portal(QString);
|
||||||
|
|
||||||
|
GPGateway currentGateway() const;
|
||||||
|
void setCurrentGateway(const GPGateway gateway);
|
||||||
|
|
||||||
|
void doConnect();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onSettingsButtonClicked();
|
void onSettingsButtonClicked();
|
||||||
void onSettingsAccepted();
|
void onSettingsAccepted();
|
||||||
@@ -58,7 +66,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
Ui::GPClient *ui;
|
Ui::GPClient *ui;
|
||||||
com::yuezk::qt::GPService *vpn;
|
IVpn *vpn;
|
||||||
|
|
||||||
QSystemTrayIcon *systemTrayIcon;
|
QSystemTrayIcon *systemTrayIcon;
|
||||||
QMenu *contextMenu;
|
QMenu *contextMenu;
|
||||||
@@ -83,20 +91,15 @@ private:
|
|||||||
void populateGatewayMenu();
|
void populateGatewayMenu();
|
||||||
void updateConnectionStatus(const VpnStatus &status);
|
void updateConnectionStatus(const VpnStatus &status);
|
||||||
|
|
||||||
void doConnect();
|
|
||||||
void portalLogin();
|
void portalLogin();
|
||||||
void tryGatewayLogin();
|
void tryGatewayLogin();
|
||||||
void gatewayLogin();
|
void gatewayLogin();
|
||||||
|
|
||||||
QString portal() const;
|
|
||||||
bool connected() const;
|
bool connected() const;
|
||||||
|
|
||||||
QList<GPGateway> allGateways() const;
|
QList<GPGateway> allGateways() const;
|
||||||
void setAllGateways(QList<GPGateway> gateways);
|
void setAllGateways(QList<GPGateway> gateways);
|
||||||
|
|
||||||
GPGateway currentGateway() const;
|
|
||||||
void setCurrentGateway(const GPGateway gateway);
|
|
||||||
|
|
||||||
void clearSettings();
|
void clearSettings();
|
||||||
};
|
};
|
||||||
#endif // GPCLIENT_H
|
#endif // GPCLIENT_H
|
||||||
|
@@ -6,7 +6,7 @@ LoginParams::LoginParams(const QString clientos)
|
|||||||
{
|
{
|
||||||
params.addQueryItem("prot", QUrl::toPercentEncoding("https:"));
|
params.addQueryItem("prot", QUrl::toPercentEncoding("https:"));
|
||||||
params.addQueryItem("server", "");
|
params.addQueryItem("server", "");
|
||||||
params.addQueryItem("inputSrc", "");
|
params.addQueryItem("inputStr", "");
|
||||||
params.addQueryItem("jnlpReady", "jnlpReady");
|
params.addQueryItem("jnlpReady", "jnlpReady");
|
||||||
params.addQueryItem("user", "");
|
params.addQueryItem("user", "");
|
||||||
params.addQueryItem("passwd", "");
|
params.addQueryItem("passwd", "");
|
||||||
@@ -61,6 +61,11 @@ void LoginParams::setPreloginCookie(const QString cookie)
|
|||||||
updateQueryItem("prelogin-cookie", cookie);
|
updateQueryItem("prelogin-cookie", cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoginParams::setInputStr(const QString inputStr)
|
||||||
|
{
|
||||||
|
updateQueryItem("inputStr", inputStr);
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray LoginParams::toUtf8() const
|
QByteArray LoginParams::toUtf8() const
|
||||||
{
|
{
|
||||||
return params.toString().toUtf8();
|
return params.toString().toUtf8();
|
||||||
|
@@ -15,6 +15,7 @@ public:
|
|||||||
void setUserAuthCookie(const QString cookie);
|
void setUserAuthCookie(const QString cookie);
|
||||||
void setPrelogonAuthCookie(const QString cookie);
|
void setPrelogonAuthCookie(const QString cookie);
|
||||||
void setPreloginCookie(const QString cookie);
|
void setPreloginCookie(const QString cookie);
|
||||||
|
void setInputStr(const QString inputStr);
|
||||||
|
|
||||||
QByteArray toUtf8() const;
|
QByteArray toUtf8() const;
|
||||||
|
|
||||||
|
@@ -3,24 +3,22 @@
|
|||||||
#include <QtCore/QDir>
|
#include <QtCore/QDir>
|
||||||
#include <QtCore/QStandardPaths>
|
#include <QtCore/QStandardPaths>
|
||||||
#include <plog/Log.h>
|
#include <plog/Log.h>
|
||||||
|
#include <plog/Init.h>
|
||||||
#include <plog/Appenders/ColorConsoleAppender.h>
|
#include <plog/Appenders/ColorConsoleAppender.h>
|
||||||
|
#include <plog/Formatters/TxtFormatter.h>
|
||||||
|
|
||||||
#include "singleapplication.h"
|
#include "singleapplication.h"
|
||||||
#include "gpclient.h"
|
#include "gpclient.h"
|
||||||
|
#include "vpn_dbus.h"
|
||||||
|
#include "vpn_json.h"
|
||||||
#include "enhancedwebview.h"
|
#include "enhancedwebview.h"
|
||||||
#include "sigwatch.h"
|
#include "sigwatch.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
const QDir path = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + "/GlobalProtect-openconnect";
|
plog::ColorConsoleAppender<plog::TxtFormatter> consoleAppender(plog::streamStdErr);
|
||||||
const QString logFile = path.path() + "/gpclient.log";
|
plog::init(plog::debug, &consoleAppender);
|
||||||
if (!path.exists()) {
|
|
||||||
path.mkpath(".");
|
|
||||||
}
|
|
||||||
|
|
||||||
static plog::ColorConsoleAppender<plog::TxtFormatter> consoleAppender;
|
|
||||||
plog::init(plog::debug, logFile.toUtf8()).addAppender(&consoleAppender);
|
|
||||||
|
|
||||||
PLOGI << "GlobalProtect started, version: " << VERSION;
|
PLOGI << "GlobalProtect started, version: " << VERSION;
|
||||||
|
|
||||||
@@ -33,9 +31,35 @@ int main(int argc, char *argv[])
|
|||||||
SingleApplication app(argc, argv);
|
SingleApplication app(argc, argv);
|
||||||
app.setQuitOnLastWindowClosed(false);
|
app.setQuitOnLastWindowClosed(false);
|
||||||
|
|
||||||
GPClient w;
|
QCommandLineParser parser;
|
||||||
|
parser.addHelpOption();
|
||||||
|
parser.addVersionOption();
|
||||||
|
parser.addPositionalArgument("server", "The URL of the VPN server. Optional.");
|
||||||
|
parser.addPositionalArgument("gateway", "The URL of the specific VPN gateway. Optional.");
|
||||||
|
parser.addOptions({
|
||||||
|
{"json", "Write the result of the handshake with the GlobalConnect server to stdout as JSON and terminate. Useful for scripting."},
|
||||||
|
{"now", "Do not show the dialog with the connect button; connect immediately instead."},
|
||||||
|
});
|
||||||
|
parser.process(app);
|
||||||
|
|
||||||
|
const QStringList positional = parser.positionalArguments();
|
||||||
|
|
||||||
|
IVpn *vpn = parser.isSet("json") // yes it leaks, but this is cleared on exit anyway
|
||||||
|
? static_cast<IVpn*>(new VpnJson(nullptr)) // Print to stdout and exit
|
||||||
|
: static_cast<IVpn*>(new VpnDbus(nullptr)); // Contact GPService daemon via dbus
|
||||||
|
GPClient w(nullptr, vpn);
|
||||||
w.show();
|
w.show();
|
||||||
|
|
||||||
|
if (positional.size() > 0) {
|
||||||
|
w.portal(positional.at(0));
|
||||||
|
}
|
||||||
|
if (positional.size() > 1) {
|
||||||
|
GPGateway gw;
|
||||||
|
gw.setName(positional.at(1));
|
||||||
|
gw.setAddress(positional.at(1));
|
||||||
|
w.setCurrentGateway(gw);
|
||||||
|
}
|
||||||
|
|
||||||
QObject::connect(&app, &SingleApplication::instanceStarted, &w, &GPClient::activate);
|
QObject::connect(&app, &SingleApplication::instanceStarted, &w, &GPClient::activate);
|
||||||
|
|
||||||
UnixSignalWatcher sigwatch;
|
UnixSignalWatcher sigwatch;
|
||||||
@@ -45,5 +69,12 @@ int main(int argc, char *argv[])
|
|||||||
sigwatch.watchForSignal(SIGHUP);
|
sigwatch.watchForSignal(SIGHUP);
|
||||||
QObject::connect(&sigwatch, &UnixSignalWatcher::unixSignal, &w, &GPClient::quit);
|
QObject::connect(&sigwatch, &UnixSignalWatcher::unixSignal, &w, &GPClient::quit);
|
||||||
|
|
||||||
|
if (parser.isSet("now")) {
|
||||||
|
w.doConnect();
|
||||||
|
}
|
||||||
|
if (parser.isSet("json")) {
|
||||||
|
QObject::connect(static_cast<VpnJson*>(vpn), &VpnJson::connected, &w, &GPClient::quit);
|
||||||
|
}
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
@@ -41,7 +41,7 @@ void PortalAuthenticator::onPreloginFinished()
|
|||||||
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
|
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
|
||||||
|
|
||||||
if (reply->error()) {
|
if (reply->error()) {
|
||||||
PLOGE << QString("Error occurred while accessing %1, %2").arg(preloginUrl).arg(reply->errorString());
|
PLOGE << QString("Error occurred while accessing %1, %2").arg(preloginUrl, reply->errorString());
|
||||||
emit preloginFailed("Error occurred on the portal prelogin interface.");
|
emit preloginFailed("Error occurred on the portal prelogin interface.");
|
||||||
delete reply;
|
delete reply;
|
||||||
return;
|
return;
|
||||||
@@ -195,9 +195,6 @@ void PortalAuthenticator::onFetchConfigFinished()
|
|||||||
if (normalLoginWindow) {
|
if (normalLoginWindow) {
|
||||||
PLOGI << "Closing the NormalLoginWindow...";
|
PLOGI << "Closing the NormalLoginWindow...";
|
||||||
|
|
||||||
// Save the credentials for reuse
|
|
||||||
settings::save("username", username);
|
|
||||||
settings::save("password", password);
|
|
||||||
normalLoginWindow->close();
|
normalLoginWindow->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
GPClient/vpn.h
Normal file
24
GPClient/vpn.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef VPN_H
|
||||||
|
#define VPN_H
|
||||||
|
#include <QtCore/QObject>
|
||||||
|
#include <QtCore/QString>
|
||||||
|
|
||||||
|
class IVpn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IVpn() = default;
|
||||||
|
|
||||||
|
virtual void connect(const QString &preferredServer, const QList<QString> &servers, const QString &username, const QString &passwd, const QString &extraArgs) = 0;
|
||||||
|
virtual void disconnect() = 0;
|
||||||
|
virtual int status() = 0;
|
||||||
|
|
||||||
|
// signals: // SIGNALS
|
||||||
|
// virtual void connected();
|
||||||
|
// virtual void disconnected();
|
||||||
|
// virtual void error(const QString &errorMessage);
|
||||||
|
// virtual void logAvailable(const QString &log);
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_INTERFACE(IVpn, "IVpn") // define this out of namespace scope
|
||||||
|
|
||||||
|
#endif
|
13
GPClient/vpn_dbus.cpp
Normal file
13
GPClient/vpn_dbus.cpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include "vpn_dbus.h"
|
||||||
|
|
||||||
|
void VpnDbus::connect(const QString &preferredServer, const QList<QString> &servers, const QString &username, const QString &passwd, const QString &extraArgs) {
|
||||||
|
inner->connect(preferredServer, username, passwd, extraArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VpnDbus::disconnect() {
|
||||||
|
inner->disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
int VpnDbus::status() {
|
||||||
|
return inner->status();
|
||||||
|
}
|
33
GPClient/vpn_dbus.h
Normal file
33
GPClient/vpn_dbus.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#ifndef VPN_DBUS_H
|
||||||
|
#define VPN_DBUS_H
|
||||||
|
#include "vpn.h"
|
||||||
|
#include "gpserviceinterface.h"
|
||||||
|
|
||||||
|
class VpnDbus : public QObject, public IVpn
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_INTERFACES(IVpn)
|
||||||
|
|
||||||
|
private:
|
||||||
|
com::yuezk::qt::GPService *inner;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VpnDbus(QObject *parent) : QObject(parent) {
|
||||||
|
inner = new com::yuezk::qt::GPService("com.yuezk.qt.GPService", "/", QDBusConnection::systemBus(), this);
|
||||||
|
QObject::connect(inner, &com::yuezk::qt::GPService::connected, this, &VpnDbus::connected);
|
||||||
|
QObject::connect(inner, &com::yuezk::qt::GPService::disconnected, this, &VpnDbus::disconnected);
|
||||||
|
QObject::connect(inner, &com::yuezk::qt::GPService::error, this, &VpnDbus::error);
|
||||||
|
QObject::connect(inner, &com::yuezk::qt::GPService::logAvailable, this, &VpnDbus::logAvailable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void connect(const QString &preferredServer, const QList<QString> &servers, const QString &username, const QString &passwd, const QString &extraArgs);
|
||||||
|
void disconnect();
|
||||||
|
int status();
|
||||||
|
|
||||||
|
signals: // SIGNALS
|
||||||
|
void connected();
|
||||||
|
void disconnected();
|
||||||
|
void error(const QString &errorMessage);
|
||||||
|
void logAvailable(const QString &log);
|
||||||
|
};
|
||||||
|
#endif
|
24
GPClient/vpn_json.cpp
Normal file
24
GPClient/vpn_json.cpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#include "vpn_json.h"
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
void VpnJson::connect(const QString &preferredServer, const QList<QString> &servers, const QString &username, const QString &passwd, const QString &extraArgs) {
|
||||||
|
QJsonArray sl;
|
||||||
|
for (const QString &srv : servers) {
|
||||||
|
sl.push_back(QJsonValue(srv));
|
||||||
|
}
|
||||||
|
QJsonObject j;
|
||||||
|
j["server"] = preferredServer;
|
||||||
|
j["availableServers"] = sl;
|
||||||
|
j["cookie"] = passwd;
|
||||||
|
QTextStream(stdout) << QJsonDocument(j).toJson(QJsonDocument::Compact) << "\n";
|
||||||
|
emit connected();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VpnJson::disconnect() { /* nop */ }
|
||||||
|
|
||||||
|
int VpnJson::status() {
|
||||||
|
return 4; // disconnected
|
||||||
|
}
|
23
GPClient/vpn_json.h
Normal file
23
GPClient/vpn_json.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef VPN_JSON_H
|
||||||
|
#define VPN_JSON_H
|
||||||
|
#include "vpn.h"
|
||||||
|
|
||||||
|
class VpnJson : public QObject, public IVpn
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_INTERFACES(IVpn)
|
||||||
|
|
||||||
|
public:
|
||||||
|
VpnJson(QObject *parent) : QObject(parent) {}
|
||||||
|
|
||||||
|
void connect(const QString &preferredServer, const QList<QString> &servers, const QString &username, const QString &passwd, const QString &extraArgs);
|
||||||
|
void disconnect();
|
||||||
|
int status();
|
||||||
|
|
||||||
|
signals: // SIGNALS
|
||||||
|
void connected();
|
||||||
|
void disconnected();
|
||||||
|
void error(const QString &errorMessage);
|
||||||
|
void logAvailable(const QString &log);
|
||||||
|
};
|
||||||
|
#endif
|
@@ -181,7 +181,7 @@ void GPService::onProcessStdout()
|
|||||||
QString output = openconnect->readAllStandardOutput();
|
QString output = openconnect->readAllStandardOutput();
|
||||||
|
|
||||||
log(output);
|
log(output);
|
||||||
if (output.indexOf("Connected as") >= 0) {
|
if (output.indexOf("Connected as") >= 0 || output.indexOf("Configured as") >= 0) {
|
||||||
vpnStatus = GPService::VpnConnected;
|
vpnStatus = GPService::VpnConnected;
|
||||||
emit connected();
|
emit connected();
|
||||||
}
|
}
|
||||||
|
164
README.md
164
README.md
@@ -5,8 +5,10 @@ A GlobalProtect VPN client (GUI) for Linux based on Openconnect and built with Q
|
|||||||
<img src="https://user-images.githubusercontent.com/3297602/133869036-5c02b0d9-c2d9-4f87-8c81-e44f68cfd6ac.png">
|
<img src="https://user-images.githubusercontent.com/3297602/133869036-5c02b0d9-c2d9-4f87-8c81-e44f68cfd6ac.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a href="https://ko-fi.com/M4M75PYKZ" target="_blank"><img src="https://ko-fi.com/img/githubbutton_sm.svg" alt="ko-fi" style="height: 35px !important;width: auto !important;"></a>
|
<a href="https://paypal.me/zongkun" target="_blank"><img src="https://cdn.jsdelivr.net/gh/everdrone/coolbadge@5ea5937cabca5ecbfc45d6b30592bd81f219bc8d/badges/Paypal/Coffee/Blue/Small.png" alt="Buy me a coffee via Paypal" style="height: 32px; width: 268px;" ></a>
|
||||||
<a href="https://www.buymeacoffee.com/yuezk" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 35px !important;width: auto !important;" ></a>
|
<a href="https://ko-fi.com/M4M75PYKZ" target="_blank"><img src="https://ko-fi.com/img/githubbutton_sm.svg" alt="Support me on Ko-fi" style="height: 32px; width: 238px;"></a>
|
||||||
|
<a href="https://www.buymeacoffee.com/yuezk" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 32px; width: 114px;" ></a>
|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@@ -15,38 +17,78 @@ A GlobalProtect VPN client (GUI) for Linux based on Openconnect and built with Q
|
|||||||
- Supports automatically selecting the preferred gateway from the multiple gateways.
|
- Supports automatically selecting the preferred gateway from the multiple gateways.
|
||||||
- Supports switching gateway from the system tray menu manually.
|
- Supports switching gateway from the system tray menu manually.
|
||||||
|
|
||||||
## Future plan
|
|
||||||
|
|
||||||
- [ ] Improve the release process
|
## Install
|
||||||
- [ ] Process bugs and feature requests
|
|
||||||
- [ ] Support for bypassing the `gpclient` parameters
|
|
||||||
- [ ] Support the CLI mode
|
|
||||||
|
|
||||||
## Passing the Custom Parameters to `OpenConnect` CLI
|
|OS|Stable version | Development version|
|
||||||
|
|---|--------------|--------------------|
|
||||||
|
|Linux Mint, Ubuntu 18.04 or later|[ppa:yuezk/globalprotect-openconnect](https://launchpad.net/~yuezk/+archive/ubuntu/globalprotect-openconnect)|[ppa:yuezk/globalprotect-openconnect-snapshot](https://launchpad.net/~yuezk/+archive/ubuntu/globalprotect-openconnect-snapshot)|
|
||||||
|
|Arch, Manjaro|[globalprotect-openconnect](https://archlinux.org/packages/community/x86_64/globalprotect-openconnect/)|[AUR: globalprotect-openconnect-git](https://aur.archlinux.org/packages/globalprotect-openconnect-git/)|
|
||||||
|
|Fedora|[copr: yuezk/globalprotect-openconnect](https://copr.fedorainfracloud.org/coprs/yuezk/globalprotect-openconnect/)|[copr: yuezk/globalprotect-openconnect](https://copr.fedorainfracloud.org/coprs/yuezk/globalprotect-openconnect/)|
|
||||||
|
|openSUSE, CentOS 8|[OBS: globalprotect-openconnect](https://build.opensuse.org/package/show/home:yuezk/globalprotect-openconnect)|[OBS: globalprotect-openconnect-snapshot](https://build.opensuse.org/package/show/home:yuezk/globalprotect-openconnect-snapshot)|
|
||||||
|
|
||||||
Custom parameters can be appended to the `OpenConnect` CLI with the following settings.
|
Add the repository in the above table and install it with your favorite package manager tool.
|
||||||
|
|
||||||
> Tokens with spaces can be surrounded by double quotes; three consecutive double quotes represent the quote character itself.
|
[](https://repology.org/project/globalprotect-openconnect/versions)
|
||||||
|
[](https://repology.org/project/globalprotect-openconnect/versions)
|
||||||
|
[](https://repology.org/project/globalprotect-openconnect/versions)
|
||||||
|
[](https://repology.org/project/globalprotect-openconnect/versions)
|
||||||
|
[](https://repology.org/project/globalprotect-openconnect/versions)
|
||||||
|
[](https://repology.org/project/globalprotect-openconnect/versions)
|
||||||
|
[](https://repology.org/project/globalprotect-openconnect/versions)
|
||||||
|
|
||||||
|
### Linux Mint, Ubuntu 18.04 or later
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo add-apt-repository ppa:yuezk/globalprotect-openconnect
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt install globalprotect-openconnect
|
||||||
|
```
|
||||||
|
|
||||||
|
> For Linux Mint, you might need to import the GPG key with: `sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 7937C393082992E5D6E4A60453FC26B43838D761` if you encountered an error `gpg: keyserver receive failed: General error`.
|
||||||
|
|
||||||
|
### Arch Linux / Manjaro
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo pacman -S globalprotect-openconnect
|
||||||
|
```
|
||||||
|
|
||||||
|
### AUR snapshot version
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yay -S globalprotect-openconnect-git
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fedora
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo dnf copr enable yuezk/globalprotect-openconnect
|
||||||
|
sudo dnf install globalprotect-openconnect
|
||||||
|
```
|
||||||
|
|
||||||
|
### openSUSE
|
||||||
|
|
||||||
|
- openSUSE Tumbleweed
|
||||||
|
```sh
|
||||||
|
sudo zypper ar https://download.opensuse.org/repositories/home:/yuezk/openSUSE_Tumbleweed/home:yuezk.repo
|
||||||
|
sudo zypper ref
|
||||||
|
sudo zypper install globalprotect-openconnect
|
||||||
|
```
|
||||||
|
|
||||||
|
- openSUSE Leap
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo zypper ar https://download.opensuse.org/repositories/home:/yuezk/openSUSE_Leap_15.2/home:yuezk.repo
|
||||||
|
sudo zypper ref
|
||||||
|
sudo zypper install globalprotect-openconnect
|
||||||
|
```
|
||||||
|
### CentOS 8
|
||||||
|
|
||||||
|
1. Add the repository: `https://download.opensuse.org/repositories/home:/yuezk/CentOS_8/home:yuezk.repo`
|
||||||
|
1. Install `globalprotect-openconnect`
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="https://user-images.githubusercontent.com/3297602/130319209-744be02b-d657-4f49-a76d-d2c81b5c46d5.png" />
|
|
||||||
<p>
|
|
||||||
|
|
||||||
## Display the system tray icon on Gnome 40
|
## Build & Install from source code
|
||||||
|
|
||||||
Install the [AppIndicator and KStatusNotifierItem Support](https://extensions.gnome.org/extension/615/appindicator-support/) extension and you will see the system try icon (Restart the system after the installation).
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="https://user-images.githubusercontent.com/3297602/130831022-b93492fd-46dd-4a8e-94a4-13b5747120b7.png" />
|
|
||||||
<p>
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
- Openconnect v8.x
|
|
||||||
- Qt5, qt5-webengine, qt5-websockets
|
|
||||||
|
|
||||||
## Build & Install
|
|
||||||
|
|
||||||
Clone this repo with:
|
Clone this repo with:
|
||||||
|
|
||||||
@@ -55,10 +97,6 @@ git clone https://github.com/yuezk/GlobalProtect-openconnect.git
|
|||||||
cd GlobalProtect-openconnect
|
cd GlobalProtect-openconnect
|
||||||
```
|
```
|
||||||
|
|
||||||
### Arch/Manjaro
|
|
||||||
|
|
||||||
Install from the [globalprotect-openconnect](https://aur.archlinux.org/packages/globalprotect-openconnect/) AUR.
|
|
||||||
|
|
||||||
### Ubuntu/Mint
|
### Ubuntu/Mint
|
||||||
|
|
||||||
> **⚠️ REQUIRED for Ubuntu 18.04 ⚠️**
|
> **⚠️ REQUIRED for Ubuntu 18.04 ⚠️**
|
||||||
@@ -107,38 +145,6 @@ Install the Qt5 dependencies and OpenConnect:
|
|||||||
./scripts/install.sh
|
./scripts/install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### Debian package
|
|
||||||
|
|
||||||
Relatively manual process for now:
|
|
||||||
|
|
||||||
* Clone the source tree
|
|
||||||
|
|
||||||
```
|
|
||||||
git clone https://github.com/yuezk/GlobalProtect-openconnect.git
|
|
||||||
cd GlobalProtect-openconnect
|
|
||||||
```
|
|
||||||
|
|
||||||
* Install git-archive-all using the pip. Remember to adjust the version numbers etc.
|
|
||||||
|
|
||||||
```
|
|
||||||
pip install git-archive-all
|
|
||||||
```
|
|
||||||
|
|
||||||
* Next create an upstream source tree using git archive.
|
|
||||||
|
|
||||||
```
|
|
||||||
git-archive-all --force-submodules --prefix=globalprotect-openconnect-1.3.0/ ../globalprotect-openconnect_1.3.0.orig.tar.gz
|
|
||||||
```
|
|
||||||
|
|
||||||
* Finally extract the source tree, build the debian package, and install it.
|
|
||||||
|
|
||||||
```
|
|
||||||
cd ..
|
|
||||||
tar -xzvf globalprotect-openconnect_1.3.0.orig.tar.gz
|
|
||||||
cd globalprotect-openconnect-1.3.0
|
|
||||||
fakeroot dpkg-buildpackage -uc -us -sa 2>&1 | tee ../build.log
|
|
||||||
sudo dpkg -i globalprotect-openconnect_1.3.0-1ppa1_amd64.deb
|
|
||||||
```
|
|
||||||
|
|
||||||
### NixOS
|
### NixOS
|
||||||
In `configuration.nix`:
|
In `configuration.nix`:
|
||||||
@@ -153,6 +159,38 @@ Relatively manual process for now:
|
|||||||
environment.systemPackages = [ globalprotect-openconnect ];
|
environment.systemPackages = [ globalprotect-openconnect ];
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Run
|
||||||
|
|
||||||
|
Once the software is installed, you can run `gpclient` to start the UI.
|
||||||
|
|
||||||
|
## Passing the Custom Parameters to `OpenConnect` CLI
|
||||||
|
|
||||||
|
Custom parameters can be appended to the `OpenConnect` CLI with the following settings.
|
||||||
|
|
||||||
|
> Tokens with spaces can be surrounded by double quotes; three consecutive double quotes represent the quote character itself.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://user-images.githubusercontent.com/3297602/130319209-744be02b-d657-4f49-a76d-d2c81b5c46d5.png" />
|
||||||
|
<p>
|
||||||
|
|
||||||
|
## Display the system tray icon on Gnome 40
|
||||||
|
|
||||||
|
Install the [AppIndicator and KStatusNotifierItem Support](https://extensions.gnome.org/extension/615/appindicator-support/) extension and you will see the system try icon (Restart the system after the installation).
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://user-images.githubusercontent.com/3297602/130831022-b93492fd-46dd-4a8e-94a4-13b5747120b7.png" />
|
||||||
|
<p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Future plan
|
||||||
|
|
||||||
|
- [x] Improve the release process
|
||||||
|
- [ ] Process bugs and feature requests
|
||||||
|
- [ ] Support for bypassing the `gpclient` parameters
|
||||||
|
- [ ] Support the CLI mode
|
||||||
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
The application logs can be found at: `~/.cache/GlobalProtect-openconnect/gpclient.log`
|
The application logs can be found at: `~/.cache/GlobalProtect-openconnect/gpclient.log`
|
||||||
|
15
debian/changelog
vendored
15
debian/changelog
vendored
@@ -1,3 +1,18 @@
|
|||||||
|
globalprotect-openconnect (1.4.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Updated VERSION, Bumped 1.3.4 –> 1.4.0
|
||||||
|
* Fix gpservice after openconnect v8.20 (#124)
|
||||||
|
* Add 2FA support (#112)
|
||||||
|
* Add a scripting mode to GPClient (#110)
|
||||||
|
* Stop saving credentials (#111)
|
||||||
|
* update CI
|
||||||
|
* add editorconfig
|
||||||
|
* Update README.md
|
||||||
|
* Add a run entry (#108)
|
||||||
|
* update the installation instruction of Arch Linux
|
||||||
|
|
||||||
|
-- Kevin Yue <k3vinyue@gmail.com> Wed, 02 Mar 2022 21:34:19 +0800
|
||||||
|
|
||||||
globalprotect-openconnect (1.3.4-1) unstable; urgency=medium
|
globalprotect-openconnect (1.3.4-1) unstable; urgency=medium
|
||||||
|
|
||||||
* Updated VERSION, Bumped 1.3.3 –> 1.3.4
|
* Updated VERSION, Bumped 1.3.3 –> 1.3.4
|
||||||
|
2
debian/source/format
vendored
2
debian/source/format
vendored
@@ -1 +1 @@
|
|||||||
3.0 (quilt)
|
3.0 (native)
|
@@ -1,3 +1,18 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Mar 2 13:34:19 UTC 2022 - k3vinyue@gmail.com - 1.4.0
|
||||||
|
|
||||||
|
- Update to 1.4.0
|
||||||
|
* Updated VERSION, Bumped 1.3.4 –> 1.4.0
|
||||||
|
* Fix gpservice after openconnect v8.20 (#124)
|
||||||
|
* Add 2FA support (#112)
|
||||||
|
* Add a scripting mode to GPClient (#110)
|
||||||
|
* Stop saving credentials (#111)
|
||||||
|
* update CI
|
||||||
|
* add editorconfig
|
||||||
|
* Update README.md
|
||||||
|
* Add a run entry (#108)
|
||||||
|
* update the installation instruction of Arch Linux
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Sun Oct 24 04:13:24 UTC 2021 - k3vinyue@gmail.com - 1.3.4
|
Sun Oct 24 04:13:24 UTC 2021 - k3vinyue@gmail.com - 1.3.4
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
Name: globalprotect-openconnect
|
Name: globalprotect-openconnect
|
||||||
Version: 1.3.4
|
Version: 1.4.0
|
||||||
Release: 1
|
Release: 1
|
||||||
Summary: A GlobalProtect VPN client powered by OpenConnect
|
Summary: A GlobalProtect VPN client powered by OpenConnect
|
||||||
Group: Productivity/Networking/PPP
|
Group: Productivity/Networking/PPP
|
||||||
|
@@ -304,7 +304,7 @@ do-versionfile() {
|
|||||||
[ -f VERSION ] && ACTION_MSG="Updated" || ACTION_MSG="Created"
|
[ -f VERSION ] && ACTION_MSG="Updated" || ACTION_MSG="Created"
|
||||||
|
|
||||||
GIT_MSG+="${ACTION_MSG} VERSION, "
|
GIT_MSG+="${ACTION_MSG} VERSION, "
|
||||||
echo $V_USR_INPUT > VERSION # Create file
|
echo $V_USR_INPUT | tr -d "\n" > VERSION # Create file
|
||||||
echo -e "\n${I_OK} ${S_NOTICE}${ACTION_MSG} [${S_NORM}VERSION${S_NOTICE}] file"
|
echo -e "\n${I_OK} ${S_NOTICE}${ACTION_MSG} [${S_NORM}VERSION${S_NOTICE}] file"
|
||||||
|
|
||||||
# Stage file for commit
|
# Stage file for commit
|
||||||
|
0
scripts/release.sh
Normal file → Executable file
0
scripts/release.sh
Normal file → Executable file
Reference in New Issue
Block a user