Skip to content

Commit b551597

Browse files
committed
add sni
1 parent 2496870 commit b551597

2 files changed

Lines changed: 130 additions & 7 deletions

File tree

src/http/server.rs

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ use crate::private::mutex::{Mutex, RawMutex};
3535
pub struct CHttpsSslConfig(pub httpd_ssl_config_t);
3636

3737

38+
#[cfg(all(esp_idf_esp_tls_server_sni_hook, esp_idf_comp_esp_http_server_enabled))]
39+
use super::sni::*;
40+
3841
#[derive(Copy, Clone, Debug)]
3942
pub struct Configuration {
4043
pub http_port: u16,
@@ -92,7 +95,7 @@ impl From<&Configuration> for Newtype<httpd_config_t> {
9295
}
9396
}
9497

95-
#[derive(Debug)]
98+
#[cfg_attr(not(esp_idf_esp_tls_server_sni_hook), derive(Debug))]
9699
pub struct SslConfiguration<'a> {
97100
pub http_configuration: Configuration,
98101
pub client_verify_cert: Option<&'a str>,
@@ -103,17 +106,40 @@ pub struct SslConfiguration<'a> {
103106
#[cfg(esp_idf_version_major = "5")]
104107
pub use_secure_element: bool,
105108
pub session_tickets: bool,
109+
110+
#[cfg(esp_idf_esp_tls_server_sni_hook)]
111+
pub sni: Option<Box<dyn SNICB<'a>>>,
106112
}
107113

114+
#[cfg(esp_idf_esp_tls_server_sni_hook)]
115+
impl<'a> Debug for SslConfiguration<'a> {
116+
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
117+
118+
let sni_s = if self.sni.is_some() {
119+
"Some(..)"
120+
} else { "None" };
121+
122+
f.write_fmt(format_args!(
123+
"SslConfiguration {{ http_configuration = {:?}, client_verify_cert = {:?}, cacert = {:?}, prvtkey = {:?}, transport_mode_secure = {:?}, session_tickets = {:?}, use_secure_element = {:?}, sni = {:?} }}",
124+
self.http_configuration,
125+
self.client_verify_cert,
126+
self.cacert,
127+
self.prvtkey,
128+
self.transport_mode_secure,
129+
self.use_secure_element,
130+
self.session_tickets,
131+
sni_s
132+
))
133+
}
134+
}
135+
136+
108137
impl<'a> From<&SslConfiguration<'a>> for Newtype<httpd_config_t> {
109138
fn from(conf: &SslConfiguration<'a>) -> Self {
110139
Self::from(&conf.http_configuration)
111140
}
112141
}
113142

114-
115-
116-
117143
#[cfg(esp_idf_version_major = "5")]
118144
impl<'a> From<&SslConfiguration<'a>> for CHttpsSslConfig {
119145
fn from(conf: &SslConfiguration) -> Self {
@@ -137,6 +163,10 @@ impl<'a> From<&SslConfiguration<'a>> for CHttpsSslConfig {
137163
port_insecure: conf.http_configuration.http_port,
138164
session_tickets: conf.session_tickets,
139165
user_cb: None,
166+
#[cfg(esp_idf_esp_tls_server_sni_hook)]
167+
sni_callback: Some(sni_trampoline),
168+
#[cfg(esp_idf_esp_tls_server_sni_hook)]
169+
sni_callback_p_info: conf.sni.as_ref().map(|cb| cb as *const _ as *mut c_types::c_void).unwrap_or(ptr::null_mut() as _),
140170
})
141171
}
142172
}
@@ -163,7 +193,11 @@ impl<'a> From<&SslConfiguration<'a>> for CHttpsSslConfig {
163193
port_insecure: conf.http_configuration.http_port,
164194
use_secure_element: false,
165195
session_tickets: conf.session_tickets,
166-
user_cb: None
196+
user_cb: None,
197+
#[cfg(esp_idf_esp_tls_server_sni_hook)]
198+
sni_callback: Some(sni_trampoline),
199+
#[cfg(esp_idf_esp_tls_server_sni_hook)]
200+
sni_callback_p_info: conf.sni.as_ref().map(|cb| cb as *const _ as *mut c_types::c_void).unwrap_or(ptr::null_mut() as _),
167201
})
168202
}
169203
}
@@ -176,7 +210,12 @@ impl<'a> Default for SslConfiguration<'a> {
176210
cacert: None,
177211
prvtkey: None,
178212
transport_mode_secure: true,
179-
session_tickets: false
213+
session_tickets: false,
214+
#[cfg(esp_idf_version_major = "5")]
215+
use_secure_element: false,
216+
217+
#[cfg(esp_idf_esp_tls_server_sni_hook)]
218+
sni: None
180219
}
181220
}
182221
}
@@ -219,7 +258,6 @@ impl Drop for CHttpsSslConfig {
219258
}
220259
}
221260

