From ad02a6bb00df8760d6dbd11a02391a74643e9614 Mon Sep 17 00:00:00 2001 From: Tokarak <63452145+Tokarak@users.noreply.github.com> Date: Fri, 20 Sep 2024 17:29:13 +0100 Subject: [PATCH 01/15] POC: disable cert verification --- Cargo.lock | 1 + Cargo.toml | 1 + src/client.rs | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a7dfbc00..286763d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1240,6 +1240,7 @@ dependencies = [ "route-recognizer", "rss", "rust-embed", + "rustls", "sealed_test", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 451a83a9..609b521a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ pretty_env_logger = "0.5.0" dotenvy = "0.15.7" rss = "2.0.7" arc-swap = "1.7.1" +rustls = { version = "0.21.12", features = ["dangerous_configuration"] } [dev-dependencies] diff --git a/src/client.rs b/src/client.rs index d4701ba5..3093fa36 100644 --- a/src/client.rs +++ b/src/client.rs @@ -7,6 +7,7 @@ use hyper::header::HeaderValue; use hyper::StatusCode; use hyper::{body, body::Buf, client, header, Body, Client, Method, Request, Response, Uri}; use hyper_rustls::HttpsConnector; +use rustls::ClientConfig; use libflate::gzip; use log::{error, trace, warn}; use once_cell::sync::Lazy; @@ -16,7 +17,7 @@ use serde_json::Value; use std::sync::atomic::Ordering; use std::sync::atomic::{AtomicBool, AtomicU16}; use std::{io, result::Result}; - +use std::sync::Arc; use crate::dbg_msg; use crate::oauth::{force_refresh_token, token_daemon, Oauth}; use crate::server::RequestExt; @@ -26,7 +27,34 @@ const REDDIT_URL_BASE: &str = "https://oauth.reddit.com"; const ALTERNATIVE_REDDIT_URL_BASE: &str = "https://www.reddit.com"; pub static CLIENT: Lazy>> = Lazy::new(|| { - let https = hyper_rustls::HttpsConnectorBuilder::new().with_native_roots().https_only().enable_http1().build(); + // let https = hyper_rustls::HttpsConnectorBuilder::new().with_native_roots().https_only().enable_http1().build(); + + // A custom certificate verifier that does nothing. + struct NoCertificateVerification; + + impl rustls::client::ServerCertVerifier for NoCertificateVerification { + fn verify_server_cert( + &self, + _: &rustls::Certificate, + _: &[rustls::Certificate], + _: &rustls::ServerName, + _: &mut dyn Iterator, + _: &[u8], + _: std::time::SystemTime, + ) -> Result { + Ok(rustls::client::ServerCertVerified::assertion()) + } + } + + let mut config = ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(rustls::RootCertStore::empty()) + .with_no_client_auth(); + + config.dangerous().set_certificate_verifier(Arc::new(NoCertificateVerification)); + let https = hyper_rustls::HttpsConnectorBuilder::new() + .with_tls_config(config) + .https_only().enable_http1().build(); client::Client::builder().build(https) }); From a5e1380876293b87089dc9933fcd3e23d24ab2ce Mon Sep 17 00:00:00 2001 From: Tokarak <63452145+Tokarak@users.noreply.github.com> Date: Fri, 20 Sep 2024 17:45:51 +0100 Subject: [PATCH 02/15] Formatting and import scope changes --- src/client.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/client.rs b/src/client.rs index 3093fa36..ca87a961 100644 --- a/src/client.rs +++ b/src/client.rs @@ -7,7 +7,6 @@ use hyper::header::HeaderValue; use hyper::StatusCode; use hyper::{body, body::Buf, client, header, Body, Client, Method, Request, Response, Uri}; use hyper_rustls::HttpsConnector; -use rustls::ClientConfig; use libflate::gzip; use log::{error, trace, warn}; use once_cell::sync::Lazy; @@ -17,7 +16,7 @@ use serde_json::Value; use std::sync::atomic::Ordering; use std::sync::atomic::{AtomicBool, AtomicU16}; use std::{io, result::Result}; -use std::sync::Arc; + use crate::dbg_msg; use crate::oauth::{force_refresh_token, token_daemon, Oauth}; use crate::server::RequestExt; @@ -29,6 +28,9 @@ const ALTERNATIVE_REDDIT_URL_BASE: &str = "https://www.reddit.com"; pub static CLIENT: Lazy>> = Lazy::new(|| { // let https = hyper_rustls::HttpsConnectorBuilder::new().with_native_roots().https_only().enable_http1().build(); + use rustls::ClientConfig; + use std::sync::Arc; + // A custom certificate verifier that does nothing. struct NoCertificateVerification; @@ -52,9 +54,7 @@ pub static CLIENT: Lazy>> = Lazy::new(|| { .with_no_client_auth(); config.dangerous().set_certificate_verifier(Arc::new(NoCertificateVerification)); - let https = hyper_rustls::HttpsConnectorBuilder::new() - .with_tls_config(config) - .https_only().enable_http1().build(); + let https = hyper_rustls::HttpsConnectorBuilder::new().with_tls_config(config).https_only().enable_http1().build(); client::Client::builder().build(https) }); From 98079086a5d82f37af16ed5e7d9c44d520071bb4 Mon Sep 17 00:00:00 2001 From: Tokarak <63452145+Tokarak@users.noreply.github.com> Date: Fri, 20 Sep 2024 18:31:23 +0100 Subject: [PATCH 03/15] Refactor: new feature "no-https-verification" --- Cargo.toml | 3 +++ src/client.rs | 58 ++++++++++++++++++++++++++++----------------------- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 609b521a..d3d0f793 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,9 @@ authors = [ ] edition = "2021" +[features] +no-https-verification = [] + [dependencies] askama = { version = "0.12.1", default-features = false } cached = { version = "0.51.3", features = ["async"] } diff --git a/src/client.rs b/src/client.rs index ca87a961..69a98a92 100644 --- a/src/client.rs +++ b/src/client.rs @@ -26,35 +26,41 @@ const REDDIT_URL_BASE: &str = "https://oauth.reddit.com"; const ALTERNATIVE_REDDIT_URL_BASE: &str = "https://www.reddit.com"; pub static CLIENT: Lazy>> = Lazy::new(|| { - // let https = hyper_rustls::HttpsConnectorBuilder::new().with_native_roots().https_only().enable_http1().build(); - - use rustls::ClientConfig; - use std::sync::Arc; - - // A custom certificate verifier that does nothing. - struct NoCertificateVerification; - - impl rustls::client::ServerCertVerifier for NoCertificateVerification { - fn verify_server_cert( - &self, - _: &rustls::Certificate, - _: &[rustls::Certificate], - _: &rustls::ServerName, - _: &mut dyn Iterator, - _: &[u8], - _: std::time::SystemTime, - ) -> Result { - Ok(rustls::client::ServerCertVerified::assertion()) + // Use native certificates to verify requests to reddit + #[cfg(not(feature = "no-https-verification"))] + let https = hyper_rustls::HttpsConnectorBuilder::new().with_native_roots().https_only().enable_http1().build(); + + // If https verification is disabled for debug purposes, create a custom ClientConfig + #[cfg(feature = "no-https-verification")] + let https = { + use rustls::ClientConfig; + use std::sync::Arc; + + // A custom certificate verifier that does nothing. + struct NoCertificateVerification; + + impl rustls::client::ServerCertVerifier for NoCertificateVerification { + fn verify_server_cert( + &self, + _: &rustls::Certificate, + _: &[rustls::Certificate], + _: &rustls::ServerName, + _: &mut dyn Iterator, + _: &[u8], + _: std::time::SystemTime, + ) -> Result { + Ok(rustls::client::ServerCertVerified::assertion()) + } } - } - let mut config = ClientConfig::builder() - .with_safe_defaults() - .with_root_certificates(rustls::RootCertStore::empty()) - .with_no_client_auth(); + let mut config = ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(rustls::RootCertStore::empty()) + .with_no_client_auth(); - config.dangerous().set_certificate_verifier(Arc::new(NoCertificateVerification)); - let https = hyper_rustls::HttpsConnectorBuilder::new().with_tls_config(config).https_only().enable_http1().build(); + config.dangerous().set_certificate_verifier(Arc::new(NoCertificateVerification)); + hyper_rustls::HttpsConnectorBuilder::new().with_tls_config(config).https_only().enable_http1().build() + }; client::Client::builder().build(https) }); From f392b37339a29ae8dc70403bc3755e04712c23ce Mon Sep 17 00:00:00 2001 From: Tokarak <63452145+Tokarak@users.noreply.github.com> Date: Sat, 21 Sep 2024 18:23:29 +0100 Subject: [PATCH 04/15] Add cli flag `--no-https-verification` Throws error when the flag is enabled and the eponymous feature is disabled. Currently not linked to any underlying functionality. --- src/main.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 406a0d3f..79307bbe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -119,7 +119,7 @@ async fn main() { // Initialize logger pretty_env_logger::init(); - let matches = Command::new("Redlib") + let mut cmd = Command::new("Redlib") .version(env!("CARGO_PKG_VERSION")) .about("Private front-end for Reddit written in Rust ") .arg( @@ -158,7 +158,23 @@ async fn main() { .default_value("604800") .num_args(1), ) - .get_matches(); + .arg( + Arg::new("no-https-verification") + .long("no-https-verification") + .help("Disables HTTPS certificate verification between the instance and reddit. This can be useful to debug the HTTPS connection with an HTTPS sniffer. Only works when the 'no-https-verification' feature is enabled at compile time.") + .num_args(0), + ); + let matches = cmd.get_matches_mut(); + + #[cfg(not(feature = "no-https-verification"))] + if matches.contains_id("no-https-verification") { + cmd + .error( + clap::error::ErrorKind::InvalidValue, + "`--no-https-verification` can only be enabled if the `no-https-verification` feature is enabled", + ) + .exit() + } let address = matches.get_one::("address").unwrap(); let port = matches.get_one::("port").unwrap(); From edb16f29ce5d9b79f3683d2264260eb191893ffe Mon Sep 17 00:00:00 2001 From: Tokarak <63452145+Tokarak@users.noreply.github.com> Date: Sat, 21 Sep 2024 18:32:16 +0100 Subject: [PATCH 05/15] Enable deafult clap-rs features --- Cargo.lock | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 5 ++--- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 286763d6..b9ee4f20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,12 +65,55 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + [[package]] name = "anstyle" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "arc-swap" version = "1.7.1" @@ -303,8 +346,10 @@ version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ + "anstream", "anstyle", "clap_lex", + "strsim 0.11.1", ] [[package]] @@ -313,6 +358,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + [[package]] name = "cookie" version = "0.18.1" @@ -888,6 +939,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itoa" version = "1.0.11" @@ -1927,6 +1984,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "1.9.1" diff --git a/Cargo.toml b/Cargo.toml index d3d0f793..a6213643 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,9 +16,8 @@ no-https-verification = [] [dependencies] askama = { version = "0.12.1", default-features = false } cached = { version = "0.51.3", features = ["async"] } -clap = { version = "4.4.11", default-features = false, features = [ - "std", - "env", +clap = { version = "4.4.11", features = [ + "env" ] } regex = "1.10.2" serde = { version = "1.0.193", features = ["derive"] } From 9e2dc50d6ecac6eb5afd2cff450a179bd4ee6d0e Mon Sep 17 00:00:00 2001 From: Matthew Esposito Date: Mon, 23 Sep 2024 10:44:17 -0400 Subject: [PATCH 06/15] fix(client): use boolean flag --- src/client.rs | 37 ++++++++++++++++++++++--------------- src/main.rs | 5 ++++- src/oauth.rs | 2 +- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/client.rs b/src/client.rs index 69a98a92..e9d82d71 100644 --- a/src/client.rs +++ b/src/client.rs @@ -15,6 +15,7 @@ use serde_json::Value; use std::sync::atomic::Ordering; use std::sync::atomic::{AtomicBool, AtomicU16}; +use std::sync::OnceLock; use std::{io, result::Result}; use crate::dbg_msg; @@ -25,14 +26,28 @@ use crate::utils::format_url; const REDDIT_URL_BASE: &str = "https://oauth.reddit.com"; const ALTERNATIVE_REDDIT_URL_BASE: &str = "https://www.reddit.com"; -pub static CLIENT: Lazy>> = Lazy::new(|| { +pub static CLIENT: OnceLock>> = OnceLock::new(); + +pub static OAUTH_CLIENT: Lazy> = Lazy::new(|| { + let client = block_on(Oauth::new()); + tokio::spawn(token_daemon()); + ArcSwap::new(client.into()) +}); + +pub static OAUTH_RATELIMIT_REMAINING: AtomicU16 = AtomicU16::new(99); + +pub static OAUTH_IS_ROLLING_OVER: AtomicBool = AtomicBool::new(false); + +/// Generate a client given a flag. +#[allow(unused_variables)] +pub fn generate_client(no_https_verification: bool) -> Client> { // Use native certificates to verify requests to reddit #[cfg(not(feature = "no-https-verification"))] let https = hyper_rustls::HttpsConnectorBuilder::new().with_native_roots().https_only().enable_http1().build(); // If https verification is disabled for debug purposes, create a custom ClientConfig #[cfg(feature = "no-https-verification")] - let https = { + let https = if no_https_verification { use rustls::ClientConfig; use std::sync::Arc; @@ -60,19 +75,11 @@ pub static CLIENT: Lazy>> = Lazy::new(|| { config.dangerous().set_certificate_verifier(Arc::new(NoCertificateVerification)); hyper_rustls::HttpsConnectorBuilder::new().with_tls_config(config).https_only().enable_http1().build() + } else { + hyper_rustls::HttpsConnectorBuilder::new().with_native_roots().https_only().enable_http1().build() }; client::Client::builder().build(https) -}); - -pub static OAUTH_CLIENT: Lazy> = Lazy::new(|| { - let client = block_on(Oauth::new()); - tokio::spawn(token_daemon()); - ArcSwap::new(client.into()) -}); - -pub static OAUTH_RATELIMIT_REMAINING: AtomicU16 = AtomicU16::new(99); - -pub static OAUTH_IS_ROLLING_OVER: AtomicBool = AtomicBool::new(false); +} /// Gets the canonical path for a resource on Reddit. This is accomplished by /// making a `HEAD` request to Reddit at the path given in `path`. @@ -155,7 +162,7 @@ async fn stream(url: &str, req: &Request) -> Result, String let parsed_uri = url.parse::().map_err(|_| "Couldn't parse URL".to_string())?; // Build the hyper client from the HTTPS connector. - let client: Client<_, Body> = CLIENT.clone(); + let client: Client<_, Body> = CLIENT.get().unwrap().clone(); let mut builder = Request::get(parsed_uri); @@ -211,7 +218,7 @@ fn request(method: &'static Method, path: String, redirect: bool, quarantine: bo let url = format!("{REDDIT_URL_BASE}{path}"); // Construct the hyper client from the HTTPS connector. - let client: Client<_, Body> = CLIENT.clone(); + let client: Client<_, Body> = CLIENT.get().unwrap().clone(); let (token, vendor_id, device_id, user_agent, loid) = { let client = OAUTH_CLIENT.load_full(); diff --git a/src/main.rs b/src/main.rs index 79307bbe..ef5456b6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,7 +22,7 @@ use futures_lite::FutureExt; use hyper::{header::HeaderValue, Body, Request, Response}; mod client; -use client::{canonical_path, proxy}; +use client::{canonical_path, generate_client, proxy, CLIENT}; use log::info; use once_cell::sync::Lazy; use server::RequestExt; @@ -179,6 +179,7 @@ async fn main() { let address = matches.get_one::("address").unwrap(); let port = matches.get_one::("port").unwrap(); let hsts = matches.get_one("hsts").map(|m: &String| m.as_str()); + let no_https_verification = matches.contains_id("no-https-verification"); let listener = [address, ":", port].concat(); @@ -199,6 +200,8 @@ async fn main() { Lazy::force(&instance_info::INSTANCE_INFO); info!("Creating OAUTH client."); Lazy::force(&OAUTH_CLIENT); + info!("Creating HTTP client."); + CLIENT.set(generate_client(no_https_verification)).unwrap(); // Define default headers (added to all responses) app.default_headers = headers! { diff --git a/src/oauth.rs b/src/oauth.rs index efdf41e7..08e46520 100644 --- a/src/oauth.rs +++ b/src/oauth.rs @@ -70,7 +70,7 @@ impl Oauth { let request = builder.body(body).unwrap(); // Send request - let client: client::Client<_, Body> = CLIENT.clone(); + let client: client::Client<_, Body> = CLIENT.get().unwrap().clone(); let resp = client.request(request).await.ok()?; // Parse headers - loid header _should_ be saved sent on subsequent token refreshes. From 3323c0273cd2ba4c733ab6a7dcdff33f12e02dfd Mon Sep 17 00:00:00 2001 From: Matthew Esposito Date: Mon, 23 Sep 2024 10:47:53 -0400 Subject: [PATCH 07/15] fix(client): Fix ordering of evaluations --- src/client.rs | 1 + src/main.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/client.rs b/src/client.rs index e9d82d71..885ab992 100644 --- a/src/client.rs +++ b/src/client.rs @@ -48,6 +48,7 @@ pub fn generate_client(no_https_verification: bool) -> Client Date: Mon, 23 Sep 2024 11:02:12 -0400 Subject: [PATCH 08/15] fix(tests): enable manual constructor for all tests with ctor --- Cargo.lock | 11 +++++++++++ Cargo.toml | 1 + src/main.rs | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index b9ee4f20..e3fd1a2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -427,6 +427,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "ctor" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" +dependencies = [ + "quote", + "syn 2.0.68", +] + [[package]] name = "darling" version = "0.14.4" @@ -1282,6 +1292,7 @@ dependencies = [ "cached", "clap", "cookie", + "ctor", "dotenvy", "fastrand", "futures-lite", diff --git a/Cargo.toml b/Cargo.toml index a6213643..d94a8d5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,7 @@ dotenvy = "0.15.7" rss = "2.0.7" arc-swap = "1.7.1" rustls = { version = "0.21.12", features = ["dangerous_configuration"] } +ctor = "0.2.8" [dev-dependencies] diff --git a/src/main.rs b/src/main.rs index 830c17ce..9fe00311 100644 --- a/src/main.rs +++ b/src/main.rs @@ -405,3 +405,9 @@ async fn main() { eprintln!("Server error: {e}"); } } + +#[cfg(test)] +#[ctor::ctor] +fn init() { + CLIENT.set(generate_client(false)).unwrap(); +} From b51a7a346df6001cfd0802e852728d8ae2176438 Mon Sep 17 00:00:00 2001 From: Matthew Esposito Date: Mon, 23 Sep 2024 11:04:41 -0400 Subject: [PATCH 09/15] fix(main): update clap args to fix invalidvalue check --- src/main.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 9fe00311..50458db2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -161,8 +161,7 @@ async fn main() { .arg( Arg::new("no-https-verification") .long("no-https-verification") - .help("Disables HTTPS certificate verification between the instance and reddit. This can be useful to debug the HTTPS connection with an HTTPS sniffer. Only works when the 'no-https-verification' feature is enabled at compile time.") - .num_args(0), + .help("Disables HTTPS certificate verification between the instance and reddit. This can be useful to debug the HTTPS connection with an HTTPS sniffer. Only works when the 'no-https-verification' feature is enabled at compile time."), ); let matches = cmd.get_matches_mut(); From 78aa92a17189aab12dd7ef2ee7124780a6591c24 Mon Sep 17 00:00:00 2001 From: Tokarak <63452145+Tokarak@users.noreply.github.com> Date: Sun, 20 Oct 2024 15:24:21 +0100 Subject: [PATCH 10/15] Revert "fix(main): update clap args to fix invalidvalue check" This reverts commit b51a7a346df6001cfd0802e852728d8ae2176438. --- src/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 50458db2..9fe00311 100644 --- a/src/main.rs +++ b/src/main.rs @@ -161,7 +161,8 @@ async fn main() { .arg( Arg::new("no-https-verification") .long("no-https-verification") - .help("Disables HTTPS certificate verification between the instance and reddit. This can be useful to debug the HTTPS connection with an HTTPS sniffer. Only works when the 'no-https-verification' feature is enabled at compile time."), + .help("Disables HTTPS certificate verification between the instance and reddit. This can be useful to debug the HTTPS connection with an HTTPS sniffer. Only works when the 'no-https-verification' feature is enabled at compile time.") + .num_args(0), ); let matches = cmd.get_matches_mut(); From 8bda5c0d374792511aa918e877b57115bb9bf1cd Mon Sep 17 00:00:00 2001 From: Tokarak <63452145+Tokarak@users.noreply.github.com> Date: Sun, 20 Oct 2024 17:53:45 +0100 Subject: [PATCH 11/15] Use OnceLock for global `VERIFY_HTTPS` --- src/client.rs | 5 +++-- src/main.rs | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/client.rs b/src/client.rs index 4b0157db..51506b0f 100644 --- a/src/client.rs +++ b/src/client.rs @@ -32,6 +32,7 @@ const ALTERNATIVE_REDDIT_URL_BASE: &str = "https://www.reddit.com"; const ALTERNATIVE_REDDIT_URL_BASE_HOST: &str = "www.reddit.com"; pub static CLIENT: OnceLock>> = OnceLock::new(); +pub static VERIFY_HTTPS: OnceLock = OnceLock::new(); pub static OAUTH_CLIENT: Lazy> = Lazy::new(|| { let client = block_on(Oauth::new()); @@ -50,14 +51,14 @@ static URL_PAIRS: [(&str, &str); 2] = [ /// Generate a client given a flag. #[allow(unused_variables)] -pub fn generate_client(no_https_verification: bool) -> Client> { +pub fn generate_client(https_verification: bool) -> Client> { // Use native certificates to verify requests to reddit #[cfg(not(feature = "no-https-verification"))] let https = hyper_rustls::HttpsConnectorBuilder::new().with_native_roots().https_only().enable_http1().build(); // If https verification is disabled for debug purposes, create a custom ClientConfig #[cfg(feature = "no-https-verification")] - let https = if no_https_verification { + let https = if ! https_verification { log::warn!("HTTPS verification is disabled."); use rustls::ClientConfig; use std::sync::Arc; diff --git a/src/main.rs b/src/main.rs index 561d5f76..781fd2f3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,7 +28,7 @@ use once_cell::sync::Lazy; use server::RequestExt; use utils::{error, redirect, ThemeAssets}; -use crate::client::OAUTH_CLIENT; +use crate::client::{OAUTH_CLIENT, VERIFY_HTTPS}; mod server; @@ -179,7 +179,7 @@ async fn main() { let address = matches.get_one::("address").unwrap(); let port = matches.get_one::("port").unwrap(); let hsts = matches.get_one("hsts").map(|m: &String| m.as_str()); - let no_https_verification = matches.contains_id("no-https-verification"); + VERIFY_HTTPS.set(! matches.contains_id("no-https-verification")).unwrap(); let listener = [address, ":", port].concat(); @@ -195,7 +195,7 @@ async fn main() { // at first request info!("Creating HTTP client."); - CLIENT.set(generate_client(no_https_verification)).unwrap(); + CLIENT.set(generate_client(*VERIFY_HTTPS.get().unwrap())).unwrap(); info!("Evaluating config."); Lazy::force(&config::CONFIG); info!("Evaluating instance info."); From 0c7cb106552c8547ca33f4852a679600f79d6528 Mon Sep 17 00:00:00 2001 From: Tokarak <63452145+Tokarak@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:50:17 +0100 Subject: [PATCH 12/15] Fix behaviour of `--no-https-verification` --- src/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 781fd2f3..0d4e0e97 100644 --- a/src/main.rs +++ b/src/main.rs @@ -162,12 +162,12 @@ async fn main() { Arg::new("no-https-verification") .long("no-https-verification") .help("Disables HTTPS certificate verification between the instance and reddit. This can be useful to debug the HTTPS connection with an HTTPS sniffer. Only works when the 'no-https-verification' feature is enabled at compile time.") - .num_args(0), + .action(ArgAction::SetFalse) ); let matches = cmd.get_matches_mut(); #[cfg(not(feature = "no-https-verification"))] - if matches.contains_id("no-https-verification") { + if ! matches.get_flag("no-https-verification") { cmd .error( clap::error::ErrorKind::InvalidValue, @@ -179,7 +179,7 @@ async fn main() { let address = matches.get_one::("address").unwrap(); let port = matches.get_one::("port").unwrap(); let hsts = matches.get_one("hsts").map(|m: &String| m.as_str()); - VERIFY_HTTPS.set(! matches.contains_id("no-https-verification")).unwrap(); + VERIFY_HTTPS.set(matches.get_flag("no-https-verification")).unwrap(); let listener = [address, ":", port].concat(); From 7d422242bedff7fd4f278907aa2412d7ce1c0f79 Mon Sep 17 00:00:00 2001 From: Tokarak <63452145+Tokarak@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:52:42 +0100 Subject: [PATCH 13/15] Add `--no-https-verification` info to instance-info page --- src/instance_info.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/instance_info.rs b/src/instance_info.rs index c05ce5c1..cbb89cca 100644 --- a/src/instance_info.rs +++ b/src/instance_info.rs @@ -2,6 +2,7 @@ use crate::{ config::{Config, CONFIG}, server::RequestExt, utils::{ErrorTemplate, Preferences}, + client::VERIFY_HTTPS, }; use build_html::{Container, Html, HtmlContainer, Table}; use hyper::{http::Error, Body, Request, Response}; @@ -88,6 +89,7 @@ pub struct InstanceInfo { git_commit: String, deploy_date: String, compile_mode: String, + verify_https: bool, deploy_unix_ts: i64, config: Config, } @@ -103,6 +105,7 @@ impl InstanceInfo { compile_mode: "Debug".into(), #[cfg(not(debug_assertions))] compile_mode: "Release".into(), + verify_https: *VERIFY_HTTPS.get().unwrap(), deploy_unix_ts: OffsetDateTime::now_local().unwrap_or_else(|_| OffsetDateTime::now_utc()).unix_timestamp(), config: CONFIG.clone(), } @@ -127,6 +130,7 @@ impl InstanceInfo { ["SFW only", &convert(&self.config.sfw_only)], ["Pushshift frontend", &convert(&self.config.pushshift)], ["RSS enabled", &convert(&self.config.enable_rss)], + ["Reddit HTTPS verification", &self.verify_https.to_string()], ["Full URL", &convert(&self.config.full_url)], //TODO: fallback to crate::config::DEFAULT_PUSHSHIFT_FRONTEND ]) @@ -168,6 +172,7 @@ impl InstanceInfo { SFW only: {:?}\n Pushshift frontend: {:?}\n RSS enabled: {:?}\n + Reddit HTTPS Verification: {:?}\n Full URL: {:?}\n Config:\n Banner: {:?}\n @@ -194,6 +199,7 @@ impl InstanceInfo { self.compile_mode, self.config.sfw_only, self.config.enable_rss, + self.verify_https, self.config.full_url, self.config.pushshift, self.config.banner, From 77fa67299ca5ea2afc415249e4c5ad60aaa08134 Mon Sep 17 00:00:00 2001 From: Tokarak <63452145+Tokarak@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:56:23 +0100 Subject: [PATCH 14/15] Run cargo fmt --- src/client.rs | 3 ++- src/instance_info.rs | 2 +- src/main.rs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/client.rs b/src/client.rs index 51506b0f..f9908003 100644 --- a/src/client.rs +++ b/src/client.rs @@ -31,6 +31,7 @@ const REDDIT_SHORT_URL_BASE_HOST: &str = "redd.it"; const ALTERNATIVE_REDDIT_URL_BASE: &str = "https://www.reddit.com"; const ALTERNATIVE_REDDIT_URL_BASE_HOST: &str = "www.reddit.com"; +// CLIENT and VERIFY_HTTPS are initialised in main.rs pub static CLIENT: OnceLock>> = OnceLock::new(); pub static VERIFY_HTTPS: OnceLock = OnceLock::new(); @@ -58,7 +59,7 @@ pub fn generate_client(https_verification: bool) -> Client Date: Sun, 2 Feb 2025 22:26:00 -0500 Subject: [PATCH 15/15] fix(cargo): gate dep feature behind feature --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0a45db76..ae7dbff4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ authors = [ edition = "2021" [features] -no-https-verification = [] +no-https-verification = ["rustls/dangerous_configuration"] [dependencies] rinja = { version = "0.3.4", default-features = false } @@ -46,7 +46,7 @@ pretty_env_logger = "0.5.0" dotenvy = "0.15.7" rss = "2.0.7" arc-swap = "1.7.1" -rustls = { version = "0.21.12", features = ["dangerous_configuration"] } +rustls = { version = "0.21.12" } ctor = "0.2.8" serde_json_path = "0.6.7" async-recursion = "1.1.1"