src/sync_impl.c
author Edouard Tisserant <edouard@pep-project.org>
Sat, 24 Sep 2016 09:27:25 +0200
branchkeysync
changeset 1172 15a75c0cc78f
parent 1170 8949bee99bcd
child 1203 c463238a1942
permissions -rw-r--r--
Sync : changed sync queue payload type so that sync protocol can receive event such as keygen or decrypt failure asynchronously from other sessions. Fixed problem with ownership of payload leading to memory leak in some case.
vb@1059
     1
#include "../asn.1/DeviceGroup-Protocol.h"
vb@1059
     2
#include "sync_impl.h"
vb@1059
     3
#include "pEp_internal.h"
vb@1059
     4
#include "keymanagement.h"
vb@1076
     5
#include "message_api.h"
vb@1059
     6
#include "map_asn1.h"
vb@1059
     7
#include "baseprotocol.h"
vb@1059
     8
vb@1077
     9
#define SYNC_VERSION_MAJOR 1
vb@1077
    10
#define SYNC_VERSION_MINOR 0
vb@1077
    11
edouard@1172
    12
struct _sync_msg_t {
edouard@1172
    13
    bool is_a_message;
edouard@1172
    14
    union {
edouard@1172
    15
        DeviceGroup_Protocol_t *message;
edouard@1172
    16
        struct {
edouard@1172
    17
            DeviceState_event event;
edouard@1172
    18
            Identity partner;
edouard@1172
    19
            void *extra;
edouard@1172
    20
        } event;
edouard@1172
    21
    } u;
edouard@1172
    22
};
edouard@1172
    23
vb@1059
    24
PEP_STATUS receive_sync_msg(
vb@1059
    25
        PEP_SESSION session,
edouard@1172
    26
        sync_msg_t *sync_msg
vb@1059
    27
    )
vb@1059
    28
{
edouard@1172
    29
    PEP_STATUS status;
vb@1059
    30
    void *extra = NULL;
vb@1059
    31
    Identity partner = NULL;
vb@1059
    32
    DeviceState_event event = DeviceState_event_NONE;
edouard@1172
    33
    assert(session && sync_msg);
edouard@1172
    34
    if (!(session && sync_msg))
edouard@1172
    35
        return PEP_ILLEGAL_VALUE;
vb@1059
    36
edouard@1172
    37
    if(sync_msg->is_a_message){
edouard@1172
    38
        DeviceGroup_Protocol_t *msg = sync_msg->u.message;
edouard@1172
    39
        assert(msg && msg->payload.present != DeviceGroup_Protocol__payload_PR_NOTHING);
edouard@1172
    40
        if (!(msg && msg->payload.present != DeviceGroup_Protocol__payload_PR_NOTHING)){
edouard@1172
    41
            status = PEP_OUT_OF_MEMORY;
edouard@1172
    42
            goto error;
edouard@1172
    43
        }
vb@1059
    44
edouard@1172
    45
        switch (msg->payload.present) {
edouard@1172
    46
            case DeviceGroup_Protocol__payload_PR_beacon:
edouard@1172
    47
                partner = Identity_to_Struct(&msg->header.me, NULL);
edouard@1172
    48
                if (!partner){
edouard@1172
    49
                    status = PEP_OUT_OF_MEMORY;
edouard@1172
    50
                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1172
    51
                    goto error;
edouard@1172
    52
                }
edouard@1172
    53
                event = Beacon;
edouard@1172
    54
                break;
vb@1059
    55
edouard@1172
    56
            case DeviceGroup_Protocol__payload_PR_handshakeRequest:
edouard@1172
    57
                partner = Identity_to_Struct(&msg->header.me, NULL);
edouard@1172
    58
                if (!partner){
edouard@1172
    59
                    status = PEP_OUT_OF_MEMORY;
edouard@1172
    60
                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1172
    61
                    goto error;
edouard@1172
    62
                }
edouard@1172
    63
                event = HandshakeRequest;
edouard@1172
    64
                break;
vb@1059
    65
edouard@1172
    66
            case DeviceGroup_Protocol__payload_PR_groupKeys:
edouard@1172
    67
                partner = Identity_to_Struct(&msg->header.me, NULL);
edouard@1172
    68
                if (!partner){
edouard@1172
    69
                    status = PEP_OUT_OF_MEMORY;
edouard@1172
    70
                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1172
    71
                    goto error;
edouard@1172
    72
                }
edouard@1172
    73
                identity_list *group_keys = IdentityList_to_identity_list(
edouard@1172
    74
                        &msg->payload.choice.groupKeys.ownIdentities, NULL);
edouard@1172
    75
                if (!group_keys) {
edouard@1172
    76
                    free_identity(partner);
edouard@1172
    77
                    status = PEP_OUT_OF_MEMORY;
edouard@1172
    78
                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1172
    79
                    goto error;
edouard@1172
    80
                }
edouard@1172
    81
                extra = (void *) group_keys;
edouard@1172
    82
                event = GroupKeys;
edouard@1172
    83
                break;
edouard@1172
    84
edouard@1172
    85
            default:
edouard@1172
    86
                status = PEP_SYNC_ILLEGAL_MESSAGE;
edouard@1172
    87
                ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1172
    88
                goto error;
edouard@1172
    89
        }
edouard@1172
    90
    }
edouard@1172
    91
    else{
edouard@1172
    92
        partner = sync_msg->u.event.partner;
edouard@1172
    93
        extra = sync_msg->u.event.extra;
edouard@1172
    94
        event = sync_msg->u.event.event;
vb@1059
    95
    }
vb@1059
    96
edouard@1172
    97
    status = fsm_DeviceState_inject(session, event, partner, extra);
edouard@1157
    98
edouard@1157
    99
    free_identity(partner);
edouard@1157
   100
edouard@1172
   101
error:
edouard@1172
   102
    free(sync_msg);
edouard@1172
   103
edouard@1159
   104
    return status;
vb@1059
   105
}
vb@1059
   106
