mirror of
https://github.com/yuezk/GlobalProtect-openconnect.git
synced 2025-05-20 07:26:58 -04:00
Compare commits
3 Commits
1e211e8912
...
87b965f80c
Author | SHA1 | Date | |
---|---|---|---|
|
87b965f80c | ||
|
b09b21ae0f | ||
|
7e372cd113 |
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -48,6 +48,7 @@
|
|||||||
"vpnc",
|
"vpnc",
|
||||||
"vpninfo",
|
"vpninfo",
|
||||||
"wmctrl",
|
"wmctrl",
|
||||||
"XAUTHORITY"
|
"XAUTHORITY",
|
||||||
|
"yuezk"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -1423,7 +1423,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gpapi"
|
name = "gpapi"
|
||||||
version = "2.0.0-beta2"
|
version = "2.0.0-beta3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.21.5",
|
"base64 0.21.5",
|
||||||
@ -1451,7 +1451,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gpauth"
|
name = "gpauth"
|
||||||
version = "2.0.0-beta2"
|
version = "2.0.0-beta3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@ -1471,7 +1471,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gpclient"
|
name = "gpclient"
|
||||||
version = "2.0.0-beta2"
|
version = "2.0.0-beta3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@ -1492,7 +1492,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gpservice"
|
name = "gpservice"
|
||||||
version = "2.0.0-beta2"
|
version = "2.0.0-beta3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"axum",
|
"axum",
|
||||||
@ -2447,7 +2447,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openconnect"
|
name = "openconnect"
|
||||||
version = "2.0.0-beta2"
|
version = "2.0.0-beta3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"is_executable",
|
"is_executable",
|
||||||
|
@ -4,7 +4,7 @@ resolver = "2"
|
|||||||
members = ["crates/*", "apps/gpclient", "apps/gpservice", "apps/gpauth"]
|
members = ["crates/*", "apps/gpclient", "apps/gpservice", "apps/gpauth"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "2.0.0-beta2"
|
version = "2.0.0-beta3"
|
||||||
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"
|
||||||
|
11
README.md
11
README.md
@ -54,6 +54,11 @@ The GUI version is also available after you installed it. You can launch it from
|
|||||||
>
|
>
|
||||||
> This instruction is for the 2.x version. The 1.x version is still available on the [1.x](https://github.com/yuezk/GlobalProtect-openconnect/tree/1.x) branch, you can build it from the source code by following the instructions in the `README.md` file.
|
> This instruction is for the 2.x version. The 1.x version is still available on the [1.x](https://github.com/yuezk/GlobalProtect-openconnect/tree/1.x) branch, you can build it from the source code by following the instructions in the `README.md` file.
|
||||||
|
|
||||||
|
> [!Warning]
|
||||||
|
>
|
||||||
|
> The client requires `openconnect >= 8.20`, please make sure you have it installed, you can check it with `openconnect --version`.
|
||||||
|
> Installing the client from PPA will automatically install the required version of `openconnect`.
|
||||||
|
|
||||||
### Debian/Ubuntu based distributions
|
### Debian/Ubuntu based distributions
|
||||||
|
|
||||||
#### Install from PPA
|
#### Install from PPA
|
||||||
@ -82,6 +87,10 @@ sudo dpkg -i globalprotect-openconnect_*.deb
|
|||||||
|
|
||||||
Install from AUR: [globalprotect-openconnect-git](https://aur.archlinux.org/packages/globalprotect-openconnect-git/)
|
Install from AUR: [globalprotect-openconnect-git](https://aur.archlinux.org/packages/globalprotect-openconnect-git/)
|
||||||
|
|
||||||
|
```
|
||||||
|
yay -S globalprotect-openconnect-git
|
||||||
|
```
|
||||||
|
|
||||||
#### Install from package
|
#### Install from package
|
||||||
|
|
||||||
Download the latest package from [releases](https://github.com/yuezk/GlobalProtect-openconnect/releases) page. Then install it with `pacman`:
|
Download the latest package from [releases](https://github.com/yuezk/GlobalProtect-openconnect/releases) page. Then install it with `pacman`:
|
||||||
@ -111,7 +120,7 @@ Download the latest RPM package from [releases](https://github.com/yuezk/GlobalP
|
|||||||
|
|
||||||
### Other distributions
|
### Other distributions
|
||||||
|
|
||||||
The project depends on `openconnect`, `webkit2gtk`, `libsecret`, `libayatana-appindicator` or `libappindicator-gtk3`. You can install them first and then download the latest binary release (i.e., `*.bin.tar.gz`) from [releases](https://github.com/yuezk/GlobalProtect-openconnect/releases) page.
|
The project depends on `openconnect >= 8.20`, `webkit2gtk`, `libsecret`, `libayatana-appindicator` or `libappindicator-gtk3`. You can install them first and then download the latest binary release (i.e., `*.bin.tar.gz`) from [releases](https://github.com/yuezk/GlobalProtect-openconnect/releases) page.
|
||||||
|
|
||||||
## [License](./LICENSE)
|
## [License](./LICENSE)
|
||||||
|
|
||||||
|
@ -47,6 +47,20 @@ pub(crate) struct ConnectArgs {
|
|||||||
clean: bool,
|
clean: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ConnectArgs {
|
||||||
|
fn os_version(&self) -> String {
|
||||||
|
if let Some(os_version) = &self.os_version {
|
||||||
|
return os_version.to_owned();
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.os {
|
||||||
|
Os::Linux => format!("Linux {}", whoami::distro()),
|
||||||
|
Os::Windows => String::from("Microsoft Windows 11 Pro , 64-bit"),
|
||||||
|
Os::Mac => String::from("Apple Mac OS X 13.4.0"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct ConnectHandler<'a> {
|
pub(crate) struct ConnectHandler<'a> {
|
||||||
args: &'a ConnectArgs,
|
args: &'a ConnectArgs,
|
||||||
shared_args: &'a SharedArgs,
|
shared_args: &'a SharedArgs,
|
||||||
@ -63,7 +77,7 @@ impl<'a> ConnectHandler<'a> {
|
|||||||
let gp_params = GpParams::builder()
|
let gp_params = GpParams::builder()
|
||||||
.user_agent(&self.args.user_agent)
|
.user_agent(&self.args.user_agent)
|
||||||
.client_os(ClientOs::from(&self.args.os))
|
.client_os(ClientOs::from(&self.args.os))
|
||||||
.os_version(self.args.os_version.clone())
|
.os_version(self.args.os_version())
|
||||||
.ignore_tls_errors(self.shared_args.ignore_tls_errors)
|
.ignore_tls_errors(self.shared_args.ignore_tls_errors)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@ -125,7 +139,7 @@ impl<'a> ConnectHandler<'a> {
|
|||||||
.saml_request(prelogin.saml_request())
|
.saml_request(prelogin.saml_request())
|
||||||
.user_agent(&self.args.user_agent)
|
.user_agent(&self.args.user_agent)
|
||||||
.os(self.args.os.as_str())
|
.os(self.args.os.as_str())
|
||||||
.os_version(self.args.os_version.as_deref())
|
.os_version(Some(&self.args.os_version()))
|
||||||
.hidpi(self.args.hidpi)
|
.hidpi(self.args.hidpi)
|
||||||
.fix_openssl(self.shared_args.fix_openssl)
|
.fix_openssl(self.shared_args.fix_openssl)
|
||||||
.ignore_tls_errors(self.shared_args.ignore_tls_errors)
|
.ignore_tls_errors(self.shared_args.ignore_tls_errors)
|
||||||
|
@ -164,31 +164,34 @@ impl Credential {
|
|||||||
let mut params = HashMap::new();
|
let mut params = HashMap::new();
|
||||||
params.insert("user", self.username());
|
params.insert("user", self.username());
|
||||||
|
|
||||||
match self {
|
let (passwd, prelogin_cookie, portal_userauthcookie, portal_prelogonuserauthcookie) = match self
|
||||||
Credential::Password(cred) => {
|
{
|
||||||
params.insert("passwd", cred.password());
|
Credential::Password(cred) => (Some(cred.password()), None, None, None),
|
||||||
}
|
Credential::PreloginCookie(cred) => (None, Some(cred.prelogin_cookie()), None, None),
|
||||||
Credential::PreloginCookie(cred) => {
|
Credential::AuthCookie(cred) => (
|
||||||
params.insert("prelogin-cookie", cred.prelogin_cookie());
|
None,
|
||||||
}
|
None,
|
||||||
Credential::AuthCookie(cred) => {
|
Some(cred.user_auth_cookie()),
|
||||||
params.insert("portal-userauthcookie", cred.user_auth_cookie());
|
Some(cred.prelogon_user_auth_cookie()),
|
||||||
params.insert(
|
),
|
||||||
"portal-prelogonuserauthcookie",
|
Credential::CachedCredential(cred) => (
|
||||||
cred.prelogon_user_auth_cookie(),
|
cred.password(),
|
||||||
);
|
None,
|
||||||
}
|
Some(cred.auth_cookie.user_auth_cookie()),
|
||||||
Credential::CachedCredential(cred) => {
|
Some(cred.auth_cookie.prelogon_user_auth_cookie()),
|
||||||
if let Some(password) = cred.password() {
|
),
|
||||||
params.insert("passwd", password);
|
};
|
||||||
}
|
|
||||||
params.insert("portal-userauthcookie", cred.auth_cookie.user_auth_cookie());
|
params.insert("passwd", passwd.unwrap_or_default());
|
||||||
params.insert(
|
params.insert("prelogin-cookie", prelogin_cookie.unwrap_or_default());
|
||||||
"portal-prelogonuserauthcookie",
|
params.insert(
|
||||||
cred.auth_cookie.prelogon_user_auth_cookie(),
|
"portal-userauthcookie",
|
||||||
);
|
portal_userauthcookie.unwrap_or_default(),
|
||||||
}
|
);
|
||||||
}
|
params.insert(
|
||||||
|
"portal-prelogonuserauthcookie",
|
||||||
|
portal_prelogonuserauthcookie.unwrap_or_default(),
|
||||||
|
);
|
||||||
|
|
||||||
params
|
params
|
||||||
}
|
}
|
||||||
|
@ -23,14 +23,8 @@ pub async fn gateway_login(
|
|||||||
|
|
||||||
info!("Gateway login, user_agent: {}", gp_params.user_agent());
|
info!("Gateway login, user_agent: {}", gp_params.user_agent());
|
||||||
|
|
||||||
let res_xml = client
|
let res = client.post(&login_url).form(¶ms).send().await?;
|
||||||
.post(&login_url)
|
let res_xml = res.error_for_status()?.text().await?;
|
||||||
.form(¶ms)
|
|
||||||
.send()
|
|
||||||
.await?
|
|
||||||
.error_for_status()?
|
|
||||||
.text()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let doc = Document::parse(&res_xml)?;
|
let doc = Document::parse(&res_xml)?;
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ pub struct GpParams {
|
|||||||
client_os: ClientOs,
|
client_os: ClientOs,
|
||||||
os_version: Option<String>,
|
os_version: Option<String>,
|
||||||
client_version: Option<String>,
|
client_version: Option<String>,
|
||||||
computer: Option<String>,
|
computer: String,
|
||||||
ignore_tls_errors: bool,
|
ignore_tls_errors: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,10 +62,7 @@ impl GpParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn computer(&self) -> &str {
|
pub(crate) fn computer(&self) -> &str {
|
||||||
match self.computer {
|
&self.computer
|
||||||
Some(ref computer) => computer,
|
|
||||||
None => self.client_os.as_str(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ignore_tls_errors(&self) -> bool {
|
pub fn ignore_tls_errors(&self) -> bool {
|
||||||
@ -84,14 +81,8 @@ impl GpParams {
|
|||||||
params.insert("ipv6-support", "yes");
|
params.insert("ipv6-support", "yes");
|
||||||
params.insert("inputStr", "");
|
params.insert("inputStr", "");
|
||||||
params.insert("clientVer", "4100");
|
params.insert("clientVer", "4100");
|
||||||
|
|
||||||
params.insert("clientos", client_os);
|
params.insert("clientos", client_os);
|
||||||
|
params.insert("computer", &self.computer);
|
||||||
if let Some(computer) = &self.computer {
|
|
||||||
params.insert("computer", computer);
|
|
||||||
} else {
|
|
||||||
params.insert("computer", client_os);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(os_version) = &self.os_version {
|
if let Some(os_version) = &self.os_version {
|
||||||
params.insert("os-version", os_version);
|
params.insert("os-version", os_version);
|
||||||
@ -110,7 +101,7 @@ pub struct GpParamsBuilder {
|
|||||||
client_os: ClientOs,
|
client_os: ClientOs,
|
||||||
os_version: Option<String>,
|
os_version: Option<String>,
|
||||||
client_version: Option<String>,
|
client_version: Option<String>,
|
||||||
computer: Option<String>,
|
computer: String,
|
||||||
ignore_tls_errors: bool,
|
ignore_tls_errors: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +112,7 @@ impl GpParamsBuilder {
|
|||||||
client_os: ClientOs::Linux,
|
client_os: ClientOs::Linux,
|
||||||
os_version: Default::default(),
|
os_version: Default::default(),
|
||||||
client_version: Default::default(),
|
client_version: Default::default(),
|
||||||
computer: Default::default(),
|
computer: whoami::hostname(),
|
||||||
ignore_tls_errors: false,
|
ignore_tls_errors: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,7 +138,7 @@ impl GpParamsBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn computer(&mut self, computer: &str) -> &mut Self {
|
pub fn computer(&mut self, computer: &str) -> &mut Self {
|
||||||
self.computer = Some(computer.to_string());
|
self.computer = computer.to_string();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,14 +132,8 @@ pub async fn retrieve_config(
|
|||||||
|
|
||||||
info!("Portal config, user_agent: {}", gp_params.user_agent());
|
info!("Portal config, user_agent: {}", gp_params.user_agent());
|
||||||
|
|
||||||
let res_xml = client
|
let res = client.post(&url).form(¶ms).send().await?;
|
||||||
.post(&url)
|
let res_xml = res.error_for_status()?.text().await?;
|
||||||
.form(¶ms)
|
|
||||||
.send()
|
|
||||||
.await?
|
|
||||||
.error_for_status()?
|
|
||||||
.text()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
ensure!(!res_xml.is_empty(), PortalConfigError::EmptyResponse);
|
ensure!(!res_xml.is_empty(), PortalConfigError::EmptyResponse);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user