1use std::mem;
4
5use anyhow::{Context as _, Error, Result};
6use deltachat_contact_tools::{addr_cmp, ContactAddress};
7use num_traits::FromPrimitive;
8
9use crate::aheader::{Aheader, EncryptPreference};
10use crate::chat::{self, Chat};
11use crate::chatlist::Chatlist;
12use crate::config::Config;
13use crate::constants::Chattype;
14use crate::contact::{Contact, Origin};
15use crate::context::Context;
16use crate::events::EventType;
17use crate::key::{DcKey, Fingerprint, SignedPublicKey};
18use crate::message::Message;
19use crate::mimeparser::SystemMessage;
20use crate::sql::Sql;
21use crate::{chatlist_events, stock_str};
22
23#[derive(Debug)]
25pub enum PeerstateKeyType {
26 GossipKey,
28
29 PublicKey,
31}
32
33#[derive(Debug, PartialEq, Eq, Clone)]
35pub struct Peerstate {
36 pub addr: String,
38
39 pub last_seen: i64,
44
45 pub last_seen_autocrypt: i64,
47
48 pub prefer_encrypt: EncryptPreference,
50
51 pub public_key: Option<SignedPublicKey>,
53
54 pub public_key_fingerprint: Option<Fingerprint>,
56
57 pub gossip_key: Option<SignedPublicKey>,
59
60 pub gossip_timestamp: i64,
65
66 pub gossip_key_fingerprint: Option<Fingerprint>,
68
69 pub verified_key: Option<SignedPublicKey>,
72
73 pub verified_key_fingerprint: Option<Fingerprint>,
75
76 pub verifier: Option<String>,
78
79 pub secondary_verified_key: Option<SignedPublicKey>,
83
84 pub secondary_verified_key_fingerprint: Option<Fingerprint>,
86
87 pub secondary_verifier: Option<String>,
89
90 pub backward_verified_key_id: Option<i64>,
93
94 pub fingerprint_changed: bool,
98}
99
100impl Peerstate {
101 pub fn from_header(header: &Aheader, message_time: i64) -> Self {
103 Self::from_public_key(
104 &header.addr,
105 message_time,
106 header.prefer_encrypt,
107 &header.public_key,
108 )
109 }
110
111 pub fn from_public_key(
113 addr: &str,
114 last_seen: i64,
115 prefer_encrypt: EncryptPreference,
116 public_key: &SignedPublicKey,
117 ) -> Self {
118 Peerstate {
119 addr: addr.to_string(),
120 last_seen,
121 last_seen_autocrypt: last_seen,
122 prefer_encrypt,
123 public_key: Some(public_key.clone()),
124 public_key_fingerprint: Some(public_key.dc_fingerprint()),
125 gossip_key: None,
126 gossip_key_fingerprint: None,
127 gossip_timestamp: 0,
128 verified_key: None,
129 verified_key_fingerprint: None,
130 verifier: None,
131 secondary_verified_key: None,
132 secondary_verified_key_fingerprint: None,
133 secondary_verifier: None,
134 backward_verified_key_id: None,
135 fingerprint_changed: false,
136 }
137 }
138
139 pub fn from_gossip(gossip_header: &Aheader, message_time: i64) -> Self {
141 Peerstate {
142 addr: gossip_header.addr.clone(),
143 last_seen: 0,
144 last_seen_autocrypt: 0,
145
146 prefer_encrypt: gossip_header.prefer_encrypt,
153 public_key: None,
154 public_key_fingerprint: None,
155 gossip_key: Some(gossip_header.public_key.clone()),
156 gossip_key_fingerprint: Some(gossip_header.public_key.dc_fingerprint()),
157 gossip_timestamp: message_time,
158 verified_key: None,
159 verified_key_fingerprint: None,
160 verifier: None,
161 secondary_verified_key: None,
162 secondary_verified_key_fingerprint: None,
163 secondary_verifier: None,
164 backward_verified_key_id: None,
165 fingerprint_changed: false,
166 }
167 }
168
169 pub async fn from_addr(context: &Context, addr: &str) -> Result<Option<Peerstate>> {
171 if context.is_self_addr(addr).await? {
172 return Ok(None);
173 }
174 let query = "SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, \
175 gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, \
176 verified_key, verified_key_fingerprint, \
177 verifier, \
178 secondary_verified_key, secondary_verified_key_fingerprint, \
179 secondary_verifier, \
180 backward_verified_key_id \
181 FROM acpeerstates \
182 WHERE addr=? COLLATE NOCASE LIMIT 1;";
183 Self::from_stmt(context, query, (addr,)).await
184 }
185
186 pub async fn from_fingerprint(
188 context: &Context,
189 fingerprint: &Fingerprint,
190 ) -> Result<Option<Peerstate>> {
191 let query = "SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, \
193 gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, \
194 verified_key, verified_key_fingerprint, \
195 verifier, \
196 secondary_verified_key, secondary_verified_key_fingerprint, \
197 secondary_verifier, \
198 backward_verified_key_id \
199 FROM acpeerstates \
200 WHERE public_key_fingerprint=? \
201 OR gossip_key_fingerprint=? \
202 ORDER BY public_key_fingerprint=? DESC LIMIT 1;";
203 let fp = fingerprint.hex();
204 Self::from_stmt(context, query, (&fp, &fp, &fp)).await
205 }
206
207 pub async fn from_verified_fingerprint_or_addr(
212 context: &Context,
213 fingerprint: &Fingerprint,
214 addr: &str,
215 ) -> Result<Option<Peerstate>> {
216 if context.is_self_addr(addr).await? {
217 return Ok(None);
218 }
219 let query = "SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, \
220 gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, \
221 verified_key, verified_key_fingerprint, \
222 verifier, \
223 secondary_verified_key, secondary_verified_key_fingerprint, \
224 secondary_verifier, \
225 backward_verified_key_id \
226 FROM acpeerstates \
227 WHERE verified_key_fingerprint=? \
228 OR addr=? COLLATE NOCASE \
229 ORDER BY verified_key_fingerprint=? DESC, addr=? COLLATE NOCASE DESC, \
230 last_seen DESC LIMIT 1;";
231 let fp = fingerprint.hex();
232 Self::from_stmt(context, query, (&fp, addr, &fp, addr)).await
233 }
234
235 async fn from_stmt(
236 context: &Context,
237 query: &str,
238 params: impl rusqlite::Params + Send,
239 ) -> Result<Option<Peerstate>> {
240 let peerstate = context
241 .sql
242 .query_row_optional(query, params, |row| {
243 let res = Peerstate {
244 addr: row.get("addr")?,
245 last_seen: row.get("last_seen")?,
246 last_seen_autocrypt: row.get("last_seen_autocrypt")?,
247 prefer_encrypt: EncryptPreference::from_i32(row.get("prefer_encrypted")?)
248 .unwrap_or_default(),
249 public_key: row
250 .get("public_key")
251 .ok()
252 .and_then(|blob: Vec<u8>| SignedPublicKey::from_slice(&blob).ok()),
253 public_key_fingerprint: row
254 .get::<_, Option<String>>("public_key_fingerprint")?
255 .map(|s| s.parse::<Fingerprint>())
256 .transpose()
257 .unwrap_or_default(),
258 gossip_key: row
259 .get("gossip_key")
260 .ok()
261 .and_then(|blob: Vec<u8>| SignedPublicKey::from_slice(&blob).ok()),
262 gossip_key_fingerprint: row
263 .get::<_, Option<String>>("gossip_key_fingerprint")?
264 .map(|s| s.parse::<Fingerprint>())
265 .transpose()
266 .unwrap_or_default(),
267 gossip_timestamp: row.get("gossip_timestamp")?,
268 verified_key: row
269 .get("verified_key")
270 .ok()
271 .and_then(|blob: Vec<u8>| SignedPublicKey::from_slice(&blob).ok()),
272 verified_key_fingerprint: row
273 .get::<_, Option<String>>("verified_key_fingerprint")?
274 .map(|s| s.parse::<Fingerprint>())
275 .transpose()
276 .unwrap_or_default(),
277 verifier: {
278 let verifier: Option<String> = row.get("verifier")?;
279 verifier.filter(|s| !s.is_empty())
280 },
281 secondary_verified_key: row
282 .get("secondary_verified_key")
283 .ok()
284 .and_then(|blob: Vec<u8>| SignedPublicKey::from_slice(&blob).ok()),
285 secondary_verified_key_fingerprint: row
286 .get::<_, Option<String>>("secondary_verified_key_fingerprint")?
287 .map(|s| s.parse::<Fingerprint>())
288 .transpose()
289 .unwrap_or_default(),
290 secondary_verifier: {
291 let secondary_verifier: Option<String> = row.get("secondary_verifier")?;
292 secondary_verifier.filter(|s| !s.is_empty())
293 },
294 backward_verified_key_id: row.get("backward_verified_key_id")?,
295 fingerprint_changed: false,
296 };
297
298 Ok(res)
299 })
300 .await?;
301 Ok(peerstate)
302 }
303
304 pub fn recalc_fingerprint(&mut self) {
309 if let Some(ref public_key) = self.public_key {
310 let old_public_fingerprint = self.public_key_fingerprint.take();
311 self.public_key_fingerprint = Some(public_key.dc_fingerprint());
312
313 if old_public_fingerprint.is_some()
314 && old_public_fingerprint != self.public_key_fingerprint
315 {
316 self.fingerprint_changed = true;
317 }
318 }
319
320 if let Some(ref gossip_key) = self.gossip_key {
321 let old_gossip_fingerprint = self.gossip_key_fingerprint.take();
322 self.gossip_key_fingerprint = Some(gossip_key.dc_fingerprint());
323
324 if old_gossip_fingerprint.is_none()
325 || self.gossip_key_fingerprint.is_none()
326 || old_gossip_fingerprint != self.gossip_key_fingerprint
327 {
328 if old_gossip_fingerprint.is_some() && self.public_key_fingerprint.is_none() {
331 self.fingerprint_changed = true;
332 }
333 }
334 }
335 }
336
337 pub fn degrade_encryption(&mut self, message_time: i64) {
341 self.prefer_encrypt = EncryptPreference::Reset;
342 self.last_seen = message_time;
343 }
344
345 pub fn apply_header(&mut self, context: &Context, header: &Aheader, message_time: i64) {
347 if !addr_cmp(&self.addr, &header.addr) {
348 return;
349 }
350
351 if message_time >= self.last_seen {
352 self.last_seen = message_time;
353 self.last_seen_autocrypt = message_time;
354 if (header.prefer_encrypt == EncryptPreference::Mutual
355 || header.prefer_encrypt == EncryptPreference::NoPreference)
356 && header.prefer_encrypt != self.prefer_encrypt
357 {
358 self.prefer_encrypt = header.prefer_encrypt;
359 }
360
361 if self.public_key.as_ref() != Some(&header.public_key) {
362 self.public_key = Some(header.public_key.clone());
363 self.recalc_fingerprint();
364 }
365 } else {
366 warn!(
367 context,
368 "Ignoring outdated Autocrypt header because message_time={} < last_seen={}.",
369 message_time,
370 self.last_seen
371 );
372 }
373 }
374
375 pub fn apply_gossip(&mut self, gossip_header: &Aheader, message_time: i64) {
377 if self.addr.to_lowercase() != gossip_header.addr.to_lowercase() {
378 return;
379 }
380
381 if message_time >= self.gossip_timestamp {
382 self.gossip_timestamp = message_time;
383 if self.gossip_key.as_ref() != Some(&gossip_header.public_key) {
384 self.gossip_key = Some(gossip_header.public_key.clone());
385 self.recalc_fingerprint();
386 }
387
388 if self.last_seen_autocrypt == 0
400 && self.prefer_encrypt == EncryptPreference::NoPreference
401 && gossip_header.prefer_encrypt == EncryptPreference::Mutual
402 {
403 self.prefer_encrypt = EncryptPreference::Mutual;
404 }
405 };
406 }
407
408 pub fn take_key(mut self, verified: bool) -> Option<SignedPublicKey> {
412 if verified {
413 self.verified_key.take()
414 } else {
415 self.public_key.take().or_else(|| self.gossip_key.take())
416 }
417 }
418
419 pub fn peek_key(&self, verified: bool) -> Option<&SignedPublicKey> {
429 if verified {
430 self.verified_key.as_ref()
431 } else {
432 self.public_key.as_ref().or(self.gossip_key.as_ref())
433 }
434 }
435
436 fn peek_key_fingerprint(&self, verified: bool) -> Option<&Fingerprint> {
440 if verified {
441 self.verified_key_fingerprint.as_ref()
442 } else {
443 self.public_key_fingerprint
444 .as_ref()
445 .or(self.gossip_key_fingerprint.as_ref())
446 }
447 }
448
449 pub(crate) fn is_using_verified_key(&self) -> bool {
455 let verified = self.peek_key_fingerprint(true);
456
457 verified.is_some() && verified == self.peek_key_fingerprint(false)
458 }
459
460 pub(crate) async fn is_backward_verified(&self, context: &Context) -> Result<bool> {
461 let Some(backward_verified_key_id) = self.backward_verified_key_id else {
462 return Ok(false);
463 };
464
465 let self_key_id = context.get_config_i64(Config::KeyId).await?;
466
467 let backward_verified = backward_verified_key_id == self_key_id;
468 Ok(backward_verified)
469 }
470
471 pub fn set_verified(
482 &mut self,
483 key: SignedPublicKey,
484 fingerprint: Fingerprint,
485 verifier: String,
486 ) -> Result<()> {
487 if key.dc_fingerprint() == fingerprint {
488 self.verified_key = Some(key);
489 self.verified_key_fingerprint = Some(fingerprint);
490 self.verifier = Some(verifier);
491 Ok(())
492 } else {
493 Err(Error::msg(format!(
494 "{fingerprint} is not peer's key fingerprint",
495 )))
496 }
497 }
498
499 pub fn set_secondary_verified_key(&mut self, gossip_key: SignedPublicKey, verifier: String) {
505 let fingerprint = gossip_key.dc_fingerprint();
506 if self.verified_key_fingerprint.as_ref() != Some(&fingerprint) {
507 self.secondary_verified_key = Some(gossip_key);
508 self.secondary_verified_key_fingerprint = Some(fingerprint);
509 self.secondary_verifier = Some(verifier);
510 }
511 }
512
513 pub async fn save_to_db(&self, sql: &Sql) -> Result<()> {
515 self.save_to_db_ex(sql, None).await
516 }
517
518 pub(crate) async fn save_to_db_ex(&self, sql: &Sql, old_addr: Option<&str>) -> Result<()> {
522 let trans_fn = |t: &mut rusqlite::Transaction| {
523 let verified_key_fingerprint =
524 self.verified_key_fingerprint.as_ref().map(|fp| fp.hex());
525 if let Some(old_addr) = old_addr {
526 t.execute(
538 "UPDATE acpeerstates
539 SET verified_key=NULL, verified_key_fingerprint='', verifier=''
540 WHERE addr=? AND verified_key_fingerprint=?",
541 (old_addr, &verified_key_fingerprint),
542 )?;
543 }
544 t.execute(
545 "INSERT INTO acpeerstates (
546 last_seen,
547 last_seen_autocrypt,
548 prefer_encrypted,
549 public_key,
550 gossip_timestamp,
551 gossip_key,
552 public_key_fingerprint,
553 gossip_key_fingerprint,
554 verified_key,
555 verified_key_fingerprint,
556 verifier,
557 secondary_verified_key,
558 secondary_verified_key_fingerprint,
559 secondary_verifier,
560 backward_verified_key_id,
561 addr)
562 VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
563 ON CONFLICT (addr)
564 DO UPDATE SET
565 last_seen = excluded.last_seen,
566 last_seen_autocrypt = excluded.last_seen_autocrypt,
567 prefer_encrypted = excluded.prefer_encrypted,
568 public_key = excluded.public_key,
569 gossip_timestamp = excluded.gossip_timestamp,
570 gossip_key = excluded.gossip_key,
571 public_key_fingerprint = excluded.public_key_fingerprint,
572 gossip_key_fingerprint = excluded.gossip_key_fingerprint,
573 verified_key = excluded.verified_key,
574 verified_key_fingerprint = excluded.verified_key_fingerprint,
575 verifier = excluded.verifier,
576 secondary_verified_key = excluded.secondary_verified_key,
577 secondary_verified_key_fingerprint = excluded.secondary_verified_key_fingerprint,
578 secondary_verifier = excluded.secondary_verifier,
579 backward_verified_key_id = excluded.backward_verified_key_id",
580 (
581 self.last_seen,
582 self.last_seen_autocrypt,
583 self.prefer_encrypt as i64,
584 self.public_key.as_ref().map(|k| k.to_bytes()),
585 self.gossip_timestamp,
586 self.gossip_key.as_ref().map(|k| k.to_bytes()),
587 self.public_key_fingerprint.as_ref().map(|fp| fp.hex()),
588 self.gossip_key_fingerprint.as_ref().map(|fp| fp.hex()),
589 self.verified_key.as_ref().map(|k| k.to_bytes()),
590 &verified_key_fingerprint,
591 self.verifier.as_deref().unwrap_or(""),
592 self.secondary_verified_key.as_ref().map(|k| k.to_bytes()),
593 self.secondary_verified_key_fingerprint
594 .as_ref()
595 .map(|fp| fp.hex()),
596 self.secondary_verifier.as_deref().unwrap_or(""),
597 self.backward_verified_key_id,
598 &self.addr,
599 ),
600 )?;
601 Ok(())
602 };
603 sql.transaction(trans_fn).await
604 }
605
606 pub fn get_verifier(&self) -> Option<&str> {
608 self.verifier.as_deref()
609 }
610
611 async fn handle_setup_change(
617 &self,
618 context: &Context,
619 timestamp: i64,
620 change: PeerstateChange,
621 ) -> Result<()> {
622 if context.is_self_addr(&self.addr).await? {
623 return Ok(());
625 }
626
627 let contact_id = context
628 .sql
629 .query_get_value(
630 "SELECT id FROM contacts WHERE addr=? COLLATE NOCASE;",
631 (&self.addr,),
632 )
633 .await?
634 .with_context(|| format!("contact with peerstate.addr {:?} not found", &self.addr))?;
635
636 let chats = Chatlist::try_load(context, 0, None, Some(contact_id)).await?;
637 let msg = match &change {
638 PeerstateChange::FingerprintChange => {
639 stock_str::contact_setup_changed(context, &self.addr).await
640 }
641 PeerstateChange::Aeap(new_addr) => {
642 let old_contact = Contact::get_by_id(context, contact_id).await?;
643 stock_str::aeap_addr_changed(
644 context,
645 old_contact.get_display_name(),
646 &self.addr,
647 new_addr,
648 )
649 .await
650 }
651 };
652 for (chat_id, msg_id) in chats.iter() {
653 let timestamp_sort = if let Some(msg_id) = msg_id {
654 let lastmsg = Message::load_from_db(context, *msg_id).await?;
655 lastmsg.timestamp_sort
656 } else {
657 chat_id.created_timestamp(context).await?
658 };
659
660 if let PeerstateChange::Aeap(new_addr) = &change {
661 let chat = Chat::load_from_db(context, *chat_id).await?;
662
663 if chat.typ == Chattype::Group && !chat.is_protected() {
664 continue;
667 }
668
669 if (chat.typ == Chattype::Group && chat.is_protected())
674 || chat.typ == Chattype::Broadcast
675 {
676 match ContactAddress::new(new_addr) {
677 Ok(new_addr) => {
678 let (new_contact_id, _) = Contact::add_or_lookup(
679 context,
680 "",
681 &new_addr,
682 Origin::IncomingUnknownFrom,
683 )
684 .await?;
685 context
686 .sql
687 .transaction(|transaction| {
688 transaction.execute(
689 "UPDATE chats_contacts
690 SET remove_timestamp=MAX(add_timestamp+1, ?)
691 WHERE chat_id=? AND contact_id=?",
692 (timestamp, chat_id, contact_id),
693 )?;
694 transaction.execute(
695 "INSERT INTO chats_contacts
696 (chat_id, contact_id, add_timestamp)
697 VALUES (?1, ?2, ?3)
698 ON CONFLICT (chat_id, contact_id)
699 DO UPDATE SET add_timestamp=MAX(remove_timestamp, ?3)",
700 (chat_id, new_contact_id, timestamp),
701 )?;
702 Ok(())
703 })
704 .await?;
705
706 context.emit_event(EventType::ChatModified(*chat_id));
707 }
708 Err(err) => {
709 warn!(
710 context,
711 "New address {:?} is not valid, not doing AEAP: {:#}.",
712 new_addr,
713 err
714 )
715 }
716 }
717 }
718 }
719
720 chat::add_info_msg_with_cmd(
721 context,
722 *chat_id,
723 &msg,
724 SystemMessage::Unknown,
725 timestamp_sort,
726 Some(timestamp),
727 None,
728 None,
729 None,
730 )
731 .await?;
732 }
733
734 chatlist_events::emit_chatlist_changed(context);
735 chatlist_events::emit_chatlist_items_changed_for_contact(context, contact_id);
737 Ok(())
738 }
739
740 pub(crate) async fn handle_fingerprint_change(
742 &self,
743 context: &Context,
744 timestamp: i64,
745 ) -> Result<()> {
746 if self.fingerprint_changed {
747 self.handle_setup_change(context, timestamp, PeerstateChange::FingerprintChange)
748 .await?;
749 }
750 Ok(())
751 }
752}
753
754pub(crate) async fn maybe_do_aeap_transition(
759 context: &Context,
760 mime_parser: &mut crate::mimeparser::MimeMessage,
761) -> Result<()> {
762 let Some(peerstate) = &mime_parser.peerstate else {
763 return Ok(());
764 };
765
766 if !addr_cmp(&peerstate.addr, &mime_parser.from.addr) {
769 if !mime_parser.has_chat_version() {
773 info!(
774 context,
775 "Not doing AEAP from {} to {} because the message is not a chat message.",
776 &peerstate.addr,
777 &mime_parser.from.addr
778 );
779 return Ok(());
780 }
781
782 if mime_parser.signatures.is_empty() {
785 info!(
786 context,
787 "Not doing AEAP from {} to {} because the message is not encrypted and signed.",
788 &peerstate.addr,
789 &mime_parser.from.addr
790 );
791 return Ok(());
792 }
793
794 if !mime_parser.from_is_signed {
799 info!(
800 context,
801 "Not doing AEAP from {} to {} because From: is not signed.",
802 &peerstate.addr,
803 &mime_parser.from.addr
804 );
805 return Ok(());
806 }
807
808 if mime_parser.timestamp_sent <= peerstate.last_seen {
811 info!(
812 context,
813 "Not doing AEAP from {} to {} because {} < {}.",
814 &peerstate.addr,
815 &mime_parser.from.addr,
816 mime_parser.timestamp_sent,
817 peerstate.last_seen
818 );
819 return Ok(());
820 }
821
822 info!(
823 context,
824 "Doing AEAP transition from {} to {}.", &peerstate.addr, &mime_parser.from.addr
825 );
826
827 let peerstate = mime_parser.peerstate.as_mut().context("no peerstate??")?;
828 peerstate
831 .handle_setup_change(
832 context,
833 mime_parser.timestamp_sent,
834 PeerstateChange::Aeap(mime_parser.from.addr.clone()),
835 )
836 .await?;
837
838 let old_addr = mem::take(&mut peerstate.addr);
839 peerstate.addr.clone_from(&mime_parser.from.addr);
840 let header = mime_parser.autocrypt_header.as_ref().context(
841 "Internal error: Tried to do an AEAP transition without an autocrypt header??",
842 )?;
843 peerstate.apply_header(context, header, mime_parser.timestamp_sent);
844
845 peerstate
846 .save_to_db_ex(&context.sql, Some(&old_addr))
847 .await?;
848 }
849
850 Ok(())
851}
852
853enum PeerstateChange {
858 FingerprintChange,
861 Aeap(String),
864}
865
866#[cfg(test)]
867mod tests {
868 use super::*;
869 use crate::test_utils::alice_keypair;
870
871 #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
872 async fn test_peerstate_save_to_db() {
873 let ctx = crate::test_utils::TestContext::new().await;
874 let addr = "hello@mail.com";
875
876 let pub_key = alice_keypair().public;
877
878 let peerstate = Peerstate {
879 addr: addr.into(),
880 last_seen: 10,
881 last_seen_autocrypt: 11,
882 prefer_encrypt: EncryptPreference::Mutual,
883 public_key: Some(pub_key.clone()),
884 public_key_fingerprint: Some(pub_key.dc_fingerprint()),
885 gossip_key: Some(pub_key.clone()),
886 gossip_timestamp: 12,
887 gossip_key_fingerprint: Some(pub_key.dc_fingerprint()),
888 verified_key: Some(pub_key.clone()),
889 verified_key_fingerprint: Some(pub_key.dc_fingerprint()),
890 verifier: None,
891 secondary_verified_key: None,
892 secondary_verified_key_fingerprint: None,
893 secondary_verifier: None,
894 backward_verified_key_id: None,
895 fingerprint_changed: false,
896 };
897
898 assert!(
899 peerstate.save_to_db(&ctx.ctx.sql).await.is_ok(),
900 "failed to save to db"
901 );
902
903 let peerstate_new = Peerstate::from_addr(&ctx.ctx, addr)
904 .await
905 .expect("failed to load peerstate from db")
906 .expect("no peerstate found in the database");
907
908 assert_eq!(peerstate, peerstate_new);
909 let peerstate_new2 = Peerstate::from_fingerprint(&ctx.ctx, &pub_key.dc_fingerprint())
910 .await
911 .expect("failed to load peerstate from db")
912 .expect("no peerstate found in the database");
913 assert_eq!(peerstate, peerstate_new2);
914 }
915
916 #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
917 async fn test_peerstate_double_create() {
918 let ctx = crate::test_utils::TestContext::new().await;
919 let addr = "hello@mail.com";
920 let pub_key = alice_keypair().public;
921
922 let peerstate = Peerstate {
923 addr: addr.into(),
924 last_seen: 10,
925 last_seen_autocrypt: 11,
926 prefer_encrypt: EncryptPreference::Mutual,
927 public_key: Some(pub_key.clone()),
928 public_key_fingerprint: Some(pub_key.dc_fingerprint()),
929 gossip_key: None,
930 gossip_timestamp: 12,
931 gossip_key_fingerprint: None,
932 verified_key: None,
933 verified_key_fingerprint: None,
934 verifier: None,
935 secondary_verified_key: None,
936 secondary_verified_key_fingerprint: None,
937 secondary_verifier: None,
938 backward_verified_key_id: None,
939 fingerprint_changed: false,
940 };
941
942 assert!(
943 peerstate.save_to_db(&ctx.ctx.sql).await.is_ok(),
944 "failed to save"
945 );
946 assert!(
947 peerstate.save_to_db(&ctx.ctx.sql).await.is_ok(),
948 "double-call with create failed"
949 );
950 }
951
952 #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
953 async fn test_peerstate_with_empty_gossip_key_save_to_db() {
954 let ctx = crate::test_utils::TestContext::new().await;
955 let addr = "hello@mail.com";
956
957 let pub_key = alice_keypair().public;
958
959 let peerstate = Peerstate {
960 addr: addr.into(),
961 last_seen: 10,
962 last_seen_autocrypt: 11,
963 prefer_encrypt: EncryptPreference::Mutual,
964 public_key: Some(pub_key.clone()),
965 public_key_fingerprint: Some(pub_key.dc_fingerprint()),
966 gossip_key: None,
967 gossip_timestamp: 12,
968 gossip_key_fingerprint: None,
969 verified_key: None,
970 verified_key_fingerprint: None,
971 verifier: None,
972 secondary_verified_key: None,
973 secondary_verified_key_fingerprint: None,
974 secondary_verifier: None,
975 backward_verified_key_id: None,
976 fingerprint_changed: false,
977 };
978
979 assert!(
980 peerstate.save_to_db(&ctx.ctx.sql).await.is_ok(),
981 "failed to save"
982 );
983
984 let peerstate_new = Peerstate::from_addr(&ctx.ctx, addr)
985 .await
986 .expect("failed to load peerstate from db");
987
988 assert_eq!(Some(peerstate), peerstate_new);
989 }
990
991 #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
992 async fn test_peerstate_load_db_defaults() {
993 let ctx = crate::test_utils::TestContext::new().await;
994 let addr = "hello@mail.com";
995
996 ctx.ctx
1003 .sql
1004 .execute("INSERT INTO acpeerstates (addr) VALUES(?)", (addr,))
1005 .await
1006 .expect("Failed to write to the database");
1007
1008 let peerstate = Peerstate::from_addr(&ctx.ctx, addr)
1009 .await
1010 .expect("Failed to load peerstate from db")
1011 .expect("Loaded peerstate is empty");
1012
1013 assert_eq!(peerstate.public_key_fingerprint, None);
1016 assert_eq!(peerstate.gossip_key_fingerprint, None);
1017 assert_eq!(peerstate.verified_key_fingerprint, None);
1018 }
1019
1020 #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
1021 async fn test_peerstate_degrade_reordering() {
1022 let ctx = crate::test_utils::TestContext::new().await;
1023
1024 let addr = "example@example.org";
1025 let pub_key = alice_keypair().public;
1026 let header = Aheader::new(addr.to_string(), pub_key, EncryptPreference::Mutual);
1027
1028 let mut peerstate = Peerstate {
1029 addr: addr.to_string(),
1030 last_seen: 0,
1031 last_seen_autocrypt: 0,
1032 prefer_encrypt: EncryptPreference::NoPreference,
1033 public_key: None,
1034 public_key_fingerprint: None,
1035 gossip_key: None,
1036 gossip_timestamp: 0,
1037 gossip_key_fingerprint: None,
1038 verified_key: None,
1039 verified_key_fingerprint: None,
1040 verifier: None,
1041 secondary_verified_key: None,
1042 secondary_verified_key_fingerprint: None,
1043 secondary_verifier: None,
1044 backward_verified_key_id: None,
1045 fingerprint_changed: false,
1046 };
1047
1048 peerstate.apply_header(&ctx, &header, 100);
1049 assert_eq!(peerstate.prefer_encrypt, EncryptPreference::Mutual);
1050
1051 peerstate.degrade_encryption(300);
1052 assert_eq!(peerstate.prefer_encrypt, EncryptPreference::Reset);
1053
1054 peerstate.apply_header(&ctx, &header, 200);
1057 assert_eq!(peerstate.prefer_encrypt, EncryptPreference::Reset);
1058
1059 peerstate.apply_header(&ctx, &header, 300);
1061 assert_eq!(peerstate.prefer_encrypt, EncryptPreference::Mutual);
1062 }
1063}