From 07034d2cecd8dec4620f00adc68e28fe07a5f04a Mon Sep 17 00:00:00 2001 From: Aram Peres Date: Wed, 4 Aug 2021 19:26:09 -0400 Subject: [PATCH] Clippy. Re-add blocking SSL config --- rups/src/blocking/client.rs | 41 +++++++++++++++++++++++++++++++++---- rups/src/blocking/stream.rs | 29 +++++++++++++------------- rups/src/proto/mod.rs | 4 ++-- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/rups/src/blocking/client.rs b/rups/src/blocking/client.rs index 096ec40..62a02ff 100644 --- a/rups/src/blocking/client.rs +++ b/rups/src/blocking/client.rs @@ -1,6 +1,6 @@ use crate::blocking::stream::ConnectionStream; use crate::proto::{ClientSentences, Sentence, ServerSentences}; -use crate::{Config, Host, TcpHost}; +use crate::{Config, Error, Host, NutError, TcpHost}; use std::net::TcpStream; /// A synchronous NUT client. @@ -45,13 +45,46 @@ impl Client { // Expect the OK self.stream .read_sentence::()? - .as_exactly(ClientSentences::StartTLSOk {})?; + .exactly(ClientSentences::StartTLSOk {})?; + + // Initialize SSL configurations + let mut ssl_config = rustls::ClientConfig::new(); + let sess = if self.config.ssl_insecure { + ssl_config + .dangerous() + .set_certificate_verifier(std::sync::Arc::new( + crate::ssl::InsecureCertificateValidator::new(&self.config), + )); + + let dns_name = webpki::DNSNameRef::try_from_ascii_str("www.google.com").unwrap(); + + rustls::ClientSession::new(&std::sync::Arc::new(ssl_config), dns_name) + } else { + // Try to get hostname as given (e.g. localhost can be used for strict SSL, but not 127.0.0.1) + let hostname = self + .config + .host + .hostname() + .ok_or(Error::Nut(NutError::SslInvalidHostname))?; + + let dns_name = webpki::DNSNameRef::try_from_ascii_str(&hostname) + .map_err(|_| Error::Nut(NutError::SslInvalidHostname))?; + + ssl_config + .root_store + .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); + + rustls::ClientSession::new(&std::sync::Arc::new(ssl_config), dns_name) + }; // Un-buffer to get back underlying stream self.stream = self.stream.unbuffered(); - // TODO: Un-buffer - // TODO: Do the upgrade + // Upgrade to SSL + self.stream = self.stream.upgrade_ssl_client(sess)?; + + // Re-buffer + self.stream = self.stream.buffered(); } Ok(self) } diff --git a/rups/src/blocking/stream.rs b/rups/src/blocking/stream.rs index 5801ae2..e2ccc5c 100644 --- a/rups/src/blocking/stream.rs +++ b/rups/src/blocking/stream.rs @@ -129,7 +129,7 @@ impl ConnectionStream { } /// Wraps the current stream with a `BufReader`. - pub fn buffered(mut self) -> ConnectionStream { + pub fn buffered(self) -> ConnectionStream { Self::Buffered(Box::new(BufReader::new(self))) } @@ -137,10 +137,11 @@ impl ConnectionStream { /// If the current stream is not buffered, it returns itself (no-op). /// /// Note that, if the stream is buffered, any un-consumed data will be discarded. - pub fn unbuffered(mut self) -> ConnectionStream { - match self { - Self::Buffered(buf) => buf.into_inner(), - _ => self, + pub fn unbuffered(self) -> ConnectionStream { + if let Self::Buffered(buf) = self { + buf.into_inner() + } else { + self } } } @@ -172,9 +173,8 @@ impl BufRead for ConnectionStream { } fn consume(&mut self, amt: usize) { - match self { - Self::Buffered(reader) => reader.consume(amt), - _ => (), + if let Self::Buffered(reader) = self { + reader.consume(amt) } } } @@ -215,12 +215,11 @@ impl Write for ConnectionStream { mod tests { use super::ConnectionStream; use crate::proto::{ClientSentences, Sentence, ServerSentences}; - use std::io::{Read, Write}; #[test] fn read_write_sentence() { - let mut client_stream = mockstream::SharedMockStream::new(); - let mut server_stream = client_stream.clone(); + let client_stream = mockstream::SharedMockStream::new(); + let server_stream = client_stream.clone(); let mut client_stream = ConnectionStream::Mock(client_stream).buffered(); let mut server_stream = ConnectionStream::Mock(server_stream).buffered(); @@ -253,10 +252,10 @@ mod tests { .expect("Failed to write UPS LIST"); // Client reads list of UPS devices. - let sentence = client_stream + client_stream .read_sentence::() .expect("Failed to read BEGIN LIST UPS") - .as_exactly(ClientSentences::BeginListUps {}) + .exactly(ClientSentences::BeginListUps {}) .unwrap(); let sentences: Vec = client_stream @@ -285,10 +284,10 @@ mod tests { .expect("Failed to write LOGIN nutdev0"); // Server receives login - let sentence = server_stream + let _sentence = server_stream .read_sentence::() .expect("Failed to read LOGIN nutdev0") - .as_exactly(ServerSentences::ExecLogin { + .exactly(ServerSentences::ExecLogin { ups_name: "nutdev0".into(), }) .unwrap(); diff --git a/rups/src/proto/mod.rs b/rups/src/proto/mod.rs index 856cc46..20702ad 100644 --- a/rups/src/proto/mod.rs +++ b/rups/src/proto/mod.rs @@ -113,7 +113,7 @@ pub trait Sentence: Eq + Sized + Into> { fn encode(&self) -> Vec<&str>; /// Returns an error if the sentence does not match what was expected. - fn as_matching bool>(self, matcher: F) -> crate::Result { + fn matching bool>(self, matcher: F) -> crate::Result { if matcher(&self) { Ok(self) } else { @@ -122,7 +122,7 @@ pub trait Sentence: Eq + Sized + Into> { } /// Returns an error if the sentence is not equal to what was expected. - fn as_exactly(self, expected: Self) -> crate::Result { + fn exactly(self, expected: Self) -> crate::Result { if expected == self { Ok(self) } else {