src/sync_actions.c
author Krista Bennett <krista@pep-project.org>
Fri, 03 Nov 2017 13:32:38 +0100
changeset 2271 25bfd109320c
child 2287 026ab4dae779
child 2461 85c8e5aad3bc
permissions -rw-r--r--
SYNC HAS RETURNED. Keysync still removed from Engine.
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@2271
    59
    PEP_STATUS status = get_identity(session, partner->address, PEP_OWN_USERID,
krista@2271
    60
            &me);
krista@2271
    61
    if (status == PEP_OUT_OF_MEMORY)
krista@2271
    62
        return invalid_out_of_memory;
krista@2271
    63
    if (status != PEP_STATUS_OK)
krista@2271
    64
        return invalid_condition; // error
krista@2271
    65
krista@2271
    66
    int result = invalid_condition; // error state has to be overwritten
krista@2271
    67
krista@2271
    68
    time_t own_created;
krista@2271
    69
    time_t partners_created;
krista@2271
    70
krista@2271
    71
    status = key_created(session, me->fpr, &own_created);
krista@2271
    72
    if (status != PEP_STATUS_OK)
krista@2271
    73
        goto the_end;
krista@2271
    74
krista@2271
    75
    status = key_created(session, partner->fpr, &partners_created);
krista@2271
    76
    if (status != PEP_STATUS_OK)
krista@2271
    77
        goto the_end;
krista@2271
    78
krista@2271
    79
    if (own_created > partners_created)
krista@2271
    80
        result = 0;
krista@2271
    81
    else
krista@2271
    82
        result = 1;
krista@2271
    83
krista@2271
    84
the_end:
krista@2271
    85
    free_identity(me);
krista@2271
    86
    return result;
krista@2271
    87
}
krista@2271
    88
krista@2271
    89
int sameIdentities(PEP_SESSION session, Identity a, Identity b)
krista@2271
    90
{
krista@2271
    91
    assert(session);
krista@2271
    92
    assert(a);
krista@2271
    93
    assert(b);
krista@2271
    94
krista@2271
    95
    if (!(session && a && b))
krista@2271
    96
        return invalid_condition; // error
krista@2271
    97
krista@2271
    98
    if (a->fpr == NULL || b->fpr == NULL ||
krista@2271
    99
        (!_same_fpr(a->fpr, strlen(a->fpr), b->fpr, strlen(b->fpr))) ||
krista@2271
   100
        a->address == NULL || b->address == NULL ||
krista@2271
   101
        strcmp(a->address, b->address) != 0 ||
krista@2271
   102
        a->user_id == NULL || b->user_id == NULL ||
krista@2271
   103
        strcmp(a->user_id, b->user_id) != 0)
krista@2271
   104
            return 0;
krista@2271
   105
    return 1;
krista@2271
   106
}
krista@2271
   107
krista@2271
   108
int sameKeyAndAddress(PEP_SESSION session, Identity a, Identity b)
krista@2271
   109
{
krista@2271
   110
    assert(session);
krista@2271
   111
    assert(a);
krista@2271
   112
    assert(b);
krista@2271
   113
krista@2271
   114
    if (!(session && a && b))
krista@2271
   115
        return invalid_condition; // error
krista@2271
   116
krista@2271
   117
    if (a->fpr == NULL || b->fpr == NULL ||
krista@2271
   118
        (!_same_fpr(a->fpr, strlen(a->fpr), b->fpr, strlen(b->fpr))) ||
krista@2271
   119
        a->address == NULL || b->address == NULL ||
krista@2271
   120
        strcmp(a->address, b->address) != 0)
krista@2271
   121
            return 0;
krista@2271
   122
    return 1;
krista@2271
   123
}
krista@2271
   124
krista@2271
   125
// actions
krista@2271
   126
krista@2271
   127
PEP_STATUS _notifyHandshake(
krista@2271
   128
        PEP_SESSION session,
krista@2271
   129
        Identity partner,
krista@2271
   130
        sync_handshake_signal signal
krista@2271
   131
    )
