1
0
Fork 0
mirror of https://github.com/deltachat/deltachat-core.git synced 2025-10-06 03:50:08 +02:00

prepare mrapeerstate_t to handle gossip keys, allow public_key and gossip_key being NULL

This commit is contained in:
B. Petersen 2018-02-13 01:07:57 +01:00
parent 4a1f2b2d81
commit bc6e8e0a9e
6 changed files with 61 additions and 19 deletions

View file

@ -261,7 +261,7 @@ static void log_contactlist(mrmailbox_t* mailbox, mrarray_t* contacts)
case MRA_PE_RESET: pe = safe_strdup("reset"); break; case MRA_PE_RESET: pe = safe_strdup("reset"); break;
default: pe = mr_mprintf("unknown-value (%i)", peerstate->m_prefer_encrypt); break; default: pe = mr_mprintf("unknown-value (%i)", peerstate->m_prefer_encrypt); break;
} }
line2 = mr_mprintf(", prefer-encrypt=%s, key-bytes=%i", pe, peerstate->m_public_key->m_bytes); line2 = mr_mprintf(", prefer-encrypt=%s", pe);
free(pe); free(pe);
} }
mrcontact_unref(contact); mrcontact_unref(contact);

View file

@ -44,9 +44,16 @@ static void mrapeerstate_empty(mrapeerstate_t* ths)
free(ths->m_addr); free(ths->m_addr);
ths->m_addr = NULL; ths->m_addr = NULL;
if( ths->m_public_key->m_binary ) { if( ths->m_public_key ) {
mrkey_unref(ths->m_public_key); mrkey_unref(ths->m_public_key);
ths->m_public_key = mrkey_new(); ths->m_public_key = NULL;
}
ths->m_gossip_timestamp = 0;
if( ths->m_gossip_key ) {
mrkey_unref(ths->m_gossip_key);
ths->m_gossip_key = NULL;
} }
} }
@ -63,7 +70,7 @@ int mrapeerstate_load_from_db__(mrapeerstate_t* ths, mrsqlite3_t* sql, const cha
mrapeerstate_empty(ths); mrapeerstate_empty(ths);
stmt = mrsqlite3_predefine__(sql, SELECT_aclpp_FROM_acpeerstates_WHERE_a, stmt = mrsqlite3_predefine__(sql, SELECT_aclpp_FROM_acpeerstates_WHERE_a,
"SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key FROM acpeerstates WHERE addr=? COLLATE NOCASE;"); "SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, gossip_timestamp, gossip_key FROM acpeerstates WHERE addr=? COLLATE NOCASE;");
sqlite3_bind_text(stmt, 1, addr, -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 1, addr, -1, SQLITE_STATIC);
if( sqlite3_step(stmt) != SQLITE_ROW ) { if( sqlite3_step(stmt) != SQLITE_ROW ) {
goto cleanup; goto cleanup;
@ -72,7 +79,19 @@ int mrapeerstate_load_from_db__(mrapeerstate_t* ths, mrsqlite3_t* sql, const cha
ths->m_last_seen = sqlite3_column_int64 (stmt, 1); ths->m_last_seen = sqlite3_column_int64 (stmt, 1);
ths->m_last_seen_autocrypt = sqlite3_column_int64 (stmt, 2); ths->m_last_seen_autocrypt = sqlite3_column_int64 (stmt, 2);
ths->m_prefer_encrypt = sqlite3_column_int (stmt, 3); ths->m_prefer_encrypt = sqlite3_column_int (stmt, 3);
mrkey_set_from_stmt (ths->m_public_key, stmt, 4, MR_PUBLIC); #define PUBLIC_KEY_COL 4
ths->m_gossip_timestamp = sqlite3_column_int (stmt, 5);
#define GOSSIP_KEY_COL 6
if( sqlite3_column_type(stmt, PUBLIC_KEY_COL)!=SQLITE_NULL ) {
ths->m_public_key = mrkey_new();
mrkey_set_from_stmt(ths->m_public_key, stmt, PUBLIC_KEY_COL, MR_PUBLIC);
}
if( sqlite3_column_type(stmt, GOSSIP_KEY_COL)!=SQLITE_NULL ) {
ths->m_gossip_key = mrkey_new();
mrkey_set_from_stmt(ths->m_gossip_key, stmt, GOSSIP_KEY_COL, MR_PUBLIC);
}
success = 1; success = 1;
@ -86,8 +105,7 @@ int mrapeerstate_save_to_db__(const mrapeerstate_t* ths, mrsqlite3_t* sql, int c
int success = 0; int success = 0;
sqlite3_stmt* stmt; sqlite3_stmt* stmt;
if( ths==NULL || sql==NULL if( ths==NULL || sql==NULL || ths->m_addr==NULL ) {
|| ths->m_addr==NULL || ths->m_public_key->m_binary==NULL || ths->m_public_key->m_bytes<=0 ) {
return 0; return 0;
} }
@ -100,12 +118,14 @@ int mrapeerstate_save_to_db__(const mrapeerstate_t* ths, mrsqlite3_t* sql, int c
if( (ths->m_to_save&MRA_SAVE_ALL) || create ) if( (ths->m_to_save&MRA_SAVE_ALL) || create )
{ {
stmt = mrsqlite3_predefine__(sql, UPDATE_acpeerstates_SET_lcpp_WHERE_a, stmt = mrsqlite3_predefine__(sql, UPDATE_acpeerstates_SET_lcpp_WHERE_a,
"UPDATE acpeerstates SET last_seen=?, last_seen_autocrypt=?, prefer_encrypted=?, public_key=? WHERE addr=?;"); "UPDATE acpeerstates SET last_seen=?, last_seen_autocrypt=?, prefer_encrypted=?, public_key=?, gossip_timestamp=?, gossip_key=? WHERE addr=?;");
sqlite3_bind_int64(stmt, 1, ths->m_last_seen); sqlite3_bind_int64(stmt, 1, ths->m_last_seen);
sqlite3_bind_int64(stmt, 2, ths->m_last_seen_autocrypt); sqlite3_bind_int64(stmt, 2, ths->m_last_seen_autocrypt);
sqlite3_bind_int64(stmt, 3, ths->m_prefer_encrypt); sqlite3_bind_int64(stmt, 3, ths->m_prefer_encrypt);
sqlite3_bind_blob (stmt, 4, ths->m_public_key->m_binary, ths->m_public_key->m_bytes, SQLITE_STATIC); sqlite3_bind_blob (stmt, 4, ths->m_public_key? ths->m_public_key->m_binary : NULL/*results in sqlite3_bind_null()*/, ths->m_public_key? ths->m_public_key->m_bytes : 0, SQLITE_STATIC);
sqlite3_bind_text (stmt, 5, ths->m_addr, -1, SQLITE_STATIC); sqlite3_bind_int64(stmt, 5, ths->m_gossip_timestamp);
sqlite3_bind_blob (stmt, 6, ths->m_gossip_key? ths->m_gossip_key->m_binary : NULL/*results in sqlite3_bind_null()*/, ths->m_gossip_key? ths->m_gossip_key->m_bytes : 0, SQLITE_STATIC);
sqlite3_bind_text (stmt, 7, ths->m_addr, -1, SQLITE_STATIC);
if( sqlite3_step(stmt) != SQLITE_DONE ) { if( sqlite3_step(stmt) != SQLITE_DONE ) {
goto cleanup; goto cleanup;
} }
@ -142,8 +162,6 @@ mrapeerstate_t* mrapeerstate_new()
exit(43); /* cannot allocate little memory, unrecoverable error */ exit(43); /* cannot allocate little memory, unrecoverable error */
} }
ths->m_public_key = mrkey_new();
return ths; return ths;
} }
@ -156,6 +174,7 @@ void mrapeerstate_unref(mrapeerstate_t* ths)
free(ths->m_addr); free(ths->m_addr);
mrkey_unref(ths->m_public_key); mrkey_unref(ths->m_public_key);
mrkey_unref(ths->m_gossip_key);
free(ths); free(ths);
} }
@ -167,7 +186,7 @@ char* mrapeerstate_render_gossip_header(mrapeerstate_t* peerstate)
autocryptheader->m_prefer_encrypt = MRA_PE_NOPREFERENCE; /* the spec says, we SHOULD NOT gossip this flag */ autocryptheader->m_prefer_encrypt = MRA_PE_NOPREFERENCE; /* the spec says, we SHOULD NOT gossip this flag */
autocryptheader->m_addr = safe_strdup(peerstate->m_addr); autocryptheader->m_addr = safe_strdup(peerstate->m_addr);
autocryptheader->m_public_key = mrkey_ref(peerstate->m_public_key); autocryptheader->m_public_key = mrkey_ref(peerstate->m_public_key? peerstate->m_public_key : peerstate->m_gossip_key); /* may be NULL */
ret = mraheader_render(autocryptheader); ret = mraheader_render(autocryptheader);
@ -193,7 +212,10 @@ int mrapeerstate_init_from_header(mrapeerstate_t* ths, const mraheader_t* header
ths->m_last_seen_autocrypt = message_time; ths->m_last_seen_autocrypt = message_time;
ths->m_to_save = MRA_SAVE_ALL; ths->m_to_save = MRA_SAVE_ALL;
ths->m_prefer_encrypt = header->m_prefer_encrypt; ths->m_prefer_encrypt = header->m_prefer_encrypt;
ths->m_public_key = mrkey_new();
mrkey_set_from_key(ths->m_public_key, header->m_public_key); mrkey_set_from_key(ths->m_public_key, header->m_public_key);
return 1; return 1;
} }
@ -233,6 +255,10 @@ int mrapeerstate_apply_header(mrapeerstate_t* ths, const mraheader_t* header, ti
ths->m_to_save |= MRA_SAVE_ALL; ths->m_to_save |= MRA_SAVE_ALL;
} }
if( ths->m_public_key == NULL ) {
ths->m_public_key = mrkey_new();
}
if( !mrkey_equals(ths->m_public_key, header->m_public_key) ) if( !mrkey_equals(ths->m_public_key, header->m_public_key) )
{ {
mrkey_set_from_key(ths->m_public_key, header->m_public_key); mrkey_set_from_key(ths->m_public_key, header->m_public_key);

View file

@ -47,10 +47,14 @@ typedef struct mrapeerstate_t
/** @privatesection */ /** @privatesection */
char* m_addr; char* m_addr;
time_t m_last_seen; time_t m_last_seen;
time_t m_last_seen_autocrypt; time_t m_last_seen_autocrypt;
mrkey_t* m_public_key; /*!=NULL*/ mrkey_t* m_public_key; /* may be NULL */
int m_prefer_encrypt; int m_prefer_encrypt;
time_t m_gossip_timestamp;
mrkey_t* m_gossip_key; /* may be NULL */
#define MRA_SAVE_LAST_SEEN 0x01 #define MRA_SAVE_LAST_SEEN 0x01
#define MRA_SAVE_ALL 0x02 #define MRA_SAVE_ALL 0x02
int m_to_save; int m_to_save;

View file

@ -4855,7 +4855,7 @@ char* mrmailbox_get_contact_encrinfo(mrmailbox_t* mailbox, uint32_t contact_id)
if( e2ee_enabled if( e2ee_enabled
&& peerstate_ok && peerstate_ok
&& peerstate->m_prefer_encrypt==MRA_PE_MUTUAL && peerstate->m_prefer_encrypt==MRA_PE_MUTUAL
&& peerstate->m_public_key->m_binary!=NULL ) && peerstate->m_public_key!=NULL )
{ {
/* e2e fine and used */ /* e2e fine and used */
p = mrstock_str(MR_STR_ENCR_E2E); mrstrbuilder_cat(&ret, p); free(p); p = mrstock_str(MR_STR_ENCR_E2E); mrstrbuilder_cat(&ret, p); free(p);
@ -4875,7 +4875,7 @@ char* mrmailbox_get_contact_encrinfo(mrmailbox_t* mailbox, uint32_t contact_id)
} }
/* ... and then explain why we cannot use e2e */ /* ... and then explain why we cannot use e2e */
if( peerstate_ok && peerstate->m_public_key->m_binary!=NULL && peerstate->m_prefer_encrypt!=MRA_PE_MUTUAL ) { if( peerstate_ok && peerstate->m_public_key && peerstate->m_prefer_encrypt!=MRA_PE_MUTUAL ) {
explain_id = MR_STR_E2E_DIS_BY_RCPT; explain_id = MR_STR_E2E_DIS_BY_RCPT;
} }
else if( !e2ee_enabled ) { else if( !e2ee_enabled ) {
@ -4888,7 +4888,7 @@ char* mrmailbox_get_contact_encrinfo(mrmailbox_t* mailbox, uint32_t contact_id)
/* show fingerprints for comparison (sorted by email-address to make a device-side-by-side comparison easier) */ /* show fingerprints for comparison (sorted by email-address to make a device-side-by-side comparison easier) */
if( peerstate_ok if( peerstate_ok
&& peerstate->m_public_key->m_binary!=NULL ) && peerstate->m_public_key )
{ {
if( self_key->m_binary == NULL ) { if( self_key->m_binary == NULL ) {
mrpgp_rand_seed(mailbox, peerstate->m_addr, strlen(peerstate->m_addr) /*just some random data*/); mrpgp_rand_seed(mailbox, peerstate->m_addr, strlen(peerstate->m_addr) /*just some random data*/);

View file

@ -366,6 +366,7 @@ void mrmailbox_e2ee_encrypt(mrmailbox_t* mailbox, const clist* recipients_addr,
const char* recipient_addr = clist_content(iter1); const char* recipient_addr = clist_content(iter1);
mrapeerstate_t* peerstate = mrapeerstate_new(); mrapeerstate_t* peerstate = mrapeerstate_new();
if( mrapeerstate_load_from_db__(peerstate, mailbox->m_sql, recipient_addr) if( mrapeerstate_load_from_db__(peerstate, mailbox->m_sql, recipient_addr)
&& peerstate->m_public_key
&& peerstate->m_public_key->m_binary!=NULL && peerstate->m_public_key->m_binary!=NULL
&& peerstate->m_public_key->m_bytes>0 && peerstate->m_public_key->m_bytes>0
&& (peerstate->m_prefer_encrypt==MRA_PE_MUTUAL || e2ee_guaranteed) ) && (peerstate->m_prefer_encrypt==MRA_PE_MUTUAL || e2ee_guaranteed) )
@ -747,7 +748,7 @@ int mrmailbox_e2ee_decrypt(mrmailbox_t* mailbox, struct mailmime* in_out_message
} }
/* if not yet done, load peer with public key for verification (should be last as the peer may be modified above) */ /* if not yet done, load peer with public key for verification (should be last as the peer may be modified above) */
if( peerstate->m_public_key->m_bytes <= 0 ) { if( peerstate->m_last_seen == 0 ) {
mrapeerstate_load_from_db__(peerstate, mailbox->m_sql, from); mrapeerstate_load_from_db__(peerstate, mailbox->m_sql, from);
} }
@ -758,7 +759,7 @@ int mrmailbox_e2ee_decrypt(mrmailbox_t* mailbox, struct mailmime* in_out_message
*ret_validation_errors = 0; *ret_validation_errors = 0;
int avoid_deadlock = 10; int avoid_deadlock = 10;
while( avoid_deadlock > 0 ) { while( avoid_deadlock > 0 ) {
if( !decrypt_recursive(mailbox, in_out_message, private_keyring, peerstate->m_public_key->m_bytes>0? peerstate->m_public_key : NULL, ret_validation_errors) ) { if( !decrypt_recursive(mailbox, in_out_message, private_keyring, peerstate->m_public_key, ret_validation_errors) ) {
break; break;
} }
sth_decrypted = 1; sth_decrypted = 1;

View file

@ -331,6 +331,17 @@ int mrsqlite3_open__(mrsqlite3_t* ths, const char* dbfile, int flags)
mrsqlite3_set_config_int__(ths, "dbversion", NEW_DB_VERSION); mrsqlite3_set_config_int__(ths, "dbversion", NEW_DB_VERSION);
} }
#undef NEW_DB_VERSION #undef NEW_DB_VERSION
#define NEW_DB_VERSION 18
if( dbversion < NEW_DB_VERSION )
{
mrsqlite3_execute__(ths, "ALTER TABLE acpeerstates ADD COLUMN gossip_timestamp INTEGER DEFAULT 0;");
mrsqlite3_execute__(ths, "ALTER TABLE acpeerstates ADD COLUMN gossip_key;");
dbversion = NEW_DB_VERSION;
mrsqlite3_set_config_int__(ths, "dbversion", NEW_DB_VERSION);
}
#undef NEW_DB_VERSION
} }
mrmailbox_log_info(ths->m_mailbox, 0, "Opened \"%s\" successfully.", dbfile); mrmailbox_log_info(ths->m_mailbox, 0, "Opened \"%s\" successfully.", dbfile);