src/sync_impl.c
author Krista Bennett <krista@pep-project.org>
Wed, 15 Mar 2017 18:02:46 +0100
changeset 1674 5639f969866a
parent 1647 f089d9e32e60
child 1714 a6712af7a964
child 1750 33b2fa2368e6
permissions -rw-r--r--
Added pgp_encrypt_only stubs for NetPGP
vb@1513
     1
// This file is under GNU General Public License 3.0
vb@1513
     2
// see LICENSE.txt
vb@1513
     3
edouard@1261
     4
#include "platform.h"
edouard@1260
     5
edouard@1260
     6
// it seems pEp_internal.h needs to be the first pEp include due to the 
markus@1259
     7
// #define for the dllimport / dllexport DYNAMIC_API stuff.
markus@1259
     8
#include "pEp_internal.h"
markus@1259
     9
vb@1059
    10
#include "sync_impl.h"
vb@1059
    11
#include "keymanagement.h"
vb@1076
    12
#include "message_api.h"
vb@1059
    13
#include "map_asn1.h"
vb@1059
    14
#include "baseprotocol.h"
vb@1059
    15
vb@1077
    16
#define SYNC_VERSION_MAJOR 1
vb@1077
    17
#define SYNC_VERSION_MINOR 0
vb@1077
    18
edouard@1316
    19
#define SYNC_INHIBIT_TIME (60*10)
edouard@1316
    20
#define SYNC_MSG_EXPIRE_TIME (60 * 10)
edouard@1316
    21
edouard@1172
    22
struct _sync_msg_t {
edouard@1172
    23
    bool is_a_message;
edouard@1172
    24
    union {
edouard@1172
    25
        DeviceGroup_Protocol_t *message;
edouard@1172
    26
        struct {
edouard@1172
    27
            DeviceState_event event;
edouard@1172
    28
            Identity partner;
edouard@1172
    29
            void *extra;
edouard@1172
    30
        } event;
edouard@1172
    31
    } u;
edouard@1172
    32
};
edouard@1172
    33
edouard@1605
    34
static bool _is_own_uuid( PEP_SESSION session, UTF8String_t *uuid)
edouard@1605
    35
{
edouard@1605
    36
    return strncmp(session->sync_session->sync_uuid,
edouard@1606
    37
                   (const char*)uuid->buf, uuid->size) == 0;
edouard@1605
    38
}
edouard@1605
    39
edouard@1625
    40
static bool _is_own_group_uuid( PEP_SESSION session, UTF8String_t *uuid, char** our_group)
edouard@1605
    41
{
edouard@1625
    42
    PEP_STATUS status = PEP_STATUS_OK;
edouard@1605
    43
    char *devgrp = NULL;
edouard@1605
    44
edouard@1625
    45
    if(our_group == NULL || *our_group == NULL)
edouard@1625
    46
        status = get_device_group(session, &devgrp);
edouard@1625
    47
    else
edouard@1625
    48
        devgrp = *our_group;
edouard@1605
    49
edouard@1605
    50
    bool res = (status == PEP_STATUS_OK && devgrp && devgrp[0] &&
edouard@1605
    51
        strncmp(devgrp,(const char*)uuid->buf, uuid->size) == 0);
edouard@1625
    52
edouard@1625
    53
    if(our_group == NULL)
edouard@1625
    54
        free(devgrp);
edouard@1625
    55
    else if(*our_group == NULL)
edouard@1625
    56
        *our_group = devgrp;
edouard@1625
    57
edouard@1605
    58
    return res;
edouard@1605
    59
}
edouard@1605
    60
vb@1059
    61
PEP_STATUS receive_sync_msg(
vb@1059
    62
        PEP_SESSION session,
edouard@1445
    63
        sync_msg_t *sync_msg,
edouard@1445
    64
        time_t *timeout
vb@1059
    65
    )
