Compare commits

...

20 Commits

Author SHA1 Message Date
Kevin Yue
37a511c24d Release 1.4.1 2022-03-03 21:58:59 +08:00
Kevin Yue
ad7db36c92 Updated VERSION, Bumped 1.4.0 –> 1.4.1 2022-03-03 21:58:27 +08:00
Kevin Yue
11dc5920ef print the gpservice logs 2022-03-03 21:30:33 +08:00
Kevin Yue
e6383916c7 update AUR packaging 2022-03-02 22:11:47 +08:00
Kevin Yue
1d9d928b26 update AUR packaging 2022-03-02 22:06:26 +08:00
Kevin Yue
c02ad5d46d Release 1.4.0 2022-03-02 21:34:19 +08:00
Kevin Yue
2319c7c49c Updated VERSION, Bumped 1.3.4 –> 1.4.0 2022-03-02 21:28:02 +08:00
David Cohen
e0c2c14dc3 Fix gpservice after openconnect v8.20 (#124) 2022-03-01 15:41:29 +08:00
Kevin Yue
8f27c92e7b Add 2FA support (#112) 2021-12-20 22:20:02 +08:00
Karolin Varner
9d6ec84c14 Add a scripting mode to GPClient (#110) 2021-12-20 18:46:16 +08:00
Kevin Yue
dd81ed9519 Stop saving credentials (#111) 2021-12-20 18:43:37 +08:00
Kevin Yue
32bd713965 update CI 2021-12-20 18:32:18 +08:00
Kevin Yue
ba92517141 add editorconfig 2021-12-20 18:31:56 +08:00
Kevin Yue
0e4e082594 Update README.md 2021-11-30 16:42:04 +08:00
Kevin Yue
3e590cab7b Update README.md 2021-11-30 10:44:38 +08:00
Aloïs de Gouvello
3e0e4cff12 Add a run entry (#108)
Fix #107
2021-11-30 10:43:56 +08:00
Kevin Yue
692df2f2c5 update the installation instruction of Arch Linux 2021-11-01 17:12:15 +08:00
Kevin Yue
f2b9ffddde Update README.md 2021-10-30 09:41:32 +08:00
Kevin Yue
ca38925066 Update README.md 2021-10-24 17:26:02 +08:00
Kevin Yue
8591dd7e81 Update README.md 2021-10-24 16:43:01 +08:00
34 changed files with 645 additions and 343 deletions

16
.editorconfig Normal file
View 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

View File

@@ -3,7 +3,6 @@ name: Build
on:
push:
branches:
- master
- develop
tags:
- "v*.*.*"
@@ -67,64 +66,21 @@ jobs:
with:
name: snapshot-source-code
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
run: |
sudo apt update
sudo apt install debmake debhelper cmake \
libqt5websockets5-dev qtbase5-dev qtwebengine5-dev
- name: Build deb package for 18.04
- name: Extract source code
run: |
cd $GITHUB_WORKSPACE/artifacts
mkdir build-18.04
cp *.tar.gz build-18.04 && cd build-18.04
mkdir deb-build && cp *.tar.gz deb-build && cd deb-build
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:
if: ${{ github.event_name != 'pull_request' && github.ref == 'refs/heads/develop' }}
needs: snapshot-archive-all
@@ -234,62 +190,19 @@ jobs:
name: release-source-code
path: artifacts
- name: Import GPG key
id: import_gpg
uses: crazy-max/ghaction-import-gpg@v4
- name: Extract source code
run: |
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:
repository: 'ppa:yuezk/globalprotect-openconnect'
gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.PPA_GPG_PASSPHRASE }}
- 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
gpg_passphrase: ${{ secrets.PPA_GPG_PASSPHRASE }}
pkgdir: '${{ github.workspace }}/artifacts/deb-build/globalprotect-openconnect*/'
release-aur:
if: startsWith(github.ref, 'refs/tags/v')
@@ -307,7 +220,7 @@ jobs:
VERSION: $(cat ./artifacts/VERSION)
uses: yuezk/github-actions-deploy-aur@update-pkgver
with:
pkgname: globalprotect-openconnect
pkgname: globalprotect-openconnect-git
pkgbuild: ./artifacts/aur/PKGBUILD
assets: ./artifacts/aur/*.tar.gz
update_pkgver: true
@@ -351,4 +264,4 @@ jobs:
- uses: softprops/action-gh-release@v1
with:
files: |
./artifacts/*.tar.gz
./artifacts/*.tar.gz

View File

@@ -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

View File

@@ -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

View File

@@ -33,6 +33,11 @@ add_executable(gpclient
gpclient.ui
normalloginwindow.ui
settingsdialog.ui
challengedialog.h
challengedialog.cpp
challengedialog.ui
vpn_dbus.cpp
vpn_json.cpp
resources.qrc
${gpclient_GENERATED_SOURCES}
)
@@ -52,7 +57,7 @@ add_3rdparty(
add_3rdparty(
plog
GIT_REPOSITORY https://github.com/SergiusTheBest/plog.git
GIT_TAG 1.1.5
GIT_TAG master
CMAKE_ARGS
-DPLOG_BUILD_SAMPLES=OFF
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}

View 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);
}
}

View 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
View 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>

View File

@@ -1,14 +1,17 @@
#include <QtNetwork/QNetworkReply>
#include <QtCore/QRegularExpression>
#include <QtCore/QRegularExpressionMatch>
#include <plog/Log.h>
#include "gatewayauthenticator.h"
#include "gphelper.h"
#include "loginparams.h"
#include "preloginresponse.h"
#include "challengedialog.h"
using namespace gpclient::helper;
GatewayAuthenticator::GatewayAuthenticator(const QString& gateway, const GatewayAuthenticatorParams params)
GatewayAuthenticator::GatewayAuthenticator(const QString& gateway, GatewayAuthenticatorParams params)
: QObject()
, gateway(gateway)
, params(params)
@@ -33,6 +36,7 @@ void GatewayAuthenticator::authenticate()
loginParams.setUser(params.username());
loginParams.setPassword(params.password());
loginParams.setUserAuthCookie(params.userAuthCookie());
loginParams.setInputStr(params.inputStr());
login(loginParams);
}
@@ -48,10 +52,10 @@ void GatewayAuthenticator::login(const LoginParams &loginParams)
void GatewayAuthenticator::onLoginFinished()
{
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
QByteArray response;
QByteArray response = reply->readAll();
if (reply->error() || (response = reply->readAll()).contains("Authentication failure")) {
PLOGE << QString("Failed to login the gateway at %1, %2").arg(loginUrl).arg(reply->errorString());
if (reply->error() || response.contains("Authentication failure")) {
PLOGE << QString("Failed to login the gateway at %1, %2").arg(loginUrl, reply->errorString());
if (normalLoginWindow) {
normalLoginWindow->setProcessing(false);
@@ -62,6 +66,13 @@ void GatewayAuthenticator::onLoginFinished()
return;
}
// 2FA
if (response.contains("Challenge")) {
PLOGI << "The server need input the challenge...";
showChallenge(response);
return;
}
if (normalLoginWindow) {
normalLoginWindow->close();
}
@@ -83,7 +94,7 @@ void GatewayAuthenticator::onPreloginFinished()
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
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.");
return;
@@ -98,7 +109,7 @@ void GatewayAuthenticator::onPreloginFinished()
} else if (response.hasNormalAuthFields()) {
normalAuth(response.labelUsername(), response.labelPassword(), response.authMessage());
} 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.");
}
@@ -107,7 +118,7 @@ void GatewayAuthenticator::onPreloginFinished()
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->setPortalAddress(gateway);
@@ -128,11 +139,10 @@ void GatewayAuthenticator::onPerformNormalLogin(const QString &username, const Q
PLOGI << "Start to perform normal login...";
normalLoginWindow->setProcessing(true);
LoginParams loginParams { params.clientos() };
loginParams.setUser(username);
loginParams.setPassword(password);
params.setUsername(username);
params.setPassword(password);
login(loginParams);
authenticate();
}
void GatewayAuthenticator::onLoginWindowRejected()
@@ -179,3 +189,38 @@ void GatewayAuthenticator::onSAMLLoginFail(const QString 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();
}

View File

@@ -4,6 +4,7 @@
#include <QtCore/QObject>
#include "normalloginwindow.h"
#include "challengedialog.h"
#include "loginparams.h"
#include "gatewayauthenticatorparams.h"
@@ -11,7 +12,7 @@ class GatewayAuthenticator : public QObject
{
Q_OBJECT
public:
explicit GatewayAuthenticator(const QString& gateway, const GatewayAuthenticatorParams params);
explicit GatewayAuthenticator(const QString& gateway, GatewayAuthenticatorParams params);
~GatewayAuthenticator();
void authenticate();
@@ -31,16 +32,18 @@ private slots:
private:
QString gateway;
const GatewayAuthenticatorParams params;
GatewayAuthenticatorParams params;
QString preloginUrl;
QString loginUrl;
NormalLoginWindow *normalLoginWindow{ nullptr };
ChallengeDialog *challengeDialog{ nullptr };
void login(const LoginParams& loginParams);
void doAuth();
void normalAuth(QString labelUsername, QString labelPassword, QString authMessage);
void samlAuth(QString samlMethod, QString samlRequest, QString preloginUrl = "");
void showChallenge(const QString &responseText);
};
#endif // GATEWAYAUTHENTICATOR_H

View File

@@ -55,3 +55,13 @@ void GatewayAuthenticatorParams::setClientos(const QString &newClientos)
m_clientos = newClientos;
}
const QString &GatewayAuthenticatorParams::inputStr() const
{
return m_inputStr;
}
void GatewayAuthenticatorParams::setInputStr(const QString &inputStr)
{
m_inputStr = inputStr;
}

View File

@@ -24,11 +24,15 @@ public:
const QString &clientos() const;
void setClientos(const QString &newClientos);
const QString &inputStr() const;
void setInputStr(const QString &inputStr);
private:
QString m_username;
QString m_password;
QString m_userAuthCookie;
QString m_clientos;
QString m_inputStr;
};
#endif // GATEWAYAUTHENTICATORPARAMS_H

View File

@@ -11,9 +11,10 @@
using namespace gpclient::helper;
GPClient::GPClient(QWidget *parent)
GPClient::GPClient(QWidget *parent, IVpn *vpn)
: QMainWindow(parent)
, ui(new Ui::GPClient)
, vpn(vpn)
, settingsDialog(new SettingsDialog(this))
{
ui->setupUi(this);
@@ -25,14 +26,14 @@ GPClient::GPClient(QWidget *parent)
setupSettings();
// Restore portal from the previous settings
ui->portalInput->setText(settings::get("portal", "").toString());
this->portal(settings::get("portal", "").toString());
// DBus service setup
vpn = new com::yuezk::qt::GPService("com.yuezk.qt.GPService", "/", QDBusConnection::systemBus(), this);
connect(vpn, &com::yuezk::qt::GPService::connected, this, &GPClient::onVPNConnected);
connect(vpn, &com::yuezk::qt::GPService::disconnected, this, &GPClient::onVPNDisconnected);
connect(vpn, &com::yuezk::qt::GPService::error, this, &GPClient::onVPNError);
connect(vpn, &com::yuezk::qt::GPService::logAvailable, this, &GPClient::onVPNLogAvailable);
QObject *ov = dynamic_cast<QObject*>(vpn);
connect(ov, SIGNAL(connected()), this, SLOT(onVPNConnected()));
connect(ov, SIGNAL(disconnected()), this, SLOT(onVPNDisconnected()));
connect(ov, SIGNAL(error(QString)), this, SLOT(onVPNError(QString)));
connect(ov, SIGNAL(logAvailable(QString)), this, SLOT(onVPNLogAvailable(QString)));
// Initiallize the context menu of system tray.
initSystemTrayIcon();
@@ -373,7 +374,11 @@ void GPClient::onGatewaySuccess(const QString &authCookie)
PLOGI << "Gateway login succeeded, got the cookie " << authCookie;
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...");
updateConnectionStatus(VpnStatus::pending);
}
@@ -410,6 +415,11 @@ QString GPClient::portal() const
return input;
}
void GPClient::portal(QString p)
{
ui->portalInput->setText(p);
}
bool GPClient::connected() const
{
const QString statusText = ui->statusLabel->text();

View File

@@ -6,9 +6,9 @@
#include <QtWidgets/QMenu>
#include <QtWidgets/QPushButton>
#include "gpserviceinterface.h"
#include "portalconfigresponse.h"
#include "settingsdialog.h"
#include "vpn.h"
QT_BEGIN_NAMESPACE
namespace Ui { class GPClient; }
@@ -19,12 +19,20 @@ class GPClient : public QMainWindow
Q_OBJECT
public:
GPClient(QWidget *parent = nullptr);
GPClient(QWidget *parent, IVpn *vpn);
~GPClient();
void activate();
void quit();
QString portal() const;
void portal(QString);
GPGateway currentGateway() const;
void setCurrentGateway(const GPGateway gateway);
void doConnect();
private slots:
void onSettingsButtonClicked();
void onSettingsAccepted();
@@ -58,7 +66,7 @@ private:
};
Ui::GPClient *ui;
com::yuezk::qt::GPService *vpn;
IVpn *vpn;
QSystemTrayIcon *systemTrayIcon;
QMenu *contextMenu;
@@ -83,20 +91,15 @@ private:
void populateGatewayMenu();
void updateConnectionStatus(const VpnStatus &status);
void doConnect();
void portalLogin();
void tryGatewayLogin();
void gatewayLogin();
QString portal() const;
bool connected() const;
QList<GPGateway> allGateways() const;
void setAllGateways(QList<GPGateway> gateways);
GPGateway currentGateway() const;
void setCurrentGateway(const GPGateway gateway);
void clearSettings();
};
#endif // GPCLIENT_H

View File

@@ -6,7 +6,7 @@ LoginParams::LoginParams(const QString clientos)
{
params.addQueryItem("prot", QUrl::toPercentEncoding("https:"));
params.addQueryItem("server", "");
params.addQueryItem("inputSrc", "");
params.addQueryItem("inputStr", "");
params.addQueryItem("jnlpReady", "jnlpReady");
params.addQueryItem("user", "");
params.addQueryItem("passwd", "");
@@ -61,6 +61,11 @@ void LoginParams::setPreloginCookie(const QString cookie)
updateQueryItem("prelogin-cookie", cookie);
}
void LoginParams::setInputStr(const QString inputStr)
{
updateQueryItem("inputStr", inputStr);
}
QByteArray LoginParams::toUtf8() const
{
return params.toString().toUtf8();

View File

@@ -15,6 +15,7 @@ public:
void setUserAuthCookie(const QString cookie);
void setPrelogonAuthCookie(const QString cookie);
void setPreloginCookie(const QString cookie);
void setInputStr(const QString inputStr);
QByteArray toUtf8() const;

View File

@@ -3,24 +3,22 @@
#include <QtCore/QDir>
#include <QtCore/QStandardPaths>
#include <plog/Log.h>
#include <plog/Init.h>
#include <plog/Appenders/ColorConsoleAppender.h>
#include <plog/Formatters/TxtFormatter.h>
#include "singleapplication.h"
#include "gpclient.h"
#include "vpn_dbus.h"
#include "vpn_json.h"
#include "enhancedwebview.h"
#include "sigwatch.h"
#include "version.h"
int main(int argc, char *argv[])
{
const QDir path = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + "/GlobalProtect-openconnect";
const QString logFile = path.path() + "/gpclient.log";
if (!path.exists()) {
path.mkpath(".");
}
static plog::ColorConsoleAppender<plog::TxtFormatter> consoleAppender;
plog::init(plog::debug, logFile.toUtf8()).addAppender(&consoleAppender);
plog::ColorConsoleAppender<plog::TxtFormatter> consoleAppender(plog::streamStdErr);
plog::init(plog::debug, &consoleAppender);
PLOGI << "GlobalProtect started, version: " << VERSION;
@@ -33,9 +31,35 @@ int main(int argc, char *argv[])
SingleApplication app(argc, argv);
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();
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);
UnixSignalWatcher sigwatch;
@@ -45,5 +69,12 @@ int main(int argc, char *argv[])
sigwatch.watchForSignal(SIGHUP);
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();
}

View File

@@ -41,7 +41,7 @@ void PortalAuthenticator::onPreloginFinished()
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
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.");
delete reply;
return;
@@ -195,9 +195,6 @@ void PortalAuthenticator::onFetchConfigFinished()
if (normalLoginWindow) {
PLOGI << "Closing the NormalLoginWindow...";
// Save the credentials for reuse
settings::save("username", username);
settings::save("password", password);
normalLoginWindow->close();
}

24
GPClient/vpn.h Normal file
View 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
View 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
View 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(QString errorMessage);
void logAvailable(QString log);
};
#endif

24
GPClient/vpn_json.cpp Normal file
View 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
View 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

View File

@@ -181,7 +181,7 @@ void GPService::onProcessStdout()
QString output = openconnect->readAllStandardOutput();
log(output);
if (output.indexOf("Connected as") >= 0) {
if (output.indexOf("Connected as") >= 0 || output.indexOf("Configured as") >= 0) {
vpnStatus = GPService::VpnConnected;
emit connected();
}

164
README.md
View File

@@ -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">
</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://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://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://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
@@ -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 switching gateway from the system tray menu manually.
## Future plan
- [ ] Improve the release process
- [ ] Process bugs and feature requests
- [ ] Support for bypassing the `gpclient` parameters
- [ ] Support the CLI mode
## Install
## 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.
[![Arch package](https://repology.org/badge/version-for-repo/arch/globalprotect-openconnect.svg)](https://repology.org/project/globalprotect-openconnect/versions)
[![AUR package](https://repology.org/badge/version-for-repo/aur/globalprotect-openconnect.svg)](https://repology.org/project/globalprotect-openconnect/versions)
[![Manjaro Stable package](https://repology.org/badge/version-for-repo/manjaro_stable/globalprotect-openconnect.svg)](https://repology.org/project/globalprotect-openconnect/versions)
[![Manjaro Testing package](https://repology.org/badge/version-for-repo/manjaro_testing/globalprotect-openconnect.svg)](https://repology.org/project/globalprotect-openconnect/versions)
[![Manjaro Unstable package](https://repology.org/badge/version-for-repo/manjaro_unstable/globalprotect-openconnect.svg)](https://repology.org/project/globalprotect-openconnect/versions)
[![nixpkgs unstable package](https://repology.org/badge/version-for-repo/nix_unstable/globalprotect-openconnect.svg)](https://repology.org/project/globalprotect-openconnect/versions)
[![Parabola package](https://repology.org/badge/version-for-repo/parabola/globalprotect-openconnect.svg)](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
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
## Build & Install from source code
Clone this repo with:
@@ -55,10 +97,6 @@ git clone https://github.com/yuezk/GlobalProtect-openconnect.git
cd GlobalProtect-openconnect
```
### Arch/Manjaro
Install from the [globalprotect-openconnect](https://aur.archlinux.org/packages/globalprotect-openconnect/) AUR.
### Ubuntu/Mint
> **⚠️ REQUIRED for Ubuntu 18.04 ⚠️**
@@ -107,38 +145,6 @@ Install the Qt5 dependencies and OpenConnect:
./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
In `configuration.nix`:
@@ -153,6 +159,38 @@ Relatively manual process for now:
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
The application logs can be found at: `~/.cache/GlobalProtect-openconnect/gpclient.log`

View File

@@ -1 +1 @@
1.3.4
1.4.1

23
debian/changelog vendored
View File

@@ -1,3 +1,26 @@
globalprotect-openconnect (1.4.1-1) unstable; urgency=medium
* Updated VERSION, Bumped 1.4.0 > 1.4.1
* print the gpservice logs
* update AUR packaging
-- Kevin Yue <k3vinyue@gmail.com> Thu, 03 Mar 2022 21:58:59 +0800
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
* Updated VERSION, Bumped 1.3.3 > 1.3.4

View File

@@ -1 +1 @@
3.0 (quilt)
3.0 (native)

View File

@@ -1,3 +1,26 @@
-------------------------------------------------------------------
Thu Mar 3 13:58:59 UTC 2022 - k3vinyue@gmail.com - 1.4.1
- Update to 1.4.1
* Updated VERSION, Bumped 1.4.0 > 1.4.1
* print the gpservice logs
* update AUR packaging
-------------------------------------------------------------------
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

View File

@@ -1,5 +1,5 @@
Name: globalprotect-openconnect
Version: 1.3.4
Version: 1.4.1
Release: 1
Summary: A GlobalProtect VPN client powered by OpenConnect
Group: Productivity/Networking/PPP

View File

@@ -18,7 +18,7 @@ cp -r ./packaging/obs ./artifacts
cp ./artifacts/*.tar.gz ./artifacts/obs/globalprotect-openconnect.tar.gz
# Prepare the AUR package
cp ./packaging/aur/PKGBUILD ./artifacts/aur
cp ./packaging/aur/PKGBUILD-git ./artifacts/aur/PKGBUILD
cp ./artifacts/*.tar.gz ./artifacts/aur/globalprotect-openconnect.tar.gz
# Prepare the flatpak package

View File

@@ -304,7 +304,7 @@ do-versionfile() {
[ -f VERSION ] && ACTION_MSG="Updated" || ACTION_MSG="Created"
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"
# Stage file for commit

0
scripts/release.sh Normal file → Executable file
View File