Skip to content

Commit

Permalink
SSH Parser (#88)
Browse files Browse the repository at this point in the history
Adds an SSH parser, datatype, and sample application to Retina
  • Loading branch information
diana-qing authored Dec 16, 2024
1 parent 9e20c0b commit 01a149c
Show file tree
Hide file tree
Showing 16 changed files with 689 additions and 7 deletions.
Binary file added .DS_Store
Binary file not shown.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ members = [
"examples/protocols",
"examples/basic",
"examples/basic_file",
"examples/log_ssh",
]
resolver = "2"

Expand Down
2 changes: 1 addition & 1 deletion configs/offline.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ nb_memory_channels = 6
timeout_resolution = 100
udp_inactivity_timeout = 60_000
tcp_inactivity_timeout = 300_000
tcp_establish_timeout = 5000
tcp_establish_timeout = 5000
1 change: 1 addition & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ x509-parser = "0.13.2"
bitmask-enum = "2.2.4"
quote = "1.0.26"
proc-macro2 = "1.0.56"
ssh-parser = "0.5.0"
syn = { version = "2.0.15" }
regex = "1.7.3"
ring = "0.17.8"
Expand Down
2 changes: 2 additions & 0 deletions core/src/filter/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ lazy_static! {
let http = g.add_node(protocol!("http"));
let dns = g.add_node(protocol!("dns"));
let quic = g.add_node(protocol!("quic"));
let ssh = g.add_node(protocol!("ssh"));
// define valid outer layers for each protocol header
g.extend_with_edges([
(ipv4, ethernet),
Expand All @@ -37,6 +38,7 @@ lazy_static! {
(http, tcp),
(dns, udp), (dns, tcp),
(quic, udp), //TODO: tls over quic
(ssh, tcp),
]);
g
};
Expand Down
8 changes: 4 additions & 4 deletions core/src/memory/mempool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::fmt;
use std::os::raw::{c_int, c_uint};
use std::ptr::NonNull;

use anyhow::{bail, Context, Result};
use anyhow::{Context, Result};
use thiserror::Error;

const RX_BUF_ALIGN: u32 = 1024;
Expand All @@ -36,9 +36,9 @@ impl Mempool {
config.capacity as c_uint,
config.cache_size as c_uint,
0,
mbuf_size
.try_into()
.with_context(|| format!("mbuf size {mbuf_size} is larger than 65535, please adjust mtu"))?,
mbuf_size.try_into().with_context(|| {
format!("mbuf size {mbuf_size} is larger than 65535, please adjust mtu")
})?,
socket_id.raw() as c_int,
)
};
Expand Down
13 changes: 12 additions & 1 deletion core/src/protocols/stream/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ pub mod conn;
pub mod dns;
pub mod http;
pub mod quic;
pub mod ssh;
pub mod tls;

use self::conn::ConnField;
use self::conn::{Ipv4CData, Ipv6CData, TcpCData, UdpCData};
use self::dns::{parser::DnsParser, Dns};
use self::http::{parser::HttpParser, Http};
use self::quic::parser::QuicParser;
use self::ssh::{parser::SshParser, Ssh};
use self::tls::{parser::TlsParser, Tls};
use crate::conntrack::conn_id::FiveTuple;
use crate::conntrack::pdu::L4Pdu;
Expand All @@ -27,7 +29,7 @@ use anyhow::Result;
use quic::QuicConn;
use strum_macros::EnumString;

pub(crate) const IMPLEMENTED_PROTOCOLS: [&str; 4] = ["tls", "dns", "http", "quic"];
pub(crate) const IMPLEMENTED_PROTOCOLS: [&str; 5] = ["tls", "dns", "http", "quic", "ssh"];

/// Represents the result of parsing one packet as a protocol message.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down Expand Up @@ -206,6 +208,7 @@ pub enum SessionData {
Dns(Box<Dns>),
Http(Box<Http>),
Quic(Box<QuicConn>),
Ssh(Box<Ssh>),
Null,
}

Expand Down Expand Up @@ -250,6 +253,7 @@ pub enum ConnParser {
Dns(DnsParser),
Http(HttpParser),
Quic(QuicParser),
Ssh(SshParser),
Unknown,
}

