x509_validator/
policy_builder.rs1use crate::PolicyFailureReason;
2use crate::der_parser::Oid;
3use crate::policy::{PolicyEvaluationResult, ValidationPolicy};
4use crate::unverified_chain::UnverifiedCertificateChain;
5
6pub struct Tuple2<A, B> {
12 first: A,
13 second: B,
14}
15
16impl<A, B> Tuple2<A, B> {
17 pub fn new(first: A, second: B) -> Self {
18 Self { first, second }
19 }
20}
21
22impl<A: ValidationPolicy, B: ValidationPolicy> ValidationPolicy for Tuple2<A, B> {
23 fn verifying_critical_extensions(&self) -> Vec<Oid<'static>> {
24 let mut exts = self
25 .first
26 .verifying_critical_extensions();
27 exts.extend(
28 self.second
29 .verifying_critical_extensions(),
30 );
31 exts
32 }
33
34 fn chain_meets_policy_requirements(
35 &self,
36 chain: &UnverifiedCertificateChain<'_>,
37 ) -> PolicyEvaluationResult {
38 self.first
39 .chain_meets_policy_requirements(chain)?;
40 self.second
41 .chain_meets_policy_requirements(chain)
42 }
43}
44
45pub enum Either<A, B> {
50 First(A),
51 Second(B),
52}
53
54impl<A: ValidationPolicy, B: ValidationPolicy> ValidationPolicy for Either<A, B> {
55 fn verifying_critical_extensions(&self) -> Vec<Oid<'static>> {
56 match self {
57 Self::First(a) => a.verifying_critical_extensions(),
58 Self::Second(b) => b.verifying_critical_extensions(),
59 }
60 }
61
62 fn chain_meets_policy_requirements(
63 &self,
64 chain: &UnverifiedCertificateChain<'_>,
65 ) -> PolicyEvaluationResult {
66 match self {
67 Self::First(a) => a.chain_meets_policy_requirements(chain),
68 Self::Second(b) => b.chain_meets_policy_requirements(chain),
69 }
70 }
71}
72
73pub struct WrappedOptional<P> {
78 wrapped: Option<P>,
79}
80
81impl<P> WrappedOptional<P> {
82 pub fn new(wrapped: Option<P>) -> Self {
83 Self { wrapped }
84 }
85}
86
87impl<P: ValidationPolicy> ValidationPolicy for WrappedOptional<P> {
88 fn verifying_critical_extensions(&self) -> Vec<Oid<'static>> {
89 self.wrapped
90 .as_ref()
91 .map(|p| p.verifying_critical_extensions())
92 .unwrap_or_default()
93 }
94
95 fn chain_meets_policy_requirements(
96 &self,
97 chain: &UnverifiedCertificateChain<'_>,
98 ) -> PolicyEvaluationResult {
99 match &self.wrapped {
100 Some(p) => p.chain_meets_policy_requirements(chain),
101 None => Ok(()),
102 }
103 }
104}
105
106#[macro_export]
125macro_rules! policy {
126 (if ($cond:expr) { $then:expr } else { $else_:expr }; $($rest:tt)+) => {
131 $crate::policy_builder::Tuple2::new(
132 if $cond {
133 $crate::policy_builder::Either::First($then)
134 } else {
135 $crate::policy_builder::Either::Second($else_)
136 },
137 $crate::policy!($($rest)+),
138 )
139 };
140 (if ($cond:expr) { $then:expr } else { $else_:expr }) => {
142 if $cond {
143 $crate::policy_builder::Either::First($then)
144 } else {
145 $crate::policy_builder::Either::Second($else_)
146 }
147 };
148 (if ($cond:expr) { $body:expr }; $($rest:tt)+) => {
150 $crate::policy_builder::Tuple2::new(
151 $crate::policy_builder::WrappedOptional::new(if $cond { Some($body) } else { None }),
152 $crate::policy!($($rest)+),
153 )
154 };
155 (if ($cond:expr) { $body:expr }) => {
157 $crate::policy_builder::WrappedOptional::new(if $cond { Some($body) } else { None })
158 };
159 ($first:expr; $($rest:tt)+) => {
161 $crate::policy_builder::Tuple2::new($first, $crate::policy!($($rest)+))
162 };
163 ($only:expr) => {
165 $only
166 };
167}
168
169pub struct OneOfTuple2<A, B> {
176 first: A,
177 second: B,
178}
179
180impl<A, B> OneOfTuple2<A, B> {
181 pub fn new(first: A, second: B) -> Self {
182 Self { first, second }
183 }
184}
185
186impl<A: ValidationPolicy, B: ValidationPolicy> ValidationPolicy for OneOfTuple2<A, B> {
187 fn verifying_critical_extensions(&self) -> Vec<Oid<'static>> {
188 let first = self
189 .first
190 .verifying_critical_extensions();
191 let second = self
192 .second
193 .verifying_critical_extensions();
194 first
195 .into_iter()
196 .filter(|oid| second.contains(oid))
197 .collect()
198 }
199
200 fn chain_meets_policy_requirements(
201 &self,
202 chain: &UnverifiedCertificateChain<'_>,
203 ) -> PolicyEvaluationResult {
204 match self
205 .first
206 .chain_meets_policy_requirements(chain)
207 {
208 Ok(()) => Ok(()),
209 Err(first_reason) => match self
210 .second
211 .chain_meets_policy_requirements(chain)
212 {
213 Ok(()) => Ok(()),
214 Err(second_reason) => Err(PolicyFailureReason::new(format!(
215 "{first_reason} and {second_reason}"
216 ))),
217 },
218 }
219 }
220}
221
222pub struct OneOfWrappedOptional<P> {
226 wrapped: Option<P>,
227}
228
229impl<P> OneOfWrappedOptional<P> {
230 pub fn new(wrapped: Option<P>) -> Self {
231 Self { wrapped }
232 }
233}
234
235impl<P: ValidationPolicy> ValidationPolicy for OneOfWrappedOptional<P> {
236 fn verifying_critical_extensions(&self) -> Vec<Oid<'static>> {
237 self.wrapped
238 .as_ref()
239 .map(|p| p.verifying_critical_extensions())
240 .unwrap_or_default()
241 }
242
243 fn chain_meets_policy_requirements(
244 &self,
245 chain: &UnverifiedCertificateChain<'_>,
246 ) -> PolicyEvaluationResult {
247 match &self.wrapped {
248 Some(p) => p.chain_meets_policy_requirements(chain),
249 None => Err(PolicyFailureReason::new("alternative is disabled")),
250 }
251 }
252}
253
254#[macro_export]
274macro_rules! one_of {
275 (if ($cond:expr) { $then:expr } else { $else_:expr }; $($rest:tt)+) => {
280 $crate::policy_builder::OneOfTuple2::new(
281 if $cond {
282 $crate::policy_builder::Either::First($then)
283 } else {
284 $crate::policy_builder::Either::Second($else_)
285 },
286 $crate::one_of!($($rest)+),
287 )
288 };
289 (if ($cond:expr) { $then:expr } else { $else_:expr }) => {
291 if $cond {
292 $crate::policy_builder::Either::First($then)
293 } else {
294 $crate::policy_builder::Either::Second($else_)
295 }
296 };
297 (if ($cond:expr) { $body:expr }; $($rest:tt)+) => {
299 $crate::policy_builder::OneOfTuple2::new(
300 $crate::policy_builder::OneOfWrappedOptional::new(if $cond { Some($body) } else { None }),
301 $crate::one_of!($($rest)+),
302 )
303 };
304 (if ($cond:expr) { $body:expr }) => {
306 $crate::policy_builder::OneOfWrappedOptional::new(if $cond { Some($body) } else { None })
307 };
308 ($first:expr; $($rest:tt)+) => {
310 $crate::policy_builder::OneOfTuple2::new($first, $crate::one_of!($($rest)+))
311 };
312 ($only:expr) => {
314 $only
315 };
316}