Browse Source

message struct: add rating field

Add the new rating field to the ASN.1 representation as well (I am about to
discover, in a forthcoming commit, that that is in fact a stupid decision).

Move the rating enum definition from message_api.h to pEpEngine.h in order to
make it accessible from message.h .  This is temporary anyway: the new rating
engine is coming.

Remove the rating output parameter from decrypt_message.  This will temporarily
break *everything*!
ENGINE-959
Luca Saiu 3 months ago
parent
commit
aacb352faa
7 changed files with 263 additions and 54 deletions
  1. +8
    -2
      asn.1/message.asn1
  2. +133
    -0
      src/map_asn1.c
  3. +4
    -0
      src/message.c
  4. +1
    -0
      src/message.h
  5. +49
    -13
      src/message_api.c
  6. +34
    -39
      src/message_api.h
  7. +34
    -0
      src/pEpEngine.h

+ 8
- 2
asn.1/message.asn1 View File

@ -17,7 +17,7 @@ BEGIN
EXPORTS ASN1Message;
IMPORTS
PString, PStringList, Identity, IdentityList, PStringPairList, Hash
PString, PStringList, Identity, IdentityList, PStringPairList, Hash, Rating
FROM PEP { iso(1) org(3) dod(6) internet(1) private(4)
enterprise(1) pEp(47878) basic(0) };
@ -86,8 +86,14 @@ ASN1Message ::= SEQUENCE {
longmsg-formatted UTF8String OPTIONAL, -- UTF-8 string of long message
-- (formatted)
attachments PBlobList OPTIONAL -- blobs with attachments
attachments PBlobList OPTIONAL, -- blobs with attachments
-- internal: rawmsg
-- This field is optional only for back-compatibility. FIXME: no, not really: I should support a case for PEP_rating_undefined, which is not handled in the ASN.1 encoding. This creates an ambiguity: the field could be omitted because there is no rating or because the other endpoint uses an older version
rating Rating OPTIONAL, -- message rating
-- Space for future extensions.
...
}
END


+ 133
- 0
src/map_asn1.c View File

