1use std::borrow::Borrow;
2use std::collections::BTreeMap;
3use std::fmt;
4use std::time::SystemTime;
5use std::ops::Deref;
6
7use sequoia_openpgp as openpgp;
8
9use openpgp::Result;
10use openpgp::cert::prelude::*;
11use openpgp::cert::raw::RawCert;
12use openpgp::Fingerprint;
13use openpgp::packet::UserID;
14use openpgp::policy::Policy;
15
16use sequoia_cert_store as cert_store;
17
18use crate::CertSynopsis;
19use crate::Certification;
20use crate::FULLY_TRUSTED;
21use crate::Path;
22use crate::Paths;
23use crate::store::CertStore;
24use crate::store::Store;
25use crate::store::SynopsisSlice;
26
27pub(crate) mod filter;
28use filter::CapCertificateFilter;
29use filter::CapDepthFilter;
30use filter::ChainFilter;
31use filter::SuppressIssuerFilter;
32use filter::SuppressCertificationFilter;
33use filter::TrustedIntroducerFilter;
34mod root;
35pub use root::Root;
36mod roots;
37pub use roots::Roots;
38mod path;
39pub use path::PathError;
40pub use path::CertLints;
41pub use path::CertificationLints;
42pub use path::PathLints;
43mod builder;
44pub use builder::NetworkBuilder;
45
46use super::TRACE;
47
48pub struct Network<S>
50 where S: Store
51{
52 store: S,
53
54 roots: Roots,
56
57 certification_network: bool,
61
62 maximum_depth: Option<usize>,
64}
65
66impl<S> fmt::Debug for Network<S>
67 where S: Store
68{
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(f, "Network {{\n")?;
71 write!(f, " Reference time: {:?}\n", self.reference_time())?;
72 write!(f, " Nodes:\n")?;
73
74 let mut certs: Vec<_> = self.synopses().map(|cert| {
75 (
76 cert.userids()
77 .map(|userid| {
78 String::from_utf8_lossy(userid.value())
79 .into_owned()
80 })
81 .collect::<Vec<String>>()
82 .join(", "),
83 cert.fingerprint()
84 )
85 }).collect();
86 certs.sort();
87
88 for (userid, fpr) in certs {
89 write!(f, " {}: {}\n", fpr, userid)?;
90 }
91
92 write!(f, " Edges:\n")?;
93
94 let mut certifications: Vec<crate::CertificationSet> = self
95 .iter_fingerprints()
96 .filter_map(|fpr| {
97 if let Ok(cs) = self.certifications_of(&fpr, 0.into()) {
98 if cs.is_empty() {
99 None
100 } else {
101 Some((*cs).clone())
102 }
103 } else {
104 None
105 }
106 })
107 .flatten()
108 .collect::<Vec<_>>();
109 certifications.sort_by_key(|cs| {
110 (cs.issuer().primary_userid().map(|u| u.userid().clone()),
111 cs.issuer().fingerprint(),
112 cs.target().fingerprint())
113 });
114
115 let mut last_issuer_fpr = None;
116 for cs in certifications.into_iter() {
117 let issuer = &cs.issuer();
118 let issuer_fpr = issuer.fingerprint();
119 if Some(&issuer_fpr) != last_issuer_fpr.as_ref() {
120 write!(f, " {} certifies:\n", issuer)?;
121 last_issuer_fpr = Some(issuer_fpr);
122 }
123
124 let target_fpr = cs.target().fingerprint();
125 for c in cs.into_certifications() {
126 write!(f, " {}, {}: {}, {}, {}\n",
127 target_fpr,
128 c.userid().map(|userid| {
129 String::from_utf8_lossy(userid.value()).into_owned()
130 }).unwrap_or_else(|| "<No User ID>".into()),
131 c.depth(), c.amount(),
132 if let Some(re_set) = c.regular_expressions() {
133 if re_set.matches_everything() {
134 "*".into()
135 } else {
136 format!("{:?}", re_set)
137 }
138 } else {
139 "<invalid RE>".into()
140 })?;
141 }
142 }
143
144 write!(f, "}}\n")?;
145
146 Ok(())
147 }
148}
149
150impl<S> Deref for Network<S>
151 where S: Store
152{
153 type Target = S;
154
155 fn deref(&self) -> &Self::Target {
156 &self.store
157 }
158}
159
160impl<S> Network<S>
161 where S: Store
162{
163 pub fn new<R>(store: S, roots: R)
172 -> Result<Self>
173 where R: Into<Roots>,
174 {
175 tracer!(TRACE, "Network::new");
176
177 let roots = roots.into();
178
179 t!("Roots ({}): {}.",
180 roots.iter().count(),
181 roots.iter()
182 .map(|r| format!("{} ({})", r.fingerprint(), r.amount()))
183 .collect::<Vec<_>>()
184 .join(", "));
185
186 Ok(NetworkBuilder::rooted(store, roots).build())
187 }
188
189 pub fn backend(&self) -> &S {
191 &self.store
192 }
193}
194
195impl<'a: 'policy, 'policy> Network<CertStore<'a, 'policy, cert_store::store::Certs<'a>>> {
196 pub fn from_certs<I, C, T, R>(certs: I,
201 policy: &'policy dyn Policy, t: T,
202 roots: R)
203 -> Result<Self>
204 where T: Into<Option<SystemTime>>,
205 I: IntoIterator<Item=C>,
206 C: Into<Cert>,
207 R: Into<Roots>,
208 {
209 tracer!(TRACE, "Network::from_certs");
210
211 let t = t.into().unwrap_or_else(|| SystemTime::now());
212 Network::new(
213 CertStore::from_certs(
214 certs.into_iter().map(|c| c.into()),
215 policy, t)?,
216 roots)
217 }
218
219 pub fn from_cert_refs<I, C, T, R>(certs: I,
224 policy: &'policy dyn Policy, t: T,
225 roots: R)
226 -> Result<Self>
227 where T: Into<Option<SystemTime>>,
228 I: IntoIterator<Item=C>,
229 C: Into<&'a Cert>,
230 R: Into<Roots>,
231 {
232 tracer!(TRACE, "Network::from_certs");
233
234 let t = t.into().unwrap_or_else(|| SystemTime::now());
235 Network::new(
236 CertStore::from_cert_refs(
237 certs.into_iter().map(|c| c.into()),
238 policy, t)?,
239 roots)
240 }
241
242 pub fn from_bytes<T, R>(certs: &'a [u8], policy: &'policy dyn Policy, t: T,
247 roots: R)
248 -> Result<Self>
249 where T: Into<Option<SystemTime>>,
250 R: Into<Roots>,
251 {
252 tracer!(TRACE, "Network::from_bytes");
253
254 let t = t.into().unwrap_or_else(|| SystemTime::now());
255 Network::new(CertStore::from_bytes(certs, policy, t)?, roots)
256 }
257
258 pub fn from_raw_certs<T, R>(certs: impl Iterator<Item=RawCert<'a>>,
263 policy: &'a dyn Policy, t: T,
264 roots: R)
265 -> Result<Self>
266 where T: Into<Option<SystemTime>>,
267 R: Into<Roots>,
268 {
269 tracer!(TRACE, "Network::from_raw_certs");
270
271 let t = t.into().unwrap_or_else(|| SystemTime::now());
272 Network::new(
273 CertStore::from_raw_certs(certs, policy, t)?,
274 roots)
275 }
276}
277
278impl<'a> Network<SynopsisSlice<'a>> {
279 pub fn from_synopses<R>(certs: &'a [CertSynopsis],
284 certifications: &'a [Certification],
285 t: SystemTime,
286 roots: R)
287 -> Result<Self>
288 where R: Into<Roots>
289 {
290 Network::new(
291 SynopsisSlice::new(certs, certifications, t)?,
292 roots)
293 }
294}
295
296impl<S> Network<S>
297 where S: Store
298{
299 pub fn roots(&self) -> &Roots
301 {
302 &self.roots
303 }
304
305 pub fn is_root<F>(&self, fpr: F) -> bool
307 where F: Borrow<Fingerprint>
308 {
309 self.roots.is_root(fpr.borrow())
310 }
311
312 pub fn root<F>(&self, fpr: F) -> Option<&Root>
314 where F: Borrow<Fingerprint>
315 {
316 self.roots.get(fpr.borrow())
317 }
318
319 pub fn certification_network(&self) -> bool {
324 self.certification_network
325 }
326
327 pub fn authentication_network(&self) -> bool {
332 ! self.certification_network
333 }
334
335 pub fn maximum_depth(&mut self) -> Option<usize> {
341 self.maximum_depth
342 }
343
344 fn authenticate_internal<U, F>(&self, target_userid: U, target_fpr: F,
345 target_trust_amount: usize,
346 gossip: bool)
347 -> Paths
348 where U: Borrow<UserID>,
349 F: Borrow<Fingerprint>,
350 {
351 tracer!(TRACE, "Network::authenticate_internal");
352
353 let target_userid = target_userid.borrow();
354 let target_fpr = target_fpr.borrow();
355
356 t!("Authenticating <{}, {}>",
357 target_fpr, String::from_utf8_lossy(target_userid.value()));
358 t!("Roots ({}):", self.roots.iter().count());
359 for (i, r) in self.roots.iter().enumerate() {
360 t!(" {}: {} ({})", i, r.fingerprint(), r.amount());
361 }
362
363 let mut paths = Paths::new();
364
365 let mut filter = ChainFilter::new();
366 if self.certification_network {
367 filter.push(TrustedIntroducerFilter::new());
371 } else {
372 if self.roots.iter().any(|r| r.amount() != FULLY_TRUSTED) {
373 let mut caps = CapCertificateFilter::new();
374 for r in self.roots.iter() {
375 let amount = r.amount();
376 if amount != FULLY_TRUSTED {
377 caps.cap(r.fingerprint().clone(), amount);
378 }
379 }
380 filter.push(caps);
381 };
382 }
383
384 if let Some(limit) = self.maximum_depth {
388 filter.push(CapDepthFilter::new(limit));
389 }
390
391 let mut progress = true;
392 'next_path: while progress
393 && (paths.amount() < target_trust_amount || gossip)
394 {
395 progress = false;
396
397 let mut gossip_paths = Vec::new();
398
399 for self_signed in [true, false] {
400 let auth_paths: BTreeMap<Fingerprint, (Path, usize)>
401 = self.backward_propagate(
402 target_fpr.clone(), target_userid.clone(),
403 self_signed, &filter, gossip);
404
405 if let Some((path, path_amount)) = self.roots.iter()
411 .filter_map(|r| {
413 auth_paths.get(r.fingerprint())
414 })
415 .max_by_key(|(path, path_amount)| {
419 (path_amount,
421 -(path.len() as isize),
423 path.root().fingerprint())
426 })
427 {
428 let path = path.clone();
429
430 if path.len() == 1 {
431 let mut suppress_filter
433 = SuppressIssuerFilter::new();
434 suppress_filter.suppress_issuer(
435 &path.root().fingerprint(), *path_amount);
436 filter.push(suppress_filter);
437 } else {
438 let mut suppress_filter
441 = SuppressCertificationFilter::new();
442 suppress_filter.suppress_path(&path, *path_amount);
443 filter.push(suppress_filter);
444 }
445
446 paths.push(path, *path_amount);
447 progress = true;
448 continue 'next_path;
451 } else if gossip {
452 gossip_paths.extend(auth_paths.into_values());
453 }
454 }
455
456 assert!(! progress);
458
459 if gossip {
460 t!("Adding the remaining paths ({}) as gossip paths",
466 gossip_paths.len());
467
468 gossip_paths.sort_by_key(|(path, _amount)| {
469 -(path.len() as isize)
470 });
471 for (path, _amount) in gossip_paths.into_iter() {
472 if ! paths.has_suffix(&path) {
473 t!("Adding: {:?} (length: {})", path, path.len());
474 paths.push(path, 0);
475 } else {
476 t!("Skipping suffix: {:?}", path);
477 }
478 }
479 }
480 }
481
482 paths
483 }
484
485 pub fn authenticate<U, F>(&self, target_userid: U, target_fpr: F,
492 target_trust_amount: usize)
493 -> Paths
494 where U: Borrow<UserID>,
495 F: Borrow<Fingerprint>,
496 {
497 self.authenticate_internal(target_userid, target_fpr,
498 target_trust_amount, false)
499 }
500
501 pub fn gossip<U, F>(&self, target_fpr: F, target_userid: U)
511 -> Paths
512 where U: Borrow<UserID>,
513 F: Borrow<Fingerprint>,
514 {
515 self.authenticate_internal(target_userid, target_fpr,
516 0, true)
517 }
518}
519
520#[cfg(test)]
521mod test {
522 use super::*;
523
524 use openpgp::Fingerprint;
525 use openpgp::packet::UserID;
526 use openpgp::parse::Parse;
527 use openpgp::policy::StandardPolicy;
528
529 #[allow(unused)]
530 #[test]
531 fn third_party_certifications_of() -> Result<()> {
532 let p = &StandardPolicy::new();
533
534 let alice_fpr: Fingerprint =
535 "2A2A4A23A7EEC119BC0B46642B3825DC02A05FEA"
536 .parse().expect("valid fingerprint");
537 let alice_uid
538 = UserID::from("<alice@example.org>");
539
540 let bob_fpr: Fingerprint =
541 "03182611B91B1E7E20B848E83DFC151ABFAD85D5"
542 .parse().expect("valid fingerprint");
543 let bob_uid
544 = UserID::from("<bob@other.org>");
545 let bob_some_org_uid
547 = UserID::from("<bob@some.org>");
548 let carol_fpr: Fingerprint =
551 "9CA36907B46FE7B6B9EE9601E78064C12B6D7902"
552 .parse().expect("valid fingerprint");
553 let carol_uid
554 = UserID::from("<carol@example.org>");
555 let dave_fpr: Fingerprint =
558 "C1BC6794A6C6281B968A6A41ACE2055D610CEA03"
559 .parse().expect("valid fingerprint");
560 let dave_uid
561 = UserID::from("<dave@other.org>");
562 let certs: Vec<Cert> = CertParser::from_bytes(
566 &crate::testdata::data("multiple-userids-1.pgp"))?
567 .map(|c| c.expect("Valid certificate"))
568 .collect();
569 let store = CertStore::from_cert_refs(
570 certs.iter().map(|c| c.into()), p, None)?;
571 let n = NetworkBuilder::rootless(store).build();
572
573 eprintln!("{:?}", n);
574
575 assert!(
577 n.third_party_certifications_of(&alice_fpr.clone())
578 .is_empty());
579
580 let mut c = n.third_party_certifications_of(&bob_fpr);
582 assert_eq!(c.len(), 2);
583 c.sort_by_key(|c| (c.issuer().fingerprint(),
584 c.userid().map(Clone::clone)));
585 assert_eq!(&c[0].issuer().fingerprint(), &alice_fpr);
586 assert_eq!(c[0].userid(), Some(&bob_uid));
587 assert_eq!(&c[1].issuer().fingerprint(), &alice_fpr);
588 assert_eq!(c[1].userid(), Some(&bob_some_org_uid));
589
590 Ok(())
591 }
592
593 #[allow(unused)]
594 #[test]
595 fn certified_userids_of() -> Result<()> {
596 let p = &StandardPolicy::new();
597
598 let alice_fpr: Fingerprint =
599 "2A2A4A23A7EEC119BC0B46642B3825DC02A05FEA"
600 .parse().expect("valid fingerprint");
601 let alice_uid
602 = UserID::from("<alice@example.org>");
603
604 let bob_fpr: Fingerprint =
605 "03182611B91B1E7E20B848E83DFC151ABFAD85D5"
606 .parse().expect("valid fingerprint");
607 let bob_uid
608 = UserID::from("<bob@other.org>");
609 let bob_some_org_uid
611 = UserID::from("<bob@some.org>");
612 let carol_fpr: Fingerprint =
615 "9CA36907B46FE7B6B9EE9601E78064C12B6D7902"
616 .parse().expect("valid fingerprint");
617 let carol_uid
618 = UserID::from("<carol@example.org>");
619 let dave_fpr: Fingerprint =
622 "C1BC6794A6C6281B968A6A41ACE2055D610CEA03"
623 .parse().expect("valid fingerprint");
624 let dave_uid
625 = UserID::from("<dave@other.org>");
626 let certs: Vec<Cert> = CertParser::from_bytes(
630 &crate::testdata::data("multiple-userids-1.pgp"))?
631 .map(|c| c.expect("Valid certificate"))
632 .collect();
633 let store = CertStore::from_cert_refs(
634 certs.iter().map(|c| c.into()), p, None)?;
635 let n = NetworkBuilder::rootless(store).build();
636
637 eprintln!("{:?}", n);
638
639 let mut c = n.certified_userids_of(&alice_fpr);
641 assert_eq!(c.len(), 1);
642
643 let mut c = n.certified_userids_of(&bob_fpr);
646 assert_eq!(c.len(), 2);
647 c.sort_unstable();
648 assert_eq!(&c[0], &bob_uid);
649 assert_eq!(&c[1], &bob_some_org_uid);
650
651 Ok(())
652 }
653
654 #[allow(unused)]
655 #[test]
656 fn certified_userids() -> Result<()> {
657 let p = &StandardPolicy::new();
658
659 let alice_fpr: Fingerprint =
660 "2A2A4A23A7EEC119BC0B46642B3825DC02A05FEA"
661 .parse().expect("valid fingerprint");
662 let alice_uid
663 = UserID::from("<alice@example.org>");
664
665 let bob_fpr: Fingerprint =
666 "03182611B91B1E7E20B848E83DFC151ABFAD85D5"
667 .parse().expect("valid fingerprint");
668 let bob_uid
669 = UserID::from("<bob@other.org>");
670 let bob_some_org_uid
672 = UserID::from("<bob@some.org>");
673 let carol_fpr: Fingerprint =
676 "9CA36907B46FE7B6B9EE9601E78064C12B6D7902"
677 .parse().expect("valid fingerprint");
678 let carol_uid
679 = UserID::from("<carol@example.org>");
680 let dave_fpr: Fingerprint =
683 "C1BC6794A6C6281B968A6A41ACE2055D610CEA03"
684 .parse().expect("valid fingerprint");
685 let dave_uid
686 = UserID::from("<dave@other.org>");
687 let certs: Vec<Cert> = CertParser::from_bytes(
691 &crate::testdata::data("multiple-userids-1.pgp"))?
692 .map(|c| c.expect("Valid certificate"))
693 .collect();
694 let store = CertStore::from_cert_refs(
695 certs.iter().map(|c| c.into()), p, None)?;
696 let n = NetworkBuilder::rootless(store).build();
697
698 eprintln!("{:?}", n);
699
700 let mut got = n.certified_userids();
703 assert_eq!(got.len(), 5);
704
705 got.sort_unstable();
706
707 let mut expected = [
708 (alice_fpr.clone(), alice_uid.clone()),
709 (bob_fpr.clone(), bob_uid.clone()),
710 (bob_fpr.clone(), bob_some_org_uid.clone()),
711 (carol_fpr.clone(), carol_uid.clone()),
712 (dave_fpr.clone(), dave_uid.clone()),
713 ];
714 expected.sort_unstable();
715
716 assert_eq!(got, expected);
717
718 Ok(())
719 }
720}