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(
34 content: &[u8],
35) -> Result<'_, AttributeValueAssertion<'_>> {
36 let (content, attribute_desc) = parse_ldap_attribute_description(content)?;
37 let (content, assertion_value) = parse_ldap_assertion_value(content)?;
38 let assertion = AttributeValueAssertion {
39 attribute_desc,
40 assertion_value: assertion_value.into(),
41 };
42 Ok((content, assertion))
43}
44
45impl<'a> FromBer<'a, LdapError> for AttributeValueAssertion<'a> {
46 fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, Self, LdapError> {
47 Sequence::from_ber_and_then(bytes, parse_ldap_attribute_value_assertion_content)
48 }
49}
50
51#[inline]
53fn parse_ldap_assertion_value(i: &[u8]) -> Result<'_, &[u8]> {
54 parse_ldap_octet_string_as_slice(i)
55}
56
57#[inline]
59fn parse_ldap_attribute_value(i: &[u8]) -> Result<'_, AttributeValue<'_>> {
60 map(parse_ldap_octet_string_as_slice, |v| {
61 AttributeValue(Cow::Borrowed(v))
62 })(i)
63}
64
65impl<'a> FromBer<'a, LdapError> for PartialAttribute<'a> {
69 fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, Self, LdapError> {
70 Sequence::from_ber_and_then(bytes, |i| {
71 let (i, attr_type) = LdapString::from_ber(i)?;
72 let (i, attr_vals) = Set::from_ber_and_then(i, |inner| {
73 many0(complete(
74 parse_ldap_attribute_value,
76 ))(inner)
77 })?;
78 let partial_attr = PartialAttribute {
79 attr_type,
80 attr_vals,
81 };
82 Ok((i, partial_attr))
83 })
84 }
85}
86
87impl<'a> FromBer<'a, LdapError> for Attribute<'a> {
91 fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, Self, LdapError> {
92 Sequence::from_ber_and_then(bytes, |i| {
93 let (i, attr_type) = LdapString::from_ber(i)?;
94 let (i, attr_vals) = Set::from_ber_and_then(i, |inner| {
95 many1(complete(
96 parse_ldap_attribute_value,
98 ))(inner)
99 })?;
100 let attr = Attribute {
101 attr_type,
102 attr_vals,
103 };
104 Ok((i, attr))
105 })
106 }
107}
108
109impl<'a> FromBer<'a, LdapError> for Filter<'a> {
127 #[inline]
128 fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, Self, LdapError> {
129 filter_from_ber(MAX_FILTER_DEPTH)(bytes)
130 }
131}
132
133#[inline]
135const fn filter_from_ber<'i>(
136 limit: usize,
137) -> impl FnMut(&'i [u8]) -> ParseResult<'i, Filter<'i>, LdapError> {
138 move |bytes: &'i [u8]| Filter::from_ber_recursive(bytes, limit)
139}
140
141impl<'a> Filter<'a> {
142 fn from_ber_recursive(bytes: &'a [u8], limit: usize) -> ParseResult<'a, Self, LdapError> {
146 if limit == 0 {
147 return Err(Err::Error(LdapError::FilterMaxDepth));
148 }
149 let limit = limit - 1;
151
152 let (rem, any) = Any::from_ber(bytes).map_err(Err::convert)?;
154 any.class()
157 .assert_eq(Class::ContextSpecific)
158 .map_err(|e| Err::Error(e.into()))?;
159 let content = any.data;
160 let (_, filter) = match any.tag().0 {
161 0 => {
162 let (rem, sub_filters) = many1(complete(filter_from_ber(limit)))(content)?;
163 Ok((rem, Filter::And(sub_filters)))
164 }
165 1 => {
166 let (rem, sub_filters) = many1(complete(filter_from_ber(limit)))(content)?;
167 Ok((rem, Filter::Or(sub_filters)))
168 }
169 2 => map(filter_from_ber(limit), |f| Filter::Not(Box::new(f)))(content),
170 3 => map(
171 parse_ldap_attribute_value_assertion_content,
172 Filter::EqualityMatch,
173 )(content),
174 4 => map(parse_ldap_substrings_filter_content, Filter::Substrings)(content),
175 5 => map(
176 parse_ldap_attribute_value_assertion_content,
177 Filter::GreaterOrEqual,
178 )(content),
179 6 => map(
180 parse_ldap_attribute_value_assertion_content,
181 Filter::LessOrEqual,
182 )(content),
183 7 => {
184 let s =
185 std::str::from_utf8(content).or(Err(Err::Error(LdapError::InvalidString)))?;
186 let s = LdapString(Cow::Borrowed(s));
187 Ok(([].as_ref(), Filter::Present(s)))
188 }
189 8 => map(
190 parse_ldap_attribute_value_assertion_content,
191 Filter::ApproxMatch,
192 )(content),
193 9 => map(
194 parse_ldap_matching_rule_assertion_content,
195 Filter::ExtensibleMatch,
196 )(content),
197 _ => {
198 Err(Err::Error(LdapError::InvalidFilterType))
201 }
202 }?;
203 Ok((rem, filter))
205 }
206}
207
208fn parse_ldap_substrings_filter_content(i: &[u8]) -> Result<'_, SubstringFilter<'_>> {
216 let (i, filter_type) = parse_ldap_attribute_description(i)?;
217 let (i, substrings) =
218 Sequence::from_ber_and_then(i, |inner| many1(complete(parse_ldap_substring))(inner))?;
219 let filter = SubstringFilter {
220 filter_type,
221 substrings,
222 };
223 Ok((i, filter))
224}
225
226fn parse_ldap_substring(bytes: &[u8]) -> Result<'_, Substring<'_>> {
227 let (rem, any) = Any::from_ber(bytes).map_err(Err::convert)?;
228 let b = AssertionValue(Cow::Borrowed(any.data));
230 match any.tag().0 {
231 0 => Ok((rem, Substring::Initial(b))),
232 1 => Ok((rem, Substring::Any(b))),
233 2 => Ok((rem, Substring::Final(b))),
234 _ => Err(Err::Error(LdapError::InvalidSubstring)),
235 }
236}
237
238fn parse_ldap_matching_rule_assertion_content(i: &[u8]) -> Result<'_, MatchingRuleAssertion<'_>> {
244 let (i, matching_rule) =
246 OptTaggedParser::new(Class::ContextSpecific, Tag(1)).parse_ber(i, |_, content| {
247 let s = std::str::from_utf8(content).or(Err(Err::Error(LdapError::InvalidString)))?;
248 let s = LdapString(Cow::Borrowed(s));
249 Ok((&b""[..], s))
250 })?;
251 let (i, rule_type) =
252 OptTaggedParser::new(Class::ContextSpecific, Tag(2)).parse_ber(i, |_, content| {
253 let s = std::str::from_utf8(content).or(Err(Err::Error(LdapError::InvalidString)))?;
254 let s = AttributeDescription(Cow::Borrowed(s));
255 Ok((&b""[..], s))
256 })?;
257 let (i, assertion_value) =
258 TaggedParser::from_ber_and_then(Class::ContextSpecific, 3, i, |content| {
259 let s = AssertionValue(Cow::Borrowed(content));
260 Ok((&b""[..], s))
261 })?;
262 let (i, dn_attributes) =
263 OptTaggedImplicit::<bool, asn1_rs::Error, 4>::from_ber(i).map_err(Err::convert)?;
264 let dn_attributes = dn_attributes.map(|t| t.into_inner());
265 let assertion = MatchingRuleAssertion {
266 matching_rule,
267 rule_type,
268 assertion_value,
269 dn_attributes,
270 };
271 Ok((i, assertion))
272}