mirror of
				https://github.com/yuezk/GlobalProtect-openconnect.git
				synced 2025-05-20 07:26:58 -04:00 
			
		
		
		
	upgrade gpauth
This commit is contained in:
		@@ -1,5 +1,6 @@
 | 
			
		||||
[package]
 | 
			
		||||
name = "gpclient"
 | 
			
		||||
rust-version.workspace = true
 | 
			
		||||
authors.workspace = true
 | 
			
		||||
version.workspace = true
 | 
			
		||||
edition.workspace = true
 | 
			
		||||
@@ -9,10 +10,11 @@ license.workspace = true
 | 
			
		||||
common = { path = "../../crates/common" }
 | 
			
		||||
gpapi = { path = "../../crates/gpapi", features = ["clap"] }
 | 
			
		||||
openconnect = { path = "../../crates/openconnect" }
 | 
			
		||||
 | 
			
		||||
anyhow.workspace = true
 | 
			
		||||
clap.workspace = true
 | 
			
		||||
env_logger.workspace = true
 | 
			
		||||
inquire = "0.6.2"
 | 
			
		||||
inquire = "0.7"
 | 
			
		||||
log.workspace = true
 | 
			
		||||
tokio.workspace = true
 | 
			
		||||
sysinfo.workspace = true
 | 
			
		||||
@@ -22,3 +24,7 @@ tempfile.workspace = true
 | 
			
		||||
reqwest.workspace = true
 | 
			
		||||
directories = "5.0"
 | 
			
		||||
compile-time.workspace = true
 | 
			
		||||
 | 
			
		||||
[features]
 | 
			
		||||
default = ["webview-auth"]
 | 
			
		||||
webview-auth = ["gpapi/webview-auth"]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,10 @@
 | 
			
		||||
use std::{env::temp_dir, fs::File};
 | 
			
		||||
 | 
			
		||||
use clap::{Parser, Subcommand};
 | 
			
		||||
use gpapi::utils::openssl;
 | 
			
		||||
use gpapi::{
 | 
			
		||||
  clap::{handle_error, Args},
 | 
			
		||||
  utils::openssl,
 | 
			
		||||
};
 | 
			
		||||
use log::{info, LevelFilter};
 | 
			
		||||
use tempfile::NamedTempFile;
 | 
			
		||||
 | 
			
		||||
