Skip to main content

structured_cms/timestamp/
request_extensions.rs

1//! Request extension recognition is broader than critical token recognition.
2
3use super::{RecognitionError, Request};
4use crate::Error;
5use structured_asn1::{
6    Oid, Reader,
7    memory::{Execution, OwnedVec, Work},
8};
9use structured_pkix::Extension;
10
11impl<'a> Request<'a> {
12    /// Reports every requested extension the supplied handler does not recognize.
13    ///
14    /// RFC3161 ยง2.4.1 requires server recognition regardless of criticality.
15    /// This is not a certificate-understands or token-critical-only query.
16    /// The common fallible catalogue iterator admits each metadata access;
17    /// the handler must independently admit its data-dependent decoding work.
18    /// No empty/partial successful list is returned after processing or handler
19    /// refusal. Recognition itself does not grant policy/algorithm permission.
20    /// <https://www.rfc-editor.org/rfc/rfc3161#section-2.4.1>
21    pub fn unrecognized_extensions<E>(
22        &self,
23        parent: &Reader<'_>,
24        mut recognizes: impl FnMut(&Extension<'a>, &Execution<'_>) -> Result<bool, E>,
25    ) -> Result<OwnedVec<Oid<'a>>, RecognitionError<E>> {
26        const FIELD: &str = "timeStampReq.extensions";
27        if !self.same_session(parent) {
28            return Err(RecognitionError::Processing(Error::pkix(
29                structured_pkix::Error::new(
30                    structured_pkix::ErrorCode::ForeignReader,
31                    FIELD,
32                    self.span().start,
33                ),
34            )));
35        }
36        let work = parent.execution();
37        let mut unknown = work.vector();
38        if let Some(extensions) = self.extensions() {
39            for entry in extensions.iter(&work) {
40                let entry =
41                    entry.map_err(|source| RecognitionError::Processing(Error::pkix(source)))?;
42                if !recognizes(entry, &work).map_err(|source| RecognitionError::Callback {
43                    span: entry.span(),
44                    source,
45                })? {
46                    unknown.try_push(entry.kind()).map_err(|reason| {
47                        RecognitionError::Processing(Error::resource(
48                            reason,
49                            FIELD,
50                            entry.span().start,
51                        ))
52                    })?;
53                }
54            }
55        }
56        Ok(unknown.into_owned())
57    }
58}