Browse Source

KEYSYNC: Added arbitrary hard coded sync message expiry (10m), and made special case when receiving groupKeys message so that they are not consumed giving a chance to other devices in the group to receive it as well.

doc_update_sequoia
Edouard Tisserant 6 years ago
parent
commit
7dd1fd4469
4 changed files with 174 additions and 55 deletions
  1. +2
    -1
      asn.1/devicegroup.asn1
  2. +32
    -0
      src/map_asn1.c
  3. +39
    -0
      src/map_asn1.h
  4. +101
    -54
      src/sync_impl.c

+ 2
- 1
asn.1/devicegroup.asn1 View File

@ -27,8 +27,9 @@ DeviceGroup-Protocol ::= SEQUENCE {
sequence INTEGER, /* always increases */
me Identity, /* identity of the sender */
state INTEGER, /* state the sender is in */
devicegroup BOOLEAN
devicegroup BOOLEAN,
/* signals if this message is coming from a device group member */
expiry GeneralizedTime
},
payload CHOICE {


+ 32
- 0
src/map_asn1.c View File

@ -178,3 +178,35 @@ enomem:
return NULL;
}
timestamp *GeneralizedTime_to_timestamp(GeneralizedTime_t * asntime, timestamp *result)
{
assert(asntime);
if (!asntime)
return NULL;
time_t smpltime = asn_GT2time(asntime, NULL, 0);
if (!result){
result = new_timestamp(smpltime);
}
else
gmtime_r(&smpltime, result);
return result;
}
time_t GeneralizedTime_to_time_t(GeneralizedTime_t * asntime)
{
return asn_GT2time(asntime, NULL, 0);
}
GeneralizedTime_t *timestamp_to_GeneralizedTime(timestamp * ts, GeneralizedTime_t *result)
{
assert(ts);
if (!ts)
return NULL;
GeneralizedTime_t *asntime = asn_time2GT(result, ts, 0);
return asntime;
}

+ 39
- 0
src/map_asn1.h View File

