mirror of
https://github.com/yuezk/GlobalProtect-openconnect.git
synced 2025-05-20 07:26:58 -04:00
Refactor using Tauri (#278)
This commit is contained in:
74
crates/gpapi/src/gateway/login.rs
Normal file
74
crates/gpapi/src/gateway/login.rs
Normal file
@@ -0,0 +1,74 @@
|
||||
use log::info;
|
||||
use reqwest::Client;
|
||||
use roxmltree::Document;
|
||||
use urlencoding::encode;
|
||||
|
||||
use crate::{credential::Credential, gp_params::GpParams};
|
||||
|
||||
pub async fn gateway_login(
|
||||
gateway: &str,
|
||||
cred: &Credential,
|
||||
gp_params: &GpParams,
|
||||
) -> anyhow::Result<String> {
|
||||
let login_url = format!("https://{}/ssl-vpn/login.esp", gateway);
|
||||
let client = Client::builder()
|
||||
.user_agent(gp_params.user_agent())
|
||||
.build()?;
|
||||
|
||||
let mut params = cred.to_params();
|
||||
let extra_params = gp_params.to_params();
|
||||
|
||||
params.extend(extra_params);
|
||||
params.insert("server", gateway);
|
||||
|
||||
info!("Gateway login, user_agent: {}", gp_params.user_agent());
|
||||
|
||||
let res_xml = client
|
||||
.post(&login_url)
|
||||
.form(¶ms)
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?
|
||||
.text()
|
||||
.await?;
|
||||
|
||||
let doc = Document::parse(&res_xml)?;
|
||||
|
||||
build_gateway_token(&doc, gp_params.computer())
|
||||
}
|
||||
|
||||
fn build_gateway_token(doc: &Document, computer: &str) -> anyhow::Result<String> {
|
||||
let args = doc
|
||||
.descendants()
|
||||
.filter(|n| n.has_tag_name("argument"))
|
||||
.map(|n| n.text().unwrap_or("").to_string())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let params = [
|
||||
read_args(&args, 1, "authcookie")?,
|
||||
read_args(&args, 3, "portal")?,
|
||||
read_args(&args, 4, "user")?,
|
||||
read_args(&args, 7, "domain")?,
|
||||
read_args(&args, 15, "preferred-ip")?,
|
||||
("computer", computer),
|
||||
];
|
||||
|
||||
let token = params
|
||||
.iter()
|
||||
.map(|(k, v)| format!("{}={}", k, encode(v)))
|
||||
.collect::<Vec<_>>()
|
||||
.join("&");
|
||||
|
||||
Ok(token)
|
||||
}
|
||||
|
||||
fn read_args<'a>(
|
||||
args: &'a [String],
|
||||
index: usize,
|
||||
key: &'a str,
|
||||
) -> anyhow::Result<(&'a str, &'a str)> {
|
||||
args
|
||||
.get(index)
|
||||
.ok_or_else(|| anyhow::anyhow!("Failed to read {key} from args"))
|
||||
.map(|s| (key, s.as_ref()))
|
||||
}
|
41
crates/gpapi/src/gateway/mod.rs
Normal file
41
crates/gpapi/src/gateway/mod.rs
Normal file
@@ -0,0 +1,41 @@
|
||||
mod login;
|
||||
mod parse_gateways;
|
||||
|
||||
pub use login::*;
|
||||
pub(crate) use parse_gateways::*;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Type, Clone)]
|
||||
pub(crate) struct PriorityRule {
|
||||
pub(crate) name: String,
|
||||
pub(crate) priority: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Type, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Gateway {
|
||||
pub(crate) name: String,
|
||||
pub(crate) address: String,
|
||||
pub(crate) priority: u32,
|
||||
pub(crate) priority_rules: Vec<PriorityRule>,
|
||||
}
|
||||
|
||||
impl Display for Gateway {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{} ({})", self.name, self.address)
|
||||
}
|
||||
}
|
||||
|
||||
impl Gateway {
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn server(&self) -> &str {
|
||||
&self.address
|
||||
}
|
||||
}
|
63
crates/gpapi/src/gateway/parse_gateways.rs
Normal file
63
crates/gpapi/src/gateway/parse_gateways.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
use roxmltree::Document;
|
||||
|
||||
use super::{Gateway, PriorityRule};
|
||||
|
||||
pub(crate) fn parse_gateways(doc: &Document) -> Option<Vec<Gateway>> {
|
||||
let node_gateways = doc.descendants().find(|n| n.has_tag_name("gateways"))?;
|
||||
let list_gateway = node_gateways
|
||||
.descendants()
|
||||
.find(|n| n.has_tag_name("list"))?;
|
||||
|
||||
let gateways = list_gateway
|
||||
.children()
|
||||
.filter_map(|gateway_item| {
|
||||
if !gateway_item.has_tag_name("entry") {
|
||||
return None;
|
||||
}
|
||||
let address = gateway_item.attribute("name").unwrap_or("").to_string();
|
||||
let name = gateway_item
|
||||
.children()
|
||||
.find(|n| n.has_tag_name("description"))
|
||||
.and_then(|n| n.text())
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
let priority = gateway_item
|
||||
.children()
|
||||
.find(|n| n.has_tag_name("priority"))
|
||||
.and_then(|n| n.text())
|
||||
.and_then(|s| s.parse().ok())
|
||||
.unwrap_or(u32::MAX);
|
||||
let priority_rules = gateway_item
|
||||
.children()
|
||||
.find(|n| n.has_tag_name("priority-rule"))
|
||||
.map(|n| {
|
||||
n.children()
|
||||
.filter_map(|n| {
|
||||
if !n.has_tag_name("entry") {
|
||||
return None;
|
||||
}
|
||||
let name = n.attribute("name").unwrap_or("").to_string();
|
||||
let priority: u32 = n
|
||||
.children()
|
||||
.find(|n| n.has_tag_name("priority"))
|
||||
.and_then(|n| n.text())
|
||||
.and_then(|s| s.parse().ok())
|
||||
.unwrap_or(u32::MAX);
|
||||
|
||||
Some(PriorityRule { name, priority })
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
Some(Gateway {
|
||||
name,
|
||||
address,
|
||||
priority,
|
||||
priority_rules,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
Some(gateways)
|
||||
}
|
Reference in New Issue
Block a user