diff --git a/src/http/server.rs b/src/http/server.rs index dc95f9524d1..7b24bf850b9 100644 --- a/src/http/server.rs +++ b/src/http/server.rs @@ -35,6 +35,9 @@ use crate::private::mutex::{Mutex, RawMutex}; pub struct CHttpsSslConfig(pub httpd_ssl_config_t); +#[cfg(all(esp_idf_esp_tls_server_sni_hook, esp_idf_comp_esp_http_server_enabled))] +use super::sni::*; + #[derive(Copy, Clone, Debug)] pub struct Configuration { pub http_port: u16, @@ -92,7 +95,7 @@ impl From<&Configuration> for Newtype { } } -#[derive(Debug)] +#[cfg_attr(not(esp_idf_esp_tls_server_sni_hook), derive(Debug))] pub struct SslConfiguration<'a> { pub http_configuration: Configuration, pub client_verify_cert: Option<&'a str>, @@ -100,6 +103,30 @@ pub struct SslConfiguration<'a> { pub prvtkey: Option<&'a str>, pub transport_mode_secure: bool, pub session_tickets: bool, + + #[cfg(esp_idf_esp_tls_server_sni_hook)] + pub sni: Option>>, +} + +#[cfg(esp_idf_esp_tls_server_sni_hook)] +impl<'a> Debug for SslConfiguration<'a> { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + + let sni_s = if self.sni.is_some() { + "Some(..)" + } else { "None" }; + + f.write_fmt(format_args!( + "SslConfiguration {{ http_configuration = {:?}, client_verify_cert = {:?}, cacert = {:?}, prvtkey = {:?}, transport_mode_secure = {:?}, session_tickets = {:?}, sni = {:?} }}", + self.http_configuration, + self.client_verify_cert, + self.cacert, + self.prvtkey, + self.transport_mode_secure, + self.session_tickets, + sni_s + )) + } } impl<'a> From<&SslConfiguration<'a>> for Newtype { @@ -128,7 +155,11 @@ impl<'a> From<&SslConfiguration<'a>> for CHttpsSslConfig { port_secure: conf.http_configuration.https_port, port_insecure: conf.http_configuration.http_port, session_tickets: conf.session_tickets, - user_cb: None + user_cb: None, + #[cfg(esp_idf_esp_tls_server_sni_hook)] + sni_callback: Some(sni_trampoline), + #[cfg(esp_idf_esp_tls_server_sni_hook)] + 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 _), }) } } @@ -141,7 +172,10 @@ impl<'a> Default for SslConfiguration<'a> { cacert: None, prvtkey: None, transport_mode_secure: true, - session_tickets: false + session_tickets: false, + + #[cfg(esp_idf_esp_tls_server_sni_hook)] + sni: None } } } diff --git a/src/http/sni.rs b/src/http/sni.rs new file mode 100644 index 00000000000..9cc9dc032dc --- /dev/null +++ b/src/http/sni.rs @@ -0,0 +1,82 @@ +use std::ffi::CStr; +use esp_idf_sys::*; +use log::*; + +// Workaround for unstable feature 'trait_alias' +pub trait SNICB<'a>: FnMut(&'a str) -> SNIResult<'a> { } + +// Workaround for unstable feature 'trait_alias' +impl<'a, T> SNICB<'a> for T + where T: FnMut(&'a str) -> SNIResult<'a> { +} + + +pub struct HandshakeServerCertificate<'a> { + pub pk: &'a mut mbedtls_pk_context, + pub cert: &'a mut mbedtls_x509_crt, +} + +pub struct HandshakeCertifiacteAuthority<'a> { + pub ca: &'a mut mbedtls_x509_crt, + pub crl: &'a mut mbedtls_x509_crl, +} + +pub struct HandshakeVerifyMode(c_types::c_int); + +pub struct SNIResult<'a> { + server_certificate: Option>, + certificate_authority: Option>, + verify_mode: Option +} + +impl<'a> SNIResult<'a> { + pub fn new() -> SNIResult<'a> { SNIResult { server_certificate: None, certificate_authority: None, verify_mode: None }} + + pub fn set_hs_server_certficate(mut self, pk: &'a mut mbedtls_pk_context, cert: &'a mut mbedtls_x509_crt) -> SNIResult<'a> { + self.server_certificate = Some(HandshakeServerCertificate { pk, cert }); + self + } + + pub fn set_hs_certificate_authority(mut self, ca: &'a mut mbedtls_x509_crt, crl: &'a mut mbedtls_x509_crl) -> SNIResult<'a> { + self.certificate_authority = Some(HandshakeCertifiacteAuthority { ca, crl }); + self + } + + pub fn set_hs_verify_mode(mut self, verify_mode: u32) -> SNIResult<'a> { + self.verify_mode = Some(HandshakeVerifyMode(verify_mode as _)); + self + } +} + + +#[cfg(esp_idf_esp_tls_server_sni_hook)] +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 +{ + let cb = &mut *(p_info as *mut Box>); + + let name = CStr::from_ptr(name as _).to_str().unwrap(); + + let SNIResult { server_certificate, certificate_authority, verify_mode } = cb(name); + + if let Some(HandshakeServerCertificate { pk, cert }) = server_certificate { + if let Err(err) = esp!(mbedtls_pk_check_pair(&mut cert.pk, pk)) { + error!("Certificate and private key supplied by the SNI callback do not match: {:?}", err); + return err.code() + }; + + if let Err(err) = esp!(mbedtls_ssl_set_hs_own_cert(ssl, cert, pk)) { + error!("Could not set handshake certificate and private key: {:?}", err); + return err.code() + }; + }; + + if let Some(HandshakeCertifiacteAuthority { ca, crl }) = certificate_authority { + mbedtls_ssl_set_hs_ca_chain(ssl, ca, crl) + }; + + if let Some(HandshakeVerifyMode(authmode)) = verify_mode { + mbedtls_ssl_set_hs_authmode(ssl, authmode) + }; + + return ESP_OK; +} diff --git a/src/wifi.rs b/src/wifi.rs index c352a21f67a..864606f3bbd 100644 --- a/src/wifi.rs +++ b/src/wifi.rs @@ -174,7 +174,7 @@ impl From> for AccessPointInfo { wifi_second_chan_t_WIFI_SECOND_CHAN_BELOW => SecondaryChannel::Below, _ => panic!(), }, - signal_strength: a.rssi as _, + signal_strength: a.rssi as u8, protocols: EnumSet::::empty(), // TODO auth_method: AuthMethod::from(Newtype::(a.authmode)), } @@ -639,7 +639,7 @@ where WifiDriver::is_started(self) } - fn is_connected(&self) -> Result { + fn is_up(&self) -> Result { WifiDriver::is_up(self) } @@ -660,22 +660,6 @@ where fn scan(&mut self) -> Result, Self::Error> { WifiDriver::scan(self) } - - fn start(&mut self) -> Result<(), Self::Error> { - WifiDriver::start(self) - } - - fn stop(&mut self) -> Result<(), Self::Error> { - WifiDriver::stop(self) - } - - fn connect(&mut self) -> Result<(), Self::Error> { - WifiDriver::connect(self) - } - - fn disconnect(&mut self) -> Result<(), Self::Error> { - WifiDriver::disconnect(self) - } } #[cfg(esp_idf_comp_esp_netif_enabled)] @@ -869,7 +853,7 @@ where EspWifi::is_started(self) } - fn is_connected(&self) -> Result { + fn is_up(&self) -> Result { EspWifi::is_up(self) } @@ -887,25 +871,9 @@ where EspWifi::scan_n(self) } - fn scan(&mut self) -> Result, Self::Error> { + fn scan(&mut self) -> Result, Self::Error> { EspWifi::scan(self) } - - fn start(&mut self) -> Result<(), Self::Error> { - EspWifi::start(self) - } - - fn stop(&mut self) -> Result<(), Self::Error> { - EspWifi::stop(self) - } - - fn connect(&mut self) -> Result<(), Self::Error> { - EspWifi::connect(self) - } - - fn disconnect(&mut self) -> Result<(), Self::Error> { - EspWifi::disconnect(self) - } } #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -1120,7 +1088,7 @@ where EspRawWifi::is_started(self) } - fn is_connected(&self) -> Result { + fn is_up(&self) -> Result { EspRawWifi::is_up(self) } @@ -1141,22 +1109,6 @@ where fn scan(&mut self) -> Result, Self::Error> { EspRawWifi::scan(self) } - - fn start(&mut self) -> Result<(), Self::Error> { - EspRawWifi::start(self) - } - - fn stop(&mut self) -> Result<(), Self::Error> { - EspRawWifi::stop(self) - } - - fn connect(&mut self) -> Result<(), Self::Error> { - EspRawWifi::connect(self) - } - - fn disconnect(&mut self) -> Result<(), Self::Error> { - EspRawWifi::disconnect(self) - } } #[derive(Copy, Clone, Debug, Eq, PartialEq)]