Merged ENGINE-179
authorEdouard Tisserant <edouard@pep-project.org>
Tue, 06 Jun 2017 18:11:09 +0200
changeset 1827277a39ed449b
parent 1824 def83c456552
parent 1822 5a77127f3f7e
child 1830 acb58598b45b
child 1832 93c627c7f709
Merged ENGINE-179
src/message_api.c
     1.1 --- a/src/message_api.c	Tue Jun 06 17:53:56 2017 +0200
     1.2 +++ b/src/message_api.c	Tue Jun 06 18:11:09 2017 +0200
     1.3 @@ -1592,6 +1592,52 @@
     1.4      return status;
     1.5  }
     1.6  
     1.7 +PEP_STATUS amend_rating_according_to_sender_and_recipients(
     1.8 +    PEP_SESSION session,
     1.9 +    PEP_rating *rating,
    1.10 +    pEp_identity *sender,
    1.11 +    stringlist_t *recipients) {
    1.12 +    
    1.13 +    PEP_STATUS status = PEP_STATUS_OK;
    1.14 +
    1.15 +    if (*rating > PEP_rating_mistrust) {
    1.16 +        PEP_rating kl_rating = PEP_rating_undefined;
    1.17 +
    1.18 +        if (recipients)
    1.19 +            kl_rating = keylist_rating(session, recipients);
    1.20 +
    1.21 +        if (kl_rating <= PEP_rating_mistrust) {
    1.22 +            *rating = kl_rating;
    1.23 +        }
    1.24 +        else if (*rating >= PEP_rating_reliable &&
    1.25 +                 kl_rating < PEP_rating_reliable) {
    1.26 +            *rating = PEP_rating_unreliable;
    1.27 +        }
    1.28 +        else if (*rating >= PEP_rating_reliable &&
    1.29 +                 kl_rating >= PEP_rating_reliable) {
    1.30 +            if (!(sender && sender->user_id && sender->user_id[0])) {
    1.31 +                *rating = PEP_rating_unreliable;
    1.32 +            }
    1.33 +            else {
    1.34 +                char *fpr = recipients->value;
    1.35 +                pEp_identity *_sender = new_identity(sender->address, fpr,
    1.36 +                                                   sender->user_id, sender->username);
    1.37 +                if (_sender == NULL)
    1.38 +                    return PEP_OUT_OF_MEMORY;
    1.39 +                status = get_trust(session, _sender);
    1.40 +                if (_sender->comm_type != PEP_ct_unknown) {
    1.41 +                    *rating = worst_rating(_rating(_sender->comm_type, PEP_rating_undefined),
    1.42 +                              kl_rating);
    1.43 +                }
    1.44 +                free_identity(_sender);
    1.45 +                if (status == PEP_CANNOT_FIND_IDENTITY)
    1.46 +                   status = PEP_STATUS_OK;
    1.47 +            }
    1.48 +        }
    1.49 +    }
    1.50 +    return status;
    1.51 +}
    1.52 +
    1.53  
    1.54  DYNAMIC_API PEP_STATUS _decrypt_message(
    1.55          PEP_SESSION session,
    1.56 @@ -1982,45 +2028,13 @@
    1.57  
    1.58          *rating = decrypt_rating(decrypt_status);
    1.59  
    1.60 -        if (*rating > PEP_rating_mistrust) {
    1.61 -            PEP_rating kl_rating = PEP_rating_undefined;
    1.62 -
    1.63 -            if (_keylist)
    1.64 -                kl_rating = keylist_rating(session, _keylist);
    1.65 -
    1.66 -            if (kl_rating <= PEP_rating_mistrust) {
    1.67 -                *rating = kl_rating;
    1.68 -            }
    1.69 -            else if (*rating >= PEP_rating_reliable &&
    1.70 -                     kl_rating < PEP_rating_reliable) {
    1.71 -                *rating = PEP_rating_unreliable;
    1.72 -            }
    1.73 -            else if (*rating >= PEP_rating_reliable &&
    1.74 -                     kl_rating >= PEP_rating_reliable) {
    1.75 -                if (!(src->from && src->from->user_id && src->from->user_id[0])) {
    1.76 -                    *rating = PEP_rating_unreliable;
    1.77 -                }
    1.78 -                else {
    1.79 -                    char *fpr = _keylist->value;
    1.80 -                    pEp_identity *_from = new_identity(src->from->address, fpr,
    1.81 -                                                       src->from->user_id, src->from->username);
    1.82 -                    if (_from == NULL)
    1.83 -                        goto enomem;
    1.84 -                    status = get_trust(session, _from);
    1.85 -                    if (_from->comm_type != PEP_ct_unknown) {
    1.86 -                        *rating = worst_rating(_rating(_from->comm_type, PEP_rating_undefined),
    1.87 -                                  kl_rating);
    1.88 -                    }
    1.89 -                    free_identity(_from);
    1.90 -                    if (status == PEP_CANNOT_FIND_IDENTITY)
    1.91 -                       status = PEP_STATUS_OK;
    1.92 -                    if (status != PEP_STATUS_OK)
    1.93 -                    {
    1.94 -                        GOTO(pep_error);
    1.95 -                    }
    1.96 -                }
    1.97 -            }
    1.98 -        }
    1.99 +        status = amend_rating_according_to_sender_and_recipients(session,
   1.100 +                                                                 rating,
   1.101 +                                                                 src->from,
   1.102 +                                                                 _keylist);
   1.103 +
   1.104 +        if (status != PEP_STATUS_OK)
   1.105 +            GOTO(pep_error);
   1.106      }
   1.107      else
   1.108      {
   1.109 @@ -2624,3 +2638,138 @@
   1.110  
   1.111      return ERROR(status);
   1.112  }
   1.113 +
   1.114 +static PEP_rating string_to_rating(const char * rating)
   1.115 +{
   1.116 +    if (rating == NULL)
   1.117 +        return PEP_rating_undefined;
   1.118 +    if (strcmp(rating, "cannot_decrypt") == 0)
   1.119 +        return PEP_rating_cannot_decrypt;
   1.120 +    if (strcmp(rating, "have_no_key") == 0)
   1.121 +        return PEP_rating_have_no_key;
   1.122 +    if (strcmp(rating, "unencrypted") == 0)
   1.123 +        return PEP_rating_unencrypted;
   1.124 +    if (strcmp(rating, "unencrypted_for_some") == 0)
   1.125 +        return PEP_rating_unencrypted_for_some;
   1.126 +    if (strcmp(rating, "unreliable") == 0)
   1.127 +        return PEP_rating_unreliable;
   1.128 +    if (strcmp(rating, "reliable") == 0)
   1.129 +        return PEP_rating_reliable;
   1.130 +    if (strcmp(rating, "trusted") == 0)
   1.131 +        return PEP_rating_trusted;
   1.132 +    if (strcmp(rating, "trusted_and_anonymized") == 0)
   1.133 +        return PEP_rating_trusted_and_anonymized;
   1.134 +    if (strcmp(rating, "fully_anonymous") == 0)
   1.135 +        return PEP_rating_fully_anonymous;
   1.136 +    if (strcmp(rating, "mistrust") == 0)
   1.137 +        return PEP_rating_mistrust;
   1.138 +    if (strcmp(rating, "b0rken") == 0)
   1.139 +        return PEP_rating_b0rken;
   1.140 +    if (strcmp(rating, "under_attack") == 0)
   1.141 +        return PEP_rating_under_attack;
   1.142 +    return PEP_rating_undefined;
   1.143 +}
   1.144 +
   1.145 +static PEP_STATUS string_to_keylist(const char * skeylist, stringlist_t **keylist)
   1.146 +{
   1.147 +    if (skeylist == NULL || keylist == NULL)
   1.148 +        return PEP_ILLEGAL_VALUE;
   1.149 +
   1.150 +    stringlist_t *rkeylist = NULL;
   1.151 +    stringlist_t *_kcurr = NULL;
   1.152 +    const char * fpr_begin = skeylist;
   1.153 +    const char * fpr_end = NULL;
   1.154 +
   1.155 +    do {
   1.156 +        fpr_end = strstr(fpr_begin, ",");
   1.157 +        
   1.158 +        char * fpr = strndup(
   1.159 +            fpr_begin,
   1.160 +            (fpr_end == NULL) ? strlen(fpr_begin) : fpr_end - fpr_begin);
   1.161 +        
   1.162 +        if (fpr == NULL)
   1.163 +            goto enomem;
   1.164 +        
   1.165 +        _kcurr = stringlist_add(_kcurr, fpr);
   1.166 +        if (_kcurr == NULL) {
   1.167 +            free(fpr);
   1.168 +            goto enomem;
   1.169 +        }
   1.170 +        
   1.171 +        if (rkeylist == NULL)
   1.172 +            rkeylist = _kcurr;
   1.173 +        
   1.174 +        fpr_begin = fpr_end ? fpr_end + 1 : NULL;
   1.175 +        
   1.176 +    } while (fpr_begin);
   1.177 +    
   1.178 +    *keylist = rkeylist;
   1.179 +    return PEP_STATUS_OK;
   1.180 +    
   1.181 +enomem:
   1.182 +    free_stringlist(rkeylist);
   1.183 +    return PEP_OUT_OF_MEMORY;
   1.184 +}
   1.185 +
   1.186 +DYNAMIC_API PEP_STATUS re_evaluate_message_rating(
   1.187 +    PEP_SESSION session,
   1.188 +    message *msg,
   1.189 +    stringlist_t *x_keylist,
   1.190 +    PEP_rating x_enc_status,
   1.191 +    PEP_rating *rating
   1.192 +)
   1.193 +{
   1.194 +    PEP_STATUS status = PEP_STATUS_OK;
   1.195 +    stringlist_t *_keylist = x_keylist;
   1.196 +    bool must_free_keylist = false;
   1.197 +
   1.198 +    assert(session);
   1.199 +    assert(msg);
   1.200 +    assert(rating);
   1.201 +
   1.202 +    if (!(session && msg && rating))
   1.203 +        return ERROR(PEP_ILLEGAL_VALUE);
   1.204 +
   1.205 +    *rating = PEP_rating_undefined;
   1.206 +
   1.207 +    if (x_enc_status == PEP_rating_undefined){
   1.208 +        for (stringpair_list_t *i = msg->opt_fields; i && i->value ; i=i->next) {
   1.209 +            if (strcasecmp(i->value->key, "X-EncStatus") == 0){
   1.210 +                x_enc_status = string_to_rating(i->value->value);
   1.211 +                break;
   1.212 +            }
   1.213 +        }
   1.214 +    }
   1.215 +    if (x_enc_status == PEP_rating_undefined)
   1.216 +        return ERROR(PEP_ILLEGAL_VALUE);
   1.217 +
   1.218 +
   1.219 +    if (_keylist == NULL){
   1.220 +        for (stringpair_list_t *i = msg->opt_fields; i && i->value ; i=i->next) {
   1.221 +            if (strcasecmp(i->value->key, "X-KeyList") == 0){
   1.222 +                status = string_to_keylist(i->value->value, &_keylist);
   1.223 +                if (status != PEP_STATUS_OK)
   1.224 +                    GOTO(pep_error);
   1.225 +                must_free_keylist = true;
   1.226 +                break;
   1.227 +            }
   1.228 +        }
   1.229 +    }
   1.230 +    if (_keylist == NULL)
   1.231 +        return ERROR(PEP_ILLEGAL_VALUE);
   1.232 +
   1.233 +    PEP_rating _rating = x_enc_status;
   1.234 +
   1.235 +    status = amend_rating_according_to_sender_and_recipients(session,
   1.236 +                                                             &_rating,
   1.237 +                                                             msg->from,
   1.238 +                                                             _keylist);
   1.239 +    if (status == PEP_STATUS_OK)
   1.240 +        *rating = _rating;
   1.241 +    
   1.242 +pep_error:
   1.243 +    if (must_free_keylist)
   1.244 +        free_stringlist(_keylist);
   1.245 +
   1.246 +    return ERROR(status);
   1.247 +}
     2.1 --- a/src/message_api.h	Tue Jun 06 17:53:56 2017 +0200
     2.2 +++ b/src/message_api.h	Tue Jun 06 18:11:09 2017 +0200
     2.3 @@ -422,6 +422,35 @@
     2.4      const char* lang, char **words, bool full
     2.5  );
     2.6  
     2.7 +// re_evaluate_message_rating() - re-evaluate already decrypted message rating
     2.8 +//
     2.9 +//  parameters:
    2.10 +//      session (in)            session handle
    2.11 +//      msg (in)                message to get the rating for
    2.12 +//      x_keylist (in)          decrypted message recipients keys fpr
    2.13 +//      x_enc_status (in)       original rating for the decrypted message
    2.14 +//      rating (out)            rating for the message
    2.15 +//
    2.16 +//  return value:
    2.17 +//      PEP_ILLEGAL_VALUE       if decrypted message doesn't contain 
    2.18 +//                              X-EncStatus optional field and x_enc_status is 
    2.19 +//                              pEp_rating_udefined
    2.20 +//                              or if decrypted message doesn't contain 
    2.21 +//                              X-Keylist optional field and x_keylist is NULL
    2.22 +//      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
    2.23 +//
    2.24 +//  caveat:
    2.25 +//      msg->from must point to a valid pEp_identity
    2.26 +//      the ownership of msg remains with the caller
    2.27 +//	    the ownership of x_keylist remains with to the caller
    2.28 +
    2.29 +DYNAMIC_API PEP_STATUS re_evaluate_message_rating(
    2.30 +    PEP_SESSION session,
    2.31 +    message *msg,
    2.32 +    stringlist_t *x_keylist,
    2.33 +    PEP_rating x_enc_status,
    2.34 +    PEP_rating *rating
    2.35 +);
    2.36  #ifdef __cplusplus
    2.37  }
    2.38  #endif
     3.1 --- a/test/least_common_denom_color_test.cc	Tue Jun 06 17:53:56 2017 +0200
     3.2 +++ b/test/least_common_denom_color_test.cc	Tue Jun 06 18:11:09 2017 +0200
     3.3 @@ -58,7 +58,6 @@
     3.4      
     3.5      message* msg_ptr = nullptr;
     3.6      message* dest_msg = nullptr;
     3.7 -    message* final_ptr = nullptr;
     3.8      stringlist_t* keylist = nullptr;
     3.9      PEP_rating rating;
    3.10      PEP_decrypt_flags_t flags;
    3.11 @@ -66,53 +65,69 @@
    3.12      status = mime_decode_message(mailtext.c_str(), mailtext.length(), &msg_ptr);
    3.13      assert(status == PEP_STATUS_OK);
    3.14      assert(msg_ptr);
    3.15 -    final_ptr = msg_ptr;
    3.16 +
    3.17      status = decrypt_message(session, msg_ptr, &dest_msg, &keylist, &rating, &flags);
    3.18 -    final_ptr = dest_msg ? dest_msg : msg_ptr;
    3.19 -  
    3.20 -    cout << "shortmsg: " << final_ptr->shortmsg << endl << endl;
    3.21 -    cout << "longmsg: " << final_ptr->longmsg << endl << endl;
    3.22 -    cout << "longmsg_formatted: " << (final_ptr->longmsg_formatted ? final_ptr->longmsg_formatted : "(empty)") << endl << endl;
    3.23 -
    3.24 +    assert(status == PEP_STATUS_OK);
    3.25 +    assert(dest_msg);
    3.26      /* message is signed and no recip is mistrusted... */
    3.27      assert(color_from_rating(rating) == PEP_color_yellow);
    3.28  
    3.29 -    if (final_ptr == dest_msg)
    3.30 -    	free_message(dest_msg);
    3.31 -    free_message(msg_ptr);
    3.32 -    free_stringlist(keylist);
    3.33 +    cout << "shortmsg: " << dest_msg->shortmsg << endl << endl;
    3.34 +    cout << "longmsg: " << dest_msg->longmsg << endl << endl;
    3.35 +    cout << "longmsg_formatted: " << (dest_msg->longmsg_formatted ? dest_msg->longmsg_formatted : "(empty)") << endl << endl;
    3.36 +
    3.37 +    PEP_rating decrypt_rating = rating;
    3.38 +    
    3.39 +    /* re-evaluate rating, counting on optional fields */
    3.40 +    status = re_evaluate_message_rating(session, dest_msg, NULL, PEP_rating_undefined, &rating);
    3.41 +    assert(status == PEP_STATUS_OK);
    3.42 +    assert(color_from_rating(rating) == PEP_color_yellow);
    3.43 +
    3.44 +    /* re-evaluate rating, without optional fields */
    3.45 +    status = re_evaluate_message_rating(session, dest_msg, keylist, decrypt_rating, &rating);
    3.46 +    assert(status == PEP_STATUS_OK);
    3.47 +    assert(color_from_rating(rating) == PEP_color_yellow);
    3.48  
    3.49      /* Ok, now mistrust one recip */
    3.50      key_mistrusted(session, recip2);
    3.51 +
    3.52 +    /* re-evaluate rating, counting on optional fields */
    3.53 +    status = re_evaluate_message_rating(session, dest_msg, NULL, PEP_rating_undefined, &rating);
    3.54 +    assert(status == PEP_STATUS_OK);
    3.55 +    assert(color_from_rating(rating) == PEP_color_red);
    3.56 +
    3.57 +    /* re-evaluate rating, without optional fields */
    3.58 +    status = re_evaluate_message_rating(session, dest_msg, keylist, decrypt_rating, &rating);
    3.59 +    assert(status == PEP_STATUS_OK);
    3.60 +    assert(color_from_rating(rating) == PEP_color_red);
    3.61 +
    3.62 +    free_message(dest_msg);
    3.63 +    free_message(msg_ptr);
    3.64 +    free_stringlist(keylist);
    3.65      
    3.66      msg_ptr = nullptr;
    3.67      dest_msg = nullptr;
    3.68 -    final_ptr = nullptr;
    3.69      keylist = nullptr;
    3.70      rating = PEP_rating_unreliable;
    3.71  
    3.72      status = mime_decode_message(mailtext.c_str(), mailtext.length(), &msg_ptr);
    3.73      assert(status == PEP_STATUS_OK);
    3.74      assert(msg_ptr);
    3.75 -    final_ptr = msg_ptr;
    3.76      status = decrypt_message(session, msg_ptr, &dest_msg, &keylist, &rating, &flags);
    3.77 -    final_ptr = dest_msg ? dest_msg : msg_ptr;
    3.78    
    3.79 -    cout << "shortmsg: " << final_ptr->shortmsg << endl << endl;
    3.80 -    cout << "longmsg: " << final_ptr->longmsg << endl << endl;
    3.81 -    cout << "longmsg_formatted: " << (final_ptr->longmsg_formatted ? final_ptr->longmsg_formatted : "(empty)") << endl << endl;
    3.82 +    cout << "shortmsg: " << dest_msg->shortmsg << endl << endl;
    3.83 +    cout << "longmsg: " << dest_msg->longmsg << endl << endl;
    3.84 +    cout << "longmsg_formatted: " << (dest_msg->longmsg_formatted ? dest_msg->longmsg_formatted : "(empty)") << endl << endl;
    3.85  
    3.86      /* message is signed and no recip is mistrusted... */
    3.87      assert(color_from_rating(rating) == PEP_color_red);
    3.88  
    3.89 -    if (final_ptr == dest_msg)
    3.90 -    	free_message(dest_msg);
    3.91 +    free_message(dest_msg);
    3.92      free_message(msg_ptr);
    3.93      free_stringlist(keylist);
    3.94  
    3.95      msg_ptr = nullptr;
    3.96      dest_msg = nullptr;
    3.97 -    final_ptr = nullptr;
    3.98      keylist = nullptr;
    3.99      rating = PEP_rating_unreliable;
   3.100