krista@2271
   132
{
krista@2271
   133
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   134
krista@2271
   135
    assert(session);
krista@2271
   136
    assert(partner);
krista@2271
   137
krista@2271
   138
    if (!(session && partner))
krista@2271
   139
        return PEP_ILLEGAL_VALUE;
krista@2271
   140
krista@2271
   141
    assert(session->notifyHandshake);
krista@2271
   142
    if (!session->notifyHandshake)
krista@2271
   143
        return PEP_SYNC_NO_NOTIFY_CALLBACK;
krista@2271
   144
krista@2271
   145
    // notifyHandshake take ownership of given identities
krista@2271
   146
    pEp_identity *me = NULL;
krista@2271
   147
    status = get_identity(session, partner->address, PEP_OWN_USERID, &me);
krista@2271
   148
    if (status != PEP_STATUS_OK)
krista@2271
   149
        goto error;
krista@2271
   150
    
krista@2271
   151
    pEp_identity *_partner = NULL;
krista@2271
   152
    _partner = identity_dup(partner);
krista@2271
   153
    if (_partner == NULL){
krista@2271
   154
        status = PEP_OUT_OF_MEMORY;
krista@2271
   155
        goto error;
krista@2271
   156
    }
krista@2271
   157
krista@2271
   158
    status = session->notifyHandshake(session->sync_obj, me, _partner, signal);
krista@2271
   159
    if (status != PEP_STATUS_OK)
krista@2271
   160
        goto error;
krista@2271
   161
krista@2271
   162
    return status;
krista@2271
   163
krista@2271
   164
error:
krista@2271
   165
    free_identity(me);
krista@2271
   166
    return status;
krista@2271
   167
}
krista@2271
   168
krista@2271
   169
// acceptHandshake() - stores acception of partner
krista@2271
   170
//
krista@2271
   171
//  params:
krista@2271
   172
//      session (in)        session handle
krista@2271
   173
//      state (in)          state the state machine is in
krista@2271
   174
//      partner (in)        partner to communicate with
krista@2271
   175
//
krista@2271
   176
//  returns:
krista@2271
   177
//      PEP_STATUS_OK or any other value on error
krista@2271
   178
krista@2271
   179
PEP_STATUS acceptHandshake(
krista@2271
   180
        PEP_SESSION session,
krista@2271
   181
        DeviceState_state state,
krista@2271
   182
        Identity partner,
krista@2271
   183
        void *extra
krista@2271
   184
    )
krista@2271
   185
{
krista@2271
   186
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   187
krista@2271
   188
    assert(session);
krista@2271
   189
    assert(partner);
krista@2271
   190
    assert(extra == NULL);
krista@2271
   191
    if (!(session && partner))
krista@2271
   192
        return PEP_ILLEGAL_VALUE;
krista@2271
   193
krista@2271
   194
    status = trust_personal_key(session, partner);
krista@2271
   195
krista@2271
   196
    return status;
krista@2271
   197
}
krista@2271
   198
krista@2271
   199
krista@2271
   200
// rejectHandshake() - stores rejection of partner
krista@2271
   201
//
krista@2271
   202
//  params:
krista@2271
   203
//      session (in)        session handle
krista@2271
   204
//      state (in)          state the state machine is in
krista@2271
   205
//      partner (in)        partner to communicate with
krista@2271
   206
//
krista@2271
   207
//  returns:
krista@2271
   208
//      PEP_STATUS_OK or any other value on error
krista@2271
   209
krista@2271
   210
PEP_STATUS rejectHandshake(
krista@2271
   211
        PEP_SESSION session,
krista@2271
   212
        DeviceState_state state,
krista@2271
   213
        Identity partner,
krista@2271
   214
        void *extra
krista@2271
   215
    )
krista@2271
   216
{
krista@2271
   217
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   218
krista@2271
   219
    assert(session);
krista@2271
   220
    assert(partner);
krista@2271
   221
    assert(extra == NULL);
krista@2271
   222
    if (!(session && partner))
krista@2271
   223
        return PEP_ILLEGAL_VALUE;
krista@2271
   224
krista@2271
   225
    // TODO : disable sync globally if not in a group
krista@2271
   226
    status = set_identity_flags(session, partner,
krista@2271
   227
            partner->flags | PEP_idf_not_for_sync);
krista@2271
   228
krista@2271
   229
    return status;
krista@2271
   230
}
krista@2271
   231
krista@2271
   232
PEP_STATUS _storeGroupKeys(
krista@2271
   233
        PEP_SESSION session,
krista@2271
   234
        identity_list *group_keys
krista@2271
   235
    )
