Skip to content

Commit 5a923ec

Browse files
authored
Allow overriding server name (#177)
Signed-off-by: Mikail Bagishov <[email protected]>
1 parent c64ea21 commit 5a923ec

File tree

2 files changed

+32
-7
lines changed

2 files changed

+32
-7
lines changed

src/connector.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub struct HttpsConnector<T> {
2121
force_https: bool,
2222
http: T,
2323
tls_config: Arc<rustls::ClientConfig>,
24+
override_server_name: Option<String>,
2425
}
2526

2627
impl<T> fmt::Debug for HttpsConnector<T> {
@@ -40,6 +41,7 @@ where
4041
force_https: false,
4142
http,
4243
tls_config: cfg.into(),
44+
override_server_name: None,
4345
}
4446
}
4547
}
@@ -83,21 +85,26 @@ where
8385
Box::pin(f)
8486
} else if sch == &http::uri::Scheme::HTTPS {
8587
let cfg = self.tls_config.clone();
86-
let hostname = dst
87-
.host()
88-
.unwrap_or_default()
89-
.to_string();
88+
let hostname = match self.override_server_name.as_deref() {
89+
Some(h) => h,
90+
None => dst.host().unwrap_or_default(),
91+
};
92+
let hostname = match rustls::ServerName::try_from(hostname) {
93+
Ok(dnsname) => dnsname,
94+
Err(_) => {
95+
let err = io::Error::new(io::ErrorKind::Other, "invalid dnsname");
96+
return Box::pin(async move { Err(Box::new(err).into()) });
97+
}
98+
};
9099
let connecting_future = self.http.call(dst);
91100

92101
let f = async move {
93102
let tcp = connecting_future
94103
.await
95104
.map_err(Into::into)?;
96105
let connector = TlsConnector::from(cfg);
97-
let dnsname = rustls::ServerName::try_from(hostname.as_str())
98-
.map_err(|_| io::Error::new(io::ErrorKind::Other, "invalid dnsname"))?;
99106
let tls = connector
100-
.connect(dnsname, tcp)
107+
.connect(hostname, tcp)
101108
.await
102109
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
103110
Ok(MaybeHttpsStream::Https(tls))

src/connector/builder.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ impl ConnectorBuilder<WantsSchemes> {
106106
ConnectorBuilder(WantsProtocols1 {
107107
tls_config: self.0.tls_config,
108108
https_only: true,
109+
override_server_name: None,
109110
})
110111
}
111112

@@ -117,6 +118,7 @@ impl ConnectorBuilder<WantsSchemes> {
117118
ConnectorBuilder(WantsProtocols1 {
118119
tls_config: self.0.tls_config,
119120
https_only: false,
121+
override_server_name: None,
120122
})
121123
}
122124
}
@@ -128,6 +130,7 @@ impl ConnectorBuilder<WantsSchemes> {
128130
pub struct WantsProtocols1 {
129131
tls_config: ClientConfig,
130132
https_only: bool,
133+
override_server_name: Option<String>,
131134
}
132135

133136
impl WantsProtocols1 {
@@ -136,6 +139,7 @@ impl WantsProtocols1 {
136139
force_https: self.https_only,
137140
http: conn,
138141
tls_config: std::sync::Arc::new(self.tls_config),
142+
override_server_name: self.override_server_name,
139143
}
140144
}
141145

@@ -169,6 +173,20 @@ impl ConnectorBuilder<WantsProtocols1> {
169173
enable_http1: false,
170174
})
171175
}
176+
177+
/// Override server name for the TLS stack
178+
///
179+
/// By default, for each connection hyper-rustls will extract host portion
180+
/// of the destination URL and verify that server certificate contains
181+
/// this value.
182+
///
183+
/// If this method is called, hyper-rustls will instead verify that server
184+
/// certificate contains `override_server_name`. Domain name included in
185+
/// the URL will not affect certificate validation.
186+
pub fn with_server_name(mut self, override_server_name: String) -> Self {
187+
self.0.override_server_name = Some(override_server_name);
188+
self
189+
}
172190
}
173191

174192
/// State of a builder with HTTP1 enabled, that may have some other

0 commit comments

Comments
 (0)