sync/cond_act_sync.yml2
author Volker Birk <vb@pep-project.org>
Thu, 02 May 2019 13:23:25 +0200
branchsync
changeset 3605 27595b58666d
parent 3601 0052c5587b9a
child 3609 548e7dd045e5
permissions -rw-r--r--
for three parties
     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 ||
   328 
   329 action saveGroupKeys
   330 ||
   331     identity_list *il = IdentityList_to_identity_list(&session->sync_state.keysync.ownIdentities, NULL);
   332     if (!il)
   333         return PEP_OUT_OF_MEMORY;
   334     
   335     // BUG: this should be a transaction and been rolled back completely on error
   336     for (identity_list *_il = il; _il && _il->ident; _il = _il->next) {
   337         PEP_STATUS status = set_identity(session, _il->ident);
   338         if (status) {
   339             free_identity_list(il);
   340             return status;
   341         }
   342     }
   343 
   344     free_identity_list(il);
   345 ||
   346 
   347 action ownKeysAreGroupKeys
   348 ||
   349     PEP_STATUS status = PEP_STATUS_OK;
   350 
   351     // set flag for current keys
   352     for (identity_list *il = session->own_sync_state.own_identities; il && il->ident ; il = il->next) {
   353         if (!(il->ident->flags && PEP_idf_not_for_sync)) {
   354             status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
   355             if (status)
   356                 return status;
   357         }
   358     }
   359 ||
   360 
   361 action receivedKeysAreGroupKeys
   362 ||
   363     PEP_STATUS status = PEP_STATUS_OK;
   364 
   365     // set flag for current keys
   366     for (identity_list *il = session->own_sync_state.own_identities; il && il->ident ; il = il->next) {
   367         if (!(il->ident->flags && PEP_idf_not_for_sync)) {
   368             status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
   369             if (status)
   370                 return status;
   371         }
   372     }
   373 
   374     identity_list *il = IdentityList_to_identity_list(&session->sync_state.keysync.ownIdentities, NULL);
   375     if (!il)
   376         return PEP_OUT_OF_MEMORY;
   377 
   378     for (il = session->own_sync_state.own_identities; il && il->ident ; il = il->next) {
   379         // replace partner's user_id with own user_id
   380         free(il->ident->user_id);
   381         il->ident->user_id = strdup(session->sync_state.common.from->user_id);
   382         if (!il->ident->user_id) {
   383             free_identity_list(il);
   384             return PEP_OUT_OF_MEMORY;
   385         }
   386 
   387         status = myself(session, il->ident);
   388         if (status) {
   389             free_identity_list(il);
   390             return status;
   391         }
   392 
   393         status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
   394         if (status) {
   395             free_identity_list(il);
   396             return status;
   397         }
   398     }
   399 
   400     free_identity_list(il);
   401 ||
   402 
   403 action trustThisKey
   404 ||
   405     assert(session->sync_state.common.from && session->sync_state.common.signature_fpr);
   406     if (!(session->sync_state.common.from && session->sync_state.common.signature_fpr))
   407         return PEP_ILLEGAL_VALUE;
   408 
   409     pEp_identity *ident = session->sync_state.common.from;
   410     free(ident->fpr);
   411     ident->fpr = strdup(session->sync_state.common.signature_fpr);
   412     assert(ident->fpr);
   413     if (!ident->fpr)
   414         return PEP_OUT_OF_MEMORY;
   415 
   416     PEP_STATUS status = trust_own_key(session, ident);
   417     if (status)
   418         return status;
   419 
   420     OCTET_STRING_fromBuf(&session->sync_state.keysync.key, ident->fpr, strlen(ident->fpr));
   421 ||
   422 
   423 action untrustThisKey
   424 ||
   425     assert(session->sync_state.common.from && session->sync_state.common.signature_fpr);
   426     if (!(session->sync_state.common.from && session->sync_state.common.signature_fpr))
   427         return PEP_ILLEGAL_VALUE;
   428 
   429     pEp_identity *ident = session->sync_state.common.from;
   430     free(ident->fpr);
   431     ident->fpr = strdup(session->sync_state.common.signature_fpr);
   432     assert(ident->fpr);
   433     if (!ident->fpr)
   434         return PEP_OUT_OF_MEMORY;
   435 
   436     PEP_STATUS status = key_reset_trust(session, ident);
   437     if (status)
   438         return status;
   439 
   440     OCTET_STRING_fromBuf(&session->sync_state.keysync.key, "", 0);
   441 ||
   442 
   443 action tellWeAreGrouped
   444 ||
   445     session->sync_state.keysync.is_group = true;
   446 ||
   447 
   448 action tellWeAreNotGrouped
   449 ||
   450     session->sync_state.keysync.is_group = false;
   451 ||
   452 
   453 action disable;
   454