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