edouard@1167
   107
// from sync.c
edouard@1167
   108
int call_inject_sync_msg(PEP_SESSION session, void *msg);
edouard@1167
   109
edouard@1172
   110
PEP_STATUS inject_DeviceState_event(
edouard@1172
   111
    PEP_SESSION session, 
edouard@1172
   112
    DeviceState_event event,
edouard@1172
   113
    Identity partner,
edouard@1172
   114
    void *extra)
edouard@1172
   115
{
edouard@1172
   116
    PEP_STATUS status;
edouard@1172
   117
edouard@1172
   118
    assert(session);
edouard@1172
   119
    if (!(session))
edouard@1172
   120
        return PEP_ILLEGAL_VALUE;
edouard@1172
   121
edouard@1172
   122
    sync_msg_t *sync_msg = malloc(sizeof(sync_msg_t));
edouard@1172
   123
    if(sync_msg == NULL)
edouard@1172
   124
        return PEP_OUT_OF_MEMORY;
edouard@1172
   125
edouard@1172
   126
    sync_msg->is_a_message = false;
edouard@1172
   127
    sync_msg->u.event.partner = partner;
edouard@1172
   128
    sync_msg->u.event.extra = extra;
edouard@1172
   129
    sync_msg->u.event.event = event;
edouard@1172
   130
edouard@1172
   131
    status = call_inject_sync_msg(session, sync_msg);
edouard@1172
   132
    if (status == PEP_SYNC_NO_INJECT_CALLBACK){
edouard@1172
   133
        free(sync_msg);
edouard@1172
   134
    }
edouard@1172
   135
edouard@1172
   136
    return status;
edouard@1172
   137
}
edouard@1172
   138
edouard@1165
   139
PEP_STATUS receive_DeviceState_msg(
edouard@1165
   140
    PEP_SESSION session, 
edouard@1165
   141
    message *src, 
edouard@1165
   142
    PEP_rating rating, 
edouard@1165
   143
    stringlist_t *keylist)