vb@1059
    66
{
edouard@1172
    67
    PEP_STATUS status;
vb@1059
    68
    void *extra = NULL;
vb@1059
    69
    Identity partner = NULL;
vb@1059
    70
    DeviceState_event event = DeviceState_event_NONE;
edouard@1172
    71
    assert(session && sync_msg);
edouard@1172
    72
    if (!(session && sync_msg))
edouard@1172
    73
        return PEP_ILLEGAL_VALUE;
vb@1059
    74
edouard@1340
    75
    bool msgIsFromGroup = false;
edouard@1172
    76
    if(sync_msg->is_a_message){
edouard@1172
    77
        DeviceGroup_Protocol_t *msg = sync_msg->u.message;
edouard@1172
    78
        assert(msg && msg->payload.present != DeviceGroup_Protocol__payload_PR_NOTHING);
edouard@1172
    79
        if (!(msg && msg->payload.present != DeviceGroup_Protocol__payload_PR_NOTHING)){
edouard@1172
    80
            status = PEP_OUT_OF_MEMORY;
edouard@1172
    81
            goto error;
edouard@1172
    82
        }
vb@1059
    83
edouard@1605
    84
        partner = Identity_to_Struct(&msg->header.me, NULL);
edouard@1605
    85
        if (!partner){
edouard@1605
    86
            status = PEP_OUT_OF_MEMORY;
edouard@1605
    87
            ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1605
    88
            goto error;
edouard@1605
    89
        }
edouard@1605
    90
edouard@1340
    91
        msgIsFromGroup = msg->header.devicegroup;
edouard@1340
    92
edouard@1172
    93
        switch (msg->payload.present) {
edouard@1172
    94
            case DeviceGroup_Protocol__payload_PR_beacon:
edouard@1172
    95
                event = Beacon;
edouard@1172
    96
                break;
vb@1059
    97
edouard@1172
    98
            case DeviceGroup_Protocol__payload_PR_handshakeRequest:
edouard@1608
    99
            {
edouard@1608
   100
                // re-check uuid in case sync_uuid or group changed while in the queue
edouard@1625
   101
                char *own_group_id = NULL;
edouard@1608
   102
                bool is_for_me = _is_own_uuid(session, 
edouard@1608
   103
                    msg->payload.choice.handshakeRequest.partner_id);
edouard@1608
   104
                bool is_for_group = !is_for_me && _is_own_group_uuid(session, 
edouard@1625
   105
                    msg->payload.choice.handshakeRequest.partner_id, &own_group_id);
edouard@1608
   106
                if (!(is_for_me || is_for_group)){
edouard@1625
   107
                    status = PEP_MESSAGE_IGNORE;
edouard@1575
   108
                    goto error;
edouard@1575
   109
                }
edouard@1586
   110
edouard@1625
   111
                UTF8String_t *guuid = msg->payload.choice.handshakeRequest.group_id;
edouard@1625
   112
                if(msgIsFromGroup && guuid && guuid->buf && guuid->size) {
edouard@1625
   113
                    bool is_from_own_group = _is_own_group_uuid(session, 
edouard@1625
   114
                                                                guuid, &own_group_id);
edouard@1625
   115
edouard@1625
   116
                    // Filter handshake requests from own group
edouard@1625
   117
                    if(is_from_own_group) {
edouard@1625
   118
                        status = PEP_MESSAGE_IGNORE;
edouard@1586
   119
                        goto error;
edouard@1586
   120
                    }
edouard@1605
   121
edouard@1625
   122
                    // if it comes from another group, 
edouard@1625
   123
                    // we want to communicate with that group
edouard@1625
   124
                    // insert group_id given in handshake request 
edouard@1625
   125
                    // into partner's id
edouard@1625
   126
edouard@1625
   127
                    free(partner->user_id);
edouard@1625
   128
                    partner->user_id = strndup((const char*)guuid->buf, guuid->size);
edouard@1625
   129
                    if(partner->user_id == NULL){
edouard@1625
   130
                        status = PEP_OUT_OF_MEMORY;
edouard@1625
   131
                        goto error;
edouard@1625
   132
                    }
edouard@1625
   133
edouard@1625
   134
                    // if it comes from another group, and we are grouped,
edouard@1625
   135
                    // then this is groupmerge
edouard@1586
   136
                }
edouard@1586
   137
edouard@1316
   138
                event = HandshakeRequest;
edouard@1316
   139
                break;
edouard@1256
   140
edouard@1608
   141
            }
edouard@1316
   142
            case DeviceGroup_Protocol__payload_PR_updateRequest:
edouard@1316
   143
                event = UpdateRequest;
edouard@1172
   144
                break;
vb@1059
   145
edouard@1172
   146
            case DeviceGroup_Protocol__payload_PR_groupKeys:
edouard@1586
   147
            {
edouard@1625
   148
                // re-check uuid in case sync_uuid or group_uuid changed while in the queue
edouard@1625
   149
                char *own_group_id = NULL;
edouard@1625
   150
                UTF8String_t *puuid = msg->payload.choice.groupKeys.partner_id;
edouard@1625
   151
                bool is_for_me = _is_own_uuid(session, puuid);
edouard@1625
   152
                bool is_for_group = !is_for_me &&
edouard@1625
   153
                                    _is_own_group_uuid(session, 
edouard@1625
   154
                                        puuid, &own_group_id);
edouard@1625
   155
                if (!(is_for_me || is_for_group)){
edouard@1625
   156
                    status = PEP_MESSAGE_IGNORE;
edouard@1625
   157
                    goto error;
edouard@1625
   158
                }
edouard@1625
   159
edouard@1625
   160
                UTF8String_t *guuid = msg->payload.choice.groupKeys.group_id;
edouard@1625
   161
edouard@1625
   162
                // GroupKeys come from groups, no choice
edouard@1625
   163
                if(!(msgIsFromGroup && guuid && guuid->buf && guuid->size)) {
edouard@1575
   164
                    status = PEP_SYNC_ILLEGAL_MESSAGE;
edouard@1575
   165
                    goto error;
edouard@1575
   166
                }
edouard@1625
   167
edouard@1625
   168
                // Filter groupKeys from own group
edouard@1625
   169
                bool is_from_own_group = _is_own_group_uuid(session, 
edouard@1625
   170
                                                            guuid, 
edouard@1625
   171
                                                            &own_group_id);
edouard@1625
   172
                if(is_from_own_group) {
edouard@1625
   173
                    // FixMe : protocol shouldn't allow this
edouard@1625
   174
                    status = PEP_SYNC_ILLEGAL_MESSAGE;
edouard@1625
   175
                    goto error;
edouard@1625
   176
                }
edouard@1625
   177
edouard@1625
   178
                // insert group_id given in groupKeys into partner's id
edouard@1625
   179
                free(partner->user_id);
edouard@1625
   180
                partner->user_id = strndup((const char*)guuid->buf, guuid->size);
edouard@1625
   181
                if(partner->user_id == NULL){
edouard@1625
   182
                    status = PEP_OUT_OF_MEMORY;
edouard@1625
   183
                    goto error;
edouard@1625
   184
                }
edouard@1625
   185
edouard@1625
   186
                // if it comes from another group, and we are grouped,
edouard@1625
   187
                // then this is groupmerge's groupKeys
edouard@1625
   188
edouard@1586
   189
                group_keys_extra_t *group_keys_extra;
edouard@1586
   190
                group_keys_extra = malloc(sizeof(group_keys_extra_t));
edouard@1586
   191
                if(group_keys_extra == NULL){
edouard@1586
   192
                    status = PEP_OUT_OF_MEMORY;
edouard@1586
   193
                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1586
   194
                    goto error;
edouard@1586
   195
                }
edouard@1586
   196
edouard@1625
   197
                char *group_id = strndup((char*)guuid->buf, guuid->size);
edouard@1586
   198
edouard@1625
   199
                if (!group_id){
edouard@1586
   200
                    status = PEP_OUT_OF_MEMORY;
edouard@1586
   201
                    free(group_keys_extra);
edouard@1586
   202
                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1586
   203
                    goto error;
edouard@1586
   204
                }
edouard@1586
   205
                group_keys_extra->group_id = group_id;
edouard@1586
   206
edouard@1172
   207
                identity_list *group_keys = IdentityList_to_identity_list(
edouard@1587
   208
                        &msg->payload.choice.groupKeys.ownIdentities,
edouard@1281
   209
                        NULL);
edouard@1172
   210
                if (!group_keys) {
edouard@1172
   211
                    status = PEP_OUT_OF_MEMORY;
edouard@1586
   212
                    free(group_id);
edouard@1586
   213
                    free(group_keys_extra);
edouard@1586
   214
                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1586
   215
                    goto error;
edouard@1586
   216
                }
edouard@1586
   217
                group_keys_extra->group_keys = group_keys;
edouard@1586
   218
edouard@1586
   219
                extra = (void *) group_keys_extra;
edouard@1587
   220
                event = GroupKeys;
edouard@1586
   221
edouard@1586
   222
                break;
edouard@1586
   223
            }
edouard@1586
   224
            case DeviceGroup_Protocol__payload_PR_groupUpdate:
edouard@1586
   225
            {
edouard@1586
   226
                identity_list *group_keys = IdentityList_to_identity_list(
edouard@1586
   227
                        &msg->payload.choice.groupUpdate.ownIdentities, NULL);
edouard@1586
   228
                if (!group_keys) {
edouard@1586
   229
                    status = PEP_OUT_OF_MEMORY;
edouard@1172
   230
                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1172
   231
                    goto error;
edouard@1172
   232
                }
edouard@1172
   233
                extra = (void *) group_keys;
edouard@1586
   234
                event = GroupUpdate;
edouard@1172
   235
                break;
edouard@1316
   236
            }
edouard@1172
   237
edouard@1172
   238
            default:
edouard@1172
   239
                status = PEP_SYNC_ILLEGAL_MESSAGE;
edouard@1172
   240
                ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1172
   241
                goto error;
edouard@1172
   242
        }
edouard@1316
   243
edouard@1172
   244
    }
edouard@1172
   245
    else{
edouard@1172
   246
        partner = sync_msg->u.event.partner;
edouard@1172
   247
        extra = sync_msg->u.event.extra;
edouard@1172
   248
        event = sync_msg->u.event.event;
vb@1059
   249
    }
vb@1059
   250
edouard@1316
   251
    // Event inhibition, to limit mailbox and prevent cycles
edouard@1316
   252
    time_t *last = NULL;
edouard@1316
   253
    switch(event){
edouard@1316
   254
        case CannotDecrypt:
edouard@1316
   255
            last = &session->LastCannotDecrypt;
edouard@1316
   256
            break;
edouard@1316
   257
edouard@1316
   258
        case UpdateRequest:
edouard@1316
   259
            last = &session->LastUpdateRequest;
edouard@1316
   260
            break;
edouard@1316
   261
edouard@1316
   262
        default:
edouard@1316
   263
            break;
edouard@1316
   264
    }
edouard@1567
   265
edouard@1316
   266
    if(last != NULL){
edouard@1567
   267
        time_t now = time(NULL);
edouard@1316
   268
        if(*last != 0 && (*last + SYNC_INHIBIT_TIME) > now ){
edouard@1316
   269
            status = PEP_STATEMACHINE_INHIBITED_EVENT;
edouard@1316
   270
            goto error;
edouard@1316
   271
        }
edouard@1316
   272
        *last = now;
edouard@1316
   273
    }
edouard@1316
   274
edouard@1256
   275
    // partner identity must be explicitely added DB to later
edouard@1256
   276
    // be able to communicate securely with it.
edouard@1256
   277
    if(partner){
edouard@1260
   278
        // protect virtual user IDs 
edouard@1256
   279
        if((strncmp("TOFU_", partner->user_id, 6) == 0 &&
edouard@1256
   280
           strlen(partner->user_id) == strlen(partner->address) + 6 &&
edouard@1256
   281
           strcmp(partner->user_id + 6, partner->address)) ||
edouard@1260
   282
        // protect own ID 
edouard@1256
   283
           (strcmp(PEP_OWN_USERID, partner->user_id) == 0)){
edouard@1256
   284
            status = PEP_SYNC_ILLEGAL_MESSAGE;
edouard@1256
   285
            goto error;
edouard@1256
   286
        }
edouard@1256
   287
edouard@1260
   288
        // partner IDs are UUIDs bound to session lifespan
edouard@1256
   289
        // and therefore partner identities are not supposed
edouard@1260
   290
        // to mutate over time, but just not be used anymore.
edouard@1260
   291
        // It should then be safe to accept given identity if not 
edouard@1256
   292
        // already pre-existing
edouard@1256
   293
        pEp_identity *stored_identity = NULL;
edouard@1256
   294
        status = get_identity(session,
edouard@1256
   295
                              partner->address,
edouard@1256
   296
                              partner->user_id,
edouard@1256
   297
                              &stored_identity);
edouard@1256
   298
edouard@1256
   299
        if (!stored_identity) {
edouard@1260
   300
            // make a safe copy of partner, with no flags or comm_type
edouard@1260
   301
            pEp_identity *tmpident = new_identity(partner->address,
edouard@1260
   302
                                                  partner->fpr,
edouard@1260
   303
                                                  partner->user_id,
edouard@1260
   304
                                                  partner->username);
edouard@1260
   305
            if (tmpident == NULL){
edouard@1260
   306
                status = PEP_OUT_OF_MEMORY;
edouard@1260
   307
                goto error;
edouard@1260
   308
            }
edouard@1260
   309
edouard@1260
   310
            // finaly add partner to DB
edouard@1260
   311
            status = set_identity(session, tmpident);
edouard@1340
   312
            assert(status == PEP_STATUS_OK);
edouard@1340
   313
            if(status == PEP_STATUS_OK && msgIsFromGroup)
edouard@1340
   314
                status = set_identity_flags(session, tmpident, PEP_idf_devicegroup);
edouard@1260
   315
            free_identity(tmpident);
edouard@1256
   316
            assert(status == PEP_STATUS_OK);
edouard@1256
   317
            if (status != PEP_STATUS_OK) {
edouard@1256
   318
                goto error;
edouard@1256
   319
            }
edouard@1256
   320
        }
edouard@1256
   321
        else if (status == PEP_STATUS_OK) {
edouard@1256
   322
            free_identity(stored_identity);
edouard@1256
   323
        } 
edouard@1256
   324
        else
edouard@1256
   325
            goto error;
edouard@1256
   326
    }
edouard@1256
   327
edouard@1445
   328
    status = fsm_DeviceState_inject(session, event, partner, extra, timeout);
edouard@1157
   329
edouard@1587
   330
error:
edouard@1587
   331
edouard@1157
   332
    free_identity(partner);
edouard@1157
   333
edouard@1587
   334
    switch(event){
edouard@1587
   335
        case GroupKeys:
edouard@1587
   336
        {
edouard@1597
   337
            free_group_keys_extra((group_keys_extra_t*)extra);
edouard@1587
   338
            break;
edouard@1587
   339
        }
edouard@1587
   340
        case GroupUpdate:
edouard@1587
   341
        {
edouard@1587
   342
            identity_list *group_keys = (identity_list*) extra;
edouard@1587
   343
            free_identity_list(group_keys);
edouard@1587
   344
            break;
edouard@1587
   345
        }
edouard@1587
   346
        default:
edouard@1587
   347
            assert(extra==NULL);
edouard@1587
   348
            break;
edouard@1587
   349
    }
edouard@1587
   350
edouard@1172
   351
    free(sync_msg);
edouard@1172
   352
edouard@1159
   353
    return status;
vb@1059
   354
}
vb@1059
   355