krista@2271
   236
{
krista@2271
   237
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   238
krista@2271
   239
    for (identity_list *il = group_keys; il && il->ident; il = il->next) {
krista@2271
   240
krista@2271
   241
        if (strcmp(il->ident->user_id, PEP_OWN_USERID)!=0) {
krista@2271
   242
            assert(0);
krista@2271
   243
            continue;
krista@2271
   244
        }
krista@2271
   245
        // Check that identity isn't excluded from sync.
krista@2271
   246
        pEp_identity *stored_identity = NULL;
krista@2271
   247
        status = get_identity(session, il->ident->address, PEP_OWN_USERID,
krista@2271
   248
                &stored_identity);
krista@2271
   249
        if (status == PEP_STATUS_OK) {
krista@2271
   250
            if(stored_identity->flags & PEP_idf_not_for_sync){
krista@2271
   251
                free_identity(stored_identity);
krista@2271
   252
                continue;
krista@2271
   253
            }
krista@2271
   254
            free_identity(stored_identity);
krista@2271
   255
        }
krista@2271
   256
krista@2271
   257
        status = set_identity(session, il->ident);
krista@2271
   258
        if (status != PEP_STATUS_OK)
krista@2271
   259
            break;
krista@2271
   260
    }
krista@2271
   261
krista@2271
   262
    return status;
krista@2271
   263
}
krista@2271
   264
    
krista@2271
   265
krista@2271
   266
// storeGroupKeys() - 
krista@2271
   267
//
krista@2271
   268
//  params:
krista@2271
   269
//      session (in)        session handle
krista@2271
   270
//      state (in)          state the state machine is in
krista@2271
   271
//      partner (in)        partner to communicate with
krista@2271
   272
//      _group_keys (in)    group keys received from partner
krista@2271
   273
//
krista@2271
   274
//  returns:
krista@2271
   275
//      PEP_STATUS_OK or any other value on error
krista@2271
   276
krista@2271
   277
PEP_STATUS storeGroupKeys(
krista@2271
   278
        PEP_SESSION session,
krista@2271
   279
        DeviceState_state state,
krista@2271
   280
        Identity partner,
krista@2271
   281
        void *group_keys_extra_
krista@2271
   282
    )
krista@2271
   283
{
krista@2271
   284
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   285
krista@2271
   286
    assert(session);
krista@2271
   287
    assert(partner);
krista@2271
   288
    assert(group_keys_extra_);
krista@2271
   289
    if (!(session && partner && group_keys_extra_))
krista@2271
   290
        return PEP_ILLEGAL_VALUE;
krista@2271
   291
krista@2271
   292
    group_keys_extra_t *group_keys_extra = 
krista@2271
   293
        (group_keys_extra_t*) group_keys_extra_;
krista@2271
   294
    identity_list *group_keys = group_keys_extra->group_keys;
krista@2271
   295
    char *group_id = group_keys_extra->group_id;
krista@2271
   296
krista@2271
   297
    status = _storeGroupKeys(session, group_keys);
krista@2271
   298
    if (status != PEP_STATUS_OK)
krista@2271
   299
        return status;
krista@2271
   300
krista@2271
   301
    // set group id according to given group-id
krista@2271
   302
    status = set_device_group(session, group_id);
krista@2271
   303
    if (status != PEP_STATUS_OK)
krista@2271
   304
        return status;
krista@2271
   305
    
krista@2271
   306
    return status;
krista@2271
   307
}
krista@2271
   308
krista@2271
   309
// storeGroupUpdate() - 
krista@2271
   310
//
krista@2271
   311
//  params:
krista@2271
   312
//      session (in)        session handle
krista@2271
   313
//      state (in)          state the state machine is in
krista@2271
   314
//      partner (in)        partner to communicate with
krista@2271
   315
//      _group_keys (in)    group keys received from partner
krista@2271
   316
//
krista@2271
   317
//  returns:
krista@2271
   318
//      PEP_STATUS_OK or any other value on error
krista@2271
   319
krista@2271
   320
PEP_STATUS storeGroupUpdate(
krista@2271
   321
        PEP_SESSION session,
krista@2271
   322
        DeviceState_state state,
krista@2271
   323
        Identity partner,
krista@2271
   324
        void *group_keys_
krista@2271
   325
    )
