From 3d8bad0e9d9a6c640159ff666b1d99cc0e9c0c36 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Tue, 26 Jan 2021 14:57:18 +0100 Subject: autocrypt: Include at least one user id in cleaned certs. --- autocrypt/src/lib.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/autocrypt/src/lib.rs b/autocrypt/src/lib.rs index e14511f9..36af44c3 100644 --- a/autocrypt/src/lib.rs +++ b/autocrypt/src/lib.rs @@ -133,12 +133,14 @@ impl AutocryptHeader { } // The UserIDs matching ADDR. + let mut found_one = false; for uidb in cert.userids().with_policy(policy, None) { // XXX: Fix match once we have the rfc2822-name-addr. if let Ok(Some(a)) = uidb.userid().email() { if &a == addr { acc.push(uidb.userid().clone().into()); acc.push(uidb.binding_signature().clone().into()); + found_one = true; } else { // Address is not matching. continue; @@ -149,6 +151,16 @@ impl AutocryptHeader { } } + // User ids are only decorative in Autocrypt. By convention, + // the cert should include a user id matching the sender's + // address, but we should include at least one user id. + if ! found_one { + if let Ok(uidb) = cert.with_policy(policy, None)?.primary_userid() { + acc.push(uidb.userid().clone().into()); + acc.push(uidb.binding_signature().clone().into()); + } + } + let cleaned_cert = Cert::try_from(acc)?; Ok(AutocryptHeader { @@ -1062,4 +1074,39 @@ mod test { assert_eq!(cert.userids().next().unwrap().userid().value(), &b"Testy McTestface "[..]); } + + #[test] + fn autocrypt_header_new_address_mismatch() -> Result<()> { + let p = &P::new(); + + let cert = + Cert::from_bytes(&include_bytes!("../tests/data/testy.pgp")[..])?; + let header = AutocryptHeader::new_sender(p, &cert, + "anna-lena@example.org", + "mutual")?; + let mut buf = Vec::new(); + write!(&mut buf, "Autocrypt: ")?; + header.serialize(&mut buf)?; + + let ac = AutocryptHeaders::from_bytes(&buf)?; + + // We expect exactly one Autocrypt header. + assert_eq!(ac.headers.len(), 1); + + assert_eq!(ac.headers[0].get("addr").unwrap().value, + "anna-lena@example.org"); + + assert_eq!(ac.headers[0].get("prefer-encrypt").unwrap().value, + "mutual"); + + let cert = ac.headers[0].key.as_ref() + .expect("Failed to parse key material."); + assert_eq!(&cert.fingerprint().to_string(), + "3E88 77C8 7727 4692 9751 89F5 D03F 6F86 5226 FE8B"); + assert_eq!(cert.userids().len(), 1); + assert_eq!(cert.keys().subkeys().count(), 1); + assert_eq!(cert.userids().next().unwrap().userid().value(), + &b"Testy McTestface "[..]); + Ok(()) + } } -- cgit v1.2.3