markus@1226
   356
// TODO: DYNAMIC_API was here, but broke the windows build. 
markus@1226
   357
// We need to check whether it belongs here or it's a bug.
markus@1226
   358
/* DYNAMIC_API */ void free_sync_msg(sync_msg_t *sync_msg)
Edouard@1203
   359
{
roker@1482
   360
    if (!sync_msg)
Edouard@1203
   361
        return;
Edouard@1203
   362
Edouard@1203
   363
    if(sync_msg->is_a_message){
Edouard@1203
   364
        DeviceGroup_Protocol_t *msg = sync_msg->u.message;
Edouard@1203
   365
        assert(msg);
Edouard@1203
   366
        if (!(msg))
Edouard@1203
   367
            return;
Edouard@1203
   368
Edouard@1203
   369
        ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
Edouard@1203
   370
    }
Edouard@1203
   371
    else{
Edouard@1203
   372
        Identity partner = NULL;
Edouard@1203
   373
        partner = sync_msg->u.event.partner;
Edouard@1203
   374
        if(partner != NULL)
Edouard@1203
   375
            free_identity(partner);
Edouard@1203
   376
    }
Edouard@1203
   377
Edouard@1203
   378
    free(sync_msg);
Edouard@1203
   379
Edouard@1203
   380
    return;
Edouard@1203
   381
}
Edouard@1203
   382
