nullnet-libfireparse 0.3.4

A library for parsing and translating firewall configurations across multiple NullNet targets
Documentation
use crate::SSHConfig;
use roxmltree::Document;

const DEFAULT_PORT: u16 = 22;
const DEFAUKT_ENABLE: bool = false;
pub struct OpnSenseSSHParser {}

impl OpnSenseSSHParser {
    pub fn parse(document: &Document) -> SSHConfig {
        let ssh_node = document
            .descendants()
            .find(|e| e.has_tag_name("opnsense"))
            .and_then(|e| e.children().find(|ce| ce.has_tag_name("system")))
            .and_then(|e| e.children().find(|ce| ce.has_tag_name("ssh")));

        if let Some(ssh_node) = ssh_node {
            let enabled = ssh_node.children().any(|e| e.has_tag_name("enable"));

            let port = ssh_node
                .children()
                .find(|e| e.has_tag_name("port"))
                .and_then(|e| e.text())
                .and_then(|t| t.parse::<u16>().ok())
                .unwrap_or(DEFAULT_PORT);

            SSHConfig { enabled, port }
        } else {
            SSHConfig {
                enabled: DEFAUKT_ENABLE,
                port: DEFAULT_PORT,
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use roxmltree::Document;

    const DEFAULT_PORT: u16 = 22;

    #[test]
    fn test_missing_all_nodes() {
        let xml = r#"<config></config>"#;
        let doc = Document::parse(xml).expect("Failed to parse XML");
        let config = OpnSenseSSHParser::parse(&doc);
        assert_eq!(
            config,
            SSHConfig {
                enabled: false,
                port: DEFAULT_PORT
            }
        );
    }

    #[test]
    fn test_missing_ssh_node() {
        let xml = r#"
            <opnsense>
                <system>
                    <other>value</other>
                </system>
            </opnsense>
        "#;
        let doc = Document::parse(xml).expect("Failed to parse XML");
        let config = OpnSenseSSHParser::parse(&doc);
        assert_eq!(
            config,
            SSHConfig {
                enabled: false,
                port: DEFAULT_PORT
            }
        );
    }

    #[test]
    fn test_enabled_with_default_port() {
        let xml = r#"
            <opnsense>
                <system>
                    <ssh>
                        <enable/>
                    </ssh>
                </system>
            </opnsense>
        "#;
        let doc = Document::parse(xml).expect("Failed to parse XML");
        let config = OpnSenseSSHParser::parse(&doc);
        assert_eq!(
            config,
            SSHConfig {
                enabled: true,
                port: DEFAULT_PORT
            }
        );
    }

    #[test]
    fn test_enabled_with_custom_port() {
        let xml = r#"
            <opnsense>
                <system>
                    <ssh>
                        <enable/>
                        <port>2222</port>
                    </ssh>
                </system>
            </opnsense>
        "#;
        let doc = Document::parse(xml).expect("Failed to parse XML");
        let config = OpnSenseSSHParser::parse(&doc);
        assert_eq!(
            config,
            SSHConfig {
                enabled: true,
                port: 2222
            }
        );
    }

    #[test]
    fn test_invalid_port_falls_back_to_default() {
        let xml = r#"
            <opnsense>
                <system>
                    <ssh>
                        <enable/>
                        <port>not_a_number</port>
                    </ssh>
                </system>
            </opnsense>
        "#;
        let doc = Document::parse(xml).expect("Failed to parse XML");
        let config = OpnSenseSSHParser::parse(&doc);
        assert_eq!(
            config,
            SSHConfig {
                enabled: true,
                port: DEFAULT_PORT
            }
        );
    }

    #[test]
    fn test_disabled_no_enable_tag() {
        let xml = r#"
            <opnsense>
                <system>
                    <ssh>
                        <port>2222</port>
                    </ssh>
                </system>
            </opnsense>
        "#;
        let doc = Document::parse(xml).expect("Failed to parse XML");
        let config = OpnSenseSSHParser::parse(&doc);
        assert_eq!(
            config,
            SSHConfig {
                enabled: false,
                port: 2222
            }
        );
    }
}