Bump dependencies, set rust-version

This commit is contained in:
John-John Tedro 2023-04-12 16:18:34 +02:00
parent d40e3ce844
commit 3e396f8577
6 changed files with 181 additions and 145 deletions

View file

@ -1,15 +1,16 @@
[package] [package]
name = "irc" name = "irc"
version = "0.15.0" version = "0.15.0"
description = "the irc crate usable, async IRC for Rust "
authors = ["Aaron Weiss <aweiss@hey.com>"] authors = ["Aaron Weiss <aweiss@hey.com>"]
edition = "2018"
rust-version = "1.60"
description = "the irc crate usable, async IRC for Rust "
documentation = "https://docs.rs/irc/"
readme = "README.md"
repository = "https://github.com/aatxe/irc"
license = "MPL-2.0" license = "MPL-2.0"
keywords = ["irc", "client", "thread-safe", "async", "tokio"] keywords = ["irc", "client", "thread-safe", "async", "tokio"]
categories = ["asynchronous", "network-programming"] categories = ["asynchronous", "network-programming"]
documentation = "https://docs.rs/irc/"
repository = "https://github.com/aatxe/irc"
readme = "README.md"
edition = "2018"
[badges] [badges]
@ -37,46 +38,47 @@ yaml = ["yaml_config"]
proxy = ["tokio-socks"] proxy = ["tokio-socks"]
tls-native = ["native-tls", "tokio-native-tls"] tls-native = ["native-tls", "tokio-native-tls"]
tls-rust = ["tokio-rustls", "webpki-roots"] tls-rust = ["tokio-rustls", "webpki-roots", "rustls-pemfile"]
[dependencies] [dependencies]
chrono = { version = "0.4", default-features = false, features = ["clock", "std"] } chrono = { version = "0.4.24", default-features = false, features = ["clock", "std"] }
encoding = "0.2.0" encoding = "0.2.33"
futures-util = { version = "0.3.0", default-features = false, features = ["alloc", "sink"] } futures-util = { version = "0.3.28", default-features = false, features = ["alloc", "sink"] }
irc-proto = { version = "0.15.0", path = "irc-proto" } irc-proto = { version = "0.15.0", path = "irc-proto" }
log = "0.4.0" log = "0.4.17"
parking_lot = "0.11.0" parking_lot = "0.12.1"
thiserror = "1.0.0" thiserror = "1.0.40"
pin-project = "1.0.2" pin-project = "1.0.12"
tokio = { version = "1.0.0", features = ["net", "time", "sync"] } tokio = { version = "1.27.0", features = ["net", "time", "sync"] }
tokio-stream = "0.1.0" tokio-stream = "0.1.12"
tokio-util = { version = "0.6.0", features = ["codec"] } tokio-util = { version = "0.7.7", features = ["codec"] }
# Feature - Config # Feature - Config
serde = { version = "1.0.0", optional = true } serde = { version = "1.0.160", optional = true }
serde_derive = { version = "1.0.0", optional = true } serde_derive = { version = "1.0.160", optional = true }
serde_json = { version = "1.0.0", optional = true } serde_json = { version = "1.0.95", optional = true }
serde_yaml = { version = "0.8.0", optional = true } serde_yaml = { version = "0.9.21", optional = true }
toml = { version = "0.5.0", optional = true } toml = { version = "0.7.3", optional = true }
# Feature - Proxy # Feature - Proxy
tokio-socks = { version = "0.5.1", optional = true } tokio-socks = { version = "0.5.1", optional = true }
# Feature - TLS # Feature - TLS
native-tls = { version = "0.2.0", optional = true } native-tls = { version = "0.2.11", optional = true }
tokio-rustls = { version = "0.22.0", features = ["dangerous_configuration"], optional = true } tokio-rustls = { version = "0.24.0", features = ["dangerous_configuration"], optional = true }
tokio-native-tls = { version = "0.3.0", optional = true } rustls-pemfile = { version = "1.0.2", optional = true }
webpki-roots = { version = "0.20.0", optional = true } tokio-native-tls = { version = "0.3.1", optional = true }
webpki-roots = { version = "0.23.0", optional = true }
[dev-dependencies] [dev-dependencies]
anyhow = "1.0.0" anyhow = "1.0.70"
args = "2.0.0" args = "2.2.0"
env_logger = "0.7.0" env_logger = "0.10.0"
futures = "0.3.0" futures = "0.3.28"
getopts = "0.2.0" getopts = "0.2.21"
tokio = { version = "1.0.0", features = ["rt", "rt-multi-thread", "macros", "net", "time"] } tokio = { version = "1.27.0", features = ["rt", "rt-multi-thread", "macros", "net", "time"] }
[[example]] [[example]]

