1
0
mirror of https://github.com/fafhrd91/actix-net synced 2024-11-27 18:02:58 +01:00

add no-op SSL TLV

This commit is contained in:
Rob Ede 2023-09-17 21:53:51 +01:00
parent 21c31ad63d
commit 70f59f46ef
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
3 changed files with 77 additions and 10 deletions

View File

@ -8,15 +8,17 @@ description = "PROXY protocol utilities"
keywords = ["proxy", "protocol", "network", "haproxy", "tcp"] keywords = ["proxy", "protocol", "network", "haproxy", "tcp"]
categories = ["network-programming", "asynchronous"] categories = ["network-programming", "asynchronous"]
homepage = "https://actix.rs" homepage = "https://actix.rs"
repository = "https://github.com/actix/actix-net.git" repository = "https://github.com/actix/actix-net"
license = "MIT OR Apache-2.0" license.workspace = true
edition = "2018" edition.workspace = true
rust-version.workspace = true
[dependencies] [dependencies]
actix-service = "2" actix-service = "2"
actix-utils = "3" actix-utils = "3"
arrayvec = "0.7" arrayvec = "0.7"
bitflags = "2"
crc32fast = "1" crc32fast = "1"
futures-core = { version = "0.3.17", default-features = false, features = ["std"] } futures-core = { version = "0.3.17", default-features = false, features = ["std"] }
futures-util = { version = "0.3.17", default-features = false, features = ["std"] } futures-util = { version = "0.3.17", default-features = false, features = ["std"] }

View File

@ -1,7 +1,7 @@
use std::{borrow::Cow, convert::TryFrom, str}; use std::{borrow::Cow, convert::TryFrom, str};
const PP2_TYPE_ALPN: u8 = 0x01; const PP2_TYPE_ALPN: u8 = 0x01; // done
const PP2_TYPE_AUTHORITY: u8 = 0x02; const PP2_TYPE_AUTHORITY: u8 = 0x02; // done
const PP2_TYPE_CRC32C: u8 = 0x03; // done const PP2_TYPE_CRC32C: u8 = 0x03; // done
const PP2_TYPE_NOOP: u8 = 0x04; // done const PP2_TYPE_NOOP: u8 = 0x04; // done
const PP2_TYPE_UNIQUE_ID: u8 = 0x05; // done const PP2_TYPE_UNIQUE_ID: u8 = 0x05; // done
@ -100,7 +100,7 @@ impl Tlv for Authority {
} }
fn value_bytes(&self) -> Cow<'_, [u8]> { fn value_bytes(&self) -> Cow<'_, [u8]> {
Cow::Borrowed(&self.authority.as_bytes()) Cow::Borrowed(self.authority.as_bytes())
} }
} }
@ -178,11 +178,15 @@ impl UniqueId {
/// ///
/// ///
/// # Panics /// # Panics
/// Panics if `value` is empty (i.e., has length of 0). /// Panics if `value` is 0 bytes or larger than 128 bytes.
pub fn new(id: impl Into<Vec<u8>>) -> Self { pub fn new(id: impl Into<Vec<u8>>) -> Self {
let value = id.into(); let value = id.into();
assert!(!value.is_empty(), "UniqueId TLV `value` cannot be empty"); assert!(!value.is_empty(), "UniqueId TLV `value` cannot be empty");
assert!(
value.len() < 128,
"UniqueId TLV `value` cannot be larger than 128 bytes"
);
Self { value } Self { value }
} }
@ -202,6 +206,67 @@ impl Tlv for UniqueId {
} }
} }
bitflags::bitflags! {
#[derive(Debug, Clone, PartialEq, Eq)]
struct SslClientFlags: u8 {
const PP2_CLIENT_SSL = 0x01;
const PP2_CLIENT_CERT_CONN = 0x02;
const PP2_CLIENT_CERT_SESS = 0x04;
}
}
/// TLS (SSL).
///
/// Heckin broken atm.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Ssl {
/// The <client> field is made of a bit field indicating which element is present.
///
/// Note, that each of these elements may lead to extra data being appended to
/// this TLV using a second level of TLV encapsulation. It is thus possible to
/// find multiple TLV values after this field. The total length of the pp2_tlv_ssl
/// TLV will reflect this.
client: SslClientFlags,
/// The <verify> field will be zero if the client presented a certificate
/// and it was successfully verified, and non-zero otherwise.
verify: bool,
/// Sub-TLVs.
tlvs: Vec<SslTlv>,
}
impl Tlv for Ssl {
const TYPE: u8 = PP2_TYPE_SSL;
fn try_from_value(value: &[u8]) -> Option<Self> {
/// The PP2_CLIENT_SSL flag indicates that the client connected over SSL/TLS. When
/// this field is present, the US-ASCII string representation of the TLS version is
/// appended at the end of the field in the TLV format using the type
/// PP2_SUBTYPE_SSL_VERSION.
const PP2_CLIENT_SSL: u8 = 0x01;
/// PP2_CLIENT_CERT_CONN indicates that the client provided a certificate over the
/// current connection.
const PP2_CLIENT_CERT_CONN: u8 = 0x02;
/// PP2_CLIENT_CERT_SESS indicates that the client provided a
/// certificate at least once over the TLS session this connection belongs to.
const PP2_CLIENT_CERT_SESS: u8 = 0x04;
// TODO: finish parsing
None
}
fn value_bytes(&self) -> Cow<'_, [u8]> {
Cow::Borrowed(&[])
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
struct SslTlv {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -110,7 +110,7 @@ impl Header {
for (typ, value) in &self.tlvs { for (typ, value) in &self.tlvs {
wrt.write_all(&[*typ])?; wrt.write_all(&[*typ])?;
wrt.write_all(&(value.len() as u16).to_be_bytes())?; wrt.write_all(&(value.len() as u16).to_be_bytes())?;
wrt.write_all(&value)?; wrt.write_all(value)?;
} }
Ok(()) Ok(())
@ -170,7 +170,7 @@ impl Header {
let crc_sent = self let crc_sent = self
.tlvs .tlvs
.iter() .iter()
.filter_map(|(typ, value)| Crc32c::try_from_parts(*typ, &value)) .filter_map(|(typ, value)| Crc32c::try_from_parts(*typ, value))
.next()?; .next()?;
// If the checksum is provided as part of the PROXY header and the checksum // If the checksum is provided as part of the PROXY header and the checksum
@ -185,7 +185,7 @@ impl Header {
let mut this = self.clone(); let mut this = self.clone();
for (typ, value) in this.tlvs.iter_mut() { for (typ, value) in this.tlvs.iter_mut() {
if Crc32c::try_from_parts(*typ, &value).is_some() { if Crc32c::try_from_parts(*typ, value).is_some() {
value.fill(0); value.fill(0);
} }
} }