use crate::{
Configuration, FireparseError,
utils::{self, find_in_snapshot},
};
use aliases_parser::PfSenseAliasesParser;
use hostname_parser::PfSenseHostnameParser;
use interfaces_parser::PfSenseInterfacesParser;
use nullnet_libconfmon::{InterfaceSnapshot, Snapshot};
use roxmltree::Document;
use rules_parser::PfSenseRulesParser;
use ssh_parser::PfSenseSSHParser;
use webgui_parser::PfSenseWebGuiParser;
mod aliases_parser;
mod endpoint_parser;
mod hostname_parser;
mod interfaces_parser;
mod rules_parser;
mod ssh_parser;
mod webgui_parser;
pub struct PfSenseParser {}
impl PfSenseParser {
pub fn parse(snapshot: Snapshot) -> Result<Configuration, FireparseError> {
let (xmltree, document_encoded) = PfSenseParser::parse_config_from_snapshot(&snapshot)?;
let iterfaces = PfSenseParser::parse_interfaces_info_from_snapshot(&snapshot)?;
Ok(Configuration {
raw_content: document_encoded,
aliases: PfSenseAliasesParser::parse(&xmltree),
rules: PfSenseRulesParser::parse(&xmltree),
interfaces: PfSenseInterfacesParser::parse(&xmltree, iterfaces),
hostname: PfSenseHostnameParser::parse(&xmltree),
gui_protocol: PfSenseWebGuiParser::parse(&xmltree, "https"),
ssh: PfSenseSSHParser::parse(&xmltree),
})
}
fn parse_config_from_snapshot(
snapshot: &Snapshot,
) -> Result<(Document, String), FireparseError> {
let pfsense_config =
find_in_snapshot(snapshot, "config.xml").ok_or(FireparseError::ParserError(
String::from("PfSenseParser: 'config.xml' file is missing in the snapshot"),
))?;
let config_content = std::str::from_utf8(&pfsense_config.content).map_err(|e| {
FireparseError::ParserError(format!(
"PfSenseParser: Failed to parse 'config.xml' blob as UTF-8: {e}"
))
})?;
let xmltree = Document::parse(config_content)
.map_err(|e| FireparseError::ParserError(e.to_string()))?;
let document_encoded = utils::encode_base64(config_content.as_bytes());
Ok((xmltree, document_encoded))
}
fn parse_interfaces_info_from_snapshot(
snapshot: &Snapshot,
) -> Result<Vec<InterfaceSnapshot>, FireparseError> {
let ifaces_data =
find_in_snapshot(snapshot, "#NetworkInterfaces").ok_or(FireparseError::ParserError(
String::from("PfSenseParser: '#NetworkInterfaces' file is missing in the snapshot"),
))?;
InterfaceSnapshot::deserialize_snapshot(&ifaces_data.content)
.map_err(|e| FireparseError::ParserError(format!("PfSenseParser: Failed to deserialize network interfaces data from the snapshot. {e}")))
}
}