Compare commits
No commits in common. "2a097fb800302fd238244e42581c01e02bfdee10" and "6e4722d060fb550b8027f9219b2d124775de17a2" have entirely different histories.
2a097fb800
...
6e4722d060
4 changed files with 51 additions and 55 deletions
26
Cargo.toml
26
Cargo.toml
|
@ -12,25 +12,15 @@ categories = ["network-programming"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base16ct = "0.2.0"
|
base16ct = "0.2.0"
|
||||||
base64ct = "1.6.0"
|
base64ct = "1.6.0"
|
||||||
sha2 = "0.10.8"
|
|
||||||
|
|
||||||
num_enum = "0.7.3"
|
|
||||||
bytes = "1.7.1"
|
bytes = "1.7.1"
|
||||||
|
dashmap = { version = "6.0.1", optional = true }
|
||||||
mime = "0.3.17"
|
mime = "0.3.17"
|
||||||
url = "2.5.2"
|
num_enum = "0.7.3"
|
||||||
|
sha2 = "0.10.8"
|
||||||
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"] }
|
||||||
webpki-roots = { version = "0.26.3", optional = true }
|
url = "2.5.2"
|
||||||
|
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"
|
||||||
|
@ -40,3 +30,9 @@ 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,21 +24,15 @@ 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(
|
match wv.verify_server_cert(end_entity, intermediates, server_name, ocsp_response, now)
|
||||||
end_entity,
|
{
|
||||||
_intermediates,
|
|
||||||
server_name,
|
|
||||||
_ocsp_response,
|
|
||||||
now,
|
|
||||||
) {
|
|
||||||
Ok(verified) => {
|
Ok(verified) => {
|
||||||
return Ok(verified);
|
return Ok(verified);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,12 @@ use crate::{
|
||||||
Client,
|
Client,
|
||||||
};
|
};
|
||||||
|
|
||||||
use tokio_rustls::rustls::{self, client::danger::ServerCertVerifier, SupportedProtocolVersion};
|
use tokio_rustls::rustls::{
|
||||||
|
self,
|
||||||
#[cfg(feature = "webpki")]
|
client::{danger::ServerCertVerifier, WebPkiServerVerifier},
|
||||||
use tokio_rustls::rustls::{client::WebPkiServerVerifier, pki_types::TrustAnchor};
|
pki_types::TrustAnchor,
|
||||||
|
SupportedProtocolVersion,
|
||||||
|
};
|
||||||
|
|
||||||
/// Builder for creating configured [`Client`] instance
|
/// Builder for creating configured [`Client`] instance
|
||||||
pub struct ClientBuilder {
|
pub struct ClientBuilder {
|
||||||
|
@ -56,32 +58,24 @@ 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 {
|
||||||
let webpki_verifier = {
|
|
||||||
#[cfg(feature = "webpki")]
|
|
||||||
if !self.root_certs.is_empty() {
|
|
||||||
Some(
|
|
||||||
WebPkiServerVerifier::builder_with_provider(
|
|
||||||
Arc::new(self.root_certs),
|
|
||||||
provider.clone(),
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
// panics only if roots are empty (that is checked above)
|
|
||||||
// or CRLs couldn't be parsed (we didn't provide any)
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "webpki"))]
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
tls_config
|
tls_config
|
||||||
.dangerous()
|
.dangerous()
|
||||||
.with_custom_certificate_verifier(Arc::new(CustomCertVerifier {
|
.with_custom_certificate_verifier(Arc::new(CustomCertVerifier {
|
||||||
provider: provider.clone(),
|
provider: provider.clone(),
|
||||||
webpki_verifier,
|
webpki_verifier: if !self.root_certs.is_empty() {
|
||||||
|
Some(
|
||||||
|
WebPkiServerVerifier::builder_with_provider(
|
||||||
|
Arc::new(self.root_certs),
|
||||||
|
provider,
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
// panics only if roots are empty (that is checked above)
|
||||||
|
// or CRLs couldn't be parsed (we didn't provide any)
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
ss_allowed: true,
|
ss_allowed: true,
|
||||||
ss_verifier: ssv,
|
ss_verifier: ssv,
|
||||||
}))
|
}))
|
||||||
|
@ -108,7 +102,6 @@ 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());
|
||||||
|
@ -117,7 +110,6 @@ 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,6 +8,7 @@ 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::{
|
||||||
|
@ -24,6 +25,19 @@ 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]
|
||||||
|
@ -93,8 +107,8 @@ impl Client {
|
||||||
host: &str,
|
host: &str,
|
||||||
port: u16,
|
port: u16,
|
||||||
) -> Result<Response, LibError> {
|
) -> Result<Response, LibError> {
|
||||||
let addr = tokio::net::lookup_host((host, port))
|
let addr = (host, port)
|
||||||
.await?
|
.to_socket_addrs()?
|
||||||
.next()
|
.next()
|
||||||
.ok_or(InvalidUrl::ConvertError)?;
|
.ok_or(InvalidUrl::ConvertError)?;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue