sync/cond_act_sync.yml2
author Neal H. Walfield <neal@pep.foundation>
Wed, 08 May 2019 12:20:37 +0200
branchemail_comparison
changeset 3649 1dd837adc30b
parent 3609 548e7dd045e5
child 3722 0f31947b826d
permissions -rw-r--r--
Fix public key.
     1 // This file is under GNU General Public License 3.0
     2 // see LICENSE.txt
     3 
     4 // generate conditions and actions
     5 
     6 // Copyleft (c) 2017-2019, p≡p foundation
     7 
     8 // Written by Volker Birk
     9 
    10 
    11 include ./sql_func.yml2
    12 
    13 // condition: PEP_STATUS «@name»(PEP_SESSION session, bool *result)
    14 
    15 condition deviceGrouped {
    16     call "exec_sql_int" with "sql"
    17         > "select count(*) from identity where is_own = 1 and (flags & 0x100) = 0x100;"
    18     |> *result = _result > 0;
    19 }
    20 
    21 condition weAreFirst
    22 ||
    23     TID_t *t1 = &session->sync_state.keysync.challenge;
    24     TID_t *t2 = &session->own_sync_state.challenge;
    25 
    26     *result = _TID_greater(t1, t2);
    27 ||
    28 
    29 condition partnerIsGrouped
    30 |> *result = session->sync_state.keysync.is_group;
    31 
    32 condition challengeAccepted
    33 ||
    34     TID_t *t1 = &session->sync_state.keysync.challenge;
    35     TID_t *t2 = &session->own_sync_state.challenge;
    36 
    37     *result = t1->size == t2->size && memcmp(t1->buf, t2->buf, t1->size) == 0;
    38 ||
    39 
    40 condition sameChallenge
    41 ||
    42     TID_t *t1 = &session->sync_state.keysync.challenge;
    43     TID_t *t2 = &session->own_sync_state.challenge;
    44 
    45     *result = t1->size == t2->size && memcmp(t1->buf, t2->buf, t1->size) == 0;
    46 ||
    47 
    48 condition sameTransaction
    49 ||
    50     TID_t *t1 = &session->sync_state.keysync.negotiation;
    51     TID_t *t2 = &session->own_sync_state.negotiation;
    52 
    53     // test if TID is identical
    54     *result = t1->size == t2->size && memcmp(t1->buf, t2->buf, t1->size) == 0;
    55 ||
    56 
    57 condition sameTransactionAndPartner
    58 ||
    59     TID_t *t1 = &session->sync_state.keysync.negotiation;
    60     TID_t *t2 = &session->own_sync_state.negotiation;
    61 
    62     const char *s1 = session->sync_state.common.signature_fpr;
    63     const char *s2 = session->own_sync_state.signature_fpr;
    64 
    65     // test if TID is identical
    66     *result = t1->size == t2->size && memcmp(t1->buf, t2->buf, t1->size) == 0
    67     // and test if we're talking to the same sender
    68             && s1 && s2 && strcmp(s1, s2) == 0;
    69 ||
    70 
    71 condition keyElectionWon
    72 ||
    73     pEp_identity *from = session->sync_state.common.from;
    74     char *signature_fpr = session->sync_state.common.signature_fpr;
    75 
    76     assert(from && from->address && from->address[0] && from->user_id &&
    77             from->user_id[0]);
    78     if (!(from && from->address && from->address[0] && from->user_id &&
    79             from->user_id[0]))
    80         return PEP_ILLEGAL_VALUE;
    81 
    82     pEp_identity *me = NULL;
    83     PEP_STATUS status = get_identity(session, from->address, from->user_id, &me);
    84     assert(status == PEP_STATUS_OK);
    85     if (status)
    86         return status;
    87 
    88     assert(me->fpr && me->fpr[0]);
    89     if (!(me->fpr && me->fpr[0])) {
    90         free_identity(me);
    91         return PEP_ILLEGAL_VALUE;
    92     }
    93 
    94     size_t len = MIN(strlen(signature_fpr), strlen(me->fpr));
    95     *result = strncasecmp(signature_fpr, me->fpr, len) > 0;
    96     free_identity(me);
    97 ||
    98 
    99 // action: PEP_STATUS «@name»(PEP_SESSION session)
   100 
   101 function "new_UUID" {
   102     param "dst";
   103     ||
   104         pEpUUID c;
   105         uuid_generate_random(c);
   106 
   107         OCTET_STRING_fromBuf(«$dst», (char *) c, 16);
   108     ||
   109 }
   110 
   111 function "copy_UUID" {
   112     param "src", param "dst";
   113     ||
   114         {
   115             TID_t *src = «$src»;
   116             TID_t *dst = «$dst»;
   117 
   118             assert(src->size == 16);
   119             if (!(src->size == 16))
   120                 return PEP_UNKNOWN_ERROR;
   121 
   122             OCTET_STRING_fromBuf(dst, (char *) src->buf, src->size);
   123         }
   124     ||
   125 }
   126 
   127 function "xor_UUID" {
   128     param "src", param "dst";
   129     ||
   130         {
   131             TID_t *src = «$src»;
   132             TID_t *dst = «$dst»;
   133 
   134             assert(src->size == 16 && dst->size == 16);
   135             if (!(src->size == 16 && dst->size == 16))
   136                 return PEP_UNKNOWN_ERROR;
   137 
   138             for (int i=0; i < src->size; ++i)
   139                 dst->buf[i] ^= src->buf[i];
   140         }
   141     ||
   142 }
   143 
   144 action newChallenge {
   145     // random new challenge
   146     call "new_UUID" with "dst" > &session->own_sync_state.challenge
   147     // store a copy of this challenge
   148     call "copy_UUID" {
   149         with "src" > &session->own_sync_state.challenge
   150         with "dst" > &session->sync_state.common.challenge
   151     }
   152 }
   153 
   154 action replyChallenge call "copy_UUID" {
   155     with "src" > &session->sync_state.keysync.challenge
   156     with "dst" > &session->own_sync_state.challenge
   157 }
   158 
   159 action useOwnChallenge call "copy_UUID" {
   160     with "src" > &session->sync_state.common.challenge
   161     with "dst" > &session->own_sync_state.challenge
   162 }
   163 
   164 action newTransaction {
   165 ||
   166     // sender key must be stable while transaction
   167     assert(session->sync_state.common.signature_fpr);
   168     free(session->own_sync_state.signature_fpr);
   169     session->own_sync_state.signature_fpr
   170             = strdup(session->sync_state.common.signature_fpr);
   171     assert(session->own_sync_state.signature_fpr);
   172     if (!session->own_sync_state.signature_fpr)
   173         return PEP_OUT_OF_MEMORY;
   174 
   175 ||
   176     call "copy_UUID" {
   177         with "src" > &session->sync_state.keysync.challenge
   178         with "dst" > &session->sync_state.keysync.negotiation
   179     }
   180     call "xor_UUID" {
   181         with "src" > &session->own_sync_state.challenge
   182         with "dst" > &session->sync_state.keysync.negotiation
   183     }
   184     call "copy_UUID" {
   185         with "src" > &session->sync_state.keysync.negotiation
   186         with "dst" > &session->own_sync_state.negotiation
   187     }
   188 }
   189 
   190 action closeTransaction
   191 ||
   192     memset(session->sync_state.keysync.negotiation.buf, 0,
   193             session->sync_state.keysync.negotiation.size);
   194     memset(session->own_sync_state.negotiation.buf, 0,
   195             session->own_sync_state.negotiation.size);
   196 ||
   197 
   198 action storeTransaction {
   199 ||
   200     // sender key must be stable while transaction
   201     assert(session->sync_state.common.signature_fpr);
   202     free(session->own_sync_state.signature_fpr);
   203     session->own_sync_state.signature_fpr
   204             = strdup(session->sync_state.common.signature_fpr);
   205     assert(session->own_sync_state.signature_fpr);
   206     if (!session->own_sync_state.signature_fpr)
   207         return PEP_OUT_OF_MEMORY;
   208 
   209 ||
   210     call "copy_UUID" {
   211         with "src" > &session->sync_state.keysync.negotiation
   212         with "dst" > &session->own_sync_state.negotiation
   213     }
   214 }
   215 
   216 function "show_handshake" {
   217     param "type";
   218     ||
   219         assert(session->notifyHandshake);
   220         if (!session->notifyHandshake)
   221             return PEP_SYNC_NO_NOTIFY_CALLBACK;
   222      
   223     ||
   224     choose {
   225     when "$type = 'SYNC_NOTIFY_TIMEOUT' or $type = 'SYNC_NOTIFY_SOLE' or $type = 'SYNC_NOTIFY_IN_GROUP'"
   226     ||
   227         pEp_identity *me = new_identity(NULL, NULL, NULL, NULL);
   228         pEp_identity *partner = new_identity(NULL, NULL, NULL, NULL);
   229         assert(me && partner);
   230         if (!(me && partner)) {
   231             free_identity(me);
   232             free_identity(partner);
   233             return PEP_OUT_OF_MEMORY;
   234         }
   235 
   236         PEP_STATUS status = session->notifyHandshake(me, partner, «$type»);
   237         if (status)
   238             return status;
   239     ||
   240     otherwise
   241     ||
   242         assert(session->sync_state.common.from);
   243         if (!session->sync_state.common.from)
   244             return PEP_ILLEGAL_VALUE;
   245 
   246         pEp_identity *from = session->sync_state.common.from;
   247         pEp_identity *me = NULL;
   248         PEP_STATUS status = get_identity(session, from->address, from->user_id, &me);
   249         assert(status == PEP_STATUS_OK);
   250         if (status)
   251             return status;
   252 
   253         assert(me->fpr && me->fpr[0]);
   254         if (!(me->fpr && me->fpr[0])) {
   255             free_identity(me);
   256             return PEP_ILLEGAL_VALUE;
   257         }
   258 
   259         pEp_identity *partner = identity_dup(from);
   260         if (!partner) {
   261             free_identity(me);
   262             return PEP_OUT_OF_MEMORY;
   263         }
   264 
   265         assert(session->sync_state.common.signature_fpr);
   266         if (session->sync_state.common.signature_fpr) {
   267             free(partner->fpr);
   268             partner->fpr = strdup(session->sync_state.common.signature_fpr);
   269             if (!partner->fpr) {
   270                 free_identity(me);
   271                 free_identity(partner);
   272                 return PEP_OUT_OF_MEMORY;
   273             }
   274         }
   275 
   276         status = session->notifyHandshake(me, partner, «$type»);
   277         if (status)
   278             return status;
   279     ||
   280     }
   281 }
   282 
   283 action showSoleHandshake
   284     call "show_handshake" with "type" > SYNC_NOTIFY_INIT_FORM_GROUP
   285 
   286 action showJoinGroupHandshake
   287     call "show_handshake" with "type" > SYNC_NOTIFY_INIT_ADD_OUR_DEVICE
   288 
   289 action showGroupedHandshake
   290     call "show_handshake" with "type" > SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE
   291 
   292 action hideHandshakeDialog
   293     call "show_handshake" with "type" > SYNC_NOTIFY_OVERTAKEN
   294 
   295 action showDeviceAdded
   296     call "show_handshake" with "type" > SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED
   297 
   298 action showGroupCreated
   299     call "show_handshake" with "type" > SYNC_NOTIFY_ACCEPTED_GROUP_CREATED
   300 
   301 action showBeingSole
   302     call "show_handshake" with "type" > SYNC_NOTIFY_SOLE
   303 
   304 action showBeingInGroup
   305     call "show_handshake" with "type" > SYNC_NOTIFY_IN_GROUP
   306 
   307 timeout KeySync
   308     call "show_handshake" with "type" > SYNC_NOTIFY_TIMEOUT
   309 
   310 action prepareOwnKeys
   311 ||
   312     stringlist_t *own_keys;
   313     PEP_STATUS status = _own_keys_retrieve(session, &own_keys, PEP_idf_not_for_sync, true);
   314     if (status)
   315         return status;
   316 
   317     if (session->own_sync_state.own_keys)
   318         free_stringlist(session->own_sync_state.own_keys);
   319     session->own_sync_state.own_keys = own_keys;
   320 
   321     identity_list *il;
   322     status = _own_identities_retrieve(session, &il, PEP_idf_not_for_sync);
   323     if (status)
   324         return status;
   325 
   326     IdentityList_from_identity_list(il, &session->sync_state.keysync.ownIdentities);
   327     free_identity_list(il);
   328 ||
   329 
   330 action saveGroupKeys
   331 ||
   332     identity_list *il = IdentityList_to_identity_list(&session->sync_state.keysync.ownIdentities, NULL);
   333     if (!il)
   334         return PEP_OUT_OF_MEMORY;
   335     
   336     // BUG: this should be a transaction and been rolled back completely on error
   337     for (identity_list *_il = il; _il && _il->ident; _il = _il->next) {
   338         PEP_STATUS status = set_identity(session, _il->ident);
   339         if (status) {
   340             free_identity_list(il);
   341             return status;
   342         }
   343     }
   344 
   345     free_identity_list(il);
   346 ||
   347 
   348 action ownKeysAreGroupKeys
   349 ||
   350     PEP_STATUS status = PEP_STATUS_OK;
   351 
   352     // set flag for current keys
   353     for (identity_list *il = session->own_sync_state.own_identities; il && il->ident ; il = il->next) {
   354         if (!(il->ident->flags && PEP_idf_not_for_sync)) {
   355             status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
   356             if (status)
   357                 return status;
   358         }
   359     }
   360 ||
   361 
   362 action receivedKeysAreGroupKeys
   363 ||
   364     PEP_STATUS status = PEP_STATUS_OK;
   365 
   366     // set flag for current keys
   367     for (identity_list *il = session->own_sync_state.own_identities; il && il->ident ; il = il->next) {
   368         if (!(il->ident->flags && PEP_idf_not_for_sync)) {
   369             status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
   370             if (status)
   371                 return status;
   372         }
   373     }
   374 
   375     identity_list *il = IdentityList_to_identity_list(&session->sync_state.keysync.ownIdentities, NULL);
   376     if (!il)
   377         return PEP_OUT_OF_MEMORY;
   378 
   379     for (il = session->own_sync_state.own_identities; il && il->ident ; il = il->next) {
   380         // replace partner's user_id with own user_id
   381         free(il->ident->user_id);
   382         il->ident->user_id = strdup(session->sync_state.common.from->user_id);
   383         if (!il->ident->user_id) {
   384             free_identity_list(il);
   385             return PEP_OUT_OF_MEMORY;
   386         }
   387 
   388         status = myself(session, il->ident);
   389         if (status) {
   390             free_identity_list(il);
   391             return status;
   392         }
   393 
   394         status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
   395         if (status) {
   396             free_identity_list(il);
   397             return status;
   398         }
   399     }
   400 
   401     free_identity_list(il);
   402 ||
   403 
   404 action trustThisKey
   405 ||
   406     assert(session->sync_state.common.from && session->sync_state.common.signature_fpr);
   407     if (!(session->sync_state.common.from && session->sync_state.common.signature_fpr))
   408         return PEP_ILLEGAL_VALUE;
   409 
   410     pEp_identity *ident = session->sync_state.common.from;
   411     free(ident->fpr);
   412     ident->fpr = strdup(session->sync_state.common.signature_fpr);
   413     assert(ident->fpr);
   414     if (!ident->fpr)
   415         return PEP_OUT_OF_MEMORY;
   416 
   417     PEP_STATUS status = trust_own_key(session, ident);
   418     if (status)
   419         return status;
   420 
   421     OCTET_STRING_fromBuf(&session->sync_state.keysync.key, ident->fpr, strlen(ident->fpr));
   422 ||
   423 
   424 action untrustThisKey
   425 ||
   426     assert(session->sync_state.common.from && session->sync_state.common.signature_fpr);
   427     if (!(session->sync_state.common.from && session->sync_state.common.signature_fpr))
   428         return PEP_ILLEGAL_VALUE;
   429 
   430     pEp_identity *ident = session->sync_state.common.from;
   431     free(ident->fpr);
   432     ident->fpr = strdup(session->sync_state.common.signature_fpr);
   433     assert(ident->fpr);
   434     if (!ident->fpr)
   435         return PEP_OUT_OF_MEMORY;
   436 
   437     PEP_STATUS status = key_reset_trust(session, ident);
   438     if (status)
   439         return status;
   440 
   441     OCTET_STRING_fromBuf(&session->sync_state.keysync.key, "", 0);
   442 ||
   443 
   444 action tellWeAreGrouped
   445 ||
   446     session->sync_state.keysync.is_group = true;
   447 ||
   448 
   449 action tellWeAreNotGrouped
   450 ||
   451     session->sync_state.keysync.is_group = false;
   452 ||
   453 
   454 action disable;
   455