src/sync_actions.c
author Krista Bennett <krista@pep-project.org>
Fri, 04 May 2018 16:30:21 +0200
branchlocal_cpptest
changeset 2652 43b913f99a27
parent 2462 48b526a0daac
child 2829 e444c3c960bb
permissions -rw-r--r--
Shelving broken things to break other things
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
// Actions for DeviceState state machine
krista@2271
     5
krista@2271
     6
#include <assert.h>
krista@2271
     7
#include "pEp_internal.h"
krista@2271
     8
#include "message.h"
krista@2271
     9
#include "sync_fsm.h"
krista@2271
    10
#include "sync_impl.h"
krista@2271
    11
#include "map_asn1.h"
krista@2271
    12
#include "baseprotocol.h"
krista@2271
    13
krista@2271
    14
// conditions
krista@2271
    15
krista@2271
    16
int deviceGrouped(PEP_SESSION session)
krista@2271
    17
{
krista@2271
    18
    assert(session);
krista@2271
    19
    if (!session)
krista@2271
    20
        return invalid_condition; // error
krista@2271
    21
krista@2271
    22
    char *devgrp = NULL;
krista@2271
    23
    int res = 0;
krista@2271
    24
    PEP_STATUS status;
krista@2271
    25
krista@2271
    26
    status = get_device_group(session, &devgrp);
krista@2271
    27
krista@2271
    28
    if (status == PEP_STATUS_OK && devgrp && devgrp[0])
krista@2271
    29
        res = 1;
krista@2271
    30
krista@2271
    31
    free(devgrp);
krista@2271
    32
krista@2271
    33
    return res;
krista@2271
    34
}
krista@2271
    35
krista@2271
    36
int keyElectionWon(PEP_SESSION session, Identity partner)
krista@2271
    37
{
krista@2271
    38
    assert(session);
krista@2271
    39
    assert(partner);
krista@2271
    40
    if (!(session && partner))
krista@2271
    41
        return invalid_condition; // error
krista@2271
    42
krista@2271
    43
    int partner_is_group = partner->flags & PEP_idf_devicegroup;
krista@2271
    44
krista@2271
    45
    if (deviceGrouped(session)){
krista@2271
    46
        // existing group always wins against sole device
krista@2271
    47
        if(!partner_is_group)
krista@2271
    48
            return 1;
krista@2271
    49
    } else {
krista@2271
    50
        // sole device always loses against group
krista@2271
    51
        if(partner_is_group)
krista@2271
    52
            return 0;
krista@2271
    53
    }
krista@2271
    54
krista@2271
    55
    // two groups or two sole are elected based on key age
krista@2271
    56
    // key created first wins
krista@2271
    57
krista@2271
    58
    Identity me = NULL;
krista@2461
    59
    
krista@2461
    60
    char* own_id = NULL;
krista@2461
    61
    PEP_STATUS status = get_default_own_userid(session, &own_id);
krista@2461
    62
    if (own_id) {
krista@2461
    63
        status = get_identity(session, partner->address, own_id,
krista@2461
    64
                              &me);
krista@2461
    65
        free(own_id);
krista@2461
    66
    }
krista@2271
    67
    if (status == PEP_OUT_OF_MEMORY)
krista@2271
    68
        return invalid_out_of_memory;
krista@2271
    69
    if (status != PEP_STATUS_OK)
krista@2271
    70
        return invalid_condition; // error
krista@2271
    71
krista@2271
    72
    int result = invalid_condition; // error state has to be overwritten
krista@2271
    73
krista@2271
    74
    time_t own_created;
krista@2271
    75
    time_t partners_created;
krista@2271
    76
krista@2271
    77
    status = key_created(session, me->fpr, &own_created);
krista@2271
    78
    if (status != PEP_STATUS_OK)
krista@2271
    79
        goto the_end;
krista@2271
    80
krista@2271
    81
    status = key_created(session, partner->fpr, &partners_created);
krista@2271
    82
    if (status != PEP_STATUS_OK)
krista@2271
    83
        goto the_end;
krista@2271
    84
krista@2271
    85
    if (own_created > partners_created)
krista@2271
    86
        result = 0;
krista@2271
    87
    else
krista@2271
    88
        result = 1;
krista@2271
    89
krista@2271
    90
the_end:
krista@2271
    91
    free_identity(me);
krista@2271
    92
    return result;
krista@2271
    93
}
krista@2271
    94