View file

@ -1,14 +1,15 @@
[package] [package]
name = "irc-proto" name = "irc-proto"
version = "0.15.0" version = "0.15.0"
description = "The IRC protocol distilled."
authors = ["Aaron Weiss <aweiss@hey.com>"] authors = ["Aaron Weiss <aweiss@hey.com>"]
edition = "2018"
rust-version = "1.60"
description = "The IRC protocol distilled."
documentation = "https://docs.rs/irc-proto/"
repository = "https://github.com/aatxe/irc"
license = "MPL-2.0" license = "MPL-2.0"
keywords = ["irc", "protocol", "tokio"] keywords = ["irc", "protocol", "tokio"]
categories = ["network-programming"] categories = ["network-programming"]
documentation = "https://docs.rs/irc-proto/"
repository = "https://github.com/aatxe/irc"
edition = "2018"
[badges] [badges]
travis-ci = { repository = "aatxe/irc" } travis-ci = { repository = "aatxe/irc" }
@ -17,9 +18,9 @@ travis-ci = { repository = "aatxe/irc" }
default = ["bytes", "tokio", "tokio-util"] default = ["bytes", "tokio", "tokio-util"]
[dependencies] [dependencies]
encoding = "0.2.0" encoding = "0.2.33"
thiserror = "1.0.0" thiserror = "1.0.40"
bytes = { version = "1.0.0", optional = true } bytes = { version = "1.4.0", optional = true }
tokio = { version = "1.0.0", optional = true } tokio = { version = "1.27.0", optional = true }
tokio-util = { version = "0.6.0", features = ["codec"], optional = true } tokio-util = { version = "0.7.7", features = ["codec"], optional = true }

View file

