From 04f816be316fe6317109070f1e7517723c0db267 Mon Sep 17 00:00:00 2001 From: link2xt Date: Mon, 15 Mar 2021 07:52:32 +0300 Subject: [PATCH] qr: return QrFprMismatch on fingerprint mismatch Previously QrFprWithoutAddr was returned incorrectly. Also fix spelling error ("Missmatch"). --- src/lot.rs | 2 +- src/qr.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/lot.rs b/src/lot.rs index 7868eea6c..e209bbd80 100644 --- a/src/lot.rs +++ b/src/lot.rs @@ -87,7 +87,7 @@ pub enum LotState { QrFprOk = 210, /// id=contact - QrFprMissmatch = 220, + QrFprMismatch = 220, /// test1=formatted fingerprint QrFprWithoutAddr = 230, diff --git a/src/qr.rs b/src/qr.rs index 4a69ccc7f..677e00214 100644 --- a/src/qr.rs +++ b/src/qr.rs @@ -72,6 +72,7 @@ pub async fn check_qr(context: &Context, qr: impl AsRef) -> Lot { /// scheme: `OPENPGP4FPR:FINGERPRINT#a=ADDR&n=NAME&i=INVITENUMBER&s=AUTH` /// or: `OPENPGP4FPR:FINGERPRINT#a=ADDR&g=GROUPNAME&x=GROUPID&i=INVITENUMBER&s=AUTH` +/// or: `OPENPGP4FPR:FINGERPRINT#a=ADDR` #[allow(clippy::indexing_slicing)] async fn decode_openpgp(context: &Context, qr: &str) -> Lot { let payload = &qr[OPENPGP4FPR_SCHEME.len()..]; @@ -169,6 +170,14 @@ async fn decode_openpgp(context: &Context, qr: &str) -> Lot { .unwrap_or_default(); chat::add_info_msg(context, id, format!("{} verified.", peerstate.addr)).await; + } else if let Some(addr) = addr { + lot.state = LotState::QrFprMismatch; + lot.id = match Contact::lookup_id_by_addr(context, &addr, Origin::Unknown).await { + Ok(contact_id) => contact_id.unwrap_or_default(), + Err(err) => { + return format_err!("Error looking up contact {:?}: {}", addr, err).into() + } + }; } else { lot.state = LotState::QrFprWithoutAddr; lot.text1 = Some(fingerprint.to_string()); @@ -436,7 +445,10 @@ fn normalize_address(addr: &str) -> Result { mod tests { use super::*; - use crate::test_utils::TestContext; + use crate::aheader::EncryptPreference; + use crate::key::DcKey; + use crate::peerstate::ToSave; + use crate::test_utils::{alice_keypair, TestContext}; #[async_std::test] async fn test_decode_http() { @@ -625,6 +637,59 @@ mod tests { assert_eq!(contact.get_name(), ""); } + #[async_std::test] + async fn test_decode_openpgp_fingerprint() { + let ctx = TestContext::new().await; + + let contact_id = Contact::create(&ctx, "Alice", "alice@example.com") + .await + .expect("failed to create contact"); + let pub_key = alice_keypair().public; + let peerstate = Peerstate { + addr: "alice@example.com".to_string(), + last_seen: 1, + last_seen_autocrypt: 1, + prefer_encrypt: EncryptPreference::Mutual, + public_key: Some(pub_key.clone()), + public_key_fingerprint: Some(pub_key.fingerprint()), + gossip_key: None, + gossip_timestamp: 0, + gossip_key_fingerprint: None, + verified_key: None, + verified_key_fingerprint: None, + to_save: Some(ToSave::All), + fingerprint_changed: false, + }; + assert!( + peerstate.save_to_db(&ctx.ctx.sql, true).await.is_ok(), + "failed to save peerstate" + ); + + let res = check_qr( + &ctx.ctx, + "OPENPGP4FPR:1234567890123456789012345678901234567890#a=alice@example.com", + ) + .await; + assert_eq!(res.get_state(), LotState::QrFprMismatch); + assert_eq!(res.get_id(), contact_id); + + let res = check_qr( + &ctx.ctx, + format!("OPENPGP4FPR:{}#a=alice@example.com", pub_key.fingerprint()), + ) + .await; + assert_eq!(res.get_state(), LotState::QrFprOk); + assert_eq!(res.get_id(), contact_id); + + let res = check_qr( + &ctx.ctx, + "OPENPGP4FPR:1234567890123456789012345678901234567890#a=bob@example.org", + ) + .await; + assert_eq!(res.get_state(), LotState::QrFprMismatch); + assert_eq!(res.get_id(), 0); + } + #[async_std::test] async fn test_decode_openpgp_without_addr() { let ctx = TestContext::new().await;