krista@2271
    95
int sameIdentities(PEP_SESSION session, Identity a, Identity b)
krista@2271
    96
{
krista@2271
    97
    assert(session);
krista@2271
    98
    assert(a);
krista@2271
    99
    assert(b);
krista@2271
   100
krista@2271
   101
    if (!(session && a && b))
krista@2271
   102
        return invalid_condition; // error
krista@2271
   103
krista@2271
   104
    if (a->fpr == NULL || b->fpr == NULL ||
krista@2271
   105
        (!_same_fpr(a->fpr, strlen(a->fpr), b->fpr, strlen(b->fpr))) ||
krista@2271
   106
        a->address == NULL || b->address == NULL ||
krista@2271
   107
        strcmp(a->address, b->address) != 0 ||
krista@2271
   108
        a->user_id == NULL || b->user_id == NULL ||
krista@2271
   109
        strcmp(a->user_id, b->user_id) != 0)
krista@2271
   110
            return 0;
krista@2271
   111
    return 1;
krista@2271
   112
}
krista@2271
   113
krista@2271
   114
int sameKeyAndAddress(PEP_SESSION session, Identity a, Identity b)
krista@2271
   115
{
krista@2271
   116
    assert(session);
krista@2271
   117
    assert(a);
krista@2271
   118
    assert(b);
krista@2271
   119
krista@2271
   120
    if (!(session && a && b))
krista@2271
   121
        return invalid_condition; // error
krista@2271
   122
krista@2271
   123
    if (a->fpr == NULL || b->fpr == NULL ||
krista@2271
   124
        (!_same_fpr(a->fpr, strlen(a->fpr), b->fpr, strlen(b->fpr))) ||
krista@2271
   125
        a->address == NULL || b->address == NULL ||
krista@2271
   126
        strcmp(a->address, b->address) != 0)
krista@2271
   127
            return 0;
krista@2271
   128
    return 1;
krista@2271
   129
}
krista@2271
   130
krista@2271
   131
// actions
krista@2271
   132
krista@2271
   133
PEP_STATUS _notifyHandshake(
krista@2271
   134
        PEP_SESSION session,
krista@2271
   135
        Identity partner,
krista@2271
   136
        sync_handshake_signal signal
krista@2271
   137
    )
krista@2271
   138
{
krista@2271
   139
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   140
krista@2271
   141
    assert(session);
krista@2271
   142
    assert(partner);
krista@2271
   143
krista@2271
   144
    if (!(session && partner))
krista@2271
   145
        return PEP_ILLEGAL_VALUE;
krista@2271
   146
krista@2271
   147
    assert(session->notifyHandshake);
krista@2271
   148
    if (!session->notifyHandshake)
krista@2271
   149
        return PEP_SYNC_NO_NOTIFY_CALLBACK;
krista@2271
   150
krista@2461
   151
    char* own_id = NULL;
krista@2461
   152
    status = get_default_own_userid(session, &own_id);
krista@2461
   153
        
krista@2271
   154
    // notifyHandshake take ownership of given identities
krista@2271
   155
    pEp_identity *me = NULL;
krista@2461
   156
    if (own_id) {
krista@2461
   157
        status = get_identity(session, partner->address, own_id, &me);
krista@2461
   158
        free(own_id);
krista@2461
   159
    }
krista@2271
   160
    if (status != PEP_STATUS_OK)
krista@2271
   161
        goto error;
krista@2271
   162
    
krista@2271
   163
    pEp_identity *_partner = NULL;
krista@2271
   164
    _partner = identity_dup(partner);
krista@2271
   165
    if (_partner == NULL){
krista@2271
   166
        status = PEP_OUT_OF_MEMORY;
krista@2271
   167
        goto error;
krista@2271
   168
    }
krista@2271
   169
krista@2271
   170
    status = session->notifyHandshake(session->sync_obj, me, _partner, signal);
krista@2271
   171
    if (status != PEP_STATUS_OK)
krista@2271
   172
        goto error;
krista@2271
   173
krista@2271
   174
    return status;
krista@2271
   175
krista@2271
   176
error:
krista@2271
   177
    free_identity(me);
krista@2271
   178
    return status;
krista@2271
   179
}
krista@2271
   180