@ -550,13 +550,11 @@ mod test {
#[test] #[test]
fn to_message_with_colon_in_suffix() { fn to_message_with_colon_in_suffix() {
let msg = "PRIVMSG #test ::test" let msg = "PRIVMSG #test ::test".parse::<Message>().unwrap();
.parse::<Message>()
.unwrap();
let message = Message { let message = Message {
tags: None, tags: None,
prefix: None, prefix: None,
command: PRIVMSG("#test".to_string(), ":test".to_string()) command: PRIVMSG("#test".to_string(), ":test".to_string()),
}; };
assert_eq!(msg, message); assert_eq!(msg, message);
} }

View file

@ -16,30 +16,32 @@ use tokio_socks::tcp::Socks5Stream;
#[cfg(feature = "proxy")] #[cfg(feature = "proxy")]
use crate::client::data::ProxyType; use crate::client::data::ProxyType;
#[cfg(feature = "tls-native")] #[cfg(all(feature = "tls-native", not(feature = "tls-rust")))]
use std::{fs::File, io::Read}; use std::{fs::File, io::Read};
#[cfg(feature = "tls-native")] #[cfg(all(feature = "tls-native", not(feature = "tls-rust")))]
use native_tls::{Certificate, Identity, TlsConnector}; use native_tls::{Certificate, Identity, TlsConnector};
#[cfg(feature = "tls-native")] #[cfg(all(feature = "tls-native", not(feature = "tls-rust")))]
use tokio_native_tls::{self, TlsStream}; use tokio_native_tls::{self, TlsStream};
#[cfg(feature = "tls-rust")]
use rustls_pemfile::certs;
#[cfg(feature = "tls-rust")] #[cfg(feature = "tls-rust")]
use std::{ use std::{
convert::TryFrom,
fs::File, fs::File,
io::{BufReader, Error, ErrorKind}, io::{BufReader, Error, ErrorKind},
sync::Arc, sync::Arc,
}; };
#[cfg(feature = "tls-rust")] #[cfg(feature = "tls-rust")]
use webpki_roots::TLS_SERVER_ROOTS; use tokio_rustls::client::TlsStream;
#[cfg(feature = "tls-rust")] #[cfg(feature = "tls-rust")]
use tokio_rustls::{ use tokio_rustls::{
client::TlsStream, rustls::client::{ServerCertVerified, ServerCertVerifier},
rustls::{self, internal::pemfile::certs, ClientConfig, PrivateKey}, rustls::{
webpki::DNSNameRef, self, Certificate, ClientConfig, OwnedTrustAnchor, PrivateKey, RootCertStore, ServerName,
},
TlsConnector, TlsConnector,
}; };
@ -157,7 +159,7 @@ impl Connection {
Ok(Transport::new(&config, framed, tx)) Ok(Transport::new(&config, framed, tx))
} }
#[cfg(feature = "tls-native")] #[cfg(all(feature = "tls-native", not(feature = "tls-rust")))]
async fn new_secured_transport( async fn new_secured_transport(
config: &Config, config: &Config,
tx: UnboundedSender<Message>, tx: UnboundedSender<Message>,
@ -221,44 +223,46 @@ impl Connection {
config: &Config, config: &Config,
tx: UnboundedSender<Message>, tx: UnboundedSender<Message>,
) -> error::Result<Transport<TlsStream<TcpStream>>> { ) -> error::Result<Transport<TlsStream<TcpStream>>> {
let mut builder = ClientConfig::default(); struct DangerousAcceptAllVerifier;
builder
.root_store
.add_server_trust_anchors(&TLS_SERVER_ROOTS);
if let Some(cert_path) = config.cert_path() { impl ServerCertVerifier for DangerousAcceptAllVerifier {
if let Ok(mut file) = File::open(cert_path) { fn verify_server_cert(
let mut cert_data = BufReader::new(file); &self,
builder _: &Certificate,
.root_store _: &[Certificate],
.add_pem_file(&mut cert_data) _: &ServerName,
.map_err(|_| { _: &mut dyn Iterator<Item = &[u8]>,
error::Error::Io(Error::new(ErrorKind::InvalidInput, "invalid cert")) _: &[u8],
})?; _: std::time::SystemTime,
log::info!("Added {} to trusted certificates.", cert_path); ) -> Result<ServerCertVerified, rustls::Error> {
} else { return Ok(ServerCertVerified::assertion());
return Err(error::Error::InvalidConfig {
path: config.path(),
cause: error::ConfigError::FileMissing {
file: cert_path.to_string(),
},
});
} }
} }
if let Some(client_cert_path) = config.client_cert_path() { enum ClientAuth {
if let Ok(mut file) = File::open(client_cert_path) { SingleCert(Vec<Certificate>, PrivateKey),
NoClientAuth,
}
let client_auth = if let Some(client_cert_path) = config.client_cert_path() {
if let Ok(file) = File::open(client_cert_path) {
let client_cert_data = certs(&mut BufReader::new(file)).map_err(|_| { let client_cert_data = certs(&mut BufReader::new(file)).map_err(|_| {
error::Error::Io(Error::new(ErrorKind::InvalidInput, "invalid cert")) error::Error::Io(Error::new(ErrorKind::InvalidInput, "invalid cert"))
})?; })?;
let client_cert_data = client_cert_data
.into_iter()
.map(Certificate)
.collect::<Vec<_>>();
let client_cert_pass = PrivateKey(Vec::from(config.client_cert_pass())); let client_cert_pass = PrivateKey(Vec::from(config.client_cert_pass()));
builder
.set_single_client_cert(client_cert_data, client_cert_pass)
.map_err(|err| error::Error::Io(Error::new(ErrorKind::InvalidInput, err)))?;
log::info!( log::info!(
"Using {} for client certificate authentication.", "Using {} for client certificate authentication.",
client_cert_path client_cert_path
); );
ClientAuth::SingleCert(client_cert_data, client_cert_pass)
} else { } else {
return Err(error::Error::InvalidConfig { return Err(error::Error::InvalidConfig {
path: config.path(), path: config.path(),
@ -267,15 +271,68 @@ impl Connection {
}, },
}); });
} }
} else {
ClientAuth::NoClientAuth
};
macro_rules! make_client_auth {
($builder:expr) => {
match client_auth {
ClientAuth::SingleCert(data, pass) => {
$builder.with_single_cert(data, pass).map_err(|err| {
error::Error::Io(Error::new(ErrorKind::InvalidInput, err))
})?
}
ClientAuth::NoClientAuth => $builder.with_no_client_auth(),
}
};
} }
if config.dangerously_accept_invalid_certs() { let builder = ClientConfig::builder()
builder.dangerous().set_certificate_verifier(Arc::new(DangerousAcceptAllVerifier)); .with_safe_default_cipher_suites()
} .with_safe_default_kx_groups()
.with_safe_default_protocol_versions()?;
let connector = TlsConnector::from(Arc::new(builder)); let tls_config = if config.dangerously_accept_invalid_certs() {
let domain = DNSNameRef::try_from_ascii_str(config.server()?)?; let builder =
builder.with_custom_certificate_verifier(Arc::new(DangerousAcceptAllVerifier));
make_client_auth!(builder)
} else {
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,
)
},
));
if let Some(cert_path) = config.cert_path() {
if let Ok(data) = std::fs::read(cert_path) {
root_store.add(&Certificate(data)).map_err(|_| {
error::Error::Io(Error::new(ErrorKind::InvalidInput, "invalid cert"))
})?;
log::info!("Added {} to trusted certificates.", cert_path);
} else {
return Err(error::Error::InvalidConfig {
path: config.path(),
cause: error::ConfigError::FileMissing {
file: cert_path.to_string(),
},
});
}
}
let builder = builder.with_root_certificates(root_store);
make_client_auth!(builder)
};
let connector = TlsConnector::from(Arc::new(tls_config));
let domain = ServerName::try_from(config.server()?)?;
let stream = Self::new_stream(config).await?; let stream = Self::new_stream(config).await?;
let stream = connector.connect(domain, stream).await?; let stream = connector.connect(domain, stream).await?;
let framed = Framed::new(stream, IrcCodec::new(config.encoding())?); let framed = Framed::new(stream, IrcCodec::new(config.encoding())?);
@ -371,19 +428,3 @@ impl Sink<Message> for Connection {
} }
} }
} }
#[cfg(feature = "tls-rust")]
struct DangerousAcceptAllVerifier;
#[cfg(feature = "tls-rust")]
impl rustls::ServerCertVerifier for DangerousAcceptAllVerifier {
fn verify_server_cert(
&self,
_: &rustls::RootCertStore,
_: &[rustls::Certificate],
_: DNSNameRef,
_: &[u8]
) -> Result<rustls::ServerCertVerified, rustls::TLSError> {
return Ok(rustls::ServerCertVerified::assertion());
}
}

