From de421e96885786b1afa9129fedaaa13a8dddc5bd Mon Sep 17 00:00:00 2001 From: TudbuT Date: Thu, 27 Oct 2022 09:32:39 +0200 Subject: [PATCH] upgrade to rustls --- Cargo.lock | 63 ++----------------------------------------- Cargo.toml | 9 ++++--- src/frame.rs | 75 +++++++++++++++++++++++++++++++--------------------- src/main.rs | 2 +- 4 files changed, 53 insertions(+), 96 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96dad40..9f800e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -389,21 +389,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form-data-builder" version = "1.0.1" @@ -919,45 +904,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "openssl" -version = "0.10.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "openssl-sys" -version = "0.9.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5230151e44c0f05157effb743e8d517472843121cf9243e8b81393edb5acd9ce" -dependencies = [ - "autocfg", - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "ordered-float" version = "2.10.0" @@ -1111,11 +1057,12 @@ version = "0.1.0" dependencies = [ "form-data-builder", "gif", - "openssl", "png", + "rustls", "serenity", "songbird", "tokio", + "webpki-roots", ] [[package]] @@ -1910,12 +1857,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index cc0a0a2..ede79eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,8 @@ edition = "2021" tokio = {version="1.21.2", features=["full"]} serenity = {version="0.11.5", features=["builder", "cache", "client", "framework", "gateway", "http", "model", "standard_framework", "utils", "rustls_backend", "voice"]} songbird = {version="0.3.0", features=["driver", "serenity-rustls"]} -openssl = "0.10.42" -form-data-builder = "1.0.1" -png = "0.17.6" -gif = "0.11.4" +rustls = "0.20" +form-data-builder = "1.0" +png = "0.17" +gif = "0.11" +webpki-roots = "0.22" diff --git a/src/frame.rs b/src/frame.rs index b55724f..6510837 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -1,16 +1,17 @@ use form_data_builder::FormData; -use openssl::ssl::{Ssl, SslContext, SslMethod, SslStream}; +use rustls::{OwnedTrustAnchor, RootCertStore, ClientConfig, ClientConnection, Stream}; use std::{ ffi::OsStr, io::{Cursor, Read, Write}, net::{Shutdown, TcpStream}, - time::Duration, + time::Duration, sync::Arc, }; pub struct Frame { pub bytes: Vec, pub channel: u64, - cache_stream: Option>, + tcp_stream: Option, + cache_stream: Option, byte_to_write: Option, } @@ -19,18 +20,28 @@ impl Frame { Frame { bytes, channel, + tcp_stream: None, cache_stream: None, byte_to_write: None, } } pub fn cache_frame(&mut self, message: u64, content: &str, token: &str) { - let ssl_context = SslContext::builder(SslMethod::tls_client()) - .expect("ssl: context init failed") - .build(); - let ssl = Ssl::new(&ssl_context).expect("ssl: init failed"); - let tcp_stream = TcpStream::connect("discord.com:443").expect("api: connect error"); - let mut stream = SslStream::new(ssl, tcp_stream).expect("ssl: stream init failed"); + let mut root_store = RootCertStore::empty(); + root_store.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| { + OwnedTrustAnchor::from_subject_spki_name_constraints( + ta.subject, + ta.spki, + ta.name_constraints, + ) + })); + let client_config = Arc::new(ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(root_store) + .with_no_client_auth()); + let mut tcp_stream = TcpStream::connect("discord.com:443").expect("api: connect error"); + let mut connection = ClientConnection::new(client_config, "discord.com".try_into().unwrap()).expect("ssl: context init failed"); + let mut stream: Stream = Stream::new(&mut connection, &mut tcp_stream); let mut form = FormData::new(Vec::new()); @@ -61,7 +72,6 @@ impl Frame { .expect("form: attachment failed"); let mut data = form.finish().expect("form: finish failed"); - stream.connect().expect("api: connection failed"); stream .write_all( format!( @@ -100,33 +110,38 @@ impl Frame { .expect("api: write failed"); stream.flush().expect("api: flush failed"); - self.cache_stream = Some(stream); + self.cache_stream = Some(connection); + self.tcp_stream = Some(tcp_stream); // now the frame is ready to send the next part } pub fn complete_send(&mut self) { let cache_stream = &mut self.cache_stream; let byte_to_write = &self.byte_to_write; - if let Some(stream) = cache_stream { + let tcp_stream = &mut self.tcp_stream; + if let Some(connection) = cache_stream { if let Some(byte) = byte_to_write { - stream - .write_all(&[*byte]) - .expect("api: write failed at complete_send"); - stream.flush().expect("api: flush failed"); - stream - .get_ref() - .set_read_timeout(Some(Duration::from_millis(500))) - .expect("tcp: unable to set timeout"); - let mut buf = Vec::new(); - let _ = stream.read_to_end(&mut buf); // failure is normal - stream.shutdown().expect("ssl: shutdown failed"); - stream - .get_ref() - .shutdown(Shutdown::Both) - .expect("tcp: shutdown failed"); - self.cache_stream = None; - self.byte_to_write = None; - return; + if let Some(tcp_stream) = tcp_stream { + let mut stream: Stream = Stream::new(connection, tcp_stream); + stream + .write_all(&[*byte]) + .expect("api: write failed at complete_send"); + stream.flush().expect("api: flush failed"); + stream.sock + .set_read_timeout(Some(Duration::from_millis(500))) + .expect("tcp: unable to set timeout"); + let mut buf = Vec::new(); + let _ = stream.read_to_end(&mut buf); // failure is normal + stream.conn.send_close_notify(); + stream.conn.write_tls(stream.sock).expect("ssl: unable to close connection"); + stream.sock.flush().expect("ssl: unable to flush"); + stream.sock + .shutdown(Shutdown::Both) + .expect("tcp: shutdown failed"); + self.cache_stream = None; + self.byte_to_write = None; + return; + } } } panic!("complete_send called on uncached frame!"); diff --git a/src/main.rs b/src/main.rs index 8823c8a..01d8c9f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -98,7 +98,7 @@ async fn send_video(message: Message, ctx: Context) { + (api_time as i64 * str::parse::( env::var("PROJBOTV3_API_TIME_FACTOR") - .unwrap_or_else(|_| "3".into()) + .unwrap_or_else(|_| "5".into()) .as_str(), ) .unwrap()) as u64,