Add disabled-by-default insecure-tcp feature to tokio-xmpp for use by component connections

This commit is contained in:
moparisthebest 2024-01-01 01:13:51 -05:00
parent 38bfba4a18
commit 019450ff4b
No known key found for this signature in database
GPG key ID: 88C93BFE27BC8229
9 changed files with 112 additions and 12 deletions

View file

@ -36,6 +36,8 @@ tokio-rustls = { version = "0.24", optional = true }
[dev-dependencies] [dev-dependencies]
env_logger = { version = "0.10", default-features = false, features = ["auto-color", "humantime"] } env_logger = { version = "0.10", default-features = false, features = ["auto-color", "humantime"] }
# this is needed for echo-component example
tokio-xmpp = { path = ".", features = ["insecure-tcp"]}
[features] [features]
default = ["starttls-rust"] default = ["starttls-rust"]
@ -44,4 +46,5 @@ tls-rust = ["tokio-rustls", "webpki-roots"]
tls-native = ["tokio-native-tls", "native-tls"] tls-native = ["tokio-native-tls", "native-tls"]
starttls-native = ["starttls", "tls-native"] starttls-native = ["starttls", "tls-native"]
starttls-rust = ["starttls", "tls-rust"] starttls-rust = ["starttls", "tls-rust"]
insecure-tcp = []
syntax-highlighting = ["syntect"] syntax-highlighting = ["syntect"]

View file

