From 95362fd9e8944788998c2ad139cd2ebaf32f79a9 Mon Sep 17 00:00:00 2001 From: DarkCat09 Date: Thu, 1 Aug 2024 12:05:39 +0400 Subject: [PATCH] feat: add example and dev deps Note: current version of main.rs example just disables TLS cert verification if `-k` arg provided. Instead, it must use custom storage for self-signed certs. tokio with macros & fs features in dev deps is needed for main.rs example. --- Cargo.lock | 12 +++++ Cargo.toml | 7 +++ examples/main.rs | 111 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 examples/main.rs diff --git a/Cargo.lock b/Cargo.lock index 17e1bba..7acdd2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -340,6 +340,7 @@ dependencies = [ "mio", "pin-project-lite", "socket2", + "tokio-macros", "windows-sys", ] @@ -355,6 +356,17 @@ dependencies = [ "webpki-roots", ] +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tokio-rustls" version = "0.26.0" diff --git a/Cargo.toml b/Cargo.toml index bba3e15..11900d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,10 @@ tokio = { version = "1.39.2", features = ["io-util", "net"] } tokio-rustls = { version = "0.26.0", default-features = false, features = ["ring"] } url = "2.5.2" webpki-roots = "0.26.3" + +[[example]] +name = "main" +path = "examples/main.rs" + +[dev-dependencies] +tokio = { version = "1.39.2", features = ["macros", "rt-multi-thread", "io-util", "fs"] } diff --git a/examples/main.rs b/examples/main.rs new file mode 100644 index 0000000..82e8b28 --- /dev/null +++ b/examples/main.rs @@ -0,0 +1,111 @@ +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio_rustls::rustls::{ + client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}, + ClientConfig, SignatureScheme, +}; + +#[tokio::main] +async fn main() -> Result<(), tokio_gemini::LibError> { + let mut args = std::env::args(); + let mut insecure = false; + let mut url = "gemini://geminiprotocol.net/".to_owned(); + if let Some(arg) = args.nth(1) { + if arg == "-k" { + insecure = true; + if let Some(arg) = args.nth(2) { + url = arg; + } + } else { + url = arg; + } + } + + let client = if insecure { + tokio_gemini::Client::from(get_insecure_config()) + } else { + tokio_gemini::Client::default() + }; + let mut resp = client.request(&url).await?; + { + let status_code = resp.status().status_code(); + let status_num: u8 = status_code.into(); + eprintln!("{} {:?}", status_num, status_code); + } + if resp.status().reply_type() == tokio_gemini::ReplyType::Success { + let mime = resp.mime()?; + eprintln!("Mime: {}", mime); + let mut buf = [0u8, 128]; + let body = resp.body(); + if mime.type_() == mime::TEXT { + loop { + let n = body.read(&mut buf).await?; + if n == 0 { + break; + } + print!("{}", std::str::from_utf8(&buf[..n])?); + } + } else { + eprintln!("Downloading into content.bin"); + let mut f = tokio::fs::File::create("content.bin").await?; + loop { + let n = body.read(&mut buf).await?; + if n == 0 { + break; + } + f.write_all(&buf[..n]).await?; + } + } + } else { + eprintln!("Message: {}", resp.message()); + } + Ok(()) +} + +fn get_insecure_config() -> ClientConfig { + ClientConfig::builder() + .dangerous() + .with_custom_certificate_verifier(std::sync::Arc::new(NoCertVerification {})) + .with_no_client_auth() +} + +#[derive(Debug)] +struct NoCertVerification; + +impl ServerCertVerifier for NoCertVerification { + fn verify_server_cert( + &self, + end_entity: &tokio_rustls::rustls::pki_types::CertificateDer<'_>, + intermediates: &[tokio_rustls::rustls::pki_types::CertificateDer<'_>], + server_name: &tokio_rustls::rustls::pki_types::ServerName<'_>, + ocsp_response: &[u8], + now: tokio_rustls::rustls::pki_types::UnixTime, + ) -> Result { + Ok(ServerCertVerified::assertion()) + } + + fn verify_tls12_signature( + &self, + message: &[u8], + cert: &tokio_rustls::rustls::pki_types::CertificateDer<'_>, + dss: &tokio_rustls::rustls::DigitallySignedStruct, + ) -> Result { + Ok(HandshakeSignatureValid::assertion()) + } + + fn verify_tls13_signature( + &self, + message: &[u8], + cert: &tokio_rustls::rustls::pki_types::CertificateDer<'_>, + dss: &tokio_rustls::rustls::DigitallySignedStruct, + ) -> Result { + Ok(HandshakeSignatureValid::assertion()) + } + + fn supported_verify_schemes(&self) -> Vec { + vec![ + SignatureScheme::ECDSA_NISTP256_SHA256, + SignatureScheme::ECDSA_NISTP384_SHA384, + SignatureScheme::ECDSA_NISTP521_SHA512, + ] + } +}