edouard@1167
   383
// from sync.c
edouard@1167
   384
int call_inject_sync_msg(PEP_SESSION session, void *msg);
edouard@1167
   385
edouard@1172
   386
PEP_STATUS inject_DeviceState_event(
edouard@1172
   387
    PEP_SESSION session, 
edouard@1172
   388
    DeviceState_event event,
edouard@1172
   389
    Identity partner,
edouard@1172
   390
    void *extra)
edouard@1172
   391
{
edouard@1172
   392
    PEP_STATUS status;
edouard@1172
   393
edouard@1172
   394
    assert(session);
edouard@1172
   395
    if (!(session))
edouard@1172
   396
        return PEP_ILLEGAL_VALUE;
edouard@1172
   397
edouard@1172
   398
    sync_msg_t *sync_msg = malloc(sizeof(sync_msg_t));
edouard@1172
   399
    if(sync_msg == NULL)
edouard@1172
   400
        return PEP_OUT_OF_MEMORY;
edouard@1172
   401
edouard@1172
   402
    sync_msg->is_a_message = false;
edouard@1172
   403
    sync_msg->u.event.partner = partner;
edouard@1172
   404
    sync_msg->u.event.extra = extra;
edouard@1172
   405
    sync_msg->u.event.event = event;
edouard@1172
   406
edouard@1172
   407
    status = call_inject_sync_msg(session, sync_msg);
edouard@1172
   408
    if (status == PEP_SYNC_NO_INJECT_CALLBACK){
edouard@1172
   409
        free(sync_msg);
edouard@1172
   410
    }
edouard@1172
   411
edouard@1172
   412
    return status;
edouard@1172
   413
}
edouard@1172
   414
edouard@1165
   415
PEP_STATUS receive_DeviceState_msg(
edouard@1165
   416
    PEP_SESSION session, 
edouard@1165
   417
    message *src, 
edouard@1165
   418
    PEP_rating rating, 
edouard@1165
   419
    stringlist_t *keylist)
