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