2024-06-10 15:22:41 +02:00
use std ::ffi ::OsStr ;
use std ::path ::Path ;
2024-11-18 15:52:26 +01:00
use super ::common ::{ artifact , Sq , STANDARD_POLICY } ;
2024-06-10 15:22:41 +02:00
use sequoia_openpgp as openpgp ;
2024-08-20 15:06:49 +02:00
use openpgp ::{
Cert ,
Result ,
cert ::amalgamation ::ValidateAmalgamation ,
2024-11-18 15:52:26 +01:00
parse ::Parse ,
2024-08-20 15:06:49 +02:00
} ;
2024-06-10 15:22:41 +02:00
#[ test ]
2024-08-20 15:06:49 +02:00
fn update_files ( ) -> Result < ( ) > {
2024-06-10 15:22:41 +02:00
// See https://gitlab.com/sequoia-pgp/sequoia/-/issues/1111
let now = std ::time ::SystemTime ::now ( )
- std ::time ::Duration ::new ( 60 * 60 , 0 ) ;
let sq = Sq ::at ( now ) ;
let alice_userid = " <alice@example.org> " ;
let ( alice , alice_pgp , _alice_rev )
= sq . key_generate ( & [ ] , & [ " <alice@example.org> " ] ) ;
let ( _bob , bob_pgp , _bob_rev )
= sq . key_generate ( & [ ] , & [ " <bob@example.org> " ] ) ;
// Attest the certifications.
//
// public is first merged into private.
let attest = | sq : & Sq , public : & Path | {
let priv_file = sq . scratch_file (
& * format! ( " {} -priv " ,
public . file_name ( )
. unwrap_or ( OsStr ::new ( " " ) )
. to_str ( ) . unwrap_or ( " " ) ) ) ;
2024-11-16 09:20:01 +01:00
sq . keyring_merge (
2024-10-31 10:00:54 +01:00
& [ public , & alice_pgp ] [ .. ] , None ,
2024-06-10 15:22:41 +02:00
& * priv_file ) ;
2024-11-06 20:48:18 +01:00
let approval_file = sq . scratch_file (
& * format! ( " {} -approval " , public . display ( ) ) ) ;
2024-06-10 15:22:41 +02:00
2024-11-06 20:48:18 +01:00
let approval = sq . key_approvals_update (
& priv_file , & [ " --add-all " ] , & * approval_file ) ;
2024-06-10 15:22:41 +02:00
2024-11-06 20:48:18 +01:00
eprintln! ( " {} " , sq . inspect ( & approval_file ) ) ;
2024-06-10 15:22:41 +02:00
2024-11-06 20:48:18 +01:00
assert_eq! ( approval . bad_signatures ( ) . count ( ) , 0 ) ;
2024-06-10 15:22:41 +02:00
2024-11-06 20:48:18 +01:00
let approval_ua = approval . userids ( ) . next ( ) . unwrap ( ) ;
assert_eq! ( approval_ua . attestations ( ) . count ( ) , 1 ) ;
2024-06-10 15:22:41 +02:00
} ;
// Attest nothing.
attest ( & sq , & alice_pgp ) ;
// Have Bob certify Alice.
let alice2_pub_pgp = sq . scratch_file ( " alice2_pub " ) ;
2024-11-20 11:54:50 +01:00
let alice2 = sq . pki_vouch_add ( & [ ] ,
2024-10-17 17:35:14 +02:00
& bob_pgp ,
& alice_pgp ,
& [ alice_userid ] ,
& * alice2_pub_pgp ) ;
2024-06-10 15:22:41 +02:00
assert_eq! ( alice2 . fingerprint ( ) , alice . fingerprint ( ) ) ;
// Attest Bob's certification.
attest ( & sq , & alice2_pub_pgp ) ;
2024-06-10 17:04:46 +02:00
Ok ( ( ) )
}
2024-08-20 15:06:49 +02:00
const ALICE_USERID : & str = " <alice@example.org> " ;
const BOB_USERID : & str = " <bob@example.org> " ;
fn make_keys ( sq : & Sq ) -> Result < ( Cert , Cert ) > {
let ( alice , alice_pgp , _alice_rev )
= sq . key_generate ( & [ ] , & [ ALICE_USERID ] ) ;
let ( bob , bob_pgp , _bob_rev )
= sq . key_generate ( & [ ] , & [ BOB_USERID ] ) ;
sq . key_import ( alice_pgp ) ;
sq . key_import ( bob_pgp ) ;
Ok ( ( alice , bob ) )
}
2024-06-10 17:04:46 +02:00
#[ test ]
2024-08-20 15:06:49 +02:00
fn update_all ( ) -> Result < ( ) > {
2024-06-10 17:04:46 +02:00
// See https://gitlab.com/sequoia-pgp/sequoia/-/issues/1111
let now = std ::time ::SystemTime ::now ( )
- std ::time ::Duration ::new ( 60 * 60 , 0 ) ;
let sq = Sq ::at ( now ) ;
2024-08-20 15:06:49 +02:00
let ( alice , bob ) = make_keys ( & sq ) ? ;
2024-06-10 17:04:46 +02:00
2024-08-20 15:06:49 +02:00
// Attest the zero certifications.
2024-11-06 20:48:18 +01:00
let approval = sq . key_approvals_update (
2024-08-20 15:06:49 +02:00
alice . key_handle ( ) , & [ " --add-all " ] , None ) ;
2024-06-10 17:04:46 +02:00
2024-11-06 20:48:18 +01:00
assert_eq! ( approval . bad_signatures ( ) . count ( ) , 0 ) ;
let approval_ua = approval . userids ( ) . next ( ) . unwrap ( ) ;
assert_eq! ( approval_ua . attestations ( ) . count ( ) , 1 ) ;
assert_eq! ( approval_ua . with_policy ( STANDARD_POLICY , None ) . unwrap ( )
2024-08-20 15:06:49 +02:00
. attested_certifications ( ) . count ( ) , 0 ) ;
// Have Bob certify Alice.
2024-11-20 11:54:50 +01:00
let alice2 = sq . pki_vouch_add ( & [ ] ,
2024-10-17 17:35:14 +02:00
bob . key_handle ( ) ,
alice . key_handle ( ) ,
& [ ALICE_USERID ] ,
None ) ;
2024-08-20 15:06:49 +02:00
assert_eq! ( alice2 . fingerprint ( ) , alice . fingerprint ( ) ) ;
// Attest Bob's certification.
2024-11-06 20:48:18 +01:00
let approval = sq . key_approvals_update (
2024-08-20 15:06:49 +02:00
& alice . key_handle ( ) , & [ " --add-all " ] , None ) ;
2024-11-06 20:48:18 +01:00
assert_eq! ( approval . bad_signatures ( ) . count ( ) , 0 ) ;
let approval_ua = approval . userids ( ) . next ( ) . unwrap ( ) ;
assert_eq! ( approval_ua . attestations ( ) . count ( ) , 2 ) ;
assert_eq! ( approval_ua . with_policy ( STANDARD_POLICY , None ) . unwrap ( )
2024-08-20 15:06:49 +02:00
. attested_certifications ( ) . count ( ) , 1 ) ;
// Drop the approval of Bob's certification.
2024-11-06 20:48:18 +01:00
let approval = sq . key_approvals_update (
2024-08-20 15:06:49 +02:00
& alice . key_handle ( ) , & [ " --remove-all " ] , None ) ;
2024-11-06 20:48:18 +01:00
assert_eq! ( approval . bad_signatures ( ) . count ( ) , 0 ) ;
let approval_ua = approval . userids ( ) . next ( ) . unwrap ( ) ;
assert_eq! ( approval_ua . attestations ( ) . count ( ) , 3 ) ;
assert_eq! ( approval_ua . with_policy ( STANDARD_POLICY , None ) . unwrap ( )
2024-08-20 15:06:49 +02:00
. attested_certifications ( ) . count ( ) , 0 ) ;
Ok ( ( ) )
}
#[ test ]
fn update_by ( ) -> Result < ( ) > {
// See https://gitlab.com/sequoia-pgp/sequoia/-/issues/1111
let now = std ::time ::SystemTime ::now ( )
- std ::time ::Duration ::new ( 60 * 60 , 0 ) ;
let sq = Sq ::at ( now ) ;
let ( alice , bob ) = make_keys ( & sq ) ? ;
let bob_fp = bob . fingerprint ( ) . to_string ( ) ;
2024-06-10 17:04:46 +02:00
// Attest the zero certifications.
2024-11-06 20:48:18 +01:00
let approval = sq . key_approvals_update (
2024-08-20 15:06:49 +02:00
alice . key_handle ( ) , & [ " --add-by " , & bob_fp ] , None ) ;
2024-06-10 17:04:46 +02:00
2024-11-06 20:48:18 +01:00
assert_eq! ( approval . bad_signatures ( ) . count ( ) , 0 ) ;
let approval_ua = approval . userids ( ) . next ( ) . unwrap ( ) ;
assert_eq! ( approval_ua . attestations ( ) . count ( ) , 1 ) ;
assert_eq! ( approval_ua . with_policy ( STANDARD_POLICY , None ) . unwrap ( )
2024-08-20 15:06:49 +02:00
. attested_certifications ( ) . count ( ) , 0 ) ;
2024-06-10 17:04:46 +02:00
// Have Bob certify Alice.
2024-11-20 11:54:50 +01:00
let alice2 = sq . pki_vouch_add ( & [ ] ,
2024-10-17 17:35:14 +02:00
bob . key_handle ( ) ,
alice . key_handle ( ) ,
& [ ALICE_USERID ] ,
None ) ;
2024-06-10 17:04:46 +02:00
assert_eq! ( alice2 . fingerprint ( ) , alice . fingerprint ( ) ) ;
// Attest Bob's certification.
2024-11-06 20:48:18 +01:00
let approval = sq . key_approvals_update (
2024-08-20 15:06:49 +02:00
& alice . key_handle ( ) , & [ " --add-by " , & bob_fp ] , None ) ;
2024-06-10 17:04:46 +02:00
2024-11-06 20:48:18 +01:00
assert_eq! ( approval . bad_signatures ( ) . count ( ) , 0 ) ;
let approval_ua = approval . userids ( ) . next ( ) . unwrap ( ) ;
assert_eq! ( approval_ua . attestations ( ) . count ( ) , 2 ) ;
assert_eq! ( approval_ua . with_policy ( STANDARD_POLICY , None ) . unwrap ( )
2024-08-20 15:06:49 +02:00
. attested_certifications ( ) . count ( ) , 1 ) ;
// Drop the approval of Bob's certification.
2024-11-06 20:48:18 +01:00
let approval = sq . key_approvals_update (
2024-08-20 15:06:49 +02:00
& alice . key_handle ( ) , & [ " --remove-by " , & bob_fp ] , None ) ;
2024-11-06 20:48:18 +01:00
assert_eq! ( approval . bad_signatures ( ) . count ( ) , 0 ) ;
let approval_ua = approval . userids ( ) . next ( ) . unwrap ( ) ;
assert_eq! ( approval_ua . attestations ( ) . count ( ) , 3 ) ;
assert_eq! ( approval_ua . with_policy ( STANDARD_POLICY , None ) . unwrap ( )
2024-08-20 15:06:49 +02:00
. attested_certifications ( ) . count ( ) , 0 ) ;
Ok ( ( ) )
}
#[ test ]
fn update_authenticated ( ) -> Result < ( ) > {
// See https://gitlab.com/sequoia-pgp/sequoia/-/issues/1111
let now = std ::time ::SystemTime ::now ( )
- std ::time ::Duration ::new ( 60 * 60 , 0 ) ;
let sq = Sq ::at ( now ) ;
let ( alice , bob ) = make_keys ( & sq ) ? ;
let bob_fp = bob . fingerprint ( ) . to_string ( ) ;
// Have Bob certify Alice.
2024-11-20 11:54:50 +01:00
let alice2 = sq . pki_vouch_add ( & [ ] ,
2024-10-17 17:35:14 +02:00
bob . key_handle ( ) ,
alice . key_handle ( ) ,
& [ ALICE_USERID ] ,
None ) ;
2024-08-20 15:06:49 +02:00
assert_eq! ( alice2 . fingerprint ( ) , alice . fingerprint ( ) ) ;
// Attest the zero certifications.
2024-11-06 20:48:18 +01:00
let approval = sq . key_approvals_update (
2024-08-20 15:06:49 +02:00
alice . key_handle ( ) , & [ " --add-authenticated " ] , None ) ;
2024-06-10 17:04:46 +02:00
2024-11-06 20:48:18 +01:00
assert_eq! ( approval . bad_signatures ( ) . count ( ) , 0 ) ;
let approval_ua = approval . userids ( ) . next ( ) . unwrap ( ) ;
assert_eq! ( approval_ua . attestations ( ) . count ( ) , 1 ) ;
assert_eq! ( approval_ua . with_policy ( STANDARD_POLICY , None ) . unwrap ( )
2024-08-20 15:06:49 +02:00
. attested_certifications ( ) . count ( ) , 0 ) ;
// Link Bob's cert to his user ID.
let mut link = sq . command ( ) ;
2024-10-15 16:00:46 +02:00
link . args ( & [ " pki " , " link " , " add " ,
" --cert " , & bob_fp ,
" --userid " , BOB_USERID ] ) ;
2024-08-20 15:06:49 +02:00
sq . run ( link , true ) ;
// Attest Bob's certification.
2024-11-06 20:48:18 +01:00
let approval = sq . key_approvals_update (
2024-08-20 15:06:49 +02:00
& alice . key_handle ( ) , & [ " --add-authenticated " ] , None ) ;
2024-11-06 20:48:18 +01:00
assert_eq! ( approval . bad_signatures ( ) . count ( ) , 0 ) ;
let approval_ua = approval . userids ( ) . next ( ) . unwrap ( ) ;
assert_eq! ( approval_ua . attestations ( ) . count ( ) , 2 ) ;
assert_eq! ( approval_ua . with_policy ( STANDARD_POLICY , None ) . unwrap ( )
2024-08-20 15:06:49 +02:00
. attested_certifications ( ) . count ( ) , 1 ) ;
2024-06-10 17:04:46 +02:00
2024-06-10 15:22:41 +02:00
Ok ( ( ) )
}
2024-11-18 15:52:26 +01:00
#[ test ]
fn ignore_shadow_ca ( ) {
// Check that update ignores certificates made by shadow CAs.
let now = std ::time ::SystemTime ::now ( )
- std ::time ::Duration ::new ( 60 * 60 , 0 ) ;
let sq = Sq ::at ( now ) ;
let ( alice , bob ) = make_keys ( & sq ) . unwrap ( ) ;
// Have Bob certify Alice.
2024-11-20 11:54:50 +01:00
let alice2 = sq . pki_vouch_add ( & [ ] ,
2024-11-18 15:52:26 +01:00
bob . key_handle ( ) ,
alice . key_handle ( ) ,
& [ ALICE_USERID ] ,
None ) ;
assert_eq! ( alice2 . fingerprint ( ) , alice . fingerprint ( ) ) ;
let shadow_ca = artifact ( " keys/_sequoia_ca_keys.openpgp.org.pgp " ) ;
sq . key_import ( & shadow_ca ) ;
let shadow_ca = Cert ::from_file ( & shadow_ca ) . unwrap ( ) ;
// Have the shadow CA certify Alice.
2024-11-20 11:54:50 +01:00
let alice2 = sq . pki_vouch_add ( & [ ] ,
2024-11-18 15:52:26 +01:00
& shadow_ca . key_handle ( ) ,
alice . key_handle ( ) ,
& [ ALICE_USERID ] ,
None ) ;
assert_eq! ( alice2 . fingerprint ( ) , alice . fingerprint ( ) ) ;
// Attest to all certifications. This should ignore the shadow
// CA's certification.
let approval = sq . key_approvals_update (
& alice . key_handle ( ) , & [ " --add-all " ] , None ) ;
assert_eq! ( approval . bad_signatures ( ) . count ( ) , 0 ) ;
let approval_ua = approval . userids ( ) . next ( ) . unwrap ( ) ;
// We have an attestation key signature.
assert_eq! ( approval_ua . attestations ( ) . count ( ) , 1 ) ;
// With one attestation (not two!).
assert_eq! ( approval_ua . with_policy ( STANDARD_POLICY , None ) . unwrap ( )
. attested_certifications ( ) . count ( ) , 1 ) ;
}
#[ test ]
fn ignore_unexportable_certifications ( ) {
// Check that update ignores certificates that are not exportable.
let now = std ::time ::SystemTime ::now ( )
- std ::time ::Duration ::new ( 60 * 60 , 0 ) ;
let sq = Sq ::at ( now ) ;
let ( alice , bob ) = make_keys ( & sq ) . unwrap ( ) ;
// Have Bob create a non-exportable certification for Alice.
2024-11-20 11:54:50 +01:00
let alice2 = sq . pki_vouch_add ( & [ " --local " ] ,
2024-11-18 15:52:26 +01:00
bob . key_handle ( ) ,
alice . key_handle ( ) ,
& [ ALICE_USERID ] ,
None ) ;
assert_eq! ( alice2 . fingerprint ( ) , alice . fingerprint ( ) ) ;
// Attest to all certifications. This should ignore
// non-exportable certifications.
let approval = sq . key_approvals_update (
& alice . key_handle ( ) , & [ " --add-all " ] , None ) ;
assert_eq! ( approval . bad_signatures ( ) . count ( ) , 0 ) ;
let approval_ua = approval . userids ( ) . next ( ) . unwrap ( ) ;
for attestation in approval_ua . attestations ( ) {
eprintln! ( " - {:?} " , attestation ) ;
}
// We have an attestation key signature.
assert_eq! ( approval_ua . attestations ( ) . count ( ) , 1 ) ;
// With zero attestations.
assert_eq! ( approval_ua . with_policy ( STANDARD_POLICY , None ) . unwrap ( )
. attested_certifications ( ) . count ( ) , 0 ) ;
}