@@ -23,6 +23,8 @@ use crate::qr::check_qr;
23
23
use crate :: securejoin:: bob:: JoinerProgress ;
24
24
use crate :: sync:: Sync :: * ;
25
25
use crate :: token;
26
+ use crate :: tools:: create_id;
27
+ use crate :: tools:: time;
26
28
27
29
mod bob;
28
30
mod qrinvite;
@@ -75,10 +77,21 @@ pub async fn get_securejoin_qr(context: &Context, group: Option<ChatId>) -> Resu
75
77
let sync_token = token:: lookup ( context, Namespace :: InviteNumber , grpid)
76
78
. await ?
77
79
. is_none ( ) ;
78
- // invitenumber will be used to allow starting the handshake,
79
- // auth will be used to verify the fingerprint
80
+ // Invite number is used to request the inviter key.
80
81
let invitenumber = token:: lookup_or_new ( context, Namespace :: InviteNumber , grpid) . await ?;
81
- let auth = token:: lookup_or_new ( context, Namespace :: Auth , grpid) . await ?;
82
+
83
+ // Auth token is used to verify the key-contact
84
+ // if the token is not old
85
+ // and add the contact to the group
86
+ // if there is an associated group ID.
87
+ //
88
+ // We always generate a new auth token
89
+ // because auth tokens "expire"
90
+ // and can only be used to join groups
91
+ // without verification afterwards.
92
+ let auth = create_id ( ) ;
93
+ token:: save ( context, Namespace :: Auth , grpid, & auth) . await ?;
94
+
82
95
let self_addr = context. get_primary_self_addr ( ) . await ?;
83
96
let self_name = context
84
97
. get_config ( Config :: Displayname )
@@ -364,7 +377,19 @@ pub(crate) async fn handle_securejoin_handshake(
364
377
) ;
365
378
return Ok ( HandshakeMessage :: Ignore ) ;
366
379
} ;
367
- let Some ( grpid) = token:: auth_foreign_key ( context, auth) . await ? else {
380
+ let Some ( ( grpid, timestamp) ) = context
381
+ . sql
382
+ . query_row_optional (
383
+ "SELECT foreign_key, timestamp FROM tokens WHERE namespc=? AND token=?" ,
384
+ ( Namespace :: Auth , auth) ,
385
+ |row| {
386
+ let foreign_key: String = row. get ( 0 ) ?;
387
+ let timestamp: i64 = row. get ( 1 ) ?;
388
+ Ok ( ( foreign_key, timestamp) )
389
+ } ,
390
+ )
391
+ . await ?
392
+ else {
368
393
warn ! (
369
394
context,
370
395
"Ignoring {step} message because of invalid auth code."
@@ -382,14 +407,23 @@ pub(crate) async fn handle_securejoin_handshake(
382
407
}
383
408
} ;
384
409
385
- if !verify_sender_by_fingerprint ( context, & fingerprint, contact_id) . await ? {
410
+ let sender_contact = Contact :: get_by_id ( context, contact_id) . await ?;
411
+ let sender_is_verified = sender_contact
412
+ . fingerprint ( )
413
+ . is_some_and ( |fp| fp == fingerprint) ;
414
+ if !sender_is_verified {
386
415
warn ! (
387
416
context,
388
417
"Ignoring {step} message because of fingerprint mismatch."
389
418
) ;
390
419
return Ok ( HandshakeMessage :: Ignore ) ;
391
420
}
392
421
info ! ( context, "Fingerprint verified via Auth code." , ) ;
422
+
423
+ // Mark the contact as verified if auth code is 600 second old.
424
+ if time ( ) < timestamp + 600 {
425
+ mark_contact_id_as_verified ( context, contact_id, Some ( ContactId :: SELF ) ) . await ?;
426
+ }
393
427
contact_id. regossip_keys ( context) . await ?;
394
428
ContactId :: scaleup_origin ( context, & [ contact_id] , Origin :: SecurejoinInvited ) . await ?;
395
429
// for setup-contact, make Alice's one-to-one chat with Bob visible
0 commit comments