@ -2,7 +2,7 @@ use futures::stream::StreamExt;
use std::env::args; use std::env::args;
use std::process::exit; use std::process::exit;
use std::str::FromStr; use std::str::FromStr;
use tokio_xmpp::Component; use tokio_xmpp::tcp::TcpComponent as Component;
use xmpp_parsers::message::{Body, Message, MessageType}; use xmpp_parsers::message::{Body, Message, MessageType};
use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType}; use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType};
use xmpp_parsers::{Element, Jid}; use xmpp_parsers::{Element, Jid};
@ -12,22 +12,21 @@ async fn main() {
env_logger::init(); env_logger::init();
let args: Vec<String> = args().collect(); let args: Vec<String> = args().collect();
if args.len() < 3 || args.len() > 5 { if args.len() < 3 || args.len() > 4 {
println!("Usage: {} <jid> <password> [server] [port]", args[0]); println!("Usage: {} <jid> <password> [server:port]", args[0]);
exit(1); exit(1);
} }
let jid = &args[1]; let jid = &args[1];
let password = &args[2]; let password = &args[2];
let server = &args let server = args
.get(3) .get(3)
.unwrap() .unwrap()
.parse() .parse()
.unwrap_or("127.0.0.1".to_owned()); .unwrap_or("127.0.0.1:5347".to_owned());
let port: u16 = args.get(4).unwrap().parse().unwrap_or(5347u16);
// Component instance // Component instance
println!("{} {} {} {}", jid, password, server, port); println!("{} {} {}", jid, password, server);
let mut component = Component::new(jid, password, server, port).await.unwrap(); let mut component = Component::new(jid, password, server).await.unwrap();
// Make the two interfaces for sending and receiving independent // Make the two interfaces for sending and receiving independent
// of each other so we can move one into a closure. // of each other so we can move one into a closure.

View file

@ -31,7 +31,11 @@ pub struct Component<C: ServerConnector> {
impl<C: ServerConnector> Component<C> { impl<C: ServerConnector> Component<C> {
/// Start a new XMPP component /// Start a new XMPP component
pub async fn new(jid: &str, password: &str, connector: C) -> Result<Self, Error> { pub async fn new_with_connector(
jid: &str,
password: &str,
connector: C,
) -> Result<Self, Error> {
let jid = Jid::from_str(jid)?; let jid = Jid::from_str(jid)?;
let password = password.to_owned(); let password = password.to_owned();
let stream = component_login(connector, jid.clone(), password).await?; let stream = component_login(connector, jid.clone(), password).await?;

View file

@ -17,6 +17,8 @@ compile_error!(
#[cfg(feature = "starttls")] #[cfg(feature = "starttls")]
pub mod starttls; pub mod starttls;
mod stream_start; mod stream_start;
#[cfg(feature = "insecure-tcp")]
pub mod tcp;
mod xmpp_codec; mod xmpp_codec;
pub use crate::xmpp_codec::Packet; pub use crate::xmpp_codec::Packet;
mod event; mod event;

View file

@ -1,3 +1,5 @@
//! StartTLS ServerConnector Error
use hickory_resolver::{error::ResolveError, proto::error::ProtoError}; use hickory_resolver::{error::ResolveError, proto::error::ProtoError};
#[cfg(feature = "tls-native")] #[cfg(feature = "tls-native")]
use native_tls::Error as TlsError; use native_tls::Error as TlsError;
@ -9,7 +11,7 @@ use tokio_rustls::rustls::client::InvalidDnsNameError;
#[cfg(all(feature = "tls-rust", not(feature = "tls-native")))] #[cfg(all(feature = "tls-rust", not(feature = "tls-native")))]
use tokio_rustls::rustls::Error as TlsError; use tokio_rustls::rustls::Error as TlsError;
/// Top-level error type /// StartTLS ServerConnector Error
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
/// Error resolving DNS and establishing a connection /// Error resolving DNS and establishing a connection

View file

@ -26,16 +26,21 @@ use tokio::{
}; };
use xmpp_parsers::{ns, Element, Jid}; use xmpp_parsers::{ns, Element, Jid};
use crate::{connect::ServerConnector, xmpp_codec::Packet}; use crate::{connect::ServerConnector, xmpp_codec::Packet, AsyncClient, SimpleClient};
use crate::{connect::ServerConnectorError, xmpp_stream::XMPPStream}; use crate::{connect::ServerConnectorError, xmpp_stream::XMPPStream};
use self::error::Error; use self::error::Error;
use self::happy_eyeballs::{connect_to_host, connect_with_srv}; use self::happy_eyeballs::{connect_to_host, connect_with_srv};
mod client; mod client;
mod error; pub mod error;
mod happy_eyeballs; mod happy_eyeballs;
/// AsyncClient that connects over StartTls
pub type StartTlsAsyncClient = AsyncClient<ServerConfig>;
/// SimpleClient that connects over StartTls
pub type StartTlsSimpleClient = SimpleClient<ServerConfig>;
/// StartTLS XMPP server connection configuration /// StartTLS XMPP server connection configuration
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum ServerConfig { pub enum ServerConfig {

View file

@ -0,0 +1,10 @@
use crate::{Component, Error};
use super::TcpServerConnector;
impl Component<TcpServerConnector> {
/// Start a new XMPP component
pub async fn new(jid: &str, password: &str, server: String) -> Result<Self, Error> {
Self::new_with_connector(jid, password, TcpServerConnector::new(server)).await
}
}

View file

@ -0,0 +1,26 @@
//! TCP ServerConnector Error
use core::fmt;
/// TCP ServerConnector Error
#[derive(Debug)]
pub enum Error {
/// tokio-xmpp error
TokioXMPP(crate::error::Error),
}
impl std::error::Error for Error {}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::TokioXMPP(e) => write!(fmt, "TokioXMPP error: {}", e),
}
}
}
impl From<crate::error::Error> for Error {
fn from(e: crate::error::Error) -> Self {
Error::TokioXMPP(e)
}
}

49
tokio-xmpp/src/tcp/mod.rs Normal file
View file

@ -0,0 +1,49 @@
//! `starttls::ServerConfig` provides a `ServerConnector` for starttls connections
use std::sync::Arc;
use tokio::net::TcpStream;
use crate::{
connect::{ServerConnector, ServerConnectorError},
xmpp_stream::XMPPStream,
Component,
};
use self::error::Error;
mod component;
pub mod error;
/// Component that connects over TCP
pub type TcpComponent = Component<TcpServerConnector>;
/// Connect via insecure plaintext TCP to an XMPP server
/// This should only be used over localhost or otherwise when you know what you are doing
/// Probably mostly useful for Components
#[derive(Debug, Clone)]
pub struct TcpServerConnector(Arc<String>);
impl TcpServerConnector {
/// Create a new connector with the given address
pub fn new(addr: String) -> Self {
Self(addr.into())
}
}
impl ServerConnectorError for Error {}
impl ServerConnector for TcpServerConnector {
type Stream = TcpStream;
type Error = Error;
async fn connect(
&self,
jid: &xmpp_parsers::Jid,
ns: &str,
) -> Result<XMPPStream<Self::Stream>, Self::Error> {
let stream = TcpStream::connect(&*self.0)
.await
.map_err(|e| crate::Error::Io(e))?;
Ok(XMPPStream::start(stream, jid.clone(), ns.to_owned()).await?)
}
}