krista@2271
   181
// acceptHandshake() - stores acception of partner
krista@2271
   182
//
krista@2271
   183
//  params:
krista@2271
   184
//      session (in)        session handle
krista@2271
   185
//      state (in)          state the state machine is in
krista@2271
   186
//      partner (in)        partner to communicate with
krista@2271
   187
//
krista@2271
   188
//  returns:
krista@2271
   189
//      PEP_STATUS_OK or any other value on error
krista@2271
   190
krista@2271
   191
PEP_STATUS acceptHandshake(
krista@2271
   192
        PEP_SESSION session,
krista@2271
   193
        DeviceState_state state,
krista@2271
   194
        Identity partner,
krista@2271
   195
        void *extra
krista@2271
   196
    )
krista@2271
   197
{
krista@2271
   198
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   199
krista@2271
   200
    assert(session);
krista@2271
   201
    assert(partner);
krista@2271
   202
    assert(extra == NULL);
krista@2271
   203
    if (!(session && partner))
krista@2271
   204
        return PEP_ILLEGAL_VALUE;
krista@2271
   205
krista@2271
   206
    status = trust_personal_key(session, partner);
krista@2271
   207
krista@2271
   208
    return status;
krista@2271
   209
}
krista@2271
   210
krista@2271
   211
krista@2271
   212
// rejectHandshake() - stores rejection of partner
krista@2271
   213
//
krista@2271
   214
//  params:
krista@2271
   215
//      session (in)        session handle
krista@2271
   216
//      state (in)          state the state machine is in
krista@2271
   217
//      partner (in)        partner to communicate with
krista@2271
   218
//
krista@2271
   219
//  returns:
krista@2271
   220
//      PEP_STATUS_OK or any other value on error
krista@2271
   221
krista@2271
   222
PEP_STATUS rejectHandshake(
krista@2271
   223
        PEP_SESSION session,
krista@2271
   224
        DeviceState_state state,
krista@2271
   225
        Identity partner,
krista@2271
   226
        void *extra
krista@2271
   227
    )
krista@2271
   228
{
krista@2271
   229
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   230
krista@2271
   231
    assert(session);
krista@2271
   232
    assert(partner);
krista@2271
   233
    assert(extra == NULL);
krista@2271
   234
    if (!(session && partner))
krista@2271
   235
        return PEP_ILLEGAL_VALUE;
krista@2271
   236
krista@2271
   237
    // TODO : disable sync globally if not in a group
krista@2271
   238
    status = set_identity_flags(session, partner,
krista@2271
   239
            partner->flags | PEP_idf_not_for_sync);
krista@2271
   240
krista@2271
   241
    return status;
krista@2271
   242
}
krista@2271
   243
krista@2271
   244
PEP_STATUS _storeGroupKeys(
krista@2271
   245
        PEP_SESSION session,
krista@2271
   246
        identity_list *group_keys
krista@2271
   247
    )
krista@2271
   248
{
krista@2271
   249
    PEP_STATUS status = PEP_STATUS_OK;
krista@2461
   250
    
krista@2461
   251
    char* own_id = NULL;
krista@2461
   252
    status = get_default_own_userid(session, &own_id);
krista@2461
   253
    
krista@2461
   254
    // FIXME: Is this where and what we wanna do with this?
krista@2461
   255
    if (status != PEP_STATUS_OK)
krista@2461
   256
        return status;
krista@2461
   257
        
krista@2271
   258
    for (identity_list *il = group_keys; il && il->ident; il = il->next) {
krista@2271
   259
krista@2461
   260
        if (strcmp(il->ident->user_id, own_id)!=0) {
krista@2271
   261
            assert(0);
krista@2271
   262
            continue;
krista@2271
   263
        }
krista@2271
   264
        // Check that identity isn't excluded from sync.
krista@2271
   265
        pEp_identity *stored_identity = NULL;
krista@2461
   266
        status = get_identity(session, il->ident->address, own_id,
krista@2271
   267
                &stored_identity);
krista@2271
   268
        if (status == PEP_STATUS_OK) {
krista@2271
   269
            if(stored_identity->flags & PEP_idf_not_for_sync){
krista@2271
   270
                free_identity(stored_identity);
krista@2271
   271
                continue;
krista@2271
   272
            }
krista@2271
   273
            free_identity(stored_identity);
krista@2271
   274
        }
krista@2271
   275
krista@2271
   276
        status = set_identity(session, il->ident);
krista@2271
   277
        if (status != PEP_STATUS_OK)
krista@2271
   278
            break;
krista@2271
   279
    }
krista@2461
   280
    
krista@2461
   281
    free(own_id);
krista@2271
   282
    return status;
krista@2271
   283
}
krista@2271
   284
    
