src/sync_actions.c
author Krista Grothoff <krista@pep-project.org>
Mon, 13 Feb 2017 22:13:48 +0100
branchenigmail-color-tests
changeset 1582 7dd855780eef
parent 1575 ae0c4b0953a5
child 1586 599deda50386
permissions -rw-r--r--
closing branch
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"
vb@951
    10
#include "map_asn1.h"
vb@1046
    11
#include "baseprotocol.h"
vb@623
    12
vb@951
    13
// conditions
vb@951
    14
edouard@1574
    15
int deviceGrouped(PEP_SESSION session)
vb@951
    16
{
vb@951
    17
    assert(session);
vb@951
    18
    if (!session)
vb@964
    19
        return invalid_condition; // error
vb@951
    20
edouard@1574
    21
    char *devgrp = NULL;
edouard@1574
    22
    int res = 0;
edouard@1574
    23
    PEP_STATUS status;
vb@959
    24
edouard@1574
    25
    status = get_device_group(session, &devgrp);
edouard@1574
    26
edouard@1574
    27
    if (status == PEP_STATUS_OK && devgrp && devgrp[0])
edouard@1574
    28
        res = 1;
edouard@1574
    29
edouard@1574
    30
    free(devgrp);
edouard@1574
    31
edouard@1574
    32
    return res;
vb@951
    33
}
vb@951
    34
vb@959
    35
int keyElectionWon(PEP_SESSION session, Identity partner)
vb@951
    36
{
vb@951
    37
    assert(session);
vb@951
    38
    assert(partner);
vb@951
    39
    if (!(session && partner))
vb@964
    40
        return invalid_condition; // error
vb@951
    41
vb@951
    42
    // an already existing group always wins
vb@951
    43
edouard@1574
    44
    if (deviceGrouped(session)) {
vb@951
    45
        assert(!(partner->flags & PEP_idf_devicegroup));
vb@959
    46
        return 1;
vb@951
    47
    }
vb@951
    48
vb@951
    49
    if (partner->flags & PEP_idf_devicegroup)
vb@959
    50
        return 0;
vb@951
    51
vb@951
    52
    Identity me = NULL;
vb@951
    53
    PEP_STATUS status = get_identity(session, partner->address, PEP_OWN_USERID,
vb@951
    54
            &me);
vb@964
    55
    if (status == PEP_OUT_OF_MEMORY)
vb@964
    56
        return invalid_out_of_memory;
vb@951
    57
    if (status != PEP_STATUS_OK)
vb@964
    58
        return invalid_condition; // error
vb@951
    59
vb@964
    60
    int result = invalid_condition; // error state has to be overwritten
vb@951
    61
vb@959
    62
    time_t own_created;
vb@959
    63
    time_t partners_created;
vb@959
    64
vb@959
    65
    status = key_created(session, me->fpr, &own_created);
vb@959
    66
    if (status != PEP_STATUS_OK)
vb@959
    67
        goto the_end;
vb@959
    68
vb@959
    69
    status = key_created(session, partner->fpr, &partners_created);
vb@959
    70
    if (status != PEP_STATUS_OK)
vb@959
    71
        goto the_end;
vb@959
    72
vb@959
    73
    if (own_created > partners_created)
vb@959
    74
        result = 0;
vb@959
    75
    else
vb@959
    76
        result = 1;
vb@951
    77
vb@951
    78
the_end:
vb@951
    79
    free_identity(me);
vb@951
    80
    return result;
vb@951
    81
}
vb@650
    82
edouard@1523
    83
int sameIdentities(PEP_SESSION session, Identity a, Identity b)
edouard@1523
    84
{
edouard@1523
    85
    assert(session);
edouard@1523
    86
    assert(a);
edouard@1523
    87
    assert(b);
edouard@1523
    88
edouard@1523
    89
    if (!(session && a && b))
edouard@1523
    90
        return invalid_condition; // error
edouard@1523
    91
edouard@1524
    92
    if (a->fpr == NULL || b->fpr == NULL ||
edouard@1523
    93
        (!_same_fpr(a->fpr, strlen(a->fpr), b->fpr, strlen(b->fpr))) ||
edouard@1524
    94
        a->address == NULL || b->address == NULL ||
edouard@1523
    95
        strcmp(a->address, b->address) != 0 ||
edouard@1524
    96
        a->user_id == NULL || b->user_id == NULL ||
edouard@1523
    97
        strcmp(a->user_id, b->user_id) != 0)
edouard@1523
    98
            return 0;
edouard@1523
    99
    return 1;
edouard@1523
   100
}
edouard@1523
   101
edouard@1523
   102
// actions
edouard@1523
   103
edouard@1477
   104
PEP_STATUS _notifyHandshake(
edouard@1459
   105
        PEP_SESSION session,
edouard@1459
   106
        Identity partner,
edouard@1459
   107
        sync_handshake_signal signal
edouard@1459
   108
    )