@ -617,6 +617,122 @@ enomem:
return NULL;
}
/**
* <!-- ASN1Rating_from_rating() -->
*
* @brief Convert rating from its default representation into ASN.1
*
* @param msg[in] rating to convert
* @param result[out] the equivalent of in in the other encoding
*
* @retval PEP_STATUS_OK conversion successful
* @retval PEP_ILLEGAL_VALUE the in argument was PEP_rating_undefined
*
* @warning fail on PEP_rating_undefined , which has no equivalent in the
* ASN.1 version
* @warning The API is different from the similarly named ASN1Message_from_message
* because of the incomplete mapping. This should not be very error-prone
* in practice, because this function has two arguments and using it
* incorrectly will lead to compile-time errors.
*
*/
static PEP_STATUS ASN1Rating_from_rating(
PEP_rating in,
e_Rating *out
)
{
#define CASE(pep_case, asn1_case) \
case pep_case: *out = (asn1_case); return PEP_STATUS_OK;
/* This must be kept in sync with the enum _PEP_rating definition in
pEpEngin.h and the machine-generated enum Rating definition in
asn.1/Rating.h : */
switch (in) {
case PEP_rating_undefined: return PEP_ILLEGAL_VALUE;
// no color
CASE (PEP_rating_cannot_decrypt, Rating_cannot_decrypt)
CASE (PEP_rating_have_no_key, Rating_have_no_key)
CASE (PEP_rating_unencrypted, Rating_unencrypted)
CASE (PEP_rating_unreliable, Rating_unreliable)
CASE (PEP_rating_b0rken, Rating_b0rken)
// yellow
CASE (PEP_rating_reliable, Rating_reliable)
// green
CASE (PEP_rating_trusted, Rating_trusted)
CASE (PEP_rating_trusted_and_anonymized, Rating_trusted_and_anonymized)
CASE (PEP_rating_fully_anonymous, Rating_fully_anonymous)
// red
CASE (PEP_rating_mistrust, Rating_mistrust)
CASE (PEP_rating_under_attack, Rating_under_attack)
default:
assert(0);
}
#undef CASE
}
/**
* <!-- ASN1Rating_to_rating() -->
*
* @brief Convert rating from ASN.1 into the default pEp representation
*
* @param msg[in] pointer to a rating to convert, or NULL
*
* @retval PEP_rating_undefined if the in pointer was NULL
* @retval the equivalent of in in the other encoding
*
* @warning fail on PEP_rating_undefined , which has no equivalent in the
* ASN.1 version
* @warning The API is different from the similarly named ASN1Message_from_message
* because of the mapping, which is incomplete in one direction but
* not the other.
*
*/
static PEP_rating ASN1Rating_to_rating(
Rating_t *in
)
{
#define CASE(pep_case, asn1_case) \
case asn1_case: return (pep_case);
/* This must be kept in sync with the enum _PEP_rating definition in
pEpEngin.h and the machine-generated enum Rating definition in
asn.1/Rating.h : */
if (in == NULL)
return PEP_rating_undefined;
else
switch (* in) {
// no color
CASE (PEP_rating_cannot_decrypt, Rating_cannot_decrypt)
CASE (PEP_rating_have_no_key, Rating_have_no_key)
CASE (PEP_rating_unencrypted, Rating_unencrypted)
CASE (PEP_rating_unreliable, Rating_unreliable)
CASE (PEP_rating_b0rken, Rating_b0rken)
// yellow
CASE (PEP_rating_reliable, Rating_reliable)
// green
CASE (PEP_rating_trusted, Rating_trusted)
CASE (PEP_rating_trusted_and_anonymized, Rating_trusted_and_anonymized)
CASE (PEP_rating_fully_anonymous, Rating_fully_anonymous)
// red
CASE (PEP_rating_mistrust, Rating_mistrust)
CASE (PEP_rating_under_attack, Rating_under_attack)
default:
assert(0);
}
#undef CASE
}
ASN1Message_t *ASN1Message_from_message(
message *msg,
ASN1Message_t *result,
@ -850,6 +966,21 @@ ASN1Message_t *ASN1Message_from_message(
result->attachments = bl;
}
e_Rating asn1_rating;
PEP_STATUS rating_conversion_status
= ASN1Rating_from_rating(msg->rating, & asn1_rating);
if (rating_conversion_status == PEP_ILLEGAL_VALUE)
result->rating = NULL;
else if (rating_conversion_status == PEP_STATUS_OK) {
result->rating = calloc(1, sizeof (e_Rating));
assert(result->rating);
if (! result->rating)
goto enomem;
* result->rating = asn1_rating;
}
else
assert(0);
return result;
enomem:
@ -1080,6 +1211,8 @@ message *ASN1Message_to_message(
result->attachments = a;
}
result->rating = ASN1Rating_to_rating(msg->rating);
return result;
enomem:


+ 4
- 0
src/message.c View File

@ -197,6 +197,8 @@ DYNAMIC_API message * message_dup(const message *src)
msg->enc_format = src->enc_format;
msg->rating = src->rating;
return msg;
enomem:
@ -209,11 +211,13 @@ DYNAMIC_API void message_transfer(message* dst, message *src)
assert(dst);
assert(src);
/* Scalars */
dst->dir = src->dir;
dst->rawmsg_ref = src->rawmsg_ref;
dst->rawmsg_size = src->rawmsg_size;
dst->refering_msg_ref = src->refering_msg_ref;
dst->enc_format = src->enc_format;
dst->rating = src->rating;
/* Strings */
free(dst->id);


+ 1
- 0
src/message.h View File

@ -87,6 +87,7 @@ typedef struct _message {
char* _sender_fpr; // INTERNAL USE ONLY - fingerprint of
// sending signer.
// (read_only to the outside)
PEP_rating rating; // message rating
} message;
/**


+ 49
- 13
src/message_api.c View File

@ -24,6 +24,8 @@
#include "group.h"
#include "group_internal.h"
#include "status_to_string.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
@ -108,6 +110,8 @@ static char * keylist_to_string(const stringlist_t *keylist)
static const char * rating_to_string(PEP_rating rating)
{
switch (rating) {
case PEP_rating_undefined:
return "undefined";
case PEP_rating_cannot_decrypt:
return "cannot_decrypt";
case PEP_rating_have_no_key:
@ -131,7 +135,7 @@ static const char * rating_to_string(PEP_rating rating)
case PEP_rating_under_attack:
return "under_attack";
default:
return "undefined";
assert(0);
}
}
@ -404,6 +408,8 @@ void decorate_message(
replace_opt_field(msg, "X-KeyList", _keylist, clobber);
free(_keylist);
}
msg->rating = rating;
}
/**
@ -2682,6 +2688,9 @@ DYNAMIC_API PEP_STATUS encrypt_message(
if (src->dir == PEP_dir_incoming)
return PEP_ILLEGAL_VALUE;
// Reset the message rating before doing anything...
src->rating = PEP_rating_undefined;
determine_encryption_format(src);
// TODO: change this for multi-encryption in message format 2.0
if (src->enc_format != PEP_enc_none)
@ -2944,7 +2953,16 @@ DYNAMIC_API PEP_STATUS encrypt_message(
}
if (msg) {
decorate_message(session, msg, PEP_rating_undefined, NULL, true, true);
/* Obtain the message rating... */
PEP_rating rating;
status = sent_message_rating(session, msg, & rating);
if (status == PEP_OUT_OF_MEMORY)
goto enomem;
else if (status != PEP_STATUS_OK)
goto pEp_error;
/* ...And store it into the message along with the other decorations. */
decorate_message(session, msg, rating, NULL, true, true);
if (_src->id) {
msg->id = strdup(_src->id);
assert(msg->id);
@ -4990,7 +5008,9 @@ static const char* process_key_claim(message* src,
// There are times when we don't want errors during calls to be fatal. Once any action is taken on that
// status, if we are going to continue processing and not bail from the message, the status needs to be reset
// to PEP_STATUS_OK, or, alternately, we need to be using a temp status variable.
//
// This internal function does *not* set the rating field of the message: that
// part of the job is within decrypt_message.
static PEP_STATUS _decrypt_message(
PEP_SESSION session,
message *src,
@ -6264,7 +6284,6 @@ DYNAMIC_API PEP_STATUS decrypt_message(
message *src,
message **dst,
stringlist_t **keylist,
PEP_rating *rating,
PEP_decrypt_flags_t *flags
)
{
@ -6272,24 +6291,32 @@ DYNAMIC_API PEP_STATUS decrypt_message(
assert(src);
assert(dst);
assert(keylist);
assert(rating);
assert(flags);
if (!(session && src && dst && keylist && rating && flags))
if (!(session && src && dst && keylist && flags))
return PEP_ILLEGAL_VALUE;
if (!(*flags & PEP_decrypt_flag_untrusted_server))
*keylist = NULL;
// Reset the message rating before doing anything. We will compute a new
// value, that _decrypt_message sets as an output parameter.
src->rating = PEP_rating_undefined;
PEP_rating rating = PEP_rating_undefined;
stringlist_t* imported_key_fprs = NULL;
uint64_t changed_key_bitvec = 0;
PEP_STATUS status = _decrypt_message(session, src, dst, keylist,
rating, flags, NULL,
&rating, flags, NULL,
&imported_key_fprs, &changed_key_bitvec);
message *msg = *dst ? *dst : src;
/* Set the rating field of the message. Notice that even in case of non-ok
result status the value of this field may be meaningful. */
msg->rating = rating;
// Ok, now we check to see if it was an administrative message. We do this by testing base_extract for success
// with protocol families.
if (msg && msg->from) {
@ -6303,10 +6330,10 @@ DYNAMIC_API PEP_STATUS decrypt_message(
tmp_status = base_extract_message(session, msg, BASE_SYNC, &size, &data, &sender_fpr);
if (!tmp_status && size && data) {
if (sender_fpr)
signal_Sync_message(session, *rating, data, size, msg->from, sender_fpr);
signal_Sync_message(session, rating, data, size, msg->from, sender_fpr);
// FIXME: this must be changed to sender_fpr
else if (*keylist)
signal_Sync_message(session, *rating, data, size, msg->from, (*keylist)->value);
signal_Sync_message(session, rating, data, size, msg->from, (*keylist)->value);
}
}
if (tmp_status != PEP_STATUS_OK) {
@ -6324,7 +6351,7 @@ DYNAMIC_API PEP_STATUS decrypt_message(
PEP_STATUS tmpstatus = base_extract_message(session, msg, BASE_DISTRIBUTION, &size, &data,
&sender_fpr);
if (!tmpstatus && size && data) {
process_Distribution_message(session, msg, *rating, data, size, sender_fpr);
process_Distribution_message(session, msg, rating, data, size, sender_fpr);
}
}
}
@ -6352,7 +6379,7 @@ DYNAMIC_API PEP_STATUS decrypt_message(
// // if ((!event_sender_fpr) && *keylist)
// // event_sender_fpr = (*keylist)->value;
// if (event_sender_fpr)
// signal_Sync_message(session, *rating, data, size, msg->from, event_sender_fpr);
// signal_Sync_message(session, rating, data, size, msg->from, event_sender_fpr);
// }
// free(sender_fpr);
// }
@ -6480,6 +6507,16 @@ static void _max_comm_type_from_identity_list_preview(
}
}
DYNAMIC_API PEP_STATUS sent_message_rating(
PEP_SESSION session,
message *msg,
PEP_rating *rating
)
{
// FIXME: this is a stub. See ENGINE-847.
return outgoing_message_rating (session, msg, rating);
}
DYNAMIC_API PEP_STATUS outgoing_message_rating(
PEP_SESSION session,
message *msg,
@ -6947,9 +6984,8 @@ DYNAMIC_API PEP_STATUS get_message_trustwords(
// Message is to be decrypted
message *dst = NULL;
stringlist_t *_keylist = keylist;
PEP_rating rating;
PEP_decrypt_flags_t flags;
status = decrypt_message( session, msg, &dst, &_keylist, &rating, &flags);
status = decrypt_message( session, msg, &dst, &_keylist, &flags);
if (status != PEP_STATUS_OK) {
free_message(dst);


+ 34
- 39
src/message_api.h View File

@ -70,9 +70,11 @@ typedef enum _message_wrap_type {
* @brief Encrypt message in memory
*
* @param[in] session session handle
* @param[in,out] src message to encrypt - usually in-only, but can be
* in-out for unencrypted messages; in that case,
* we may attach the key and decorate the message
* @param[in,out] src message to encrypt - usually in-only except for
* the rating field, but can be in-out for
* unencrypted messages; in that case, we may
* attach the key and decorate the message.
* In any case, reset the rating.
* @param[in] extra extra keys for encryption
* @param[out] dst pointer to new encrypted message or NULL if no
* encryption could take place
@ -193,39 +195,6 @@ DYNAMIC_API PEP_STATUS encrypt_message_for_self(
PEP_encrypt_flags_t flags
);
/**
* @enum PEP_rating
*
* @brief TODO
*
*/
typedef enum _PEP_rating {
PEP_rating_undefined = 0,
// no color
PEP_rating_cannot_decrypt = 1,
PEP_rating_have_no_key = 2,
PEP_rating_unencrypted = 3,
PEP_rating_unreliable = 5,
PEP_rating_b0rken = -2,
// yellow
PEP_rating_reliable = 6,
// green
PEP_rating_trusted = 7,
PEP_rating_trusted_and_anonymized = 8,
PEP_rating_fully_anonymous = 9,
// red
PEP_rating_mistrust = -1,
PEP_rating_under_attack = -3
} PEP_rating;
/**
* @enum PEP_color
@ -278,7 +247,9 @@ typedef unsigned int PEP_decrypt_flags_t;
* @brief Decrypt message in memory
*
* @param[in] session session handle
* @param[in,out] src message to decrypt - see warning about identities below
* @param[in,out] src message to decrypt - see warning about identities below.
* the rating field of src (instead of dst) is updated
* in case encryption fails.
* @param[out] dst pointer to new decrypted message or NULL on failure
* @param[in,out] keylist in: stringlist with additional keyids for reencryption if needed
* (will be freed and replaced with output keylist)
@ -286,7 +257,6 @@ typedef unsigned int PEP_decrypt_flags_t;
* first key is signer, additional keys are the ones it was encrypted
* to. Only signer and whichever of the user's keys was used are
* reliable
* @param[out] rating rating for the message
* @param[in,out] flags flags to signal special decryption features
*
* @retval <ERROR> any error status
@ -350,7 +320,6 @@ DYNAMIC_API PEP_STATUS decrypt_message(
message *src,
message **dst,
stringlist_t **keylist,
PEP_rating *rating,
PEP_decrypt_flags_t *flags
);
@ -384,6 +353,32 @@ DYNAMIC_API PEP_STATUS own_message_private_key_details(
);
/**
* <!-- sent_message_rating() -->
*
* @brief Get rating for a sent message
*
* @param[in] session session handle
* @param[in] msg message to get the rating for
* @param[out] rating rating for the message
*
*
* @retval PEP_STATUS_OK
* @retval PEP_ILLEGAL_VALUE illegal parameter values
*
* @warning msg->from must point to a valid pEp_identity
* msg->dir must be PEP_dir_outgoing
* the ownership of msg remains with the caller
*
*/
DYNAMIC_API PEP_STATUS sent_message_rating(
PEP_SESSION session,
message *msg,
PEP_rating *rating
);
// FIXME: the current implementation is a stub, until ENGINE-847 is ready.
/**
* <!-- outgoing_message_rating() -->
*


+ 34
- 0
src/pEpEngine.h View File

@ -214,6 +214,40 @@ typedef enum _PEP_enc_format {
PEP_enc_auto = 255 // figure out automatically where possible
} PEP_enc_format;
/**
* @enum PEP_rating
*
* @brief TODO
*
*/
typedef enum _PEP_rating {
PEP_rating_undefined = 0,
// no color
PEP_rating_cannot_decrypt = 1,
PEP_rating_have_no_key = 2,
PEP_rating_unencrypted = 3,
PEP_rating_unreliable = 5,
PEP_rating_b0rken = -2,
// yellow
PEP_rating_reliable = 6,
// green
PEP_rating_trusted = 7,
PEP_rating_trusted_and_anonymized = 8,
PEP_rating_fully_anonymous = 9,
// red
PEP_rating_mistrust = -1,
PEP_rating_under_attack = -3
} PEP_rating;
/**
* <!-- messageToSend() -->


Loading…
Cancel
Save