Compare commits
3 commits
6e4722d060
...
2a097fb800
Author | SHA1 | Date | |
---|---|---|---|
2a097fb800 | |||
d6db194a1a | |||
cc8a62c19e |
4 changed files with 56 additions and 52 deletions
28
Cargo.toml
28
Cargo.toml
|
@ -12,15 +12,25 @@ categories = ["network-programming"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base16ct = "0.2.0"
|
base16ct = "0.2.0"
|
||||||
base64ct = "1.6.0"
|
base64ct = "1.6.0"
|
||||||
bytes = "1.7.1"
|
|
||||||
dashmap = { version = "6.0.1", optional = true }
|
|
||||||
mime = "0.3.17"
|
|
||||||
num_enum = "0.7.3"
|
|
||||||
sha2 = "0.10.8"
|
sha2 = "0.10.8"
|
||||||
|
|
||||||
|
num_enum = "0.7.3"
|
||||||
|
bytes = "1.7.1"
|
||||||
|
mime = "0.3.17"
|
||||||
|
url = "2.5.2"
|
||||||
|
|
||||||
tokio = { version = "1.39.2", features = ["io-util", "net"] }
|
tokio = { version = "1.39.2", features = ["io-util", "net"] }
|
||||||
tokio-rustls = { version = "0.26.0", default-features = false, features = ["ring"] }
|
tokio-rustls = { version = "0.26.0", default-features = false, features = ["ring"] }
|
||||||
url = "2.5.2"
|
webpki-roots = { version = "0.26.3", optional = true }
|
||||||
webpki-roots = "0.26.3"
|
|
||||||
|
dashmap = { version = "6.0.1", optional = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tokio = { version = "1.39.2", features = ["macros", "rt-multi-thread"] }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
webpki = ["dep:webpki-roots"]
|
||||||
|
file-sscv = ["dep:dashmap", "tokio/fs"]
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "simple"
|
name = "simple"
|
||||||
|
@ -30,9 +40,3 @@ path = "examples/simple.rs"
|
||||||
name = "main"
|
name = "main"
|
||||||
path = "examples/main.rs"
|
path = "examples/main.rs"
|
||||||
required-features = ["file-sscv"]
|
required-features = ["file-sscv"]
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
tokio = { version = "1.39.2", features = ["macros", "rt-multi-thread"] }
|
|
||||||
|
|
||||||
[features]
|
|
||||||
file-sscv = ["dep:dashmap", "tokio/fs"]
|
|
||||||
|
|
|
@ -24,15 +24,21 @@ impl ServerCertVerifier for CustomCertVerifier {
|
||||||
fn verify_server_cert(
|
fn verify_server_cert(
|
||||||
&self,
|
&self,
|
||||||
end_entity: &CertificateDer<'_>,
|
end_entity: &CertificateDer<'_>,
|
||||||
intermediates: &[CertificateDer<'_>],
|
_intermediates: &[CertificateDer<'_>],
|
||||||
server_name: &ServerName<'_>,
|
server_name: &ServerName<'_>,
|
||||||
ocsp_response: &[u8],
|
_ocsp_response: &[u8],
|
||||||
now: UnixTime,
|
now: UnixTime,
|
||||||
) -> Result<ServerCertVerified, rustls::Error> {
|
) -> Result<ServerCertVerified, rustls::Error> {
|
||||||
// if webpki CA certs enabled
|
// if webpki CA certs enabled
|
||||||
|
#[cfg(feature = "webpki")]
|
||||||
if let Some(wv) = &self.webpki_verifier {
|
if let Some(wv) = &self.webpki_verifier {
|
||||||
match wv.verify_server_cert(end_entity, intermediates, server_name, ocsp_response, now)
|
match wv.verify_server_cert(
|
||||||
{
|
end_entity,
|
||||||
|
_intermediates,
|
||||||
|
server_name,
|
||||||
|
_ocsp_response,
|
||||||
|
now,
|
||||||
|
) {
|
||||||
Ok(verified) => {
|
Ok(verified) => {
|
||||||
return Ok(verified);
|
return Ok(verified);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,10 @@ use crate::{
|
||||||
Client,
|
Client,
|
||||||
};
|
};
|
||||||
|
|
||||||
use tokio_rustls::rustls::{
|
use tokio_rustls::rustls::{self, client::danger::ServerCertVerifier, SupportedProtocolVersion};
|
||||||
self,
|
|
||||||
client::{danger::ServerCertVerifier, WebPkiServerVerifier},
|
#[cfg(feature = "webpki")]
|
||||||
pki_types::TrustAnchor,
|
use tokio_rustls::rustls::{client::WebPkiServerVerifier, pki_types::TrustAnchor};
|
||||||
SupportedProtocolVersion,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Builder for creating configured [`Client`] instance
|
/// Builder for creating configured [`Client`] instance
|
||||||
pub struct ClientBuilder {
|
pub struct ClientBuilder {
|
||||||
|
@ -58,15 +56,13 @@ impl ClientBuilder {
|
||||||
let tls_config = if let Some(cv) = self.custom_verifier {
|
let tls_config = if let Some(cv) = self.custom_verifier {
|
||||||
tls_config.dangerous().with_custom_certificate_verifier(cv)
|
tls_config.dangerous().with_custom_certificate_verifier(cv)
|
||||||
} else if let Some(ssv) = self.ss_verifier {
|
} else if let Some(ssv) = self.ss_verifier {
|
||||||
tls_config
|
let webpki_verifier = {
|
||||||
.dangerous()
|
#[cfg(feature = "webpki")]
|
||||||
.with_custom_certificate_verifier(Arc::new(CustomCertVerifier {
|
if !self.root_certs.is_empty() {
|
||||||
provider: provider.clone(),
|
|
||||||
webpki_verifier: if !self.root_certs.is_empty() {
|
|
||||||
Some(
|
Some(
|
||||||
WebPkiServerVerifier::builder_with_provider(
|
WebPkiServerVerifier::builder_with_provider(
|
||||||
Arc::new(self.root_certs),
|
Arc::new(self.root_certs),
|
||||||
provider,
|
provider.clone(),
|
||||||
)
|
)
|
||||||
.build()
|
.build()
|
||||||
// panics only if roots are empty (that is checked above)
|
// panics only if roots are empty (that is checked above)
|
||||||
|
@ -75,7 +71,17 @@ impl ClientBuilder {
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "webpki"))]
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
tls_config
|
||||||
|
.dangerous()
|
||||||
|
.with_custom_certificate_verifier(Arc::new(CustomCertVerifier {
|
||||||
|
provider: provider.clone(),
|
||||||
|
webpki_verifier,
|
||||||
ss_allowed: true,
|
ss_allowed: true,
|
||||||
ss_verifier: ssv,
|
ss_verifier: ssv,
|
||||||
}))
|
}))
|
||||||
|
@ -102,6 +108,7 @@ impl ClientBuilder {
|
||||||
/// Include webpki trust anchors.
|
/// Include webpki trust anchors.
|
||||||
/// Not recommended (useless) as most Gemini capsules use self-signed
|
/// Not recommended (useless) as most Gemini capsules use self-signed
|
||||||
/// TLS certs and properly configured TOFU policy is enough.
|
/// TLS certs and properly configured TOFU policy is enough.
|
||||||
|
#[cfg(feature = "webpki")]
|
||||||
pub fn with_webpki_roots(mut self) -> Self {
|
pub fn with_webpki_roots(mut self) -> Self {
|
||||||
self.root_certs
|
self.root_certs
|
||||||
.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
|
.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
|
||||||
|
@ -110,6 +117,7 @@ impl ClientBuilder {
|
||||||
|
|
||||||
/// Include custom trust anchors.
|
/// Include custom trust anchors.
|
||||||
/// Not recommended (useless), see note for [`ClientBuilder::with_webpki_roots`].
|
/// Not recommended (useless), see note for [`ClientBuilder::with_webpki_roots`].
|
||||||
|
#[cfg(feature = "webpki")]
|
||||||
pub fn with_custom_roots(
|
pub fn with_custom_roots(
|
||||||
mut self,
|
mut self,
|
||||||
iter: impl IntoIterator<Item = TrustAnchor<'static>>,
|
iter: impl IntoIterator<Item = TrustAnchor<'static>>,
|
||||||
|
|
|
@ -8,7 +8,6 @@ pub use response::Response;
|
||||||
use crate::{error::*, status::*};
|
use crate::{error::*, status::*};
|
||||||
use builder::ClientBuilder;
|
use builder::ClientBuilder;
|
||||||
|
|
||||||
use std::net::ToSocketAddrs;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use tokio::{
|
use tokio::{
|
||||||
|
@ -25,19 +24,6 @@ pub struct Client {
|
||||||
connector: TlsConnector,
|
connector: TlsConnector,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Client {
|
|
||||||
/// Create a Client with webpki_roots trust anchors and no client auth cert.
|
|
||||||
/// Will be possibly removed in next versions.
|
|
||||||
fn default() -> Self {
|
|
||||||
let roots =
|
|
||||||
rustls::RootCertStore::from_iter(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
|
|
||||||
let config = rustls::ClientConfig::builder()
|
|
||||||
.with_root_certificates(roots)
|
|
||||||
.with_no_client_auth();
|
|
||||||
Client::from(config)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<rustls::ClientConfig> for Client {
|
impl From<rustls::ClientConfig> for Client {
|
||||||
/// Create a Client from a Rustls config.
|
/// Create a Client from a Rustls config.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -107,8 +93,8 @@ impl Client {
|
||||||
host: &str,
|
host: &str,
|
||||||
port: u16,
|
port: u16,
|
||||||
) -> Result<Response, LibError> {
|
) -> Result<Response, LibError> {
|
||||||
let addr = (host, port)
|
let addr = tokio::net::lookup_host((host, port))
|
||||||
.to_socket_addrs()?
|
.await?
|
||||||
.next()
|
.next()
|
||||||
.ok_or(InvalidUrl::ConvertError)?;
|
.ok_or(InvalidUrl::ConvertError)?;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue