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