@ -4,6 +4,7 @@
#include "identity_list.h"
#include "../asn.1/Identity.h"
#include "../asn.1/IdentityList.h"
#include "../asn.1/GeneralizedTime.h"
#ifdef __cplusplus
extern "C" {
@ -74,6 +75,44 @@ IdentityList_t *IdentityList_from_identity_list(
identity_list *IdentityList_to_identity_list(IdentityList_t *list, identity_list *result);
// GeneralizedTime_to_timestamp() - convert ASN.1 GeneralizedTime to timestamp
//
// params:
// asntime (in) ASN.1 GeneralizedTime to convert
// result (inout) timestamp to update or NULL to alloc a new one
//
// return value:
// pointer to allocated timestamp
//
// caveat:
// if a new timestamp is allocated, the ownership goes to the caller
timestamp *GeneralizedTime_to_timestamp(GeneralizedTime_t * asntime, timestamp *result);
// GeneralizedTime_to_time_t() - convert ASN.1 GeneralizedTime to time_t
//
// params:
// asntime (in) ASN.1 GeneralizedTime to convert
//
// return value:
// resulting time_t
//
time_t GeneralizedTime_to_time_t(GeneralizedTime_t * asntime);
// timestamp_GeneralizedTime_to() - convert ASN.1 timestamp to GeneralizedTime
//
// params:
// ts (in) timestam to convert
// result (inout) GeneralizedTime_t to update or NULL to alloc a new one
//
// return value:
// pointer to allocated ASN.1 GeneralizedTime
//
// caveat:
// if a new GeneralizedTime is allocated, the ownership goes to the caller
GeneralizedTime_t *timestamp_to_GeneralizedTime(timestamp * ts, GeneralizedTime_t *result);
#ifdef __cplusplus
}


+ 101
- 54
src/sync_impl.c View File

@ -175,6 +175,9 @@ PEP_STATUS receive_DeviceState_msg(
return PEP_ILLEGAL_VALUE;
bool found = false;
bool expired = false;
bool discarded = false;
bool force_keep_msg = false;
bloblist_t *last = NULL;
for (bloblist_t *bl = src->attachments; bl && bl->value; bl = bl->next) {
@ -183,9 +186,9 @@ PEP_STATUS receive_DeviceState_msg(
DeviceGroup_Protocol_t *msg = NULL;
uper_decode_complete(NULL, &asn_DEF_DeviceGroup_Protocol, (void **)
&msg, bl->value, bl->size);
if (msg) {
int32_t value = (int32_t) msg->header.sequence;
char *user_id = strndup((char *) msg->header.me.user_id->buf,
msg->header.me.user_id->size);
assert(user_id);
@ -194,79 +197,105 @@ PEP_STATUS receive_DeviceState_msg(
return PEP_OUT_OF_MEMORY;
}
switch (msg->payload.present) {
// HandshakeRequest needs encryption
case DeviceGroup_Protocol__payload_PR_handshakeRequest:
if (rating < PEP_rating_reliable ||
strncmp(session->sync_uuid,
(const char *)msg->payload.choice.handshakeRequest.partner.user_id->buf,
msg->payload.choice.handshakeRequest.partner.user_id->size) != 0){
ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
free(user_id);
return PEP_MESSAGE_DISCARDED;
}
break;
// accepting GroupKeys needs encryption and trust
case DeviceGroup_Protocol__payload_PR_groupKeys:
if (!keylist || rating < PEP_rating_reliable ||
strncmp(session->sync_uuid,
(const char *)msg->payload.choice.groupKeys.partner.user_id->buf,
msg->payload.choice.groupKeys.partner.user_id->size) != 0){
ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
free(user_id);
return PEP_MESSAGE_DISCARDED;
}
// check trust of identity with the right user_id
pEp_identity *_from = new_identity(src->from->address,
keylist->value,
user_id,
src->from->username);
if (_from == NULL){
free(user_id);
ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
return PEP_OUT_OF_MEMORY;
}
PEP_rating this_user_id_rating = PEP_rating_undefined;
identity_rating(session, _from, &this_user_id_rating);
free_identity(_from);
if (this_user_id_rating < PEP_rating_trusted ) {
ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
free(user_id);
return PEP_MESSAGE_DISCARDED;
}
break;
default:
break;
// check message expiry
time_t expiry = GeneralizedTime_to_time_t(&msg->header.expiry);
time_t now = time(NULL);
if(expiry != 0 && now != 0 && expiry < now){
expired = true;
goto flush;
}
int32_t value = (int32_t) msg->header.sequence;
PEP_STATUS status = sequence_value(session, (char *) user_id,
&value);
if (status == PEP_STATUS_OK) {
switch (msg->payload.present) {
// HandshakeRequest needs encryption
case DeviceGroup_Protocol__payload_PR_handshakeRequest:
if (rating < PEP_rating_reliable ||
strncmp(session->sync_uuid,
(const char *)msg->payload.choice.handshakeRequest.partner.user_id->buf,
msg->payload.choice.handshakeRequest.partner.user_id->size) != 0){
discarded = true;
goto flush;
}
break;
// accepting GroupKeys needs encryption and trust
case DeviceGroup_Protocol__payload_PR_groupKeys:
if (!keylist || rating < PEP_rating_reliable ||
// if header.state is HandshakingSole, then
// group is just forming in between 2 devices
// message must be addressed to that instance
// to be consumed
(msg->header.state == HandshakingSole &&
strncmp(session->sync_uuid,
(const char *)msg->payload.choice.groupKeys.partner.user_id->buf,
msg->payload.choice.groupKeys.partner.user_id->size) != 0)){
discarded = true;
goto flush;
}
// otherwise, when group keys are sent from a
// pre-existing group, inject message but flag is
// as discarded to prevent app to delete it, so
// that other group members can also be updated
if(msg->header.state != HandshakingSole){
force_keep_msg = true;
}
// check trust of identity with the right user_id
pEp_identity *_from = new_identity(src->from->address,
keylist->value,
user_id,
src->from->username);
if (_from == NULL){
status = PEP_OUT_OF_MEMORY;
goto flush;
}
PEP_rating this_user_id_rating = PEP_rating_undefined;
identity_rating(session, _from, &this_user_id_rating);
free_identity(_from);
if (this_user_id_rating < PEP_rating_trusted ) {
discarded = true;
goto flush;
}
break;
default:
break;
}
found = true;
sync_msg_t *sync_msg = malloc(sizeof(sync_msg_t));
if(sync_msg == NULL){
ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
return PEP_OUT_OF_MEMORY;
status = PEP_OUT_OF_MEMORY;
goto flush;
}
sync_msg->is_a_message = true;
sync_msg->u.message = msg;
status = call_inject_sync_msg(session, sync_msg);
if (status != PEP_STATUS_OK){
ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
if (status == PEP_SYNC_NO_INJECT_CALLBACK){
free(sync_msg);
}
return status;
goto flush;
}
}
else if (status == PEP_OWN_SEQUENCE) {
ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
return PEP_MESSAGE_DISCARDED;
status = PEP_STATUS_OK;
discarded = true;
goto flush;
}
flush:
ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
free(user_id);
if (status != PEP_STATUS_OK)
return status;
}
if (!session->keep_sync_msg) {
@ -288,7 +317,11 @@ PEP_STATUS receive_DeviceState_msg(
}
}
if (found && !session->keep_sync_msg) {
if (force_keep_msg) {
return PEP_MESSAGE_DISCARDED;
}
if ((expired || found) && !session->keep_sync_msg) {
for (stringpair_list_t *spl = src->opt_fields ; spl && spl->value ;
spl = spl->next) {
if (spl->value->key &&
@ -298,8 +331,12 @@ PEP_STATUS receive_DeviceState_msg(
return PEP_MESSAGE_CONSUMED;
}
}
return PEP_MESSAGE_DISCARDED;
}
if(discarded)
return PEP_MESSAGE_DISCARDED;
return PEP_STATUS_OK;
}
@ -319,6 +356,9 @@ void free_DeviceGroup_Protocol_msg(DeviceGroup_Protocol_t *msg)
ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
}
// Ten minutes
#define SYNC_MSG_EXPIRE_DELTA (60 * 10)
PEP_STATUS unicast_msg(
PEP_SESSION session,
const Identity partner,
@ -382,6 +422,13 @@ PEP_STATUS unicast_msg(
else
msg->header.devicegroup = 0;
timestamp *expiry = new_timestamp(time(NULL) + SYNC_MSG_EXPIRE_DELTA);
if(timestamp_to_GeneralizedTime(expiry, &msg->header.expiry) == NULL){
free_timestamp(expiry);
goto enomem;
}
free_timestamp(expiry);
if (asn_check_constraints(&asn_DEF_DeviceGroup_Protocol, msg, NULL, NULL)) {
status = PEP_CONTRAINTS_VIOLATED;
goto error;


Loading…
Cancel
Save