vb@1059
   420
{
vb@1059
   421
    assert(session && src);
vb@1059
   422
    if (!(session && src))
vb@1059
   423
        return PEP_ILLEGAL_VALUE;
vb@1059
   424
edouard@1339
   425
    bool consume = false;
edouard@1339
   426
    bool discard = false;
edouard@1248
   427
    bool force_keep_msg = false;
vb@1338
   428
vb@1059
   429
    for (bloblist_t *bl = src->attachments; bl && bl->value; bl = bl->next) {
vb@1132
   430
        if (bl->mime_type && strcasecmp(bl->mime_type, "application/pEp.sync") == 0
vb@1059
   431
                && bl->size) {
vb@1077
   432
            DeviceGroup_Protocol_t *msg = NULL;
vb@1091
   433
            uper_decode_complete(NULL, &asn_DEF_DeviceGroup_Protocol, (void **)
vb@1091
   434
                    &msg, bl->value, bl->size);
edouard@1248
   435
vb@1059
   436
            if (msg) {
edouard@1257
   437
                PEP_STATUS status = PEP_STATUS_OK;
vb@1088
   438
vb@1091
   439
                char *user_id = strndup((char *) msg->header.me.user_id->buf,
vb@1091
   440
                        msg->header.me.user_id->size);
vb@1091
   441
                assert(user_id);
vb@1091
   442
                if (!user_id) {
vb@1091
   443
                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
vb@1091
   444
                    return PEP_OUT_OF_MEMORY;
vb@1091
   445
                }
vb@1091
   446
edouard@1521
   447
                // detect and mitigate address spoofing
edouard@1521
   448
                Identity check_me = NULL;
edouard@1527
   449
                char* null_terminated_address = 
edouard@1521
   450
                    strndup((char *) msg->header.me.address->buf,
edouard@1521
   451
                            msg->header.me.address->size);
edouard@1521
   452
edouard@1527
   453
                if(null_terminated_address){
edouard@1527
   454
                    status = get_identity(session, 
edouard@1527
   455
                                          null_terminated_address, 
edouard@1527
   456
                                          PEP_OWN_USERID, 
edouard@1527
   457
                                          &check_me);
edouard@1527
   458
                    free(null_terminated_address);
edouard@1527
   459
                } 
edouard@1527
   460
                else
edouard@1527
   461
                    status = PEP_OUT_OF_MEMORY;
edouard@1521
   462
edouard@1521
   463
                if (status == PEP_OUT_OF_MEMORY)
edouard@1521
   464
                    goto free_all;
edouard@1521
   465
edouard@1521
   466
                free_identity(check_me);
edouard@1521
   467
edouard@1521
   468
                bool not_own_address = status != PEP_STATUS_OK;
edouard@1521
   469
                status = PEP_STATUS_OK;
edouard@1521
   470
edouard@1521
   471
                if (not_own_address || 
edouard@1521
   472
                    strncmp(src->from->address,
edouard@1521
   473
                            (char *) msg->header.me.address->buf,
edouard@1521
   474
                            msg->header.me.address->size) != 0 ||
edouard@1521
   475
                    strncmp(src->to->ident->address,
edouard@1521
   476
                            (char *) msg->header.me.address->buf,
edouard@1521
   477
                            msg->header.me.address->size) != 0) {
edouard@1521
   478
                    consume = true;
edouard@1521
   479
                    goto free_all;
edouard@1521
   480
                }
edouard@1521
   481
edouard@1521
   482
                // if encrypted, ensure that header.me.fpr match signer's fpr
edouard@1521
   483
                if (rating >= PEP_rating_reliable && (
edouard@1521
   484
                        !keylist ||
edouard@1521
   485
                        !_same_fpr((char *) msg->header.me.fpr.buf,
edouard@1521
   486
                                   msg->header.me.fpr.size,
edouard@1521
   487
                                   keylist->value,
edouard@1521
   488
                                   strlen(keylist->value)))) {
edouard@1521
   489
                    consume = true;
edouard@1521
   490
                    goto free_all;
edouard@1521
   491
                }
edouard@1521
   492
edouard@1248
   493
                // check message expiry 
edouard@1257
   494
                if(src->recv) {
edouard@1316
   495
                    time_t expiry = timegm(src->recv) + SYNC_MSG_EXPIRE_TIME;
edouard@1257
   496
                    time_t now = time(NULL);
edouard@1257
   497
                    if(expiry != 0 && now != 0 && expiry < now){
edouard@1339
   498
                        consume = true;
edouard@1257
   499
                        goto free_all;
edouard@1257
   500
                    }
edouard@1165
   501
                }
edouard@1165
   502
edouard@1248
   503
                int32_t value = (int32_t) msg->header.sequence;
edouard@1568
   504
                if (value < 1) {
edouard@1568
   505
                    status = PEP_SEQUENCE_VIOLATED;
edouard@1568
   506
                } else {
edouard@1568
   507
                    status = sequence_value(session, (char *) user_id,
edouard@1568
   508
                            &value);
edouard@1568
   509
                }
vb@1088
   510
vb@1088
   511
                if (status == PEP_STATUS_OK) {
edouard@1248
   512
                    switch (msg->payload.present) {
edouard@1248
   513
                        // HandshakeRequest needs encryption
edouard@1248
   514
                        case DeviceGroup_Protocol__payload_PR_handshakeRequest:
edouard@1607
   515
                        {
edouard@1625
   516
                            UTF8String_t *puuid = 
edouard@1625
   517
                              msg->payload.choice.handshakeRequest.partner_id;
edouard@1625
   518
                            bool is_for_me = _is_own_uuid(session, puuid);
edouard@1625
   519
                            bool is_for_group = !is_for_me && 
edouard@1625
   520
                                                _is_own_group_uuid(
edouard@1625
   521
                                                    session, puuid, NULL);
edouard@1625
   522
edouard@1608
   523
                            // Reject handshake requests not addressed to us
edouard@1248
   524
                            if (rating < PEP_rating_reliable ||
edouard@1607
   525
                                !(is_for_me || is_for_group)){
edouard@1339
   526
                                discard = true;
edouard@1256
   527
                                goto free_all;
edouard@1248
   528
                            }
edouard@1608
   529
edouard@1608
   530
                            // do not consume handshake request for group
edouard@1607
   531
                            if(is_for_group){ 
edouard@1607
   532
                                force_keep_msg = true;
edouard@1607
   533
                            }
edouard@1248
   534
                            break;
edouard@1607
   535
                        }
edouard@1297
   536
                        // accepting GroupKeys needs encryption and trust of peer device
edouard@1248
   537
                        case DeviceGroup_Protocol__payload_PR_groupKeys:
edouard@1297
   538
                        {
edouard@1625
   539
                            UTF8String_t *puuid = msg->payload.choice.groupKeys.partner_id;
edouard@1625
   540
                            bool is_for_me = _is_own_uuid(session, puuid);
edouard@1625
   541
                            bool is_for_group = !is_for_me &&
edouard@1625
   542
                                                _is_own_group_uuid(session, 
edouard@1625
   543
                                                    puuid, NULL);
edouard@1248
   544
                            if (!keylist || rating < PEP_rating_reliable ||
edouard@1297
   545
                                // message is only consumed by instance it is addressed to
edouard@1625
   546
                                !(is_for_me || is_for_group)){
edouard@1339
   547
                                discard = true;
edouard@1256
   548
                                goto free_all;
edouard@1248
   549
                            }
edouard@1248
   550
edouard@1647
   551
                            // do not consume groupKeys for group
edouard@1625
   552
                            if(is_for_group){ 
edouard@1625
   553
                                // This happens in case case of groupmerge
edouard@1625
   554
                                force_keep_msg = true;
edouard@1625
   555
                            }
edouard@1625
   556
edouard@1647
   557
                            // Trust check disabled here but it still it should be safe.
edouard@1647
   558
                            // SameIdentity checks in state machine ensures that we only
edouard@1647
   559
                            // store groupkeys signed by device or group that have been 
edouard@1647
   560
                            // previously accepted in handshake.
edouard@1647
   561
                            //
edouard@1647
   562
                            // // check trust of identity using user_id given in msg.header.me
edouard@1647
   563
                            // // to exacly match identity of device, the one trusted in
edouard@1647
   564
                            // // case of accepted handshake from a sole device
edouard@1647
   565
                            // pEp_identity *_from = new_identity(NULL, 
edouard@1647
   566
                            //                                    keylist->value,
edouard@1647
   567
                            //                                    user_id,
edouard@1647
   568
                            //                                    NULL);
edouard@1647
   569
                            // if (_from == NULL){
edouard@1647
   570
                            //     status = PEP_OUT_OF_MEMORY;
edouard@1647
   571
                            //     goto free_all;
edouard@1647
   572
                            // }
edouard@1647
   573
                            // status = get_trust(session, _from);
edouard@1647
   574
                            // if (status != PEP_STATUS_OK || _from->comm_type < PEP_ct_strong_encryption) {
edouard@1625
   575
edouard@1647
   576
                            //     // re-try with group_id instead, in case of handshake with pre-existing group
edouard@1647
   577
                            //     UTF8String_t *guuid = msg->payload.choice.groupKeys.group_id;
edouard@1647
   578
                            //     free(_from->user_id);
edouard@1647
   579
                            //     if ((_from->user_id = strndup((const char*)guuid->buf, guuid->size)) == NULL){
edouard@1647
   580
                            //         free_identity(_from);
edouard@1647
   581
                            //         status = PEP_OUT_OF_MEMORY;
edouard@1647
   582
                            //         goto free_all;
edouard@1647
   583
                            //     }
edouard@1647
   584
                            //     _from->comm_type = PEP_ct_unknown;
edouard@1625
   585
edouard@1647
   586
                            //     status = get_trust(session, _from);
edouard@1647
   587
                            //     if (status != PEP_STATUS_OK || _from->comm_type < PEP_ct_strong_encryption) {
edouard@1647
   588
                            //         status = PEP_STATUS_OK;
edouard@1647
   589
                            //         free_identity(_from);
edouard@1647
   590
                            //         discard = true;
edouard@1647
   591
                            //         goto free_all;
edouard@1647
   592
                            //     }
edouard@1647
   593
                            // }
edouard@1647
   594
                            // free_identity(_from);
edouard@1248
   595
                            break;
edouard@1297
   596
                        }
edouard@1297
   597
                        case DeviceGroup_Protocol__payload_PR_groupUpdate:
edouard@1316
   598
                        case DeviceGroup_Protocol__payload_PR_updateRequest:
edouard@1316
   599
                        {
edouard@1297
   600
                            // inject message but don't consume it, so 
edouard@1297
   601
                            // that other group members can also be updated
edouard@1297
   602
                            force_keep_msg = true;
edouard@1297
   603
                            
edouard@1297
   604
                            if (!keylist || rating < PEP_rating_reliable){
edouard@1339
   605
                                discard = true;
edouard@1297
   606
                                goto free_all;
edouard@1297
   607
                            }
edouard@1297
   608
                            // GroupUpdate and UpdateRequests come from group.
edouard@1297
   609
                            // check trust relation in between signer key and 
edouard@1297
   610
                            // own id to be sure.
edouard@1297
   611
                            pEp_identity *_from = new_identity(NULL, 
edouard@1297
   612
                                                               keylist->value,
edouard@1297
   613
                                                               PEP_OWN_USERID,
edouard@1297
   614
                                                               NULL);
edouard@1297
   615
                            if (_from == NULL){
edouard@1297
   616
                                status = PEP_OUT_OF_MEMORY;
edouard@1297
   617
                                goto free_all;
edouard@1297
   618
                            }
edouard@1297
   619
                            status = get_trust(session, _from);
edouard@1368
   620
                            if (status != PEP_STATUS_OK || _from->comm_type < PEP_ct_pEp) {
edouard@1368
   621
                                status = PEP_STATUS_OK;
edouard@1297
   622
                                free_identity(_from);
edouard@1339
   623
                                discard = true;
edouard@1297
   624
                                goto free_all;
edouard@1297
   625
                            }
edouard@1297
   626
                            free_identity(_from);
edouard@1297
   627
                        }
edouard@1248
   628
                        default:
edouard@1248
   629
                            break;
edouard@1248
   630
                    }
edouard@1248
   631
edouard@1248
   632
edouard@1339
   633
                    consume = true;
edouard@1172
   634
                    sync_msg_t *sync_msg = malloc(sizeof(sync_msg_t));
edouard@1172
   635
                    if(sync_msg == NULL){
edouard@1248
   636
                        status = PEP_OUT_OF_MEMORY;
edouard@1256
   637
                        goto free_all;
edouard@1172
   638
                    }
edouard@1172
   639
                    sync_msg->is_a_message = true;
edouard@1172
   640
                    sync_msg->u.message = msg;
edouard@1172
   641
                    status = call_inject_sync_msg(session, sync_msg);
edouard@1165
   642
                    if (status != PEP_STATUS_OK){
edouard@1172
   643
                        if (status == PEP_SYNC_NO_INJECT_CALLBACK){
edouard@1172
   644
                            free(sync_msg);
edouard@1172
   645
                        }
edouard@1256
   646
                        goto free_all;
edouard@1165
   647
                    }
edouard@1339
   648
                    // don't free message now that it is in the queue
edouard@1256
   649
                    goto free_userid;
edouard@1165
   650
                }
edouard@1636
   651
                else if (status == PEP_OWN_SEQUENCE || status == PEP_SEQUENCE_VIOLATED) {
edouard@1248
   652
                    status = PEP_STATUS_OK;
edouard@1339
   653
                    discard = true;
edouard@1256
   654
                    goto free_all;
vb@1088
   655
                }
edouard@1248
   656
edouard@1256
   657
            free_all:
edouard@1248
   658
                ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1256
   659
            free_userid:
edouard@1248
   660
                free(user_id);
edouard@1248
   661
edouard@1248
   662
                if (status != PEP_STATUS_OK)
edouard@1248
   663
                    return status;
vb@1059
   664
            }
vb@1059
   665
        }
vb@1059
   666
    }
vb@1059
   667
edouard@1248
   668
    if (force_keep_msg) {
edouard@1369
   669
        return PEP_MESSAGE_IGNORE;
edouard@1248
   670
    }
edouard@1248
   671
edouard@1339
   672
    if (consume && !session->keep_sync_msg) {
vb@1059
   673
        for (stringpair_list_t *spl = src->opt_fields ; spl && spl->value ;
vb@1059
   674
                spl = spl->next) {
vb@1059
   675
            if (spl->value->key &&
vb@1059
   676
                    strcasecmp(spl->value->key, "pEp-auto-consume") == 0) {
vb@1059
   677
                if (spl->value->value &&
vb@1059
   678
                        strcasecmp(spl->value->value, "yes") == 0)
edouard@1369
   679
                    return PEP_MESSAGE_CONSUME;
vb@1059
   680
            }
vb@1059
   681
        }
edouard@1369
   682
        return PEP_MESSAGE_IGNORE;
vb@1059
   683
    }
vb@1059
   684
edouard@1339
   685
    if(discard)
edouard@1369
   686
        return PEP_MESSAGE_IGNORE;
edouard@1248
   687
vb@1338
   688
    if (!session->keep_sync_msg) {
vb@1338
   689
        bloblist_t *last = NULL;
vb@1338
   690
        for (bloblist_t *bl = src->attachments; bl && bl->value; ) {
vb@1338
   691
            if (bl->mime_type && strcasecmp(bl->mime_type, "application/pEp.sync") == 0) {
vb@1338
   692
                bloblist_t *b = bl;
vb@1338
   693
                bl = bl->next;
vb@1338
   694
                if (!last)
vb@1338
   695
                    src->attachments = bl;
vb@1338
   696
                else
vb@1338
   697
                    last->next = bl;
vb@1338
   698
                free(b->mime_type);
vb@1338
   699
                free(b->filename);
vb@1338
   700
                free(b->value);
vb@1338
   701
                free(b);
vb@1338
   702
            }
vb@1338
   703
            else {
vb@1338
   704
                last = bl;
vb@1338
   705
                bl = bl->next;
vb@1338
   706
            }
vb@1338
   707
        }
vb@1338
   708
    }
vb@1338
   709
vb@1059
   710
    return PEP_STATUS_OK;
vb@1059
   711
}
vb@1059
   712
