sync/cond_act_sync.yml2
author Volker Birk <vb@pep-project.org>
Fri, 31 Jan 2020 14:50:40 +0100
branchsync
changeset 4391 0b2f7da808df
parent 4390 64a2a246abf5
child 4395 709b7ca25654
permissions -rw-r--r--
bad typo fixed
     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-2020, 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 weAreOfferer
    22 ||
    23     TID_t *t1 = &session->sync_state.keysync.challenge;
    24     TID_t *t2 = &session->sync_state.own.challenge;
    25 
    26     *result = _TID_greater(t1, t2);
    27 ||
    28 
    29 condition partnerIsGrouped
    30 |> *result = session->sync_state.keysync.is_group;
    31 
    32 condition sameChallenge
    33 ||
    34     TID_t *t1 = &session->sync_state.keysync.challenge;
    35     TID_t *t2 = &session->sync_state.own.challenge;
    36 
    37     *result = t1->size == t2->size && memcmp(t1->buf, t2->buf, t1->size) == 0;
    38 ||
    39 
    40 condition sameResponse
    41 ||
    42     TID_t *t1 = &session->sync_state.keysync.response;
    43     TID_t *t2 = &session->sync_state.own.response;
    44 
    45     *result = t1->size == t2->size && memcmp(t1->buf, t2->buf, t1->size) == 0;
    46 ||
    47 
    48 condition sameNegotiation
    49 ||
    50     TID_t *t1 = &session->sync_state.keysync.negotiation;
    51     TID_t *t2 = &session->sync_state.comm_partner.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 sameNegotiationAndPartner
    58 ||
    59     TID_t *t1 = &session->sync_state.keysync.negotiation;
    60     TID_t *t2 = &session->sync_state.comm_partner.negotiation;
    61 
    62     const char *s1 = session->sync_state.comm_partner.sender_fpr;
    63     const char *s2 = session->sync_state.transport.sender_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 fromGroupMember
    72 ||
    73     const char *sender_fpr = session->sync_state.comm_partner.sender_fpr;
    74     return is_own_key(session, sender_fpr, result);
    75 ||
    76 
    77 condition keyElectionWon
    78 ||
    79     pEp_identity *from = session->sync_state.transport.from;
    80     char *sender_fpr = session->sync_state.comm_partner.sender_fpr;
    81 
    82     assert(from && from->address && from->address[0] && from->user_id &&
    83             from->user_id[0]);
    84     if (!(from && from->address && from->address[0] && from->user_id &&
    85             from->user_id[0]))
    86         return PEP_ILLEGAL_VALUE;
    87 
    88     pEp_identity *me = NULL;
    89     PEP_STATUS status = get_identity(session, from->address, from->user_id, &me);
    90     assert(status == PEP_STATUS_OK);
    91     if (status)
    92         return status;
    93 
    94     assert(me->fpr && me->fpr[0]);
    95     if (!(me->fpr && me->fpr[0])) {
    96         free_identity(me);
    97         return PEP_ILLEGAL_VALUE;
    98     }
    99 
   100     size_t len = MIN(strlen(sender_fpr), strlen(me->fpr));
   101     *result = strncasecmp(sender_fpr, me->fpr, len) > 0;
   102     free_identity(me);
   103 ||
   104 
   105 // action: PEP_STATUS «@name»(PEP_SESSION session)
   106 
   107 function "new_UUID" {
   108     param "dst";
   109     ||
   110         {
   111             pEpUUID c;
   112             uuid_generate_random(c);
   113 
   114             OCTET_STRING_fromBuf(«$dst», (char *) c, 16);
   115         }
   116     ||
   117 }
   118 
   119 function "copy_UUID" {
   120     param "src", param "dst";
   121     ||
   122         {
   123             TID_t *src = «$src»;
   124             TID_t *dst = «$dst»;
   125 
   126             assert(src->size == 16);
   127             if (!(src->size == 16))
   128                 return PEP_UNKNOWN_ERROR;
   129 
   130             OCTET_STRING_fromBuf(dst, (char *) src->buf, src->size);
   131         }
   132     ||
   133 }
   134 
   135 function "xor_UUID" {
   136     param "src", param "dst";
   137     ||
   138         {
   139             TID_t *src = «$src»;
   140             TID_t *dst = «$dst»;
   141 
   142             assert(src->size == 16 && dst->size == 16);
   143             if (!(src->size == 16 && dst->size == 16))
   144                 return PEP_UNKNOWN_ERROR;
   145 
   146             for (int i=0; i < src->size; ++i)
   147                 dst->buf[i] ^= src->buf[i];
   148         }
   149     ||
   150 }
   151 
   152 action newChallengeAndNegotiationBase {
   153     // random new challenge
   154     call "new_UUID" with "dst" > &session->sync_state.own.challenge
   155     call "copy_UUID" {
   156         with "src" > &session->sync_state.own.challenge
   157         with "dst" > &session->sync_state.keysync.challenge
   158     }
   159 
   160     // random new response
   161     call "new_UUID" with "dst" > &session->sync_state.own.response
   162     call "copy_UUID" {
   163         with "src" > &session->sync_state.own.response
   164         with "dst" > &session->sync_state.keysync.response
   165     }
   166 
   167     // this is the random data we are using as a base
   168     call "new_UUID" with "dst" > &session->sync_state.own.negotiation
   169 ||
   170     memset(session->sync_state.keysync.negotiation.buf, 0,
   171             session->sync_state.keysync.negotiation.size);
   172     memset(session->sync_state.comm_partner.negotiation.buf, 0,
   173             session->sync_state.comm_partner.negotiation.size);
   174 ||
   175 }
   176 
   177 action useOwnChallenge call "copy_UUID" {
   178     with "src" > &session->sync_state.own.challenge
   179     with "dst" > &session->sync_state.keysync.challenge
   180 }
   181 
   182 action useOwnResponse call "copy_UUID" {
   183     with "src" > &session->sync_state.own.response
   184     with "dst" > &session->sync_state.keysync.response
   185 }
   186 
   187 action openNegotiation {
   188 ||
   189     // sender key must be stable while transaction
   190 
   191     // we take the actual signature of the last message and store it in our
   192     // state for the comm partner
   193     assert(session->sync_state.transport.sender_fpr);
   194 
   195     free(session->sync_state.comm_partner.sender_fpr);
   196 
   197     session->sync_state.comm_partner.sender_fpr
   198             = strdup(session->sync_state.transport.sender_fpr);
   199     assert(session->sync_state.comm_partner.sender_fpr);
   200     if (!session->sync_state.comm_partner.sender_fpr)
   201         return PEP_OUT_OF_MEMORY;
   202 
   203     // we need a unique TID for the Negotiation with each single comm_partner
   204     // we identify the comm_partners by their Challenge
   205     // we derive the actual Negotiation TID by having random data and XORing it
   206     // with comm_partner's Challenge
   207 
   208     // copy Negotiation base into buffer
   209 
   210 ||
   211     call "copy_UUID" {
   212         with "src" > &session->sync_state.own.negotiation
   213         with "dst" > &session->sync_state.keysync.negotiation
   214     }
   215 ||
   216 
   217     // we're XORing this with the challenge of the comm_partner, which is in
   218     // the buffer already
   219 
   220 ||
   221     call "xor_UUID" {
   222         with "src" > &session->sync_state.keysync.challenge
   223         with "dst" > &session->sync_state.keysync.negotiation
   224     }
   225 ||
   226 
   227     // this is the Negotiation's TID for this comm_partner
   228 
   229 ||
   230     call "copy_UUID" {
   231         with "src" > &session->sync_state.keysync.negotiation
   232         with "dst" > &session->sync_state.comm_partner.negotiation
   233     }
   234 }
   235 
   236 action storeNegotiation {
   237 ||
   238     // sender key must be stable while transaction
   239 
   240     // we take the actual signature of the last message and store it in our
   241     // state for the comm partner
   242     assert(session->sync_state.transport.sender_fpr);
   243 
   244     free(session->sync_state.comm_partner.sender_fpr);
   245 
   246     session->sync_state.comm_partner.sender_fpr
   247             = strdup(session->sync_state.transport.sender_fpr);
   248     assert(session->sync_state.comm_partner.sender_fpr);
   249     if (!session->sync_state.comm_partner.sender_fpr)
   250         return PEP_OUT_OF_MEMORY;
   251 
   252 ||
   253     call "copy_UUID" {
   254         with "src" > &session->sync_state.keysync.negotiation
   255         with "dst" > &session->sync_state.comm_partner.negotiation
   256     }
   257 }
   258 
   259 function "show_handshake" {
   260     param "type";
   261     ||
   262         assert(session->notifyHandshake);
   263         if (!session->notifyHandshake)
   264             return PEP_SYNC_NO_NOTIFY_CALLBACK;
   265 
   266     ||
   267     choose {
   268     when "$type = 'SYNC_NOTIFY_INIT_ADD_OUR_DEVICE' or $type = 'SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE' or $type = 'SYNC_NOTIFY_INIT_FORM_GROUP'"
   269     ||
   270         assert(session->sync_state.transport.from);
   271         if (!session->sync_state.transport.from)
   272             return PEP_ILLEGAL_VALUE;
   273 
   274         pEp_identity *from = session->sync_state.transport.from;
   275         pEp_identity *me = NULL;
   276         PEP_STATUS status = get_identity(session, from->address, from->user_id, &me);
   277         assert(status == PEP_STATUS_OK);
   278         if (status)
   279             return status;
   280 
   281         assert(me->fpr && me->fpr[0]);
   282         if (!(me->fpr && me->fpr[0])) {
   283             free_identity(me);
   284             return PEP_ILLEGAL_VALUE;
   285         }
   286 
   287         pEp_identity *partner = identity_dup(from);
   288         if (!partner) {
   289             free_identity(me);
   290             return PEP_OUT_OF_MEMORY;
   291         }
   292 
   293         assert(session->sync_state.comm_partner.sender_fpr);
   294         if (session->sync_state.comm_partner.sender_fpr) {
   295             free(partner->fpr);
   296             partner->fpr = strdup(session->sync_state.comm_partner.sender_fpr);
   297             assert(partner->fpr);
   298             if (!partner->fpr) {
   299                 free_identity(me);
   300                 free_identity(partner);
   301                 return PEP_OUT_OF_MEMORY;
   302             }
   303         }
   304 
   305         free(partner->user_id);
   306         partner->user_id = strdup("#NV");
   307         assert(partner->user_id);
   308         if (!partner->user_id) {
   309             free_identity(me);
   310             free_identity(partner);
   311             return PEP_OUT_OF_MEMORY;
   312         }
   313 
   314         status = session->notifyHandshake(me, partner, «$type»);
   315         if (status)
   316             return status;
   317     ||
   318     otherwise
   319     ||
   320         pEp_identity *me = new_identity(NULL, NULL, NULL, NULL);
   321         pEp_identity *partner = new_identity(NULL, NULL, NULL, NULL);
   322         assert(me && partner);
   323         if (!(me && partner)) {
   324             free_identity(me);
   325             free_identity(partner);
   326             return PEP_OUT_OF_MEMORY;
   327         }
   328 
   329         PEP_STATUS status = session->notifyHandshake(me, partner, «$type»);
   330         if (status)
   331             return status;
   332     ||
   333     }
   334 }
   335 
   336 action showSoleHandshake
   337     call "show_handshake" with "type" > SYNC_NOTIFY_INIT_FORM_GROUP
   338 
   339 action showJoinGroupHandshake
   340     call "show_handshake" with "type" > SYNC_NOTIFY_INIT_ADD_OUR_DEVICE
   341 
   342 action showGroupedHandshake
   343     call "show_handshake" with "type" > SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE
   344 
   345 action showDeviceAdded
   346     call "show_handshake" with "type" > SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED
   347 
   348 action showDeviceAccepted
   349     call "show_handshake" with "type" > SYNC_NOTIFY_ACCEPTED_DEVICE_ACCEPTED
   350 
   351 action showGroupCreated
   352     call "show_handshake" with "type" > SYNC_NOTIFY_ACCEPTED_GROUP_CREATED
   353 
   354 action showBeingSole
   355     call "show_handshake" with "type" > SYNC_NOTIFY_SOLE
   356 
   357 action showBeingInGroup
   358     call "show_handshake" with "type" > SYNC_NOTIFY_IN_GROUP
   359 
   360 timeout KeySync
   361     call "show_handshake" with "type" > SYNC_NOTIFY_TIMEOUT
   362 
   363 action prepareOwnKeys
   364 ||
   365     stringlist_t *own_keys;
   366     PEP_STATUS status = _own_keys_retrieve(session, &own_keys, PEP_idf_not_for_sync, true);
   367     if (status)
   368         return status;
   369 
   370     if (session->sync_state.own.keys)
   371         free_stringlist(session->sync_state.own.keys);
   372     session->sync_state.own.keys = own_keys;
   373 
   374     identity_list *il;
   375     status = _own_identities_retrieve(session, &il, PEP_idf_not_for_sync);
   376     if (status)
   377         return status;
   378 
   379     IdentityList_from_identity_list(il, &session->sync_state.keysync.ownIdentities);
   380     free_identity_list(il);
   381 ||
   382 
   383 action saveGroupKeys
   384 ||
   385     char *user_id = NULL;
   386     PEP_STATUS status = get_default_own_userid(session, &user_id);
   387     if (status)
   388         return status;
   389 
   390     identity_list *il = IdentityList_to_identity_list(&session->sync_state.keysync.ownIdentities, NULL);
   391     if (!il) {
   392         free(user_id);
   393         return PEP_OUT_OF_MEMORY;
   394     }
   395     status = set_all_userids_to_own(session, il);
   396     if (status != PEP_STATUS_OK) {
   397         free(user_id);
   398         return status;
   399     }
   400 
   401     identity_list *oil = session->sync_state.own.identities;
   402 
   403     // BUG: this should be a transaction and been rolled back completely on error
   404     for (identity_list *_il = il; _il && _il->ident; _il = _il->next) {
   405         bool found = false;
   406         status = _have_identity_in(oil, _il->ident, &found);
   407         if (status)
   408             break;
   409 
   410         if (!found) {
   411             _il->ident->me = true;
   412 
   413             status = set_identity(session, _il->ident);
   414             if (status)
   415                 break;
   416         }
   417     }
   418 
   419     free(user_id);
   420     free_identity_list(il);
   421 ||
   422 
   423 action ownKeysAreDefaultKeys
   424 ||
   425     PEP_STATUS status = PEP_STATUS_OK;
   426 
   427     // set flag for all keys; don't change anything else
   428     for (identity_list *il = session->sync_state.own.identities; il && il->ident ; il = il->next) {
   429         if (!(il->ident->flags & PEP_idf_not_for_sync)) {
   430             status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
   431             if (status)
   432                 return status;
   433         }
   434     }
   435 ||
   436 
   437 action receivedKeysAreDefaultKeys
   438 ||
   439     PEP_STATUS status = PEP_STATUS_OK;
   440     // set flag for all keys
   441     for (identity_list *il = session->sync_state.own.identities; il && il->ident ; il = il->next) {
   442         if (!(il->ident->flags & PEP_idf_not_for_sync)) {
   443 
   444             status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
   445             if (status)
   446                 return status;
   447         }
   448     }
   449 
   450     char *user_id = NULL;
   451     status = get_default_own_userid(session, &user_id);
   452     if (status)
   453         return status;
   454 
   455     identity_list *il = IdentityList_to_identity_list(&session->sync_state.keysync.ownIdentities, NULL);
   456     if (!il)
   457         return PEP_OUT_OF_MEMORY;
   458 
   459     status = set_all_userids_to_own(session, il);
   460     if (status != PEP_STATUS_OK) {
   461         free(user_id);
   462         return status;
   463     }
   464 
   465     for (identity_list *_il = il; _il && _il->ident ; _il = _il->next) {
   466         status = set_own_key(session, _il->ident, _il->ident->fpr);
   467         if (status) {
   468             free_identity_list(il);
   469             free(user_id);
   470             return status;
   471         }
   472     }
   473 
   474     free_identity_list(il);
   475     free(user_id);
   476 ||
   477 
   478 action useThisKey
   479 ||
   480     assert(session->sync_state.comm_partner.sender_fpr);
   481     if (!session->sync_state.comm_partner.sender_fpr)
   482         return PEP_ILLEGAL_VALUE;
   483 
   484     const char *fpr = session->sync_state.comm_partner.sender_fpr;
   485     OCTET_STRING_fromBuf(&session->sync_state.keysync.key, fpr, strlen(fpr));
   486 ||
   487 
   488 action storeThisKey
   489 ||
   490     assert(session->sync_state.keysync.key.size);
   491     if (!session->sync_state.keysync.key.size)
   492         return PEP_ILLEGAL_VALUE;
   493 
   494     char *fpr = strndup((const char *) session->sync_state.keysync.key.buf, session->sync_state.keysync.key.size);
   495     assert(fpr);
   496     if (!fpr)
   497         return PEP_OUT_OF_MEMORY;
   498 
   499     free(session->sync_state.comm_partner.sender_fpr);
   500     session->sync_state.comm_partner.sender_fpr = fpr;
   501 ||
   502 
   503 action trustThisKey
   504 ||
   505     assert(session->sync_state.transport.from && session->sync_state.comm_partner.sender_fpr);
   506     if (!(session->sync_state.transport.from && session->sync_state.comm_partner.sender_fpr))
   507         return PEP_ILLEGAL_VALUE;
   508 
   509     pEp_identity *ident = identity_dup(session->sync_state.transport.from);
   510     if (!ident)
   511         return PEP_OUT_OF_MEMORY;
   512     free(ident->fpr);
   513     ident->fpr = strdup(session->sync_state.comm_partner.sender_fpr);
   514     assert(ident->fpr);
   515     if (!ident->fpr) {
   516         free_identity(ident);
   517         return PEP_OUT_OF_MEMORY;
   518     }
   519 
   520     PEP_STATUS status = trust_own_key(session, ident);
   521     if (status) {
   522         free_identity(ident);
   523         return status;
   524     }
   525 
   526     OCTET_STRING_fromBuf(&session->sync_state.keysync.key, ident->fpr, strlen(ident->fpr));
   527     free_identity(ident);
   528 ||
   529 
   530 action untrustThisKey
   531 ||
   532     assert(session->sync_state.transport.from && session->sync_state.comm_partner.sender_fpr);
   533     if (!(session->sync_state.transport.from && session->sync_state.comm_partner.sender_fpr))
   534         return PEP_ILLEGAL_VALUE;
   535 
   536     pEp_identity *ident = session->sync_state.transport.from;
   537     free(ident->fpr);
   538     ident->fpr = strdup(session->sync_state.comm_partner.sender_fpr);
   539     assert(ident->fpr);
   540     if (!ident->fpr)
   541         return PEP_OUT_OF_MEMORY;
   542 
   543     PEP_STATUS status = key_reset_trust(session, ident);
   544     if (status)
   545         return status;
   546 
   547     OCTET_STRING_fromBuf(&session->sync_state.keysync.key, "", 0);
   548 ||
   549 
   550 action tellWeAreGrouped
   551 ||
   552     session->sync_state.keysync.is_group = true;
   553 ||
   554 
   555 action tellWeAreNotGrouped
   556 ||
   557     session->sync_state.keysync.is_group = false;
   558 ||
   559 
   560 action disable
   561 ||
   562     disable_sync(session);
   563 ||
   564 
   565 action resetOwnGroupedKeys
   566 ||
   567     return key_reset_own_grouped_keys(session);
   568 ||
   569 
   570 action resetOwnKeysUngrouped
   571 ||
   572     return key_reset_all_own_keys(session);
   573 ||