vb@1059
   144
{
vb@1059
   145
    assert(session && src);
vb@1059
   146
    if (!(session && src))
vb@1059
   147
        return PEP_ILLEGAL_VALUE;
vb@1059
   148
vb@1059
   149
    bool found = false;
vb@1092
   150
    
vb@1092
   151
    bloblist_t *last = NULL;
vb@1059
   152
    for (bloblist_t *bl = src->attachments; bl && bl->value; bl = bl->next) {
vb@1132
   153
        if (bl->mime_type && strcasecmp(bl->mime_type, "application/pEp.sync") == 0
vb@1059
   154
                && bl->size) {
vb@1077
   155
            DeviceGroup_Protocol_t *msg = NULL;
vb@1091
   156
            uper_decode_complete(NULL, &asn_DEF_DeviceGroup_Protocol, (void **)
vb@1091
   157
                    &msg, bl->value, bl->size);
vb@1059
   158
            if (msg) {
vb@1088
   159
vb@1088
   160
                int32_t value = (int32_t) msg->header.sequence;
vb@1091
   161
                char *user_id = strndup((char *) msg->header.me.user_id->buf,
vb@1091
   162
                        msg->header.me.user_id->size);
vb@1091
   163
                assert(user_id);
vb@1091
   164
                if (!user_id) {
vb@1091
   165
                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
vb@1091
   166
                    return PEP_OUT_OF_MEMORY;
vb@1091
   167
                }
vb@1091
   168
edouard@1165
   169
                switch (msg->payload.present) {
edouard@1165
   170
                    // HandshakeRequest needs encryption
edouard@1165
   171
                    case DeviceGroup_Protocol__payload_PR_handshakeRequest:
edouard@1165
   172
                        if (rating < PEP_rating_reliable) {
edouard@1165
   173
                            ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1165
   174
                            free(user_id);
edouard@1165
   175
                            goto skip;
edouard@1165
   176
                        }
edouard@1165
   177
                        break;
edouard@1165
   178
                    // accepting GroupKeys needs encryption and trust
edouard@1165
   179
                    case DeviceGroup_Protocol__payload_PR_groupKeys:
edouard@1165
   180
                        if (!keylist || rating < PEP_rating_reliable) {
edouard@1165
   181
                            ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1165
   182
                            free(user_id);
edouard@1165
   183
                            goto skip;
edouard@1165
   184
                        }
edouard@1165
   185
edouard@1165
   186
                        // check trust of identity with the right user_id
edouard@1165
   187
                        pEp_identity *_from = new_identity(src->from->address, 
edouard@1165
   188
                                                           keylist->value,
edouard@1165
   189
                                                           user_id,
edouard@1165
   190
                                                           src->from->username);
edouard@1165
   191
                        if (_from == NULL){
edouard@1165
   192
                            free(user_id);
edouard@1165
   193
                            ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1165
   194
                            return PEP_OUT_OF_MEMORY;
edouard@1165
   195
                        }
edouard@1165
   196
                        PEP_rating this_user_id_rating = PEP_rating_undefined;
edouard@1165
   197
                        identity_rating(session, _from, &this_user_id_rating);
edouard@1165
   198
                        free_identity(_from);
edouard@1165
   199
edouard@1165
   200
                        if (this_user_id_rating < PEP_rating_trusted ) {
edouard@1165
   201
                            ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1165
   202
                            free(user_id);
edouard@1165
   203
                            goto skip;
edouard@1165
   204
                        }
edouard@1165
   205
                        break;
edouard@1165
   206
                    default:
edouard@1165
   207
                        break;
edouard@1165
   208
                }
edouard@1165
   209
edouard@1165
   210
vb@1091
   211
                PEP_STATUS status = sequence_value(session, (char *) user_id,
vb@1091
   212
                        &value);
vb@1088
   213
vb@1088
   214
                if (status == PEP_STATUS_OK) {
edouard@1165
   215
                    found = true;
edouard@1172
   216
                    sync_msg_t *sync_msg = malloc(sizeof(sync_msg_t));
edouard@1172
   217
                    if(sync_msg == NULL){
edouard@1172
   218
                        ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1172
   219
                        return PEP_OUT_OF_MEMORY;
edouard@1172
   220
                    }
edouard@1172
   221
                    sync_msg->is_a_message = true;
edouard@1172
   222
                    sync_msg->u.message = msg;
edouard@1172
   223
                    status = call_inject_sync_msg(session, sync_msg);
edouard@1165
   224
                    if (status != PEP_STATUS_OK){
edouard@1172
   225
                        ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1172
   226
                        if (status == PEP_SYNC_NO_INJECT_CALLBACK){
edouard@1172
   227
                            free(sync_msg);
edouard@1172
   228
                        }
vb@1088
   229
                        return status;
edouard@1165
   230
                    }
edouard@1165
   231
                }
edouard@1165
   232
                else if (status == PEP_OWN_SEQUENCE) {
edouard@1170
   233
                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
edouard@1170
   234
                    return PEP_MESSAGE_DISCARDED;
vb@1088
   235
                }
vb@1059
   236
            }
vb@1092
   237
vb@1110
   238
            if (!session->keep_sync_msg) {
vb@1110
   239
                bloblist_t *blob = bl;
vb@1110
   240
                if (last)
vb@1110
   241
                    last->next = bl->next;
vb@1110
   242
                else
vb@1110
   243
                    src->attachments = bl->next;
vb@1092
   244
vb@1110
   245
                blob->next = NULL;
vb@1110
   246
                free_bloblist(blob);
vb@1110
   247
            }
vb@1110
   248
            else {
vb@1110
   249
                last = bl;
vb@1110
   250
            }
vb@1092
   251
        }
vb@1092
   252
        else {
vb@1099
   253
skip:
vb@1092
   254
            last = bl;
vb@1059
   255
        }
vb@1059
   256
    }
vb@1059
   257
vb@1113
   258
    if (found && !session->keep_sync_msg) {
vb@1059
   259
        for (stringpair_list_t *spl = src->opt_fields ; spl && spl->value ;
vb@1059
   260
                spl = spl->next) {
vb@1059
   261
            if (spl->value->key &&
vb@1059
   262
                    strcasecmp(spl->value->key, "pEp-auto-consume") == 0) {
vb@1059
   263
                if (spl->value->value &&
vb@1059
   264
                        strcasecmp(spl->value->value, "yes") == 0)
vb@1059
   265
                    return PEP_MESSAGE_CONSUMED;
vb@1059
   266
            }
vb@1059
   267
        }
vb@1059
   268
    }
vb@1059
   269
vb@1059
   270
    return PEP_STATUS_OK;
vb@1059
   271
}
vb@1059
   272
