1.1 --- a/src/baseprotocol.c Thu Nov 22 13:23:26 2018 +0100
1.2 +++ b/src/baseprotocol.c Thu Nov 22 13:24:28 2018 +0100
1.3 @@ -5,12 +5,15 @@
1.4 #include "message_api.h"
1.5
1.6 PEP_STATUS base_decorate_message(
1.7 + PEP_SESSION session,
1.8 message *msg,
1.9 char *payload,
1.10 size_t size,
1.11 char *fpr
1.12 )
1.13 {
1.14 + PEP_STATUS status = PEP_STATUS_OK;
1.15 +
1.16 assert(msg);
1.17 assert(payload);
1.18 assert(size);
1.19 @@ -24,17 +27,31 @@
1.20 goto enomem;
1.21
1.22 if (fpr) {
1.23 - // add signature
1.24 + char *sign;
1.25 + size_t sign_size;
1.26 + status = sign_only(session, payload, size, fpr, &sign, &sign_size);
1.27 + if (status)
1.28 + goto error;
1.29 +
1.30 + assert(sign && sign_size);
1.31 +
1.32 + bl = bloblist_add(bl, sign, sign_size,
1.33 + "application/pEp.sign", "ignore_this_attachment.pEp");
1.34 + if (!bl)
1.35 + goto enomem;
1.36 }
1.37
1.38 - msg->attachments = bl;
1.39 return PEP_STATUS_OK;
1.40
1.41 enomem:
1.42 - return PEP_OUT_OF_MEMORY;
1.43 + status = PEP_OUT_OF_MEMORY;
1.44 +
1.45 +error:
1.46 + return status;
1.47 }
1.48
1.49 PEP_STATUS base_prepare_message(
1.50 + PEP_SESSION session,
1.51 const pEp_identity *me,
1.52 const pEp_identity *partner,
1.53 char *payload,
1.54 @@ -81,7 +98,7 @@
1.55 if (!msg->longmsg)
1.56 goto enomem;
1.57
1.58 - status = base_decorate_message(msg, payload, size, fpr);
1.59 + status = base_decorate_message(session, msg, payload, size, fpr);
1.60 if (status == PEP_STATUS_OK)
1.61 *result = msg;
1.62 return status;
1.63 @@ -91,25 +108,77 @@
1.64 return PEP_OUT_OF_MEMORY;
1.65 }
1.66
1.67 -PEP_STATUS base_extract_message(message *msg, size_t *size, const char **payload)
1.68 +PEP_STATUS base_extract_message(
1.69 + PEP_SESSION session,
1.70 + message *msg,
1.71 + size_t *size,
1.72 + const char **payload,
1.73 + char **fpr
1.74 + )
1.75 {
1.76 PEP_STATUS status = PEP_STATUS_OK;
1.77
1.78 - assert(msg && size && payload);
1.79 - if (!(msg && size && payload))
1.80 + assert(session && msg && size && payload && fpr);
1.81 + if (!(session && msg && size && payload && fpr))
1.82 return PEP_ILLEGAL_VALUE;
1.83
1.84 *size = 0;
1.85 *payload = NULL;
1.86
1.87 + const char *_payload = NULL;
1.88 + size_t _payload_size = 0;
1.89 + const char *_sign = NULL;
1.90 + size_t _sign_size = 0;
1.91 + stringlist_t *keylist = NULL;
1.92 +
1.93 for (bloblist_t *bl = msg->attachments; bl ; bl = bl->next) {
1.94 if (bl->mime_type && strcasecmp(bl->mime_type, "application/pEp.sync") == 0) {
1.95 - *size = bl->size;
1.96 - *payload = bl->value;
1.97 - break;
1.98 + if (!_payload) {
1.99 + _payload = bl->value;
1.100 + _payload_size = bl->size;
1.101 + }
1.102 + else {
1.103 + status = PEP_DECRYPT_WRONG_FORMAT;
1.104 + goto the_end;
1.105 + }
1.106 + }
1.107 + else if (bl->mime_type && strcasecmp(bl->mime_type, "application/pEp.sign") == 0) {
1.108 + if (!_sign) {
1.109 + _sign = bl->value;
1.110 + _sign_size = bl->size;
1.111 + }
1.112 + else {
1.113 + status = PEP_DECRYPT_WRONG_FORMAT;
1.114 + goto the_end;
1.115 + }
1.116 + }
1.117 + }
1.118 +
1.119 + if (!(_payload && _payload_size))
1.120 + goto the_end;
1.121 +
1.122 + if (_sign) {
1.123 + status = verify_text(session, _payload, _payload_size, _sign, _sign_size, &keylist);
1.124 + if (status != PEP_VERIFIED || !keylist || !keylist->value) {
1.125 + // signature invalid or does not match; ignore sync message
1.126 + status = PEP_STATUS_OK;
1.127 + goto the_end;
1.128 + }
1.129 +
1.130 + char *_fpr = strdup(keylist->value);
1.131 + assert(_fpr);
1.132 + if (!_fpr) {
1.133 + status = PEP_OUT_OF_MEMORY;
1.134 + goto the_end;
1.135 }
1.136 }
1.137
1.138 + *size = _payload_size;
1.139 + *payload = _payload;
1.140 + status = PEP_STATUS_OK;
1.141 +
1.142 +the_end:
1.143 + free_stringlist(keylist);
1.144 return status;
1.145 }
1.146
2.1 --- a/src/baseprotocol.h Thu Nov 22 13:23:26 2018 +0100
2.2 +++ b/src/baseprotocol.h Thu Nov 22 13:24:28 2018 +0100
2.3 @@ -13,6 +13,7 @@
2.4 // base_decorate_message() - decorate a message with payload
2.5 //
2.6 // parameters:
2.7 +// session (in) session handle
2.8 // msg (inout) message to decorate
2.9 // payload (in) payload to send
2.10 // size (in) size of payload
2.11 @@ -26,6 +27,7 @@
2.12 // the ownership of the msg remains with the caller
2.13
2.14 PEP_STATUS base_decorate_message(
2.15 + PEP_SESSION session,
2.16 message *msg,
2.17 char *payload,
2.18 size_t size,
2.19 @@ -36,6 +38,7 @@
2.20 // base_prepare_message() - prepare a sync message with payload
2.21 //
2.22 // parameters:
2.23 +// session (in) session handle
2.24 // me (in) identity to use for the sender
2.25 // partner (in) identity to use for the receiver
2.26 // payload (in) payload to send
2.27 @@ -51,6 +54,7 @@
2.28 // the ownership of the result goes to the caller
2.29
2.30 PEP_STATUS base_prepare_message(
2.31 + PEP_SESSION session,
2.32 const pEp_identity *me,
2.33 const pEp_identity *partner,
2.34 char *payload,
2.35 @@ -63,9 +67,12 @@
2.36 // base_extract_message() - extract a sync message from a pEp message
2.37 //
2.38 // parameters:
2.39 +// session (in) session handle
2.40 // msg (in) message to analyze
2.41 // size (out) size of extracted payload or 0 if not found
2.42 // payload (out) extraced payload
2.43 +// fpr (out) if message was correctly signed then fpr of signature's
2.44 +// key, otherwise NULL
2.45 //
2.46 // returns:
2.47 // PEP_STATUS_OK and payload == NULL if no sync message
2.48 @@ -74,8 +81,15 @@
2.49 //
2.50 // caveat:
2.51 // payload may point to msg attachment, the ownership does not change
2.52 +// if fpr != NULL the ownership goes to the caller
2.53
2.54 -PEP_STATUS base_extract_message(message *msg, size_t *size, const char **payload);
2.55 +PEP_STATUS base_extract_message(
2.56 + PEP_SESSION session,
2.57 + message *msg,
2.58 + size_t *size,
2.59 + const char **payload,
2.60 + char **fpr
2.61 + );
2.62
2.63
2.64 #ifdef __cplusplus
3.1 --- a/src/message_api.c Thu Nov 22 13:23:26 2018 +0100
3.2 +++ b/src/message_api.c Thu Nov 22 13:24:28 2018 +0100
3.3 @@ -3749,16 +3749,29 @@
3.4 if (!(session && src && dst && keylist && rating && flags))
3.5 return PEP_ILLEGAL_VALUE;
3.6
3.7 + *keylist = NULL;
3.8 PEP_STATUS status = _decrypt_message(session, src, dst, keylist, rating, flags, NULL);
3.9
3.10 message *msg = *dst ? *dst : src;
3.11
3.12 - if (session->inject_sync_event && msg) {
3.13 + if (session->inject_sync_event && msg && msg->from) {
3.14 size_t size;
3.15 const char *data;
3.16 - status = base_extract_message(msg, &size, &data);
3.17 - if (size && data)
3.18 - signal_Sync_message(session, *rating, data, size);
3.19 + char *sync_fpr = NULL;
3.20 + status = base_extract_message(session, msg, &size, &data, &sync_fpr);
3.21 + if (!status && size && data) {
3.22 + pEp_identity *_from = identity_dup(msg->from);
3.23 + if (!_from) {
3.24 + free_message(*dst);
3.25 + *dst = NULL;
3.26 + free_stringlist(*keylist);
3.27 + *keylist = NULL;
3.28 + return PEP_OUT_OF_MEMORY;
3.29 + }
3.30 + memcpy(&session->sync_state.common.from, _from, sizeof(pEp_identity));
3.31 + signal_Sync_message(session, *rating, data, size, sync_fpr);
3.32 + }
3.33 + free(sync_fpr);
3.34 }
3.35
3.36 return status;
5.1 --- a/sync/gen_statemachine.ysl2 Thu Nov 22 13:23:26 2018 +0100
5.2 +++ b/sync/gen_statemachine.ysl2 Thu Nov 22 13:24:28 2018 +0100
5.3 @@ -197,7 +197,8 @@
5.4 PEP_SESSION session,
5.5 PEP_rating rating,
5.6 const char *data,
5.7 - size_t size
5.8 + size_t size,
5.9 + const char *fpr
5.10 );
5.11
5.12 #ifdef __cplusplus
5.13 @@ -310,7 +311,8 @@
5.14 PEP_SESSION session,
5.15 PEP_rating rating,
5.16 const char *data,
5.17 - size_t size
5.18 + size_t size,
5.19 + const char *fpr
5.20 )
5.21 {
5.22 assert(session && data && size);
5.23 @@ -337,6 +339,17 @@
5.24 goto the_end;
5.25 }
5.26
5.27 + if (fpr) {
5.28 + if (session->«yml:lcase(@name)»_state.common.from->fpr)
5.29 + free(session->«yml:lcase(@name)»_state.common.from->fpr);
5.30 + session->«yml:lcase(@name)»_state.common.from->fpr = strdup(fpr);
5.31 + assert(session->«yml:lcase(@name)»_state.common.from->fpr);
5.32 + if (!session->«yml:lcase(@name)»_state.common.from->fpr) {
5.33 + status = PEP_OUT_OF_MEMORY;
5.34 + goto the_end;
5.35 + }
5.36 + }
5.37 +
5.38 ev = new_«@name»_event(fsm, event, msg);
5.39 if (!ev) {
5.40 status = PEP_OUT_OF_MEMORY;
5.41 @@ -349,6 +362,7 @@
5.42 status = PEP_STATEMACHINE_ERROR;
5.43 goto the_end;
5.44 }
5.45 +
5.46 return PEP_STATUS_OK;
5.47
5.48 the_end:
5.49 @@ -455,6 +469,7 @@
5.50 switch (message_type) {
5.51 `` for "fsm/message[@security='unencrypted']" |>>> case «../@name»__payload_PR_«yml:mixedCase(@name)»:
5.52 status = base_prepare_message(
5.53 + session,
5.54 li->ident,
5.55 li->ident,
5.56 _data,
5.57 @@ -472,6 +487,7 @@
5.58
5.59 default:
5.60 status = base_prepare_message(
5.61 + session,
5.62 li->ident,
5.63 li->ident,
5.64 _data,
5.65 @@ -609,10 +625,14 @@
5.66 switch (event) {
5.67 ||
5.68 if "message[@security='unencrypted']" {
5.69 - | // these messages are going untested
5.70 + | // these messages require a detached signature
5.71 for "message[@security='unencrypted']"
5.72 |>> case «../@name»__payload_PR_«yml:mixedCase(@name)»:
5.73 ||
5.74 + if (!fpr) {
5.75 + status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
5.76 + goto the_end;
5.77 + }
5.78 break;
5.79
5.80 ||
5.81 @@ -621,7 +641,7 @@
5.82 ||
5.83 // these messages must arrive encrypted
5.84 `` for "message[@security='untrusted']" |>> case «../@name»__payload_PR_«yml:mixedCase(@name)»:
5.85 - if (rating < PEP_rating_reliable) {
5.86 + if (fpr || rating < PEP_rating_reliable) {
5.87 status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
5.88 goto the_end;
5.89 }
5.90 @@ -632,7 +652,7 @@
5.91 ||
5.92 // these messages must come through a trusted channel
5.93 `` for "message[@security='trusted']" |>> case «ancestor::fsm/@name»__payload_PR_«yml:mixedCase(@name)»:
5.94 - if (rating < PEP_rating_trusted) {
5.95 + if (fpr || rating < PEP_rating_trusted) {
5.96 status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
5.97 goto the_end;
5.98 }