Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next/536/20240717/v4 #11515

Merged
merged 11 commits into from
Jul 18, 2024
1 change: 1 addition & 0 deletions doc/userguide/upgrade.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ Major changes
<upgrade/8.0-dns-logging-changes>`.
- PF_RING support has been moved to a plugin. See :doc:`PF_RING plugin
<upgrade/8.0-pfring-plugin>`.
- LDAP parser and logger have been introduced.

Removals
~~~~~~~~
Expand Down
372 changes: 372 additions & 0 deletions etc/schema.json

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions rust/Cargo.lock.in

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/Cargo.toml.in
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ lazy_static = "~1.4.0"
base64 = "~0.13.0"
bendy = { version = "~0.3.3", default-features = false }
asn1-rs = { version = "~0.6.1" }
ldap-parser = { version = "~0.4.0" }

# last version to work with MSRV 1.63
time = "=0.3.20"
Expand Down
226 changes: 226 additions & 0 deletions rust/src/ldap/filters.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
/* Copyright (C) 2024 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/

// written by Giuseppe Longo <[email protected]>

use crate::ldap::types::LdapString;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Filter {
And(Vec<Filter>),
Or(Vec<Filter>),
Not(Box<Filter>),
EqualityMatch(AttributeValueAssertion),
Substrings(SubstringFilter),
GreaterOrEqual(AttributeValueAssertion),
LessOrEqual(AttributeValueAssertion),
Present(LdapString),
ApproxMatch(AttributeValueAssertion),
ExtensibleMatch(MatchingRuleAssertion),
}

impl<'a> From<ldap_parser::filter::Filter<'a>> for Filter {
fn from(f: ldap_parser::filter::Filter) -> Self {
match f {
ldap_parser::filter::Filter::And(val) => {
let mut vec = Vec::new();
for filter in val {
vec.push(filter.into());
}
Filter::And(vec)
}
ldap_parser::filter::Filter::Or(val) => {
let mut vec = Vec::new();
for filter in val {
vec.push(filter.into());
}
Filter::Or(vec)
}
ldap_parser::filter::Filter::Not(val) => {
let f = *val;
let f2: Filter = f.into();
Filter::Not(Box::from(f2))
}
ldap_parser::filter::Filter::EqualityMatch(val) => {
Filter::EqualityMatch(AttributeValueAssertion {
attribute_desc: LdapString(val.attribute_desc.0.to_string()),
assertion_value: val.assertion_value.to_vec(),
})
}
ldap_parser::filter::Filter::Substrings(val) => {
let filter_type = LdapString(val.filter_type.0.to_string());
let mut substrings: Vec<Substring> = Vec::new();
for s in val.substrings {
substrings.push(s.into());
}
Filter::Substrings(SubstringFilter {
filter_type,
substrings,
})
}
ldap_parser::filter::Filter::GreaterOrEqual(val) => {
Filter::GreaterOrEqual(AttributeValueAssertion {
attribute_desc: LdapString(val.attribute_desc.0.to_string()),
assertion_value: val.assertion_value.to_vec(),
})
}
ldap_parser::filter::Filter::LessOrEqual(val) => {
Filter::LessOrEqual(AttributeValueAssertion {
attribute_desc: LdapString(val.attribute_desc.0.to_string()),
assertion_value: val.assertion_value.to_vec(),
})
}
ldap_parser::filter::Filter::Present(val) => {
Filter::Present(LdapString(val.0.to_string()))
}
ldap_parser::filter::Filter::ApproxMatch(val) => {
Filter::ApproxMatch(AttributeValueAssertion {
attribute_desc: LdapString(val.attribute_desc.0.to_string()),
assertion_value: val.assertion_value.to_vec(),
})
}
ldap_parser::filter::Filter::ExtensibleMatch(val) => {
let matching_rule = if let Some(mr) = val.matching_rule {
Some(LdapString(mr.0.to_string()))
} else {
None
};
let rule_type = if let Some(rt) = val.rule_type {
Some(AttributeDescription(rt.0.to_string()))
} else {
None
};
let assertion_value = AssertionValue(val.assertion_value.0.to_vec());
let dn_attributes = val.dn_attributes;
Filter::ExtensibleMatch(MatchingRuleAssertion {
matching_rule,
rule_type,
assertion_value,
dn_attributes,
})
}
}
}
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PartialAttribute {
pub attr_type: LdapString,
pub attr_vals: Vec<AttributeValue>,
}

impl<'a> From<&ldap_parser::filter::PartialAttribute<'a>> for PartialAttribute {
fn from(value: &ldap_parser::filter::PartialAttribute) -> Self {
let attr_type = LdapString(value.attr_type.0.to_string());
let attr_vals: Vec<AttributeValue> = value
.attr_vals
.iter()
.map(|a| AttributeValue(a.0.to_vec()))
.collect();

Self {
attr_type,
attr_vals,
}
}
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Attribute {
pub attr_type: LdapString,
pub attr_vals: Vec<AttributeValue>,
}

impl<'a> From<&ldap_parser::filter::Attribute<'a>> for Attribute {
fn from(value: &ldap_parser::filter::Attribute) -> Self {
let attr_type = LdapString(value.attr_type.0.to_string());
let attr_vals: Vec<AttributeValue> = value
.attr_vals
.iter()
.map(|a| AttributeValue(a.0.to_vec()))
.collect();

Self {
attr_type,
attr_vals,
}
}
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AttributeValueAssertion {
pub attribute_desc: LdapString,
pub assertion_value: Vec<u8>,
}
impl<'a> From<&ldap_parser::filter::AttributeValueAssertion<'a>> for AttributeValueAssertion {
fn from(value: &ldap_parser::filter::AttributeValueAssertion) -> Self {
let attribute_desc = LdapString(value.attribute_desc.0.to_string());
let assertion_value = value.assertion_value.to_vec();
Self {
attribute_desc,
assertion_value,
}
}
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AttributeDescription(pub String);

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MatchingRuleAssertion {
pub matching_rule: Option<LdapString>,
pub rule_type: Option<AttributeDescription>,
pub assertion_value: AssertionValue,
pub dn_attributes: Option<bool>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MatchingRuleId(pub String);

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SubstringFilter {
pub filter_type: LdapString,
pub substrings: Vec<Substring>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Substring {
Initial(AssertionValue),
Any(AssertionValue),
Final(AssertionValue),
}
impl<'a> From<ldap_parser::filter::Substring<'a>> for Substring {
fn from(value: ldap_parser::filter::Substring) -> Self {
match value {
ldap_parser::filter::Substring::Initial(val) => {
Substring::Initial(AssertionValue(val.0.to_vec()))
}
ldap_parser::filter::Substring::Any(val) => {
Substring::Any(AssertionValue(val.0.to_vec()))
}
ldap_parser::filter::Substring::Final(val) => {
Substring::Final(AssertionValue(val.0.to_vec()))
}
}
}
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AssertionValue(pub Vec<u8>);

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AttributeValue(pub Vec<u8>);
Loading
Loading