@ -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 ;
}