Skip to content

Commit

Permalink
Add option to ignore tls errors
Browse files Browse the repository at this point in the history
  • Loading branch information
yuezk committed Jan 21, 2024
1 parent 0e8fb0f commit eaf41ff
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 27 deletions.
30 changes: 26 additions & 4 deletions apps/gpauth/src/auth_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ use tokio_util::sync::CancellationToken;
use webkit2gtk::{
gio::Cancellable,
glib::{GString, TimeSpan},
LoadEvent, SettingsExt, URIResponse, URIResponseExt, WebContextExt, WebResource, WebResourceExt,
WebView, WebViewExt, WebsiteDataManagerExtManual, WebsiteDataTypes,
LoadEvent, SettingsExt, TLSErrorsPolicy, URIResponse, URIResponseExt, WebContextExt, WebResource,
WebResourceExt, WebView, WebViewExt, WebsiteDataManagerExtManual, WebsiteDataTypes,
};

enum AuthDataError {
/// Failed to load page due to TLS error
TlsError,
/// 1. Found auth data in headers/body but it's invalid
/// 2. Loaded an empty page, failed to load page. etc.
Invalid,
Expand Down Expand Up @@ -127,6 +129,12 @@ impl<'a> AuthWindow<'a> {
let saml_request = self.saml_request.to_string();
let (auth_result_tx, mut auth_result_rx) = mpsc::unbounded_channel::<AuthResult>();
let raise_window_cancel_token: Arc<RwLock<Option<CancellationToken>>> = Default::default();
let gp_params = self.gp_params.as_ref().unwrap();
let tls_err_policy = if gp_params.ignore_tls_errors() {
TLSErrorsPolicy::Ignore
} else {
TLSErrorsPolicy::Fail
};

if self.clean {
clear_webview_cookies(window).await?;
Expand All @@ -136,6 +144,10 @@ impl<'a> AuthWindow<'a> {
window.with_webview(move |wv| {
let wv = wv.inner();

if let Some(context) = wv.context() {
context.set_tls_errors_policy(tls_err_policy);
}

if let Some(settings) = wv.settings() {
let ua = settings.user_agent().unwrap_or("".into());
info!("Auth window user agent: {}", ua);
Expand Down Expand Up @@ -176,12 +188,15 @@ impl<'a> AuthWindow<'a> {
}
});

wv.connect_load_failed_with_tls_errors(|_wv, uri, cert, err| {
let auth_result_tx_clone = auth_result_tx.clone();
wv.connect_load_failed_with_tls_errors(move |_wv, uri, cert, err| {
let redacted_uri = redact_uri(uri);
warn!(
"Failed to load uri: {} with error: {}, cert: {}",
redacted_uri, err, cert
);

send_auth_result(&auth_result_tx_clone, Err(AuthDataError::TlsError));
true
});

Expand All @@ -195,12 +210,14 @@ impl<'a> AuthWindow<'a> {
})?;

let portal = self.server.to_string();
let gp_params = self.gp_params.as_ref().unwrap();

loop {
if let Some(auth_result) = auth_result_rx.recv().await {
match auth_result {
Ok(auth_data) => return Ok(auth_data),
Err(AuthDataError::TlsError) => {
return Err(anyhow::anyhow!("TLS error: certificate verify failed"))
}
Err(AuthDataError::NotFound) => {
info!("No auth data found, it may not be the /SAML20/SP/ACS endpoint");

Expand Down Expand Up @@ -406,6 +423,11 @@ fn read_auth_data(main_resource: &WebResource, auth_result_tx: mpsc::UnboundedSe
send_auth_result(&auth_result_tx, auth_result)
});
}
Err(AuthDataError::TlsError) => {
// NOTE: This is unreachable
info!("TLS error found in headers, trying to read from body...");
send_auth_result(&auth_result_tx, Err(AuthDataError::TlsError));
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions apps/gpauth/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,17 @@ struct Cli {
#[arg(long)]
fix_openssl: bool,
#[arg(long)]
ignore_tls_errors: bool,
#[arg(long)]
clean: bool,
}

impl Cli {
async fn run(&mut self) -> anyhow::Result<()> {
if self.ignore_tls_errors {
info!("TLS errors will be ignored");
}

let mut openssl_conf = self.prepare_env()?;

self.server = normalize_server(&self.server)?;
Expand Down Expand Up @@ -95,6 +101,7 @@ impl Cli {
.user_agent(&self.user_agent)
.client_os(ClientOs::from(&self.os))
.os_version(self.os_version.clone())
.ignore_tls_errors(self.ignore_tls_errors)
.build();

gp_params
Expand Down
30 changes: 28 additions & 2 deletions apps/gpclient/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ const VERSION: &str = concat!(
")"
);

pub(crate) struct SharedArgs {
pub(crate) fix_openssl: bool,
pub(crate) ignore_tls_errors: bool,
}

#[derive(Subcommand)]
enum CliCommand {
#[command(about = "Connect to a portal server")]
Expand Down Expand Up @@ -51,6 +56,8 @@ struct Cli {
help = "Get around the OpenSSL `unsafe legacy renegotiation` error"
)]
fix_openssl: bool,
#[arg(long, help = "Ignore the TLS errors")]
ignore_tls_errors: bool,
}

impl Cli {
Expand All @@ -67,9 +74,17 @@ impl Cli {
// The temp file will be dropped automatically when the file handle is dropped
// So, declare it here to ensure it's not dropped
let _file = self.fix_openssl()?;
let shared_args = SharedArgs {
fix_openssl: self.fix_openssl,
ignore_tls_errors: self.ignore_tls_errors,
};

if self.ignore_tls_errors {
info!("TLS errors will be ignored");
}

match &self.command {
CliCommand::Connect(args) => ConnectHandler::new(args, self.fix_openssl).handle().await,
CliCommand::Connect(args) => ConnectHandler::new(args, &shared_args).handle().await,
CliCommand::Disconnect => DisconnectHandler::new().handle(),
CliCommand::LaunchGui(args) => LaunchGuiHandler::new(args).handle().await,
}
Expand All @@ -89,13 +104,24 @@ pub(crate) async fn run() {
if let Err(err) = cli.run().await {
eprintln!("\nError: {}", err);

if err.to_string().contains("unsafe legacy renegotiation") && !cli.fix_openssl {
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") {
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(" "));
}

std::process::exit(1);
}
}
12 changes: 7 additions & 5 deletions apps/gpclient/src/connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use inquire::{Password, PasswordDisplayMode, Select, Text};
use log::info;
use openconnect::Vpn;

use crate::GP_CLIENT_LOCK_FILE;
use crate::{cli::SharedArgs, GP_CLIENT_LOCK_FILE};

#[derive(Args)]
pub(crate) struct ConnectArgs {
Expand Down Expand Up @@ -49,12 +49,12 @@ pub(crate) struct ConnectArgs {

pub(crate) struct ConnectHandler<'a> {
args: &'a ConnectArgs,
fix_openssl: bool,
shared_args: &'a SharedArgs,
}

impl<'a> ConnectHandler<'a> {
pub(crate) fn new(args: &'a ConnectArgs, fix_openssl: bool) -> Self {
Self { args, fix_openssl }
pub(crate) fn new(args: &'a ConnectArgs, shared_args: &'a SharedArgs) -> Self {
Self { args, shared_args }
}

pub(crate) async fn handle(&self) -> anyhow::Result<()> {
Expand All @@ -64,6 +64,7 @@ impl<'a> ConnectHandler<'a> {
.user_agent(&self.args.user_agent)
.client_os(ClientOs::from(&self.args.os))
.os_version(self.args.os_version.clone())
.ignore_tls_errors(self.shared_args.ignore_tls_errors)
.build();

let prelogin = prelogin(&portal, &gp_params).await?;
Expand Down Expand Up @@ -126,7 +127,8 @@ impl<'a> ConnectHandler<'a> {
.os(self.args.os.as_str())
.os_version(self.args.os_version.as_deref())
.hidpi(self.args.hidpi)
.fix_openssl(self.fix_openssl)
.fix_openssl(self.shared_args.fix_openssl)
.ignore_tls_errors(self.shared_args.ignore_tls_errors)
.clean(self.args.clean)
.launch()
.await
Expand Down
15 changes: 14 additions & 1 deletion crates/gpapi/src/gp_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ pub struct GpParams {
os_version: Option<String>,
client_version: Option<String>,
computer: Option<String>,
ignore_tls_errors: bool,
}

impl GpParams {
Expand All @@ -67,9 +68,13 @@ impl GpParams {
}
}

pub fn ignore_tls_errors(&self) -> bool {
self.ignore_tls_errors
}

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();
let client_os = self.client_os.as_str();

// Common params
params.insert("prot", "https:");
Expand Down Expand Up @@ -106,6 +111,7 @@ pub struct GpParamsBuilder {
os_version: Option<String>,
client_version: Option<String>,
computer: Option<String>,
ignore_tls_errors: bool,
}

impl GpParamsBuilder {
Expand All @@ -116,6 +122,7 @@ impl GpParamsBuilder {
os_version: Default::default(),
client_version: Default::default(),
computer: Default::default(),
ignore_tls_errors: false,
}
}

Expand Down Expand Up @@ -144,13 +151,19 @@ impl GpParamsBuilder {
self
}

pub fn ignore_tls_errors(&mut self, ignore_tls_errors: bool) -> &mut Self {
self.ignore_tls_errors = ignore_tls_errors;
self
}

pub fn build(&self) -> GpParams {
GpParams {
user_agent: self.user_agent.clone(),
client_os: self.client_os.clone(),
os_version: self.os_version.clone(),
client_version: self.client_version.clone(),
computer: self.computer.clone(),
ignore_tls_errors: self.ignore_tls_errors,
}
}
}
Expand Down
19 changes: 7 additions & 12 deletions crates/gpapi/src/portal/prelogin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,18 +101,13 @@ pub async fn prelogin(portal: &str, gp_params: &GpParams) -> anyhow::Result<Prel
.any(|required_param| required_param == k)
});

println!("params: {:?}", params);

let client = Client::builder().user_agent(user_agent).build()?;

let res_xml = client
.post(&prelogin_url)
.form(&params)
.send()
.await?
.error_for_status()?
.text()
.await?;
let client = Client::builder()
.danger_accept_invalid_certs(gp_params.ignore_tls_errors())
.user_agent(user_agent)
.build()?;

let res = client.post(&prelogin_url).form(&params).send().await?;
let res_xml = res.error_for_status()?.text().await?;

trace!("Prelogin response: {}", res_xml);
let doc = Document::parse(&res_xml)?;
Expand Down
15 changes: 13 additions & 2 deletions crates/gpapi/src/process/auth_launcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub struct SamlAuthLauncher<'a> {
os_version: Option<&'a str>,
hidpi: bool,
fix_openssl: bool,
ignore_tls_errors: bool,
clean: bool,
}

Expand All @@ -27,6 +28,7 @@ impl<'a> SamlAuthLauncher<'a> {
os_version: None,
hidpi: false,
fix_openssl: false,
ignore_tls_errors: false,
clean: false,
}
}
Expand Down Expand Up @@ -61,6 +63,11 @@ impl<'a> SamlAuthLauncher<'a> {
self
}

pub fn ignore_tls_errors(mut self, ignore_tls_errors: bool) -> Self {
self.ignore_tls_errors = ignore_tls_errors;
self
}

pub fn clean(mut self, clean: bool) -> Self {
self.clean = clean;
self
Expand All @@ -87,12 +94,16 @@ impl<'a> SamlAuthLauncher<'a> {
auth_cmd.arg("--os-version").arg(os_version);
}

if self.hidpi {
auth_cmd.arg("--hidpi");
}

if self.fix_openssl {
auth_cmd.arg("--fix-openssl");
}

if self.hidpi {
auth_cmd.arg("--hidpi");
if self.ignore_tls_errors {
auth_cmd.arg("--ignore-tls-errors");
}

if self.clean {
Expand Down
1 change: 0 additions & 1 deletion crates/gpapi/src/utils/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ pub fn raise_window(win: &Window) -> anyhow::Result<()> {
}
let title = win.title()?;
tokio::spawn(async move {
info!("Raising window: {}", title);
if let Err(err) = wmctrl_raise_window(&title).await {
warn!("Failed to raise window: {}", err);
}
Expand Down

0 comments on commit eaf41ff

Please sign in to comment.