Add the data-line filter

This commit is contained in:
Rodolphe Bréard 2020-11-28 12:10:22 +01:00
parent 0a4ac5a709
commit 1ac792ed6b
6 changed files with 33 additions and 37 deletions

8
src/data_line.rs Normal file
View file

@ -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!("");
}

View file

@ -43,6 +43,12 @@ pub trait Filter {
return false; 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 { fn on_filter_ehlo(&mut self, _entry: &FilterEntry, _identity: &str) -> FilterResponse {
FilterResponse::Proceed FilterResponse::Proceed
} }

View file

@ -43,12 +43,14 @@
//! //!
//! More examples can be found in the [examples directory](https://github.com/breard-r/rust-opensmtpd/tree/main/examples). //! 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 data_structures;
mod filter; mod filter;
mod io; mod io;
mod parsers; mod parsers;
mod process; mod process;
pub use crate::data_line::return_data_line;
pub use crate::data_structures::address::Address; pub use crate::data_structures::address::Address;
pub use crate::data_structures::auth_result::AuthResult; pub use crate::data_structures::auth_result::AuthResult;
pub use crate::data_structures::event::Event; pub use crate::data_structures::event::Event;

View file

@ -26,22 +26,13 @@ pub struct FilterEntry {
pub token: String, pub token: String,
} }
pub struct DataLineEntry {
pub session_id: String,
pub token: String,
}
pub(crate) enum EntryOption { pub(crate) enum EntryOption {
Report(ReportEntry), Report(ReportEntry),
Filter(FilterEntry), Filter(FilterEntry),
DataLine(DataLineEntry),
} }
pub(crate) fn parse_entry(input: &[u8]) -> IResult<&[u8], EntryOption> { pub(crate) fn parse_entry(input: &[u8]) -> IResult<&[u8], EntryOption> {
let (input, entry) = alt(( let (input, entry) = alt((parse_report_entry_meta, parse_filter_entry_meta))(input)?;
parse_report_entry_meta,
alt((parse_filter_entry_meta, parse_data_line_entry_meta)),
))(input)?;
Ok((input, entry)) Ok((input, entry))
} }
@ -59,13 +50,6 @@ fn parse_filter_entry_meta(input: &[u8]) -> IResult<&[u8], EntryOption> {
Ok((input, EntryOption::Filter(entry))) 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> { fn parse_report_entry(input: &[u8]) -> IResult<&[u8], ReportEntry> {
let (input, version) = parse_string_parameter(input)?; let (input, version) = parse_string_parameter(input)?;
let (input, _) = parse_delimiter(input)?; let (input, _) = parse_delimiter(input)?;
@ -109,14 +93,6 @@ fn parse_filter_entry(input: &[u8]) -> IResult<&[u8], FilterEntry> {
Ok((input, entry)) 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> { fn parse_timestamp(input: &[u8]) -> IResult<&[u8], TimeVal> {
let (input, sec) = map_res(digit1, |s| String::from_utf8_lossy(s).parse::<i64>())(input)?; let (input, sec) = map_res(digit1, |s| String::from_utf8_lossy(s).parse::<i64>())(input)?;
let (input, _) = tag(".")(input)?; let (input, _) = tag(".")(input)?;

View file

@ -1,6 +1,6 @@
use super::{ use super::{
is_parameter_char, parse_data_structure, parse_delimiter, parse_eol, parse_string_parameter, is_body_char, is_parameter_char, parse_data_structure, parse_delimiter, parse_eol,
parse_usize, parse_string_parameter, parse_usize,
}; };
use crate::{Address, AuthResult, FilterKind, FilterPhase, MailResult, Method}; use crate::{Address, AuthResult, FilterKind, FilterPhase, MailResult, Method};
use nom::branch::alt; use nom::branch::alt;
@ -32,6 +32,13 @@ pub(crate) fn parse_filter_connect(
Ok((input, (rdns, fcrdns, src, dest))) 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> { pub(crate) fn parse_filter_ehlo(input: &[u8]) -> IResult<&[u8], String> {
let (input, _) = parse_delimiter(input)?; let (input, _) = parse_delimiter(input)?;
let (input, s) = parse_string_parameter(input)?; let (input, s) = parse_string_parameter(input)?;

View file

@ -1,7 +1,7 @@
use crate::parsers::entry::{parse_entry, EntryOption}; use crate::parsers::entry::{parse_entry, EntryOption};
use crate::parsers::parameters::{ use crate::parsers::parameters::{
parse_filter_auth, parse_filter_connect, parse_filter_ehlo, parse_filter_helo, parse_filter_auth, parse_filter_connect, parse_filter_data_line, parse_filter_ehlo,
parse_filter_mail_from, parse_filter_rcpt_to, parse_filter_starttls, 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_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_connect, parse_report_link_greeting, parse_report_link_identify,
parse_report_link_tls, parse_report_protocol_client, parse_report_protocol_server, 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)) Some($obj.on_filter_connect(&$f, &rdns, &fcrdns, &src, &dest))
} }
FilterPhase::Data => Some($obj.on_filter_data(&$f)), 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 => { FilterPhase::Ehlo => {
let (_, identity) = parse_filter_ehlo($input).map_err(|e| e.to_string())?; let (_, identity) = parse_filter_ehlo($input).map_err(|e| e.to_string())?;
Some($obj.on_filter_ehlo(&$f, &identity)) 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<T>(user_object: &mut T, input: &[u8]) -> Result<(), String> pub(crate) fn line<T>(user_object: &mut T, input: &[u8]) -> Result<(), String>
where where
T: Filter, T: Filter,
@ -162,7 +160,6 @@ where
); );
}; };
} }
EntryOption::DataLine(l) => handle_data_line!(user_object, l, input),
}; };
Ok(()) Ok(())
} }