vb@1059
   713
DeviceGroup_Protocol_t *new_DeviceGroup_Protocol_msg(DeviceGroup_Protocol__payload_PR type)
vb@1059
   714
{
vb@1059
   715
    DeviceGroup_Protocol_t *msg = (DeviceGroup_Protocol_t *)
vb@1073
   716
            calloc(1, sizeof(DeviceGroup_Protocol_t));
vb@1059
   717
    assert(msg);
vb@1059
   718
    if (!msg)
vb@1059
   719
        return NULL;
vb@1059
   720
    msg->payload.present = type;
vb@1059
   721
    return msg;
vb@1059
   722
}
vb@1059
   723
vb@1059
   724
void free_DeviceGroup_Protocol_msg(DeviceGroup_Protocol_t *msg)
vb@1059
   725
{
vb@1059
   726
    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
vb@1059
   727
}
vb@1059
   728
Edouard@1495
   729
Edouard@1495
   730
#ifndef NDEBUG
Edouard@1495
   731
static int _append(const void *buffer, size_t size, void *appkey)
edouard@1494
   732
{
edouard@1494
   733
    char **dest_ptr = (char **)appkey;
edouard@1494
   734
    size_t osize = strlen(*dest_ptr);
edouard@1494
   735
    size_t nsize = size + osize;
edouard@1494
   736
    *dest_ptr = realloc(*dest_ptr, nsize + 1);
edouard@1494
   737
    if(*dest_ptr == NULL) return -1;
edouard@1494
   738
    memcpy(*dest_ptr + osize, buffer, size);
edouard@1494
   739
    (*dest_ptr)[nsize] = '\0';
edouard@1494
   740
    return 0;
edouard@1494
   741
}
Edouard@1495
   742