krista@2271
   285
krista@2271
   286
// storeGroupKeys() - 
krista@2271
   287
//
krista@2271
   288
//  params:
krista@2271
   289
//      session (in)        session handle
krista@2271
   290
//      state (in)          state the state machine is in
krista@2271
   291
//      partner (in)        partner to communicate with
krista@2271
   292
//      _group_keys (in)    group keys received from partner
krista@2271
   293
//
krista@2271
   294
//  returns:
krista@2271
   295
//      PEP_STATUS_OK or any other value on error
krista@2271
   296
krista@2271
   297
PEP_STATUS storeGroupKeys(
krista@2271
   298
        PEP_SESSION session,
krista@2271
   299
        DeviceState_state state,
krista@2271
   300
        Identity partner,
krista@2271
   301
        void *group_keys_extra_
krista@2271
   302
    )
krista@2271
   303
{
krista@2271
   304
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   305
krista@2271
   306
    assert(session);
krista@2271
   307
    assert(partner);
krista@2271
   308
    assert(group_keys_extra_);
krista@2271
   309
    if (!(session && partner && group_keys_extra_))
krista@2271
   310
        return PEP_ILLEGAL_VALUE;
krista@2271
   311
krista@2271
   312
    group_keys_extra_t *group_keys_extra = 
krista@2271
   313
        (group_keys_extra_t*) group_keys_extra_;
krista@2271
   314
    identity_list *group_keys = group_keys_extra->group_keys;
krista@2271
   315
    char *group_id = group_keys_extra->group_id;
krista@2271
   316
krista@2271
   317
    status = _storeGroupKeys(session, group_keys);
krista@2271
   318
    if (status != PEP_STATUS_OK)
krista@2271
   319
        return status;
krista@2271
   320
krista@2271
   321
    // set group id according to given group-id
krista@2271
   322
    status = set_device_group(session, group_id);
krista@2271
   323
    if (status != PEP_STATUS_OK)
krista@2271
   324
        return status;
krista@2271
   325
    
krista@2271
   326
    return status;
krista@2271
   327
}
krista@2271
   328
krista@2271
   329
// storeGroupUpdate() - 
krista@2271
   330
//
krista@2271
   331
//  params:
krista@2271
   332
//      session (in)        session handle
krista@2271
   333
//      state (in)          state the state machine is in
krista@2271
   334
//      partner (in)        partner to communicate with
krista@2271
   335
//      _group_keys (in)    group keys received from partner
krista@2271
   336
//
krista@2271
   337
//  returns:
krista@2271
   338
//      PEP_STATUS_OK or any other value on error
krista@2271
   339
krista@2271
   340
PEP_STATUS storeGroupUpdate(
krista@2271
   341
        PEP_SESSION session,
krista@2271
   342
        DeviceState_state state,
krista@2271
   343
        Identity partner,
krista@2271
   344
        void *group_keys_
krista@2271
   345
    )
krista@2271
   346
{
krista@2271
   347
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   348
krista@2271
   349
    assert(session);
krista@2271
   350
    assert(partner);
krista@2271
   351
    assert(group_keys_);
krista@2271
   352
    if (!(session && partner && group_keys_))
krista@2271
   353
        return PEP_ILLEGAL_VALUE;
krista@2271
   354
krista@2271
   355
    identity_list *group_keys = (identity_list*) group_keys_;
krista@2271
   356
krista@2271
   357
    status = _storeGroupKeys(session, group_keys);
krista@2271
   358
krista@2271
   359
krista@2271
   360
    return status;
krista@2271
   361
}
krista@2271
   362