edouard@1459
   109
{
edouard@1459
   110
    PEP_STATUS status = PEP_STATUS_OK;
edouard@1459
   111
edouard@1459
   112
    assert(session);
edouard@1459
   113
    assert(partner);
edouard@1459
   114
edouard@1459
   115
    if (!(session && partner))
edouard@1459
   116
        return PEP_ILLEGAL_VALUE;
edouard@1459
   117
edouard@1459
   118
    assert(session->notifyHandshake);
edouard@1459
   119
    if (!session->notifyHandshake)
edouard@1459
   120
        return PEP_SYNC_NO_NOTIFY_CALLBACK;
edouard@1459
   121
edouard@1459
   122
    // notifyHandshake take ownership of given identities
edouard@1459
   123
    pEp_identity *me = NULL;
edouard@1459
   124
    status = get_identity(session, partner->address, PEP_OWN_USERID, &me);
edouard@1459
   125
    if (status != PEP_STATUS_OK)
edouard@1459
   126
        goto error;
edouard@1459
   127
    
edouard@1459
   128
    pEp_identity *_partner = NULL;
edouard@1459
   129
    _partner = identity_dup(partner);
edouard@1459
   130
    if (_partner == NULL){
edouard@1459
   131
        status = PEP_OUT_OF_MEMORY;
edouard@1459
   132
        goto error;
edouard@1459
   133
    }
edouard@1459
   134
edouard@1459
   135
    status = session->notifyHandshake(session->sync_obj, me, _partner, signal);
edouard@1459
   136
    if (status != PEP_STATUS_OK)
edouard@1459
   137
        goto error;
edouard@1459
   138
edouard@1459
   139
    return status;
edouard@1459
   140
edouard@1459
   141
error:
edouard@1459
   142
    free_identity(me);
edouard@1459
   143
    return status;
edouard@1459
   144
}
edouard@1459
   145
edouard@1161
   146
// acceptHandshake() - stores acception of partner
vb@623
   147
//
vb@623
   148
//  params:
vb@627
   149
//      session (in)        session handle
vb@690
   150
//      state (in)          state the state machine is in
vb@807
   151
//      partner (in)        partner to communicate with
vb@623
   152
//
vb@623
   153
//  returns:
vb@623
   154
//      PEP_STATUS_OK or any other value on error
vb@623
   155
edouard@1161
   156
PEP_STATUS acceptHandshake(
edouard@1161
   157
        PEP_SESSION session,
edouard@1161
   158
        DeviceState_state state,
edouard@1161
   159
        Identity partner,
edouard@1161
   160
        void *extra
edouard@1161
   161
    )
edouard@1161
   162
{
edouard@1161
   163
    PEP_STATUS status = PEP_STATUS_OK;
edouard@1161
   164
edouard@1161
   165
    assert(session);
edouard@1161
   166
    assert(partner);
edouard@1161
   167
    assert(extra == NULL);
edouard@1161
   168
    if (!(session && partner))
edouard@1161
   169
        return PEP_ILLEGAL_VALUE;
edouard@1161
   170
edouard@1161
   171
    status = trust_personal_key(session, partner);
edouard@1161
   172
edouard@1161
   173
    return status;
edouard@1161
   174
}
edouard@1161
   175
edouard@1161
   176
edouard@1161
   177
// rejectHandshake() - stores rejection of partner
edouard@1161
   178
//
edouard@1161
   179
//  params:
edouard@1161
   180
//      session (in)        session handle
edouard@1161
   181
//      state (in)          state the state machine is in
edouard@1161
   182
//      partner (in)        partner to communicate with
edouard@1161
   183
//
edouard@1161
   184
//  returns:
edouard@1161
   185
//      PEP_STATUS_OK or any other value on error
edouard@1161
   186
edouard@1161
   187
PEP_STATUS rejectHandshake(
vb@690
   188
        PEP_SESSION session,
vb@690
   189
        DeviceState_state state,
vb@939
   190
        Identity partner,
vb@939
   191
        void *extra
vb@690
   192
    )
vb@623
   193
{
vb@623
   194
    PEP_STATUS status = PEP_STATUS_OK;
vb@623
   195
vb@650
   196
    assert(session);
vb@665
   197
    assert(partner);
vb@939
   198
    assert(extra == NULL);
vb@665
   199
    if (!(session && partner))
vb@665
   200
        return PEP_ILLEGAL_VALUE;
vb@623
   201
vb@939
   202
    status = set_identity_flags(session, partner,
vb@939
   203
            partner->flags | PEP_idf_not_for_sync);
vb@623
   204
vb@623
   205
    return status;
vb@623
   206
}
vb@623
   207
vb@650
   208
vb@657
   209
// storeGroupKeys() - 
vb@623
   210
//
vb@623
   211
//  params:
vb@627
   212
//      session (in)        session handle
vb@690
   213
//      state (in)          state the state machine is in
vb@807
   214
//      partner (in)        partner to communicate with
vb@939
   215
//      _group_keys (in)    group keys received from partner
vb@623
   216
//
vb@623
   217
//  returns:
vb@623
   218
//      PEP_STATUS_OK or any other value on error
vb@623
   219
vb@690
   220
PEP_STATUS storeGroupKeys(
vb@690
   221
        PEP_SESSION session,
vb@690
   222
        DeviceState_state state,
vb@939
   223
        Identity partner,
vb@939
   224
        void *_group_keys
vb@690
   225
    )
