Skip to content

Commit

Permalink
fix: Decode CAS callback before parsing
Browse files Browse the repository at this point in the history
Related: #372
  • Loading branch information
yuezk committed Jun 13, 2024
1 parent 54d4f2e commit c52d2bc
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 22 deletions.
23 changes: 12 additions & 11 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -168,22 +168,23 @@ jobs:
steps:
- name: Prepare workspace
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
uses: actions/download-artifact@v3
with:
path: gh-release
path: gh-release/gp/.build/artifacts

- name: Create GH release
env:
GH_TOKEN: ${{ secrets.GH_PAT }}
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: |
gh -R "$REPO" release delete $RELEASE_TAG --yes --cleanup-tag || true
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-*/*
cd gh-release/gp/scripts && ./gh-release.sh "$RELEASE_TAG"
39 changes: 28 additions & 11 deletions crates/gpapi/src/auth.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::borrow::{Borrow, Cow};

use log::{info, warn};
use regex::Regex;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -68,24 +70,29 @@ impl SamlAuthData {
if auth_data.starts_with("cas-as") {
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!("Auth data: {}", auth_data);
AuthDataParseError::Invalid
})?;

Ok(auth_data)
} else {
info!("Parsing SAML auth data...");
return Ok(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)?;
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)
}
Ok(auth_data)
}

pub fn username(&self) -> &str {
Expand Down Expand Up @@ -143,6 +150,16 @@ mod tests {
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]
fn auth_data_from_gpcallback_non_cas() {
let auth_data = "PGh0bWw+PCEtLSA8c2FtbC1hdXRoLXN0YXR1cz4xPC9zYW1sLWF1dGgtc3RhdHVzPjxwcmVsb2dpbi1jb29raWU+cHJlbG9naW4tY29va2llPC9wcmVsb2dpbi1jb29raWU+PHNhbWwtdXNlcm5hbWU+eHl6QGVtYWlsLmNvbTwvc2FtbC11c2VybmFtZT48c2FtbC1zbG8+bm88L3NhbWwtc2xvPjxzYW1sLVNlc3Npb25Ob3RPbk9yQWZ0ZXI+PC9zYW1sLVNlc3Npb25Ob3RPbk9yQWZ0ZXI+IC0tPjwvaHRtbD4=";
Expand Down
51 changes: 51 additions & 0 deletions scripts/gh-release.sh
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit c52d2bc

Please sign in to comment.