src/sync_actions.c
author Volker Birk <vb@pep.foundation>
Sun, 31 Jul 2016 21:25:22 +0200
branchkeysync
changeset 954 a72e5c669833
parent 953 1572660086e7
child 959 c1c463ecf30c
permissions -rw-r--r--
...
vb@623
     1
// Actions for DeviceState state machine
vb@623
     2
vb@623
     3
#include <assert.h>
vb@690
     4
#include "pEp_internal.h"
vb@690
     5
#include "message.h"
vb@623
     6
#include "sync_fsm.h"
vb@951
     7
#include "map_asn1.h"
vb@623
     8
vb@951
     9
// conditions
vb@951
    10
vb@951
    11
static const char *sql_stored_group_keys =
vb@951
    12
        "select count(device_group) from person where id = "PEP_OWN_USERID";"; 
vb@951
    13
vb@951
    14
static int _stored_group_keys(void *_gc, int count, char **text, char **name)
vb@951
    15
{
vb@951
    16
    assert(_gc);
vb@951
    17
    assert(count == 1);
vb@951
    18
    assert(text && text[0]);
vb@951
    19
    if (!(_gc && count == 1 && text && text[0]))
vb@951
    20
        return -1;
vb@951
    21
vb@951
    22
    bool *gc = (bool *) _gc;
vb@951
    23
    *gc = atoi(text[0]) != 0;
vb@951
    24
    return 0;
vb@951
    25
}
vb@951
    26
vb@951
    27
bool storedGroupKeys(PEP_SESSION session)
vb@951
    28
{
vb@951
    29
    assert(session);
vb@951
    30
    if (!session)
vb@951
    31
        return false;
vb@951
    32
vb@951
    33
    bool gc = false;
vb@951
    34
    int int_result = sqlite3_exec(
vb@951
    35
        session->db,
vb@951
    36
        sql_stored_group_keys,
vb@951
    37
        _stored_group_keys,
vb@951
    38
        &gc,
vb@951
    39
        NULL
vb@951
    40
    );
vb@951
    41
    assert(int_result == SQLITE_OK);
vb@951
    42
    return gc;
vb@951
    43
}
vb@951
    44
vb@951
    45
bool keyElectionWon(PEP_SESSION session, Identity partner)
vb@951
    46
{
vb@951
    47
    assert(session);
vb@951
    48
    assert(partner);
vb@951
    49
    if (!(session && partner))
vb@951
    50
        return false;
vb@951
    51
vb@951
    52
    // an already existing group always wins
vb@951
    53
vb@951
    54
    if (storedGroupKeys(session)) {
vb@951
    55
        assert(!(partner->flags & PEP_idf_devicegroup));
vb@951
    56
        return true;
vb@951
    57
    }
vb@951
    58
vb@951
    59
    if (partner->flags & PEP_idf_devicegroup)
vb@951
    60
        return false;
vb@951
    61
vb@951
    62
    Identity me = NULL;
vb@951
    63
    PEP_STATUS status = get_identity(session, partner->address, PEP_OWN_USERID,
vb@951
    64
            &me);
vb@951
    65
    if (status != PEP_STATUS_OK)
vb@951
    66
        return false;
vb@951
    67
vb@951
    68
    bool result = false;
vb@951
    69
vb@951
    70
vb@951
    71
the_end:
vb@951
    72
    free_identity(me);
vb@951
    73
    return result;
vb@951
    74
}
vb@650
    75
vb@884
    76
// showHandshake() - trigger the handshake dialog of the application
vb@623
    77
//
vb@623
    78
//  params:
vb@627
    79
//      session (in)        session handle
vb@690
    80
//      state (in)          state the state machine is in
vb@807
    81
//      partner (in)        partner to communicate with
vb@623
    82
//
vb@623
    83
//  returns:
vb@623
    84
//      PEP_STATUS_OK or any other value on error
vb@623
    85
vb@690
    86
PEP_STATUS showHandshake(
vb@690
    87
        PEP_SESSION session,
vb@690
    88
        DeviceState_state state,
vb@939
    89
        Identity partner,
vb@939
    90
        void *extra
vb@690
    91
    )