vb@1059
   273
DeviceGroup_Protocol_t *new_DeviceGroup_Protocol_msg(DeviceGroup_Protocol__payload_PR type)
vb@1059
   274
{
vb@1059
   275
    DeviceGroup_Protocol_t *msg = (DeviceGroup_Protocol_t *)
vb@1073
   276
            calloc(1, sizeof(DeviceGroup_Protocol_t));
vb@1059
   277
    assert(msg);
vb@1059
   278
    if (!msg)
vb@1059
   279
        return NULL;
vb@1059
   280
    msg->payload.present = type;
vb@1059
   281
    return msg;
vb@1059
   282
}
vb@1059
   283
vb@1059
   284
void free_DeviceGroup_Protocol_msg(DeviceGroup_Protocol_t *msg)
vb@1059
   285
{
vb@1059
   286
    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
vb@1059
   287
}
vb@1059
   288
vb@1059
   289
PEP_STATUS unicast_msg(
vb@1059
   290
        PEP_SESSION session,
vb@1091
   291
        const Identity partner,
vb@1059
   292
        DeviceState_state state,
vb@1097
   293
        DeviceGroup_Protocol_t *msg,
vb@1097
   294
        bool encrypted
vb@1059
   295
    )
vb@1059
   296
{
vb@1059
   297
    PEP_STATUS status = PEP_STATUS_OK;
vb@1059
   298
    char *payload = NULL;
vb@1059
   299
    message *_message = NULL;
vb@1059
   300
    pEp_identity *me = NULL;
vb@1088
   301
    pEp_identity *_me = NULL;
vb@1059
   302
vb@1059
   303
    assert(session && partner && state && msg);
vb@1059
   304
    if (!(session && partner && state && msg))
vb@1059
   305
        return PEP_ILLEGAL_VALUE;
vb@1059
   306
vb@1059
   307
    assert(session->messageToSend);
vb@1059
   308
    if (!session->messageToSend) {
vb@1059
   309
        status = PEP_SEND_FUNCTION_NOT_REGISTERED;
vb@1059
   310
        goto error;
vb@1059
   311
    }
vb@1059
   312
vb@1077
   313
    msg->header.version.major = SYNC_VERSION_MAJOR;
vb@1077
   314
    msg->header.version.minor = SYNC_VERSION_MINOR;
vb@1077
   315
vb@1071
   316
    status = get_identity(session, partner->address, PEP_OWN_USERID, &me);
vb@1059
   317
    if (status != PEP_STATUS_OK)
vb@1059
   318
        goto error;
vb@1088
   319
    
vb@1088
   320
    int32_t seq = 0;
vb@1088
   321
vb@1091
   322
    status = sequence_value(session, sync_uuid, &seq);
vb@1088
   323
    if (status != PEP_OWN_SEQUENCE && status != PEP_STATUS_OK)
vb@1088
   324
        goto error;
vb@1088
   325
vb@1088
   326
    msg->header.sequence = (long) seq;
vb@1088
   327
vb@1088
   328
    _me = identity_dup(me);
vb@1088
   329
    if (!_me)
vb@1059
   330
        goto enomem;
vb@1059
   331
vb@1088
   332
    free(_me->user_id);
vb@1091
   333
    _me->user_id = strndup(sync_uuid, 36);
vb@1088
   334
    assert(_me->user_id);
vb@1088
   335
    if (!_me->user_id)
vb@1088
   336
        goto enomem;
vb@1088
   337
vb@1088
   338
    if (Identity_from_Struct(_me, &msg->header.me) == NULL)
vb@1088
   339
        goto enomem;
vb@1088
   340
vb@1088
   341
    free_identity(_me);
vb@1088
   342
    _me = NULL;
vb@1088
   343
vb@1077
   344
    msg->header.state = (long) state;
vb@1077
   345
vb@1077
   346
    bool devicegroup = storedGroupKeys(session);
vb@1077
   347
    if (devicegroup)
vb@1077
   348
        msg->header.devicegroup = 1;
vb@1077
   349
    else
vb@1077
   350
        msg->header.devicegroup = 0;
vb@1077
   351
vb@1059
   352
    if (asn_check_constraints(&asn_DEF_DeviceGroup_Protocol, msg, NULL, NULL)) {
vb@1059
   353
        status = PEP_CONTRAINTS_VIOLATED;
vb@1059
   354
        goto error;
vb@1059
   355
    }
vb@1059
   356
vb@1059
   357
    ssize_t size = uper_encode_to_new_buffer(&asn_DEF_DeviceGroup_Protocol,
vb@1059
   358
            NULL, msg, (void **) &payload);
vb@1059
   359
    if (size == -1) {
vb@1059
   360
        status = PEP_CANNOT_ENCODE;
vb@1059
   361
        goto error;
vb@1059
   362
    }
vb@1059
   363
vb@1059
   364
    status = prepare_message(me, partner, payload, size, &_message);
vb@1059
   365
    if (status != PEP_STATUS_OK)
vb@1059
   366
        goto error;
vb@1059
   367
    payload = NULL;
vb@1059
   368
    free_identity(me);
vb@1059
   369
    me = NULL;
vb@1059
   370
vb@1097
   371
    if (encrypted) {
vb@1101
   372
        if (msg->payload.present == DeviceGroup_Protocol__payload_PR_groupKeys) {
vb@1101
   373
            PEP_rating rating = PEP_rating_undefined;
vb@1101
   374
            status = outgoing_message_rating(session, _message, &rating);
vb@1101
   375
            if (status != PEP_STATUS_OK)
vb@1101
   376
                goto error;
vb@1101
   377
            if (rating < PEP_rating_trusted) {
vb@1101
   378
                status = PEP_SYNC_NO_TRUST;
vb@1101
   379
                goto error;
vb@1101
   380
            }
vb@1104
   381
            
vb@1104
   382
            IdentityList_t *list = &msg->payload.choice.groupKeys.ownIdentities;
vb@1104
   383
            for (int i=0; i<list->list.count; i++) {
vb@1104
   384
                Identity_t *ident = list->list.array[i];
vb@1133
   385
                char *fpr = strndup((const char *)ident->fpr.buf, ident->fpr.size);
vb@1133
   386
                assert(fpr);
vb@1133
   387
                if (!fpr)
vb@1133
   388
                    goto enomem;
vb@1133
   389
                static char filename[MAX_LINELENGTH];
vb@1133
   390
                int result = snprintf(filename, MAX_LINELENGTH, "%s-sec.asc", fpr);
vb@1133
   391
                if (result < 0)
vb@1133
   392
                    goto enomem;
vb@1133
   393
                char *key = NULL;
vb@1133
   394
                size_t size = 0;
vb@1133
   395
                status = export_secrect_key(session, fpr, &key, &size);
vb@1133
   396
                free(fpr);
vb@1133
   397
                if (status != PEP_STATUS_OK)
vb@1133
   398
                    goto error;
vb@1104
   399
                bloblist_t *bl = bloblist_add(_message->attachments,
vb@1133
   400
                        (char *) key, size, "application/pgp-keys", filename);
vb@1104
   401
                if (!bl)
vb@1104
   402
                    goto enomem;
vb@1104
   403
                if (!_message->attachments)
vb@1104
   404
                    _message->attachments = bl;
vb@1104
   405
            }
vb@1101
   406
        }
vb@1101
   407
vb@1097
   408
        message *_encrypted = NULL;
vb@1097
   409
        status = encrypt_message(session, _message, NULL, &_encrypted, PEP_enc_PEP, 0);
vb@1097
   410
        if (status != PEP_STATUS_OK)
vb@1097
   411
            goto error;
vb@1097
   412
        free_message(_message);
vb@1097
   413
        _message = _encrypted;
vb@1097
   414
    }
vb@1131
   415
    else {
vb@1131
   416
        attach_own_key(session, _message);
vb@1131
   417
    }
vb@1059
   418
vb@1097
   419
    status = session->messageToSend(session->sync_obj, _message);
vb@1059
   420
    return status;
vb@1059
   421
vb@1059
   422
enomem:
vb@1059
   423
    status = PEP_OUT_OF_MEMORY;
vb@1059
   424
error:
vb@1088
   425
    free_identity(_me);
vb@1059
   426
    free(payload);
vb@1059
   427
    free_message(_message);
vb@1059
   428
    free_identity(me);
vb@1059
   429
    return status;
vb@1059
   430
}
vb@1059
   431
