mirror of
https://github.com/vinezombie/vinezombie.git
synced 2026-01-24 23:17:34 +00:00
Add crypto feature, update to rustls 0.23
rustls 0.22 adds support for alternate crypto providers; 0.23 defaults to aws_lc_rs. The tls feature now pulls in NO crypto providers, but expects a process-default crypto provider to be set before doing TLS. The crypto feature pulls in ring and adds it as a provider for rustls, as we'll be using ring anyway for fancier SASL auths. Due to the 78-column limit being cumbersome on Cargo.toml, it has been restricted to only apply to markdown files.
This commit is contained in:
@@ -3,6 +3,8 @@ charset = utf-8
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
max_line_length = 78
|
||||
|
||||
[*.rs]
|
||||
|
||||
12
Cargo.toml
12
Cargo.toml
@@ -17,19 +17,21 @@ include = ["/src", "/doc/rustdoc/*", "/README.md"]
|
||||
|
||||
[dependencies]
|
||||
base64 = { version = "0.21.2", optional = true }
|
||||
rustls = { version = "0.21.4", optional = true, features = ["dangerous_configuration"] }
|
||||
rustls-native-certs = { version = "0.6.3", optional = true }
|
||||
rustls-pemfile = { version = "1.0.2", optional = true }
|
||||
ring = { version = "0.17.8", optional = true }
|
||||
rustls = { version = "0.23.5", optional = true, default-features = false, features = ["std", "tls12"] }
|
||||
rustls-native-certs = { version = "0.7.0", optional = true }
|
||||
rustls-pemfile = { version = "2.1.2", optional = true }
|
||||
serde = { version = "1.0", features = ["rc"], optional = true }
|
||||
serde_derive = { version = ">= 1.0.184", optional = true }
|
||||
tokio = { version = "1.28.2", features = ["io-util", "net", "time", "rt", "sync"], optional = true }
|
||||
tokio-rustls = { version = "0.24.1", optional = true }
|
||||
tokio-rustls = { version = "0.26.0", optional = true, default-features = false}
|
||||
tracing = { version = "0.1.37", default-features = false, features = ["std"], optional = true }
|
||||
whoami = { version = "1.5.0", optional = true }
|
||||
|
||||
[features]
|
||||
default = ["base64", "client", "tls-tokio"]
|
||||
default = ["base64", "client", "crypto", "tls-tokio"]
|
||||
client = []
|
||||
crypto = ["dep:ring", "rustls?/ring"]
|
||||
serde = ["dep:serde", "dep:serde_derive"]
|
||||
tls = ["dep:rustls", "dep:rustls-native-certs", "dep:rustls-pemfile"]
|
||||
tls-tokio = ["dep:tokio-rustls", "tls", "tokio"]
|
||||
|
||||
@@ -19,8 +19,12 @@ and includes the following:
|
||||
Adds base64 encoding/decoding.
|
||||
* `client`:
|
||||
Adds utilities for building client-side IRC software.
|
||||
* `crypto`:
|
||||
Adds `ring`-based cryptography, required for some SASL authenticators.
|
||||
Also adds `ring` as a crypto provider to rustls if `tls` is enabled.
|
||||
* `tls`:
|
||||
Adds utilities for working with rustls.
|
||||
Does NOT pull in any crypto providers.
|
||||
* `tls-tokio`: Implies `tls` and `tokio`.
|
||||
Adds support for asynchronous TLS connections.
|
||||
* `tokio`:
|
||||
|
||||
@@ -26,10 +26,10 @@ impl<'a> super::ServerAddr<'a> {
|
||||
use std::io::{Error, ErrorKind};
|
||||
let string = self.utf8_address()?;
|
||||
let stream = if self.tls {
|
||||
let name = rustls::ServerName::try_from(string)
|
||||
let name = rustls::pki_types::ServerName::try_from(string)
|
||||
.map_err(|e| Error::new(ErrorKind::InvalidInput, e))?;
|
||||
let config = tls_fn()?;
|
||||
let conn = rustls::ClientConnection::new(config, name)
|
||||
let conn = rustls::ClientConnection::new(config, name.to_owned())
|
||||
.map_err(|e| Error::new(ErrorKind::Other, e))?;
|
||||
let sock = std::net::TcpStream::connect((string, self.port_num()))?;
|
||||
let mut tls = rustls::StreamOwned { conn, sock };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::{timed_io, Bidir, TimeLimitedTokio};
|
||||
use crate::{client::tls::TlsConfig, ircmsg::ServerMsg};
|
||||
use crate::ircmsg::ServerMsg;
|
||||
use std::{pin::Pin, time::Duration};
|
||||
use tokio::{
|
||||
io::{AsyncBufRead, AsyncWrite, BufReader},
|
||||
@@ -21,17 +21,17 @@ impl<'a> super::ServerAddr<'a> {
|
||||
#[cfg(feature = "tls-tokio")]
|
||||
pub async fn connect_tokio(
|
||||
&self,
|
||||
tls_fn: impl FnOnce() -> std::io::Result<TlsConfig>,
|
||||
tls_fn: impl FnOnce() -> std::io::Result<crate::client::tls::TlsConfig>,
|
||||
) -> std::io::Result<BufReader<StreamTokio>> {
|
||||
use std::io::{Error, ErrorKind};
|
||||
let string = self.utf8_address()?;
|
||||
let stream = if self.tls {
|
||||
let name = rustls::ServerName::try_from(string)
|
||||
let name = rustls::pki_types::ServerName::try_from(string)
|
||||
.map_err(|e| Error::new(ErrorKind::InvalidInput, e))?;
|
||||
let config = tls_fn()?;
|
||||
let conn: tokio_rustls::TlsConnector = config.into();
|
||||
let sock = tokio::net::TcpStream::connect((string, self.port_num())).await?;
|
||||
let tls = conn.connect(name, sock).await?;
|
||||
let tls = conn.connect(name.to_owned(), sock).await?;
|
||||
StreamInner::Tls(tls)
|
||||
} else {
|
||||
let sock = tokio::net::TcpStream::connect((string, self.port_num())).await?;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
//! Helpers for creating TLS connections.
|
||||
|
||||
use rustls::{Certificate, ClientConfig, RootCertStore};
|
||||
use rustls::{
|
||||
pki_types::{CertificateDer, PrivateKeyDer},
|
||||
ClientConfig, RootCertStore,
|
||||
};
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
@@ -24,22 +27,62 @@ pub enum Trust {
|
||||
NoVerify,
|
||||
}
|
||||
|
||||
/// `ServerCertVerifier` that verifies literally everything.
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
struct NoVerifier;
|
||||
/// `ServerCertVerifier` that doesn't care at all about the server cert.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct NoVerifier(&'static Arc<rustls::crypto::CryptoProvider>);
|
||||
|
||||
impl rustls::client::ServerCertVerifier for NoVerifier {
|
||||
impl Default for NoVerifier {
|
||||
fn default() -> Self {
|
||||
NoVerifier(
|
||||
rustls::crypto::CryptoProvider::get_default()
|
||||
.expect("no default rustls crypto prodiver"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl rustls::client::danger::ServerCertVerifier for NoVerifier {
|
||||
fn verify_server_cert(
|
||||
&self,
|
||||
_: &rustls::Certificate,
|
||||
_: &[rustls::Certificate],
|
||||
_: &rustls::ServerName,
|
||||
_: &mut dyn Iterator<Item = &[u8]>,
|
||||
_: &CertificateDer<'_>,
|
||||
_: &[CertificateDer<'_>],
|
||||
_: &rustls::pki_types::ServerName<'_>,
|
||||
_: &[u8],
|
||||
_: std::time::SystemTime,
|
||||
) -> Result<rustls::client::ServerCertVerified, rustls::Error> {
|
||||
_: rustls::pki_types::UnixTime,
|
||||
) -> Result<rustls::client::danger::ServerCertVerified, rustls::Error> {
|
||||
// :)
|
||||
Ok(rustls::client::ServerCertVerified::assertion())
|
||||
Ok(rustls::client::danger::ServerCertVerified::assertion())
|
||||
}
|
||||
|
||||
fn verify_tls12_signature(
|
||||
&self,
|
||||
message: &[u8],
|
||||
cert: &CertificateDer<'_>,
|
||||
dss: &rustls::DigitallySignedStruct,
|
||||
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
|
||||
rustls::crypto::verify_tls12_signature(
|
||||
message,
|
||||
cert,
|
||||
dss,
|
||||
&self.0.signature_verification_algorithms,
|
||||
)
|
||||
}
|
||||
|
||||
fn verify_tls13_signature(
|
||||
&self,
|
||||
message: &[u8],
|
||||
cert: &CertificateDer<'_>,
|
||||
dss: &rustls::DigitallySignedStruct,
|
||||
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
|
||||
rustls::crypto::verify_tls12_signature(
|
||||
message,
|
||||
cert,
|
||||
dss,
|
||||
&self.0.signature_verification_algorithms,
|
||||
)
|
||||
}
|
||||
|
||||
fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
|
||||
self.0.signature_verification_algorithms.supported_schemes()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,25 +104,28 @@ pub struct TlsConfigOptions {
|
||||
|
||||
fn load_pem(path: &Path, certs: &mut RootCertStore) -> std::io::Result<()> {
|
||||
let mut file = std::io::BufReader::new(std::fs::File::open(path)?);
|
||||
for cert in rustls_pemfile::certs(&mut file)? {
|
||||
for cert in rustls_pemfile::certs(&mut file) {
|
||||
let cert = cert?;
|
||||
certs
|
||||
.add(&rustls::Certificate(cert))
|
||||
.add(CertificateDer::from(cert))
|
||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn load_client_cert(path: &Path) -> std::io::Result<(Vec<Certificate>, rustls::PrivateKey)> {
|
||||
let mut key = Option::<rustls::PrivateKey>::None;
|
||||
let mut certs = Vec::<Certificate>::new();
|
||||
fn load_client_cert(
|
||||
path: &Path,
|
||||
) -> std::io::Result<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)> {
|
||||
let mut key = Option::<PrivateKeyDer>::None;
|
||||
let mut certs = Vec::<CertificateDer>::new();
|
||||
let mut file = std::io::BufReader::new(std::fs::File::open(path)?);
|
||||
while let Some(item) = rustls_pemfile::read_one(&mut file)? {
|
||||
match item {
|
||||
rustls_pemfile::Item::X509Certificate(c) => {
|
||||
certs.push(Certificate(c));
|
||||
certs.push(CertificateDer::from(c));
|
||||
}
|
||||
rustls_pemfile::Item::PKCS8Key(k) => {
|
||||
key = Some(rustls::PrivateKey(k));
|
||||
rustls_pemfile::Item::Pkcs8Key(k) => {
|
||||
key = Some(PrivateKeyDer::from(k));
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
@@ -94,10 +140,12 @@ impl TlsConfigOptions {
|
||||
/// This is an expensive operation. It should ideally be done only once per network.
|
||||
pub fn build(&self) -> std::io::Result<TlsConfig> {
|
||||
let cli_auth =
|
||||
if let Some(path) = &self.cert { Some(load_client_cert(path)?) } else { None };
|
||||
let builder = ClientConfig::builder().with_safe_defaults();
|
||||
if let Some(path) = self.cert.as_ref() { Some(load_client_cert(path)?) } else { None };
|
||||
let builder = ClientConfig::builder();
|
||||
let config = if matches!(&self.trust, Trust::NoVerify) {
|
||||
let builder = builder.with_custom_certificate_verifier(Arc::new(NoVerifier));
|
||||
let builder = builder
|
||||
.dangerous()
|
||||
.with_custom_certificate_verifier(Arc::new(NoVerifier::default()));
|
||||
if let Some((certs, key)) = cli_auth {
|
||||
builder
|
||||
.with_client_auth_cert(certs, key)
|
||||
@@ -109,7 +157,7 @@ impl TlsConfigOptions {
|
||||
let mut certs = RootCertStore { roots: Vec::new() };
|
||||
if matches!(&self.trust, Trust::Default | Trust::Also(_)) {
|
||||
let natives = rustls_native_certs::load_native_certs()?;
|
||||
certs.add_parsable_certificates(&natives);
|
||||
certs.add_parsable_certificates(natives);
|
||||
}
|
||||
if let Trust::Only(paths) | Trust::Also(paths) = &self.trust {
|
||||
certs.roots.reserve_exact(paths.len());
|
||||
|
||||
Reference in New Issue
Block a user