sequoia_cert_store/
lib.rs

1//! A certificate store abstraction.
2//!
3//! This crates provides a unified interface for different certificate
4//! stores via the [`Store`] and [`StoreUpdate`] traits.  It also
5//! provides a number of helper functions and data structures, like
6//! [`UserIDIndex`] to help implement this functionality.
7//!
8//! [`UserIDIndex`]: store::UserIDIndex
9//!
10//! The [`CertStore`] data structure combines multiple certificate
11//! backends in a transparent way to users.
12//!
13//! # Examples
14//!
15//! We can store certificates in an in-memory store, and query the store:
16//!
17//! ```rust
18//! use std::sync::Arc;
19//! use sequoia_openpgp::cert::{Cert, CertBuilder};
20//! use sequoia_cert_store::{CertStore, LazyCert, Store, StoreUpdate};
21//!
22//! # fn main() -> anyhow::Result<()> {
23//! // Create an in-memory certificate store.  To use the default
24//! // on-disk certificate store, use `CertStore::new`.
25//! let mut certs = CertStore::empty();
26//!
27//! let (cert, _rev) = CertBuilder::new().generate()?;
28//! let fpr = cert.fingerprint();
29//!
30//! // It's not in the cert store yet:
31//! assert!(certs.lookup_by_cert_fpr(&fpr).is_err());
32//!
33//! // Insert a certificate.  If using a backing store, it would
34//! // also be written to disk.
35//! certs.update(Arc::new(LazyCert::from(cert)))?;
36//!
37//! // Make sure it is there.
38//! let cert = certs.lookup_by_cert_fpr(&fpr).expect("present");
39//! assert_eq!(cert.fingerprint(), fpr);
40//!
41//! // Resolve the `LazyCert` to a `Cert`.  Certificates are stored
42//! // using `LazyCert` so that it is possible to work with `RawCert`s
43//! // and `Cert`s.  This allows the implementation to defer fully parsing
44//! // and validating the certificate until it is actually needed.
45//! let cert: &Cert = cert.to_cert()?;
46//! # Ok(()) }
47//! ```
48//!
49//! We can use the same API on a persistent certificate store, kept on the
50//! filesystem:
51//!
52//! ```rust
53//! use std::fs;
54//! # use tempfile;
55//! #
56//! # use std::sync::Arc;
57//! #
58//! # use sequoia_openpgp as openpgp;
59//! # use openpgp::Result;
60//! # use openpgp::cert::{Cert, CertBuilder};
61//! #
62//! # use sequoia_cert_store::{CertStore, LazyCert, Store, StoreUpdate};
63//!
64//! # fn main() -> Result<()> {
65//! // Make a certificate store on the file system, in a fresh empty directory.
66//! let directory = "/tmp/test-sequoia-certificate-directory";
67//! # let directory_object = tempfile::tempdir()?; let directory = directory_object.path();
68//! fs::create_dir_all(directory)?;
69//! let mut store = CertStore::open(directory)?;
70//!
71//! // Make a new certificate.
72//! let (cert, _rev) = CertBuilder::new().generate()?;
73//! let fpr = cert.fingerprint();
74//!
75//! // The certificate of course will not be in the store yet.
76//! assert!(store.lookup_by_cert_fpr(&fpr).is_err());
77//!
78//! // Add it.
79//! store.update(Arc::new(LazyCert::from(cert)))?;
80//!
81//! // Now the certificate can be found.
82//! let found = store.lookup_by_cert_fpr(&fpr).expect("present");
83//! assert_eq!(found.fingerprint(), fpr);
84//!
85//! // Again, we can resolve the `LazyCert` to a `Cert`.
86//! let cert: &Cert = found.to_cert()?;
87//! # Ok(()) }
88//! ```
89
90use std::str;
91
92use sequoia_openpgp as openpgp;
93use openpgp::Result;
94use openpgp::packet::UserID;
95
96#[macro_use] mod log;
97#[macro_use] mod macros;
98
99pub mod store;
100pub use store::Store;
101pub use store::StoreUpdate;
102mod cert_store;
103pub use cert_store::CertStore;
104pub use cert_store::AccessMode;
105
106mod lazy_cert;
107pub use lazy_cert::LazyCert;
108
109const TRACE: bool = false;
110
111/// Converts an email address to a User ID.
112///
113/// If the email address is not valid, returns an error.
114///
115/// The email address must be a bare email address.  That is it must
116/// have the form `localpart@example.org`, and not be surrounded by
117/// angle brackets like `<localpart@example.org>`.
118///
119/// The email address is checked for validity.  Specifically, it is
120/// checked to conform with [`RFC 2822`]'s [`addr-spec`] grammar.
121///
122/// Returns a UserID containing the normalized User ID in angle
123/// brackets.
124///
125/// [`RFC 2822`]: https://www.rfc-editor.org/rfc/rfc2822
126/// [`addr-spec`]: https://www.rfc-editor.org/rfc/rfc2822#section-3.4.1
127pub fn email_to_userid(email: &str) -> Result<UserID> {
128    let email_check = UserID::from(format!("<{}>", email));
129    match email_check.email() {
130        Ok(Some(email_check)) => {
131            if email != email_check {
132                return Err(anyhow::anyhow!(
133                    "{:?} does not appear to be an email address",
134                    email));
135            }
136        }
137        Ok(None) => {
138            return Err(anyhow::anyhow!(
139                "{:?} does not appear to be an email address",
140                email));
141        }
142        Err(err) => {
143            return Err(err.context(format!(
144                "{:?} does not appear to be an email address",
145                email)));
146        }
147    }
148
149    let userid = UserID::from(&email[..]);
150    match userid.email_normalized() {
151        Err(err) => {
152            Err(err.context(format!(
153                "'{}' is not a valid email address", email)))
154        }
155        Ok(None) => {
156            Err(anyhow::anyhow!("'{}' is not a valid email address", email))
157        }
158        Ok(Some(_email)) => {
159            Ok(userid)
160        }
161    }
162}
163
164#[cfg(test)]
165mod tests {
166    use super::*;
167
168    use std::path::PathBuf;
169    use std::str;
170    use std::sync::Arc;
171
172    use anyhow::Context;
173    /// Prints the error and causes, if any.
174    pub fn print_error_chain(err: &anyhow::Error) {
175        let _ = write_error_chain_into(&mut std::io::stderr(), err);
176    }
177
178    /// Prints the error and causes, if any.
179    fn write_error_chain_into(sink: &mut dyn std::io::Write, err: &anyhow::Error)
180                              -> Result<()> {
181        writeln!(sink, "           {}", err)?;
182        for cause in err.chain().skip(1) {
183            writeln!(sink, "  because: {}", cause)?;
184        }
185        Ok(())
186    }
187
188    use openpgp::Fingerprint;
189    use openpgp::KeyHandle;
190    use openpgp::KeyID;
191    use openpgp::Cert;
192    use openpgp::parse::Parse;
193    use openpgp::policy::StandardPolicy;
194    use openpgp::serialize::Serialize;
195
196    use openpgp_cert_d as cert_d;
197
198    use store::Certs;
199    use store::Pep;
200    use store::StoreError;
201    use store::UserIDQueryParams;
202
203    fn certd_merge<'a>(new: &'a [u8], disk: Option<&[u8]>)
204        -> cert_d::Result<cert_d::MergeResult<'a>>
205    {
206        if let Some(disk) = disk {
207            let new = Cert::from_bytes(&new).expect("valid");
208            let disk = Cert::from_bytes(&disk).expect("valid");
209            let merged = new.merge_public(disk).expect("valid");
210            let mut bytes = Vec::new();
211            merged.serialize(&mut bytes).expect("valid");
212            Ok(bytes.into())
213        } else {
214            Ok(cert_d::MergeResult::DataRef(new))
215        }
216    }
217
218    include!("../tests/keyring.rs");
219
220    fn test_backend<'a, B>(backend: &B)
221        where B: Store<'a>
222    {
223        // Check Store::list.
224        {
225            let mut got: Vec<Fingerprint> = backend.fingerprints().collect();
226            got.sort();
227            let mut expected: Vec<Fingerprint> = keyring::certs.iter()
228                .map(|c| c.fingerprint.parse::<Fingerprint>().expect("valid"))
229                .collect();
230            expected.sort();
231            expected.dedup();
232            assert_eq!(got.len(), expected.len());
233            assert_eq!(got, expected);
234        }
235
236        std::thread::yield_now();
237
238        // Check Store::iter.
239        {
240            let mut got: Vec<Fingerprint>
241                = backend.certs().map(|c| c.fingerprint()).collect();
242            got.sort();
243            let mut expected: Vec<Fingerprint> = keyring::certs.iter()
244                .map(|c| c.fingerprint.parse::<Fingerprint>().expect("valid"))
245                .collect();
246            expected.sort();
247            expected.dedup();
248            assert_eq!(got.len(), expected.len());
249            assert_eq!(got, expected);
250        }
251
252        std::thread::yield_now();
253
254        // Iterate over the certificates in the keyring and check that
255        // can look up the certificate by fingerprint, by key, by User
256        // ID, and by email in various ways.
257        for handle in keyring::certs.iter() {
258            let fpr: Fingerprint = handle.fingerprint.parse().expect("valid");
259            let cert = handle.to_cert().expect("valid");
260            assert_eq!(fpr, cert.fingerprint(),
261                       "{}", handle.base);
262            let keyid = KeyID::from(fpr.clone());
263
264            // Check by_cert_fpr.
265            let got = backend.lookup_by_cert_fpr(&fpr).expect("present");
266            assert_eq!(got.fingerprint(), fpr,
267                       "{}, by_cert_fpr, primary", handle.base);
268
269            // Look up by subkey and make sure we don't get cert.
270            // Note: if a subkey is also a primary key (as is the case
271            // for the ed certificate), then we'll get a certificate
272            // back.
273            for sk in cert.keys().subkeys() {
274                match backend.lookup_by_cert_fpr(&sk.key().fingerprint()) {
275                    Ok(got) => {
276                        // Make sure what we got is what we looked up.
277                        assert_eq!(got.fingerprint(), sk.key().fingerprint());
278
279                        // Make sure subkey is also a primary key.
280                        assert!(
281                            keyring::certs.iter().any(|c| {
282                                c.fingerprint.parse::<Fingerprint>().unwrap()
283                                    == got.fingerprint()
284                            }),
285                            "{}, lookup_by_cert_fpr, subkey, unexpectedly got {}",
286                            handle.base, got.fingerprint());
287                    }
288                    Err(err) => {
289                        match err.downcast_ref::<StoreError>() {
290                            Some(StoreError::NotFound(_)) => (),
291                            _ => panic!("Expected StoreError::NotFound, \
292                                         got: {}",
293                                        err),
294                        }
295                    },
296                }
297
298                std::thread::yield_now();
299            }
300
301            // Check lookup_by_cert using key ids.
302            let got = backend.lookup_by_cert(&KeyHandle::from(&keyid))
303                .expect("present");
304            // Make sure all the returned certificates match.
305            assert!(got.iter()
306                    .all(|c| {
307                        c.keys().any(|k| k.keyid() == keyid)
308                    }),
309                    "{}, lookup_by_cert, keyid, primary",
310                    handle.base);
311
312            // Make sure one of the returned certs is the cert we're
313            // looking for.
314            assert!(got.into_iter().any(|c| c.fingerprint() == fpr),
315                    "{}, lookup_by_cert, keyid, primary", handle.base);
316
317            // Look up by subkey.  This will only return something if
318            // the subkey also happens to be a primary key.
319            for sk in cert.keys().subkeys() {
320                match backend.lookup_by_cert(&KeyHandle::from(sk.key().keyid())) {
321                    Ok(got) => {
322                        // We should never see an empty result.
323                        // Instead, the backend should return
324                        // StoreError::NotFound.
325                        assert!(! got.is_empty());
326
327                        // Make sure we got what we looked up.
328                        for got in got.iter() {
329                            assert_eq!(got.keyid(), sk.key().keyid());
330                        }
331
332                        // Make sure subkey is also a primary key.
333                        for got in got.into_iter() {
334                            assert!(
335                                keyring::certs.iter().any(|c| {
336                                    c.fingerprint.parse::<Fingerprint>()
337                                        .unwrap()
338                                        == got.fingerprint()
339                                }),
340                                "{}, lookup_by_cert_fpr, subkey, \
341                                 unexpectedly got {}",
342                                handle.base, got.fingerprint());
343                        }
344                    }
345                    Err(err) => {
346                        match err.downcast_ref::<StoreError>() {
347                            Some(StoreError::NotFound(_)) => (),
348                            _ => panic!("Expected StoreError::NotFound, \
349                                         got: {}",
350                                        err),
351                        }
352                    },
353                }
354
355                std::thread::yield_now();
356            }
357
358            // Check lookup_by_cert_or_subkey using fingerprints.
359            let got = backend.lookup_by_cert_or_subkey(&KeyHandle::from(fpr.clone()))
360                .expect("present");
361            // Make sure all the returned certificates match.
362            assert!(got.iter()
363                    .all(|c| {
364                        c.keys().any(|k| k.fingerprint() == fpr)
365                    }),
366                    "{}, lookup_by_cert_or_subkey, with fingerprint, primary",
367                    handle.base);
368
369            // Make sure one of the returned certs is the cert we're
370            // looking for.
371            assert!(got.into_iter().any(|c| c.fingerprint() == fpr),
372                    "{}, lookup_by_cert_or_subkey, with fingerprint, primary",
373                    handle.base);
374
375            // Look up by subkey and make sure we get cert.
376            for sk in cert.keys().subkeys() {
377                let got = backend.lookup_by_cert_or_subkey(
378                    &KeyHandle::from(sk.key().fingerprint()))
379                    .expect("present");
380                // Make sure all the returned certificates match.
381                for got in got.iter() {
382                    assert!(
383                        got.keys().any(|k| k.fingerprint() == sk.key().fingerprint()),
384                        "{}, lookup_by_cert_or_subkey({}), with fingerprint, subkey",
385                        handle.base, sk.key().fingerprint());
386                }
387
388                // Make sure one of the returned certs is the cert
389                // we're looking for.
390                assert!(got.into_iter().any(|c| c.fingerprint() == fpr),
391                        "{}, lookup_by_cert_or_subkey({}), with fingerprint, subkey",
392                        handle.base, sk.key().fingerprint());
393
394                std::thread::yield_now();
395            }
396
397
398            // Check lookup_by_cert_or_subkey using keyids.
399            let got = backend.lookup_by_cert_or_subkey(&KeyHandle::from(keyid.clone()))
400                .expect("present");
401            // Make sure all the returned certificates match.
402            for got in got.iter() {
403                assert!(
404                    got.keys().any(|k| k.keyid() == keyid),
405                    "{}, lookup_by_cert_or_subkey({}), with keyid, primary",
406                    handle.base, keyid);
407            }
408
409            // Make sure one of the returned certs is the cert
410            // we're looking for.
411            assert!(got.into_iter().any(|c| c.fingerprint() == fpr),
412                    "{}, lookup_by_cert_or_subkey({}), with keyid, primary",
413                    handle.base, keyid);
414
415            // Look up by subkey and make sure we get cert.
416            for sk in cert.keys().subkeys() {
417                let got = backend.lookup_by_cert_or_subkey(&KeyHandle::from(sk.key().keyid()))
418                    .expect("present");
419                // Make sure all the returned certificates match.
420                for got in got.iter() {
421                    assert!(
422                        got.keys().any(|k| k.keyid() == sk.key().keyid()),
423                        "{}, lookup_by_cert_or_subkey({}), with keyid, subkey",
424                        handle.base, sk.key().keyid());
425                }
426
427                // Make sure one of the returned certs is the cert
428                // we're looking for.
429                assert!(got.into_iter().any(|c| c.fingerprint() == fpr),
430                        "{}, lookup_by_cert_or_subkey({}), with keyid, subkey",
431                        handle.base, sk.key().keyid());
432
433                std::thread::yield_now();
434            }
435
436
437            // Check look up by User ID address by querying for each
438            // User ID, email, domain, etc.
439            for ua in cert.userids() {
440                let userid = ua.userid();
441
442                // Search by exact user id.
443                let got = backend.lookup_by_userid(userid)
444                    .expect(&format!("{}, lookup_by_userid({:?})",
445                                     handle.base, userid));
446                // Make sure all the returned certificates match.
447                for got in got.iter() {
448                    assert!(
449                        got.userids().any(|u| &u == userid),
450                        "{}, lookup_by_userid({:?})", handle.base, userid);
451                }
452
453                // Make sure one of the returned certs is the cert
454                // we're looking for.
455                assert!(got.into_iter().any(|c| c.fingerprint() == fpr),
456                        "{}, lookup_by_userid({:?})",
457                        handle.base, userid);
458
459                // Extract an interior substring (nor anchored at the
460                // start or the end), and uppercase it.
461                let pattern = str::from_utf8(userid.value()).expect("utf-8");
462                let pattern = &pattern[1..pattern.len() - 1];
463                let pattern = pattern.to_uppercase();
464
465                // grep removes all constraints so we should still
466                // find it.
467                let got = backend.grep_userid(&pattern)
468                    .expect(&format!("{}, grep_userid({:?})",
469                                     handle.base, pattern));
470
471                // Make sure all the returned certificates match.
472                let mut query = UserIDQueryParams::new();
473                query.set_email(false);
474                query.set_anchor_start(false);
475                query.set_anchor_end(false);
476                query.set_ignore_case(true);
477                for got in got.iter() {
478                    assert!(
479                        got.userids().any(|u| query.check(&u, &pattern)),
480                        "{}, grep_userid({:?})", handle.base, pattern);
481                }
482
483                // Make sure one of the returned certs is the cert
484                // we're looking for.
485                assert!(got.into_iter().any(|c| c.fingerprint() == fpr),
486                        "{}, grep_userid({:?})", handle.base, pattern);
487
488                // Now use an anchor at the start, or the end, ignore
489                // case, or not.  The only one combination that should
490                // return any results is no constraints, which we
491                // tested above.
492                for (start, end, ignore_case) in
493                    [(false, false, false),
494                     //(false, false,  true),
495                     (false,  true, false),
496                     (false,  true,  true),
497                     ( true, false, false),
498                     ( true, false,  true),
499                     ( true,  true, false),
500                     ( true,  true,  true)]
501                {
502                    let result = backend.select_userid(
503                        UserIDQueryParams::new()
504                            .set_email(false)
505                            .set_anchor_start(start)
506                            .set_anchor_end(end)
507                            .set_ignore_case(ignore_case),
508                        &pattern);
509                    match result {
510                        Ok(got) => {
511                            panic!("{}, select_userid({:?}) -> {}",
512                                   handle.base, pattern,
513                                   got.into_iter()
514                                   .map(|c| c.fingerprint().to_string())
515                                   .collect::<Vec<String>>()
516                                   .join(", "));
517                        }
518                        Err(err) => {
519                            match err.downcast_ref::<StoreError>() {
520                                Some(StoreError::NoMatches(_)) => (),
521                                _ => panic!("{}, select_userid({:?}) -> {}",
522                                            handle.base, pattern, err),
523                            }
524                        }
525                    }
526                }
527
528                // Search by exact email.
529                let email = if let Ok(Some(email)) = userid.email() {
530                    email
531                } else {
532                    // No email address.
533                    continue;
534                };
535
536                // Search with the User ID using lookup_by_email.  This will
537                // fail: a User ID that contains an email address is
538                // never a valid email address.
539                assert!(
540                    backend.lookup_by_email(
541                        str::from_utf8(userid.value()).expect("valid utf-8"))
542                        .is_err(),
543                    "{}, lookup_by_email({:?})", handle.base, userid);
544
545                // Search by email.
546                let got = backend.lookup_by_email(&email)
547                    .expect(&format!("{}, lookup_by_email({:?})",
548                                     handle.base, email));
549                // Make sure all the returned certificates match.
550                let mut query = UserIDQueryParams::new();
551                query.set_email(true);
552                query.set_anchor_start(true);
553                query.set_anchor_end(true);
554                query.set_ignore_case(false);
555                for got in got.iter() {
556                    assert!(
557                        got.userids().any(|u| query.check(&u, &email)),
558                        "{}, lookup_by_email({:?})",
559                        handle.base, email);
560                }
561
562                // Make sure one of the returned certs is the cert
563                // we're looking for.
564                assert!(got.into_iter().any(|c| c.fingerprint() == fpr),
565                        "{}, lookup_by_email({:?})", handle.base, userid);
566
567                // Extract an interior substring (nor anchored at the
568                // start or the end), and uppercase it.
569                let pattern = &email[1..email.len() - 1];
570                let pattern = pattern.to_uppercase();
571
572                // grep removes all constraints so we should still
573                // find it.
574                let got = backend.grep_email(&pattern)
575                    .expect(&format!("{}, grep_email({:?})",
576                                     handle.base, pattern));
577                // Make sure all the returned certificates match.
578                let mut query = UserIDQueryParams::new();
579                query.set_email(true);
580                query.set_anchor_start(false);
581                query.set_anchor_end(false);
582                query.set_ignore_case(true);
583                for got in got.iter() {
584                    assert!(
585                        got.userids().any(|u| query.check(&u, &pattern)),
586                        "{}, grep_email({:?})", handle.base, pattern);
587                }
588
589                // Make sure one of the returned certs is the cert
590                // we're looking for.
591                assert!(got.into_iter().any(|c| c.fingerprint() == fpr),
592                        "{}, grep_email({:?})", handle.base, pattern);
593
594                // Now use an anchor at the start, or the end, ignore
595                // case, or not.  This should not return any results;
596                // the only one that should return any results is no
597                // constraints, which we tested above.
598                for (start, end, ignore_case) in
599                    [(false, false, false),
600                     //(false, false,  true),
601                     (false,  true, false),
602                     (false,  true,  true),
603                     ( true, false, false),
604                     ( true, false,  true),
605                     ( true,  true, false),
606                     ( true,  true,  true)]
607                {
608                    let result = backend.select_userid(
609                        UserIDQueryParams::new()
610                            .set_email(true)
611                            .set_anchor_start(start)
612                            .set_anchor_end(end)
613                            .set_ignore_case(ignore_case),
614                        &pattern);
615                    match result {
616                        Ok(got) => {
617                            panic!("{}, select_userid({:?}) -> {}",
618                                   handle.base, pattern,
619                                   got.into_iter()
620                                   .map(|c| c.fingerprint().to_string())
621                                   .collect::<Vec<String>>()
622                                   .join(", "));
623                        }
624                        Err(err) => {
625                            match err.downcast_ref::<StoreError>() {
626                                Some(StoreError::NoMatches(_)) => (),
627                                _ => panic!("{}, select_userid({:?}) -> {}",
628                                            handle.base, pattern, err),
629                            }
630                        }
631                    }
632                }
633
634
635
636                // Search by domain.
637                let domain = email.rsplit('@').next().expect("have an @");
638
639                // Search with the User ID using lookup_by_email_domain.
640                // This will fail: a User ID that contains an email
641                // address is never a valid email address.
642                assert!(
643                    backend.lookup_by_email_domain(
644                        str::from_utf8(userid.value()).expect("valid utf-8"))
645                        .is_err(),
646                    "{}, lookup_by_email_domain({:?})", handle.base, userid);
647                // Likewise with the email address.
648                assert!(
649                    backend.lookup_by_email_domain(&email).is_err(),
650                    "{}, lookup_by_email_domain({:?})", handle.base, email);
651
652                // Search by domain.  We should find it.
653                let got = backend.lookup_by_email_domain(&domain)
654                    .expect(&format!("{}, lookup_by_email_domain({:?})",
655                                     handle.base, domain));
656                // Make sure all the returned certificates match.
657                let mut query = UserIDQueryParams::new();
658                query.set_email(true);
659                query.set_anchor_start(false);
660                query.set_anchor_end(true);
661                query.set_ignore_case(true);
662                let at_domain = format!("@{}", domain);
663                for got in got.iter() {
664                    assert!(
665                        got.userids().any(|u| query.check(&u, &at_domain)),
666                        "{}, lookup_by_email_domain({:?})",
667                        handle.base, domain);
668                }
669
670                // Make sure one of the returned certs is the cert
671                // we're looking for.
672                assert!(got.into_iter().any(|c| c.fingerprint() == fpr),
673                        "{}, lookup_by_email_domain({:?})",
674                        handle.base, userid);
675
676                // Uppercase it.  We should still find it.
677                let pattern = domain.to_uppercase();
678                let got = backend.lookup_by_email_domain(&pattern)
679                    .expect(&format!("{}, lookup_by_email_domain({:?})",
680                                     handle.base, pattern));
681                // Make sure all the returned certificates match.
682                let mut query = UserIDQueryParams::new();
683                query.set_email(true);
684                query.set_anchor_start(false);
685                query.set_anchor_end(true);
686                query.set_ignore_case(true);
687                let at_domain = format!("@{}", pattern);
688                for got in got.iter() {
689                    assert!(
690                        got.userids().any(|u| query.check(&u, &at_domain)),
691                        "{}, lookup_by_email_domain({:?})",
692                        handle.base, domain);
693                }
694
695                // Make sure one of the returned certs is the cert
696                // we're looking for.
697                assert!(got.into_iter().any(|c| c.fingerprint() == fpr),
698                        "{}, lookup_by_email_domain({:?})",
699                        handle.base, pattern);
700
701                // Extract a substring that we shouldn't find.
702                let pattern = &domain[1..pattern.len() - 1];
703                let result = backend.lookup_by_email_domain(pattern);
704                match result {
705                    Ok(got) => {
706                        // We should never see an empty result.
707                        // Instead, the backend should return
708                        // StoreError::NotFound.
709                        assert!(! got.is_empty());
710
711                        assert!(
712                            got.into_iter().all(|c| {
713                                c.fingerprint() != fpr
714                            }),
715                            "{}, lookup_by_email_domain({:?}, unexpectedly got {}",
716                            handle.base, pattern, fpr);
717                    }
718                    Err(err) => {
719                        match err.downcast_ref::<StoreError>() {
720                            Some(StoreError::NoMatches(_)) => (),
721                            _ => panic!("{}, lookup_by_email_domain({:?}) -> {}",
722                                        handle.base, pattern, err),
723                        }
724                    }
725                }
726
727                std::thread::yield_now();
728            }
729        }
730
731        // So far, the tests have been generic in the sense that we
732        // look up what is there.  We now do some data set-specific
733        // tests.
734
735        let sort_vec = |mut v: Vec<_>| -> Vec<_> {
736            v.sort();
737            v
738        };
739
740        // alice and alice2 share a subkey.
741        assert_eq!(
742            sort_vec(backend.lookup_by_cert_or_subkey(
743                &"5989D7BE9908AE24799DF6CFBE678043781349F1"
744                    .parse::<KeyHandle>().expect("valid"))
745                .expect("present")
746                .into_iter()
747                .map(|c| c.fingerprint())
748                .collect::<Vec<Fingerprint>>()),
749            sort_vec(
750                vec![
751                    keyring::alice.fingerprint
752                        .parse::<Fingerprint>().expect("valid"),
753                    keyring::alice2_adopted_alice.fingerprint
754                        .parse::<Fingerprint>().expect("valid"),
755            ]));
756
757        std::thread::yield_now();
758
759        // ed's primary is also a subkey on the same certificate.
760        {
761            let ed_fpr = "0C346B2B6241263F64E9C7CF1EA300797258A74E"
762                .parse::<Fingerprint>().expect("valid");
763            let ed_kh = KeyHandle::from(&ed_fpr);
764
765            assert_eq!(
766                sort_vec(backend.lookup_by_cert_or_subkey(&ed_kh)
767                         .expect("present")
768                         .into_iter()
769                         .map(|c| c.fingerprint())
770                         .collect::<Vec<Fingerprint>>()),
771                sort_vec(
772                    vec![
773                        keyring::ed.fingerprint
774                            .parse::<Fingerprint>().expect("valid"),
775                    ]));
776
777            // Also test that the CertStore implementation is not
778            // impacted.
779            let cert = backend.lookup_by_cert_fpr(&ed_fpr)
780                .expect("found cert");
781            assert_eq!(cert.fingerprint(), ed_fpr);
782
783            // Make sure the implementation doesn't return the certificate
784            // twice, once when matching on the primary key, and once when
785            // matching on the subkey.
786            let certs = backend.lookup_by_cert(&ed_kh)
787                .expect("found cert");
788            assert_eq!(certs.len(), 1);
789            assert_eq!(certs[0].fingerprint(), ed_fpr);
790
791            let certs = backend.lookup_by_cert_or_subkey(&ed_kh)
792                .expect("found cert");
793            assert_eq!(certs.len(), 1);
794            assert_eq!(certs[0].fingerprint(), ed_fpr);
795
796            let certs = backend.certs();
797            assert_eq!(certs.filter(|c| c.fingerprint() == ed_fpr).count(),
798                       1);
799
800            let fprs = backend.fingerprints();
801            assert_eq!(fprs.filter(|fpr| fpr == &ed_fpr).count(),
802                       1);
803        }
804
805        // david has a subkey that doesn't have a binding signature,
806        // but the backend is not supposed to check that.  (That
807        // subkey is bound to carol.)
808        assert_eq!(
809            sort_vec(backend.lookup_by_cert_or_subkey(
810                &"CD22D4BD99FF10FDA11A83D4213DCB92C95346CE"
811                    .parse::<KeyHandle>().expect("valid"))
812                .expect("present")
813                .into_iter()
814                .map(|c| c.fingerprint())
815                .collect::<Vec<Fingerprint>>()),
816            sort_vec(
817                vec![
818                    keyring::carol.fingerprint
819                        .parse::<Fingerprint>().expect("valid"),
820                    keyring::david.fingerprint
821                        .parse::<Fingerprint>().expect("valid"),
822            ]));
823
824
825        // Try a key that is not present.
826        match backend.lookup_by_cert_fpr(
827            &"0123 4567 89AB CDEF 0123  4567 89AB CDEF 0123 4567"
828                .parse::<Fingerprint>().expect("valid"))
829        {
830            Ok(cert) => panic!("lookup_by_cert_fpr(not present) -> {}",
831                               cert.fingerprint()),
832            Err(err) => {
833                match err.downcast_ref::<StoreError>() {
834                    Some(StoreError::NotFound(_)) => (),
835                    _ => panic!("lookup_by_cert(not present) -> {}", err),
836                }
837            }
838        }
839
840        match backend.lookup_by_cert_or_subkey(
841            &"0123 4567 89AB CDEF 0123  4567 89AB CDEF 0123 4567"
842                .parse::<KeyHandle>().expect("valid"))
843        {
844            Ok(certs) => panic!("lookup_by_cert_or_subkey(not present) -> {}",
845                                certs
846                                    .into_iter()
847                                    .map(|c| c.fingerprint().to_string())
848                                    .collect::<Vec<String>>()
849                                    .join(", ")),
850            Err(err) => {
851                match err.downcast_ref::<StoreError>() {
852                    Some(StoreError::NotFound(_)) => (),
853                    _ => panic!("lookup_by_cert(not present) -> {}", err),
854                }
855            }
856        }
857
858        std::thread::yield_now();
859
860        assert!(
861            backend.lookup_by_cert_or_subkey(
862                &"0123 4567 89AB CDEF 0123 4567 89AB CDEF"
863                    .parse::<KeyHandle>().expect("valid"))
864                .is_err());
865
866        // Check puny code handling.
867
868        // Look up the User ID using puny code.
869        assert_eq!(
870            backend.lookup_by_email("hans@xn--bcher-kva.tld")
871                .expect("present")
872                .len(),
873            1);
874        // And without puny code.
875        assert_eq!(
876            backend.lookup_by_email("hans@bücher.tld")
877                .expect("present")
878                .into_iter()
879                .map(|c| c.fingerprint())
880                .collect::<Vec<Fingerprint>>(),
881            vec![ keyring::hans_puny_code.fingerprint
882                  .parse::<Fingerprint>().expect("valid") ]);
883        // A substring shouldn't match.
884        assert_eq!(
885            backend.lookup_by_email("hans@bücher.tl")
886                .unwrap_or(Vec::new())
887                .len(),
888            0);
889
890        // The same, but just look up by domain.
891        assert_eq!(
892            backend.lookup_by_email_domain("xn--bcher-kva.tld")
893                .expect("present")
894                .into_iter()
895                .map(|c| c.fingerprint())
896                .collect::<Vec<Fingerprint>>(),
897            vec![ keyring::hans_puny_code.fingerprint
898                  .parse::<Fingerprint>().expect("valid") ]);
899        // And without puny code.
900        assert_eq!(
901            backend.lookup_by_email_domain("bücher.tld")
902                .expect("present")
903                .into_iter()
904                .map(|c| c.fingerprint())
905                .collect::<Vec<Fingerprint>>(),
906            vec![ keyring::hans_puny_code.fingerprint
907                  .parse::<Fingerprint>().expect("valid") ]);
908
909
910        std::thread::yield_now();
911
912        // Check that when looking up a subdomain, we don't get back
913        // User IDs in a subdomain.
914        assert_eq!(
915            backend.lookup_by_email_domain("company.com")
916                .expect("present")
917                .into_iter()
918                .map(|c| c.fingerprint())
919                .collect::<Vec<Fingerprint>>(),
920            vec![ keyring::una.fingerprint
921                  .parse::<Fingerprint>().expect("valid") ]);
922        assert_eq!(
923            backend.lookup_by_email_domain("sub.company.com")
924                .expect("present")
925                .into_iter()
926                .map(|c| c.fingerprint())
927                .collect::<Vec<Fingerprint>>(),
928            vec![ keyring::steve.fingerprint
929                  .parse::<Fingerprint>().expect("valid") ]);
930
931
932        // Check searching by domain.
933        assert_eq!(
934            sort_vec(backend.lookup_by_email_domain("verein.de")
935                .expect("present")
936                .into_iter()
937                .map(|c| c.fingerprint())
938                .collect::<Vec<Fingerprint>>()),
939            sort_vec(
940                vec![
941                    keyring::alice2_adopted_alice.fingerprint
942                        .parse::<Fingerprint>().expect("valid"),
943                    keyring::carol.fingerprint
944                        .parse::<Fingerprint>().expect("valid"),
945            ]));
946
947        // It should be case insenitive.
948        assert_eq!(
949            sort_vec(backend.lookup_by_email_domain("VEREIN.DE")
950                .expect("present")
951                .into_iter()
952                .map(|c| c.fingerprint())
953                .collect::<Vec<Fingerprint>>()),
954            sort_vec(
955                vec![
956                    keyring::alice2_adopted_alice.fingerprint
957                        .parse::<Fingerprint>().expect("valid"),
958                    keyring::carol.fingerprint
959                        .parse::<Fingerprint>().expect("valid"),
960            ]));
961
962
963        // Make sure the backend returns user IDs that are not self
964        // signed.
965        //
966        // Peter's self-signed user ID is: 'Peter
967        // <peter@example.com>'.  Usa certificated a non-self signed
968        // user ID: 'Dad <peter@example.family>'
969        assert_eq!(
970            backend.lookup_by_userid(
971                &UserID::from("Dad <peter@example.family>"))
972                .expect("present")
973                .len(),
974            1);
975
976        assert_eq!(
977            backend.grep_userid("Dad")
978                .expect("present")
979                .len(),
980            1);
981
982        assert_eq!(
983            backend.lookup_by_email("peter@example.family")
984                .expect("present")
985                .len(),
986            1);
987
988        assert_eq!(
989            backend.grep_email("eter@example.family")
990                .expect("present")
991                .len(),
992            1);
993
994        assert_eq!(
995            backend.lookup_by_email_domain("example.family")
996                .expect("present")
997                .len(),
998            1);
999    }
1000
1001    #[test]
1002    fn certd() -> Result<()> {
1003        use std::io::Read;
1004
1005        let path = tempfile::tempdir()?;
1006        let certd = cert_d::CertD::with_base_dir(&path)
1007            .map_err(|err| {
1008                let err = anyhow::Error::from(err)
1009                    .context(format!("While opening the certd {:?}", path));
1010                print_error_chain(&err);
1011                err
1012            })?;
1013
1014        for cert in keyring::certs.iter() {
1015            let bytes = cert.bytes();
1016            let mut reader = openpgp::armor::Reader::from_bytes(
1017                &bytes,
1018                openpgp::armor::ReaderMode::VeryTolerant);
1019            let mut bytes = Vec::new();
1020            reader.read_to_end(&mut bytes)
1021                .expect(&format!("{}", cert.base));
1022
1023            certd
1024                .insert_data(&bytes, false, certd_merge)
1025                .with_context(|| {
1026                    format!("{} ({})", cert.base, cert.fingerprint)
1027                })
1028                .expect("can insert");
1029        }
1030        drop (certd);
1031
1032        let certd = store::certd::CertD::open(&path).expect("exists");
1033        test_backend(&certd);
1034
1035        Ok(())
1036    }
1037
1038
1039    #[test]
1040    fn cert_store() -> Result<()> {
1041        use std::io::Read;
1042
1043        let path = tempfile::tempdir()?;
1044        let certd = cert_d::CertD::with_base_dir(&path)
1045            .map_err(|err| {
1046                let err = anyhow::Error::from(err)
1047                    .context(format!("While opening the certd {:?}", path));
1048                print_error_chain(&err);
1049                err
1050            })?;
1051
1052        for cert in keyring::certs.iter() {
1053            let bytes = cert.bytes();
1054            let mut reader = openpgp::armor::Reader::from_bytes(
1055                &bytes,
1056                openpgp::armor::ReaderMode::VeryTolerant);
1057            let mut bytes = Vec::new();
1058            reader.read_to_end(&mut bytes)
1059                .expect(&format!("{}", cert.base));
1060
1061            certd
1062                .insert_data(&bytes, false, certd_merge)
1063                .with_context(|| {
1064                    format!("{} ({})", cert.base, cert.fingerprint)
1065                })
1066                .expect("can insert");
1067        }
1068        drop(certd);
1069
1070        let cert_store = CertStore::open(&path).expect("exists");
1071        test_backend(&cert_store);
1072
1073        Ok(())
1074    }
1075
1076    #[test]
1077    fn cert_store_layered() -> Result<()> {
1078        use std::io::Read;
1079
1080        // A certd for each certificate.
1081        let mut paths: Vec<tempfile::TempDir> = Vec::new();
1082
1083        let mut cert_store = CertStore::empty();
1084
1085        for cert in keyring::certs.iter() {
1086            let path = tempfile::tempdir()?;
1087            let certd = cert_d::CertD::with_base_dir(&path)
1088                .map_err(|err| {
1089                    let err = anyhow::Error::from(err)
1090                        .context(format!("While opening the certd {:?}", path));
1091                    print_error_chain(&err);
1092                    err
1093                })?;
1094
1095            let bytes = cert.bytes();
1096            let mut reader = openpgp::armor::Reader::from_bytes(
1097                &bytes,
1098                openpgp::armor::ReaderMode::VeryTolerant);
1099            let mut bytes = Vec::new();
1100            reader.read_to_end(&mut bytes)
1101                .expect(&format!("{}", cert.base));
1102
1103            certd
1104                .insert_data(&bytes, false, certd_merge)
1105                .with_context(|| {
1106                    format!("{} ({})", cert.base, cert.fingerprint)
1107                })
1108                .expect("can insert");
1109            drop(certd);
1110
1111            let certd = store::CertD::open(&path).expect("valid");
1112            cert_store.add_backend(Box::new(certd), AccessMode::Always);
1113
1114            paths.push(path);
1115        }
1116
1117        test_backend(&cert_store);
1118
1119        Ok(())
1120    }
1121
1122    #[test]
1123    fn certs() -> Result<()> {
1124        use std::io::Read;
1125
1126        let mut bytes = Vec::new();
1127        for cert in keyring::certs.iter() {
1128            let binary = cert.bytes();
1129            let mut reader = openpgp::armor::Reader::from_bytes(
1130                &binary,
1131                openpgp::armor::ReaderMode::VeryTolerant);
1132            reader.read_to_end(&mut bytes)
1133                .expect(&format!("{}", cert.base));
1134        }
1135
1136        let backend = store::Certs::from_bytes(&bytes)
1137            .expect("valid");
1138        test_backend(&backend);
1139
1140        Ok(())
1141    }
1142
1143    #[test]
1144    fn certd_with_prefetch() -> Result<()> {
1145        use std::io::Read;
1146
1147        let path = tempfile::tempdir()?;
1148        let certd = cert_d::CertD::with_base_dir(&path)
1149            .map_err(|err| {
1150                let err = anyhow::Error::from(err)
1151                    .context(format!("While opening the certd {:?}", path));
1152                print_error_chain(&err);
1153                err
1154            })?;
1155
1156        for cert in keyring::certs.iter() {
1157            let bytes = cert.bytes();
1158            let mut reader = openpgp::armor::Reader::from_bytes(
1159                &bytes,
1160                openpgp::armor::ReaderMode::VeryTolerant);
1161            let mut bytes = Vec::new();
1162            reader.read_to_end(&mut bytes)
1163                .expect(&format!("{}", cert.base));
1164
1165            certd
1166                .insert_data(&bytes, false, certd_merge)
1167                .with_context(|| {
1168                    format!("{} ({})", cert.base, cert.fingerprint)
1169                })
1170                .expect("can insert");
1171        }
1172        drop (certd);
1173
1174        let certd = store::CertD::open(&path).expect("exists");
1175        certd.prefetch_all();
1176        test_backend(&certd);
1177
1178        Ok(())
1179    }
1180
1181    #[test]
1182    fn certs_with_prefetch() -> Result<()> {
1183        use std::io::Read;
1184
1185        let mut bytes = Vec::new();
1186        for cert in keyring::certs.iter() {
1187            let binary = cert.bytes();
1188            let mut reader = openpgp::armor::Reader::from_bytes(
1189                &binary,
1190                openpgp::armor::ReaderMode::VeryTolerant);
1191            reader.read_to_end(&mut bytes)
1192                .expect(&format!("{}", cert.base));
1193        }
1194
1195        let backend = store::Certs::from_bytes(&bytes)
1196            .expect("valid");
1197        backend.prefetch_all();
1198        test_backend(&backend);
1199
1200        Ok(())
1201    }
1202
1203    #[test]
1204    fn keyrings() -> Result<()> {
1205        let mut cert_store = CertStore::empty();
1206
1207        let mut base = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
1208        base.push("tests");
1209
1210        cert_store.add_keyrings(
1211            keyring::certs.iter().map(|c| {
1212                PathBuf::from(&base).join(c.filename)
1213            }))?;
1214
1215        test_backend(&cert_store);
1216
1217        Ok(())
1218    }
1219
1220    #[test]
1221    fn certs_multithreaded() -> Result<()> {
1222        use std::io::Read;
1223
1224        let mut bytes = Vec::new();
1225        for cert in keyring::certs.iter() {
1226            let binary = cert.bytes();
1227            let mut reader = openpgp::armor::Reader::from_bytes(
1228                &binary,
1229                openpgp::armor::ReaderMode::VeryTolerant);
1230            reader.read_to_end(&mut bytes)
1231                .expect(&format!("{}", cert.base));
1232        }
1233
1234        let backend = store::Certs::from_bytes(&bytes)
1235            .expect("valid");
1236
1237        std::thread::scope(|s| {
1238            let threads = (0..4usize)
1239                .map(|_| {
1240                    s.spawn(|| {
1241                        // Really make sure all threads start by sleeping
1242                        // for 10ms.
1243                        std::thread::sleep(std::time::Duration::new(0, 10));
1244
1245                        test_backend(&backend);
1246                    })
1247                })
1248                .collect::<Vec<_>>();
1249
1250            threads.into_iter().for_each(|h| {
1251                h.join().expect("joined");
1252            });
1253        });
1254
1255        Ok(())
1256    }
1257
1258    #[test]
1259    fn pep() -> Result<()> {
1260        use std::io::Read;
1261
1262        let mut bytes = Vec::new();
1263        for cert in keyring::certs.iter() {
1264            let binary = cert.bytes();
1265            let mut reader = openpgp::armor::Reader::from_bytes(
1266                &binary,
1267                openpgp::armor::ReaderMode::VeryTolerant);
1268            reader.read_to_end(&mut bytes)
1269                .expect(&format!("{}", cert.base));
1270        }
1271
1272        let backend = Pep::from_bytes(&bytes).expect("valid");
1273        backend.prefetch_all();
1274        test_backend(&backend);
1275
1276        Ok(())
1277    }
1278
1279    // Make sure that when we update a certificate, we are able to
1280    // find any new components and we are still able to find the old
1281    // components.
1282    fn test_store_update<'a, B>(backend: B) -> Result<()>
1283        where B: store::StoreUpdate<'a>
1284    {
1285        let p = &StandardPolicy::new();
1286
1287        let signing_cert =
1288            Cert::from_bytes(&keyring::halfling_signing.bytes())
1289                .expect("valid");
1290        let fpr = signing_cert.fingerprint();
1291
1292        // We expect a primary and two subkeys.
1293        assert_eq!(signing_cert.keys().count(), 3);
1294        let signing_vc = signing_cert.with_policy(p, None).expect("ok");
1295        let signing_fpr = signing_vc.keys().subkeys()
1296            .for_signing()
1297            .map(|ka| ka.key().fingerprint())
1298            .collect::<Vec<Fingerprint>>();
1299        assert_eq!(signing_fpr.len(), 1);
1300        let signing_fpr = KeyHandle::from(
1301            signing_fpr.into_iter().next().expect("have one"));
1302
1303        let auth_fpr = signing_vc.keys().subkeys()
1304            .for_authentication()
1305            .map(|ka| ka.key().fingerprint())
1306            .collect::<Vec<Fingerprint>>();
1307        assert_eq!(auth_fpr.len(), 1);
1308        let auth_fpr = KeyHandle::from(
1309            auth_fpr.into_iter().next().expect("have one"));
1310
1311        let encryption_cert =
1312            Cert::from_bytes(&keyring::halfling_encryption.bytes())
1313                .expect("valid");
1314        assert_eq!(fpr, encryption_cert.fingerprint());
1315
1316        // We expect a primary and two subkeys.
1317        assert_eq!(encryption_cert.keys().count(), 3);
1318        let encryption_vc = encryption_cert.with_policy(p, None).expect("ok");
1319        let encryption_fpr = encryption_vc.keys().subkeys()
1320            .for_transport_encryption()
1321            .map(|ka| ka.key().fingerprint())
1322            .collect::<Vec<Fingerprint>>();
1323        assert_eq!(encryption_fpr.len(), 1);
1324        let encryption_fpr = KeyHandle::from(
1325            encryption_fpr.into_iter().next().expect("have one"));
1326
1327        assert_ne!(signing_fpr, encryption_fpr);
1328
1329        let auth2_fpr = encryption_vc.keys().subkeys()
1330            .for_authentication()
1331            .map(|ka| ka.key().fingerprint())
1332            .collect::<Vec<Fingerprint>>();
1333        assert_eq!(auth2_fpr.len(), 1);
1334        let auth2_fpr = KeyHandle::from(
1335            auth2_fpr.into_iter().next().expect("have one"));
1336
1337        assert_eq!(auth_fpr, auth2_fpr);
1338
1339        let merged_cert = signing_cert.clone()
1340            .merge_public(encryption_cert.clone()).expect("ok");
1341
1342        let check = |backend: &B, have_enc: bool, cert: &Cert| {
1343            let r = backend.lookup_by_cert(&KeyHandle::from(fpr.clone())).unwrap();
1344            assert_eq!(r.len(), 1);
1345            assert_eq!(r[0].to_cert().expect("ok"), cert);
1346
1347            let r = backend.lookup_by_cert_or_subkey(&signing_fpr).unwrap();
1348            assert_eq!(r.len(), 1);
1349            assert_eq!(r[0].to_cert().expect("ok"), cert);
1350
1351            let r = backend.lookup_by_cert_or_subkey(&auth_fpr).unwrap();
1352            assert_eq!(r.len(), 1);
1353            assert_eq!(r[0].to_cert().expect("ok"), cert);
1354
1355            if have_enc {
1356                let r = backend.lookup_by_cert_or_subkey(&encryption_fpr).unwrap();
1357                assert_eq!(r.len(), 1);
1358                assert_eq!(r[0].to_cert().expect("ok"), cert);
1359            } else {
1360                assert!(backend.lookup_by_cert_or_subkey(&encryption_fpr).is_err());
1361            }
1362
1363            let r = backend.lookup_by_userid(
1364                &UserID::from("<regis@pup.com>")).unwrap();
1365            assert_eq!(r.len(), 1);
1366            assert_eq!(r[0].to_cert().expect("ok"), cert);
1367
1368            let r = backend.lookup_by_userid(
1369                &UserID::from("Halfling <signing@halfling.org>")).unwrap();
1370            assert_eq!(r.len(), 1);
1371            assert_eq!(r[0].to_cert().expect("ok"), cert);
1372
1373            if have_enc {
1374                let r = backend.lookup_by_userid(
1375                    &UserID::from("Halfling <encryption@halfling.org>"))
1376                    .unwrap();
1377                assert_eq!(r.len(), 1);
1378                assert_eq!(r[0].to_cert().expect("ok"), cert);
1379            } else {
1380                assert!(backend.lookup_by_cert_or_subkey(&encryption_fpr).is_err());
1381            }
1382        };
1383
1384        // Insert the signing certificate.
1385        backend.update(Arc::new(LazyCert::from(signing_cert.clone())))
1386            .expect("ok");
1387        check(&backend, false, &signing_cert);
1388
1389        backend.update(Arc::new(LazyCert::from(encryption_cert.clone())))
1390            .expect("ok");
1391        check(&backend, true, &merged_cert);
1392
1393        backend.update(Arc::new(LazyCert::from(signing_cert.clone())))
1394            .expect("ok");
1395        check(&backend, true, &merged_cert);
1396
1397        Ok(())
1398    }
1399
1400    // Test StoreUpdate::update for CertStore.
1401    #[test]
1402    fn test_store_update_cert_store() -> Result<()> {
1403        let path = tempfile::tempdir()?;
1404        let cert_store = CertStore::open(&path).expect("exists");
1405        test_store_update(cert_store)
1406    }
1407
1408    /// Test StoreUpdate::update for CertD.
1409    #[test]
1410    fn test_store_update_certd() -> Result<()> {
1411        let path = tempfile::tempdir()?;
1412        let certs = store::CertD::open(&path)?;
1413        test_store_update(&certs)?;
1414
1415        // We're the only user of the cert-d.  Therefore, we should be
1416        // able to keep the persistent index and the in-memory index
1417        // in sync with the cert-d without having to do any hard
1418        // reloads.
1419        assert_eq!(
1420            certs.load_stats.in_memory_loads(), 0);
1421        assert_eq!(
1422            certs.load_stats.persistent_index_scans(), 1);
1423        Ok(())
1424    }
1425
1426    // Test StoreUpdate::update for Certs.
1427    #[test]
1428    fn test_store_update_certs() -> Result<()> {
1429        let certs = Certs::empty();
1430        test_store_update(certs)
1431    }
1432
1433    // Test StoreUpdate::update for Pep.
1434    #[test]
1435    fn test_store_update_pep() -> Result<()> {
1436        let certs = Pep::empty()?;
1437        test_store_update(certs)
1438    }
1439
1440    #[test]
1441    fn test_store_multithreaded_update_cert_store() -> Result<()> {
1442        let path = tempfile::tempdir()?;
1443        let backend = CertStore::open(&path)?;
1444        test_store_multithreaded_update(backend)
1445    }
1446
1447    #[test]
1448    fn test_store_multithreaded_update_certd() -> Result<()> {
1449        let path = tempfile::tempdir()?;
1450        let backend = store::CertD::open(&path)?;
1451        test_store_multithreaded_update(backend)
1452    }
1453
1454    #[test]
1455    fn test_store_multithreaded_update_certs() -> Result<()> {
1456        let backend = store::Certs::empty();
1457        test_store_multithreaded_update(backend)
1458    }
1459
1460    #[test]
1461    fn test_store_multithreaded_update_pep() -> Result<()> {
1462        let backend = Pep::empty()?;
1463        test_store_multithreaded_update(backend)
1464    }
1465
1466    fn test_store_multithreaded_update<'a, B>(backend: B) -> Result<()>
1467        where B: store::StoreUpdate<'a> + Sync
1468    {
1469        let mut certs = Vec::new();
1470        for cert in keyring::certs.iter() {
1471            let cert = Cert::from_bytes(&cert.bytes()).expect("valid");
1472            certs.push(cert);
1473        }
1474
1475        let mut fprs: Vec<Fingerprint>
1476            = certs.iter().map(|cert| cert.fingerprint()).collect();
1477        fprs.sort();
1478        fprs.dedup();
1479
1480        std::thread::scope(|s| {
1481            let backend = &backend;
1482            let threads = certs.into_iter()
1483                .map(|cert| {
1484                    s.spawn(move || {
1485                        // Really make sure all threads start by sleeping
1486                        // for 10ms.
1487                        std::thread::sleep(std::time::Duration::new(0, 10));
1488
1489                        let kh = cert.key_handle();
1490                        backend.update(Arc::new(LazyCert::from(cert)))
1491                            .expect("ok");
1492                        assert!(backend.lookup_by_cert(&kh).is_ok());
1493                        assert!(backend.lookup_by_cert_or_subkey(&kh).is_ok());
1494                    })
1495                })
1496                .collect::<Vec<_>>();
1497
1498            threads.into_iter().for_each(|h| {
1499                h.join().expect("joined");
1500            });
1501        });
1502
1503        assert_eq!(backend.certs().count(), fprs.len());
1504
1505        Ok(())
1506    }
1507
1508}
1509