krista@2271
   326
{
krista@2271
   327
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   328
krista@2271
   329
    assert(session);
krista@2271
   330
    assert(partner);
krista@2271
   331
    assert(group_keys_);
krista@2271
   332
    if (!(session && partner && group_keys_))
krista@2271
   333
        return PEP_ILLEGAL_VALUE;
krista@2271
   334
krista@2271
   335
    identity_list *group_keys = (identity_list*) group_keys_;
krista@2271
   336
krista@2271
   337
    status = _storeGroupKeys(session, group_keys);
krista@2271
   338
krista@2271
   339
krista@2271
   340
    return status;
krista@2271
   341
}
krista@2271
   342
krista@2271
   343
// makeGroup() - 
krista@2271
   344
//
krista@2271
   345
//  params:
krista@2271
   346
//      session (in)        session handle
krista@2271
   347
//      state (in)          state the state machine is in
krista@2271
   348
//      partner (in)        ignored
krista@2271
   349
//      extra (in)          ignored
krista@2271
   350
//
krista@2271
   351
//  returns:
krista@2271
   352
//      PEP_STATUS_OK or any other value on error
krista@2271
   353
krista@2271
   354
PEP_STATUS makeGroup(
krista@2271
   355
        PEP_SESSION session,
krista@2271
   356
        DeviceState_state state,
krista@2271
   357
        Identity partner,
krista@2271
   358
        void *extra
krista@2271
   359
    )
krista@2271
   360
{
krista@2271
   361
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   362
krista@2271
   363
    assert(session);
krista@2271
   364
   
krista@2271
   365
    // make a new uuid 
krista@2271
   366
    char new_uuid[37];
krista@2271
   367
    pEpUUID uuid;
krista@2271
   368
    uuid_generate_random(uuid);
krista@2271
   369
    uuid_unparse_upper(uuid, new_uuid);
krista@2271
   370
krista@2271
   371
    // take that new uuid as group-id
krista@2271
   372
    status = set_device_group(session, new_uuid);
krista@2271
   373
krista@2271
   374
    return status;
krista@2271
   375
}
krista@2271
   376
krista@2271
   377
// renewUUID() - 
krista@2271
   378
//
krista@2271
   379
//  params:
krista@2271
   380
//      session (in)        session handle
krista@2271
   381
//      state (in)          state the state machine is in
krista@2271
   382
//      partner (in)        ignored
krista@2271
   383
//      extra (in)          ignored
krista@2271
   384
//
krista@2271
   385
//  returns:
krista@2271
   386
//      PEP_STATUS_OK or any other value on error
krista@2271
   387
krista@2271
   388
PEP_STATUS renewUUID(
krista@2271
   389
        PEP_SESSION session,
krista@2271
   390
        DeviceState_state state,
krista@2271
   391
        Identity partner,
krista@2271
   392
        void *extra
krista@2271
   393
    )
krista@2271
   394
{
krista@2271
   395
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   396
krista@2271
   397
    assert(session);
krista@2271
   398
krista@2271
   399
    // change sync_uuid when entering group 
krista@2271
   400
    // thus ignoring unprocessed handshakes
krista@2271
   401
    // addressed to previous self (sole) once in.
krista@2271
   402
    pEpUUID uuid;
krista@2271
   403
    uuid_generate_random(uuid);
krista@2271
   404
    uuid_unparse_upper(uuid, session->sync_uuid);
krista@2271
   405
    
krista@2271
   406
    return status;
krista@2271
   407
}
krista@2271
   408
krista@2271
   409
// leaveGroup() - 
krista@2271
   410
//
krista@2271
   411
//  params:
krista@2271
   412
//      session (in)        session handle
krista@2271
   413
//      state (in)          state the state machine is in
krista@2271
   414
//      partner (in)        ignored
krista@2271
   415
//      extra (in)          ignored
krista@2271
   416
//
krista@2271
   417
//  returns:
krista@2271
   418
//      PEP_STATUS_OK or any other value on error
krista@2271
   419
krista@2271
   420
PEP_STATUS leaveGroup(
krista@2271
   421
        PEP_SESSION session,
krista@2271
   422
        DeviceState_state state,
krista@2271
   423
        Identity partner,
krista@2271
   424
        void *extra
krista@2271
   425
    )
krista@2271
   426
{
krista@2271
   427
    PEP_STATUS status = PEP_STATUS_OK;
krista@2271
   428
krista@2271
   429
    assert(session);
krista@2271
   430
krista@2271
   431
    status = set_device_group(session, NULL);
krista@2271
   432
    
krista@2271
   433
    return status;
krista@2271
   434
}