tor_netdoc/parse2/
impls.rs

1//! Implementations of our useful traits, on external and parsing-mode types
2
3use super::*;
4
5/// Types related to RSA keys
6mod rsa {
7    use super::*;
8    use crate::types;
9    use tor_llcrypto::pk::rsa::PublicKey;
10
11    /// An item which contains an RSA public key as an Object, and no extra arguments
12    #[derive(Deftly)]
13    #[derive_deftly(ItemValueParseable)]
14    #[deftly(netdoc(no_extra_args))]
15    struct ParsePublicKey {
16        /// The public key data
17        #[deftly(netdoc(object))]
18        key: PublicKey,
19    }
20
21    impl ItemObjectParseable for PublicKey {
22        fn check_label(label: &str) -> Result<(), EP> {
23            match label {
24                "RSA PUBLIC KEY" => Ok(()),
25                _ => Err(EP::ObjectIncorrectLabel),
26            }
27        }
28        fn from_bytes(input: &[u8]) -> Result<Self, EP> {
29            (|| {
30                let key = PublicKey::from_der(input).ok_or(())?;
31
32                if !key.exponent_is(types::misc::RSA_FIXED_EXPONENT) {
33                    return Err(());
34                }
35                if key.bits() < types::misc::RSA_MIN_BITS {
36                    return Err(());
37                }
38
39                Ok(key)
40            })()
41            .map_err(|()| EP::ObjectInvalidData)
42        }
43    }
44
45    impl ItemValueParseable for PublicKey {
46        fn from_unparsed(item: UnparsedItem) -> Result<Self, EP> {
47            Ok(ParsePublicKey::from_unparsed(item)?.key)
48        }
49    }
50}
51
52/// Types related to times
53pub(crate) mod times {
54    use super::*;
55    use crate::types::misc::Iso8601TimeSp;
56
57    /// Date and time in deprecated ISO8601-with-space separate arguments syntax
58    ///
59    /// Eg `dir-key-published` in a dir auth key cert.
60    // TODO this should be
61    //   #[deprecated = "use the Iso8601TimeSp name instead"]
62    // but right now we have too much outstanding work in flight to do that.
63    pub type NdaSystemTimeDeprecatedSyntax = Iso8601TimeSp;
64
65    impl ItemArgumentParseable for NdaSystemTimeDeprecatedSyntax {
66        fn from_args<'s>(args: &mut ArgumentStream<'s>) -> Result<Self, ArgumentError> {
67            let t;
68            (t, *args) = (|| {
69                let whole_line_len = args.whole_line_len();
70                let options = args.parse_options();
71                let args = args.clone().into_remaining();
72                let spc2 = args
73                    .match_indices(WS)
74                    .nth(1)
75                    .map(|(spc2, _)| spc2)
76                    .unwrap_or_else(|| args.len());
77                let (t, rest) = args.split_at(spc2);
78                let t: crate::types::misc::Iso8601TimeSp =
79                    t.parse().map_err(|_| ArgumentError::Invalid)?;
80                Ok::<_, AE>((t, ArgumentStream::new(rest, whole_line_len, options)))
81            })()?;
82            Ok(t)
83        }
84    }
85}
86
87/// Protocol versions (from `tor-protover`)
88pub(crate) mod protovers {
89    use super::*;
90    use tor_protover::Protocols;
91
92    impl ItemValueParseable for Protocols {
93        fn from_unparsed(item: UnparsedItem<'_>) -> Result<Self, ErrorProblem> {
94            item.check_no_object()?;
95            item.args_copy()
96                .into_remaining()
97                .parse()
98                .map_err(item.invalid_argument_handler("protocols"))
99        }
100    }
101}
102
103/// Implementations on `Void`
104pub(crate) mod void_impls {
105    use super::*;
106
107    impl ItemValueParseable for Void {
108        fn from_unparsed(_item: UnparsedItem<'_>) -> Result<Self, ErrorProblem> {
109            Err(EP::ItemForbidden)
110        }
111    }
112
113    #[cfg(feature = "parse2")]
114    impl ItemObjectParseable for Void {
115        fn check_label(_label: &str) -> Result<(), ErrorProblem> {
116            Ok(())
117        }
118
119        fn from_bytes(_input: &[u8]) -> Result<Self, ErrorProblem> {
120            Err(EP::ObjectUnexpected)
121        }
122    }
123}
124
125/// Conversion module for `Vec<u8>` as Object with [`ItemValueParseable`]
126pub mod raw_data_object {
127    use super::*;
128
129    /// "Parse" the data
130    pub fn try_from(data: Vec<u8>) -> Result<Vec<u8>, Void> {
131        Ok(data)
132    }
133}