feat: allow extracting TLS SNI server name and TLS PSK identity (#136)

This change allows to query for the SNI server name and the PSK
identity.

The server name implements only the DNS variant, as this is what both
APIs currently seem to support.

The PSK identity is only implemented for OpenSSL, as RustTLS currently
doesn't support TLS PSK. But it could be implemented the same way, once
this becomes available.
This commit is contained in:
Jens Reimann 2022-10-14 16:45:12 +02:00 committed by GitHub
parent bc37d9c0d7
commit eabb165dda
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 2 deletions

View file

@ -32,7 +32,7 @@ ntex-service = "0.3.1"
pin-project-lite = "0.2"
# openssl
tls_openssl = { version="0.10", package = "openssl", optional = true }
tls_openssl = { version="0.10.42", package = "openssl", optional = true }
# rustls
tls_rust = { version = "0.20", package = "rustls", optional = true }

View file

@ -28,3 +28,15 @@ static MAX_SSL_ACCEPT: AtomicUsize = AtomicUsize::new(256);
thread_local! {
static MAX_SSL_ACCEPT_COUNTER: counter::Counter = counter::Counter::new(MAX_SSL_ACCEPT.load(Ordering::Relaxed));
}
/// A TLS PSK identity.
///
/// Used in conjunction with [`ntex_io::Filter::query`]:
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct PskIdentity(pub Vec<u8>);
/// The TLS SNI server name (DNS).
///
/// Used in conjunction with [`ntex_io::Filter::query`]:
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Servername(pub String);

View file

@ -8,9 +8,11 @@ use std::{
use ntex_bytes::{BufMut, BytesVec, PoolRef};
use ntex_io::{types, Base, Filter, FilterFactory, Io, IoRef, ReadStatus, WriteStatus};
use ntex_util::{future::poll_fn, ready, time, time::Millis};
use tls_openssl::ssl::{self, SslStream};
use tls_openssl::ssl::{self, NameType, SslStream};
use tls_openssl::x509::X509;
use crate::{PskIdentity, Servername};
mod accept;
pub use self::accept::{Acceptor, AcceptorService};
@ -103,6 +105,18 @@ impl<F: Filter> Filter for SslFilter<F> {
} else {
None
}
} else if id == any::TypeId::of::<Servername>() {
if let Some(name) = self.inner.borrow().ssl().servername(NameType::HOST_NAME) {
Some(Box::new(Servername(name.to_string())))
} else {
None
}
} else if id == any::TypeId::of::<PskIdentity>() {
if let Some(psk_id) = self.inner.borrow().ssl().psk_identity() {
Some(Box::new(psk_id.to_vec()))
} else {
None
}
} else {
self.inner.borrow().get_ref().inner.query(id)
}

View file

@ -8,6 +8,7 @@ use ntex_util::{future::poll_fn, ready, time, time::Millis};
use tls_rust::{ServerConfig, ServerConnection};
use crate::rustls::{IoInner, TlsFilter, Wrapper};
use crate::Servername;
use super::{PeerCert, PeerCertChain};
@ -51,6 +52,12 @@ impl<F: Filter> Filter for TlsServerFilter<F> {
} else {
None
}
} else if id == any::TypeId::of::<Servername>() {
if let Some(name) = self.session.borrow().sni_hostname() {
Some(Box::new(Servername(name.to_string())))
} else {
None
}
} else {
self.inner.filter.query(id)
}