Fix ejabberd s2s
This commit is contained in:
parent
3871589254
commit
c160acb38f
51
src/main.rs
51
src/main.rs
@ -103,8 +103,10 @@ impl Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_str(buf: &[u8]) -> &str {
|
fn to_str(buf: &[u8]) -> std::borrow::Cow<'_, str> {
|
||||||
std::str::from_utf8(buf).unwrap_or("[invalid utf-8]")
|
//&str {
|
||||||
|
//std::str::from_utf8(buf).unwrap_or("[invalid utf-8]")
|
||||||
|
String::from_utf8_lossy(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_connection(mut stream: tokio::net::TcpStream, client_addr: SocketAddr, local_addr: SocketAddr, config: CloneableConfig) -> Result<()> {
|
async fn handle_connection(mut stream: tokio::net::TcpStream, client_addr: SocketAddr, local_addr: SocketAddr, config: CloneableConfig) -> Result<()> {
|
||||||
@ -148,7 +150,11 @@ async fn handle_connection(mut stream: tokio::net::TcpStream, client_addr: Socke
|
|||||||
if !direct_tls {
|
if !direct_tls {
|
||||||
let mut stream_open = Vec::new();
|
let mut stream_open = Vec::new();
|
||||||
|
|
||||||
while let Ok(n) = stream.read(in_filter.current_buf()).await {
|
let (in_rd, mut in_wr) = stream.split();
|
||||||
|
// we naively read 1 byte at a time, which buffering significantly speeds up
|
||||||
|
let mut in_rd = tokio::io::BufReader::with_capacity(IN_BUFFER_SIZE, in_rd);
|
||||||
|
|
||||||
|
while let Ok(n) = in_rd.read(in_filter.current_buf()).await {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
bail!("stream ended before open");
|
bail!("stream ended before open");
|
||||||
}
|
}
|
||||||
@ -160,32 +166,36 @@ async fn handle_connection(mut stream: tokio::net::TcpStream, client_addr: Socke
|
|||||||
continue;
|
continue;
|
||||||
} else if buf.starts_with(b"<stream:stream ") {
|
} else if buf.starts_with(b"<stream:stream ") {
|
||||||
debug!("> {} '{}'", client_addr, to_str(&stream_open));
|
debug!("> {} '{}'", client_addr, to_str(&stream_open));
|
||||||
stream.write_all(&stream_open).await?;
|
in_wr.write_all(&stream_open).await?;
|
||||||
stream_open.clear();
|
stream_open.clear();
|
||||||
|
|
||||||
// gajim seems to REQUIRE an id here...
|
// gajim seems to REQUIRE an id here...
|
||||||
let buf = if buf.contains_seq(b"id=") {
|
let buf = if buf.contains_seq(b"id=") {
|
||||||
buf.replace(b" id='", b" id='xmpp-proxy")
|
buf.replace_first(b" id='", b" id='xmpp-proxy")
|
||||||
.replace(br#" id=""#, br#" id="xmpp-proxy"#)
|
.replace_first(br#" id=""#, br#" id="xmpp-proxy"#)
|
||||||
.replace(b" to=", br#" bla toblala="#)
|
.replace_first(b" to=", br#" bla toblala="#)
|
||||||
.replace(b" from=", b" to=")
|
.replace_first(b" from=", b" to=")
|
||||||
.replace(br#" bla toblala="#, br#" from="#)
|
.replace_first(br#" bla toblala="#, br#" from="#)
|
||||||
} else {
|
} else {
|
||||||
buf.replace(b" to=", br#" bla toblala="#)
|
buf.replace_first(b" to=", br#" bla toblala="#)
|
||||||
.replace(b" from=", b" to=")
|
.replace_first(b" from=", b" to=")
|
||||||
.replace(br#" bla toblala="#, br#" id='xmpp-proxy' from="#)
|
.replace_first(br#" bla toblala="#, br#" id='xmpp-proxy' from="#)
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("> {} '{}'", client_addr, to_str(&buf));
|
debug!("> {} '{}'", client_addr, to_str(&buf));
|
||||||
stream.write_all(&buf).await?;
|
in_wr.write_all(&buf).await?;
|
||||||
|
|
||||||
stream
|
// ejabberd never sends <starttls/> with the first, only the second?
|
||||||
.write_all(br###"<features xmlns="http://etherx.jabber.org/streams"><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"><required/></starttls></features>"###)
|
//let buf = br###"<features xmlns="http://etherx.jabber.org/streams"><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"><required/></starttls></features>"###;
|
||||||
.await?;
|
let buf = br###"<stream:features><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"><required/></starttls></stream:features>"###;
|
||||||
stream.flush().await?;
|
debug!("> {} '{}'", client_addr, to_str(buf));
|
||||||
|
in_wr.write_all(buf).await?;
|
||||||
|
in_wr.flush().await?;
|
||||||
} else if buf.starts_with(b"<starttls ") {
|
} else if buf.starts_with(b"<starttls ") {
|
||||||
stream.write_all(br###"<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls" />"###).await?;
|
let buf = br###"<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls" />"###;
|
||||||
stream.flush().await?;
|
debug!("> {} '{}'", client_addr, to_str(buf));
|
||||||
|
in_wr.write_all(buf).await?;
|
||||||
|
in_wr.flush().await?;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
bail!("bad pre-tls stanza: {}", to_str(&buf));
|
bail!("bad pre-tls stanza: {}", to_str(&buf));
|
||||||
@ -197,7 +207,6 @@ async fn handle_connection(mut stream: tokio::net::TcpStream, client_addr: Socke
|
|||||||
let stream = config.acceptor.accept(stream).await?;
|
let stream = config.acceptor.accept(stream).await?;
|
||||||
|
|
||||||
let (in_rd, mut in_wr) = tokio::io::split(stream);
|
let (in_rd, mut in_wr) = tokio::io::split(stream);
|
||||||
|
|
||||||
// we naively read 1 byte at a time, which buffering significantly speeds up
|
// we naively read 1 byte at a time, which buffering significantly speeds up
|
||||||
let mut in_rd = tokio::io::BufReader::with_capacity(IN_BUFFER_SIZE, in_rd);
|
let mut in_rd = tokio::io::BufReader::with_capacity(IN_BUFFER_SIZE, in_rd);
|
||||||
|
|
||||||
@ -396,7 +405,7 @@ impl StanzaFilter {
|
|||||||
//println!("b: '{}', cnt: {}, tag_cnt: {}, self.buf.len(): {}", b as char, self.cnt, self.tag_cnt, self.buf.len());
|
//println!("b: '{}', cnt: {}, tag_cnt: {}, self.buf.len(): {}", b as char, self.cnt, self.tag_cnt, self.buf.len());
|
||||||
self.cnt += 1;
|
self.cnt += 1;
|
||||||
if self.cnt == self.buf_size {
|
if self.cnt == self.buf_size {
|
||||||
bail!("stanza too big");
|
bail!("stanza too big: {}", to_str(&self.buf));
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use anyhow::{anyhow, Result};
|
|||||||
pub trait SliceSubsequence<T> {
|
pub trait SliceSubsequence<T> {
|
||||||
fn trim_start(&self, needle: &[T]) -> &[T];
|
fn trim_start(&self, needle: &[T]) -> &[T];
|
||||||
fn first_index_of(&self, needle: &[T]) -> Result<usize>;
|
fn first_index_of(&self, needle: &[T]) -> Result<usize>;
|
||||||
fn replace(self, needle: &[T], replacement: &[T]) -> Vec<T>;
|
fn replace_first(self, needle: &[T], replacement: &[T]) -> Vec<T>;
|
||||||
|
|
||||||
fn contains_seq(&self, needle: &[T]) -> bool {
|
fn contains_seq(&self, needle: &[T]) -> bool {
|
||||||
self.first_index_of(needle).is_ok()
|
self.first_index_of(needle).is_ok()
|
||||||
@ -36,8 +36,8 @@ impl<T: PartialEq + Clone> SliceSubsequence<T> for &[T] {
|
|||||||
Err(anyhow!("not found"))
|
Err(anyhow!("not found"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replace(self, needle: &[T], replacement: &[T]) -> Vec<T> {
|
fn replace_first(self, needle: &[T], replacement: &[T]) -> Vec<T> {
|
||||||
self.to_vec().replace(needle, replacement)
|
self.to_vec().replace_first(needle, replacement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,11 +50,17 @@ impl<T: PartialEq + Clone> SliceSubsequence<T> for Vec<T> {
|
|||||||
return (self.as_slice()).first_index_of(needle);
|
return (self.as_slice()).first_index_of(needle);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replace(mut self, needle: &[T], replacement: &[T]) -> Vec<T> {
|
fn replace_first(self, needle: &[T], replacement: &[T]) -> Vec<T> {
|
||||||
while let Ok(idx) = self.first_index_of(needle) {
|
if let Ok(idx) = self.first_index_of(needle) {
|
||||||
self.splice(idx..(idx + needle.len()), replacement.iter().cloned());
|
let second = &self[(idx + needle.len())..];
|
||||||
|
let mut ret = Vec::with_capacity(idx + replacement.len() + second.len());
|
||||||
|
ret.extend_from_slice(&self[..idx]);
|
||||||
|
ret.extend_from_slice(replacement);
|
||||||
|
ret.extend_from_slice(second);
|
||||||
|
ret
|
||||||
|
} else {
|
||||||
|
self
|
||||||
}
|
}
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,23 +80,23 @@ mod tests {
|
|||||||
assert_eq!(buf, b"bla");
|
assert_eq!(buf, b"bla");
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn replace() {
|
fn replace_first() {
|
||||||
let buf = b"bla to='tsnhaou' bla2".replace(b" to=", b" from=");
|
let buf = b"bla to='tsnhaou' bla2".replace_first(b" to=", b" from=");
|
||||||
assert_eq!(buf, b"bla from='tsnhaou' bla2");
|
assert_eq!(buf, b"bla from='tsnhaou' bla2");
|
||||||
|
|
||||||
let buf = buf.replace(b" from=", b" to=");
|
let buf = buf.replace_first(b" from=", b" to=");
|
||||||
assert_eq!(buf, b"bla to='tsnhaou' bla2");
|
assert_eq!(buf, b"bla to='tsnhaou' bla2");
|
||||||
|
|
||||||
let buf = buf.replace(b" to=", b" from=");
|
let buf = buf.replace_first(b" to=", b" from=");
|
||||||
assert_eq!(buf, b"bla from='tsnhaou' bla2");
|
assert_eq!(buf, b"bla from='tsnhaou' bla2");
|
||||||
|
|
||||||
let buf = b"bla to='tsnhaou' bla2".replace(b"bla", b"boo");
|
let buf = b"bla to='tsnhaou' bla2".replace_first(b"bla", b"boo");
|
||||||
assert_eq!(buf, b"boo to='tsnhaou' boo2");
|
assert_eq!(buf, b"boo to='tsnhaou' bla2");
|
||||||
|
|
||||||
let buf = buf.replace(b"boo", b"bla");
|
let buf = buf.replace_first(b"boo", b"bla");
|
||||||
assert_eq!(buf, b"bla to='tsnhaou' bla2");
|
assert_eq!(buf, b"bla to='tsnhaou' bla2");
|
||||||
|
|
||||||
let buf = buf.replace(b" bla2", b"");
|
let buf = buf.replace_first(b" bla2", b"");
|
||||||
assert_eq!(buf, b"bla to='tsnhaou'");
|
assert_eq!(buf, b"bla to='tsnhaou'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user