222-
223261
#[allow(non_upper_case_globals)]
224262
impl From<Newtype<c_types::c_uint>> for Method {
225263
fn from(method: Newtype<c_types::c_uint>) -> Self {

src/http/sni.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use std::ffi::CStr;
2+
use std::ptr;
3+
use esp_idf_sys::*;
4+
use log::*;
5+
6+
// Workaround for unstable feature 'trait_alias'
7+
pub trait SNICB<'a>: FnMut(&'a str) -> SNIResult<'a> { }
8+
9+
// Workaround for unstable feature 'trait_alias'
10+
impl<'a, T> SNICB<'a> for T
11+
where T: FnMut(&'a str) -> SNIResult<'a> {
12+
}
13+
14+
pub struct HandshakeServerCertificate<'a> {
15+
pub pk: &'a mut mbedtls_pk_context,
16+
pub cert: &'a mut mbedtls_x509_crt,
17+
}
18+
19+
pub struct HandshakeCertifiacteAuthority<'a> {
20+
pub ca: &'a mut mbedtls_x509_crt,
21+
pub crl: &'a mut mbedtls_x509_crl,
22+
}
23+
24+
pub struct HandshakeVerifyMode(c_types::c_int);
25+
26+
pub struct SNIResult<'a> {
27+
server_certificate: Option<HandshakeServerCertificate<'a>>,
28+
certificate_authority: Option<HandshakeCertifiacteAuthority<'a>>,
29+
verify_mode: Option<HandshakeVerifyMode>
30+
}
31+
32+
impl<'a> SNIResult<'a> {
33+
pub fn new() -> SNIResult<'a> { SNIResult { server_certificate: None, certificate_authority: None, verify_mode: None }}
34+
35+
pub fn set_hs_server_certficate(mut self, pk: &'a mut mbedtls_pk_context, cert: &'a mut mbedtls_x509_crt) -> SNIResult<'a> {
36+
self.server_certificate = Some(HandshakeServerCertificate { pk, cert });
37+
self
38+
}
39+
40+
pub fn set_hs_certificate_authority(mut self, ca: &'a mut mbedtls_x509_crt, crl: &'a mut mbedtls_x509_crl) -> SNIResult<'a> {
41+
self.certificate_authority = Some(HandshakeCertifiacteAuthority { ca, crl });
42+
self
43+
}
44+
45+
pub fn set_hs_verify_mode(mut self, verify_mode: u32) -> SNIResult<'a> {
46+
self.verify_mode = Some(HandshakeVerifyMode(verify_mode as _));
47+
self
48+
}
49+
}
50+
51+
unsafe extern "C" fn f_rng(_arg: *mut c_types::c_void, ptr: *mut u8 , bytes: u32) -> i32 {
52+
esp_fill_random(ptr as _, bytes);
53+
bytes as _
54+
}
55+
56+
pub(crate) unsafe extern "C" fn sni_trampoline<'a>(p_info: *mut c_types::c_void, ssl: *mut mbedtls_ssl_context, name: *const c_types::c_uchar, _len: c_types::c_uint) -> esp_err_t
57+
{
58+
let cb = &mut *(p_info as *mut Box<dyn SNICB<'a>>);
59+
60+
let name = CStr::from_ptr(name as _).to_str().unwrap();
61+
62+
let SNIResult { server_certificate, certificate_authority, verify_mode } = cb(name);
63+
64+
if let Some(HandshakeServerCertificate { pk, cert }) = server_certificate {
65+
if let Err(err) = esp!(mbedtls_pk_check_pair(&mut cert.pk, pk, Some(f_rng), ptr::null_mut())) {
66+
error!("Certificate and private key supplied by the SNI callback do not match: {:?}", err);
67+
return err.code()
68+
};
69+
70+
if let Err(err) = esp!(mbedtls_ssl_set_hs_own_cert(ssl, cert, pk)) {
71+
error!("Could not set handshake certificate and private key: {:?}", err);
72+
return err.code()
73+
};
74+
};
75+
76+
if let Some(HandshakeCertifiacteAuthority { ca, crl }) = certificate_authority {
77+
mbedtls_ssl_set_hs_ca_chain(ssl, ca, crl)
78+
};
79+
80+
if let Some(HandshakeVerifyMode(authmode)) = verify_mode {
81+
mbedtls_ssl_set_hs_authmode(ssl, authmode)
82+
};
83+
84+
return ESP_OK;
85+
}

0 commit comments

Comments
 (0)