diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..a25a72d00 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*.rs] +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 4 +tab_width = 4 diff --git a/core/lib/src/listener/connection.rs b/core/lib/src/listener/connection.rs index c838980f7..224ccf12a 100644 --- a/core/lib/src/listener/connection.rs +++ b/core/lib/src/listener/connection.rs @@ -22,6 +22,8 @@ pub trait Connection: AsyncRead + AsyncWrite + Send + Unpin { /// Defaults to an empty vector to indicate that no certificates were /// presented. fn certificates(&self) -> Option> { None } + + fn server_name(&self) -> Option<&str> { None } } impl Connection for Either { diff --git a/core/lib/src/request/request.rs b/core/lib/src/request/request.rs index 4721bf83d..c281b5575 100644 --- a/core/lib/src/request/request.rs +++ b/core/lib/src/request/request.rs @@ -45,13 +45,19 @@ pub(crate) struct ConnectionMeta { pub peer_endpoint: Option, #[cfg_attr(not(feature = "mtls"), allow(dead_code))] pub peer_certs: Option>>, + #[cfg_attr(feature = "tls", allow(dead_code))] + pub server_name: Option, } impl ConnectionMeta { - pub fn new(endpoint: io::Result, certs: Option>) -> Self { + pub fn new( + endpoint: io::Result, + certs: Option>, + server_name: Option<&str>) -> Self { ConnectionMeta { peer_endpoint: endpoint.ok(), peer_certs: certs.map(|c| c.into_owned()).map(Arc::new), + server_name: server_name.map(|s| s.to_string()), } } } @@ -295,6 +301,16 @@ impl<'r> Request<'r> { self.state.host.as_ref() } + /// Returns the resolved SNI server name requested in the TLS handshake, if + /// any. + /// + /// Ideally, this will match the `Host` header in the request. + #[cfg(feature = "tls")] + #[inline(always)] + pub fn sni(&mut self) -> Option<&str> { + self.connection.server_name.as_deref() + } + /// Sets the host of `self` to `host`. /// /// # Example diff --git a/core/lib/src/server.rs b/core/lib/src/server.rs index badfb44c9..4f999c2b2 100644 --- a/core/lib/src/server.rs +++ b/core/lib/src/server.rs @@ -172,7 +172,11 @@ impl Rocket { let (listener, rocket, server) = (listener.clone(), self.clone(), server.clone()); spawn_inspect(|e| log_server_error(&**e), async move { let conn = listener.connect(accept).race_io(rocket.shutdown()).await?; - let meta = ConnectionMeta::new(conn.endpoint(), conn.certificates()); + let meta = ConnectionMeta::new( + conn.endpoint(), + conn.certificates(), + conn.server_name() + ); let service = service_fn(|mut req| { let upgrade = hyper::upgrade::on(&mut req); let (parts, incoming) = req.into_parts(); @@ -205,7 +209,7 @@ impl Rocket { while let Some(mut conn) = stream.accept().race_io(rocket.shutdown()).await? { let rocket = rocket.clone(); spawn_inspect(|e: &io::Error| log_server_error(e), async move { - let meta = ConnectionMeta::new(conn.endpoint(), None); + let meta = ConnectionMeta::new(conn.endpoint(), None, None); let rx = conn.rx.cancellable(rocket.shutdown.clone()); let response = rocket.clone() .service(conn.parts, rx, None, meta) diff --git a/core/lib/src/tls/listener.rs b/core/lib/src/tls/listener.rs index 3bdf3f566..258b406d3 100644 --- a/core/lib/src/tls/listener.rs +++ b/core/lib/src/tls/listener.rs @@ -96,4 +96,13 @@ impl Connection for TlsStream { #[cfg(not(feature = "mtls"))] None } + + fn server_name(&self) -> Option<&str> { + #[cfg(feature = "tls")] { + self.get_ref().1.server_name() + } + + #[cfg(not(feature = "tls"))] + None + } }