1use std::path::Path;
2use std::sync::Arc;
3
4use anyhow::Context;
5
6use sequoia_openpgp as openpgp;
7use openpgp::cert::raw::RawCertParser;
8use openpgp::Fingerprint;
9use openpgp::KeyHandle;
10use openpgp::packet::UserID;
11use openpgp::parse::Parse;
12use openpgp::Result;
13
14use crate::LazyCert;
15use crate::store;
16use store::Certs;
17use store::MergeCerts;
18use store::Store;
19use store::StoreError;
20use store::StoreUpdate;
21use store::UserIDQueryParams;
22
23use crate::TRACE;
24
25#[derive(Debug, Clone, PartialEq, Eq)]
26#[non_exhaustive]
27pub enum AccessMode {
28 Always,
29 OnMiss,
30}
31
32#[cfg(not(certd))]
35pub(crate) enum NoCertD {}
36
37pub struct CertStore<'a> {
56 #[cfg(certd)]
57 certd: std::result::Result<store::CertD<'a>, store::Certs<'a>>,
58 #[cfg(not(certd))]
59 certd: std::result::Result<NoCertD, store::Certs<'a>>,
60
61 backends: Vec<(Box<dyn store::Store<'a> + Send + Sync + 'a>, AccessMode)>,
63
64 keyserver: Option<Box<store::KeyServer<'a>>>,
65}
66assert_send_and_sync!(CertStore<'_>);
67
68impl<'a> CertStore<'a> {
69 pub fn empty() -> Self {
71 CertStore {
72 certd: Err(store::Certs::empty()),
73 backends: Vec::new(),
74 keyserver: None,
75 }
76 }
77
78 #[cfg(certd)]
84 pub fn new() -> Result<Self> {
85 Ok(CertStore {
86 certd: Ok(store::CertD::open_default()?),
87 backends: Vec::new(),
88 keyserver: None,
89 })
90 }
91
92 #[cfg(certd)]
95 pub fn readonly() -> Result<Self> {
96 let mut cert_store = CertStore {
97 certd: Err(store::Certs::empty()),
98 backends: Vec::new(),
99 keyserver: None,
100 };
101 cert_store.add_default_certd()?;
102 Ok(cert_store)
103 }
104
105 #[cfg(certd)]
111 pub fn open<P>(path: P) -> Result<Self>
112 where P: AsRef<Path>
113 {
114 let path = path.as_ref();
115
116 Ok(CertStore {
117 certd: Ok(store::CertD::open(path)?),
118 backends: Vec::new(),
119 keyserver: None,
120 })
121 }
122
123 #[cfg(certd)]
126 pub fn open_readonly<P>(path: P) -> Result<Self>
127 where P: AsRef<Path>
128 {
129 let path = path.as_ref();
130
131 let mut cert_store = CertStore {
132 certd: Err(store::Certs::empty()),
133 backends: Vec::new(),
134 keyserver: None,
135 };
136 cert_store.add_certd(path)?;
137 Ok(cert_store)
138 }
139
140 pub fn add_backend(&mut self, backend: Box<dyn store::Store<'a> + Send + Sync + 'a>,
144 mode: AccessMode)
145 -> &mut Self
146 {
147 self.backends.push((backend, mode));
148 self
149 }
150
151 #[cfg(certd)]
156 pub fn add_certd<P>(&mut self, path: P) -> Result<&mut Self>
157 where P: AsRef<Path>
158 {
159 let path = path.as_ref();
160 self.add_backend(Box::new(store::CertD::open(path)?),
161 AccessMode::Always);
162 Ok(self)
163 }
164
165 #[cfg(certd)]
170 pub fn add_default_certd(&mut self) -> Result<&mut Self>
171 {
172 self.add_backend(Box::new(store::CertD::open_default()?),
173 AccessMode::Always);
174 Ok(self)
175 }
176
177 pub fn add_keyring<P>(&mut self, path: P) -> Result<&mut Self>
182 where P: AsRef<Path>
183 {
184 self.add_keyrings(std::iter::once(path))?;
185 Ok(self)
186 }
187
188 pub fn add_keyrings<I, P>(&mut self, filenames: I) -> Result<&mut Self>
193 where P: AsRef<Path>,
194 I: IntoIterator<Item=P>,
195 {
196 let keyring = Certs::empty();
197 let mut error = None;
198 for filename in filenames {
199 let filename = filename.as_ref();
200
201 let f = std::fs::File::open(filename)
202 .with_context(|| format!("Open {:?}", filename))?;
203 let parser = RawCertParser::from_reader(f)
204 .with_context(|| format!("Parsing {:?}", filename))?;
205
206 for cert in parser {
207 match cert {
208 Ok(cert) => {
209 keyring.update(Arc::new(cert.into()))
210 .expect("implementation doesn't fail");
211 }
212 Err(err) => {
213 eprint!("Parsing certificate in {:?}: {}",
214 filename, err);
215 error = Some(err);
216 }
217 }
218 }
219 }
220
221 if let Some(err) = error {
222 return Err(err).context("Parsing keyrings");
223 }
224
225 self.add_backend(
226 Box::new(keyring),
227 AccessMode::Always);
228
229 Ok(self)
230 }
231
232 #[cfg(feature = "keyserver")]
237 pub fn add_keyserver(&mut self, url: &str) -> Result<&mut Self>
238 {
239 self.keyserver = Some(Box::new(store::KeyServer::new(url)?));
240 Ok(self)
241 }
242
243 #[cfg(feature = "keyserver")]
252 pub fn add_keyserver_backend(&mut self, ks: store::KeyServer<'a>)
253 -> Result<&mut Self>
254 {
255 self.keyserver = Some(Box::new(ks));
256 Ok(self)
257 }
258
259 #[cfg(certd)]
261 pub fn certd(&self) -> Option<&store::CertD<'a>> {
262 self.certd.as_ref().ok()
263 }
264
265 #[cfg(certd)]
268 pub fn certd_mut(&mut self) -> Option<&mut store::CertD<'a>> {
269 self.certd.as_mut().ok()
270 }
271}
272
273macro_rules! forward {
274 ( $method:ident, append:$to_vec:expr, $self:expr, $term:expr, $($args:ident),* ) => {{
275 tracer!(TRACE, format!("{}({})", stringify!($method), $term));
276
277 let mut certs = Vec::new();
278 let mut err = None;
279
280 match &$self.certd {
281 #[cfg(certd)]
282 Ok(certd) => {
283 match certd.$method($($args),*) {
284 Err(err2) => {
285 if let Some(StoreError::NotFound(_))
286 = err2.downcast_ref::<StoreError>()
287 {
288 t!("certd returned nothing");
290 } else {
291 t!("certd returned: {}", err2);
292 err = Some(err2)
293 }
294 }
295 Ok(c) => {
296 let mut c = $to_vec(c);
297 t!("certd returned {}",
298 c.iter()
299 .map(|cert| cert.fingerprint().to_string())
300 .collect::<Vec<String>>()
301 .join(", "));
302 certs.append(&mut c)
303 }
304 }
305 }
306 #[cfg(not(certd))]
307 Ok(_) => unreachable!(),
308 Err(in_memory) => {
309 match in_memory.$method($($args),*) {
310 Err(err2) => {
311 if let Some(StoreError::NotFound(_))
312 = err2.downcast_ref::<StoreError>()
313 {
314 t!("in-memory returned nothing");
316 } else {
317 t!("in-memory returned: {}", err2);
318 err = Some(err2)
319 }
320 }
321 Ok(c) => {
322 let mut c = $to_vec(c);
323 t!("in-memory returned {}",
324 c.iter()
325 .map(|cert| cert.fingerprint().to_string())
326 .collect::<Vec<String>>()
327 .join(", "));
328 certs.append(&mut c)
329 }
330 }
331 }
332 }
333
334 for mode in [AccessMode::Always, AccessMode::OnMiss] {
335 for (backend, _) in $self.backends.iter()
336 .filter(|(_, m)| &mode == m)
337 {
338 match backend.$method($($args),*) {
339 Err(err2) => {
340 if let Some(StoreError::NotFound(_))
341 = err2.downcast_ref::<StoreError>()
342 {
343 t!("backend returned nothing");
345 } else {
346 t!("backend returned: {}", err2);
347 err = Some(err2)
348 }
349 }
350 Ok(c) => {
351 let mut c = $to_vec(c);
352 t!("backend returned {}",
353 c.iter()
354 .map(|cert| cert.fingerprint().to_string())
355 .collect::<Vec<String>>()
356 .join(", "));
357 certs.append(&mut c)
358 }
359 }
360 }
361
362 if mode == AccessMode::Always && ! certs.is_empty() {
365 break;
366 }
367 }
368
369 if certs.is_empty() {
370 if let Some(ks) = $self.keyserver.as_ref() {
371 if let Ok(c) = ks.$method($($args),*) {
372 certs = $to_vec(c);
373 t!("keyserver returned {}",
374 certs.iter()
375 .map(|cert| cert.fingerprint().to_string())
376 .collect::<Vec<String>>()
377 .join(", "));
378 }
379 }
380 }
381
382 if certs.is_empty() {
383 if let Some(err) = err {
384 t!("query failed: {}", err);
385 Err(err)
386 } else {
387 t!("query returned nothing");
388 Ok(certs)
389 }
390 } else {
391 t!("query returned {}",
392 certs.iter()
393 .map(|cert| cert.fingerprint().to_string())
394 .collect::<Vec<String>>()
395 .join(", "));
396 Ok(certs)
397 }
398 }};
399
400 ( $method:ident, $self:expr, $($args:ident),* ) => {{
401 forward!($method,
402 append:|c| c,
403 $self,
404 $($args),*)
405 }}
406}
407
408fn merge<'a, 'b>(mut certs: Vec<Arc<LazyCert<'a>>>)
409 -> Vec<Arc<LazyCert<'a>>>
410{
411 certs.sort_by_key(|cert| cert.fingerprint());
412 certs.dedup_by(|a, b| {
413 if a.fingerprint() == b.fingerprint() {
415 if let Ok(a2) = a.to_cert() {
416 if let Ok(b2) = b.to_cert() {
417 *b = Arc::new(LazyCert::from(
418 b2.clone()
419 .merge_public(a2.clone())
420 .expect("Same certificate")));
421 } else {
422 *b = Arc::new(LazyCert::from(a2.clone()));
424 }
425 } else {
426 }
429 true
430 } else {
431 false
432 }
433 });
434 certs
435}
436
437impl<'a> store::Store<'a> for CertStore<'a> {
438 fn lookup_by_cert(&self, kh: &KeyHandle)
439 -> Result<Vec<Arc<LazyCert<'a>>>>
440 {
441 let certs = forward!(lookup_by_cert, self, kh, kh)?;
442 if certs.is_empty() {
443 Err(StoreError::NotFound(kh.clone()).into())
444 } else {
445 Ok(merge(certs))
446 }
447 }
448
449 fn lookup_by_cert_fpr(&self, fingerprint: &Fingerprint)
450 -> Result<Arc<LazyCert<'a>>>
451 {
452 let certs = forward!(lookup_by_cert_fpr,
453 append:|c| vec![c],
454 self, fingerprint, fingerprint)?;
455 let certs = merge(certs);
457 assert!(certs.len() <= 1);
458 if let Some(cert) = certs.into_iter().next() {
459 Ok(cert)
460 } else {
461 Err(StoreError::NotFound(
462 KeyHandle::from(fingerprint.clone())).into())
463 }
464 }
465
466 fn lookup_by_cert_or_subkey(&self, kh: &KeyHandle)
467 -> Result<Vec<Arc<LazyCert<'a>>>>
468 {
469 let certs = forward!(lookup_by_cert_or_subkey, self, kh, kh)?;
470 if certs.is_empty() {
471 Err(StoreError::NotFound(kh.clone()).into())
472 } else {
473 Ok(merge(certs))
474 }
475 }
476
477 fn select_userid(&self, query: &UserIDQueryParams, pattern: &str)
478 -> Result<Vec<Arc<LazyCert<'a>>>>
479 {
480 let certs = forward!(select_userid, self, pattern, query, pattern)?;
481 if certs.is_empty() {
482 Err(StoreError::NoMatches(pattern.to_string()).into())
483 } else {
484 Ok(merge(certs))
485 }
486 }
487
488 fn lookup_by_userid(&self, userid: &UserID)
489 -> Result<Vec<Arc<LazyCert<'a>>>>
490 {
491 let certs = forward!(lookup_by_userid, self, userid, userid)?;
492 if certs.is_empty() {
493 Err(StoreError::NoMatches(
494 String::from_utf8_lossy(userid.value()).to_string()).into())
495 } else {
496 Ok(merge(certs))
497 }
498 }
499
500 fn grep_userid(&self, pattern: &str) -> Result<Vec<Arc<LazyCert<'a>>>> {
501 let certs = forward!(grep_userid, self, pattern, pattern)?;
502 if certs.is_empty() {
503 Err(StoreError::NoMatches(pattern.to_string()).into())
504 } else {
505 Ok(merge(certs))
506 }
507 }
508
509 fn lookup_by_email(&self, email: &str) -> Result<Vec<Arc<LazyCert<'a>>>> {
510 let certs = forward!(lookup_by_email, self, email, email)?;
511 if certs.is_empty() {
512 Err(StoreError::NoMatches(email.to_string()).into())
513 } else {
514 Ok(merge(certs))
515 }
516 }
517
518 fn grep_email(&self, pattern: &str) -> Result<Vec<Arc<LazyCert<'a>>>> {
519 let certs = forward!(grep_email, self, pattern, pattern)?;
520 if certs.is_empty() {
521 Err(StoreError::NoMatches(pattern.to_string()).into())
522 } else {
523 Ok(merge(certs))
524 }
525 }
526
527 fn lookup_by_email_domain(&self, domain: &str)
528 -> Result<Vec<Arc<LazyCert<'a>>>>
529 {
530 let certs = forward!(lookup_by_email_domain, self, domain, domain)?;
531 if certs.is_empty() {
532 Err(StoreError::NoMatches(domain.to_string()).into())
533 } else {
534 Ok(merge(certs))
535 }
536 }
537
538 fn fingerprints(&self) -> Box<dyn Iterator<Item=Fingerprint> + 'a> {
539 let mut certs = Vec::new();
540
541 match self.certd.as_ref() {
542 #[cfg(certd)]
543 Ok(certd) => certs.extend(certd.fingerprints()),
544 #[cfg(not(certd))]
545 Ok(_) => unreachable!(),
546 Err(in_memory) => certs.extend(in_memory.fingerprints()),
547 };
548
549 for (backend, mode) in self.backends.iter() {
550 if mode != &AccessMode::Always {
551 continue;
552 }
553
554 certs.extend(backend.fingerprints());
555 }
556
557 certs.sort();
558 certs.dedup();
559
560 Box::new(certs.into_iter())
561 }
562
563 fn certs<'b>(&'b self) -> Box<dyn Iterator<Item=Arc<LazyCert<'a>>> + 'b>
564 where 'a: 'b
565 {
566 let mut certs = Vec::new();
567
568 match self.certd {
569 #[cfg(certd)]
570 Ok(ref certd) => certs.extend(certd.certs()),
571 #[cfg(not(certd))]
572 Ok(_) => unreachable!(),
573 Err(ref in_memory) => certs.extend(in_memory.certs()),
574 };
575
576 for (backend, mode) in self.backends.iter() {
577 if mode != &AccessMode::Always {
578 continue;
579 }
580
581 certs.extend(backend.certs());
582 }
583
584 let certs = merge(certs);
585
586 Box::new(certs.into_iter())
587 }
588
589 fn prefetch_all(&self) {
590 match self.certd.as_ref() {
591 #[cfg(certd)]
592 Ok(certd) => certd.prefetch_all(),
593 #[cfg(not(certd))]
594 Ok(_) => unreachable!(),
595 Err(in_memory) => in_memory.prefetch_all(),
596 };
597
598 for (backend, _mode) in self.backends.iter() {
599 backend.prefetch_all();
600 }
601 }
602
603 fn prefetch_some(&self, certs: &[KeyHandle]) {
604 match self.certd.as_ref() {
605 #[cfg(certd)]
606 Ok(certd) => certd.prefetch_some(certs),
607 #[cfg(not(certd))]
608 Ok(_) => unreachable!(),
609 Err(in_memory) => in_memory.prefetch_some(certs),
610 };
611
612 for (backend, _mode) in self.backends.iter() {
613 backend.prefetch_some(certs);
614 }
615 }
616}
617
618impl<'a> store::StoreUpdate<'a> for CertStore<'a> {
619 fn update_by(&self, cert: Arc<LazyCert<'a>>,
620 merge_strategy: &dyn MergeCerts<'a>)
621 -> Result<Arc<LazyCert<'a>>>
622 {
623 tracer!(TRACE, "CertStore::update_by");
624 match self.certd.as_ref() {
625 #[cfg(certd)]
626 Ok(certd) => {
627 t!("Forwarding to underlying certd");
628 certd.update_by(cert, merge_strategy)
629 }
630 #[cfg(not(certd))]
631 Ok(_) => unreachable!(),
632 Err(in_memory) => {
633 t!("Forwarding to underlying in-memory DB");
634 in_memory.update_by(cert, merge_strategy)
635 }
636 }
637 }
638}
639
640impl<'a> CertStore<'a> {
641 pub fn flush(&mut self) -> Result<()> {
651 self.flush_impl()
652 }
653
654 #[cfg(not(certd))]
655 fn flush_impl(&mut self) -> Result<()> {
656 Ok(())
657 }
658
659 #[cfg(certd)]
660 fn flush_impl(&mut self) -> Result<()> {
661 tracer!(TRACE, "CertStore::flush");
663 t!("flushing");
664
665 let certd = if let Ok(certd) = self.certd.as_mut() {
666 certd
667 } else {
668 t!("no certd, can't sync");
671 return Ok(());
672 };
673
674 let ks = if let Some(ks) = self.keyserver.as_mut() {
675 ks
676 } else {
677 t!("no keyserver, can't sync");
680 return Ok(());
681 };
682
683 let mut flushed_certs = Vec::new();
684 let mut result = Ok(());
685 for c in ks.certs() {
686 let keyid = c.keyid();
687 if let Err(err) = certd.update(c.clone()) {
688 t!("syncing {} to the cert-d: {}", keyid, err);
689 if result.is_ok() {
690 result = Err(err)
691 .with_context(|| {
692 format!("Flushing changes to {} to disk",
693 keyid)
694 })
695 }
696 } else {
697 flushed_certs.push(c);
698 }
699 }
700
701 ks.delete_from_cache(flushed_certs.iter().map(Arc::clone));
705
706 t!("Flushed {} certificates", flushed_certs.len());
707 result
708 }
709}
710
711impl<'a> Drop for CertStore<'a> {
712 fn drop(&mut self) {
713 let _ = self.flush();
714 }
715}