merging in default ENGINE-118
authorKrista Grothoff <krista@pep-project.org>
Wed, 19 Oct 2016 12:48:13 +0200
branchENGINE-118
changeset 1322517692958c78
parent 1311 9d70c1d3f6b6
parent 1317 0e6df10f76c4
child 1323 4501141bf217
merging in default
     1.1 --- a/README-OSX.md	Tue Oct 18 17:36:15 2016 +0200
     1.2 +++ b/README-OSX.md	Wed Oct 19 12:48:13 2016 +0200
     1.3 @@ -27,7 +27,7 @@
     1.4  sudo port install mercurial
     1.5  sudo port install py27-lxml
     1.6  sudo port install gpgme
     1.7 -sudo port install autoconf
     1.8 +sudo port install automake
     1.9  sudo port install asn1c
    1.10  sudo port install zlib
    1.11  ```
     2.1 --- a/src/message_api.c	Tue Oct 18 17:36:15 2016 +0200
     2.2 +++ b/src/message_api.c	Wed Oct 19 12:48:13 2016 +0200
     2.3 @@ -1907,6 +1907,88 @@
     2.4      assert(false);
     2.5  }
     2.6  
     2.7 +static bool _is_valid_hex(const char* hexstr) {
     2.8 +    if (!hexstr)
     2.9 +        return false;
    2.10 +    
    2.11 +    const char* curr = hexstr;
    2.12 +    char currchar;
    2.13 +    
    2.14 +    for (currchar = *curr; currchar != '\0'; currchar = *(++curr)) {
    2.15 +        if ((currchar >= '0' && currchar <= '9') ||
    2.16 +            (currchar >= 'a' && currchar <= 'f') ||
    2.17 +            (currchar >= 'A' && currchar <= 'F')) 
    2.18 +        {
    2.19 +            continue;
    2.20 +        }
    2.21 +        return false;
    2.22 +    }
    2.23 +    return true;        
    2.24 +}
    2.25 +
    2.26 +// Returns, in comparison: 1 if fpr1 > fpr2, 0 if equal, -1 if fpr1 < fpr2
    2.27 +static PEP_STATUS _compare_fprs(const char* fpr1, const char* fpr2, int* comparison) {
    2.28 +    
    2.29 +    const int _FULL_FINGERPRINT_LENGTH = 40;
    2.30 +    const int _ASCII_LOWERCASE_OFFSET = 32;
    2.31 +
    2.32 +    size_t fpr1_len = strlen(fpr1);
    2.33 +    size_t fpr2_len = strlen(fpr2);
    2.34 +    
    2.35 +    if (fpr1_len != _FULL_FINGERPRINT_LENGTH || fpr2_len != _FULL_FINGERPRINT_LENGTH)
    2.36 +        return PEP_TRUSTWORDS_FPR_WRONG_LENGTH;
    2.37 +    
    2.38 +    if (!_is_valid_hex(fpr1) || !_is_valid_hex(fpr2))
    2.39 +        return PEP_ILLEGAL_VALUE;
    2.40 +    
    2.41 +    const char* fpr1_curr = fpr1;
    2.42 +    const char* fpr2_curr = fpr2;
    2.43 +    
    2.44 +    char current;
    2.45 +
    2.46 +    // Advance past leading zeros.
    2.47 +    for (current = *fpr1_curr; current != '0' && current != '\0'; current = *(++fpr1_curr), fpr1_len--);
    2.48 +    for (current = *fpr2_curr; current != '0' && current != '\0'; current = *(++fpr2_curr), fpr2_len--);
    2.49 +    
    2.50 +    if (fpr1_len == fpr2_len) {
    2.51 +        char digit1;
    2.52 +        char digit2;
    2.53 +
    2.54 +        while (fpr1_curr && *fpr1_curr != '\0') {
    2.55 +            digit1 = *fpr1_curr++;
    2.56 +            digit2 = *fpr2_curr++;
    2.57 +
    2.58 +            // Adjust for case-insensitive compare
    2.59 +            if (digit1 >= 'a' && digit1 <= 'f')
    2.60 +                digit1 -= _ASCII_LOWERCASE_OFFSET;
    2.61 +            if (digit2 >= 'a' && digit2 <= 'f')
    2.62 +                digit2 -= _ASCII_LOWERCASE_OFFSET;
    2.63 +                        
    2.64 +            // We take advantage of the fact that 'a'-'f' are larger
    2.65 +            // integer values in the ASCII table than '0'-'9'.
    2.66 +            // This allows us to compare digits directly.
    2.67 +            if (digit1 > digit2) {
    2.68 +                *comparison = 1;
    2.69 +                return PEP_STATUS_OK;
    2.70 +            } else if (digit1 < digit2) {
    2.71 +                *comparison = -1;
    2.72 +                return PEP_STATUS_OK;
    2.73 +            }
    2.74 +            
    2.75 +            // pointers already advanced above. Keep going.
    2.76 +        }
    2.77 +        *comparison = 0;
    2.78 +        return PEP_STATUS_OK;
    2.79 +    }
    2.80 +    else if (fpr1_len > fpr2_len) {
    2.81 +        *comparison = 1;
    2.82 +        return PEP_STATUS_OK;
    2.83 +    }
    2.84 +    // Otherwise, fpr1_len < fpr2_len
    2.85 +    *comparison = -1;
    2.86 +    return PEP_STATUS_OK;
    2.87 +}
    2.88 +
    2.89  DYNAMIC_API PEP_STATUS get_trustwords(
    2.90      PEP_SESSION session, pEp_identity* id1, pEp_identity* id2,
    2.91      const char* lang, char **words, size_t *wsize, bool full
    2.92 @@ -1940,28 +2022,43 @@
    2.93      char* second_set = NULL;
    2.94      size_t first_wsize = 0;
    2.95      size_t second_wsize = 0;
    2.96 -    PEP_STATUS status = PEP_UNKNOWN_ERROR;
    2.97      
    2.98 +    int fpr_comparison = -255;
    2.99 +    PEP_STATUS status = _compare_fprs(source1, source2, &fpr_comparison);
   2.100 +    if (status != PEP_STATUS_OK)
   2.101 +        return status;
   2.102 +
   2.103      char* _retstr = NULL;
   2.104 +
   2.105 +    switch (fpr_comparison) {
   2.106 +        case 1: // source1 > source2
   2.107 +            status = trustwords(session, source2, lang, &first_set, &first_wsize, max_words_per_id);
   2.108 +            if (status != PEP_STATUS_OK)
   2.109 +                goto error_release;
   2.110 +            status = trustwords(session, source1, lang, &second_set, &second_wsize, max_words_per_id); 
   2.111 +            if (status != PEP_STATUS_OK)
   2.112 +                goto error_release;
   2.113 +            break;
   2.114 +        case 0: 
   2.115 +        case -1: // source1 <= source2
   2.116 +            status = trustwords(session, source1, lang, &first_set, &first_wsize, max_words_per_id);
   2.117 +            if (status != PEP_STATUS_OK)
   2.118 +                goto error_release;
   2.119 +            status = trustwords(session, source2, lang, &second_set, &second_wsize, max_words_per_id); 
   2.120 +            if (status != PEP_STATUS_OK)
   2.121 +                goto error_release;
   2.122 +            break;
   2.123 +        default:
   2.124 +            return PEP_UNKNOWN_ERROR; // shouldn't be possible
   2.125 +    }
   2.126      
   2.127 -    if (source1 > source2) {
   2.128 -        status = trustwords(session, source2, lang, &first_set, &first_wsize, max_words_per_id);
   2.129 -        if (status != PEP_STATUS_OK)
   2.130 -            goto error_release;
   2.131 -        status = trustwords(session, source1, lang, &second_set, &second_wsize, max_words_per_id); 
   2.132 -        if (status != PEP_STATUS_OK)
   2.133 -            goto error_release;
   2.134 -    }
   2.135 -    else {
   2.136 -        status = trustwords(session, source1, lang, &first_set, &first_wsize, max_words_per_id);
   2.137 -        if (status != PEP_STATUS_OK)
   2.138 -            goto error_release;
   2.139 -        status = trustwords(session, source2, lang, &second_set, &second_wsize, max_words_per_id); 
   2.140 -        if (status != PEP_STATUS_OK)
   2.141 -            goto error_release;
   2.142 -    }
   2.143      size_t _wsize = first_wsize + second_wsize;
   2.144      
   2.145 +    bool needs_space = (first_set[first_wsize - 1] != ' ');
   2.146 +    
   2.147 +    if (needs_space)
   2.148 +        _wsize++;
   2.149 +    
   2.150      _retstr = calloc(1, _wsize + 1);
   2.151      
   2.152      size_t len = strlcpy(_retstr, first_set, _wsize);
   2.153 @@ -1969,6 +2066,13 @@
   2.154          status = PEP_UNKNOWN_ERROR;
   2.155          goto error_release;
   2.156      }
   2.157 +    if (needs_space) {
   2.158 +        strlcat(_retstr, " ", _wsize);
   2.159 +        if (len >= _wsize) {
   2.160 +            status = PEP_UNKNOWN_ERROR;
   2.161 +            goto error_release;
   2.162 +        }
   2.163 +    }
   2.164      strlcat(_retstr, second_set, _wsize);
   2.165      if (len >= _wsize){
   2.166          status = PEP_UNKNOWN_ERROR;
   2.167 @@ -1988,4 +2092,5 @@
   2.168      free(first_set);
   2.169      free(second_set);
   2.170      return status;
   2.171 -}
   2.172 \ No newline at end of file
   2.173 +}
   2.174 +
     3.1 --- a/src/pEpEngine.h	Tue Oct 18 17:36:15 2016 +0200
     3.2 +++ b/src/pEpEngine.h	Wed Oct 19 12:48:13 2016 +0200
     3.3 @@ -63,6 +63,7 @@
     3.4      PEP_CANNOT_DECRYPT_UNKNOWN                      = 0x04ff,
     3.5  
     3.6      PEP_TRUSTWORD_NOT_FOUND                         = 0x0501,
     3.7 +    PEP_TRUSTWORDS_FPR_WRONG_LENGTH                 = 0x0502,
     3.8  
     3.9      PEP_CANNOT_CREATE_KEY                           = 0x0601,
    3.10      PEP_CANNOT_SEND_KEY                             = 0x0602,
    3.11 @@ -88,6 +89,7 @@
    3.12      PEP_STATEMACHINE_INVALID_EVENT                  = 0x0983,
    3.13      PEP_STATEMACHINE_INVALID_CONDITION              = 0x0984,
    3.14      PEP_STATEMACHINE_INVALID_ACTION                 = 0x0985,
    3.15 +    PEP_STATEMACHINE_INHIBITED_EVENT                = 0x0986,
    3.16  
    3.17      PEP_COMMIT_FAILED                               = 0xff01,
    3.18      PEP_MESSAGE_CONSUMED                            = 0xff02,
     4.1 --- a/src/pEp_internal.h	Tue Oct 18 17:36:15 2016 +0200
     4.2 +++ b/src/pEp_internal.h	Wed Oct 19 12:48:13 2016 +0200
     4.3 @@ -142,6 +142,8 @@
     4.4      // key sync
     4.5      DeviceState_state sync_state;
     4.6      char sync_uuid[37];
     4.7 +    time_t LastCannotDecrypt;
     4.8 +    time_t LastUpdateRequest;
     4.9  
    4.10      // runtime config
    4.11  
     5.1 --- a/src/sync_impl.c	Tue Oct 18 17:36:15 2016 +0200
     5.2 +++ b/src/sync_impl.c	Wed Oct 19 12:48:13 2016 +0200
     5.3 @@ -14,6 +14,9 @@
     5.4  #define SYNC_VERSION_MAJOR 1
     5.5  #define SYNC_VERSION_MINOR 0
     5.6  
     5.7 +#define SYNC_INHIBIT_TIME (60*10)
     5.8 +#define SYNC_MSG_EXPIRE_TIME (60 * 10)
     5.9 +
    5.10  struct _sync_msg_t {
    5.11      bool is_a_message;
    5.12      union {
    5.13 @@ -49,34 +52,20 @@
    5.14  
    5.15          switch (msg->payload.present) {
    5.16              case DeviceGroup_Protocol__payload_PR_beacon:
    5.17 -                partner = Identity_to_Struct(&msg->header.me, NULL);
    5.18 -                if (!partner){
    5.19 -                    status = PEP_OUT_OF_MEMORY;
    5.20 -                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
    5.21 -                    goto error;
    5.22 -                }
    5.23                  event = Beacon;
    5.24                  break;
    5.25  
    5.26              case DeviceGroup_Protocol__payload_PR_handshakeRequest:
    5.27 -                partner = Identity_to_Struct(&msg->header.me, NULL);
    5.28 -                if (!partner){
    5.29 -                    status = PEP_OUT_OF_MEMORY;
    5.30 -                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
    5.31 -                    goto error;
    5.32 -                }
    5.33 +                event = HandshakeRequest;
    5.34 +                break;
    5.35  
    5.36 -                event = HandshakeRequest;
    5.37 +            case DeviceGroup_Protocol__payload_PR_updateRequest:
    5.38 +                event = UpdateRequest;
    5.39                  break;
    5.40  
    5.41              case DeviceGroup_Protocol__payload_PR_groupKeys:
    5.42              case DeviceGroup_Protocol__payload_PR_groupUpdate:
    5.43 -                partner = Identity_to_Struct(&msg->header.me, NULL);
    5.44 -                if (!partner){
    5.45 -                    status = PEP_OUT_OF_MEMORY;
    5.46 -                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
    5.47 -                    goto error;
    5.48 -                }
    5.49 +            {
    5.50                  identity_list *group_keys = IdentityList_to_identity_list(
    5.51                          msg->payload.present == 
    5.52                            DeviceGroup_Protocol__payload_PR_groupKeys ?
    5.53 @@ -84,7 +73,6 @@
    5.54                              &msg->payload.choice.groupUpdate.ownIdentities,
    5.55                          NULL);
    5.56                  if (!group_keys) {
    5.57 -                    free_identity(partner);
    5.58                      status = PEP_OUT_OF_MEMORY;
    5.59                      ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
    5.60                      goto error;
    5.61 @@ -94,12 +82,20 @@
    5.62                            DeviceGroup_Protocol__payload_PR_groupKeys ?
    5.63                              GroupKeys : GroupUpdate;
    5.64                  break;
    5.65 +            }
    5.66  
    5.67              default:
    5.68                  status = PEP_SYNC_ILLEGAL_MESSAGE;
    5.69                  ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
    5.70                  goto error;
    5.71          }
    5.72 +
    5.73 +        partner = Identity_to_Struct(&msg->header.me, NULL);
    5.74 +        if (!partner){
    5.75 +            status = PEP_OUT_OF_MEMORY;
    5.76 +            ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
    5.77 +            goto error;
    5.78 +        }
    5.79      }
    5.80      else{
    5.81          partner = sync_msg->u.event.partner;
    5.82 @@ -107,6 +103,30 @@
    5.83          event = sync_msg->u.event.event;
    5.84      }
    5.85  
    5.86 +    // Event inhibition, to limit mailbox and prevent cycles
    5.87 +    time_t *last = NULL;
    5.88 +    switch(event){
    5.89 +        case CannotDecrypt:
    5.90 +            last = &session->LastCannotDecrypt;
    5.91 +            break;
    5.92 +
    5.93 +        case UpdateRequest:
    5.94 +            last = &session->LastUpdateRequest;
    5.95 +            break;
    5.96 +
    5.97 +        default:
    5.98 +            break;
    5.99 +    }
   5.100 +    time_t now = time(NULL);
   5.101 +    if(last != NULL){
   5.102 +        if(*last != 0 && (*last + SYNC_INHIBIT_TIME) > now ){
   5.103 +            free_identity(partner);
   5.104 +            status = PEP_STATEMACHINE_INHIBITED_EVENT;
   5.105 +            goto error;
   5.106 +        }
   5.107 +        *last = now;
   5.108 +    }
   5.109 +
   5.110      // partner identity must be explicitely added DB to later
   5.111      // be able to communicate securely with it.
   5.112      if(partner){
   5.113 @@ -227,9 +247,6 @@
   5.114      return status;
   5.115  }
   5.116  
   5.117 -// Ten minutes
   5.118 -#define SYNC_MSG_EXPIRE_DELTA (60 * 10)
   5.119 -
   5.120  PEP_STATUS receive_DeviceState_msg(
   5.121      PEP_SESSION session, 
   5.122      message *src, 
   5.123 @@ -266,7 +283,7 @@
   5.124  
   5.125                  // check message expiry 
   5.126                  if(src->recv) {
   5.127 -                    time_t expiry = timegm(src->recv) + SYNC_MSG_EXPIRE_DELTA;
   5.128 +                    time_t expiry = timegm(src->recv) + SYNC_MSG_EXPIRE_TIME;
   5.129                      time_t now = time(NULL);
   5.130                      if(expiry != 0 && now != 0 && expiry < now){
   5.131                          expired = true;
   5.132 @@ -323,14 +340,12 @@
   5.133                              break;
   5.134                          }
   5.135                          case DeviceGroup_Protocol__payload_PR_groupUpdate:
   5.136 +                        case DeviceGroup_Protocol__payload_PR_updateRequest:
   5.137 +                        {
   5.138                              // inject message but don't consume it, so 
   5.139                              // that other group members can also be updated
   5.140                              force_keep_msg = true;
   5.141                              
   5.142 -                            // no break
   5.143 -
   5.144 -                        case DeviceGroup_Protocol__payload_PR_updateRequest:
   5.145 -                        {
   5.146                              if (!keylist || rating < PEP_rating_reliable){
   5.147                                  discarded = true;
   5.148                                  goto free_all;
     6.1 --- a/test/Makefile	Tue Oct 18 17:36:15 2016 +0200
     6.2 +++ b/test/Makefile	Wed Oct 19 12:48:13 2016 +0200
     6.3 @@ -6,7 +6,7 @@
     6.4  LDFLAGS?=-L$(HOME)/lib
     6.5  LDLIBS?=-letpan -lpEpEngine -lstdc++ -L../asn.1 -lasn1
     6.6  ifeq ($(BUILD_FOR),Linux)
     6.7 -LDLIBS=$(LDLIBS) -luuid
     6.8 +	LDLIBS+= -luuid
     6.9  endif
    6.10  CXXFLAGS?=-std=c++11 -g -O0 -I../src -I../asn.1
    6.11  # CXXFLAGS=-O3 -DNDEBUG
     7.1 --- a/test/trustwords_test.cc	Tue Oct 18 17:36:15 2016 +0200
     7.2 +++ b/test/trustwords_test.cc	Wed Oct 19 12:48:13 2016 +0200
     7.3 @@ -38,6 +38,8 @@
     7.4      size_t wsize2;
     7.5      size_t wsize_full;
     7.6      
     7.7 +    cout << "\nTest 1: fpr1 > fpr2, short" << endl;
     7.8 +    
     7.9      cout << "\nfinding German trustwords for " << fingerprint1 << "...\n";
    7.10      trustwords(session, fingerprint1.c_str(), "de", &words1, &wsize1, 5);
    7.11      assert(words1);
    7.12 @@ -57,10 +59,143 @@
    7.13      pEp_free(words1);
    7.14      pEp_free(words2);
    7.15      pEp_free(full_wordlist);
    7.16 +
    7.17 +    cout << "\nTest 2: fpr1 == fpr1, short" << endl;
    7.18 +    
    7.19 +    cout << "\nfinding French trustwords for " << fingerprint2 << "...\n";
    7.20 +    trustwords(session, fingerprint1.c_str(), "fr", &words1, &wsize1, 5);
    7.21 +    assert(words1);
    7.22 +    cout << words1 << "\n";
    7.23 +        
    7.24 +    cout << "\nfinding French trustwords for " << identity2->address << " and " << identity2->address << "...\n";
    7.25 +    get_trustwords(session, identity2, identity2, "fr", &full_wordlist, &wsize_full, false);
    7.26 +    assert(full_wordlist);
    7.27 +    cout << full_wordlist << "\n";
    7.28 +
    7.29 +    pEp_free(words1);
    7.30 +    pEp_free(full_wordlist);
    7.31 +
    7.32 +    cout << "\nTest 3: fpr1 < fpr2, long" << endl;
    7.33 +    
    7.34 +    cout << "\nfinding English trustwords for " << fingerprint2 << "...\n";
    7.35 +    trustwords(session, fingerprint2.c_str(), "en", &words1, &wsize1, 0);
    7.36 +    assert(words1);
    7.37 +    cout << words1 << "\n";
    7.38 +    
    7.39 +    cout << "\nfinding English trustwords for " << fingerprint1 << "...\n";
    7.40 +    trustwords(session, fingerprint1.c_str(), "en", &words2, &wsize2, 0);
    7.41 +    assert(words2);
    7.42 +    cout << words2 << "\n";
    7.43 +    
    7.44 +    cout << "\nfinding English trustwords for " << identity2->address << " and " << identity2->address << "...\n";
    7.45 +    get_trustwords(session, identity2, identity1, "en", &full_wordlist, &wsize_full, true);
    7.46 +    assert(full_wordlist);
    7.47 +    cout << full_wordlist << "\n";
    7.48 +    
    7.49 +    pEp_free(words1);
    7.50 +    pEp_free(words2);
    7.51 +    pEp_free(full_wordlist);
    7.52 +    
    7.53 +    
    7.54 +    cout << "\nTest 4: fpr1 < fpr2, leading zeros (fpr1 has more), long" << endl;
    7.55 +    
    7.56 +    pEp_identity* identity3 = new_identity(
    7.57 +        "nobody@kgrothoff.org",
    7.58 +        "000F932086185C15917B72D30571AFBCA5493553",
    7.59 +        "blargh",
    7.60 +        "Krista Grothoff");
    7.61 +    
    7.62 +    pEp_identity* identity4 = new_identity(
    7.63 +        "nobody2@kgrothoff.org",
    7.64 +        "001F932086185C15917B72D30571AFBCA5493553",
    7.65 +        "blargh",
    7.66 +        "Krista Grothoff");
    7.67 +    
    7.68 +    pEp_identity* identity5 = new_identity(
    7.69 +        "nobody3@kgrothoff.org",
    7.70 +        "001F732086185C15917B72D30571AFBCA5493553",
    7.71 +        "blargh",
    7.72 +        "Krista Grothoff");
    7.73 +
    7.74 +    string fingerprint3 = identity3->fpr;
    7.75 +    string fingerprint4 = identity4->fpr;
    7.76 +    string fingerprint5 = identity5->fpr; 
    7.77 +        
    7.78 +    cout << "\nfinding Catalan trustwords for " << fingerprint3 << "...\n";
    7.79 +    trustwords(session, fingerprint3.c_str(), "ca", &words1, &wsize1, 0);
    7.80 +    assert(words1);
    7.81 +    cout << words1 << "\n";
    7.82 +    
    7.83 +    cout << "\nfinding Catalan trustwords for " << fingerprint4 << "...\n";
    7.84 +    trustwords(session, fingerprint4.c_str(), "ca", &words2, &wsize2, 0);
    7.85 +    assert(words2);
    7.86 +    cout << words2 << "\n";
    7.87 +    
    7.88 +    cout << "\nfinding Catalan trustwords for " << identity3->address << " and " << identity4->address << "...\n";
    7.89 +    get_trustwords(session, identity3, identity4, "ca", &full_wordlist, &wsize_full, true);
    7.90 +    assert(full_wordlist);
    7.91 +    cout << full_wordlist << "\n";
    7.92 +
    7.93 +    pEp_free(words1);
    7.94 +    pEp_free(words2);
    7.95 +    pEp_free(full_wordlist);
    7.96 +
    7.97 +    cout << "\nTest 5: fpr1 > fpr2, leading zeros (same number), interior digit difference, short" << endl;
    7.98 +    
    7.99 +    cout << "\nfinding Turkish trustwords for " << fingerprint4 << "...\n";
   7.100 +    trustwords(session, fingerprint4.c_str(), "tr", &words1, &wsize1, 5);
   7.101 +    assert(words1);
   7.102 +    cout << words1 << "\n";
   7.103 +    
   7.104 +    cout << "\nfinding Turkish trustwords for " << fingerprint5 << "...\n";
   7.105 +    trustwords(session, fingerprint5.c_str(), "tr", &words2, &wsize2, 5);
   7.106 +    assert(words2);
   7.107 +    cout << words2 << "\n";
   7.108 +    
   7.109 +    cout << "\nfinding Turkish trustwords for " << identity4->address << " and " << identity5->address << "...\n";
   7.110 +    get_trustwords(session, identity4, identity5, "tr", &full_wordlist, &wsize_full, false);
   7.111 +    assert(full_wordlist);
   7.112 +    cout << full_wordlist << "\n";
   7.113 +    
   7.114 +    pEp_free(words1);
   7.115 +    pEp_free(words2);
   7.116 +    pEp_free(full_wordlist);
   7.117 +
   7.118 +    cout << "\nTest 6: fpr2 is too short" << endl;
   7.119 +    
   7.120 +    pEp_identity* identity6 = new_identity(
   7.121 +        "nobody4@kgrothoff.org",
   7.122 +        "01F932086185C15917B72D30571AFBCA5493553",
   7.123 +        "blargh",
   7.124 +        "Krista Grothoff");
   7.125 +    
   7.126 +    cout << "\nfinding Turkish trustwords for " << identity5->address << " and " << identity6->address << "...\n";
   7.127 +    PEP_STATUS status6 = get_trustwords(session, identity5, identity6, "tr", &full_wordlist, &wsize_full, false);
   7.128 +    assert(status6 == PEP_TRUSTWORDS_FPR_WRONG_LENGTH);
   7.129 +    cout << "Bad fpr length correctly recognised." << "\n";
   7.130 +    
   7.131 +    pEp_identity* identity7 = new_identity(
   7.132 +        "nobody5@kgrothoff.org",
   7.133 +        "F01X932086185C15917B72D30571AFBCA5493553",
   7.134 +        "blargh",
   7.135 +        "Krista Grothoff");
   7.136 +
   7.137 +    cout << "\nTest 7: fpr2 has a non-hex character" << endl;
   7.138 +    
   7.139 +    cout << "\nfinding Turkish trustwords for " << identity1->address << " and " << identity7->address << "...\n";
   7.140 +    PEP_STATUS status7 = get_trustwords(session, identity1, identity7, "tr", &full_wordlist, &wsize_full, true);
   7.141 +    assert(status7 == PEP_ILLEGAL_VALUE);
   7.142 +    cout << "Illegal digit value correctly recognised." << "\n";
   7.143      
   7.144      
   7.145      free(identity1);
   7.146      free(identity2);
   7.147 +    free(identity3);
   7.148 +    free(identity4);
   7.149 +    free(identity5);
   7.150 +    free(identity6);
   7.151 +    free(identity7);
   7.152 +    
   7.153      cout << "calling release()\n";
   7.154      release(session);
   7.155      return 0;