From 1ac792ed6b345427b48e338711a0e5ceef957051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolphe=20Br=C3=A9ard?= Date: Sat, 28 Nov 2020 12:10:22 +0100 Subject: [PATCH] Add the data-line filter --- src/data_line.rs | 8 ++++++++ src/filter.rs | 6 ++++++ src/lib.rs | 2 ++ src/parsers/entry.rs | 26 +------------------------- src/parsers/parameters.rs | 11 +++++++++-- src/process.rs | 17 +++++++---------- 6 files changed, 33 insertions(+), 37 deletions(-) create mode 100644 src/data_line.rs diff --git a/src/data_line.rs b/src/data_line.rs new file mode 100644 index 0000000..dc5c97c --- /dev/null +++ b/src/data_line.rs @@ -0,0 +1,8 @@ +use crate::FilterEntry; +use std::io::{self, Write}; + +pub fn return_data_line(entry: &FilterEntry, data_line: &[u8]) { + print!("filter-dataline|{}|{}|", entry.session_id, entry.token); + io::stdout().write_all(data_line).unwrap(); + println!(""); +} diff --git a/src/filter.rs b/src/filter.rs index eb1b0b3..1400ca5 100644 --- a/src/filter.rs +++ b/src/filter.rs @@ -43,6 +43,12 @@ pub trait Filter { return false; } + fn on_filter_data_line(&mut self, _entry: &FilterEntry, _data_line: &[u8]) {} + #[doc(hidden)] + fn has_filter_data_line(&self) -> bool { + return false; + } + fn on_filter_ehlo(&mut self, _entry: &FilterEntry, _identity: &str) -> FilterResponse { FilterResponse::Proceed } diff --git a/src/lib.rs b/src/lib.rs index b0c6a10..bc95e95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,12 +43,14 @@ //! //! More examples can be found in the [examples directory](https://github.com/breard-r/rust-opensmtpd/tree/main/examples). +mod data_line; mod data_structures; mod filter; mod io; mod parsers; mod process; +pub use crate::data_line::return_data_line; pub use crate::data_structures::address::Address; pub use crate::data_structures::auth_result::AuthResult; pub use crate::data_structures::event::Event; diff --git a/src/parsers/entry.rs b/src/parsers/entry.rs index cb53f72..e0adb26 100644 --- a/src/parsers/entry.rs +++ b/src/parsers/entry.rs @@ -26,22 +26,13 @@ pub struct FilterEntry { pub token: String, } -pub struct DataLineEntry { - pub session_id: String, - pub token: String, -} - pub(crate) enum EntryOption { Report(ReportEntry), Filter(FilterEntry), - DataLine(DataLineEntry), } pub(crate) fn parse_entry(input: &[u8]) -> IResult<&[u8], EntryOption> { - let (input, entry) = alt(( - parse_report_entry_meta, - alt((parse_filter_entry_meta, parse_data_line_entry_meta)), - ))(input)?; + let (input, entry) = alt((parse_report_entry_meta, parse_filter_entry_meta))(input)?; Ok((input, entry)) } @@ -59,13 +50,6 @@ fn parse_filter_entry_meta(input: &[u8]) -> IResult<&[u8], EntryOption> { Ok((input, EntryOption::Filter(entry))) } -fn parse_data_line_entry_meta(input: &[u8]) -> IResult<&[u8], EntryOption> { - let (input, _) = tag("filter-dataline")(input)?; - let (input, _) = parse_delimiter(input)?; - let (input, data_line) = parse_data_line_entry(input)?; - Ok((input, EntryOption::DataLine(data_line))) -} - fn parse_report_entry(input: &[u8]) -> IResult<&[u8], ReportEntry> { let (input, version) = parse_string_parameter(input)?; let (input, _) = parse_delimiter(input)?; @@ -109,14 +93,6 @@ fn parse_filter_entry(input: &[u8]) -> IResult<&[u8], FilterEntry> { Ok((input, entry)) } -fn parse_data_line_entry(input: &[u8]) -> IResult<&[u8], DataLineEntry> { - let (input, session_id) = parse_string_parameter(input)?; - let (input, _) = parse_delimiter(input)?; - let (input, token) = parse_string_parameter(input)?; - let entry = DataLineEntry { session_id, token }; - Ok((input, entry)) -} - fn parse_timestamp(input: &[u8]) -> IResult<&[u8], TimeVal> { let (input, sec) = map_res(digit1, |s| String::from_utf8_lossy(s).parse::())(input)?; let (input, _) = tag(".")(input)?; diff --git a/src/parsers/parameters.rs b/src/parsers/parameters.rs index e59a662..ca5f2da 100644 --- a/src/parsers/parameters.rs +++ b/src/parsers/parameters.rs @@ -1,6 +1,6 @@ use super::{ - is_parameter_char, parse_data_structure, parse_delimiter, parse_eol, parse_string_parameter, - parse_usize, + is_body_char, is_parameter_char, parse_data_structure, parse_delimiter, parse_eol, + parse_string_parameter, parse_usize, }; use crate::{Address, AuthResult, FilterKind, FilterPhase, MailResult, Method}; use nom::branch::alt; @@ -32,6 +32,13 @@ pub(crate) fn parse_filter_connect( Ok((input, (rdns, fcrdns, src, dest))) } +pub(crate) fn parse_filter_data_line(input: &[u8]) -> IResult<&[u8], &[u8]> { + let (input, _) = parse_delimiter(input)?; + let (input, s) = take_while1(is_body_char)(input)?; + let (input, _) = parse_eol(input)?; + Ok((input, s)) +} + pub(crate) fn parse_filter_ehlo(input: &[u8]) -> IResult<&[u8], String> { let (input, _) = parse_delimiter(input)?; let (input, s) = parse_string_parameter(input)?; diff --git a/src/process.rs b/src/process.rs index 54c1962..f7c7496 100644 --- a/src/process.rs +++ b/src/process.rs @@ -1,7 +1,7 @@ use crate::parsers::entry::{parse_entry, EntryOption}; use crate::parsers::parameters::{ - parse_filter_auth, parse_filter_connect, parse_filter_ehlo, parse_filter_helo, - parse_filter_mail_from, parse_filter_rcpt_to, parse_filter_starttls, + parse_filter_auth, parse_filter_connect, parse_filter_data_line, parse_filter_ehlo, + parse_filter_helo, parse_filter_mail_from, parse_filter_rcpt_to, parse_filter_starttls, parse_report_filter_report, parse_report_filter_response, parse_report_link_auth, parse_report_link_connect, parse_report_link_greeting, parse_report_link_identify, parse_report_link_tls, parse_report_protocol_client, parse_report_protocol_server, @@ -114,7 +114,11 @@ macro_rules! handle_filters { Some($obj.on_filter_connect(&$f, &rdns, &fcrdns, &src, &dest)) } FilterPhase::Data => Some($obj.on_filter_data(&$f)), - FilterPhase::DataLine => None, + FilterPhase::DataLine => { + let (_, data_line) = parse_filter_data_line($input).map_err(|e| e.to_string())?; + $obj.on_filter_data_line(&$f, &data_line); + None + } FilterPhase::Ehlo => { let (_, identity) = parse_filter_ehlo($input).map_err(|e| e.to_string())?; Some($obj.on_filter_ehlo(&$f, &identity)) @@ -139,12 +143,6 @@ macro_rules! handle_filters { }; } -macro_rules! handle_data_line { - ($obj: ident, $f: ident, $input: ident) => {{ - // TODO - }}; -} - pub(crate) fn line(user_object: &mut T, input: &[u8]) -> Result<(), String> where T: Filter, @@ -162,7 +160,6 @@ where ); }; } - EntryOption::DataLine(l) => handle_data_line!(user_object, l, input), }; Ok(()) }