sync/cond_act_sync.yml2
author Volker Birk <vb@pep-project.org>
Wed, 29 May 2019 16:15:30 +0200
branchsync
changeset 3768 7fc561191d28
parent 3767 11a9d0f61073
child 3772 f4d6efa63ee1
permissions -rw-r--r--
make temporary state visible in code
     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.comm_partner.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.comm_partner.from;
    74     char *signature_fpr = session->sync_state.comm_partner.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.temp.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.temp.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.comm_partner.signature_fpr);
   168     free(session->own_sync_state.signature_fpr);
   169     session->own_sync_state.signature_fpr
   170             = strdup(session->sync_state.comm_partner.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.comm_partner.signature_fpr);
   202     free(session->own_sync_state.signature_fpr);
   203     session->own_sync_state.signature_fpr
   204             = strdup(session->sync_state.comm_partner.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.comm_partner.from);
   243         if (!session->sync_state.comm_partner.from)
   244             return PEP_ILLEGAL_VALUE;
   245 
   246         pEp_identity *from = session->sync_state.comm_partner.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.comm_partner.signature_fpr);
   266         if (session->sync_state.comm_partner.signature_fpr) {
   267             free(partner->fpr);
   268             partner->fpr = strdup(session->sync_state.comm_partner.signature_fpr);
   269             if (!partner->fpr) {
   270                 free_identity(me);
   271                 free_identity(partner);
   272                 return PEP_OUT_OF_MEMORY;
   273             }
   274         }
   275 
   276         free(partner->user_id);
   277         partner->user_id = strdup("#NV");
   278         assert(partner->user_id);
   279         if (!partner->user_id) {
   280             free_identity(me);
   281             free_identity(partner);
   282             return PEP_OUT_OF_MEMORY;
   283         }
   284 
   285         status = session->notifyHandshake(me, partner, «$type»);
   286         if (status)
   287             return status;
   288     ||
   289     }
   290 }
   291 
   292 action showSoleHandshake
   293     call "show_handshake" with "type" > SYNC_NOTIFY_INIT_FORM_GROUP
   294 
   295 action showJoinGroupHandshake
   296     call "show_handshake" with "type" > SYNC_NOTIFY_INIT_ADD_OUR_DEVICE
   297 
   298 action showGroupedHandshake
   299     call "show_handshake" with "type" > SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE
   300 
   301 action hideHandshakeDialog
   302     call "show_handshake" with "type" > SYNC_NOTIFY_OVERTAKEN
   303 
   304 action showDeviceAdded
   305     call "show_handshake" with "type" > SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED
   306 
   307 action showGroupCreated
   308     call "show_handshake" with "type" > SYNC_NOTIFY_ACCEPTED_GROUP_CREATED
   309 
   310 action showBeingSole
   311     call "show_handshake" with "type" > SYNC_NOTIFY_SOLE
   312 
   313 action showBeingInGroup
   314     call "show_handshake" with "type" > SYNC_NOTIFY_IN_GROUP
   315 
   316 timeout KeySync
   317     call "show_handshake" with "type" > SYNC_NOTIFY_TIMEOUT
   318 
   319 action prepareOwnKeys
   320 ||
   321     stringlist_t *own_keys;
   322     PEP_STATUS status = _own_keys_retrieve(session, &own_keys, PEP_idf_not_for_sync, true);
   323     if (status)
   324         return status;
   325 
   326     if (session->own_sync_state.own_keys)
   327         free_stringlist(session->own_sync_state.own_keys);
   328     session->own_sync_state.own_keys = own_keys;
   329 
   330     identity_list *il;
   331     status = _own_identities_retrieve(session, &il, PEP_idf_not_for_sync);
   332     if (status)
   333         return status;
   334 
   335     IdentityList_from_identity_list(il, &session->sync_state.keysync.ownIdentities);
   336     free_identity_list(il);
   337 ||
   338 
   339 action saveGroupKeys
   340 ||
   341     identity_list *il = IdentityList_to_identity_list(&session->sync_state.keysync.ownIdentities, NULL);
   342     if (!il)
   343         return PEP_OUT_OF_MEMORY;
   344     
   345     // BUG: this should be a transaction and been rolled back completely on error
   346     for (identity_list *_il = il; _il && _il->ident; _il = _il->next) {
   347         PEP_STATUS status = set_identity(session, _il->ident);
   348         if (status) {
   349             free_identity_list(il);
   350             return status;
   351         }
   352     }
   353 
   354     free_identity_list(il);
   355 ||
   356 
   357 action ownKeysAreGroupKeys
   358 ||
   359     PEP_STATUS status = PEP_STATUS_OK;
   360 
   361     // set flag for current keys
   362     for (identity_list *il = session->own_sync_state.own_identities; il && il->ident ; il = il->next) {
   363         if (!(il->ident->flags && PEP_idf_not_for_sync)) {
   364             status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
   365             if (status)
   366                 return status;
   367         }
   368     }
   369 ||
   370 
   371 action receivedKeysAreGroupKeys
   372 ||
   373     PEP_STATUS status = PEP_STATUS_OK;
   374 
   375     // set flag for current keys
   376     for (identity_list *il = session->own_sync_state.own_identities; il && il->ident ; il = il->next) {
   377         if (!(il->ident->flags && PEP_idf_not_for_sync)) {
   378             status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
   379             if (status)
   380                 return status;
   381         }
   382     }
   383 
   384     identity_list *il = IdentityList_to_identity_list(&session->sync_state.keysync.ownIdentities, NULL);
   385     if (!il)
   386         return PEP_OUT_OF_MEMORY;
   387 
   388     for (il = session->own_sync_state.own_identities; il && il->ident ; il = il->next) {
   389         // replace partner's user_id with own user_id
   390         free(il->ident->user_id);
   391         il->ident->user_id = strdup(session->sync_state.comm_partner.from->user_id);
   392         if (!il->ident->user_id) {
   393             free_identity_list(il);
   394             return PEP_OUT_OF_MEMORY;
   395         }
   396 
   397         status = myself(session, il->ident);
   398         if (status) {
   399             free_identity_list(il);
   400             return status;
   401         }
   402 
   403         status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
   404         if (status) {
   405             free_identity_list(il);
   406             return status;
   407         }
   408     }
   409 
   410     free_identity_list(il);
   411 ||
   412 
   413 action trustThisKey
   414 ||
   415     assert(session->sync_state.comm_partner.from && session->sync_state.comm_partner.signature_fpr);
   416     if (!(session->sync_state.comm_partner.from && session->sync_state.comm_partner.signature_fpr))
   417         return PEP_ILLEGAL_VALUE;
   418 
   419     pEp_identity *ident = identity_dup(session->sync_state.comm_partner.from);
   420     if (!ident)
   421         return PEP_OUT_OF_MEMORY;
   422     free(ident->fpr);
   423     ident->fpr = strdup(session->sync_state.comm_partner.signature_fpr);
   424     assert(ident->fpr);
   425     if (!ident->fpr) {
   426         free_identity(ident);
   427         return PEP_OUT_OF_MEMORY;
   428     }
   429 
   430     PEP_STATUS status = trust_own_key(session, ident);
   431     if (status) {
   432         free_identity(ident);
   433         return status;
   434     }
   435 
   436     OCTET_STRING_fromBuf(&session->sync_state.keysync.key, ident->fpr, strlen(ident->fpr));
   437     free_identity(ident);
   438 ||
   439 
   440 action untrustThisKey
   441 ||
   442     assert(session->sync_state.comm_partner.from && session->sync_state.comm_partner.signature_fpr);
   443     if (!(session->sync_state.comm_partner.from && session->sync_state.comm_partner.signature_fpr))
   444         return PEP_ILLEGAL_VALUE;
   445 
   446     pEp_identity *ident = session->sync_state.comm_partner.from;
   447     free(ident->fpr);
   448     ident->fpr = strdup(session->sync_state.comm_partner.signature_fpr);
   449     assert(ident->fpr);
   450     if (!ident->fpr)
   451         return PEP_OUT_OF_MEMORY;
   452 
   453     PEP_STATUS status = key_reset_trust(session, ident);
   454     if (status)
   455         return status;
   456 
   457     OCTET_STRING_fromBuf(&session->sync_state.keysync.key, "", 0);
   458 ||
   459 
   460 action tellWeAreGrouped
   461 ||
   462     session->sync_state.keysync.is_group = true;
   463 ||
   464 
   465 action tellWeAreNotGrouped
   466 ||
   467     session->sync_state.keysync.is_group = false;
   468 ||
   469 
   470 action disable;
   471