Make it possible to disable certificate verification
This commit is contained in:
parent
3f27c90489
commit
c68a7cbe0a
|
@ -755,12 +755,15 @@ dependencies = [
|
||||||
"jitsi-xmpp-parsers",
|
"jitsi-xmpp-parsers",
|
||||||
"libc",
|
"libc",
|
||||||
"maplit",
|
"maplit",
|
||||||
|
"native-tls",
|
||||||
"nice-gst-meet",
|
"nice-gst-meet",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"pem",
|
"pem",
|
||||||
"rand",
|
"rand",
|
||||||
"rcgen",
|
"rcgen",
|
||||||
"ring",
|
"ring",
|
||||||
|
"rustls",
|
||||||
|
"rustls-native-certs",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -769,6 +772,7 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"uuid",
|
"uuid",
|
||||||
|
"webpki-roots",
|
||||||
"xmpp-parsers",
|
"xmpp-parsers",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,8 @@ tracing = { version = "0.1", default-features = false, features = ["attributes",
|
||||||
cocoa = { version = "0.24", default-features = false }
|
cocoa = { version = "0.24", default-features = false }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["tls-native"]
|
default = ["tls-rustls-native-roots"]
|
||||||
|
tls-insecure = ["lib-gst-meet/tls-insecure"]
|
||||||
tls-native = ["lib-gst-meet/tls-native"]
|
tls-native = ["lib-gst-meet/tls-native"]
|
||||||
tls-native-vendored = ["lib-gst-meet/tls-native-vendored"]
|
tls-native-vendored = ["lib-gst-meet/tls-native-vendored"]
|
||||||
tls-rustls-native-roots = ["lib-gst-meet/tls-rustls-native-roots"]
|
tls-rustls-native-roots = ["lib-gst-meet/tls-rustls-native-roots"]
|
||||||
|
|
|
@ -45,13 +45,16 @@ struct Opt {
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
select_endpoints: Option<String>,
|
select_endpoints: Option<String>,
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
last_n: Option<i32>,
|
last_n: Option<u16>,
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
recv_video_height: Option<i32>,
|
recv_video_height: Option<u16>,
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
video_type: Option<String>,
|
video_type: Option<String>,
|
||||||
#[structopt(short, long, parse(from_occurrences))]
|
#[structopt(short, long, parse(from_occurrences))]
|
||||||
verbose: u8,
|
verbose: u8,
|
||||||
|
#[cfg(feature = "tls-insecure")]
|
||||||
|
#[structopt(long, help = "Disable TLS certificate verification (use with extreme caution)")]
|
||||||
|
tls_insecure: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
@ -117,9 +120,13 @@ async fn main_inner() -> Result<()> {
|
||||||
&opt.web_socket_url,
|
&opt.web_socket_url,
|
||||||
&opt.xmpp_domain,
|
&opt.xmpp_domain,
|
||||||
Authentication::Anonymous,
|
Authentication::Anonymous,
|
||||||
|
#[cfg(feature = "tls-insecure")]
|
||||||
|
opt.tls_insecure,
|
||||||
|
#[cfg(not(feature = "tls-insecure"))]
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.context("failed to connect")?;
|
.context("failed to build connection")?;
|
||||||
|
|
||||||
tokio::spawn(background);
|
tokio::spawn(background);
|
||||||
|
|
||||||
|
@ -165,13 +172,13 @@ async fn main_inner() -> Result<()> {
|
||||||
if opt.select_endpoints.is_some() || opt.last_n.is_some() || opt.recv_video_height.is_some() {
|
if opt.select_endpoints.is_some() || opt.last_n.is_some() || opt.recv_video_height.is_some() {
|
||||||
conference
|
conference
|
||||||
.send_colibri_message(ColibriMessage::ReceiverVideoConstraints {
|
.send_colibri_message(ColibriMessage::ReceiverVideoConstraints {
|
||||||
last_n: opt.last_n,
|
last_n: Some(opt.last_n.map(i32::from).unwrap_or(-1)),
|
||||||
selected_endpoints: opt
|
selected_endpoints: opt
|
||||||
.select_endpoints
|
.select_endpoints
|
||||||
.map(|endpoints| endpoints.split(',').map(ToOwned::to_owned).collect()),
|
.map(|endpoints| endpoints.split(',').map(ToOwned::to_owned).collect()),
|
||||||
on_stage_endpoints: None,
|
on_stage_endpoints: None,
|
||||||
default_constraints: opt.recv_video_height.map(|height| Constraints {
|
default_constraints: opt.recv_video_height.map(|height| Constraints {
|
||||||
max_height: Some(height),
|
max_height: Some(height.into()),
|
||||||
ideal_height: None,
|
ideal_height: None,
|
||||||
}),
|
}),
|
||||||
constraints: None,
|
constraints: None,
|
||||||
|
|
|
@ -39,7 +39,8 @@ void gstmeet_deinit(struct Context *context);
|
||||||
|
|
||||||
JitsiConnection *gstmeet_connection_new(struct Context *context,
|
JitsiConnection *gstmeet_connection_new(struct Context *context,
|
||||||
const char *websocket_url,
|
const char *websocket_url,
|
||||||
const char *xmpp_domain);
|
const char *xmpp_domain,
|
||||||
|
bool tls_insecure);
|
||||||
|
|
||||||
void gstmeet_connection_free(JitsiConnection *connection);
|
void gstmeet_connection_free(JitsiConnection *connection);
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,7 @@ pub unsafe extern "C" fn gstmeet_connection_new(
|
||||||
context: *mut Context,
|
context: *mut Context,
|
||||||
websocket_url: *const c_char,
|
websocket_url: *const c_char,
|
||||||
xmpp_domain: *const c_char,
|
xmpp_domain: *const c_char,
|
||||||
|
tls_insecure: bool,
|
||||||
) -> *mut Connection {
|
) -> *mut Connection {
|
||||||
let websocket_url = CStr::from_ptr(websocket_url);
|
let websocket_url = CStr::from_ptr(websocket_url);
|
||||||
let xmpp_domain = CStr::from_ptr(xmpp_domain);
|
let xmpp_domain = CStr::from_ptr(xmpp_domain);
|
||||||
|
@ -89,6 +90,7 @@ pub unsafe extern "C" fn gstmeet_connection_new(
|
||||||
&websocket_url.to_string_lossy(),
|
&websocket_url.to_string_lossy(),
|
||||||
&xmpp_domain.to_string_lossy(),
|
&xmpp_domain.to_string_lossy(),
|
||||||
Authentication::Anonymous,
|
Authentication::Anonymous,
|
||||||
|
tls_insecure,
|
||||||
))
|
))
|
||||||
.map(|(connection, background)| {
|
.map(|(connection, background)| {
|
||||||
(*context).runtime.spawn(background);
|
(*context).runtime.spawn(background);
|
||||||
|
|
|
@ -25,12 +25,15 @@ itertools = { version = "0.10", default-features = false, features = ["use_std"]
|
||||||
jitsi-xmpp-parsers = { version = "0.1", path = "../jitsi-xmpp-parsers", default-features = false }
|
jitsi-xmpp-parsers = { version = "0.1", path = "../jitsi-xmpp-parsers", default-features = false }
|
||||||
libc = { version = "0.2", default-features = false }
|
libc = { version = "0.2", default-features = false }
|
||||||
maplit = { version = "1", default-features = false }
|
maplit = { version = "1", default-features = false }
|
||||||
|
native-tls = { version = "0.2", default-features = false, optional = true }
|
||||||
nice-gst-meet = { version = "0.1", path = "../nice-gst-meet", default-features = false, features = ["v0_1_18"] }
|
nice-gst-meet = { version = "0.1", path = "../nice-gst-meet", default-features = false, features = ["v0_1_18"] }
|
||||||
once_cell = { version = "1", default-features = false, features = ["std"] }
|
once_cell = { version = "1", default-features = false, features = ["std"] }
|
||||||
pem = { version = "1", default-features = false }
|
pem = { version = "1", default-features = false }
|
||||||
rand = { version = "0.8", default-features = false, features = ["std", "std_rng"] }
|
rand = { version = "0.8", default-features = false, features = ["std", "std_rng"] }
|
||||||
rcgen = { version = "0.9", default-features = false }
|
rcgen = { version = "0.9", default-features = false }
|
||||||
ring = { version = "0.16", default-features = false }
|
ring = { version = "0.16", default-features = false }
|
||||||
|
rustls = { version = "0.20", default-features = false, features = ["logging", "tls12"], optional = true }
|
||||||
|
rustls-native-certs = { version = "0.6", default-features = false, optional = true }
|
||||||
serde = { version = "1", default-features = false, features = ["derive"] }
|
serde = { version = "1", default-features = false, features = ["derive"] }
|
||||||
serde_json = { version = "1", default-features = false, features = ["std"] }
|
serde_json = { version = "1", default-features = false, features = ["std"] }
|
||||||
tokio = { version = "1", default-features = false, features = ["rt-multi-thread", "macros", "sync", "time"] }
|
tokio = { version = "1", default-features = false, features = ["rt-multi-thread", "macros", "sync", "time"] }
|
||||||
|
@ -45,11 +48,15 @@ tracing-subscriber = { version = "0.3", optional = true, default-features = fals
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
] }
|
] }
|
||||||
uuid = { version = "0.8", default-features = false, features = ["v4"] }
|
uuid = { version = "0.8", default-features = false, features = ["v4"] }
|
||||||
|
webpki-roots = { version = "0.22", default-features = false, optional = true }
|
||||||
xmpp-parsers = { git = "https://gitlab.com/xmpp-rs/xmpp-rs.git", default-features = false, features = ["disable-validation"] }
|
xmpp-parsers = { git = "https://gitlab.com/xmpp-rs/xmpp-rs.git", default-features = false, features = ["disable-validation"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["tls-native"]
|
# Ideally we would enable rustls/dangerous_configuration only when tls-insecure is enabled, but until weak-dep-features is stabilised, that
|
||||||
tls-native = ["tokio-tungstenite/native-tls"]
|
# would cause rustls to always be pulled in.
|
||||||
tls-native-vendored = ["tokio-tungstenite/native-tls-vendored"]
|
default = ["tls-rustls-native-roots"]
|
||||||
tls-rustls-native-roots = ["tokio-tungstenite/rustls-tls-native-roots"]
|
tls-insecure = []
|
||||||
tls-rustls-webpki-roots = ["tokio-tungstenite/rustls-tls-webpki-roots"]
|
tls-native = ["tokio-tungstenite/native-tls", "native-tls"]
|
||||||
|
tls-native-vendored = ["tokio-tungstenite/native-tls-vendored", "native-tls/vendored"]
|
||||||
|
tls-rustls-native-roots = ["tokio-tungstenite/rustls-tls-native-roots", "rustls", "rustls-native-certs", "rustls/dangerous_configuration"]
|
||||||
|
tls-rustls-webpki-roots = ["tokio-tungstenite/rustls-tls-webpki-roots", "rustls", "webpki-roots", "rustls/dangerous_configuration"]
|
||||||
|
|
|
@ -18,6 +18,8 @@ use tokio_tungstenite::tungstenite::{
|
||||||
};
|
};
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
|
|
||||||
|
use crate::tls::wss_connector;
|
||||||
|
|
||||||
const MAX_CONNECT_RETRIES: u8 = 3;
|
const MAX_CONNECT_RETRIES: u8 = 3;
|
||||||
const CONNECT_RETRY_SLEEP: Duration = Duration::from_secs(3);
|
const CONNECT_RETRY_SLEEP: Duration = Duration::from_secs(3);
|
||||||
|
|
||||||
|
@ -27,7 +29,7 @@ pub(crate) struct ColibriChannel {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ColibriChannel {
|
impl ColibriChannel {
|
||||||
pub(crate) async fn new(uri: &str) -> Result<Self> {
|
pub(crate) async fn new(uri: &str, tls_insecure: bool) -> Result<Self> {
|
||||||
let uri: Uri = uri.parse()?;
|
let uri: Uri = uri.parse()?;
|
||||||
let host = uri.host().context("invalid WebSocket URL: missing host")?;
|
let host = uri.host().context("invalid WebSocket URL: missing host")?;
|
||||||
|
|
||||||
|
@ -44,7 +46,7 @@ impl ColibriChannel {
|
||||||
.header("connection", "Upgrade")
|
.header("connection", "Upgrade")
|
||||||
.header("upgrade", "websocket")
|
.header("upgrade", "websocket")
|
||||||
.body(())?;
|
.body(())?;
|
||||||
match tokio_tungstenite::connect_async(request).await {
|
match tokio_tungstenite::connect_async_tls_with_config(request, None, Some(wss_connector(tls_insecure)?)).await {
|
||||||
Ok((websocket, _)) => break websocket,
|
Ok((websocket, _)) => break websocket,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if retries < MAX_CONNECT_RETRIES {
|
if retries < MAX_CONNECT_RETRIES {
|
||||||
|
|
|
@ -40,8 +40,12 @@ use crate::{
|
||||||
|
|
||||||
const DISCO_NODE: &str = "https://github.com/avstack/gst-meet";
|
const DISCO_NODE: &str = "https://github.com/avstack/gst-meet";
|
||||||
|
|
||||||
static DISCO_INFO: Lazy<DiscoInfoResult> = Lazy::new(|| {
|
static DISCO_INFO: Lazy<DiscoInfoResult> = Lazy::new(|| DiscoInfoResult {
|
||||||
let mut features = vec![
|
node: None,
|
||||||
|
identities: vec![
|
||||||
|
Identity::new("client", "bot", "en", "gst-meet"),
|
||||||
|
],
|
||||||
|
features: vec![
|
||||||
Feature::new(ns::DISCO_INFO),
|
Feature::new(ns::DISCO_INFO),
|
||||||
Feature::new(ns::JINGLE_RTP_AUDIO),
|
Feature::new(ns::JINGLE_RTP_AUDIO),
|
||||||
Feature::new(ns::JINGLE_RTP_VIDEO),
|
Feature::new(ns::JINGLE_RTP_VIDEO),
|
||||||
|
@ -50,26 +54,9 @@ static DISCO_INFO: Lazy<DiscoInfoResult> = Lazy::new(|| {
|
||||||
Feature::new("urn:ietf:rfc:5888"), // BUNDLE
|
Feature::new("urn:ietf:rfc:5888"), // BUNDLE
|
||||||
Feature::new("urn:ietf:rfc:5761"), // RTCP-MUX
|
Feature::new("urn:ietf:rfc:5761"), // RTCP-MUX
|
||||||
Feature::new("urn:ietf:rfc:4588"), // RTX
|
Feature::new("urn:ietf:rfc:4588"), // RTX
|
||||||
];
|
Feature::new("http://jitsi.org/tcc"),
|
||||||
let gst_version = gstreamer::version();
|
],
|
||||||
if gst_version.0 >= 1 && gst_version.1 >= 19 {
|
|
||||||
// RTP header extensions are supported on GStreamer 1.19+
|
|
||||||
features.push(Feature::new("http://jitsi.org/tcc"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
warn!("Upgrade GStreamer to 1.19 or later to enable RTP header extensions");
|
|
||||||
}
|
|
||||||
let identities = vec![
|
|
||||||
Identity::new("client", "bot", "en", "gst-meet"),
|
|
||||||
];
|
|
||||||
// Not supported yet:
|
|
||||||
// Feature::new("http://jitsi.org/opus-red")
|
|
||||||
DiscoInfoResult {
|
|
||||||
node: None,
|
|
||||||
identities,
|
|
||||||
features,
|
|
||||||
extensions: vec![],
|
extensions: vec![],
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
static COMPUTED_CAPS_HASH: Lazy<Hash> = Lazy::new(|| {
|
static COMPUTED_CAPS_HASH: Lazy<Hash> = Lazy::new(|| {
|
||||||
|
@ -102,6 +89,7 @@ pub struct JitsiConference {
|
||||||
pub(crate) external_services: Vec<xmpp::extdisco::Service>,
|
pub(crate) external_services: Vec<xmpp::extdisco::Service>,
|
||||||
pub(crate) jingle_session: Arc<Mutex<Option<JingleSession>>>,
|
pub(crate) jingle_session: Arc<Mutex<Option<JingleSession>>>,
|
||||||
pub(crate) inner: Arc<Mutex<JitsiConferenceInner>>,
|
pub(crate) inner: Arc<Mutex<JitsiConferenceInner>>,
|
||||||
|
pub(crate) tls_insecure: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for JitsiConference {
|
impl fmt::Debug for JitsiConference {
|
||||||
|
@ -220,6 +208,7 @@ impl JitsiConference {
|
||||||
on_colibri_message: None,
|
on_colibri_message: None,
|
||||||
connected_tx: Some(tx),
|
connected_tx: Some(tx),
|
||||||
})),
|
})),
|
||||||
|
tls_insecure: xmpp_connection.tls_insecure,
|
||||||
};
|
};
|
||||||
|
|
||||||
xmpp_connection.add_stanza_filter(conference.clone()).await;
|
xmpp_connection.add_stanza_filter(conference.clone()).await;
|
||||||
|
@ -590,7 +579,7 @@ impl StanzaFilter for JitsiConference {
|
||||||
|
|
||||||
if let Some(colibri_url) = colibri_url {
|
if let Some(colibri_url) = colibri_url {
|
||||||
info!("Connecting Colibri WebSocket to {}", colibri_url);
|
info!("Connecting Colibri WebSocket to {}", colibri_url);
|
||||||
let colibri_channel = ColibriChannel::new(&colibri_url).await?;
|
let colibri_channel = ColibriChannel::new(&colibri_url, self.tls_insecure).await?;
|
||||||
let (tx, rx) = mpsc::channel(8);
|
let (tx, rx) = mpsc::channel(8);
|
||||||
colibri_channel.subscribe(tx).await;
|
colibri_channel.subscribe(tx).await;
|
||||||
jingle_session.colibri_channel = Some(colibri_channel);
|
jingle_session.colibri_channel = Some(colibri_channel);
|
||||||
|
@ -599,6 +588,14 @@ impl StanzaFilter for JitsiConference {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut stream = ReceiverStream::new(rx);
|
let mut stream = ReceiverStream::new(rx);
|
||||||
while let Some(msg) = stream.next().await {
|
while let Some(msg) = stream.next().await {
|
||||||
|
// Some message types are handled internally rather than passed to the on_colibri_message handler.
|
||||||
|
|
||||||
|
// End-to-end ping
|
||||||
|
if let ColibriMessage::EndpointMessage { to, .. } = &msg {
|
||||||
|
// if to ==
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
let locked_inner = self_.inner.lock().await;
|
let locked_inner = self_.inner.lock().await;
|
||||||
if let Some(f) = &locked_inner.on_colibri_message {
|
if let Some(f) = &locked_inner.on_colibri_message {
|
||||||
if let Err(e) = f(self_.clone(), msg).await {
|
if let Err(e) = f(self_.clone(), msg).await {
|
||||||
|
|
|
@ -4,6 +4,7 @@ mod jingle;
|
||||||
mod pinger;
|
mod pinger;
|
||||||
mod source;
|
mod source;
|
||||||
mod stanza_filter;
|
mod stanza_filter;
|
||||||
|
mod tls;
|
||||||
mod util;
|
mod util;
|
||||||
mod xmpp;
|
mod xmpp;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
#[cfg(any(feature = "tls-rustls-native-roots", feature = "tls-rustls-webpki-roots"))]
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "tls-insecure"))]
|
||||||
|
use anyhow::bail;
|
||||||
|
use anyhow::Result;
|
||||||
|
use tokio_tungstenite::Connector;
|
||||||
|
|
||||||
|
#[cfg(feature = "tls-rustls-native-roots")]
|
||||||
|
pub(crate) fn wss_connector(insecure: bool) -> Result<tokio_tungstenite::Connector> {
|
||||||
|
let mut roots = rustls::RootCertStore::empty();
|
||||||
|
for cert in rustls_native_certs::load_native_certs()? {
|
||||||
|
roots.add(&rustls::Certificate(cert.0))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut config = rustls::ClientConfig::builder()
|
||||||
|
.with_safe_defaults()
|
||||||
|
.with_root_certificates(roots)
|
||||||
|
.with_no_client_auth();
|
||||||
|
#[cfg(feature = "tls-insecure")]
|
||||||
|
if insecure {
|
||||||
|
config.dangerous().set_certificate_verifier(Arc::new(InsecureServerCertVerifier));
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "tls-insecure"))]
|
||||||
|
if insecure {
|
||||||
|
bail!("Insecure TLS mode can only be enabled if the tls-insecure feature was enabled at compile time.")
|
||||||
|
}
|
||||||
|
Ok(Connector::Rustls(Arc::new(config)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "tls-rustls-webpki-roots")]
|
||||||
|
pub(crate) fn wss_connector(insecure: bool) -> Result<tokio_tungstenite::Connector> {
|
||||||
|
let mut roots = rustls::RootCertStore::empty();
|
||||||
|
roots.add_server_trust_anchors(
|
||||||
|
webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| {
|
||||||
|
rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
|
||||||
|
ta.subject,
|
||||||
|
ta.spki,
|
||||||
|
ta.name_constraints,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
let config = rustls::ClientConfig::builder()
|
||||||
|
.with_safe_defaults()
|
||||||
|
.with_root_certificates(roots)
|
||||||
|
.with_no_client_auth();
|
||||||
|
#[cfg(feature = "tls-insecure")]
|
||||||
|
if insecure {
|
||||||
|
config.dangerous().set_certificate_verifier(Arc::new(InsecureServerCertVerifier));
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "tls-insecure"))]
|
||||||
|
if insecure {
|
||||||
|
bail!("Insecure TLS mode can only be enabled if the tls-insecure feature was enabled at compile time.")
|
||||||
|
}
|
||||||
|
Ok(Connector::Rustls(Arc::new(config)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "tls-native", feature = "tls-native-vendored"))]
|
||||||
|
pub(crate) fn wss_connector(insecure: bool) -> Result<tokio_tungstenite::Connector> {
|
||||||
|
let mut builder = native_tls::TlsConnector::builder();
|
||||||
|
builder.min_protocol_version(Some(native_tls::Protocol::Tlsv12));
|
||||||
|
#[cfg(feature = "tls-insecure")]
|
||||||
|
if insecure {
|
||||||
|
builder.danger_accept_invalid_certs(true);
|
||||||
|
builder.danger_accept_invalid_hostnames(true);
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "tls-insecure"))]
|
||||||
|
if insecure {
|
||||||
|
bail!("Insecure TLS mode can only be enabled if the tls-insecure feature was enabled at compile time.")
|
||||||
|
}
|
||||||
|
Ok(Connector::NativeTls(builder.build()?))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "tls-insecure", any(feature = "tls-rustls-native-roots", feature = "tls-rustls-webpki-roots")))]
|
||||||
|
struct InsecureServerCertVerifier;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "tls-insecure", any(feature = "tls-rustls-native-roots", feature = "tls-rustls-webpki-roots")))]
|
||||||
|
impl rustls::client::ServerCertVerifier for InsecureServerCertVerifier {
|
||||||
|
fn verify_server_cert(&self, _end_entity: &rustls::Certificate, _intermediates: &[rustls::Certificate], _server_name: &rustls::ServerName, _scts: &mut dyn Iterator<Item = &[u8]>, _ocsp_response: &[u8], _now: std::time::SystemTime) -> Result<rustls::client::ServerCertVerified, rustls::Error> {
|
||||||
|
Ok(rustls::client::ServerCertVerified::assertion())
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ use xmpp_parsers::{
|
||||||
BareJid, Element, FullJid, Jid,
|
BareJid, Element, FullJid, Jid,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{pinger::Pinger, stanza_filter::StanzaFilter, util::generate_id, xmpp};
|
use crate::{pinger::Pinger, stanza_filter::StanzaFilter, tls::wss_connector, util::generate_id, xmpp};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
enum ConnectionState {
|
enum ConnectionState {
|
||||||
|
@ -60,6 +60,7 @@ impl fmt::Debug for ConnectionInner {
|
||||||
pub struct Connection {
|
pub struct Connection {
|
||||||
pub(crate) tx: mpsc::Sender<Element>,
|
pub(crate) tx: mpsc::Sender<Element>,
|
||||||
inner: Arc<Mutex<ConnectionInner>>,
|
inner: Arc<Mutex<ConnectionInner>>,
|
||||||
|
pub(crate) tls_insecure: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Authentication {
|
pub enum Authentication {
|
||||||
|
@ -72,6 +73,7 @@ impl Connection {
|
||||||
websocket_url: &str,
|
websocket_url: &str,
|
||||||
xmpp_domain: &str,
|
xmpp_domain: &str,
|
||||||
authentication: Authentication,
|
authentication: Authentication,
|
||||||
|
tls_insecure: bool,
|
||||||
) -> Result<(Self, impl Future<Output = ()>)> {
|
) -> Result<(Self, impl Future<Output = ()>)> {
|
||||||
let websocket_url: Uri = websocket_url.parse().context("invalid WebSocket URL")?;
|
let websocket_url: Uri = websocket_url.parse().context("invalid WebSocket URL")?;
|
||||||
let xmpp_domain: BareJid = xmpp_domain.parse().context("invalid XMPP domain")?;
|
let xmpp_domain: BareJid = xmpp_domain.parse().context("invalid XMPP domain")?;
|
||||||
|
@ -88,7 +90,7 @@ impl Connection {
|
||||||
.header("upgrade", "websocket")
|
.header("upgrade", "websocket")
|
||||||
.body(())
|
.body(())
|
||||||
.context("failed to build WebSocket request")?;
|
.context("failed to build WebSocket request")?;
|
||||||
let (websocket, _response) = tokio_tungstenite::connect_async(request)
|
let (websocket, _response) = tokio_tungstenite::connect_async_tls_with_config(request, None, Some(wss_connector(tls_insecure)?))
|
||||||
.await
|
.await
|
||||||
.context("failed to connect XMPP WebSocket")?;
|
.context("failed to connect XMPP WebSocket")?;
|
||||||
let (sink, stream) = websocket.split();
|
let (sink, stream) = websocket.split();
|
||||||
|
@ -107,6 +109,7 @@ impl Connection {
|
||||||
let connection = Self {
|
let connection = Self {
|
||||||
tx: tx.clone(),
|
tx: tx.clone(),
|
||||||
inner: inner.clone(),
|
inner: inner.clone(),
|
||||||
|
tls_insecure,
|
||||||
};
|
};
|
||||||
|
|
||||||
let writer = Connection::write_loop(rx, sink);
|
let writer = Connection::write_loop(rx, sink);
|
||||||
|
|
Loading…
Reference in New Issue