Compare commits

..

3 Commits

Author SHA1 Message Date
Kevin Yue
c347f97b95 Update vite 2024-04-04 18:34:58 +08:00
Kevin Yue
29cfa9e24b Polish authentication 2024-04-04 18:31:48 +08:00
Kevin Yue
1b1ce882a5 Update CI 2024-04-03 21:17:24 +08:00
6 changed files with 48 additions and 36 deletions

View File

@ -25,9 +25,9 @@ jobs:
id: set-matrix
run: |
if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then
echo "matrix=[\"ubuntu-latest\", \"arm64\"]" >> $GITHUB_OUTPUT
echo 'matrix=[{"runner": "ubuntu-latest", "arch": "amd64"}, {"runner": "arm64", "arch": "arm64"]' >> $GITHUB_OUTPUT
else
echo "matrix=[\"ubuntu-latest\"]" >> $GITHUB_OUTPUT
echo 'matrix=[{"runner": "ubuntu-latest", "arch": "amd64"}]' >> $GITHUB_OUTPUT
fi
tarball:
@ -70,7 +70,8 @@ jobs:
matrix:
os: ${{fromJson(needs.setup-matrix.outputs.matrix)}}
package: [deb, rpm, pkg, binary]
runs-on: ${{ matrix.os }}
runs-on: ${{ matrix.os.runner }}
name: build-gp (${{ matrix.package }}, ${{ matrix.os.arch }})
steps:
- name: Prepare workspace
run: |
@ -98,7 +99,7 @@ jobs:
- name: Upload ${{ matrix.package }} package
uses: actions/upload-artifact@v3
with:
name: artifact-gp-${{ matrix.os }}-${{ matrix.package }}
name: artifact-gp-${{ matrix.package }}-${{ matrix.os.arch }}
if-no-files-found: error
path: |
build-gp-${{ matrix.package }}/artifacts/*
@ -109,7 +110,8 @@ jobs:
strategy:
matrix:
os: ${{fromJson(needs.setup-matrix.outputs.matrix)}}
runs-on: ${{ matrix.os }}
runs-on: ${{ matrix.os.runner }}
name: build-gpgui (${{ matrix.os.arch }})
steps:
- uses: pnpm/action-setup@v2
with:
@ -148,7 +150,7 @@ jobs:
- name: Upload gpgui
uses: actions/upload-artifact@v3
with:
name: artifact-gpgui-${{ matrix.os }}
name: artifact-gpgui-${{ matrix.os.arch }}
if-no-files-found: error
path: |
gpgui-source/*.bin.tar.xz

View File

@ -185,6 +185,10 @@ impl<'a> AuthWindow<'a> {
}
info!("Loaded uri: {}", redact_uri(&uri));
if uri.starts_with("globalprotectcallback:") {
return;
}
read_auth_data(&main_resource, auth_result_tx_clone.clone());
}
});
@ -203,7 +207,9 @@ impl<'a> AuthWindow<'a> {
wv.connect_load_failed(move |_wv, _event, uri, err| {
let redacted_uri = redact_uri(uri);
if !uri.starts_with("globalprotectcallback:") {
warn!("Failed to load uri: {} with error: {}", redacted_uri, err);
}
// NOTE: Don't send error here, since load_changed event will be triggered after this
// send_auth_result(&auth_result_tx, Err(AuthDataError::Invalid));
// true to stop other handlers from being invoked for the event. false to propagate the event further.
@ -340,7 +346,7 @@ fn read_auth_data_from_headers(response: &URIResponse) -> AuthResult {
fn read_auth_data_from_body<F>(main_resource: &WebResource, callback: F)
where
F: FnOnce(AuthResult) + Send + 'static,
F: FnOnce(Result<SamlAuthData, AuthDataParseError>) + Send + 'static,
{
main_resource.data(Cancellable::NONE, |data| match data {
Ok(data) => {
@ -349,15 +355,15 @@ where
}
Err(err) => {
info!("Failed to read response body: {}", err);
callback(Err(AuthDataError::Invalid))
callback(Err(AuthDataParseError::Invalid))
}
});
}
fn read_auth_data_from_html(html: &str) -> AuthResult {
fn read_auth_data_from_html(html: &str) -> Result<SamlAuthData, AuthDataParseError> {
if html.contains("Temporarily Unavailable") {
info!("Found 'Temporarily Unavailable' in HTML, auth failed");
return Err(AuthDataError::Invalid);
return Err(AuthDataParseError::Invalid);
}
let auth_data = match SamlAuthData::from_html(html) {
@ -372,10 +378,7 @@ fn read_auth_data_from_html(html: &str) -> AuthResult {
}
};
auth_data.map_err(|err| match err {
AuthDataParseError::NotFound => AuthDataError::NotFound,
AuthDataParseError::Invalid => AuthDataError::Invalid,
})
auth_data
}
fn extract_gpcallback(html: &str) -> Option<&str> {
@ -386,13 +389,12 @@ fn extract_gpcallback(html: &str) -> Option<&str> {
}
fn read_auth_data(main_resource: &WebResource, auth_result_tx: mpsc::UnboundedSender<AuthResult>) {
if main_resource.response().is_none() {
let Some(response) = main_resource.response() else {
info!("No response found in main resource");
send_auth_result(&auth_result_tx, Err(AuthDataError::Invalid));
return;
}
};
let response = main_resource.response().unwrap();
info!("Trying to read auth data from response headers...");
match read_auth_data_from_headers(&response) {
@ -405,22 +407,27 @@ fn read_auth_data(main_resource: &WebResource, auth_result_tx: mpsc::UnboundedSe
read_auth_data_from_body(main_resource, move |auth_result| {
// Since we have already found invalid auth data in headers, which means this could be the `/SAML20/SP/ACS` endpoint
// any error result from body should be considered as invalid, and trigger a retry
let auth_result = auth_result.map_err(|_| AuthDataError::Invalid);
let auth_result = auth_result.map_err(|err| {
info!("Failed to read auth data from body: {}", err);
AuthDataError::Invalid
});
send_auth_result(&auth_result_tx, auth_result);
});
}
Err(AuthDataError::NotFound) => {
info!("No auth data found in headers, trying to read from body...");
let url = main_resource.uri().unwrap_or("".into());
let is_acs_endpoint = url.contains("/SAML20/SP/ACS");
let is_acs_endpoint = main_resource.uri().map_or(false, |uri| uri.contains("/SAML20/SP/ACS"));
read_auth_data_from_body(main_resource, move |auth_result| {
// If the endpoint is `/SAML20/SP/ACS` and no auth data found in body, it should be considered as invalid
let auth_result = auth_result.map_err(|err| {
if matches!(err, AuthDataError::NotFound) && is_acs_endpoint {
AuthDataError::Invalid
info!("Failed to read auth data from body: {}", err);
if !is_acs_endpoint && matches!(err, AuthDataParseError::NotFound) {
AuthDataError::NotFound
} else {
err
AuthDataError::Invalid
}
});
@ -492,7 +499,10 @@ mod tests {
<meta http-equiv="refresh" content="0; URL=globalprotectcallback:PGh0bWw+PCEtLSA8c">
"#;
assert_eq!(extract_gpcallback(html), Some("globalprotectcallback:PGh0bWw+PCEtLSA8c"));
assert_eq!(
extract_gpcallback(html),
Some("globalprotectcallback:PGh0bWw+PCEtLSA8c")
);
}
#[test]

View File

@ -31,6 +31,6 @@
"eslint-plugin-react-hooks": "^4.6.0",
"prettier": "3.1.0",
"typescript": "^5.0.2",
"vite": "^4.5.2"
"vite": "^4.5.3"
}
}

View File

@ -48,7 +48,7 @@ devDependencies:
version: 6.12.0(eslint@8.54.0)(typescript@5.0.2)
'@vitejs/plugin-react':
specifier: ^4.0.3
version: 4.0.3(vite@4.5.2)
version: 4.0.3(vite@4.5.3)
eslint:
specifier: ^8.54.0
version: 8.54.0
@ -68,8 +68,8 @@ devDependencies:
specifier: ^5.0.2
version: 5.0.2
vite:
specifier: ^4.5.2
version: 4.5.2(@types/node@20.8.10)
specifier: ^4.5.3
version: 4.5.3(@types/node@20.8.10)
packages:
@ -1229,7 +1229,7 @@ packages:
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
dev: true
/@vitejs/plugin-react@4.0.3(vite@4.5.2):
/@vitejs/plugin-react@4.0.3(vite@4.5.3):
resolution: {integrity: sha512-pwXDog5nwwvSIzwrvYYmA2Ljcd/ZNlcsSG2Q9CNDBwnsd55UGAyr2doXtB5j+2uymRCnCfExlznzzSFbBRcoCg==}
engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies:
@ -1239,7 +1239,7 @@ packages:
'@babel/plugin-transform-react-jsx-self': 7.22.5(@babel/core@7.23.2)
'@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.23.2)
react-refresh: 0.14.0
vite: 4.5.2(@types/node@20.8.10)
vite: 4.5.3(@types/node@20.8.10)
transitivePeerDependencies:
- supports-color
dev: true
@ -2979,8 +2979,8 @@ packages:
punycode: 2.3.1
dev: true
/vite@4.5.2(@types/node@20.8.10):
resolution: {integrity: sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==}
/vite@4.5.3(@types/node@20.8.10):
resolution: {integrity: sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==}
engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true
peerDependencies:

View File

@ -68,12 +68,12 @@ impl SamlAuthData {
if auth_data.starts_with("cas-as") {
info!("Got token auth data: {}", auth_data);
let token_cred: SamlAuthData = serde_urlencoded::from_str(auth_data).map_err(|e| {
let auth_data: SamlAuthData = serde_urlencoded::from_str(auth_data).map_err(|e| {
warn!("Failed to parse token auth data: {}", e);
AuthDataParseError::Invalid
})?;
Ok(token_cred)
Ok(auth_data)
} else {
info!("Parsing SAML auth data...");

View File

@ -42,7 +42,7 @@ impl ClientOs {
}
}
#[derive(Debug, Serialize, Deserialize, Type, Default, Clone)]
#[derive(Debug, Serialize, Deserialize, Type, Default)]
pub struct GpParams {
is_gateway: bool,
user_agent: String,