#endif
edouard@1494
   743
vb@1059
   744
PEP_STATUS unicast_msg(
vb@1059
   745
        PEP_SESSION session,
vb@1091
   746
        const Identity partner,
vb@1059
   747
        DeviceState_state state,
vb@1097
   748
        DeviceGroup_Protocol_t *msg,
vb@1097
   749
        bool encrypted
vb@1059
   750
    )
vb@1059
   751
{
vb@1059
   752
    PEP_STATUS status = PEP_STATUS_OK;
vb@1059
   753
    char *payload = NULL;
vb@1059
   754
    message *_message = NULL;
vb@1059
   755
    pEp_identity *me = NULL;
vb@1088
   756
    pEp_identity *_me = NULL;
vb@1059
   757
vb@1059
   758
    assert(session && partner && state && msg);
vb@1059
   759
    if (!(session && partner && state && msg))
vb@1059
   760
        return PEP_ILLEGAL_VALUE;
vb@1059
   761
vb@1059
   762
    assert(session->messageToSend);
vb@1059
   763
    if (!session->messageToSend) {
vb@1059
   764
        status = PEP_SEND_FUNCTION_NOT_REGISTERED;
vb@1059
   765
        goto error;
vb@1059
   766
    }
vb@1059
   767
vb@1077
   768
    msg->header.version.major = SYNC_VERSION_MAJOR;
vb@1077
   769
    msg->header.version.minor = SYNC_VERSION_MINOR;
vb@1077
   770
vb@1071
   771
    status = get_identity(session, partner->address, PEP_OWN_USERID, &me);
vb@1059
   772
    if (status != PEP_STATUS_OK)
vb@1059
   773
        goto error;
vb@1088
   774
    
vb@1088
   775
    int32_t seq = 0;
vb@1088
   776
edouard@1603
   777
    status = sequence_value(session, session->sync_session->sync_uuid, &seq);
vb@1088
   778
    if (status != PEP_OWN_SEQUENCE && status != PEP_STATUS_OK)
vb@1088
   779
        goto error;
vb@1088
   780
vb@1088
   781
    msg->header.sequence = (long) seq;
vb@1088
   782
vb@1088
   783
    _me = identity_dup(me);
vb@1088
   784
    if (!_me)
vb@1059
   785
        goto enomem;
vb@1059
   786
vb@1088
   787
    free(_me->user_id);
edouard@1603
   788
    _me->user_id = strndup(session->sync_session->sync_uuid, 36);
vb@1088
   789
    assert(_me->user_id);
vb@1088
   790
    if (!_me->user_id)
vb@1088
   791
        goto enomem;
vb@1088
   792
vb@1088
   793
    if (Identity_from_Struct(_me, &msg->header.me) == NULL)
vb@1088
   794
        goto enomem;
vb@1088
   795
vb@1088
   796
    free_identity(_me);
vb@1088
   797
    _me = NULL;
vb@1088
   798
vb@1077
   799
    msg->header.state = (long) state;
vb@1077
   800
edouard@1574
   801
    bool devicegroup = deviceGrouped(session);
vb@1077
   802
    if (devicegroup)
vb@1077
   803
        msg->header.devicegroup = 1;
vb@1077
   804
    else
vb@1077
   805
        msg->header.devicegroup = 0;
vb@1077
   806
vb@1059
   807
    if (asn_check_constraints(&asn_DEF_DeviceGroup_Protocol, msg, NULL, NULL)) {
vb@1059
   808
        status = PEP_CONTRAINTS_VIOLATED;
vb@1059
   809
        goto error;
vb@1059
   810
    }
vb@1059
   811
vb@1059
   812
    ssize_t size = uper_encode_to_new_buffer(&asn_DEF_DeviceGroup_Protocol,
vb@1059
   813
            NULL, msg, (void **) &payload);
vb@1059
   814
    if (size == -1) {
vb@1059
   815
        status = PEP_CANNOT_ENCODE;
vb@1059
   816
        goto error;
vb@1059
   817
    }
vb@1059
   818
vb@1059
   819
    status = prepare_message(me, partner, payload, size, &_message);
vb@1059
   820
    if (status != PEP_STATUS_OK)
vb@1059
   821
        goto error;
vb@1059
   822
    payload = NULL;
vb@1059
   823
    free_identity(me);
vb@1059
   824
    me = NULL;
vb@1059
   825
edouard@1494
   826
#ifndef NDEBUG
edouard@1494
   827
    asn_enc_rval_t er;
edouard@1494
   828
    er = xer_encode(&asn_DEF_DeviceGroup_Protocol, msg, 
edouard@1494
   829
                    XER_F_BASIC, _append, &_message->longmsg);
edouard@1494
   830
    if(er.encoded == -1)
edouard@1494
   831
        goto error;
edouard@1494
   832
#endif
edouard@1494
   833
vb@1097
   834
    if (encrypted) {
edouard@1386
   835
        if (msg->payload.present == DeviceGroup_Protocol__payload_PR_groupKeys || 
edouard@1386
   836
            msg->payload.present == DeviceGroup_Protocol__payload_PR_groupUpdate) {
vb@1101
   837
            PEP_rating rating = PEP_rating_undefined;
vb@1101
   838
            status = outgoing_message_rating(session, _message, &rating);
vb@1101
   839
            if (status != PEP_STATUS_OK)
vb@1101
   840
                goto error;
vb@1101
   841
            if (rating < PEP_rating_trusted) {
vb@1101
   842
                status = PEP_SYNC_NO_TRUST;
vb@1101
   843
                goto error;
vb@1101
   844
            }
edouard@1386
   845
            
edouard@1364
   846
            stringlist_t *keylist = NULL;
edouard@1412
   847
            status = _own_keys_retrieve(session, &keylist, PEP_idf_not_for_sync);
edouard@1364
   848
            if (status != PEP_STATUS_OK)
edouard@1364
   849
                goto error;
edouard@1281
   850
edouard@1364
   851
            for (stringlist_t *_keylist=keylist; _keylist!=NULL; _keylist=_keylist->next) {
edouard@1364
   852
                char *fpr = _keylist->value;
vb@1133
   853
                static char filename[MAX_LINELENGTH];
vb@1133
   854
                int result = snprintf(filename, MAX_LINELENGTH, "%s-sec.asc", fpr);
vb@1133
   855
                if (result < 0)
vb@1133
   856
                    goto enomem;
vb@1133
   857
                char *key = NULL;
vb@1133
   858
                size_t size = 0;
vb@1133
   859
                status = export_secrect_key(session, fpr, &key, &size);
vb@1133
   860
                if (status != PEP_STATUS_OK)
vb@1133
   861
                    goto error;
vb@1104
   862
                bloblist_t *bl = bloblist_add(_message->attachments,
vb@1133
   863
                        (char *) key, size, "application/pgp-keys", filename);
vb@1104
   864
                if (!bl)
vb@1104
   865
                    goto enomem;
vb@1104
   866
                if (!_message->attachments)
vb@1104
   867
                    _message->attachments = bl;
vb@1104
   868
            }
vb@1101
   869
        }
vb@1101
   870
vb@1097
   871
        message *_encrypted = NULL;
vb@1097
   872
        status = encrypt_message(session, _message, NULL, &_encrypted, PEP_enc_PEP, 0);
vb@1097
   873
        if (status != PEP_STATUS_OK)
vb@1097
   874
            goto error;
vb@1097
   875
        free_message(_message);
vb@1097
   876
        _message = _encrypted;
vb@1097
   877
    }
vb@1131
   878
    else {
vb@1131
   879
        attach_own_key(session, _message);
vb@1131
   880
    }
vb@1059
   881
vb@1097
   882
    status = session->messageToSend(session->sync_obj, _message);
vb@1059
   883
    return status;
vb@1059
   884
vb@1059
   885
enomem:
vb@1059
   886
    status = PEP_OUT_OF_MEMORY;
vb@1059
   887
error:
vb@1088
   888
    free_identity(_me);
vb@1059
   889
    free(payload);
vb@1059
   890
    free_message(_message);
vb@1059
   891
    free_identity(me);
vb@1059
   892
    return status;
vb@1059
   893
}
vb@1059
   894