@@ -50,12 +53,25 @@ struct Cli {
 | 
			
		||||
  #[command(subcommand)]
 | 
			
		||||
  command: CliCommand,
 | 
			
		||||
 | 
			
		||||
  #[arg(long, help = "Uses extended compatibility mode for OpenSSL operations to support a broader range of systems and formats.")]
 | 
			
		||||
  #[arg(
 | 
			
		||||
    long,
 | 
			
		||||
    help = "Uses extended compatibility mode for OpenSSL operations to support a broader range of systems and formats."
 | 
			
		||||
  )]
 | 
			
		||||
  fix_openssl: bool,
 | 
			
		||||
  #[arg(long, help = "Ignore the TLS errors")]
 | 
			
		||||
  ignore_tls_errors: bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Args for Cli {
 | 
			
		||||
  fn fix_openssl(&self) -> bool {
 | 
			
		||||
    self.fix_openssl
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn ignore_tls_errors(&self) -> bool {
 | 
			
		||||
    self.ignore_tls_errors
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Cli {
 | 
			
		||||
  fn fix_openssl(&self) -> anyhow::Result<Option<NamedTempFile>> {
 | 
			
		||||
    if self.fix_openssl {
 | 
			
		||||
@@ -113,24 +129,7 @@ pub(crate) async fn run() {
 | 
			
		||||
  info!("gpclient started: {}", VERSION);
 | 
			
		||||
 | 
			
		||||
  if let Err(err) = cli.run().await {
 | 
			
		||||
    eprintln!("\nError: {}", err);
 | 
			
		||||
 | 
			
		||||
    let err = err.to_string();
 | 
			
		||||
 | 
			
		||||
    if err.contains("unsafe legacy renegotiation") && !cli.fix_openssl {
 | 
			
		||||
      eprintln!("\nRe-run it with the `--fix-openssl` option to work around this issue, e.g.:\n");
 | 
			
		||||
      // Print the command
 | 
			
		||||
      let args = std::env::args().collect::<Vec<_>>();
 | 
			
		||||
      eprintln!("{} --fix-openssl {}\n", args[0], args[1..].join(" "));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if err.contains("certificate verify failed") && !cli.ignore_tls_errors {
 | 
			
		||||
      eprintln!("\nRe-run it with the `--ignore-tls-errors` option to ignore the certificate error, e.g.:\n");
 | 
			
		||||
      // Print the command
 | 
			
		||||
      let args = std::env::args().collect::<Vec<_>>();
 | 
			
		||||
      eprintln!("{} --ignore-tls-errors {}\n", args[0], args[1..].join(" "));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    handle_error(err, &cli);
 | 
			
		||||
    std::process::exit(1);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -93,12 +93,15 @@ pub(crate) struct ConnectArgs {
 | 
			
		||||
  #[arg(long, help = "Disable DTLS and ESP")]
 | 
			
		||||
  no_dtls: bool,
 | 
			
		||||
 | 
			
		||||
  #[cfg(feature = "webview-auth")]
 | 
			
		||||
  #[arg(long, help = "The HiDPI mode, useful for high-resolution screens")]
 | 
			
		||||
  hidpi: bool,
 | 
			
		||||
 | 
			
		||||
  #[cfg(feature = "webview-auth")]
 | 
			
		||||
  #[arg(long, help = "Do not reuse the remembered authentication cookie")]
 | 
			
		||||
  clean: bool,
 | 
			
		||||
 | 
			
		||||
  #[cfg(feature = "webview-auth")]
 | 
			
		||||
  #[arg(long, help = "Use the default browser to authenticate")]
 | 
			
		||||
  default_browser: bool,
 | 
			
		||||
 | 
			
		||||
@@ -151,6 +154,7 @@ impl<'a> ConnectHandler<'a> {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pub(crate) async fn handle(&self) -> anyhow::Result<()> {
 | 
			
		||||
    #[cfg(feature = "webview-auth")]
 | 
			
		||||
    if self.args.default_browser && self.args.browser.is_some() {
 | 
			
		||||
      bail!("Cannot use `--default-browser` and `--browser` options at the same time");
 | 
			
		||||
    }
 | 
			
		||||
@@ -343,28 +347,34 @@ impl<'a> ConnectHandler<'a> {
 | 
			
		||||
 | 
			
		||||
    match prelogin {
 | 
			
		||||
      Prelogin::Saml(prelogin) => {
 | 
			
		||||
        let use_default_browser = prelogin.support_default_browser() && self.args.default_browser;
 | 
			
		||||
        let browser = if prelogin.support_default_browser() {
 | 
			
		||||
          self.args.browser.as_deref()
 | 
			
		||||
        } else if !cfg!(feature = "webview-auth") {
 | 
			
		||||
          bail!("The server does not support authentication via the default browser and the gpclient is not built with the `webview-auth` feature");
 | 
			
		||||
        } else {
 | 
			
		||||
          None
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let cred = SamlAuthLauncher::new(&self.args.server)
 | 
			
		||||
        let os_version = self.args.os_version();
 | 
			
		||||
        let auth_launcher = SamlAuthLauncher::new(&self.args.server)
 | 
			
		||||
          .gateway(is_gateway)
 | 
			
		||||
          .saml_request(prelogin.saml_request())
 | 
			
		||||
          .user_agent(&self.args.user_agent)
 | 
			
		||||
          .os(self.args.os.as_str())
 | 
			
		||||
          .os_version(Some(&self.args.os_version()))
 | 
			
		||||
          .hidpi(self.args.hidpi)
 | 
			
		||||
          .os_version(Some(&os_version))
 | 
			
		||||
          .fix_openssl(self.shared_args.fix_openssl)
 | 
			
		||||
          .ignore_tls_errors(self.shared_args.ignore_tls_errors)
 | 
			
		||||
          .clean(self.args.clean)
 | 
			
		||||
          .default_browser(use_default_browser)
 | 
			
		||||
          .browser(browser)
 | 
			
		||||
          .launch()
 | 
			
		||||
          .await?;
 | 
			
		||||
          .browser(browser);
 | 
			
		||||
 | 
			
		||||
        #[cfg(feature = "webview-auth")]
 | 
			
		||||
        let use_default_browser = prelogin.support_default_browser() && self.args.default_browser;
 | 
			
		||||
        #[cfg(feature = "webview-auth")]
 | 
			
		||||
        let auth_launcher = auth_launcher
 | 
			
		||||
          .hidpi(self.args.hidpi)
 | 
			
		||||
          .clean(self.args.clean)
 | 
			
		||||
          .default_browser(use_default_browser);
 | 
			
		||||
 | 
			
		||||
        let cred = auth_launcher.launch().await?;
 | 
			
		||||
        Ok(cred)
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ use directories::ProjectDirs;
 | 
			
		||||
use gpapi::{
 | 
			
		||||
  process::service_launcher::ServiceLauncher,
 | 
			
		||||
  utils::{endpoint::http_endpoint, env_utils, shutdown_signal},
 | 
			
		||||
  GP_CALLBACK_PORT_FILENAME,
 | 
			
		||||
};
 | 
			
		||||
use log::info;
 | 
			
		||||
use tokio::io::AsyncWriteExt;
 | 
			
		||||
@@ -80,12 +81,7 @@ impl<'a> LaunchGuiHandler<'a> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async fn feed_auth_data(auth_data: &str) -> anyhow::Result<()> {
 | 
			
		||||
  let (res_gui, res_cli) = tokio::join!(feed_auth_data_gui(auth_data), feed_auth_data_cli(auth_data));
 | 
			
		||||
  if let Err(err) = res_gui {
 | 
			
		||||
    info!("Failed to feed auth data to the GUI: {}", err);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if let Err(err) = res_cli {
 | 
			
		||||
  if let Err(err) = feed_auth_data_cli(auth_data).await {
 | 
			
		||||
    info!("Failed to feed auth data to the CLI: {}", err);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -98,24 +94,10 @@ async fn feed_auth_data(auth_data: &str) -> anyhow::Result<()> {
 | 
			
		||||
  Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async fn feed_auth_data_gui(auth_data: &str) -> anyhow::Result<()> {
 | 
			
		||||
  info!("Feeding auth data to the GUI");
 | 
			
		||||
  let service_endpoint = http_endpoint().await?;
 | 
			
		||||
 | 
			
		||||
  reqwest::Client::default()
 | 
			
		||||
    .post(format!("{}/auth-data", service_endpoint))
 | 
			
		||||
    .body(auth_data.to_string())
 | 
			
		||||
    .send()
 | 
			
		||||
    .await?
 | 
			
		||||
    .error_for_status()?;
 | 
			
		||||
 | 
			
		||||
  Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async fn feed_auth_data_cli(auth_data: &str) -> anyhow::Result<()> {
 | 
			
		||||
  info!("Feeding auth data to the CLI");
 | 
			
		||||
 | 
			
		||||
  let port_file = temp_dir().join("gpcallback.port");
 | 
			
		||||
  let port_file = temp_dir().join(GP_CALLBACK_PORT_FILENAME);
 | 
			
		||||
  let port = tokio::fs::read_to_string(port_file).await?;
 | 
			
		||||
  let mut stream = tokio::net::TcpStream::connect(format!("127.0.0.1:{}", port.trim())).await?;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user