View file

@ -523,7 +523,10 @@ impl Config {
/// Gets whether or not to dangerously accept invalid certificates. /// Gets whether or not to dangerously accept invalid certificates.
/// This defaults to `false` when not specified. /// This defaults to `false` when not specified.
pub fn dangerously_accept_invalid_certs(&self) -> bool { pub fn dangerously_accept_invalid_certs(&self) -> bool {
self.dangerously_accept_invalid_certs.as_ref().cloned().unwrap_or(false) self.dangerously_accept_invalid_certs
.as_ref()
.cloned()
.unwrap_or(false)
} }
/// Gets the path to the client authentication certificate in DER format if specified. /// Gets the path to the client authentication certificate in DER format if specified.

View file

@ -5,9 +5,8 @@ use std::sync::mpsc::RecvError;
use thiserror::Error; use thiserror::Error;
use tokio::sync::mpsc::error::{SendError, TrySendError}; use tokio::sync::mpsc::error::{SendError, TrySendError};
#[cfg(feature = "tls-rust")] #[cfg(feature = "tls-rust")]
use tokio_rustls::webpki::InvalidDNSNameError; use tokio_rustls::rustls::client::InvalidDnsNameError;
use crate::proto::error::{MessageParseError, ProtocolError}; use crate::proto::error::{MessageParseError, ProtocolError};
@ -19,26 +18,51 @@ pub type Result<T, E = Error> = std::result::Result<T, E>;
pub enum Error { pub enum Error {
/// An internal I/O error. /// An internal I/O error.
#[error("an io error occurred")] #[error("an io error occurred")]
Io(#[source] IoError), Io(
#[source]
#[from]
IoError,
),
/// An internal proxy error. /// An internal proxy error.
#[cfg(feature = "proxy")] #[cfg(feature = "proxy")]
#[error("a proxy error occurred")] #[error("a proxy error occurred")]
Proxy(tokio_socks::Error), Proxy(#[from] tokio_socks::Error),
/// An internal TLS error. /// An internal TLS error.
#[cfg(feature = "tls-native")] #[cfg(all(feature = "tls-native", not(feature = "tls-rust")))]
#[error("a TLS error occurred")] #[error("a TLS error occurred")]
Tls(#[source] native_tls::Error), Tls(
#[source]
#[from]
native_tls::Error,
),
/// An internal DNS error. /// An internal TLS error.
#[cfg(feature = "tls-rust")] #[cfg(feature = "tls-rust")]
#[error("a DNS error occurred")] #[error("a TLS error occurred")]
Dns(#[source] InvalidDNSNameError), Tls(
#[source]
#[from]
tokio_rustls::rustls::Error,
),
/// An invalid DNS name was specified.
#[cfg(feature = "tls-rust")]
#[error("invalid DNS name")]
InvalidDnsNameError(
#[source]
#[from]
InvalidDnsNameError,
),
/// An internal synchronous channel closed. /// An internal synchronous channel closed.
#[error("a sync channel closed")] #[error("a sync channel closed")]
SyncChannelClosed(#[source] RecvError), SyncChannelClosed(
#[source]
#[from]
RecvError,
),
/// An internal asynchronous channel closed. /// An internal asynchronous channel closed.
#[error("an async channel closed")] #[error("an async channel closed")]
@ -176,39 +200,6 @@ impl From<ProtocolError> for Error {
} }
} }
impl From<IoError> for Error {
fn from(e: IoError) -> Error {
Error::Io(e)
}
}
#[cfg(feature = "proxy")]
impl From<tokio_socks::Error> for Error {
fn from(e: tokio_socks::Error) -> Error {
Error::Proxy(e)
}
}
#[cfg(feature = "tls-native")]
impl From<native_tls::Error> for Error {
fn from(e: native_tls::Error) -> Error {
Error::Tls(e)
}
}
#[cfg(feature = "tls-rust")]
impl From<InvalidDNSNameError> for Error {
fn from(e: InvalidDNSNameError) -> Error {
Error::Dns(e)
}
}
impl From<RecvError> for Error {
fn from(e: RecvError) -> Error {
Error::SyncChannelClosed(e)
}
}
impl<T> From<SendError<T>> for Error { impl<T> From<SendError<T>> for Error {
fn from(_: SendError<T>) -> Error { fn from(_: SendError<T>) -> Error {
Error::AsyncChannelClosed Error::AsyncChannelClosed