Expand All @@ -261,6 +265,7 @@ impl ConnParser {
ConnParser::Dns(_) => ConnParser::Dns(DnsParser::default()),
ConnParser::Http(_) => ConnParser::Http(HttpParser::default()),
ConnParser::Quic(_) => ConnParser::Quic(QuicParser::default()),
ConnParser::Ssh(_) => ConnParser::Ssh(SshParser::default()),
ConnParser::Unknown => ConnParser::Unknown,
}
}
Expand All @@ -272,6 +277,7 @@ impl ConnParser {
ConnParser::Dns(parser) => parser.parse(pdu),
ConnParser::Http(parser) => parser.parse(pdu),
ConnParser::Quic(parser) => parser.parse(pdu),
ConnParser::Ssh(parser) => parser.parse(pdu),
ConnParser::Unknown => ParseResult::None,
}
}
Expand All @@ -283,6 +289,7 @@ impl ConnParser {
ConnParser::Dns(parser) => parser.probe(pdu),
ConnParser::Http(parser) => parser.probe(pdu),
ConnParser::Quic(parser) => parser.probe(pdu),
ConnParser::Ssh(parser) => parser.probe(pdu),
ConnParser::Unknown => ProbeResult::Error,
}
}
Expand All @@ -295,6 +302,7 @@ impl ConnParser {
ConnParser::Dns(parser) => parser.remove_session(session_id),
ConnParser::Http(parser) => parser.remove_session(session_id),
ConnParser::Quic(parser) => parser.remove_session(session_id),
ConnParser::Ssh(parser) => parser.remove_session(session_id),
ConnParser::Unknown => None,
}
}
Expand All @@ -306,6 +314,7 @@ impl ConnParser {
ConnParser::Dns(parser) => parser.drain_sessions(),
ConnParser::Http(parser) => parser.drain_sessions(),
ConnParser::Quic(parser) => parser.drain_sessions(),
ConnParser::Ssh(parser) => parser.drain_sessions(),
ConnParser::Unknown => vec![],
}
}
Expand All @@ -316,6 +325,7 @@ impl ConnParser {
ConnParser::Dns(parser) => parser.session_parsed_state(),
ConnParser::Http(parser) => parser.session_parsed_state(),
ConnParser::Quic(parser) => parser.session_parsed_state(),
ConnParser::Ssh(parser) => parser.session_parsed_state(),
ConnParser::Unknown => ParsingState::Stop,
}
}
Expand All @@ -328,6 +338,7 @@ impl ConnParser {
ConnParser::Dns(_parser) => Some("dns".into()),
ConnParser::Http(_parser) => Some("http".into()),
ConnParser::Quic(_parser) => Some("quic".into()),
ConnParser::Ssh(_parser) => Some("ssh".into()),
ConnParser::Unknown => None,
}
}
Expand Down
49 changes: 49 additions & 0 deletions core/src/protocols/stream/ssh/handshake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//! SSH handshake components.
//!
use crate::utils::base64;

use serde::Serialize;

/// A parsed SSH Protocol Version Exchange message.
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
pub struct SshVersionExchange {
pub protoversion: Option<String>,
pub softwareversion: Option<String>,
pub comments: Option<String>,
}

/// A parsed SSH Key Exchange message.
#[derive(Debug, PartialEq, Serialize)]
pub struct SshKeyExchange {
#[serde(with = "base64")]
pub cookie: Vec<u8>,
pub kex_algs: Vec<String>,
pub server_host_key_algs: Vec<String>,
pub encryption_algs_client_to_server: Vec<String>,
pub encryption_algs_server_to_client: Vec<String>,
pub mac_algs_client_to_server: Vec<String>,
pub mac_algs_server_to_client: Vec<String>,
pub compression_algs_client_to_server: Vec<String>,
pub compression_algs_server_to_client: Vec<String>,
pub languages_client_to_server: Vec<String>,
pub languages_server_to_client: Vec<String>,
pub first_kex_packet_follows: bool,
}

/// A parsed Diffie-Hellman Key Exchange message sent by the client.
#[derive(Debug, Default, Serialize)]
pub struct SshDhInit {
pub e: Vec<u8>,
}

/// A parsed Diffie-Hellman Key Exchange message sent by the server.
#[derive(Debug, Default, Serialize)]
pub struct SshDhResponse {
pub pubkey_and_certs: Vec<u8>,
pub f: Vec<u8>,
pub signature: Vec<u8>,
}

#[derive(Debug, Default, Serialize)]
pub struct SshNewKeys;
Loading

0 comments on commit 01a149c

Please sign in to comment.