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