mirror of
https://github.com/yuezk/GlobalProtect-openconnect.git
synced 2025-05-20 07:26:58 -04:00
Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f482bd077b | ||
|
148468eee3 | ||
|
79083e5664 | ||
|
c52d2bc0b6 |
23
.github/workflows/build.yaml
vendored
23
.github/workflows/build.yaml
vendored
@@ -168,22 +168,23 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Prepare workspace
|
- name: Prepare workspace
|
||||||
run: rm -rf gh-release && mkdir gh-release
|
run: rm -rf gh-release && mkdir gh-release
|
||||||
|
|
||||||
|
- name: Checkout GlobalProtect-openconnect
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GH_PAT }}
|
||||||
|
repository: yuezk/GlobalProtect-openconnect
|
||||||
|
ref: ${{ github.ref }}
|
||||||
|
path: gh-release/gp
|
||||||
|
|
||||||
- name: Download all artifacts
|
- name: Download all artifacts
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
path: gh-release
|
path: gh-release/gp/.build/artifacts
|
||||||
|
|
||||||
- name: Create GH release
|
- name: Create GH release
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GH_PAT }}
|
GH_TOKEN: ${{ secrets.GH_PAT }}
|
||||||
RELEASE_TAG: ${{ github.ref == 'refs/heads/dev' && 'snapshot' || github.ref_name }}
|
RELEASE_TAG: ${{ github.ref == 'refs/heads/dev' && 'snapshot' || github.ref_name }}
|
||||||
REPO: ${{ github.repository }}
|
|
||||||
NOTES: ${{ github.ref == 'refs/heads/dev' && '**!!! DO NOT USE THIS RELEASE IN PRODUCTION !!!**' || format('Release {0}', github.ref_name) }}
|
|
||||||
run: |
|
run: |
|
||||||
gh -R "$REPO" release delete $RELEASE_TAG --yes --cleanup-tag || true
|
cd gh-release/gp/scripts && ./gh-release.sh "$RELEASE_TAG"
|
||||||
gh -R "$REPO" release create $RELEASE_TAG \
|
|
||||||
--title "$RELEASE_TAG" \
|
|
||||||
--notes "$NOTES" \
|
|
||||||
${{ github.ref == 'refs/heads/dev' && '--target dev' || '' }} \
|
|
||||||
${{ github.ref == 'refs/heads/dev' && '--prerelease' || '' }} \
|
|
||||||
gh-release/artifact-source/* \
|
|
||||||
gh-release/artifact-gpgui-*/*
|
|
||||||
|
33
Cargo.lock
generated
33
Cargo.lock
generated
@@ -570,7 +570,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "common"
|
name = "common"
|
||||||
version = "2.3.1"
|
version = "2.3.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"is_executable",
|
"is_executable",
|
||||||
]
|
]
|
||||||
@@ -898,24 +898,6 @@ dependencies = [
|
|||||||
"litrs",
|
"litrs",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "dotenvy"
|
|
||||||
version = "0.15.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "dotenvy_macro"
|
|
||||||
version = "0.15.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cb0235d912a8c749f4e0c9f18ca253b4c28cfefc1d2518096016d6e3230b6424"
|
|
||||||
dependencies = [
|
|
||||||
"dotenvy",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dtoa"
|
name = "dtoa"
|
||||||
version = "1.0.9"
|
version = "1.0.9"
|
||||||
@@ -1436,13 +1418,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gpapi"
|
name = "gpapi"
|
||||||
version = "2.3.1"
|
version = "2.3.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.21.5",
|
"base64 0.21.5",
|
||||||
"chacha20poly1305",
|
"chacha20poly1305",
|
||||||
"clap",
|
"clap",
|
||||||
"dotenvy_macro",
|
|
||||||
"log",
|
"log",
|
||||||
"md5",
|
"md5",
|
||||||
"open",
|
"open",
|
||||||
@@ -1470,7 +1451,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gpauth"
|
name = "gpauth"
|
||||||
version = "2.3.1"
|
version = "2.3.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@@ -1491,7 +1472,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gpclient"
|
name = "gpclient"
|
||||||
version = "2.3.1"
|
version = "2.3.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@@ -1513,7 +1494,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gpgui-helper"
|
name = "gpgui-helper"
|
||||||
version = "2.3.1"
|
version = "2.3.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@@ -1531,7 +1512,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gpservice"
|
name = "gpservice"
|
||||||
version = "2.3.1"
|
version = "2.3.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"axum",
|
"axum",
|
||||||
@@ -2545,7 +2526,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openconnect"
|
name = "openconnect"
|
||||||
version = "2.3.1"
|
version = "2.3.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"common",
|
"common",
|
||||||
|
@@ -5,7 +5,7 @@ members = ["crates/*", "apps/gpclient", "apps/gpservice", "apps/gpauth", "apps/g
|
|||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
rust-version = "1.70"
|
rust-version = "1.70"
|
||||||
version = "2.3.1"
|
version = "2.3.3"
|
||||||
authors = ["Kevin Yue <k3vinyue@gmail.com>"]
|
authors = ["Kevin Yue <k3vinyue@gmail.com>"]
|
||||||
homepage = "https://github.com/yuezk/GlobalProtect-openconnect"
|
homepage = "https://github.com/yuezk/GlobalProtect-openconnect"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
@@ -41,7 +41,6 @@ uzers = "0.11"
|
|||||||
whoami = "1"
|
whoami = "1"
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
redact-engine = "0.1"
|
redact-engine = "0.1"
|
||||||
dotenvy_macro = "0.15"
|
|
||||||
compile-time = "0.2"
|
compile-time = "0.2"
|
||||||
serde_urlencoded = "0.7"
|
serde_urlencoded = "0.7"
|
||||||
md5="0.7"
|
md5="0.7"
|
||||||
|
@@ -19,7 +19,7 @@ pub(crate) struct SharedArgs {
|
|||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
enum CliCommand {
|
enum CliCommand {
|
||||||
#[command(about = "Connect to a portal server")]
|
#[command(about = "Connect to a portal server")]
|
||||||
Connect(ConnectArgs),
|
Connect(Box<ConnectArgs>),
|
||||||
#[command(about = "Disconnect from the server")]
|
#[command(about = "Disconnect from the server")]
|
||||||
Disconnect,
|
Disconnect,
|
||||||
#[command(about = "Launch the GUI")]
|
#[command(about = "Launch the GUI")]
|
||||||
|
12
changelog.md
12
changelog.md
@@ -1,5 +1,17 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2.3.3 - 2024-06-23
|
||||||
|
|
||||||
|
- GUI: add the remark field for the license activation
|
||||||
|
- GUI: check the saved secret key length
|
||||||
|
|
||||||
|
## 2.3.2 - 2024-06-17
|
||||||
|
|
||||||
|
- Fix the CAS callback parsing issue (fix [#372](https://github.com/yuezk/GlobalProtect-openconnect/issues/372))
|
||||||
|
- CLI: fix the `/tmp/gpauth.html` deletion issue (fix [#366](https://github.com/yuezk/GlobalProtect-openconnect/issues/366))
|
||||||
|
- GUI: fix the license not working after reboot (fix [#376](https://github.com/yuezk/GlobalProtect-openconnect/issues/376))
|
||||||
|
- GUI: add the license activation management link
|
||||||
|
|
||||||
## 2.3.1 - 2024-05-21
|
## 2.3.1 - 2024-05-21
|
||||||
|
|
||||||
- Fix the `--sslkey` option not working
|
- Fix the `--sslkey` option not working
|
||||||
|
@@ -25,7 +25,6 @@ chacha20poly1305 = { version = "0.10", features = ["std"] }
|
|||||||
redact-engine.workspace = true
|
redact-engine.workspace = true
|
||||||
url.workspace = true
|
url.workspace = true
|
||||||
regex.workspace = true
|
regex.workspace = true
|
||||||
dotenvy_macro.workspace = true
|
|
||||||
uzers.workspace = true
|
uzers.workspace = true
|
||||||
serde_urlencoded.workspace = true
|
serde_urlencoded.workspace = true
|
||||||
md5.workspace = true
|
md5.workspace = true
|
||||||
|
19
crates/gpapi/build.rs
Normal file
19
crates/gpapi/build.rs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let manifest_dir = env!("CARGO_MANIFEST_DIR");
|
||||||
|
let workspace_dir = Path::new(manifest_dir).ancestors().nth(2).unwrap();
|
||||||
|
let gpgui_dir = workspace_dir.parent().unwrap().join("gpgui");
|
||||||
|
|
||||||
|
let gp_service_binary = workspace_dir.join("target/debug/gpservice");
|
||||||
|
let gp_client_binary = workspace_dir.join("target/debug/gpclient");
|
||||||
|
let gp_auth_binary = workspace_dir.join("target/debug/gpauth");
|
||||||
|
let gp_gui_helper_binary = workspace_dir.join("target/debug/gpgui-helper");
|
||||||
|
let gp_gui_binary = gpgui_dir.join("target/debug/gpgui");
|
||||||
|
|
||||||
|
println!("cargo:rustc-env=GP_SERVICE_BINARY={}", gp_service_binary.display());
|
||||||
|
println!("cargo:rustc-env=GP_CLIENT_BINARY={}", gp_client_binary.display());
|
||||||
|
println!("cargo:rustc-env=GP_AUTH_BINARY={}", gp_auth_binary.display());
|
||||||
|
println!("cargo:rustc-env=GP_GUI_HELPER_BINARY={}", gp_gui_helper_binary.display());
|
||||||
|
println!("cargo:rustc-env=GP_GUI_BINARY={}", gp_gui_binary.display());
|
||||||
|
}
|
@@ -1,3 +1,5 @@
|
|||||||
|
use std::borrow::{Borrow, Cow};
|
||||||
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -68,24 +70,29 @@ impl SamlAuthData {
|
|||||||
if auth_data.starts_with("cas-as") {
|
if auth_data.starts_with("cas-as") {
|
||||||
info!("Got CAS auth data from globalprotectcallback");
|
info!("Got CAS auth data from globalprotectcallback");
|
||||||
|
|
||||||
let auth_data: SamlAuthData = serde_urlencoded::from_str(auth_data).map_err(|e| {
|
// Decode the auth data and use the original value if decoding fails
|
||||||
|
let auth_data = urlencoding::decode(auth_data).unwrap_or_else(|err| {
|
||||||
|
warn!("Failed to decode token auth data: {}", err);
|
||||||
|
Cow::Borrowed(auth_data)
|
||||||
|
});
|
||||||
|
|
||||||
|
let auth_data: SamlAuthData = serde_urlencoded::from_str(auth_data.borrow()).map_err(|e| {
|
||||||
warn!("Failed to parse token auth data: {}", e);
|
warn!("Failed to parse token auth data: {}", e);
|
||||||
warn!("Auth data: {}", auth_data);
|
warn!("Auth data: {}", auth_data);
|
||||||
AuthDataParseError::Invalid
|
AuthDataParseError::Invalid
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(auth_data)
|
return Ok(auth_data);
|
||||||
} else {
|
|
||||||
info!("Parsing SAML auth data...");
|
|
||||||
|
|
||||||
let auth_data = decode_to_string(auth_data).map_err(|e| {
|
|
||||||
warn!("Failed to decode SAML auth data: {}", e);
|
|
||||||
AuthDataParseError::Invalid
|
|
||||||
})?;
|
|
||||||
let auth_data = Self::from_html(&auth_data)?;
|
|
||||||
|
|
||||||
Ok(auth_data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info!("Parsing SAML auth data...");
|
||||||
|
let auth_data = decode_to_string(auth_data).map_err(|e| {
|
||||||
|
warn!("Failed to decode SAML auth data: {}", e);
|
||||||
|
AuthDataParseError::Invalid
|
||||||
|
})?;
|
||||||
|
let auth_data = Self::from_html(&auth_data)?;
|
||||||
|
|
||||||
|
Ok(auth_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn username(&self) -> &str {
|
pub fn username(&self) -> &str {
|
||||||
@@ -143,6 +150,16 @@ mod tests {
|
|||||||
assert_eq!(auth_data.token(), Some("very_long_string"));
|
assert_eq!(auth_data.token(), Some("very_long_string"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn auth_data_from_gpcallback_cas_urlencoded() {
|
||||||
|
let auth_data = "globalprotectcallback:cas-as%3D1%26un%3Dxyz%40email.com%26token%3Dvery_long_string";
|
||||||
|
|
||||||
|
let auth_data = SamlAuthData::from_gpcallback(auth_data).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(auth_data.username(), "xyz@email.com");
|
||||||
|
assert_eq!(auth_data.token(), Some("very_long_string"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn auth_data_from_gpcallback_non_cas() {
|
fn auth_data_from_gpcallback_non_cas() {
|
||||||
let auth_data = "PGh0bWw+PCEtLSA8c2FtbC1hdXRoLXN0YXR1cz4xPC9zYW1sLWF1dGgtc3RhdHVzPjxwcmVsb2dpbi1jb29raWU+cHJlbG9naW4tY29va2llPC9wcmVsb2dpbi1jb29raWU+PHNhbWwtdXNlcm5hbWU+eHl6QGVtYWlsLmNvbTwvc2FtbC11c2VybmFtZT48c2FtbC1zbG8+bm88L3NhbWwtc2xvPjxzYW1sLVNlc3Npb25Ob3RPbk9yQWZ0ZXI+PC9zYW1sLVNlc3Npb25Ob3RPbk9yQWZ0ZXI+IC0tPjwvaHRtbD4=";
|
let auth_data = "PGh0bWw+PCEtLSA8c2FtbC1hdXRoLXN0YXR1cz4xPC9zYW1sLWF1dGgtc3RhdHVzPjxwcmVsb2dpbi1jb29raWU+cHJlbG9naW4tY29va2llPC9wcmVsb2dpbi1jb29raWU+PHNhbWwtdXNlcm5hbWU+eHl6QGVtYWlsLmNvbTwvc2FtbC11c2VybmFtZT48c2FtbC1zbG8+bm88L3NhbWwtc2xvPjxzYW1sLVNlc3Npb25Ob3RPbk9yQWZ0ZXI+PC9zYW1sLVNlc3Npb25Ob3RPbk9yQWZ0ZXI+IC0tPjwvaHRtbD4=";
|
||||||
|
@@ -29,12 +29,12 @@ pub const GP_GUI_HELPER_BINARY: &str = "/usr/bin/gpgui-helper";
|
|||||||
pub(crate) const GP_AUTH_BINARY: &str = "/usr/bin/gpauth";
|
pub(crate) const GP_AUTH_BINARY: &str = "/usr/bin/gpauth";
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
pub const GP_CLIENT_BINARY: &str = dotenvy_macro::dotenv!("GP_CLIENT_BINARY");
|
pub const GP_CLIENT_BINARY: &str = env!("GP_CLIENT_BINARY");
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
pub const GP_SERVICE_BINARY: &str = dotenvy_macro::dotenv!("GP_SERVICE_BINARY");
|
pub const GP_SERVICE_BINARY: &str = env!("GP_SERVICE_BINARY");
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
pub const GP_GUI_BINARY: &str = dotenvy_macro::dotenv!("GP_GUI_BINARY");
|
pub const GP_GUI_BINARY: &str = env!("GP_GUI_BINARY");
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
pub const GP_GUI_HELPER_BINARY: &str = dotenvy_macro::dotenv!("GP_GUI_HELPER_BINARY");
|
pub const GP_GUI_HELPER_BINARY: &str = env!("GP_GUI_HELPER_BINARY");
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
pub(crate) const GP_AUTH_BINARY: &str = dotenvy_macro::dotenv!("GP_AUTH_BINARY");
|
pub(crate) const GP_AUTH_BINARY: &str = env!("GP_AUTH_BINARY");
|
||||||
|
51
scripts/gh-release.sh
Executable file
51
scripts/gh-release.sh
Executable file
@@ -0,0 +1,51 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Usage: ./scripts/gh-release.sh <tag>
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
REPO="yuezk/GlobalProtect-openconnect"
|
||||||
|
TAG=$1
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||||
|
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
|
||||||
|
RELEASE_NOTES="Release $TAG"
|
||||||
|
|
||||||
|
if [ -z "$TAG" ]; then
|
||||||
|
echo "Usage: ./scripts/gh-release.sh <tag>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For snapshot release, we don't create a release, just clear the existing assets and upload new ones.
|
||||||
|
# This is to avoid notification spam.
|
||||||
|
release_snapshot() {
|
||||||
|
RELEASE_NOTES='**!!! DO NOT USE THIS RELEASE IN PRODUCTION !!!**'
|
||||||
|
|
||||||
|
# Get the existing assets
|
||||||
|
gh -R "$REPO" release view "$TAG" --json assets --jq '.assets[].name' \
|
||||||
|
| xargs -I {} gh -R "$REPO" release delete-asset "$TAG" {} --yes
|
||||||
|
|
||||||
|
echo "Uploading new assets..."
|
||||||
|
gh -R "$REPO" release upload "$TAG" \
|
||||||
|
"$PROJECT_DIR"/.build/artifacts/artifact-source/* \
|
||||||
|
"$PROJECT_DIR"/.build/artifacts/artifact-gpgui-*/*
|
||||||
|
}
|
||||||
|
|
||||||
|
release_tag() {
|
||||||
|
echo "Removing existing release..."
|
||||||
|
gh -R "$REPO" release delete $TAG --yes --cleanup-tag || true
|
||||||
|
|
||||||
|
echo "Creating release..."
|
||||||
|
gh -R "$REPO" release create $TAG \
|
||||||
|
--title "$TAG" \
|
||||||
|
--notes "$RELEASE_NOTES" \
|
||||||
|
"$PROJECT_DIR"/.build/artifacts/artifact-source/* \
|
||||||
|
"$PROJECT_DIR"/.build/artifacts/artifact-gpgui-*/*
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ $TAG == *"snapshot" ]]; then
|
||||||
|
release_snapshot
|
||||||
|
else
|
||||||
|
release_tag
|
||||||
|
fi
|
Reference in New Issue
Block a user