vb@1059
   432
PEP_STATUS multicast_self_msg(
vb@1059
   433
        PEP_SESSION session,
vb@1059
   434
        DeviceState_state state,
vb@1097
   435
        DeviceGroup_Protocol_t *msg,
vb@1097
   436
        bool encrypted
vb@1059
   437
    )
vb@1059
   438
{
vb@1059
   439
    PEP_STATUS status = PEP_STATUS_OK;
vb@1059
   440
vb@1059
   441
    assert(session && state && msg);
vb@1059
   442
    if (!(session && state && msg))
vb@1059
   443
        return PEP_ILLEGAL_VALUE;
vb@1059
   444
vb@1059
   445
    identity_list *own_identities = NULL;
vb@1059
   446
    status = own_identities_retrieve(session, &own_identities);
vb@1059
   447
    if (status != PEP_STATUS_OK)
vb@1059
   448
        return status;
vb@1059
   449
vb@1059
   450
    for (identity_list *_i = own_identities; _i && _i->ident; _i = _i->next) {
vb@1091
   451
        pEp_identity *me = _i->ident;
vb@1059
   452
vb@1065
   453
        // FIXME: no deep copy for multicast supported yet
vb@1065
   454
        DeviceGroup_Protocol_t *_msg = malloc(sizeof(DeviceGroup_Protocol_t));
vb@1065
   455
        assert(_msg);
vb@1065
   456
        if (_msg == NULL)
vb@1065
   457
            goto enomem;
vb@1065
   458
        memcpy(_msg, msg, sizeof(DeviceGroup_Protocol_t));
vb@1097
   459
        status = unicast_msg(session, me, state, _msg, encrypted);
vb@1067
   460
        free_DeviceGroup_Protocol_msg(_msg);
vb@1059
   461
    }
vb@1059
   462
vb@1059
   463
    free_identity_list(own_identities);
vb@1059
   464
    return PEP_STATUS_OK;
vb@1065
   465
vb@1065
   466
enomem:
vb@1065
   467
    free_identity_list(own_identities);
vb@1065
   468
    return PEP_OUT_OF_MEMORY;
vb@1059
   469
}
vb@1059
   470