vb@1059
   895
PEP_STATUS multicast_self_msg(
vb@1059
   896
        PEP_SESSION session,
vb@1059
   897
        DeviceState_state state,
vb@1097
   898
        DeviceGroup_Protocol_t *msg,
vb@1097
   899
        bool encrypted
vb@1059
   900
    )
vb@1059
   901
{
vb@1059
   902
    PEP_STATUS status = PEP_STATUS_OK;
vb@1059
   903
vb@1059
   904
    assert(session && state && msg);
vb@1059
   905
    if (!(session && state && msg))
vb@1059
   906
        return PEP_ILLEGAL_VALUE;
vb@1059
   907
vb@1059
   908
    identity_list *own_identities = NULL;
edouard@1412
   909
    status = _own_identities_retrieve(session, &own_identities, PEP_idf_not_for_sync);
vb@1059
   910
    if (status != PEP_STATUS_OK)
vb@1059
   911
        return status;
vb@1059
   912
vb@1059
   913
    for (identity_list *_i = own_identities; _i && _i->ident; _i = _i->next) {
vb@1091
   914
        pEp_identity *me = _i->ident;
vb@1059
   915
vb@1065
   916
        // FIXME: no deep copy for multicast supported yet
edouard@1281
   917
        // DeviceGroup_Protocol_t *_msg = malloc(sizeof(DeviceGroup_Protocol_t));
edouard@1281
   918
        // assert(_msg);
edouard@1281
   919
        // if (_msg == NULL){
edouard@1281
   920
        //     status = PEP_OUT_OF_MEMORY;
edouard@1281
   921
        //     goto error;
edouard@1281
   922
        // }
edouard@1281
   923
        // memcpy(_msg, msg, sizeof(DeviceGroup_Protocol_t));
edouard@1281
   924
        status = unicast_msg(session, me, state, msg, encrypted);
edouard@1281
   925
        //status = unicast_msg(session, me, state, _msg, encrypted);
edouard@1281
   926
        //free_DeviceGroup_Protocol_msg(_msg);
vb@1059
   927
    }
vb@1059
   928
vb@1059
   929
    free_identity_list(own_identities);
vb@1059
   930
    return PEP_STATUS_OK;
vb@1065
   931
edouard@1281
   932
// error:
edouard@1281
   933
//     free_identity_list(own_identities);
edouard@1281
   934
//     return status;
vb@1059
   935
}
vb@1059
   936
edouard@1597
   937
void free_group_keys_extra(group_keys_extra_t* group_keys_extra)
edouard@1597
   938
{
edouard@1597
   939
    identity_list *group_keys = group_keys_extra->group_keys;
edouard@1597
   940
    char *group_id = group_keys_extra->group_id;
edouard@1597
   941
    free_identity_list(group_keys);
edouard@1597
   942
    free(group_id);
edouard@1597
   943
    free(group_keys_extra);
edouard@1597
   944
}
edouard@1597
   945
edouard@1647
   946
group_keys_extra_t* group_keys_extra_dup(group_keys_extra_t* group_key_extra_src)
edouard@1597
   947
{
edouard@1647
   948
    group_keys_extra_t *group_key_extra_dst;
edouard@1647
   949
    group_key_extra_dst = calloc(1,sizeof(group_keys_extra_t));
edouard@1647
   950
    if(group_key_extra_dst == NULL){
edouard@1597
   951
        return NULL;
edouard@1597
   952
    }
edouard@1597
   953
edouard@1647
   954
    char *group_id = strdup(group_key_extra_src->group_id);
edouard@1597
   955
edouard@1647
   956
    if (group_key_extra_dst->group_id && !group_id){
edouard@1647
   957
        free(group_key_extra_dst);
edouard@1597
   958
        return NULL;
edouard@1597
   959
    }
edouard@1647
   960
    group_key_extra_dst->group_id = group_id;
edouard@1597
   961
edouard@1647
   962
    identity_list *group_keys = identity_list_dup(group_key_extra_src->group_keys);;
edouard@1597
   963
    if (!group_keys) {
edouard@1597
   964
        free(group_id);
edouard@1647
   965
        free(group_key_extra_dst);
edouard@1597
   966
        return NULL;
edouard@1597
   967
    }
edouard@1647
   968
    group_key_extra_dst->group_keys = group_keys;
edouard@1597
   969
edouard@1647
   970
    return group_key_extra_dst;
edouard@1597
   971
}
edouard@1597
   972