1use crate::error::*;
2use crate::filter::*;
3use crate::ldap::*;
4use crate::parser::*;
5use asn1_rs::nom;
6use asn1_rs::OptTaggedImplicit;
7use asn1_rs::{
8 Any, Class, FromBer, OptTaggedParser, ParseResult, Sequence, Set, Tag, TaggedParser,
9};
10use nom::combinator::{complete, map};
11use nom::multi::{many0, many1};
12use nom::Err;
13use std::borrow::Cow;
15
16#[inline]
20fn parse_ldap_attribute_description(i: &[u8]) -> Result<LdapString> {
21 LdapString::from_ber(i)
22}
23
24fn parse_ldap_attribute_value_assertion_content(content: &[u8]) -> Result<AttributeValueAssertion> {
34 let (content, attribute_desc) = parse_ldap_attribute_description(content)?;
35 let (content, assertion_value) = parse_ldap_assertion_value(content)?;
36 let assertion = AttributeValueAssertion {
37 attribute_desc,
38 assertion_value: assertion_value.into(),
39 };
40 Ok((content, assertion))
41}
42
43impl<'a> FromBer<'a, LdapError> for AttributeValueAssertion<'a> {
44 fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, Self, LdapError> {
45 Sequence::from_ber_and_then(bytes, parse_ldap_attribute_value_assertion_content)
46 }
47}
48
49#[inline]
51fn parse_ldap_assertion_value(i: &[u8]) -> Result<&[u8]> {
52 parse_ldap_octet_string_as_slice(i)
53}
54
55#[inline]
57fn parse_ldap_attribute_value(i: &[u8]) -> Result<AttributeValue> {
58 map(parse_ldap_octet_string_as_slice, |v| {
59 AttributeValue(Cow::Borrowed(v))
60 })(i)
61}
62
63impl<'a> FromBer<'a, LdapError> for PartialAttribute<'a> {
67 fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, Self, LdapError> {
68 Sequence::from_ber_and_then(bytes, |i| {
69 let (i, attr_type) = LdapString::from_ber(i)?;
70 let (i, attr_vals) = Set::from_ber_and_then(i, |inner| {
71 many0(complete(
72 parse_ldap_attribute_value,
74 ))(inner)
75 })?;
76 let partial_attr = PartialAttribute {
77 attr_type,
78 attr_vals,
79 };
80 Ok((i, partial_attr))
81 })
82 }
83}
84
85impl<'a> FromBer<'a, LdapError> for Attribute<'a> {
89 fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, Self, LdapError> {
90 Sequence::from_ber_and_then(bytes, |i| {
91 let (i, attr_type) = LdapString::from_ber(i)?;
92 let (i, attr_vals) = Set::from_ber_and_then(i, |inner| {
93 many1(complete(
94 parse_ldap_attribute_value,
96 ))(inner)
97 })?;
98 let attr = Attribute {
99 attr_type,
100 attr_vals,
101 };
102 Ok((i, attr))
103 })
104 }
105}
106
107impl<'a> FromBer<'a, LdapError> for Filter<'a> {
122 fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, Self, LdapError> {
123 let (rem, any) = Any::from_ber(bytes).map_err(Err::convert)?;
125 any.class()
128 .assert_eq(Class::ContextSpecific)
129 .map_err(|e| Err::Error(e.into()))?;
130 let content = any.data;
131 let (_, filter) = match any.tag().0 {
132 0 => {
133 let (rem, sub_filters) = many1(complete(Filter::from_ber))(content)?;
134 Ok((rem, Filter::And(sub_filters)))
135 }
136 1 => {
137 let (rem, sub_filters) = many1(complete(Filter::from_ber))(content)?;
138 Ok((rem, Filter::Or(sub_filters)))
139 }
140 2 => map(Filter::from_ber, |f| Filter::Not(Box::new(f)))(content),
141 3 => map(
142 parse_ldap_attribute_value_assertion_content,
143 Filter::EqualityMatch,
144 )(content),
145 4 => map(parse_ldap_substrings_filter_content, Filter::Substrings)(content),
146 5 => map(
147 parse_ldap_attribute_value_assertion_content,
148 Filter::GreaterOrEqual,
149 )(content),
150 6 => map(
151 parse_ldap_attribute_value_assertion_content,
152 Filter::LessOrEqual,
153 )(content),
154 7 => {
155 let s =
156 std::str::from_utf8(content).or(Err(Err::Error(LdapError::InvalidString)))?;
157 let s = LdapString(Cow::Borrowed(s));
158 Ok(([].as_ref(), Filter::Present(s)))
159 }
160 8 => map(
161 parse_ldap_attribute_value_assertion_content,
162 Filter::ApproxMatch,
163 )(content),
164 9 => map(
165 parse_ldap_matching_rule_assertion_content,
166 Filter::ExtensibleMatch,
167 )(content),
168 _ => {
169 Err(Err::Error(LdapError::InvalidFilterType))
172 }
173 }?;
174 Ok((rem, filter))
176 }
177}
178
179fn parse_ldap_substrings_filter_content(i: &[u8]) -> Result<SubstringFilter> {
187 let (i, filter_type) = parse_ldap_attribute_description(i)?;
188 let (i, substrings) =
189 Sequence::from_ber_and_then(i, |inner| many1(complete(parse_ldap_substring))(inner))?;
190 let filter = SubstringFilter {
191 filter_type,
192 substrings,
193 };
194 Ok((i, filter))
195}
196
197fn parse_ldap_substring(bytes: &[u8]) -> Result<Substring> {
198 let (rem, any) = Any::from_ber(bytes).map_err(Err::convert)?;
199 let b = AssertionValue(Cow::Borrowed(any.data));
201 match any.tag().0 {
202 0 => Ok((rem, Substring::Initial(b))),
203 1 => Ok((rem, Substring::Any(b))),
204 2 => Ok((rem, Substring::Final(b))),
205 _ => Err(Err::Error(LdapError::InvalidSubstring)),
206 }
207}
208
209fn parse_ldap_matching_rule_assertion_content(i: &[u8]) -> Result<MatchingRuleAssertion> {
215 let (i, matching_rule) =
217 OptTaggedParser::new(Class::ContextSpecific, Tag(1)).parse_ber(i, |_, content| {
218 let s = std::str::from_utf8(content).or(Err(Err::Error(LdapError::InvalidString)))?;
219 let s = LdapString(Cow::Borrowed(s));
220 Ok((&b""[..], s))
221 })?;
222 let (i, rule_type) =
223 OptTaggedParser::new(Class::ContextSpecific, Tag(2)).parse_ber(i, |_, content| {
224 let s = std::str::from_utf8(content).or(Err(Err::Error(LdapError::InvalidString)))?;
225 let s = AttributeDescription(Cow::Borrowed(s));
226 Ok((&b""[..], s))
227 })?;
228 let (i, assertion_value) =
229 TaggedParser::from_ber_and_then(Class::ContextSpecific, 3, i, |content| {
230 let s = AssertionValue(Cow::Borrowed(content));
231 Ok((&b""[..], s))
232 })?;
233 let (i, dn_attributes) =
234 OptTaggedImplicit::<bool, asn1_rs::Error, 4>::from_ber(i).map_err(Err::convert)?;
235 let dn_attributes = dn_attributes.map(|t| t.into_inner());
236 let assertion = MatchingRuleAssertion {
237 matching_rule,
238 rule_type,
239 assertion_value,
240 dn_attributes,
241 };
242 Ok((i, assertion))
243}