krista@2271
   363
// makeGroup() - 
krista@2271
   364
//
krista@2271
   365
//  params:
krista@2271
   366
//      session (in)        session handle
krista@2271
   367
//      state (in)          state the state machine is in
krista@2271
   368
//      partner (in)        ignored
krista@2271
   369
//      extra (in)          ignored
krista@2271
   370
//
krista@2271
   371
//  returns:
krista@2271
   372
//      PEP_STATUS_OK or any other value on error
krista@2271
   373
krista@2271
   374
PEP_STATUS makeGroup(
krista@2271
   375
        PEP_SESSION session,
krista@2271
   376
        DeviceState_state state,
krista@2271
   377
        Identity partner,
krista@2271
   378
        void *extra
krista@2271
   379
    )
krista@2271
   380
{
krista@2271
   381
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   382
krista@2271
   383
    assert(session);
krista@2271
   384
   
krista@2271
   385
    // make a new uuid 
krista@2271
   386
    char new_uuid[37];
krista@2271
   387
    pEpUUID uuid;
krista@2271
   388
    uuid_generate_random(uuid);
krista@2271
   389
    uuid_unparse_upper(uuid, new_uuid);
krista@2271
   390
krista@2271
   391
    // take that new uuid as group-id
krista@2271
   392
    status = set_device_group(session, new_uuid);
krista@2271
   393
krista@2271
   394
    return status;
krista@2271
   395
}
krista@2271
   396
krista@2271
   397
// renewUUID() - 
krista@2271
   398
//
krista@2271
   399
//  params:
krista@2271
   400
//      session (in)        session handle
krista@2271
   401
//      state (in)          state the state machine is in
krista@2271
   402
//      partner (in)        ignored
krista@2271
   403
//      extra (in)          ignored
krista@2271
   404
//
krista@2271
   405
//  returns:
krista@2271
   406
//      PEP_STATUS_OK or any other value on error
krista@2271
   407
krista@2271
   408
PEP_STATUS renewUUID(
krista@2271
   409
        PEP_SESSION session,
krista@2271
   410
        DeviceState_state state,
krista@2271
   411
        Identity partner,
krista@2271
   412
        void *extra
krista@2271
   413
    )
krista@2271
   414
{
krista@2271
   415
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   416
krista@2271
   417
    assert(session);
krista@2271
   418
krista@2271
   419
    // change sync_uuid when entering group 
krista@2271
   420
    // thus ignoring unprocessed handshakes
krista@2271
   421
    // addressed to previous self (sole) once in.
krista@2271
   422
    pEpUUID uuid;
krista@2271
   423
    uuid_generate_random(uuid);
krista@2271
   424
    uuid_unparse_upper(uuid, session->sync_uuid);
krista@2271
   425
    
krista@2271
   426
    return status;
krista@2271
   427
}
krista@2271
   428
krista@2271
   429
// leaveGroup() - 
krista@2271
   430
//
krista@2271
   431
//  params:
krista@2271
   432
//      session (in)        session handle
krista@2271
   433
//      state (in)          state the state machine is in
krista@2271
   434
//      partner (in)        ignored
krista@2271
   435
//      extra (in)          ignored
krista@2271
   436
//
krista@2271
   437
//  returns:
krista@2271
   438
//      PEP_STATUS_OK or any other value on error
krista@2271
   439
krista@2271
   440
PEP_STATUS leaveGroup(
krista@2271
   441
        PEP_SESSION session,
krista@2271
   442
        DeviceState_state state,
krista@2271
   443
        Identity partner,
krista@2271
   444
        void *extra
krista@2271
   445
    )
krista@2271
   446
{
krista@2271
   447
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   448
krista@2271
   449
    assert(session);
krista@2271
   450
krista@2271
   451
    status = set_device_group(session, NULL);
krista@2271
   452
    
krista@2271
   453
    return status;
krista@2271
   454
}