vb@623
    92
{
vb@623
    93
    PEP_STATUS status = PEP_STATUS_OK;
vb@939
    94
vb@650
    95
    assert(session);
vb@665
    96
    assert(partner);
vb@939
    97
    assert(extra == NULL);
vb@939
    98
vb@665
    99
    if (!(session && partner))
vb@665
   100
        return PEP_ILLEGAL_VALUE;
vb@939
   101
vb@907
   102
    assert(session->showHandshake);
vb@884
   103
    if (!session->showHandshake)
vb@884
   104
        return PEP_SYNC_NO_TRUSTWORDS_CALLBACK;
vb@623
   105
vb@884
   106
    pEp_identity *me = NULL;
vb@884
   107
    status = get_identity(session, partner->address, PEP_OWN_USERID, &me);
vb@884
   108
    if (status != PEP_STATUS_OK)
vb@884
   109
        goto error;
vb@884
   110
    
vb@884
   111
    status = session->showHandshake(session, me, partner);
vb@884
   112
    if (status != PEP_STATUS_OK)
vb@884
   113
        goto error;
vb@623
   114
vb@884
   115
    free_identity(me);
vb@951
   116
    free_identity(partner);
vb@623
   117
    return status;
vb@650
   118
vb@650
   119
enomem:
vb@650
   120
    status = PEP_OUT_OF_MEMORY;
vb@650
   121
error:
vb@884
   122
    free_identity(me);
vb@951
   123
    free_identity(partner);
vb@650
   124
    return status;
vb@623
   125
}
vb@623
   126
vb@650
   127
vb@907
   128
// reject() - stores rejection of partner
vb@623
   129
//
vb@623
   130
//  params:
vb@627
   131
//      session (in)        session handle
vb@690
   132
//      state (in)          state the state machine is in
vb@807
   133
//      partner (in)        partner to communicate with
vb@623
   134
//
vb@623
   135
//  returns:
vb@623
   136
//      PEP_STATUS_OK or any other value on error
vb@623
   137
vb@690
   138
PEP_STATUS reject(
vb@690
   139
        PEP_SESSION session,
vb@690
   140
        DeviceState_state state,
vb@939
   141
        Identity partner,
vb@939
   142
        void *extra
vb@690
   143
    )
vb@623
   144
{
vb@623
   145
    PEP_STATUS status = PEP_STATUS_OK;
vb@623
   146
vb@650
   147
    assert(session);
vb@665
   148
    assert(partner);
vb@939
   149
    assert(extra == NULL);
vb@665
   150
    if (!(session && partner))
vb@665
   151
        return PEP_ILLEGAL_VALUE;
vb@623
   152
vb@939
   153
    status = set_identity_flags(session, partner,
vb@939
   154
            partner->flags | PEP_idf_not_for_sync);
vb@623
   155
vb@951
   156
    free_identity(partner);
vb@623
   157
    return status;
vb@650
   158
vb@650
   159
enomem:
vb@650
   160
    status = PEP_OUT_OF_MEMORY;
vb@650
   161
error:
vb@951
   162
    free_identity(partner);
vb@650
   163
    // free...
vb@650
   164
    return status;
vb@623
   165
}
vb@623
   166
vb@650
   167
vb@657
   168
// storeGroupKeys() - 
vb@623
   169
//
vb@623
   170
//  params:
vb@627
   171
//      session (in)        session handle
vb@690
   172
//      state (in)          state the state machine is in
vb@807
   173
//      partner (in)        partner to communicate with
vb@939
   174
//      _group_keys (in)    group keys received from partner
vb@623
   175
//
vb@623
   176
//  returns:
vb@623
   177
//      PEP_STATUS_OK or any other value on error
vb@623
   178
vb@690
   179
PEP_STATUS storeGroupKeys(
vb@690
   180
        PEP_SESSION session,
vb@690
   181
        DeviceState_state state,
vb@939
   182
        Identity partner,
vb@939
   183
        void *_group_keys
vb@690
   184
    )
vb@623
   185
{
vb@623
   186
    PEP_STATUS status = PEP_STATUS_OK;
vb@623
   187
vb@650
   188
    assert(session);
vb@665
   189
    assert(partner);
vb@939
   190
    assert(_group_keys);
vb@939
   191
    if (!(session && partner && _group_keys))
vb@665
   192
        return PEP_ILLEGAL_VALUE;
vb@623
   193
vb@951
   194
    identity_list *group_keys = (identity_list *) _group_keys;
vb@951
   195
    if (!group_keys)
vb@951
   196
        goto enomem;
vb@623
   197
vb@951
   198
    free_identity(partner);
vb@951
   199
    free_identity_list(group_keys);
vb@623
   200
    return status;
vb@650
   201
vb@650
   202
enomem:
vb@650
   203
    status = PEP_OUT_OF_MEMORY;
vb@650
   204
error:
vb@650
   205
    // free...
vb@951
   206
    free_identity(partner);
vb@951
   207
    free_identity_list(group_keys);
vb@650
   208
    return status;
vb@623
   209
}
vb@623
   210
vb@954
   211
static PEP_STATUS receive_sync_msg(
vb@954
   212
        PEP_SESSION session,
vb@954
   213
        DeviceGroup_Protocol_t *msg
vb@954
   214
    )
