mirror of
https://github.com/yuezk/GlobalProtect-openconnect.git
synced 2025-04-29 14:16:26 -04:00
Support specify csd-wrapper
This commit is contained in:
parent
662e4d0b8a
commit
1cf31449d6
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1438,6 +1438,7 @@ dependencies = [
|
||||
"roxmltree",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"specta",
|
||||
"specta-macros",
|
||||
"tauri",
|
||||
|
@ -43,6 +43,7 @@ thiserror = "1"
|
||||
redact-engine = "0.1"
|
||||
dotenvy_macro = "0.15"
|
||||
compile-time = "0.2"
|
||||
serde_urlencoded = "0.7"
|
||||
|
||||
[profile.release]
|
||||
opt-level = 'z' # Optimize for size
|
||||
|
@ -10,7 +10,7 @@ use tokio::sync::{mpsc, oneshot, watch, RwLock};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
pub(crate) struct VpnTaskContext {
|
||||
vpn_handle: Arc<RwLock<Option<Vpn>>>,
|
||||
vpn_handle: Arc<std::sync::RwLock<Option<Vpn>>>,
|
||||
vpn_state_tx: Arc<watch::Sender<VpnState>>,
|
||||
disconnect_rx: RwLock<Option<oneshot::Receiver<()>>>,
|
||||
}
|
||||
@ -32,16 +32,18 @@ impl VpnTaskContext {
|
||||
}
|
||||
|
||||
let info = req.info().clone();
|
||||
let vpn_handle = self.vpn_handle.clone();
|
||||
let vpn_handle = Arc::clone(&self.vpn_handle);
|
||||
let args = req.args();
|
||||
let vpn = Vpn::builder(req.gateway().server(), args.cookie())
|
||||
.user_agent(args.user_agent())
|
||||
.script(args.vpnc_script())
|
||||
.csd_uid(args.csd_uid())
|
||||
.csd_wrapper(args.csd_wrapper())
|
||||
.os(args.openconnect_os())
|
||||
.build();
|
||||
|
||||
// Save the VPN handle
|
||||
vpn_handle.write().await.replace(vpn);
|
||||
vpn_handle.write().unwrap().replace(vpn);
|
||||
|
||||
let vpn_state_tx = self.vpn_state_tx.clone();
|
||||
let connect_info = Box::new(info.clone());
|
||||
@ -55,17 +57,30 @@ impl VpnTaskContext {
|
||||
thread::spawn(move || {
|
||||
let vpn_state_tx_clone = vpn_state_tx.clone();
|
||||
|
||||
vpn_handle.blocking_read().as_ref().map(|vpn| {
|
||||
vpn.connect(move || {
|
||||
let connect_info = Box::new(info.clone());
|
||||
vpn_state_tx.send(VpnState::Connected(connect_info)).ok();
|
||||
if let Err(err) = vpn_handle.read().map(|vpn| {
|
||||
vpn.as_ref().map(|vpn| {
|
||||
vpn.connect(move || {
|
||||
let connect_info = Box::new(info.clone());
|
||||
vpn_state_tx.send(VpnState::Connected(connect_info)).ok();
|
||||
})
|
||||
})
|
||||
});
|
||||
}) {
|
||||
info!("VPN connect failed: {:?}", err);
|
||||
}
|
||||
// .as_ref().map(|vpn| {
|
||||
// vpn.connect(move || {
|
||||
// let connect_info = Box::new(info.clone());
|
||||
// vpn_state_tx.send(VpnState::Connected(connect_info)).ok();
|
||||
// })
|
||||
// });
|
||||
|
||||
// println!("VPN connect result: {:?}", ret);
|
||||
|
||||
// Notify the VPN is disconnected
|
||||
vpn_state_tx_clone.send(VpnState::Disconnected).ok();
|
||||
// Remove the VPN handle
|
||||
vpn_handle.blocking_write().take();
|
||||
// vpn_handle.blocking_write().take();
|
||||
vpn_handle.write().unwrap().take();
|
||||
|
||||
disconnect_tx.send(()).ok();
|
||||
});
|
||||
@ -73,7 +88,9 @@ impl VpnTaskContext {
|
||||
|
||||
pub async fn disconnect(&self) {
|
||||
if let Some(disconnect_rx) = self.disconnect_rx.write().await.take() {
|
||||
if let Some(vpn) = self.vpn_handle.read().await.as_ref() {
|
||||
info!("Disconnecting VPN...");
|
||||
if let Some(vpn) = self.vpn_handle.read().unwrap().as_ref() {
|
||||
info!("VPN is connected, start disconnecting...");
|
||||
self.vpn_state_tx.send(VpnState::Disconnecting).ok();
|
||||
vpn.disconnect()
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ url.workspace = true
|
||||
regex.workspace = true
|
||||
dotenvy_macro.workspace = true
|
||||
uzers.workspace = true
|
||||
serde_urlencoded.workspace = true
|
||||
|
||||
tauri = { workspace = true, optional = true }
|
||||
clap = { workspace = true, optional = true }
|
||||
|
51
crates/gpapi/src/gateway/hip.rs
Normal file
51
crates/gpapi/src/gateway/hip.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::bail;
|
||||
use reqwest::Client;
|
||||
|
||||
use crate::{gp_params::GpParams, utils::normalize_server};
|
||||
|
||||
async fn retrieve_config(gateway: &str, cookie: &str, gp_params: &GpParams) -> anyhow::Result<()> {
|
||||
let url = normalize_server(gateway)?;
|
||||
|
||||
let config_url = format!("{}/ssl-vpn/getconfig.esp", url);
|
||||
let client = Client::builder()
|
||||
.danger_accept_invalid_certs(gp_params.ignore_tls_errors())
|
||||
.user_agent(gp_params.user_agent())
|
||||
.build()?;
|
||||
|
||||
let mut params = serde_urlencoded::from_str::<HashMap<&str, &str>>(cookie)?;
|
||||
|
||||
println!("{:?}", params);
|
||||
|
||||
params.insert("client-type", "1");
|
||||
params.insert("protocol-version", "p1");
|
||||
params.insert("internal", "no");
|
||||
params.insert("ipv6-support", "yes");
|
||||
params.insert("clientos", gp_params.client_os());
|
||||
params.insert("hmac-algo", "sha1,md5,sha256");
|
||||
params.insert("enc-algo", "aes-128-cbc,aes-256-cbc");
|
||||
|
||||
if let Some(os_version) = gp_params.os_version() {
|
||||
params.insert("os-version", os_version);
|
||||
}
|
||||
if let Some(client_version) = gp_params.client_version() {
|
||||
params.insert("app-version", client_version);
|
||||
}
|
||||
|
||||
let res = client.post(&config_url).form(¶ms).send().await?;
|
||||
let status = res.status();
|
||||
|
||||
if status.is_client_error() || status.is_server_error() {
|
||||
bail!("Retrieve config error: {}", status)
|
||||
}
|
||||
|
||||
let res_xml = res.text().await?;
|
||||
println!("{}", res_xml);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn hip_report(gateway: &str, cookie: &str, gp_params: &GpParams) -> anyhow::Result<()> {
|
||||
retrieve_config(gateway, cookie, gp_params).await
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
mod login;
|
||||
mod parse_gateways;
|
||||
pub mod hip;
|
||||
|
||||
pub use login::*;
|
||||
pub(crate) use parse_gateways::*;
|
||||
|
@ -83,6 +83,18 @@ impl GpParams {
|
||||
self.prefer_default_browser
|
||||
}
|
||||
|
||||
pub fn client_os(&self) -> &str {
|
||||
self.client_os.as_str()
|
||||
}
|
||||
|
||||
pub fn os_version(&self) -> Option<&str> {
|
||||
self.os_version.as_deref()
|
||||
}
|
||||
|
||||
pub fn client_version(&self) -> Option<&str> {
|
||||
self.client_version.as_deref()
|
||||
}
|
||||
|
||||
pub(crate) fn to_params(&self) -> HashMap<&str, &str> {
|
||||
let mut params: HashMap<&str, &str> = HashMap::new();
|
||||
let client_os = self.client_os.as_str();
|
||||
|
@ -23,6 +23,11 @@ pub fn get_non_root_user() -> anyhow::Result<User> {
|
||||
Ok(user)
|
||||
}
|
||||
|
||||
pub fn get_current_user() -> anyhow::Result<User> {
|
||||
let current_user = whoami::username();
|
||||
get_user_by_name(¤t_user)
|
||||
}
|
||||
|
||||
fn get_real_user() -> anyhow::Result<User> {
|
||||
// Read the UID from SUDO_UID or PKEXEC_UID environment variable if available.
|
||||
let uid = match env::var("SUDO_UID") {
|
||||
|
@ -32,6 +32,8 @@ pub struct ConnectArgs {
|
||||
cookie: String,
|
||||
vpnc_script: Option<String>,
|
||||
user_agent: Option<String>,
|
||||
csd_uid: u32,
|
||||
csd_wrapper: Option<String>,
|
||||
os: Option<ClientOs>,
|
||||
}
|
||||
|
||||
@ -42,6 +44,8 @@ impl ConnectArgs {
|
||||
vpnc_script: None,
|
||||
user_agent: None,
|
||||
os: None,
|
||||
csd_uid: 0,
|
||||
csd_wrapper: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,6 +64,14 @@ impl ConnectArgs {
|
||||
pub fn openconnect_os(&self) -> Option<String> {
|
||||
self.os.as_ref().map(|os| os.to_openconnect_os().to_string())
|
||||
}
|
||||
|
||||
pub fn csd_uid(&self) -> u32 {
|
||||
self.csd_uid
|
||||
}
|
||||
|
||||
pub fn csd_wrapper(&self) -> Option<String> {
|
||||
self.csd_wrapper.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Type)]
|
||||
@ -81,6 +93,16 @@ impl ConnectRequest {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_csd_uid(mut self, csd_uid: u32) -> Self {
|
||||
self.args.csd_uid = csd_uid;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_csd_wrapper<T: Into<Option<String>>>(mut self, csd_wrapper: T) -> Self {
|
||||
self.args.csd_wrapper = csd_wrapper.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_user_agent<T: Into<Option<String>>>(mut self, user_agent: T) -> Self {
|
||||
self.args.user_agent = user_agent.into();
|
||||
self
|
||||
|
@ -143,6 +143,9 @@ int vpn_connect(const vpn_options *options, vpn_connected_callback callback)
|
||||
void vpn_disconnect()
|
||||
{
|
||||
char cmd = OC_CMD_CANCEL;
|
||||
|
||||
INFO("Stopping VPN connection: %d", g_cmd_pipe_fd);
|
||||
|
||||
if (write(g_cmd_pipe_fd, &cmd, 1) < 0)
|
||||
{
|
||||
ERROR("Failed to write to command pipe, VPN connection may not be stopped");
|
||||
|
Loading…
x
Reference in New Issue
Block a user