@ -4883,10 +4883,10 @@ static void get_message_version_from_headers(
{
* major_ver = 0 ;
* minor_ver = 0 ;
const stringpair_list_t * pEp_ protocol _version = stringpair_list_find ( field_list , X_PEP_MSG_VER_KEY ) ;
const stringpair_list_t * pEp_ message _version = stringpair_list_find ( field_list , X_PEP_MSG_VER_KEY ) ;
if ( pEp_ protocol_version & & pEp_protocol _version- > value )
pEp_version_major_minor ( pEp_ protocol _version- > value - > value , major_ver , minor_ver ) ;
if ( pEp_ message_version & & pEp_message _version- > value )
pEp_version_major_minor ( pEp_ message _version- > value - > value , major_ver , minor_ver ) ;
}
// CAN return PASS errors
@ -4952,6 +4952,52 @@ static PEP_STATUS _check_and_set_default_key(
return PEP_STATUS_OK ; // We don't care about other errors here.
}
static const char * process_key_claim ( message * src ,
const char * imported_sender_key_fpr ,
const char * signer_fpr ,
int msg_major , int msg_minor ,
stringlist_t * imported_key_list ,
bool pEp_conformant ) {
if ( msg_major = = 2 & & msg_minor = = 0 )
return NULL ;
// Senders with pEp versions >= than 2.2 will never send us a 2.0 message or less
// IF they know we are a pEp user.
//
// However, they COULD think we're OpenPGP - maybe imported the key from somewhere.
//
// So we have to only take the key IF the from-2.2-message-version is listed as
// 1.0. Everything else we support would have an inner message. And only then
// if the sender key has the right name. (FIXME: Have we changed 2.1 to do this?)
// FIXME: From SENDER >= 2.2, we should be VERY careful here -- check back on this one
//
const char * sender_key = NULL ;
if ( msg_major = = 1 ) // pEp only: We only import from 2.1.34+ clients, which will use the correct name.
sender_key = imported_sender_key_fpr ;
else if ( ( msg_major = = 2 & & msg_minor > = 1 ) | | msg_major > 2 ) {
// We've been sent the inner message
// we require sender key filename to be correct and material to be present in this case
if ( ! EMPTYSTR ( imported_sender_key_fpr ) & & ! EMPTYSTR ( src - > _sender_fpr ) ) {
if ( strcmp ( imported_sender_key_fpr , src - > _sender_fpr ) = = 0 )
sender_key = src - > _sender_fpr ;
}
}
else if ( ! pEp_conformant ) {
// For header keys, we will have been sent the head of the list here.
// For others, we were sent a reference to the last set of keys imported before this and checked to be
// sure there was only one.
if ( imported_key_list ) // not necessarily signer key!
sender_key = imported_key_list - > value ;
}
if ( ! EMPTYSTR ( sender_key ) & & ! EMPTYSTR ( signer_fpr ) ) {
if ( strcmp ( sender_key , signer_fpr ) ! = 0 )
sender_key = NULL ;
}
return sender_key ;
}
// Rule for this function, since it is one of the three most complicated functions in this whole damned
// business:
@ -5205,17 +5251,15 @@ static PEP_STATUS _decrypt_message(
if ( src - > from - > address ) {
PEP_STATUS incoming_status = status ;
const char * sender_key = NULL ;
if ( imported_sender_key_fpr ) { // pEp message version 2.2 or greater
if ( imported_sender_key_fpr ) { // pEp protocol version 2.2 or greater, or someone knows to use the filename
sender_key = imported_sender_key_fpr ; // FIXME: free
}
else if ( ! is_pEp_msg & & header_key_imported ) // autocrypt
sender_key = _imported_key_list - > value ;
else {
// We do this only with pEp messages 2.1 or less, or OpenPGP messages
if ( ! is_pEp_msg | | ( major_ver = = 2 & & minor_ver < 2 ) | | major_ver < 2 ) {
if ( _imported_key_list & & ! ( _imported_key_list - > next ) )
sender_key = _imported_key_list - > value ;
}
// Basically, this is everything else, since we can trust nothing on the wire really.
if ( _imported_key_list & & ! ( _imported_key_list - > next ) )
sender_key = _imported_key_list - > value ;
} // Otherwise, too bad.
status = _check_and_set_default_key ( session , src - > from , sender_key ) ;
@ -5346,30 +5390,41 @@ static PEP_STATUS _decrypt_message(
}
if ( status = = PEP_STATUS_OK & & ! has_inner ) {
// If we're claiming to have a pEp version 2.2 or greater, we only take it
// if it had the right name during the import and if it was the ONLY key on the message?
// Senders with pEp versions greater than 2.2 will never send us a 2.0 message or less
// IF they know we are a pEp user.
//
// However, they COULD think we're OpenPGP - maybe imported the key from somewhere.
//
// So we have to only take the key IF the from-2.2-message-version is listed as
// 1.0. Everything else we support would have an inner message. And only then
// if the sender key has the right name. (FIXME: Have we changed 2.1 to do this?)
// FIXME: From SENDER >= 2.2, we should be VERY careful here -- check back on this one
//
const char * sender_key = NULL ;
// FIXME: No, not possible. Has to come from INNER message.
if ( ( major_ver = = 2 & & minor_ver > 1 ) | | major_ver > 2 ) {
if ( imported_sender_key_fpr )
sender_key = imported_sender_key_fpr ;
}
else if ( header_key_imported & & _imported_key_list ) {
sender_key = _imported_key_list - > value ;
}
else if ( * start & & ! ( ( * start ) - > next ) ) {
if ( decrypt_status = = PEP_DECRYPTED_AND_VERIFIED ) {
if ( _keylist & & ! EMPTYSTR ( _keylist - > value ) & & * start & & ! EMPTYSTR ( ( * start ) - > value ) ) {
sender_key = ( * start ) - > value ; // signer if sent from < 2.1
}
get_message_version_from_headers ( src - > opt_fields , & msg_major_ver , & msg_minor_ver ) ;
const char * key_claim_fpr = NULL ;
if ( decrypt_status = = PEP_DECRYPTED_AND_VERIFIED & & _imported_key_list ) {
// This is correct - we require sender key filename to be correct and material to be present in this case from any non-2.2+ version or OpenPGP, and we'll get 1 from 2.2+. Otherwise,
// we call shenanigans and don't trust the key to set defaults from.
if ( imported_sender_key_fpr ) {
key_claim_fpr = process_key_claim ( src , imported_sender_key_fpr ,
_imported_key_list - > value , 1 , 0 ,
_imported_key_list , true ) ;
}
else {
stringlist_t * claim_node = header_key_imported ? _imported_key_list : * start ;
key_claim_fpr = process_key_claim ( src , NULL ,
claim_node ? claim_node - > value : NULL ,
0 , 0 ,
_imported_key_list , false ) ;
}
}
if ( ! EMPTYSTR ( key_claim_fpr ) )
status = _check_and_set_default_key ( session , src - > from , key_claim_fpr ) ;
status = _check_and_set_default_key ( session , src - > from , sender_key ) ;
free ( imported_sender_key_fpr ) ;
imported_sender_key_fpr = NULL ;
@ -5417,7 +5472,7 @@ static PEP_STATUS _decrypt_message(
else if ( strcasecmp ( mime_type , " application/pEp.distribution " ) = = 0 )
filename = " file://distribution.pEp " ;
else if ( strcasecmp ( mime_type , " application/pgp-keys " ) = = 0 )
filename = " file:// pEp key.asc" ;
filename = " file:// sender_ key.asc" ;
else if ( strcasecmp ( mime_type , " application/pgp-signature " ) = = 0 )
filename = " file://electronic_signature.asc " ;
bloblist_t * bl = new_bloblist ( value , size , mime_type , filename ) ;
@ -5454,19 +5509,20 @@ static PEP_STATUS _decrypt_message(
& _changed_keys ,
& imported_sender_key_fpr ) ;
if ( status = = PEP_STATUS_OK & & src - > from & & ! is_me ( session , src - > from ) ) {
// If we're claiming to have a pEp version 2.2 or greater, we only take it
// if it had the right name during the import and if it was the ONLY key on the message?
const char * sender_key = NULL ;
if ( ( major_ver = = 2 & & minor_ver > 1 ) | | major_ver > 2 ) {
if ( imported_sender_key_fpr )
sender_key = imported_sender_key_fpr ;
}
else if ( * start & & ! ( ( * start ) - > next ) )
sender_key = ( * start ) - > value ; // signer if sent from < 2.1
status = _check_and_set_default_key ( session , src - > from , sender_key ) ;
}
const char * key_claim_fpr = NULL ;
if ( decrypt_status = = PEP_DECRYPTED_AND_VERIFIED & & _imported_key_list ) {
bool filename_matched = ! EMPTYSTR ( imported_sender_key_fpr ) ;
key_claim_fpr = process_key_claim ( src , imported_sender_key_fpr ,
_imported_key_list - > value ,
filename_matched ? 1 : 0 , 0 , // Not as redundant as you think
filename_matched ? _imported_key_list : * start ,
filename_matched ) ;
}
if ( ! EMPTYSTR ( key_claim_fpr ) )
status = _check_and_set_default_key ( session , src - > from , key_claim_fpr ) ;
break ;
default :
@ -5498,9 +5554,6 @@ static PEP_STATUS _decrypt_message(
// FIXME: replace with enums, check status
if ( has_inner | | wrap_info ) { // Given that only wrap_info OUTER happens as of the end of wrap_info use, we don't need to strcmp it
// if (strcmp(wrap_info, "OUTER") == 0) {
// // this only occurs in with a direct outer wrapper
// // where the actual content is in the inner wrapper
message * inner_message = NULL ;
// For a wrapped message, this is ALWAYS the second attachment; the
@ -5683,11 +5736,9 @@ static PEP_STATUS _decrypt_message(
imported_private_key_address = false ;
free ( private_il ) ;
private_il = NULL ;
free ( imported_sender_key_fpr ) ;
imported_sender_key_fpr = NULL ;
// Generally imported from the outer decryption - inner messages lie along side it in the message.
// So should we always pass NULL here? Probably. FIXME.
// import keys from decrypted INNER source
status = import_keys_from_decrypted_msg ( session , inner_message , is_pEp_msg ,
& keys_were_imported ,
@ -5695,23 +5746,20 @@ static PEP_STATUS _decrypt_message(
private_il ,
& _imported_key_list ,
& _changed_keys ,
& imported_sender_key_fpr ) ;
EMPTYSTR ( imported_sender_key_fpr ) ? & imported_sender_key_fpr : NULL ) ;
if ( status ! = PEP_STATUS_OK )
goto pEp_error ;
if ( ! breaks_protocol & & inner_message - > from & & ! is_me ( session , inner_message - > from ) ) {
const char * sender_key = NULL ;
// Set default?
if ( ! breaks_protocol & & inner_message - > from & & ! is_me ( session , inner_message - > from ) & & _imported_key_list ) {
// We don't consider the pEp 2.0 case anymore, so no special processing
const char * key_claim_fpr = process_key_claim ( inner_message , imported_sender_key_fpr ,
_imported_key_list - > value , msg_major_ver , msg_minor_ver ,
NULL , true ) ;
// Messages from clients 2.1 or greater should ALWAYS have sender_fpr on the inside. So...
if ( ! EMPTYSTR ( inner_message - > _sender_fpr ) )
sender_key = inner_message - > _sender_fpr ;
else { // !breaks_protocol is true, so this is a 2.0 message FROM a 2.0 client
if ( _keylist ) { // signer key, 2.0 sent from 2.0 client
sender_key = _keylist - > value ; // can be empty
}
}
status = _check_and_set_default_key ( session , inner_message - > from , sender_key ) ;
status = _check_and_set_default_key ( session , inner_message - > from , key_claim_fpr ) ;
if ( status = = PEP_OUT_OF_MEMORY )
goto enomem ;
}