vb@951
   215
{
vb@951
   216
    assert(session && msg && msg->present != DeviceGroup_Protocol_PR_NOTHING);
vb@951
   217
    if (!(session && msg && msg->present != DeviceGroup_Protocol_PR_NOTHING))
vb@951
   218
        return PEP_ILLEGAL_VALUE;
vb@951
   219
vb@951
   220
    void *extra = NULL;
vb@951
   221
    Identity partner = NULL;
vb@951
   222
    DeviceState_event event = DeviceState_event_NONE;
vb@951
   223
vb@951
   224
    switch (msg->present) {
vb@951
   225
        case DeviceGroup_Protocol_PR_beacon:
vb@951
   226
            partner = Identity_to_Struct(&msg->choice.beacon.header.me, NULL);
vb@951
   227
            if (!partner)
vb@951
   228
                return PEP_OUT_OF_MEMORY;
vb@951
   229
            event = Beacon;
vb@951
   230
            break;
vb@951
   231
vb@951
   232
        case DeviceGroup_Protocol_PR_handshakeRequest:
vb@954
   233
            partner = Identity_to_Struct(
vb@954
   234
                    &msg->choice.handshakeRequest.header.me, NULL);
vb@951
   235
            if (!partner)
vb@951
   236
                return PEP_OUT_OF_MEMORY;
vb@951
   237
            event = HandshakeRequest;
vb@951
   238
            break;
vb@951
   239
vb@951
   240
        case DeviceGroup_Protocol_PR_groupKeys:
vb@954
   241
            partner = Identity_to_Struct(&msg->choice.groupKeys.header.me,
vb@954
   242
                    NULL);
vb@951
   243
            if (!partner)
vb@951
   244
                return PEP_OUT_OF_MEMORY;
vb@951
   245
            identity_list *group_keys = IdentityList_to_identity_list(
vb@951
   246
                    &msg->choice.groupKeys.ownIdentities, NULL);
vb@951
   247
            if (!group_keys) {
vb@951
   248
                free_identity(partner);
vb@951
   249
                return PEP_OUT_OF_MEMORY;
vb@951
   250
            }
vb@951
   251
            extra = (void *) group_keys;
vb@951
   252
            event = GroupKeys;
vb@951
   253
            break;
vb@951
   254
vb@951
   255
        default:
vb@951
   256
            return PEP_SYNC_ILLEGAL_MESSAGE;
vb@951
   257
    }
vb@951
   258
vb@951
   259
    return fsm_DeviceState_inject(session, event, partner, extra);
vb@951
   260
}
vb@951
   261
vb@952
   262
PEP_STATUS receive_DeviceState_msg(PEP_SESSION session, message *src)
vb@952
   263
{
vb@952
   264
    assert(session && src);
vb@952
   265
    if (!(session && src))
vb@952
   266
        return PEP_ILLEGAL_VALUE;
vb@952
   267
vb@953
   268
    bool found = false;
vb@953
   269
vb@953
   270
    for (bloblist_t *bl = src->attachments; bl && bl->value; bl = bl->next) {
vb@953
   271
        if (bl->mime_type && strcasecmp(bl->mime_type, "application/pEp") == 0
vb@953
   272
                && bl->size) {
vb@953
   273
            DeviceGroup_Protocol_t *msg;
vb@954
   274
            uper_decode_complete(NULL, &asn_DEF_DeviceGroup_Protocol,
vb@953
   275
                    (void **) &msg, bl->value, bl->size);
vb@953
   276
            if (msg) {
vb@953
   277
                found = true;
vb@953
   278
                PEP_STATUS status = receive_sync_msg(session, msg);
vb@953
   279
                ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
vb@953
   280
                if (status != PEP_STATUS_OK)
vb@953
   281
                    return status;
vb@953
   282
            }
vb@953
   283
        }
vb@953
   284
    }
vb@953
   285
vb@953
   286
    if (found) {
vb@953
   287
        for (stringpair_list_t *spl = src->opt_fields ; spl && spl->value ;
vb@953
   288
                spl = spl->next) {
vb@953
   289
            if (spl->value->key &&
vb@953
   290
                    strcasecmp(spl->value->key, "pEp-auto-consume") == 0) {
vb@953
   291
                if (spl->value->value &&
vb@953
   292
                        strcasecmp(spl->value->value, "yes") == 0)
vb@953
   293
                    return PEP_MESSAGE_CONSUMED;
vb@953
   294
            }
vb@953
   295
        }
vb@953
   296
    }
vb@953
   297
vb@952
   298
    return PEP_STATUS_OK;
vb@952
   299
}
vb@952
   300