This commit is contained in:
Moritz Ruth 2024-03-07 15:37:42 +01:00
parent 2059555174
commit 4d476c5e42
Signed by: moritzruth
GPG key ID: C9BBAB79405EE56D
5 changed files with 161 additions and 166 deletions

View file

@ -12,11 +12,14 @@ log = "0.4.20"
tokio = { version = "1.35.1", features = ["macros", "parking_lot", "rt", "sync"] }
serde = { version = "1.0.196", features = ["derive"] }
serde_json = "1.0.114"
reqwest = "0.11.24"
reqwest = { version = "0.11.24", default-features = false, features = ["rustls-tls-native-roots"] }
url = { version = "2.5.0", features = ["serde"] }
tokio-tungstenite = { version = "0.21.0", features = ["native-tls"] }
tokio-tungstenite = { version = "0.21.0", features = ["rustls-tls-native-roots"] }
tokio-stream = "0.1.14"
futures-util = "0.3.30"
native-tls = "0.2.11"
parse-display = "0.9.0"
serde_with = "3.6.1"
serde_with = "3.6.1"
# same as tokio-tungstenite
rustls = "0.22.0"
rustls-native-certs = "0.7.0"

View file

@ -1,6 +1,5 @@
use futures_util::SinkExt;
use native_tls::TlsConnector;
use parse_display::{Display, FromStr};
use parse_display::{Display, FromStr, IntoResult};
use reqwest::header::{HeaderMap, HeaderValue};
use serde::{Deserialize, Serialize};
use serde_json::json;
@ -62,12 +61,12 @@ impl HaClient {
let state_updates_sender = broadcast::Sender::<StateUpdate>::new(min(subscribed_entity_ids.len(), 16));
let state_timestamp_by_entity_id = subscribed_entity_ids.iter().map(|i| (i.clone(), "".to_owned().into_boxed_str())).collect();
let tls_connector = TlsConnector::builder().danger_accept_invalid_certs(accept_invalid_certs).build().unwrap();
let rustls_config = rustls::ClientConfig::builder().with_root_certificates();
tokio::spawn(do_work(
base_url.clone(),
token,
tls_connector,
Arc::new(rustls_config),
state_updates_sender.clone(),
http_client.clone(),
state_timestamp_by_entity_id,
@ -124,7 +123,7 @@ impl HaClient {
async fn do_work(
base_url: Url,
token: Box<str>,
tls_connector: TlsConnector,
rustls_config: Arc<rustls::ClientConfig>,
state_updates_sender: broadcast::Sender<StateUpdate>,
http_client: reqwest::Client,
state_timestamp_by_entity_id: HashMap<EntityId, Box<str>>,
@ -142,7 +141,7 @@ async fn do_work(
loop {
let connection_result =
tokio_tungstenite::connect_async_tls_with_config(&websocket_url, None, false, Some(Connector::NativeTls(tls_connector.clone()))).await;
tokio_tungstenite::connect_async_tls_with_config(&websocket_url, None, false, Some(Connector::Rustls(Arc::clone(&rustls_config)))).await;
match connection_result {
Err(tungstenite::Error::Io(error)) => {

View file

@ -6,6 +6,7 @@ use crate::handler::Handler;
mod config;
mod ha_client;
mod handler;
mod tls;
mod util;
#[derive(Debug, Parser)]

View file

@ -0,0 +1,44 @@
use rustls::client::danger::ServerCertVerifier;
use rustls::{ClientConfig, RootCertStore, SignatureScheme};
use std::sync::Arc;
// tokio-tungstenite does not provide a way to allow invalid certs.
// Because of that, we need to build our own rustls config.
pub fn get_rustls_client_config() -> Arc<ClientConfig> {
let mut root_store = RootCertStore::empty();
let native_certs = rustls_native_certs::load_native_certs().unwrap();
_ = root_store.add_parsable_certificates(native_certs);
let mut config = ClientConfig::builder().with_root_certificates(root_store).with_no_client_auth();
config.dangerous().set_certificate_verifier(Arc::new(NoVerifier));
Arc::new(config)
}
pub struct NoVerifier;
impl ServerCertVerifier for NoVerifier {
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
todo!()
}
fn verify_server_cert(
&self,
_end_entity: &rustls::Certificate,
_intermediates: &[rustls::Certificate],
_server_name: &ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_ocsp_response: &[u8],
_now: std::time::SystemTime,
) -> Result<ServerCertVerified, TLSError> {
Ok(ServerCertVerified::assertion())
}
fn verify_tls12_signature(&self, _message: &[u8], _cert: &rustls::Certificate, _dss: &DigitallySignedStruct) -> Result<HandshakeSignatureValid, TLSError> {
Ok(HandshakeSignatureValid::assertion())
}
fn verify_tls13_signature(&self, _message: &[u8], _cert: &rustls::Certificate, _dss: &DigitallySignedStruct) -> Result<HandshakeSignatureValid, TLSError> {
Ok(HandshakeSignatureValid::assertion())
}
}