vb@623
   226
{
vb@623
   227
    PEP_STATUS status = PEP_STATUS_OK;
vb@623
   228
vb@650
   229
    assert(session);
vb@665
   230
    assert(partner);
vb@939
   231
    assert(_group_keys);
vb@939
   232
    if (!(session && partner && _group_keys))
vb@665
   233
        return PEP_ILLEGAL_VALUE;
vb@623
   234
vb@951
   235
    identity_list *group_keys = (identity_list *) _group_keys;
vb@623
   236
vb@964
   237
    for (identity_list *il = group_keys; il && il->ident; il = il->next) {
edouard@1413
   238
edouard@1413
   239
        // Check that identity isn't excluded from sync.
roker@1559
   240
        pEp_identity *stored_identity = NULL;
edouard@1413
   241
        status = get_identity(session, il->ident->address, PEP_OWN_USERID,
edouard@1413
   242
                &stored_identity);
edouard@1413
   243
        if (status == PEP_STATUS_OK) {
edouard@1413
   244
            if(stored_identity->flags & PEP_idf_not_for_sync){
edouard@1413
   245
                free_identity(stored_identity);
edouard@1413
   246
                continue;
edouard@1413
   247
            }
edouard@1413
   248
            free_identity(stored_identity);
edouard@1413
   249
        }
edouard@1413
   250
vb@964
   251
        free(il->ident->user_id);
vb@964
   252
        il->ident->user_id = strdup(PEP_OWN_USERID);
vb@964
   253
        assert(il->ident->user_id);
vb@964
   254
        if (!il->ident->user_id)
vb@964
   255
            goto enomem;
vb@964
   256
        status = set_identity(session, il->ident);
vb@964
   257
        if (status != PEP_STATUS_OK)
vb@964
   258
            break;
vb@964
   259
    }
vb@964
   260
vb@951
   261
    free_identity_list(group_keys);
edouard@1297
   262
    
vb@623
   263
    return status;
vb@650
   264
vb@650
   265
enomem:
vb@650
   266
    status = PEP_OUT_OF_MEMORY;
vb@951
   267
    free_identity_list(group_keys);
vb@650
   268
    return status;
vb@623
   269
}
vb@623
   270
edouard@1297
   271
// enterGroup() - 
edouard@1297
   272
//
edouard@1297
   273
//  params:
edouard@1297
   274
//      session (in)        session handle
edouard@1297
   275
//      state (in)          state the state machine is in
edouard@1297
   276
//      partner (in)        ignored
edouard@1297
   277
//      extra (in)          ignored
edouard@1297
   278
//
edouard@1297
   279
//  returns:
edouard@1297
   280
//      PEP_STATUS_OK or any other value on error
edouard@1297
   281
edouard@1297
   282
PEP_STATUS enterGroup(
edouard@1297
   283
        PEP_SESSION session,
edouard@1297
   284
        DeviceState_state state,
edouard@1297
   285
        Identity partner,
edouard@1297
   286
        void *extra
edouard@1297
   287
    )
edouard@1297
   288
{
edouard@1297
   289
    PEP_STATUS status = PEP_STATUS_OK;
edouard@1297
   290
edouard@1297
   291
    assert(session);
edouard@1297
   292
edouard@1297
   293
    // groups have no uuid for now
edouard@1297
   294
    status = set_device_group(session, "1");
edouard@1575
   295
edouard@1575
   296
    // change sync_uuid when entering group 
edouard@1575
   297
    // thus ignoring unprocessed handshakes
edouard@1575
   298
    // addressed to previous self (sole) once in.
edouard@1575
   299
    pEpUUID uuid;
edouard@1575
   300
    uuid_generate_random(uuid);
edouard@1575
   301
    uuid_unparse_upper(uuid, session->sync_uuid);
edouard@1297
   302
    
edouard@1297
   303
    return status;
edouard@1297
   304
}
edouard@1574
   305
edouard@1574
   306
// leaveGroup() - 
edouard@1574
   307
//
edouard@1574
   308
//  params:
edouard@1574
   309
//      session (in)        session handle
edouard@1574
   310
//      state (in)          state the state machine is in
edouard@1574
   311
//      partner (in)        ignored
edouard@1574
   312
//      extra (in)          ignored
edouard@1574
   313
//
edouard@1574
   314
//  returns:
edouard@1574
   315
//      PEP_STATUS_OK or any other value on error
edouard@1574
   316
edouard@1574
   317
PEP_STATUS leaveGroup(
edouard@1574
   318
        PEP_SESSION session,
edouard@1574
   319
        DeviceState_state state,
edouard@1574
   320
        Identity partner,
edouard@1574
   321
        void *extra
edouard@1574
   322
    )
edouard@1574
   323
{
edouard@1574
   324
    PEP_STATUS status = PEP_STATUS_OK;
edouard@1574
   325
edouard@1574
   326
    assert(session);
edouard@1574
   327
edouard@1574
   328
    status = set_device_group(session, NULL);
edouard@1574
   329
    
edouard@1574
   330
    return status;
edouard@1574
   331
}