Merging in default after 200 years ENGINE-9
authorKrista Bennett <krista@pep-project.org>
Tue, 06 Jun 2017 18:00:40 +0200
branchENGINE-9
changeset 1828a82418b6553b
parent 1714 a6712af7a964
parent 1824 def83c456552
child 1829 909cb53fc069
Merging in default after 200 years
src/message_api.c
src/sync_impl.c
     1.1 --- a/Makefile.conf	Mon Mar 27 14:53:29 2017 +0200
     1.2 +++ b/Makefile.conf	Tue Jun 06 18:00:40 2017 +0200
     1.3 @@ -2,7 +2,7 @@
     1.4  
     1.5  BUILD_ON=$(shell uname)
     1.6  BUILD_FOR=$(BUILD_ON)
     1.7 -OPTIMIZE=-g -Wall -O0 -fPIC
     1.8 +OPTIMIZE=-g -Wall -O0 -fPIC -DDEBUG_ERRORSTACK
     1.9  #OPTIMIZE=-O3 -Wall -DNDEBUG -std=c99
    1.10  LD=$(CC)
    1.11  #CC=gcc-mp-4.9 -std=c99 -fstrict-aliasing -Wstrict-aliasing=3
    1.12 @@ -10,10 +10,11 @@
    1.13  SYSTEM_DB=/usr/local/share/pEp/system.db
    1.14  PREFIX=$(HOME)
    1.15  YML2PROC=$(HOME)/yml2/yml2proc
    1.16 +YML_OPTS=--encoding=utf8
    1.17  YML_PATH=$(HOME)/yml2
    1.18  ASN1C=asn1c
    1.19  ASN1C_INCLUDE=/opt/local/share/asn1c
    1.20 -#LIBGPGME=/opt/local/lib/libgpgme-pthread.11.dylib
    1.21 +#LIBGPGME=/opt/local/lib/libgpgme.11.dylib
    1.22  
    1.23  # C makros (not environment variables) to overwrite:
    1.24  #
     2.1 --- a/README-OSX.md	Mon Mar 27 14:53:29 2017 +0200
     2.2 +++ b/README-OSX.md	Tue Jun 06 18:00:40 2017 +0200
     2.3 @@ -23,7 +23,7 @@
     2.4  Install dependencies packaged with MacPorts as follows.
     2.5  
     2.6  ```
     2.7 -sudo port install mercurial py27-lxml gpgme automake asn1c zlib openssl libiconv cyrus-sasl2
     2.8 +sudo port install mercurial py27-lxml gpgme autoconf automake libtool asn1c zlib openssl libiconv cyrus-sasl2
     2.9  ```
    2.10  
    2.11  Make sure that `python` is a version 2 one:
    2.12 @@ -124,6 +124,7 @@
    2.13  If you installed the test keys in your keyring (see: README.txt), this should just work:
    2.14  
    2.15  ```
    2.16 +cd test
    2.17  make test
    2.18  ```
    2.19  
     3.1 --- a/README.txt	Mon Mar 27 14:53:29 2017 +0200
     3.2 +++ b/README.txt	Tue Jun 06 18:00:40 2017 +0200
     3.3 @@ -56,7 +56,7 @@
     3.4  
     3.5  * Cyrus SASL, see http://cyrusimap.org/
     3.6  
     3.7 -* GnuPG via GPGME, see https://gnupg.org/
     3.8 +* GnuPG via GPGME, version 1.6.0 or newer, see https://gnupg.org/
     3.9  
    3.10  * NetPGP/p≡p, see https://cacert.pep.foundation/dev/repos/netpgp-et/
    3.11  
     4.1 --- a/build-mac/pEpEngine.xcodeproj/project.pbxproj	Mon Mar 27 14:53:29 2017 +0200
     4.2 +++ b/build-mac/pEpEngine.xcodeproj/project.pbxproj	Tue Jun 06 18:00:40 2017 +0200
     4.3 @@ -190,6 +190,7 @@
     4.4  
     4.5  /* Begin PBXFileReference section */
     4.6  		430D258A1C9ED75A00B94535 /* blacklist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = blacklist.c; path = ../src/blacklist.c; sourceTree = "<group>"; };
     4.7 +		4346F86A1ECB38E700381CBE /* sync_app.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sync_app.h; path = ../src/sync_app.h; sourceTree = "<group>"; };
     4.8  		4354FF641D6EDF300033069C /* sync_impl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_impl.c; path = ../src/sync_impl.c; sourceTree = "<group>"; };
     4.9  		4354FF681D6EE1A70033069C /* NULL.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NULL.c; path = ../asn.1/NULL.c; sourceTree = "<group>"; };
    4.10  		43BA0F451D7964750059172F /* asn1_helper.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = asn1_helper.c; path = ../src/asn1_helper.c; sourceTree = "<group>"; };
    4.11 @@ -292,7 +293,7 @@
    4.12  		646C414C1D510D8800C63EFF /* baseprotocol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = baseprotocol.c; path = ../src/baseprotocol.c; sourceTree = "<group>"; };
    4.13  		646C414D1D510D8800C63EFF /* baseprotocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = baseprotocol.h; path = ../src/baseprotocol.h; sourceTree = "<group>"; };
    4.14  		64796A3F1B455AA5004B1C24 /* libpEpEngine.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpEpEngine.a; sourceTree = BUILT_PRODUCTS_DIR; };
    4.15 -		64951A1B1BE0FCD800B10E71 /* system.db */ = {isa = PBXFileReference; lastKnownFileType = file; name = system.db; path = ../db/system.db; sourceTree = "<group>"; };
    4.16 +		64951A1B1BE0FCD800B10E71 /* system.db */ = {isa = PBXFileReference; lastKnownFileType = text; name = system.db; path = ../db/system.db; sourceTree = "<group>"; };
    4.17  		649DE08A1B45C19100912F72 /* libcurl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libcurl.a; sourceTree = "<group>"; };
    4.18  		64A8264C1B455D0800EECAF0 /* bloblist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bloblist.c; path = ../src/bloblist.c; sourceTree = "<group>"; };
    4.19  		64A8264D1B455D0800EECAF0 /* bloblist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bloblist.h; path = ../src/bloblist.h; sourceTree = "<group>"; };
    4.20 @@ -517,6 +518,7 @@
    4.21  				646C41421D510D2C00C63EFF /* sync_send_actions.c */,
    4.22  				646C41431D510D2C00C63EFF /* sync.c */,
    4.23  				646C41441D510D2C00C63EFF /* sync.h */,
    4.24 +				4346F86A1ECB38E700381CBE /* sync_app.h */,
    4.25  				646788871CEB3D120001F54C /* map_asn1.c */,
    4.26  				646788881CEB3D120001F54C /* map_asn1.h */,
    4.27  				430D258A1C9ED75A00B94535 /* blacklist.c */,
    4.28 @@ -779,7 +781,7 @@
    4.29  			);
    4.30  			runOnlyForDeploymentPostprocessing = 0;
    4.31  			shellPath = /bin/sh;
    4.32 -			shellScript = "mkdir -p \"$BUILT_PRODUCTS_DIR/include\"\n\ncp \"$SRCROOT/../src/\"{\\\npEpEngine.h,\\\ncryptotech.h,\\\nkeymanagement.h,\\\nmessage_api.h,\\\ndynamic_api.h,\\\nstringlist.h,\\\ntimestamp.h,\\\nidentity_list.h,\\\nbloblist.h,\\\nstringpair.h,\\\nmessage.h,\\\nmime.h} \"$BUILT_PRODUCTS_DIR/include\"\n\nbash -l -c \"make -C ../asn.1 generate\"\nbash -l -c \"make -C ../asn.1\"\nbash -l -c \"LC_ALL=en_US.UTF-8 YML_PATH=$HOME/yml2 make -C ../sync\"\n";
    4.33 +			shellScript = "mkdir -p \"$BUILT_PRODUCTS_DIR/include\"\n\ncp \"$SRCROOT/../src/\"{\\\npEpEngine.h,\\\ncryptotech.h,\\\nkeymanagement.h,\\\nmessage_api.h,\\\ndynamic_api.h,\\\nstringlist.h,\\\ntimestamp.h,\\\nidentity_list.h,\\\nbloblist.h,\\\nstringpair.h,\\\nmessage.h,\\\nmime.h,\\\nsync_fsm.h,\\\nsync.h,\\\nsync_app.h} \"$BUILT_PRODUCTS_DIR/include\"\n\nbash -l -c \"make -C ../asn.1 generate\"\nbash -l -c \"make -C ../asn.1\"\nbash -l -c \"LC_ALL=en_US.UTF-8 YML_PATH=$HOME/yml2 make -C ../sync\"\n";
    4.34  		};
    4.35  /* End PBXShellScriptBuildPhase section */
    4.36  
    4.37 @@ -947,7 +949,7 @@
    4.38  					"$(SRCROOT)",
    4.39  					"$(SRCROOT)/../../netpgp-et/include/",
    4.40  					"$(SRCROOT)/../../netpgp-et/src/",
    4.41 -					"$(SRCROOT)/../../netpgp-et/netpgp-xcode/openssl/include/",
    4.42 +					"$(SRCROOT)/../../OpenSSL-for-iPhone/include",
    4.43  					"$(SRCROOT)/../asn.1/",
    4.44  				);
    4.45  				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
    4.46 @@ -994,7 +996,7 @@
    4.47  					"$(SRCROOT)",
    4.48  					"$(SRCROOT)/../../netpgp-et/include/",
    4.49  					"$(SRCROOT)/../../netpgp-et/src/",
    4.50 -					"$(SRCROOT)/../../netpgp-et/netpgp-xcode/openssl/include/",
    4.51 +					"$(SRCROOT)/../../OpenSSL-for-iPhone/include",
    4.52  					"$(SRCROOT)/../asn.1/",
    4.53  				);
    4.54  				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
     5.1 --- a/db/create_system_db.sql	Mon Mar 27 14:53:29 2017 +0200
     5.2 +++ b/db/create_system_db.sql	Tue Jun 06 18:00:40 2017 +0200
     5.3 @@ -46,5 +46,8 @@
     5.4  
     5.5  INSERT INTO i18n_language VALUES ('tr', 'Türkçe');
     5.6  INSERT INTO i18n_token VALUES ('tr', 1000, 'Güvenlik kelimelerini Türkçe görüntülemek istiyorum');
     5.7 +
     5.8 +INSERT INTO i18n_language VALUES ('nl', 'Nederlands');
     5.9 +INSERT INTO i18n_token VALUES ('nl', 1000, 'Ik wil de trustwords in de nederlandse taal laten zien');
    5.10  -- add more languages here
    5.11  
     6.1 --- a/src/Makefile	Mon Mar 27 14:53:29 2017 +0200
     6.2 +++ b/src/Makefile	Tue Jun 06 18:00:40 2017 +0200
     6.3 @@ -93,7 +93,7 @@
     6.4  install: $(TARGET)
     6.5  	cp $< $(PREFIX)/lib/
     6.6  	mkdir -p $(PREFIX)/include/pEp
     6.7 -	cp pEpEngine.h keymanagement.h message_api.h dynamic_api.h stringlist.h timestamp.h identity_list.h bloblist.h stringpair.h message.h mime.h cryptotech.h sync.h sync_fsm.h blacklist.h openpgp_compat.h $(PREFIX)/include/pEp/
     6.8 +	cp pEpEngine.h keymanagement.h message_api.h dynamic_api.h stringlist.h timestamp.h identity_list.h bloblist.h stringpair.h message.h mime.h cryptotech.h sync.h sync_fsm.h sync_app.h blacklist.h openpgp_compat.h $(PREFIX)/include/pEp/
     6.9  
    6.10  uninstall:
    6.11  	rm -f $(PREFIX)/lib/$(TARGET)
     7.1 --- a/src/keymanagement.c	Mon Mar 27 14:53:29 2017 +0200
     7.2 +++ b/src/keymanagement.c	Tue Jun 06 18:00:40 2017 +0200
     7.3 @@ -91,7 +91,7 @@
     7.4      assert(!EMPTYSTR(identity->address));
     7.5  
     7.6      if (!(session && identity && !EMPTYSTR(identity->address)))
     7.7 -        return PEP_ILLEGAL_VALUE;
     7.8 +        return ERROR(PEP_ILLEGAL_VALUE);
     7.9  
    7.10      if (identity->me || (identity->user_id && strcmp(identity->user_id, PEP_OWN_USERID) == 0)) {
    7.11          identity->me = true;
    7.12 @@ -144,9 +144,23 @@
    7.13  
    7.14          /* if we have a stored_identity fpr */
    7.15          if (!EMPTYSTR(stored_identity->fpr)) {
    7.16 -            status = blacklist_is_listed(session, stored_identity->fpr, &dont_use_stored_fpr);
    7.17 -            if (status != PEP_STATUS_OK)
    7.18 -                dont_use_stored_fpr = true; 
    7.19 +            bool revoked = false;
    7.20 +            status = key_revoked(session, stored_identity->fpr, &revoked);
    7.21 +            
    7.22 +            if (status != PEP_STATUS_OK || revoked)
    7.23 +                dont_use_stored_fpr = true;
    7.24 +                
    7.25 +            if (revoked) {
    7.26 +                // Do stuff
    7.27 +                status = update_trust_for_fpr(session, stored_identity->fpr, PEP_ct_key_revoked);
    7.28 +                // What to do on failure? FIXME
    7.29 +                status = replace_identities_fpr(session, stored_identity->fpr, "");
    7.30 +            }
    7.31 +            else {    
    7.32 +                status = blacklist_is_listed(session, stored_identity->fpr, &dont_use_stored_fpr);
    7.33 +                if (status != PEP_STATUS_OK)
    7.34 +                    dont_use_stored_fpr = true; 
    7.35 +            }
    7.36          }
    7.37              
    7.38  
    7.39 @@ -179,10 +193,11 @@
    7.40                         downgrade eventually trusted comm_type */
    7.41                      temp_id->comm_type = _comm_type_key;
    7.42                  } else {
    7.43 -                    /* otherwise take stored comm_type as-is */
    7.44 +                    /* otherwise take stored comm_type as-is except if 
    7.45 +                       is unknown or is expired (but key not expired anymore) */
    7.46                      temp_id->comm_type = stored_identity->comm_type;
    7.47 -                    if (temp_id->comm_type == PEP_ct_unknown) {
    7.48 -                        /* except if unknown */
    7.49 +                    if (temp_id->comm_type == PEP_ct_unknown ||
    7.50 +                        temp_id->comm_type == PEP_ct_key_expired) {
    7.51                          temp_id->comm_type = _comm_type_key;
    7.52                      }
    7.53                  }
    7.54 @@ -311,7 +326,7 @@
    7.55      free_identity(stored_identity);
    7.56      free_identity(temp_id);
    7.57      
    7.58 -    return status;
    7.59 +    return ERROR(status);
    7.60  }
    7.61  
    7.62  PEP_STATUS elect_ownkey(
    7.63 @@ -338,19 +353,14 @@
    7.64          for (_keylist = keylist; _keylist && _keylist->value; _keylist = _keylist->next) {
    7.65              bool is_own = false;
    7.66              
    7.67 -            if (session->use_only_own_private_keys)
    7.68 -            {
    7.69 -                status = own_key_is_listed(session, _keylist->value, &is_own);
    7.70 -                assert(status == PEP_STATUS_OK);
    7.71 -                if (status != PEP_STATUS_OK) {
    7.72 -                    free_stringlist(keylist);
    7.73 -                    return status;
    7.74 -                }
    7.75 +            status = own_key_is_listed(session, _keylist->value, &is_own);
    7.76 +            assert(status == PEP_STATUS_OK);
    7.77 +            if (status != PEP_STATUS_OK) {
    7.78 +                free_stringlist(keylist);
    7.79 +                return status;
    7.80              }
    7.81 -
    7.82 -            // TODO : also accept synchronized device group keys ?
    7.83              
    7.84 -            if (!session->use_only_own_private_keys || is_own)
    7.85 +            if (is_own)
    7.86              {
    7.87                  PEP_comm_type _comm_type_key;
    7.88                  
    7.89 @@ -406,7 +416,7 @@
    7.90      
    7.91      *is_usable = !dont_use_fpr;
    7.92      
    7.93 -    return status;
    7.94 +    return ERROR(status);
    7.95  }
    7.96  
    7.97  PEP_STATUS _myself(PEP_SESSION session, pEp_identity * identity, bool do_keygen, bool ignore_flags)
    7.98 @@ -424,7 +434,7 @@
    7.99      if (!(session && identity && !EMPTYSTR(identity->address) &&
   7.100              (EMPTYSTR(identity->user_id) ||
   7.101              strcmp(identity->user_id, PEP_OWN_USERID) == 0)))
   7.102 -        return PEP_ILLEGAL_VALUE;
   7.103 +        return ERROR(PEP_ILLEGAL_VALUE);
   7.104  
   7.105      identity->comm_type = PEP_ct_pEp;
   7.106      identity->me = true;
   7.107 @@ -512,7 +522,7 @@
   7.108          status = elect_ownkey(session, identity);
   7.109          assert(status == PEP_STATUS_OK);
   7.110          if (status != PEP_STATUS_OK) {
   7.111 -            return status;
   7.112 +            return ERROR(status);
   7.113          }
   7.114  
   7.115          bool has_private = false;
   7.116 @@ -542,27 +552,18 @@
   7.117      {
   7.118          status = key_revoked(session, identity->fpr, &revoked);
   7.119  
   7.120 -        // Forces re-election if key is missing and own-key-only not forced
   7.121 -        if (!session->use_only_own_private_keys && status == PEP_KEY_NOT_FOUND) 
   7.122 +        if (status != PEP_STATUS_OK) 
   7.123          {
   7.124 -            status = elect_ownkey(session, identity);
   7.125 -            assert(status == PEP_STATUS_OK);
   7.126 -            if (status != PEP_STATUS_OK) {
   7.127 -                return status;
   7.128 -            }
   7.129 -        } 
   7.130 -        else if (status != PEP_STATUS_OK) 
   7.131 -        {
   7.132 -            return status;
   7.133 +            return ERROR(status);
   7.134          }
   7.135      }
   7.136     
   7.137      bool new_key_generated = false;
   7.138  
   7.139      if (EMPTYSTR(identity->fpr) || revoked)
   7.140 -    {        
   7.141 +    {
   7.142          if(!do_keygen){
   7.143 -            return PEP_GET_KEY_FAILED;
   7.144 +            return ERROR(PEP_GET_KEY_FAILED);
   7.145          }
   7.146  
   7.147          if(revoked)
   7.148 @@ -580,7 +581,7 @@
   7.149              DEBUG_LOG("generating key pair failed", "debug", buf);
   7.150              if(revoked && r_fpr)
   7.151                  free(r_fpr);
   7.152 -            return status;
   7.153 +            return ERROR(status);
   7.154          }
   7.155  
   7.156          new_key_generated = true;
   7.157 @@ -591,7 +592,7 @@
   7.158                                   identity->fpr, time(NULL));
   7.159              free(r_fpr);
   7.160              if (status != PEP_STATUS_OK) {
   7.161 -                return status;
   7.162 +                return ERROR(status);
   7.163              }
   7.164          }
   7.165      }
   7.166 @@ -604,7 +605,7 @@
   7.167  
   7.168          assert(status == PEP_STATUS_OK);
   7.169          if (status != PEP_STATUS_OK) {
   7.170 -            return status;
   7.171 +            return ERROR(status);
   7.172          }
   7.173  
   7.174          if (status == PEP_STATUS_OK && expired) {
   7.175 @@ -632,12 +633,12 @@
   7.176          }
   7.177      }
   7.178  
   7.179 -    return PEP_STATUS_OK;
   7.180 +    return ERROR(PEP_STATUS_OK);
   7.181  }
   7.182  
   7.183  DYNAMIC_API PEP_STATUS myself(PEP_SESSION session, pEp_identity * identity)
   7.184  {
   7.185 -    return _myself(session, identity, true, false);
   7.186 +    return ERROR(_myself(session, identity, true, false));
   7.187  }
   7.188  
   7.189  DYNAMIC_API PEP_STATUS register_examine_function(
   7.190 @@ -1009,7 +1010,7 @@
   7.191      return _own_keys_retrieve(session, keylist, 0);
   7.192  }
   7.193  
   7.194 -// TODO: Unused for now, but should be used when sync receive old keys (ENGINE-145)
   7.195 +// FIXME: should it be be used when sync receive old keys ? (ENGINE-145)
   7.196  DYNAMIC_API PEP_STATUS set_own_key(
   7.197         PEP_SESSION session,
   7.198         const char *address,
   7.199 @@ -1019,12 +1020,12 @@
   7.200      PEP_STATUS status = PEP_STATUS_OK;
   7.201      
   7.202      assert(session &&
   7.203 -           address && address[0] &&
   7.204 +           address &&
   7.205             fpr && fpr[0]
   7.206            );
   7.207      
   7.208      if (!(session &&
   7.209 -          address && address[0] &&
   7.210 +          address &&
   7.211            fpr && fpr[0]
   7.212           ))
   7.213          return PEP_ILLEGAL_VALUE;
     8.1 --- a/src/keymanagement.h	Mon Mar 27 14:53:29 2017 +0200
     8.2 +++ b/src/keymanagement.h	Tue Jun 06 18:00:40 2017 +0200
     8.3 @@ -159,7 +159,6 @@
     8.4          pEp_identity *ident
     8.5      );
     8.6  
     8.7 -
     8.8  // own_key_is_listed() - returns true id key is listed as own key
     8.9  //
    8.10  //  parameters:
    8.11 @@ -235,7 +234,12 @@
    8.12          stringlist_t **keylist
    8.13        );
    8.14  
    8.15 +DYNAMIC_API PEP_STATUS set_own_key(
    8.16 +       PEP_SESSION session,
    8.17 +       const char *address,
    8.18 +       const char *fpr
    8.19 +    );
    8.20 +
    8.21  #ifdef __cplusplus
    8.22  }
    8.23  #endif
    8.24 -
     9.1 --- a/src/message_api.c	Mon Mar 27 14:53:29 2017 +0200
     9.2 +++ b/src/message_api.c	Tue Jun 06 18:00:40 2017 +0200
     9.3 @@ -796,6 +796,7 @@
     9.4          return PEP_rating_unencrypted;
     9.5  
     9.6      case PEP_DECRYPTED:
     9.7 +    case PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH:
     9.8          return PEP_rating_unreliable;
     9.9  
    9.10      case PEP_DECRYPTED_AND_VERIFIED:
    9.11 @@ -1102,20 +1103,20 @@
    9.12      assert(enc_format != PEP_enc_none);
    9.13  
    9.14      if (!(session && src && dst && enc_format != PEP_enc_none))
    9.15 -        return PEP_ILLEGAL_VALUE;
    9.16 +        return ERROR(PEP_ILLEGAL_VALUE);
    9.17  
    9.18      if (src->dir == PEP_dir_incoming)
    9.19 -        return PEP_ILLEGAL_VALUE;
    9.20 +        return ERROR(PEP_ILLEGAL_VALUE);
    9.21  
    9.22      determine_encryption_format(src);
    9.23      if (src->enc_format != PEP_enc_none)
    9.24 -        return PEP_ILLEGAL_VALUE;
    9.25 +        return ERROR(PEP_ILLEGAL_VALUE);
    9.26  
    9.27      *dst = NULL;
    9.28  
    9.29      status = myself(session, src->from);
    9.30      if (status != PEP_STATUS_OK)
    9.31 -        goto pep_error;
    9.32 +        GOTO(pep_error);
    9.33  
    9.34      keys = new_stringlist(src->from->fpr);
    9.35      if (keys == NULL)
    9.36 @@ -1149,7 +1150,7 @@
    9.37          PEP_STATUS _status = update_identity(session, _il->ident);
    9.38          if (_status != PEP_STATUS_OK) {
    9.39              status = _status;
    9.40 -            goto pep_error;
    9.41 +            GOTO(pep_error);
    9.42          }
    9.43  
    9.44          if (_il->ident->fpr && _il->ident->fpr[0]) {
    9.45 @@ -1170,7 +1171,7 @@
    9.46              PEP_STATUS _status = update_identity(session, _il->ident);
    9.47              if (_status != PEP_STATUS_OK) {
    9.48                  status = _status;
    9.49 -                goto pep_error;
    9.50 +                GOTO(pep_error);
    9.51              }
    9.52  
    9.53              if (_il->ident->fpr && _il->ident->fpr[0]) {
    9.54 @@ -1191,7 +1192,7 @@
    9.55              if (_status != PEP_STATUS_OK)
    9.56              {
    9.57                  status = _status;
    9.58 -                goto pep_error;
    9.59 +                GOTO(pep_error);
    9.60              }
    9.61  
    9.62              if (_il->ident->fpr && _il->ident->fpr[0]) {
    9.63 @@ -1216,7 +1217,7 @@
    9.64          free_stringlist(keys);
    9.65          if (!session->passive_mode && !(flags & PEP_encrypt_flag_force_no_attached_key))
    9.66              attach_own_key(session, src);
    9.67 -        return PEP_UNENCRYPTED;
    9.68 +        return ERROR(PEP_UNENCRYPTED);
    9.69      }
    9.70      else {
    9.71          msg = clone_to_empty_message(src);
    9.72 @@ -1243,14 +1244,14 @@
    9.73          default:
    9.74              assert(0);
    9.75              status = PEP_ILLEGAL_VALUE;
    9.76 -            goto pep_error;
    9.77 +            GOTO(pep_error);
    9.78          }
    9.79  
    9.80          if (status == PEP_OUT_OF_MEMORY)
    9.81              goto enomem;
    9.82  
    9.83          if (status != PEP_STATUS_OK)
    9.84 -            goto pep_error;
    9.85 +            GOTO(pep_error);
    9.86      }
    9.87  
    9.88      free_stringlist(keys);
    9.89 @@ -1273,7 +1274,7 @@
    9.90      }
    9.91  
    9.92      *dst = msg;
    9.93 -    return status;
    9.94 +    return ERROR(status);
    9.95  
    9.96  enomem:
    9.97      status = PEP_OUT_OF_MEMORY;
    9.98 @@ -1282,7 +1283,7 @@
    9.99      free_stringlist(keys);
   9.100      free_message(msg);
   9.101  
   9.102 -    return status;
   9.103 +    return ERROR(status);
   9.104  }
   9.105  
   9.106  DYNAMIC_API PEP_STATUS encrypt_message_for_self(
   9.107 @@ -1304,18 +1305,18 @@
   9.108      assert(enc_format != PEP_enc_none);
   9.109  
   9.110      if (!(session && src && dst && enc_format != PEP_enc_none))
   9.111 -        return PEP_ILLEGAL_VALUE;
   9.112 +        return ERROR(PEP_ILLEGAL_VALUE);
   9.113  
   9.114      if (src->dir == PEP_dir_incoming)
   9.115 -        return PEP_ILLEGAL_VALUE;
   9.116 +        return ERROR(PEP_ILLEGAL_VALUE);
   9.117  
   9.118      determine_encryption_format(src);
   9.119      if (src->enc_format != PEP_enc_none)
   9.120 -        return PEP_ILLEGAL_VALUE;
   9.121 +        return ERROR(PEP_ILLEGAL_VALUE);
   9.122  
   9.123      status = myself(session, target_id);
   9.124      if (status != PEP_STATUS_OK)
   9.125 -        goto pep_error;
   9.126 +        GOTO(pep_error);
   9.127  
   9.128      *dst = NULL;
   9.129  
   9.130 @@ -1392,7 +1393,7 @@
   9.131      free_stringlist(keys);
   9.132      free_message(msg);
   9.133  
   9.134 -    return status;
   9.135 +    return ERROR(status);
   9.136  }
   9.137  
   9.138  static bool is_a_pEpmessage(const message *msg)
   9.139 @@ -1421,7 +1422,7 @@
   9.140                  && src->from->comm_type != PEP_ct_pEp)
   9.141          {
   9.142              src->from->comm_type |= PEP_ct_pEp_unconfirmed;
   9.143 -            status = update_identity(session, src->from);
   9.144 +            status = set_identity(session, src->from);
   9.145          }
   9.146          return status;
   9.147      }
   9.148 @@ -1459,8 +1460,8 @@
   9.149  
   9.150      char* curr_line = signpost;
   9.151  //    const char* end_text = ptext + psize;
   9.152 -    const char* boundary_key = "boundary=\"";
   9.153 -    const size_t BOUNDARY_KEY_SIZE = 10;
   9.154 +    const char* boundary_key = "boundary=";
   9.155 +    const size_t BOUNDARY_KEY_SIZE = 9;
   9.156  
   9.157      char* start_boundary = strstr(curr_line, boundary_key);
   9.158      if (!start_boundary)
   9.159 @@ -1468,11 +1469,17 @@
   9.160  
   9.161      start_boundary += BOUNDARY_KEY_SIZE;
   9.162  
   9.163 -    char* end_boundary = strstr(start_boundary, "\"");
   9.164 +    bool quoted = (*start_boundary == '"');
   9.165 +
   9.166 +    if (quoted)
   9.167 +        start_boundary++;
   9.168 +        
   9.169 +    char* end_boundary = (quoted ? strstr(start_boundary, "\"") : strstr(start_boundary, ";")); // FIXME: third possiblity is CRLF, or?
   9.170  
   9.171      if (!end_boundary)
   9.172          return PEP_UNKNOWN_ERROR;
   9.173  
   9.174 +    // Add space for the "--"
   9.175      size_t boundary_strlen = (end_boundary - start_boundary) + 2;
   9.176  
   9.177      signed_boundary = calloc(1, boundary_strlen + 1);
   9.178 @@ -1486,7 +1493,11 @@
   9.179  
   9.180      start_boundary += boundary_strlen;
   9.181  
   9.182 -    while (*start_boundary == '\n')
   9.183 +    if (*start_boundary == '\r') {
   9.184 +        if (*(start_boundary + 1) == '\n')
   9.185 +            start_boundary += 2;
   9.186 +    }
   9.187 +    else if (*start_boundary == '\n')
   9.188          start_boundary++;
   9.189  
   9.190      end_boundary = strstr(start_boundary + boundary_strlen, signed_boundary);
   9.191 @@ -1494,7 +1505,10 @@
   9.192      if (!end_boundary)
   9.193          return PEP_UNKNOWN_ERROR;
   9.194  
   9.195 -    end_boundary--; // See RFC3156 section 5...
   9.196 +    // See RFC3156 section 5...
   9.197 +    end_boundary--; 
   9.198 +    if (*(end_boundary - 1) == '\r')
   9.199 +        end_boundary--; 
   9.200  
   9.201      *ssize = end_boundary - start_boundary;
   9.202      *stext = start_boundary;
   9.203 @@ -1608,7 +1622,7 @@
   9.204      assert(flags);
   9.205  
   9.206      if (!(session && src && dst && keylist && rating && flags))
   9.207 -        return PEP_ILLEGAL_VALUE;
   9.208 +        return ERROR(PEP_ILLEGAL_VALUE);
   9.209  
   9.210      *flags = 0;
   9.211  
   9.212 @@ -1619,7 +1633,7 @@
   9.213      // we would need to check signature
   9.214      status = _update_identity_for_incoming_message(session, src);
   9.215      if(status != PEP_STATUS_OK)
   9.216 -        return status;
   9.217 +        return ERROR(status);
   9.218  
   9.219      // Get detached signature, if any
   9.220      bloblist_t* detached_sig = NULL;
   9.221 @@ -1653,7 +1667,7 @@
   9.222                                  PEP_decrypt_flag_consume;
   9.223                  }
   9.224                  else if (status != PEP_STATUS_OK) {
   9.225 -                    return status;
   9.226 +                    return ERROR(status);
   9.227                  }
   9.228              }
   9.229              
   9.230 @@ -1685,7 +1699,7 @@
   9.231                  }
   9.232              }
   9.233              
   9.234 -            return PEP_UNENCRYPTED;
   9.235 +            return ERROR(PEP_UNENCRYPTED);
   9.236  
   9.237          case PEP_enc_PGP_MIME:
   9.238              ctext = src->attachments->next->value;
   9.239 @@ -1709,7 +1723,7 @@
   9.240                                                     csize, dsig_text, dsig_size,
   9.241                                                     &ptext, &psize, &_keylist);
   9.242      if (status > PEP_CANNOT_DECRYPT_UNKNOWN){
   9.243 -        goto pep_error;
   9.244 +        GOTO(pep_error);
   9.245      }
   9.246  
   9.247      decrypt_status = status;
   9.248 @@ -1888,7 +1902,9 @@
   9.249              case PEP_enc_PGP_MIME_Outlook1:
   9.250                  status = copy_fields(msg, src);
   9.251                  if (status != PEP_STATUS_OK)
   9.252 -                    goto pep_error;
   9.253 +                {
   9.254 +                    GOTO(pep_error);
   9.255 +                }
   9.256  
   9.257                  if (src->shortmsg == NULL || strcmp(src->shortmsg, "pEp") == 0)
   9.258                  {
   9.259 @@ -1946,7 +1962,9 @@
   9.260  
   9.261              status = _update_identity_for_incoming_message(session, src);
   9.262              if(status != PEP_STATUS_OK)
   9.263 -                goto pep_error;
   9.264 +            {
   9.265 +                GOTO(pep_error);
   9.266 +            }
   9.267  
   9.268              char *re_ptext = NULL;
   9.269              size_t re_psize;
   9.270 @@ -1960,7 +1978,9 @@
   9.271              free(re_ptext);
   9.272  
   9.273              if (status > PEP_CANNOT_DECRYPT_UNKNOWN)
   9.274 -                goto pep_error;
   9.275 +            {
   9.276 +                GOTO(pep_error);
   9.277 +            }
   9.278  
   9.279              decrypt_status = status;
   9.280          }
   9.281 @@ -2000,7 +2020,9 @@
   9.282                      if (status == PEP_CANNOT_FIND_IDENTITY)
   9.283                         status = PEP_STATUS_OK;
   9.284                      if (status != PEP_STATUS_OK)
   9.285 -                        goto pep_error;
   9.286 +                    {
   9.287 +                        GOTO(pep_error);
   9.288 +                    }
   9.289                  }
   9.290              }
   9.291          }
   9.292 @@ -2058,7 +2080,7 @@
   9.293      *dst = msg;
   9.294      *keylist = _keylist;
   9.295  
   9.296 -    return status;
   9.297 +    return ERROR(status);
   9.298  
   9.299  enomem:
   9.300      status = PEP_OUT_OF_MEMORY;
   9.301 @@ -2068,7 +2090,7 @@
   9.302      free_message(msg);
   9.303      free_stringlist(_keylist);
   9.304  
   9.305 -    return status;
   9.306 +    return ERROR(status);
   9.307  }
   9.308  
   9.309  DYNAMIC_API PEP_STATUS decrypt_message(
   9.310 @@ -2117,8 +2139,7 @@
   9.311  
   9.312      free_identity_list(private_il);
   9.313  
   9.314 -    return status;
   9.315 -
   9.316 +    return ERROR(status);
   9.317  }
   9.318  
   9.319  static void _max_comm_type_from_identity_list(
   9.320 @@ -2159,10 +2180,10 @@
   9.321      assert(rating);
   9.322  
   9.323      if (!(session && msg && rating))
   9.324 -        return PEP_ILLEGAL_VALUE;
   9.325 +        return ERROR(PEP_ILLEGAL_VALUE);
   9.326  
   9.327      if (msg->dir != PEP_dir_outgoing)
   9.328 -        return PEP_ILLEGAL_VALUE;
   9.329 +        return ERROR(PEP_ILLEGAL_VALUE);
   9.330  
   9.331      *rating = PEP_rating_undefined;
   9.332  
   9.333 @@ -2246,89 +2267,7 @@
   9.334  
   9.335      // this should never happen
   9.336      assert(false);
   9.337 -	return PEP_color_no_color;
   9.338 -}
   9.339 -
   9.340 -static bool _is_valid_hex(const char* hexstr) {
   9.341 -    if (!hexstr)
   9.342 -        return false;
   9.343 -
   9.344 -    const char* curr = hexstr;
   9.345 -    char currchar;
   9.346 -
   9.347 -    for (currchar = *curr; currchar != '\0'; currchar = *(++curr)) {
   9.348 -        if ((currchar >= '0' && currchar <= '9') ||
   9.349 -            (currchar >= 'a' && currchar <= 'f') ||
   9.350 -            (currchar >= 'A' && currchar <= 'F'))
   9.351 -        {
   9.352 -            continue;
   9.353 -        }
   9.354 -        return false;
   9.355 -    }
   9.356 -    return true;
   9.357 -}
   9.358 -
   9.359 -// Returns, in comparison: 1 if fpr1 > fpr2, 0 if equal, -1 if fpr1 < fpr2
   9.360 -static PEP_STATUS _compare_fprs(const char* fpr1, const char* fpr2, int* comparison) {
   9.361 -
   9.362 -    const int _FULL_FINGERPRINT_LENGTH = 40;
   9.363 -    const int _ASCII_LOWERCASE_OFFSET = 32;
   9.364 -
   9.365 -    size_t fpr1_len = strlen(fpr1);
   9.366 -    size_t fpr2_len = strlen(fpr2);
   9.367 -
   9.368 -    if (fpr1_len != _FULL_FINGERPRINT_LENGTH || fpr2_len != _FULL_FINGERPRINT_LENGTH)
   9.369 -        return PEP_TRUSTWORDS_FPR_WRONG_LENGTH;
   9.370 -
   9.371 -    if (!_is_valid_hex(fpr1) || !_is_valid_hex(fpr2))
   9.372 -        return PEP_ILLEGAL_VALUE;
   9.373 -
   9.374 -    const char* fpr1_curr = fpr1;
   9.375 -    const char* fpr2_curr = fpr2;
   9.376 -
   9.377 -    char current;
   9.378 -
   9.379 -    // Advance past leading zeros.
   9.380 -    for (current = *fpr1_curr; current != '0' && current != '\0'; current = *(++fpr1_curr), fpr1_len--);
   9.381 -    for (current = *fpr2_curr; current != '0' && current != '\0'; current = *(++fpr2_curr), fpr2_len--);
   9.382 -
   9.383 -    if (fpr1_len == fpr2_len) {
   9.384 -        char digit1;
   9.385 -        char digit2;
   9.386 -
   9.387 -        while (fpr1_curr && *fpr1_curr != '\0') {
   9.388 -            digit1 = *fpr1_curr++;
   9.389 -            digit2 = *fpr2_curr++;
   9.390 -
   9.391 -            // Adjust for case-insensitive compare
   9.392 -            if (digit1 >= 'a' && digit1 <= 'f')
   9.393 -                digit1 -= _ASCII_LOWERCASE_OFFSET;
   9.394 -            if (digit2 >= 'a' && digit2 <= 'f')
   9.395 -                digit2 -= _ASCII_LOWERCASE_OFFSET;
   9.396 -
   9.397 -            // We take advantage of the fact that 'a'-'f' are larger
   9.398 -            // integer values in the ASCII table than '0'-'9'.
   9.399 -            // This allows us to compare digits directly.
   9.400 -            if (digit1 > digit2) {
   9.401 -                *comparison = 1;
   9.402 -                return PEP_STATUS_OK;
   9.403 -            } else if (digit1 < digit2) {
   9.404 -                *comparison = -1;
   9.405 -                return PEP_STATUS_OK;
   9.406 -            }
   9.407 -
   9.408 -            // pointers already advanced above. Keep going.
   9.409 -        }
   9.410 -        *comparison = 0;
   9.411 -        return PEP_STATUS_OK;
   9.412 -    }
   9.413 -    else if (fpr1_len > fpr2_len) {
   9.414 -        *comparison = 1;
   9.415 -        return PEP_STATUS_OK;
   9.416 -    }
   9.417 -    // Otherwise, fpr1_len < fpr2_len
   9.418 -    *comparison = -1;
   9.419 -    return PEP_STATUS_OK;
   9.420 +    return PEP_color_no_color;
   9.421  }
   9.422  
   9.423  DYNAMIC_API PEP_STATUS get_trustwords(
   9.424 @@ -2366,7 +2305,7 @@
   9.425      size_t second_wsize = 0;
   9.426  
   9.427      int fpr_comparison = -255;
   9.428 -    PEP_STATUS status = _compare_fprs(source1, source2, &fpr_comparison);
   9.429 +    PEP_STATUS status = _compare_fprs(source1, strlen(source1), source2, strlen(source2), &fpr_comparison);
   9.430      if (status != PEP_STATUS_OK)
   9.431          return status;
   9.432  
   9.433 @@ -2391,7 +2330,7 @@
   9.434                  goto error_release;
   9.435              break;
   9.436          default:
   9.437 -            return PEP_UNKNOWN_ERROR; // shouldn't be possible
   9.438 +            return ERROR(PEP_UNKNOWN_ERROR); // shouldn't be possible
   9.439      }
   9.440  
   9.441      size_t _wsize = first_wsize + second_wsize;
   9.442 @@ -2433,7 +2372,7 @@
   9.443      the_end:
   9.444      free(first_set);
   9.445      free(second_set);
   9.446 -    return status;
   9.447 +    return ERROR(status);
   9.448  }
   9.449  
   9.450  DYNAMIC_API PEP_STATUS get_message_trustwords(
   9.451 @@ -2519,7 +2458,7 @@
   9.452  
   9.453      if (status != PEP_STATUS_OK) {
   9.454          free_identity(partner);
   9.455 -        return status;
   9.456 +        return ERROR(status);
   9.457      }
   9.458     
   9.459      // Find own identity corresponding to given account address.
   9.460 @@ -2532,7 +2471,7 @@
   9.461  
   9.462      if (status != PEP_STATUS_OK) {
   9.463          free_identity(stored_identity);
   9.464 -        return status;
   9.465 +        return ERROR(status);
   9.466      }
   9.467  
   9.468      // get the trustwords
   9.469 @@ -2541,7 +2480,7 @@
   9.470                              partner, received_by, 
   9.471                              lang, words, &wsize, full);
   9.472  
   9.473 -    return status;
   9.474 +    return ERROR(status);
   9.475  }
   9.476  
   9.477  DYNAMIC_API PEP_STATUS MIME_decrypt_message(
   9.478 @@ -2554,13 +2493,20 @@
   9.479      PEP_decrypt_flags_t *flags
   9.480  )
   9.481  {
   9.482 +    assert(mimetext);
   9.483 +    assert(mime_plaintext);
   9.484 +    assert(keylist);
   9.485 +    assert(rating);
   9.486 +    assert(flags);
   9.487 +
   9.488      PEP_STATUS status = PEP_STATUS_OK;
   9.489      message* tmp_msg = NULL;
   9.490      message* dec_msg = NULL;
   9.491 +    *mime_plaintext = NULL;
   9.492  
   9.493      status = mime_decode_message(mimetext, size, &tmp_msg);
   9.494      if (status != PEP_STATUS_OK)
   9.495 -        goto pep_error;
   9.496 +        GOTO(pep_error);
   9.497  
   9.498      PEP_STATUS decrypt_status = decrypt_message(session,
   9.499                                                  tmp_msg,
   9.500 @@ -2569,16 +2515,30 @@
   9.501                                                  rating,
   9.502                                                  flags);
   9.503                                                  
   9.504 +    if (!dec_msg && (decrypt_status == PEP_UNENCRYPTED || decrypt_status == PEP_VERIFIED)) {
   9.505 +        dec_msg = message_dup(tmp_msg);
   9.506 +    }
   9.507 +        
   9.508 +    if (decrypt_status > PEP_CANNOT_DECRYPT_UNKNOWN || !dec_msg)
   9.509 +    {
   9.510 +        status = decrypt_status;
   9.511 +        GOTO(pep_error);
   9.512 +    }
   9.513 +
   9.514      status = mime_encode_message(dec_msg, false, mime_plaintext);
   9.515  
   9.516      if (status == PEP_STATUS_OK)
   9.517 -        return decrypt_status;
   9.518 -        
   9.519 +    {
   9.520 +        free(tmp_msg);
   9.521 +        free(dec_msg);
   9.522 +        return ERROR(decrypt_status);
   9.523 +    }
   9.524 +    
   9.525  pep_error:
   9.526      free_message(tmp_msg);
   9.527      free_message(dec_msg);
   9.528  
   9.529 -    return status;
   9.530 +    return ERROR(status);
   9.531  }
   9.532  
   9.533  
   9.534 @@ -2598,7 +2558,7 @@
   9.535  
   9.536      status = mime_decode_message(mimetext, size, &tmp_msg);
   9.537      if (status != PEP_STATUS_OK)
   9.538 -        goto pep_error;
   9.539 +        GOTO(pep_error);
   9.540  
   9.541      // This isn't incoming, though... so we need to reverse the direction
   9.542      tmp_msg->dir = PEP_dir_outgoing;
   9.543 @@ -2609,7 +2569,13 @@
   9.544                               enc_format,
   9.545                               flags);
   9.546      if (status != PEP_STATUS_OK)
   9.547 -        goto pep_error;
   9.548 +        GOTO(pep_error);
   9.549 +
   9.550 +
   9.551 +    if (!enc_msg) {
   9.552 +        status = PEP_UNKNOWN_ERROR;
   9.553 +        GOTO(pep_error);
   9.554 +    }
   9.555  
   9.556      status = mime_encode_message(enc_msg, false, mime_ciphertext);
   9.557  
   9.558 @@ -2617,7 +2583,7 @@
   9.559      free_message(tmp_msg);
   9.560      free_message(enc_msg);
   9.561  
   9.562 -    return status;
   9.563 +    return ERROR(status);
   9.564  
   9.565  }
   9.566  
   9.567 @@ -2649,6 +2615,11 @@
   9.568                                        flags);
   9.569      if (status != PEP_STATUS_OK)
   9.570          goto pep_error;
   9.571 + 
   9.572 +    if (!enc_msg) {
   9.573 +        status = PEP_UNKNOWN_ERROR;
   9.574 +        goto pep_error;
   9.575 +    }
   9.576  
   9.577      status = mime_encode_message(enc_msg, false, mime_ciphertext);
   9.578  
   9.579 @@ -2656,5 +2627,5 @@
   9.580      free_message(tmp_msg);
   9.581      free_message(enc_msg);
   9.582  
   9.583 -    return status;
   9.584 +    return ERROR(status);
   9.585  }
    10.1 --- a/src/pEpEngine.c	Mon Mar 27 14:53:29 2017 +0200
    10.2 +++ b/src/pEpEngine.c	Tue Jun 06 18:00:40 2017 +0200
    10.3 @@ -29,6 +29,11 @@
    10.4      "       and pgp_keypair_fpr = identity.main_key_id"
    10.5      "   where address = ?1 and identity.user_id = ?2;";
    10.6  
    10.7 +static const char *sql_replace_identities_fpr =  
    10.8 +    "update identity"
    10.9 +    "   set main_key_id = ?1 "
   10.10 +    "   where main_key_id = ?2 ;";
   10.11 +
   10.12  // Set person, but if already exist, only update.
   10.13  // if main_key_id already set, don't touch.
   10.14  static const char *sql_set_person = 
   10.15 @@ -85,6 +90,11 @@
   10.16      "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type) "
   10.17      "values (?1, upper(replace(?2,' ','')), ?3) ;";
   10.18  
   10.19 +static const char *sql_update_trust_for_fpr =
   10.20 +    "update trust "
   10.21 +    "set comm_type = ?1 "
   10.22 +    "where pgp_keypair_fpr = upper(replace(?2,' ','')) ;";
   10.23 +
   10.24  static const char *sql_get_trust = 
   10.25      "select comm_type from trust where user_id = ?1 "
   10.26      "and pgp_keypair_fpr = upper(replace(?2,' ','')) ;";
   10.27 @@ -136,7 +146,11 @@
   10.28      " union "
   10.29      "  select main_key_id from identity "
   10.30      "   where main_key_id = upper(replace(?1,' ',''))"
   10.31 -    "    and user_id = '" PEP_OWN_USERID "' );";
   10.32 +    "    and user_id = '" PEP_OWN_USERID "' "
   10.33 +    " union "
   10.34 +    "  select fpr from own_keys "
   10.35 +    "   where fpr = upper(replace(?1,' ',''))"
   10.36 +    " );";
   10.37  
   10.38  static const char *sql_own_identities_retrieve =  
   10.39      "select address, fpr, username, "
   10.40 @@ -209,6 +223,7 @@
   10.41      int int_result;
   10.42      
   10.43      bool in_first = false;
   10.44 +    bool very_first = false;
   10.45  
   10.46      assert(sqlite3_threadsafe());
   10.47      if (!sqlite3_threadsafe())
   10.48 @@ -234,6 +249,10 @@
   10.49  
   10.50      _session->version = PEP_ENGINE_VERSION;
   10.51  
   10.52 +#ifdef DEBUG_ERRORSTACK
   10.53 +    _session->errorstack = new_stringlist("init()");
   10.54 +#endif
   10.55 +
   10.56      assert(LOCAL_DB);
   10.57      if (LOCAL_DB == NULL) {
   10.58          status = PEP_INIT_CANNOT_OPEN_DB;
   10.59 @@ -462,6 +481,11 @@
   10.60                  assert(int_result == SQLITE_OK);
   10.61              }
   10.62          }
   10.63 +        else { 
   10.64 +            // Version from DB was 0, it means this is initial setup.
   10.65 +            // DB has just been created, and all tables are empty.
   10.66 +            very_first = true;
   10.67 +        }
   10.68  
   10.69          if (version < atoi(_DDL_USER_VERSION)) {
   10.70              int_result = sqlite3_exec(
   10.71 @@ -475,7 +499,6 @@
   10.72              );
   10.73              assert(int_result == SQLITE_OK);
   10.74          }
   10.75 -
   10.76      }
   10.77  
   10.78      int_result = sqlite3_prepare_v2(_session->db, sql_log,
   10.79 @@ -490,6 +513,11 @@
   10.80              (int)strlen(sql_get_identity), &_session->get_identity, NULL);
   10.81      assert(int_result == SQLITE_OK);
   10.82  
   10.83 +    int_result = sqlite3_prepare_v2(_session->db, sql_replace_identities_fpr,
   10.84 +            (int)strlen(sql_replace_identities_fpr), 
   10.85 +            &_session->replace_identities_fpr, NULL);
   10.86 +    assert(int_result == SQLITE_OK);
   10.87 +
   10.88      int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
   10.89              (int)strlen(sql_set_person), &_session->set_person, NULL);
   10.90      assert(int_result == SQLITE_OK);
   10.91 @@ -525,6 +553,10 @@
   10.92              (int)strlen(sql_set_trust), &_session->set_trust, NULL);
   10.93      assert(int_result == SQLITE_OK);
   10.94  
   10.95 +    int_result = sqlite3_prepare_v2(_session->db, sql_update_trust_for_fpr,
   10.96 +            (int)strlen(sql_update_trust_for_fpr), &_session->update_trust_for_fpr, NULL);
   10.97 +    assert(int_result == SQLITE_OK);
   10.98 +
   10.99      int_result = sqlite3_prepare_v2(_session->db, sql_get_trust,
  10.100              (int)strlen(sql_get_trust), &_session->get_trust, NULL);
  10.101      assert(int_result == SQLITE_OK);
  10.102 @@ -635,11 +667,44 @@
  10.103      // runtime config
  10.104  
  10.105  #ifdef ANDROID
  10.106 -    _session->use_only_own_private_keys = true;
  10.107  #elif TARGET_OS_IPHONE
  10.108 -    _session->use_only_own_private_keys = true;
  10.109 -#else
  10.110 -    _session->use_only_own_private_keys = false;
  10.111 +#else /* Desktop */
  10.112 +    if (very_first)
  10.113 +    {
  10.114 +        // On first run, all private keys already present in PGP keyring 
  10.115 +        // are taken as own in order to seamlessly integrate with
  10.116 +        // pre-existing GPG setup.
  10.117 +
  10.118 +        ////////////////////////////// WARNING: ///////////////////////////
  10.119 +        // Considering all PGP priv keys as own is dangerous in case of 
  10.120 +        // re-initialization of pEp DB, while keeping PGP keyring as-is!
  10.121 +        //
  10.122 +        // Indeed, if pEpEngine did import spoofed private keys in previous
  10.123 +        // install, then those keys become automatically trusted in case 
  10.124 +        // pEp_management.db is deleted.
  10.125 +        //
  10.126 +        // A solution to distinguish bare GPG keyring from pEp keyring is
  10.127 +        // needed here. Then keys managed by pEpEngine wouldn't be
  10.128 +        // confused with GPG keys managed by the user through GPA.
  10.129 +        ///////////////////////////////////////////////////////////////////
  10.130 +        
  10.131 +        stringlist_t *keylist = NULL;
  10.132 +
  10.133 +        status = find_private_keys(_session, NULL, &keylist);
  10.134 +        assert(status != PEP_OUT_OF_MEMORY);
  10.135 +        if (status == PEP_OUT_OF_MEMORY)
  10.136 +            return PEP_OUT_OF_MEMORY;
  10.137 +        
  10.138 +        if (keylist != NULL && keylist->value != NULL)
  10.139 +        {
  10.140 +            stringlist_t *_keylist;
  10.141 +            for (_keylist = keylist; _keylist && _keylist->value; _keylist = _keylist->next) {
  10.142 +                status = set_own_key(_session, 
  10.143 +                                     "" /* address is unused in own_keys */,
  10.144 +                                     _keylist->value);
  10.145 +            }
  10.146 +        }
  10.147 +    }
  10.148  #endif
  10.149  
  10.150      // sync_session set to own session by default
  10.151 @@ -685,6 +750,8 @@
  10.152                  sqlite3_finalize(session->trustword);
  10.153              if (session->get_identity)
  10.154                  sqlite3_finalize(session->get_identity);
  10.155 +            if (session->replace_identities_fpr)
  10.156 +                sqlite3_finalize(session->replace_identities_fpr);        
  10.157              if (session->set_person)
  10.158                  sqlite3_finalize(session->set_person);
  10.159              if (session->set_device_group)
  10.160 @@ -701,6 +768,8 @@
  10.161                  sqlite3_finalize(session->unset_identity_flags);
  10.162              if (session->set_trust)
  10.163                  sqlite3_finalize(session->set_trust);
  10.164 +            if (session->update_trust_for_fpr)
  10.165 +                sqlite3_finalize(session->update_trust_for_fpr);
  10.166              if (session->get_trust)
  10.167                  sqlite3_finalize(session->get_trust);
  10.168              if (session->least_trust)
  10.169 @@ -749,6 +818,9 @@
  10.170          release_transport_system(session, out_last);
  10.171          release_cryptotech(session, out_last);
  10.172  
  10.173 +#ifdef DEBUG_ERRORSTACK
  10.174 +        free_stringlist(session->errorstack);
  10.175 +#endif
  10.176          free(session);
  10.177      }
  10.178  }
  10.179 @@ -765,19 +837,18 @@
  10.180      session->unencrypted_subject = enable;
  10.181  }
  10.182  
  10.183 -DYNAMIC_API void config_use_only_own_private_keys(PEP_SESSION session,
  10.184 -        bool enable)
  10.185 -{
  10.186 -    assert(session);
  10.187 -    session->use_only_own_private_keys = enable;
  10.188 -}
  10.189 -
  10.190  DYNAMIC_API void config_keep_sync_msg(PEP_SESSION session, bool enable)
  10.191  {
  10.192      assert(session);
  10.193      session->keep_sync_msg = enable;
  10.194  }
  10.195  
  10.196 +DYNAMIC_API void config_service_log(PEP_SESSION session, bool enable)
  10.197 +{
  10.198 +    assert(session);
  10.199 +    session->service_log = enable;
  10.200 +}
  10.201 +
  10.202  DYNAMIC_API PEP_STATUS log_event(
  10.203          PEP_SESSION session,
  10.204          const char *title,
  10.205 @@ -815,7 +886,25 @@
  10.206      } while (result == SQLITE_BUSY);
  10.207      sqlite3_reset(session->log);
  10.208  
  10.209 -    return status;
  10.210 +    return ERROR(status);
  10.211 +}
  10.212 +
  10.213 +DYNAMIC_API PEP_STATUS log_service(
  10.214 +        PEP_SESSION session,
  10.215 +        const char *title,
  10.216 +        const char *entity,
  10.217 +        const char *description,
  10.218 +        const char *comment
  10.219 +    )
  10.220 +{
  10.221 +    assert(session);
  10.222 +    if (!session)
  10.223 +        return PEP_ILLEGAL_VALUE;
  10.224 +
  10.225 +    if (session->service_log)
  10.226 +        return log_event(session, title, entity, description, comment);
  10.227 +    else
  10.228 +        return PEP_STATUS_OK;
  10.229  }
  10.230  
  10.231  DYNAMIC_API PEP_STATUS trustword(
  10.232 @@ -1105,13 +1194,15 @@
  10.233                  identity->user_id && identity->username))
  10.234          return PEP_ILLEGAL_VALUE;
  10.235  
  10.236 +    PEP_STATUS status = PEP_STATUS_OK;
  10.237 +    
  10.238      bool listed;
  10.239  
  10.240      bool has_fpr = (identity->fpr && identity->fpr[0] != '\0');
  10.241      
  10.242      if (has_fpr) {    
  10.243          // blacklist check
  10.244 -        PEP_STATUS status = blacklist_is_listed(session, identity->fpr, &listed);
  10.245 +        status = blacklist_is_listed(session, identity->fpr, &listed);
  10.246          assert(status == PEP_STATUS_OK);
  10.247          if (status != PEP_STATUS_OK)
  10.248              return status;
  10.249 @@ -1189,6 +1280,8 @@
  10.250              }
  10.251          }
  10.252  
  10.253 +        // status = set_trust(session, identity->user_id, identity->fpr,
  10.254 +        //                    identity->comm_type)
  10.255          sqlite3_reset(session->set_trust);
  10.256          sqlite3_bind_text(session->set_trust, 1, identity->user_id, -1,
  10.257                  SQLITE_STATIC);
  10.258 @@ -1210,6 +1303,52 @@
  10.259          return PEP_COMMIT_FAILED;
  10.260  }
  10.261  
  10.262 +PEP_STATUS replace_identities_fpr(PEP_SESSION session, 
  10.263 +                                 const char* old_fpr, 
  10.264 +                                 const char* new_fpr) 
  10.265 +{
  10.266 +    assert(old_fpr);
  10.267 +    assert(new_fpr);
  10.268 +    
  10.269 +    if (!old_fpr || !new_fpr)
  10.270 +        return PEP_ILLEGAL_VALUE;
  10.271 +            
  10.272 +    sqlite3_reset(session->replace_identities_fpr);
  10.273 +    sqlite3_bind_text(session->replace_identities_fpr, 1, new_fpr, -1,
  10.274 +                      SQLITE_STATIC);
  10.275 +    sqlite3_bind_text(session->replace_identities_fpr, 2, old_fpr, -1,
  10.276 +                      SQLITE_STATIC);
  10.277 +
  10.278 +    int result = sqlite3_step(session->replace_identities_fpr);
  10.279 +    sqlite3_reset(session->replace_identities_fpr);
  10.280 +    
  10.281 +    if (result != SQLITE_DONE)
  10.282 +        return PEP_CANNOT_SET_IDENTITY;
  10.283 +
  10.284 +    return PEP_STATUS_OK;
  10.285 +}
  10.286 +
  10.287 +
  10.288 +PEP_STATUS update_trust_for_fpr(PEP_SESSION session, 
  10.289 +                                const char* fpr, 
  10.290 +                                PEP_comm_type comm_type)
  10.291 +{
  10.292 +    if (!fpr)
  10.293 +        return PEP_ILLEGAL_VALUE;
  10.294 +        
  10.295 +    sqlite3_reset(session->update_trust_for_fpr);
  10.296 +    sqlite3_bind_int(session->update_trust_for_fpr, 1, comm_type);
  10.297 +    sqlite3_bind_text(session->update_trust_for_fpr, 2, fpr, -1,
  10.298 +            SQLITE_STATIC);
  10.299 +    int result = sqlite3_step(session->update_trust_for_fpr);
  10.300 +    sqlite3_reset(session->update_trust_for_fpr);
  10.301 +    if (result != SQLITE_DONE) {
  10.302 +        return PEP_CANNOT_SET_TRUST;
  10.303 +    }
  10.304 +    
  10.305 +    return PEP_STATUS_OK;
  10.306 +}
  10.307 +
  10.308  DYNAMIC_API PEP_STATUS set_device_group(
  10.309          PEP_SESSION session,
  10.310          const char *group_name
  10.311 @@ -1849,7 +1988,7 @@
  10.312      status = PEP_OUT_OF_MEMORY;
  10.313  
  10.314  the_end:
  10.315 -    return status;
  10.316 +    return ERROR(status);
  10.317  }
  10.318  
  10.319  DYNAMIC_API PEP_STATUS get_languagelist(
  10.320 @@ -2238,8 +2377,8 @@
  10.321  
  10.322  PEP_STATUS find_private_keys(PEP_SESSION session, const char* pattern,
  10.323                               stringlist_t **keylist) {
  10.324 -    assert(session && pattern && keylist);
  10.325 -    if (!(session && pattern && keylist))
  10.326 +    assert(session && keylist);
  10.327 +    if (!(session && keylist))
  10.328          return PEP_ILLEGAL_VALUE;
  10.329      
  10.330      return session->cryptotech[PEP_crypt_OpenPGP].find_private_keys(session, pattern,
  10.331 @@ -2272,3 +2411,52 @@
  10.332  
  10.333      return PEP_STATUS_OK;
  10.334  }
  10.335 +
  10.336 +#ifdef DEBUG_ERRORSTACK
  10.337 +PEP_STATUS session_add_error(PEP_SESSION session, const char* file, unsigned line, PEP_STATUS status)
  10.338 +{
  10.339 +    char logline[48];
  10.340 +    if(status>0)
  10.341 +    {
  10.342 +        snprintf(logline,47, "%.24s:%u status=%u (0x%x)", file, line, status, status);
  10.343 +    }else{
  10.344 +        snprintf(logline,47, "%.24s:%u status=%i.", file, line, status);
  10.345 +    }
  10.346 +    stringlist_add(session->errorstack, logline); // logline is copied! :-)
  10.347 +    return status;
  10.348 +}
  10.349 +
  10.350 +DYNAMIC_API const stringlist_t* get_errorstack(PEP_SESSION session)
  10.351 +{
  10.352 +    return session->errorstack;
  10.353 +}
  10.354 +
  10.355 +DYNAMIC_API void clear_errorstack(PEP_SESSION session)
  10.356 +{
  10.357 +    const int old_len = stringlist_length(session->errorstack);
  10.358 +    char buf[48];
  10.359 +    free_stringlist(session->errorstack);
  10.360 +    snprintf(buf, 47, "(%i elements cleared)", old_len);
  10.361 +    session->errorstack = new_stringlist(buf);
  10.362 +}
  10.363 +
  10.364 +#else
  10.365 +
  10.366 +static stringlist_t* dummy_errorstack = NULL;
  10.367 +
  10.368 +DYNAMIC_API const stringlist_t* get_errorstack(PEP_SESSION session)
  10.369 +{
  10.370 +    if(dummy_errorstack == NULL)
  10.371 +    {
  10.372 +        dummy_errorstack = new_stringlist("( Please recompile pEpEngine with -DDEBUG_ERRORSTACK )");
  10.373 +    }
  10.374 +
  10.375 +    return dummy_errorstack;
  10.376 +}
  10.377 +
  10.378 +DYNAMIC_API void clear_errorstack(PEP_SESSION session)
  10.379 +{
  10.380 +    // nothing to do here
  10.381 +}
  10.382 +
  10.383 +#endif
    11.1 --- a/src/pEpEngine.h	Mon Mar 27 14:53:29 2017 +0200
    11.2 +++ b/src/pEpEngine.h	Tue Jun 06 18:00:40 2017 +0200
    11.3 @@ -46,6 +46,7 @@
    11.4      PEP_KEY_HAS_AMBIG_NAME                          = 0x0202,
    11.5      PEP_GET_KEY_FAILED                              = 0x0203,
    11.6      PEP_CANNOT_EXPORT_KEY                           = 0x0204,
    11.7 +    PEP_CANNOT_EDIT_KEY                             = 0x0205,
    11.8      
    11.9      PEP_CANNOT_FIND_IDENTITY                        = 0x0301,
   11.10      PEP_CANNOT_SET_PERSON                           = 0x0381,
   11.11 @@ -147,6 +148,25 @@
   11.12  DYNAMIC_API void release(PEP_SESSION session);
   11.13  
   11.14  
   11.15 +// const stringlist_t* get_errorstack(PEP_SESSION) - get the error stack for that session, if any
   11.16 +//
   11.17 +//  parameters:
   11.18 +//        session (in)    session handle
   11.19 +//
   11.20 +//    caveat:
   11.21 +//        To get a useful error stack you have to compile with -DDEBUG_ERRORSTACK
   11.22 +//        The error stack belongs to the session. Do no not change it!
   11.23 +DYNAMIC_API const stringlist_t* get_errorstack(PEP_SESSION session);
   11.24 +
   11.25 +
   11.26 +// void clear_errorstack(PEP_SESSION) - clear the error stack for that session, if any
   11.27 +//
   11.28 +//  parameters:
   11.29 +//        session (in)    session handle
   11.30 +//
   11.31 +DYNAMIC_API void clear_errorstack(PEP_SESSION session);
   11.32 +
   11.33 +
   11.34  // config_passive_mode() - enable passive mode
   11.35  //
   11.36  //  parameters:
   11.37 @@ -182,6 +202,14 @@
   11.38  DYNAMIC_API void config_keep_sync_msg(PEP_SESSION session, bool enable);
   11.39  
   11.40  
   11.41 +// config_service_log() - log more for service purposes
   11.42 +//
   11.43 +//      session (in)    session handle
   11.44 +//      enable (in)     flag if enabled or disabled
   11.45 +
   11.46 +DYNAMIC_API void config_service_log(PEP_SESSION session, bool enable);
   11.47 +
   11.48 +
   11.49  // decrypt_and_verify() - decrypt and/or verify a message
   11.50  //
   11.51  //    parameters:
   11.52 @@ -296,6 +324,17 @@
   11.53      );
   11.54  
   11.55  
   11.56 +DYNAMIC_API PEP_STATUS log_service(PEP_SESSION session, const char *title,
   11.57 +        const char *entity, const char *description, const char *comment);
   11.58 +
   11.59 +#define _STR_(x) #x
   11.60 +#define _D_STR_(x) _STR_(x)
   11.61 +#define S_LINE _D_STR_(__LINE__)
   11.62 +
   11.63 +#define SERVICE_LOG(session, title, entity, desc) \
   11.64 +    log_service((session), (title), (entity), (desc), "service " __FILE__ ":" S_LINE)
   11.65 +
   11.66 +
   11.67  // trustword() - get the corresponding trustword for a 16 bit value
   11.68  //
   11.69  //    parameters:
   11.70 @@ -524,6 +563,11 @@
   11.71          pEp_identity **identity
   11.72      );
   11.73  
   11.74 +PEP_STATUS replace_identities_fpr(PEP_SESSION session, 
   11.75 +                                 const char* old_fpr, 
   11.76 +                                 const char* new_fpr); 
   11.77 +
   11.78 +
   11.79  // set_identity() - set identity information
   11.80  //
   11.81  //    parameters:
   11.82 @@ -807,6 +851,14 @@
   11.83  
   11.84  DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity);
   11.85  
   11.86 +PEP_STATUS set_trust(PEP_SESSION session, 
   11.87 +                            const char* user_id,
   11.88 +                            const char* fpr, 
   11.89 +                            PEP_comm_type comm_type);
   11.90 +                            
   11.91 +PEP_STATUS update_trust_for_fpr(PEP_SESSION session, 
   11.92 +                                const char* fpr, 
   11.93 +                                PEP_comm_type comm_type);
   11.94  
   11.95  // least_trust() - get the least known trust level for a key in the database
   11.96  //
   11.97 @@ -905,6 +957,12 @@
   11.98          bool *revoked
   11.99      );
  11.100  
  11.101 +PEP_STATUS get_key_userids(
  11.102 +        PEP_SESSION session,
  11.103 +        const char* fpr,
  11.104 +        stringlist_t** keylist
  11.105 +    );
  11.106 +
  11.107  
  11.108  // get_crashdump_log() - get the last log messages out
  11.109  //
    12.1 --- a/src/pEp_internal.h	Mon Mar 27 14:53:29 2017 +0200
    12.2 +++ b/src/pEp_internal.h	Tue Jun 06 18:00:40 2017 +0200
    12.3 @@ -100,6 +100,7 @@
    12.4      sqlite3_stmt *log;
    12.5      sqlite3_stmt *trustword;
    12.6      sqlite3_stmt *get_identity;
    12.7 +    sqlite3_stmt *replace_identities_fpr;
    12.8      sqlite3_stmt *set_person;
    12.9      sqlite3_stmt *set_device_group;
   12.10      sqlite3_stmt *get_device_group;
   12.11 @@ -108,6 +109,7 @@
   12.12      sqlite3_stmt *set_identity_flags;
   12.13      sqlite3_stmt *unset_identity_flags;
   12.14      sqlite3_stmt *set_trust;
   12.15 +    sqlite3_stmt *update_trust_for_fpr;
   12.16      sqlite3_stmt *get_trust;
   12.17      sqlite3_stmt *least_trust;
   12.18      sqlite3_stmt *mark_compromized;
   12.19 @@ -159,11 +161,15 @@
   12.20  
   12.21      bool passive_mode;
   12.22      bool unencrypted_subject;
   12.23 -    bool use_only_own_private_keys;
   12.24      bool keep_sync_msg;
   12.25 +    bool service_log;
   12.26      
   12.27 +#ifdef DEBUG_ERRORSTACK
   12.28 +    stringlist_t* errorstack;
   12.29 +#endif
   12.30  };
   12.31  
   12.32 +
   12.33  PEP_STATUS init_transport_system(PEP_SESSION session, bool in_first);
   12.34  void release_transport_system(PEP_SESSION session, bool out_last);
   12.35  
   12.36 @@ -178,18 +184,120 @@
   12.37  #else
   12.38  #ifdef ANDROID
   12.39  #include <android/log.h>
   12.40 -#define  LOG_MORE(...)  __android_log_print(ANDROID_LOG_DEBUG, "pEpEngine", " %s :: %s :: %s ", __VA_ARGS__);
   12.41 +#define  LOG_MORE(...)  __android_log_print(ANDROID_LOG_DEBUG, "pEpEngine", " %s :: %s :: %s :: %s ", __VA_ARGS__);
   12.42  #else
   12.43  #include <stdio.h>
   12.44 -#define  LOG_MORE(...)  printf("pEpEngine DEBUG_LOG('%s','%s','%s')\n", __VA_ARGS__);
   12.45 +#define  LOG_MORE(...)  fprintf(stderr, "pEpEngine DEBUG_LOG('%s','%s','%s','%s')\n", __VA_ARGS__);
   12.46  #endif
   12.47  #define DEBUG_LOG(TITLE, ENTITY, DESC) {\
   12.48 -    log_event(session, (TITLE), (ENTITY), (DESC), "debug");\
   12.49 -    LOG_MORE((TITLE), (ENTITY), (DESC))\
   12.50 +    log_event(session, (TITLE), (ENTITY), (DESC), "debug " __FILE__ ":" S_LINE);\
   12.51 +    LOG_MORE((TITLE), (ENTITY), (DESC), __FILE__ ":" S_LINE)\
   12.52  }
   12.53  #endif
   12.54  
   12.55 +typedef enum _normalize_hex_rest_t {
   12.56 +    accept_hex,
   12.57 +    ignore_hex,
   12.58 +    reject_hex
   12.59 +} normalize_hex_res_t;
   12.60 +
   12.61 +static inline normalize_hex_res_t _normalize_hex(char *hex) 
   12.62 +{
   12.63 +    if (*hex >= '0' && *hex <= '9')
   12.64 +        return accept_hex;
   12.65 +
   12.66 +    if (*hex >= 'A' && *hex <= 'F') {
   12.67 +        *hex += 'a' - 'A';
   12.68 +        return accept_hex;
   12.69 +    }
   12.70 +
   12.71 +    if (*hex >= 'a' && *hex <= 'f') 
   12.72 +        return accept_hex;
   12.73 +
   12.74 +    if (*hex == ' ') 
   12.75 +        return ignore_hex;
   12.76 +
   12.77 +    return reject_hex;
   12.78 +}
   12.79 +
   12.80  // Space tolerant and case insensitive fingerprint string compare
   12.81 +static inline PEP_STATUS _compare_fprs(
   12.82 +        const char* fpra,
   12.83 +        size_t fpras,
   12.84 +        const char* fprb,
   12.85 +        size_t fprbs,
   12.86 +        int* comparison)
   12.87 +{
   12.88 +
   12.89 +    size_t ai = 0;
   12.90 +    size_t bi = 0;
   12.91 +    size_t significant = 0;
   12.92 +    int _comparison = 0;
   12.93 +    const int _FULL_FINGERPRINT_LENGTH = 40;
   12.94 +   
   12.95 +    // First compare every non-ignored chars until an end is reached
   12.96 +    while(ai < fpras && bi < fprbs)
   12.97 +    {
   12.98 +        char fprac = fpra[ai];
   12.99 +        char fprbc = fprb[bi];
  12.100 +        normalize_hex_res_t fprah = _normalize_hex(&fprac);
  12.101 +        normalize_hex_res_t fprbh = _normalize_hex(&fprbc);
  12.102 +
  12.103 +        if(fprah == reject_hex || fprbh == reject_hex)
  12.104 +            return PEP_ILLEGAL_VALUE;
  12.105 +
  12.106 +        if ( fprah == ignore_hex )
  12.107 +        {
  12.108 +            ai++;
  12.109 +        }
  12.110 +        else if ( fprbh == ignore_hex )
  12.111 +        {
  12.112 +            bi++;
  12.113 +        }
  12.114 +        else
  12.115 +        {
  12.116 +            if(fprac != fprbc && _comparison == 0 )
  12.117 +            {
  12.118 +                _comparison = fprac > fprbc ? 1 : -1;
  12.119 +            }
  12.120 +
  12.121 +            significant++;
  12.122 +            ai++;
  12.123 +            bi++;
  12.124 +
  12.125 +        } 
  12.126 +    }
  12.127 +
  12.128 +    // Bail out if we didn't got enough significnt chars
  12.129 +    if (significant != _FULL_FINGERPRINT_LENGTH )
  12.130 +        return PEP_TRUSTWORDS_FPR_WRONG_LENGTH;
  12.131 +
  12.132 +    // Then purge remaining chars, all must be ignored chars
  12.133 +    while ( ai < fpras )
  12.134 +    {
  12.135 +        char fprac = fpra[ai];
  12.136 +        normalize_hex_res_t fprah = _normalize_hex(&fprac);
  12.137 +        if( fprah == reject_hex )
  12.138 +            return PEP_ILLEGAL_VALUE;
  12.139 +        if ( fprah != ignore_hex )
  12.140 +            return PEP_TRUSTWORDS_FPR_WRONG_LENGTH;
  12.141 +        ai++;
  12.142 +    }
  12.143 +    while ( bi < fprbs )
  12.144 +    {
  12.145 +        char fprbc = fprb[bi];
  12.146 +        normalize_hex_res_t fprbh = _normalize_hex(&fprbc);
  12.147 +        if( fprbh == reject_hex )
  12.148 +            return PEP_ILLEGAL_VALUE;
  12.149 +        if ( fprbh != ignore_hex )
  12.150 +            return PEP_TRUSTWORDS_FPR_WRONG_LENGTH;
  12.151 +        bi++;
  12.152 +    }
  12.153 +
  12.154 +    *comparison = _comparison;
  12.155 +    return PEP_STATUS_OK;
  12.156 +}
  12.157 +
  12.158  static inline int _same_fpr(
  12.159          const char* fpra,
  12.160          size_t fpras,
  12.161 @@ -197,35 +305,20 @@
  12.162          size_t fprbs
  12.163      )
  12.164  {
  12.165 -    size_t ai = 0;
  12.166 -    size_t bi = 0;
  12.167 -    
  12.168 -    do
  12.169 -    {
  12.170 -        if(fpra[ai] == 0 || fprb[bi] == 0)
  12.171 -        {
  12.172 -            return 0;
  12.173 -        }
  12.174 -        else if(fpra[ai] == ' ')
  12.175 -        {
  12.176 -            ai++;
  12.177 -        }
  12.178 -        else if(fprb[bi] == ' ')
  12.179 -        {
  12.180 -            bi++;
  12.181 -        }
  12.182 -        else if(toupper(fpra[ai]) == toupper(fprb[bi]))
  12.183 -        {
  12.184 -            ai++;
  12.185 -            bi++;
  12.186 -        }
  12.187 -        else
  12.188 -        {
  12.189 -            return 0;
  12.190 -        }
  12.191 -        
  12.192 -    }
  12.193 -    while(ai < fpras && bi < fprbs);
  12.194 -    
  12.195 -    return ai == fpras && bi == fprbs;
  12.196 +    // illegal values are ignored, and considered not same.
  12.197 +    int comparison = 1;
  12.198 +
  12.199 +    _compare_fprs(fpra, fpras, fprb, fprbs, &comparison);
  12.200 +
  12.201 +    return comparison == 0;
  12.202  }
  12.203 +
  12.204 +
  12.205 +#ifdef DEBUG_ERRORSTACK
  12.206 +    PEP_STATUS session_add_error(PEP_SESSION session, const char* file, unsigned line, PEP_STATUS status);
  12.207 +    #define ERROR(status)   session_add_error(session, __FILE__, __LINE__, (status))
  12.208 +    #define GOTO(label)     do{ (void)session_add_error(session, __FILE__, __LINE__, status); goto label; }while(0)
  12.209 +#else
  12.210 +    #define ERROR(status)   (status)
  12.211 +    #define GOTO(label)     goto label
  12.212 +#endif
    13.1 --- a/src/pgp_gpg.c	Mon Mar 27 14:53:29 2017 +0200
    13.2 +++ b/src/pgp_gpg.c	Tue Jun 06 18:00:40 2017 +0200
    13.3 @@ -39,8 +39,7 @@
    13.4          assert(length == stringlist_length(values));
    13.5          if (!(length == stringlist_length(values) &&
    13.6                length <= sizeof(unsigned int) * CHAR_BIT)) {
    13.7 -            r = Fclose(f);
    13.8 -            assert(r == 0);
    13.9 +            Fclose(f);
   13.10  
   13.11              return false;
   13.12          }
   13.13 @@ -62,6 +61,8 @@
   13.14  
   13.15                          if (i == n) {
   13.16                              r = Fclose(f);
   13.17 +                            if (r != 0)
   13.18 +                                return false;
   13.19                              return true;
   13.20                          }
   13.21                      }
   13.22 @@ -83,11 +84,15 @@
   13.23          if ((found & i) == 0) {
   13.24              r = Fprintf(f, "%s %s\n", _k->value, _v->value);
   13.25              assert(r >= 0);
   13.26 +            if(r<0)
   13.27 +                return false;
   13.28          }
   13.29      }
   13.30  
   13.31      r = Fclose(f);
   13.32      assert(r == 0);
   13.33 +    if (r != 0)
   13.34 +        return false;
   13.35  
   13.36      return true;
   13.37  }
   13.38 @@ -1352,6 +1357,8 @@
   13.39  
   13.40      reading = gpg.gpgme_data_read(dh, buffer, _size);
   13.41      assert(_size == reading);
   13.42 +    if(_size != reading)
   13.43 +        return PEP_CANNOT_EXPORT_KEY;
   13.44  
   13.45      // safeguard for the naive user
   13.46      buffer[_size] = 0;
   13.47 @@ -1547,7 +1554,6 @@
   13.48      gpgme_key_t key;
   13.49  
   13.50      assert(session);
   13.51 -    assert(pattern);
   13.52      assert(keylist);
   13.53  
   13.54      *keylist = NULL;
   13.55 @@ -1584,7 +1590,9 @@
   13.56                  gpgme_user_id_t kuid = key->uids;
   13.57                  // check that at least one uid's email matches pattern exactly
   13.58                  while(kuid) {
   13.59 -                    if(kuid->email && strcmp(kuid->email, pattern) == 0){
   13.60 +                    if((pattern && kuid->email && strcmp(kuid->email, pattern) == 0) ||
   13.61 +                       pattern == NULL /* match all */ )
   13.62 +                    { 
   13.63                          char *fpr = key->subkeys->fpr;
   13.64                          assert(fpr);
   13.65                          _k = stringlist_add(_k, fpr);
   13.66 @@ -1939,11 +1947,14 @@
   13.67      gpgme_error = gpg.gpgme_op_edit(session->ctx, key, renew_fsm, &handle,
   13.68              output);
   13.69      assert(gpgme_error == GPG_ERR_NO_ERROR);
   13.70 +    if(gpgme_error != GPG_ERR_NO_ERROR) {
   13.71 +        status = PEP_CANNOT_EDIT_KEY;
   13.72 +    }
   13.73  
   13.74      gpg.gpgme_data_release(output);
   13.75      gpg.gpgme_key_unref(key);
   13.76  
   13.77 -    return PEP_STATUS_OK;
   13.78 +    return status;
   13.79  }
   13.80  
   13.81  typedef struct _revoke_state {
   13.82 @@ -2126,11 +2137,14 @@
   13.83      gpgme_error = gpg.gpgme_op_edit(session->ctx, key, revoke_fsm, &handle,
   13.84              output);
   13.85      assert(gpgme_error == GPG_ERR_NO_ERROR);
   13.86 +    if(gpgme_error != GPG_ERR_NO_ERROR) {
   13.87 +        status = PEP_CANNOT_EDIT_KEY;
   13.88 +    }
   13.89  
   13.90      gpg.gpgme_data_release(output);
   13.91      gpg.gpgme_key_unref(key);
   13.92  
   13.93 -    return PEP_STATUS_OK;
   13.94 +    return status;
   13.95  }
   13.96  
   13.97  PEP_STATUS pgp_key_expired(
    14.1 --- a/src/pgp_netpgp.c	Mon Mar 27 14:53:29 2017 +0200
    14.2 +++ b/src/pgp_netpgp.c	Tue Jun 06 18:00:40 2017 +0200
    14.3 @@ -241,6 +241,9 @@
    14.4      unsigned i,j;
    14.5  
    14.6      *length = 0;
    14.7 +    
    14.8 +    if (str == NULL)
    14.9 +        return 0;
   14.10  
   14.11      while(*str && *length < PGP_FINGERPRINT_SIZE){
   14.12          while (*str == ' ') str++;
   14.13 @@ -1055,18 +1058,18 @@
   14.14      PEP_STATUS result;
   14.15      char *buffer;
   14.16      size_t buflen;
   14.17 +    const pgp_keyring_t *srcring;
   14.18  
   14.19      assert(session);
   14.20      assert(fprstr);
   14.21      assert(key_data);
   14.22      assert(size);
   14.23  
   14.24 -    // TODO : support export secret key
   14.25 -    // crashing stub until export secret supported
   14.26 -    assert(!secret);
   14.27      if (secret)
   14.28 -        return PEP_ILLEGAL_VALUE;
   14.29 -
   14.30 +        srcring = netpgp.secring;
   14.31 +    else
   14.32 +        srcring = netpgp.pubring;
   14.33 +    
   14.34      if (!session || !fprstr || !key_data || !size)
   14.35          return PEP_ILLEGAL_VALUE;
   14.36  
   14.37 @@ -1077,7 +1080,7 @@
   14.38      if (str_to_fpr(fprstr, fpr, &fprlen)) {
   14.39          unsigned from = 0;
   14.40  
   14.41 -        if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.pubring,
   14.42 +        if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, srcring,
   14.43                                                  fpr, fprlen, &from,
   14.44                                                  NULL,0,0)) == NULL) {
   14.45              result = PEP_KEY_NOT_FOUND;
   14.46 @@ -1213,7 +1216,7 @@
   14.47  
   14.48  typedef PEP_STATUS (*find_key_cb_t)(void*, pgp_key_t *);
   14.49  
   14.50 -static PEP_STATUS find_keys_do(
   14.51 +static PEP_STATUS find_keys_do(pgp_keyring_t* keyring,
   14.52          const char *pattern, find_key_cb_t cb, void* cb_arg)
   14.53  {
   14.54      uint8_t fpr[PGP_FINGERPRINT_SIZE];
   14.55 @@ -1230,7 +1233,7 @@
   14.56          // Only one fingerprint can match
   14.57          if ((key = (pgp_key_t *)pgp_getkeybyfpr(
   14.58                          netpgp.io,
   14.59 -                        (pgp_keyring_t *)netpgp.pubring,
   14.60 +                        keyring,
   14.61                          (const uint8_t *)fpr, length,
   14.62                          &from,
   14.63                          NULL, 0, 0)) == NULL) {
   14.64 @@ -1246,7 +1249,7 @@
   14.65          result = PEP_KEY_NOT_FOUND;
   14.66          while((key = (pgp_key_t *)pgp_getnextkeybyname(
   14.67                          netpgp.io,
   14.68 -                        (pgp_keyring_t *)netpgp.pubring,
   14.69 +                        keyring,
   14.70  			            (const char *)pattern,
   14.71                          &from)) != NULL) {
   14.72  
   14.73 @@ -1365,7 +1368,8 @@
   14.74      }
   14.75      _k = _keylist;
   14.76  
   14.77 -    result = find_keys_do(pattern, &add_key_fpr_to_stringlist, &_k);
   14.78 +    result = find_keys_do((pgp_keyring_t *)netpgp.pubring,
   14.79 +                          pattern, &add_key_fpr_to_stringlist, &_k);
   14.80  
   14.81      if (result == PEP_STATUS_OK) {
   14.82          *keylist = _keylist;
   14.83 @@ -1453,7 +1457,8 @@
   14.84          goto free_encoded_keys;
   14.85      }
   14.86  
   14.87 -    result = find_keys_do(pattern, &send_key_cb, (void*)encoded_keys);
   14.88 +    result = find_keys_do((pgp_keyring_t *)netpgp.pubring,
   14.89 +                          pattern, &send_key_cb, (void*)encoded_keys);
   14.90  
   14.91      pthread_mutex_unlock(&netpgp_mutex);
   14.92  
   14.93 @@ -1873,7 +1878,8 @@
   14.94  
   14.95      PEP_STATUS result;
   14.96  
   14.97 -    result = find_keys_do(pattern, &add_keyinfo_to_stringpair_list, (void*)keyinfo_list);
   14.98 +    result = find_keys_do((pgp_keyring_t *)netpgp.pubring,
   14.99 +                          pattern, &add_keyinfo_to_stringpair_list, (void*)keyinfo_list);
  14.100  
  14.101      if (!keyinfo_list)
  14.102          result = PEP_KEY_NOT_FOUND;
  14.103 @@ -1892,10 +1898,9 @@
  14.104      PEP_STATUS result;
  14.105  
  14.106      assert(session);
  14.107 -    assert(pattern);
  14.108      assert(keylist);
  14.109  
  14.110 -    if (!session || !pattern || !keylist )
  14.111 +    if (!session || !keylist )
  14.112      {
  14.113          return PEP_ILLEGAL_VALUE;
  14.114      }
  14.115 @@ -1913,7 +1918,8 @@
  14.116      }
  14.117      _k = _keylist;
  14.118  
  14.119 -    result = find_keys_do(pattern, &add_secret_key_fpr_to_stringlist, &_k);
  14.120 +    result = find_keys_do((pgp_keyring_t *)netpgp.secring,
  14.121 +                          pattern, &add_secret_key_fpr_to_stringlist, &_k);
  14.122  
  14.123      if (result == PEP_STATUS_OK) {
  14.124          *keylist = _keylist;
    15.1 --- a/src/platform_windows.cpp	Mon Mar 27 14:53:29 2017 +0200
    15.2 +++ b/src/platform_windows.cpp	Tue Jun 06 18:00:40 2017 +0200
    15.3 @@ -139,9 +139,15 @@
    15.4      assert(filename);
    15.5  	assert(flag == RTLD_LAZY); // only lazy binding is implemented
    15.6  
    15.7 -    bool result = readRegistryString(HKEY_LOCAL_MACHINE,
    15.8 -            TEXT("SOFTWARE\\GNU\\GnuPG"), TEXT("Install Directory"), path,
    15.9 -            PATH_BUF_SIZE, NULL);
   15.10 +	// Look up GnuPG installation in current user scope
   15.11 +	bool result = readRegistryString(HKEY_CURRENT_USER,
   15.12 +		TEXT("SOFTWARE\\GNU\\GnuPG"), TEXT("Install Directory"), path,
   15.13 +		PATH_BUF_SIZE, NULL);
   15.14 +	// If not found in current user, look up in local machine
   15.15 +	if (!result)
   15.16 +		result = readRegistryString(HKEY_LOCAL_MACHINE,
   15.17 +			TEXT("SOFTWARE\\GNU\\GnuPG"), TEXT("Install Directory"), path,
   15.18 +			PATH_BUF_SIZE, NULL);
   15.19  	assert(result);
   15.20  	if (!result)
   15.21  		return NULL;
    16.1 --- a/src/sync.h	Mon Mar 27 14:53:29 2017 +0200
    16.2 +++ b/src/sync.h	Tue Jun 06 18:00:40 2017 +0200
    16.3 @@ -203,7 +203,7 @@
    16.4  
    16.5  #include "message.h"
    16.6  #include "sync_fsm.h"
    16.7 -
    16.8 +#include "sync_app.h"
    16.9  
   16.10  // this module is for being used WITHOUT the Transport API in transport.h
   16.11  // DO NOT USE IT WHEN USING Transport API!
   16.12 @@ -227,28 +227,6 @@
   16.13  
   16.14  typedef PEP_STATUS (*messageToSend_t)(void *obj, message *msg);
   16.15  
   16.16 -// TODO add this to generated code.
   16.17 -typedef enum _sync_handshake_signal {
   16.18 -    SYNC_NOTIFY_UNDEFINED = 0,
   16.19 -
   16.20 -    // request show handshake dialog
   16.21 -    SYNC_NOTIFY_INIT_ADD_OUR_DEVICE,
   16.22 -    SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE,
   16.23 -    SYNC_NOTIFY_INIT_FORM_GROUP,
   16.24 -    SYNC_NOTIFY_INIT_MOVE_OUR_DEVICE,
   16.25 -
   16.26 -    // handshake process timed out
   16.27 -    SYNC_NOTIFY_TIMEOUT,
   16.28 -
   16.29 -    // handshake accepted by user
   16.30 -    SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED,
   16.31 -    SYNC_NOTIFY_ACCEPTED_GROUP_CREATED,
   16.32 -    SYNC_NOTIFY_ACCEPTED_DEVICE_MOVED,
   16.33 -
   16.34 -    // handshake dialog must be closed
   16.35 -    SYNC_NOTIFY_OVERTAKEN
   16.36 -} sync_handshake_signal;
   16.37 -
   16.38  // notifyHandshake() - notify UI about sync handshaking process
   16.39  //
   16.40  //  parameters:
   16.41 @@ -309,11 +287,12 @@
   16.42  //  parameters:
   16.43  //      management (in)     application defined
   16.44  //      timeout (in,out)    do not wait longer than timeout for message
   16.45 +//                          timeout == NULL or *timeout == 0 is blocking
   16.46  //
   16.47  //  return value:
   16.48 -//      next message or :
   16.49 -//      NULL and timeout == 0 for termination
   16.50 -//      NULL and timeout != 0 for timeout occurence
   16.51 +//      next message, then timeout[out] == remaining time
   16.52 +//      NULL and timeout[out] != 0 for timeout occurence
   16.53 +//      NULL and timeout[out] == 0 for termination
   16.54  
   16.55  typedef void *(*retrieve_next_sync_msg_t)(void *management, time_t *timeout);
   16.56  
    17.1 --- a/src/sync_actions.c	Mon Mar 27 14:53:29 2017 +0200
    17.2 +++ b/src/sync_actions.c	Tue Jun 06 18:00:40 2017 +0200
    17.3 @@ -105,6 +105,23 @@
    17.4      return 1;
    17.5  }
    17.6  
    17.7 +int sameKeyAndAddress(PEP_SESSION session, Identity a, Identity b)
    17.8 +{
    17.9 +    assert(session);
   17.10 +    assert(a);
   17.11 +    assert(b);
   17.12 +
   17.13 +    if (!(session && a && b))
   17.14 +        return invalid_condition; // error
   17.15 +
   17.16 +    if (a->fpr == NULL || b->fpr == NULL ||
   17.17 +        (!_same_fpr(a->fpr, strlen(a->fpr), b->fpr, strlen(b->fpr))) ||
   17.18 +        a->address == NULL || b->address == NULL ||
   17.19 +        strcmp(a->address, b->address) != 0)
   17.20 +            return 0;
   17.21 +    return 1;
   17.22 +}
   17.23 +
   17.24  // actions
   17.25  
   17.26  PEP_STATUS _notifyHandshake(
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/src/sync_app.h	Tue Jun 06 18:00:40 2017 +0200
    18.3 @@ -0,0 +1,34 @@
    18.4 +//
    18.5 +//  sync_app.h
    18.6 +//  pEpEngine
    18.7 +//
    18.8 +//  Created by Dirk Zimmermann on 16.05.17.
    18.9 +//  Copyright © 2017 Edouard Tisserant. All rights reserved.
   18.10 +//
   18.11 +
   18.12 +#ifndef sync_app_h
   18.13 +#define sync_app_h
   18.14 +
   18.15 +// TODO add this to generated code.
   18.16 +typedef enum _sync_handshake_signal {
   18.17 +    SYNC_NOTIFY_UNDEFINED = 0,
   18.18 +
   18.19 +    // request show handshake dialog
   18.20 +    SYNC_NOTIFY_INIT_ADD_OUR_DEVICE,
   18.21 +    SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE,
   18.22 +    SYNC_NOTIFY_INIT_FORM_GROUP,
   18.23 +    SYNC_NOTIFY_INIT_MOVE_OUR_DEVICE,
   18.24 +
   18.25 +    // handshake process timed out
   18.26 +    SYNC_NOTIFY_TIMEOUT,
   18.27 +
   18.28 +    // handshake accepted by user
   18.29 +    SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED,
   18.30 +    SYNC_NOTIFY_ACCEPTED_GROUP_CREATED,
   18.31 +    SYNC_NOTIFY_ACCEPTED_DEVICE_MOVED,
   18.32 +
   18.33 +    // handshake dialog must be closed
   18.34 +    SYNC_NOTIFY_OVERTAKEN
   18.35 +} sync_handshake_signal;
   18.36 +
   18.37 +#endif /* sync_app_h */
    19.1 --- a/sync/Makefile	Mon Mar 27 14:53:29 2017 +0200
    19.2 +++ b/sync/Makefile	Tue Jun 06 18:00:40 2017 +0200
    19.3 @@ -13,10 +13,10 @@
    19.4  	touch .codegen
    19.5  
    19.6  .actions: devicegroup.fsm gen_actions.ysl2 fsm.yml2 functions.ysl2
    19.7 -	$(YML2PROC) -y gen_actions.ysl2 $< -o $@
    19.8 +	$(YML2PROC) $(YML_OPTS) -y gen_actions.ysl2 $< -o $@
    19.9  
   19.10  .statemachines: devicegroup.fsm gen_statemachine.ysl2 fsm.yml2 functions.ysl2
   19.11 -	$(YML2PROC) -y gen_statemachine.ysl2 $< -o $@
   19.12 +	$(YML2PROC) $(YML_OPTS) -y gen_statemachine.ysl2 $< -o $@
   19.13  
   19.14  .PHONY: clean
   19.15  
   19.16 @@ -29,7 +29,7 @@
   19.17  	yml2c $< -o $@
   19.18  
   19.19  %.dot: devicegroup.fsm gen_dot.ysl2
   19.20 -	yml2proc -y gen_dot.ysl2 $<
   19.21 +	$(YML2PROC) $(YML_OPTS) -y gen_dot.ysl2 $<
   19.22  
   19.23  %.svg: %.dot
   19.24  	dot -Tsvg -o $@ $<
    20.1 --- a/sync/devicegroup.fsm	Mon Mar 27 14:53:29 2017 +0200
    20.2 +++ b/sync/devicegroup.fsm	Tue Jun 06 18:00:40 2017 +0200
    20.3 @@ -21,6 +21,7 @@
    20.4          condition deviceGrouped();
    20.5          condition keyElectionWon(Identity partner);
    20.6          condition sameIdentities(Identity a, Identity b);
    20.7 +        condition sameKeyAndAddress(Identity a, Identity b);
    20.8  
    20.9          state InitState {
   20.10              on Init {
   20.11 @@ -31,10 +32,14 @@
   20.12          }
   20.13  
   20.14          state Sole end=1 {
   20.15 -            on KeyGen
   20.16 +            on KeyGen {
   20.17                  do sendBeacon;
   20.18 -            on CannotDecrypt
   20.19 +                go SoleWaiting;
   20.20 +            }
   20.21 +            on CannotDecrypt {
   20.22                  do sendBeacon;
   20.23 +                go SoleWaiting;
   20.24 +            }
   20.25              on Beacon(Identity partner){
   20.26                  do sendHandshakeRequest(partner);
   20.27                  go SoleBeaconed(partner);
   20.28 @@ -45,6 +50,26 @@
   20.29              }
   20.30          }
   20.31  
   20.32 +        // copy of sole state with a timeout to enable fast polling for a second
   20.33 +        // TODO use more YSLT power here (substates ?) 
   20.34 +        state SoleWaiting timeout=60 {
   20.35 +            on KeyGen {
   20.36 +                do sendBeacon;
   20.37 +            }
   20.38 +            on CannotDecrypt {
   20.39 +                do sendBeacon;
   20.40 +            }
   20.41 +            on Beacon(Identity partner){
   20.42 +                do sendHandshakeRequest(partner);
   20.43 +                go SoleBeaconed(partner);
   20.44 +            }
   20.45 +            on HandshakeRequest(Identity partner) {
   20.46 +                do sendHandshakeRequest(partner);
   20.47 +                go HandshakingSole(partner);
   20.48 +            }
   20.49 +            on Timeout go Sole;
   20.50 +        }
   20.51 +
   20.52          state SoleBeaconed timeout=600 (Identity expected) {
   20.53              on KeyGen{
   20.54                  do sendBeacon;
   20.55 @@ -71,10 +96,10 @@
   20.56  
   20.57          state HandshakingSole timeout=600 (Identity expected) {
   20.58              on Init{
   20.59 -                if keyElectionWon(partner) {
   20.60 -                    do notifyInitFormGroup(partner);
   20.61 +                if keyElectionWon(expected) {
   20.62 +                    do notifyInitFormGroup(expected);
   20.63                  } else {
   20.64 -                    do notifyInitAddOurDevice(partner);
   20.65 +                    do notifyInitAddOurDevice(expected);
   20.66                  }
   20.67              }
   20.68              on HandshakeRejected(Identity partner) {
   20.69 @@ -97,10 +122,11 @@
   20.70              }
   20.71              on Cancel go Sole;
   20.72              on GroupKeys(Identity partner, GroupKeys groupkeys) {
   20.73 -                if keyElectionWon(partner) {
   20.74 -                    // not suppose to receive groupkeys - ignore
   20.75 +                if keyElectionWon(expected) {
   20.76 +                    // not supposed to receive groupkeys - ignore
   20.77                  } else {
   20.78 -                    if sameIdentities(partner, expected) {
   20.79 +                    // UUID changes in between, so we can only check for same address and fpr
   20.80 +                    if sameKeyAndAddress(partner, expected) {
   20.81                          go WaitForAcceptSole(partner, groupkeys);
   20.82                      }
   20.83                  }
   20.84 @@ -114,7 +140,8 @@
   20.85      
   20.86          state WaitForGroupKeysSole timeout=600 (Identity expected) {
   20.87              on GroupKeys(Identity partner, GroupKeys groupkeys) {
   20.88 -                if sameIdentities(partner, expected) {
   20.89 +                // UUID changes in between, so we can only check for same address and fpr
   20.90 +                if sameKeyAndAddress(partner, expected) {
   20.91                      do storeGroupKeys(partner, groupkeys);
   20.92                      do sendGroupUpdate;
   20.93                      do renewUUID;
   20.94 @@ -134,7 +161,8 @@
   20.95                  go Sole;
   20.96              }
   20.97              on HandshakeAccepted(Identity partner) {
   20.98 -                if sameIdentities(partner, expected) {
   20.99 +                // UUID changes in between, so we can only check for same address and fpr
  20.100 +                if sameKeyAndAddress(partner, expected) {
  20.101                      do acceptHandshake(partner); 
  20.102                      do storeGroupKeys(partner, groupkeys);
  20.103                      do sendGroupUpdate;
  20.104 @@ -157,6 +185,7 @@
  20.105              on CannotDecrypt {
  20.106                  do sendUpdateRequest;
  20.107                  do sendBeacon;
  20.108 +                go GroupWaiting;
  20.109              }
  20.110              on UpdateRequest
  20.111                  do sendGroupUpdate;
  20.112 @@ -172,6 +201,29 @@
  20.113                  do storeGroupUpdate(partner, keys);
  20.114          }
  20.115  
  20.116 +        // copy of grouped state, with a timeout to enable fast poling for a minut
  20.117 +        state GroupWaiting timeout=60 {
  20.118 +            on KeyGen
  20.119 +                do sendGroupUpdate;
  20.120 +            on CannotDecrypt {
  20.121 +                do sendUpdateRequest;
  20.122 +                do sendBeacon;
  20.123 +            }
  20.124 +            on UpdateRequest
  20.125 +                do sendGroupUpdate;
  20.126 +            on Beacon(Identity partner){
  20.127 +                do sendHandshakeRequest(partner);
  20.128 +                go GroupedBeaconed(partner);
  20.129 +            }
  20.130 +            on HandshakeRequest(Identity partner) {
  20.131 +                do sendHandshakeRequest(partner);
  20.132 +                go HandshakingGrouped(partner);
  20.133 +            }
  20.134 +            on GroupUpdate(Identity partner, IdentityList keys)
  20.135 +                do storeGroupUpdate(partner, keys);
  20.136 +            on Timeout go Grouped;
  20.137 +        }
  20.138 +
  20.139          state GroupedBeaconed timeout=600 (Identity expected){
  20.140              on KeyGen
  20.141                  do sendGroupUpdate;
  20.142 @@ -201,7 +253,7 @@
  20.143          state HandshakingGrouped timeout=600 (Identity expected) {
  20.144              // HandshakeRequest from same group are filtered in receive_sync_msg
  20.145              on Init{
  20.146 -                if keyElectionWon(partner) {
  20.147 +                if keyElectionWon(expected) {
  20.148                      do notifyInitAddOtherDevice(partner);
  20.149                  } else {
  20.150                      do notifyInitMoveOurDevice(partner);
  20.151 @@ -224,8 +276,13 @@
  20.152              }
  20.153              on Cancel go Grouped;
  20.154              on GroupKeys(Identity partner, GroupKeys groupkeys) {
  20.155 -                if sameIdentities(partner, expected) {
  20.156 -                    go WaitForAcceptGrouped(partner, groupkeys);
  20.157 +                if keyElectionWon(expected) {
  20.158 +                    // not supposed to receive groupkeys - ignore
  20.159 +                } else {
  20.160 +                    // UUID changes in between, so we can only check for same address and fpr
  20.161 +                    if sameKeyAndAddress(partner, expected) {
  20.162 +                        go WaitForAcceptGrouped(partner, groupkeys);
  20.163 +                    }
  20.164                  }
  20.165              }
  20.166              on GroupUpdate(Identity partner, IdentityList keys) {
    21.1 --- a/sync/fsm.yml2	Mon Mar 27 14:53:29 2017 +0200
    21.2 +++ b/sync/fsm.yml2	Tue Jun 06 18:00:40 2017 +0200
    21.3 @@ -14,5 +14,6 @@
    21.4  decl transition @target, go is transition;
    21.5  decl action @name, do is action;
    21.6  decl condition @name, if is condition;
    21.7 +decl alternative, else is alternative;
    21.8  decl interface @name;
    21.9  decl tag @name (id);
    22.1 --- a/sync/gen_dot.ysl2	Mon Mar 27 14:53:29 2017 +0200
    22.2 +++ b/sync/gen_dot.ysl2	Tue Jun 06 18:00:40 2017 +0200
    22.3 @@ -21,9 +21,10 @@
    22.4  
    22.5      template "event" {
    22.6          param "state";
    22.7 +        const "transitions", "transition|descendant::condition/transition|descendant::alternative/transition";
    22.8          choose {
    22.9 -            when "count(transition) > 0"
   22.10 -                apply "transition|condition/transition", 0
   22.11 +            when "count($transitions) > 0"
   22.12 +                apply "$transitions", 0
   22.13                      with "state", "$state", with "event", "@name";
   22.14              otherwise
   22.15                  if "@name != 'Init'"
    23.1 --- a/sync/gen_statemachine.ysl2	Mon Mar 27 14:53:29 2017 +0200
    23.2 +++ b/sync/gen_statemachine.ysl2	Tue Jun 06 18:00:40 2017 +0200
    23.3 @@ -231,7 +231,6 @@
    23.4          ||
    23.5  
    23.6          ||
    23.7 -            *timeout = «@timeout»;
    23.8              switch (event) {
    23.9          ||
   23.10  
   23.11 @@ -239,6 +238,7 @@
   23.12          ||
   23.13                  case Init: 
   23.14                      DEBUG_LOG("FSM event", "«../@filename»_fsm.c, state=«@name»", "event=Init") 
   23.15 +                    *timeout = «@timeout»;
   23.16                      break;
   23.17          ||
   23.18  
   23.19 @@ -300,13 +300,16 @@
   23.20          case «@name»:
   23.21          {
   23.22              DEBUG_LOG("FSM event", "«../../@filename»_fsm.c, state=«../@name»", "event=«@name»")
   23.23 +        `` if "@name='Init'" |> *timeout = «../@timeout»;
   23.24          ||
   23.25 +
   23.26          if "count(parm) > 1" {
   23.27              // TODO get ride of void *extra, pass per-event struct incl all params.
   23.28              const "extrapEpType" call "pEp_type" with "type","name(parm[2]/*[1])"; 
   23.29              const "extraArgName","name(parm[2]/*[2])"; 
   23.30              |> «$extrapEpType» «$extraArgName» = («$extrapEpType»)extra;
   23.31          }
   23.32 +
   23.33          ||
   23.34          `` apply "action|transition|condition";
   23.35          `` if "name(*[position()=last()]) != 'transition'" |> break;
   23.36 @@ -346,10 +349,10 @@
   23.37          |> if (cond_result) {
   23.38          apply "action|transition|condition";
   23.39          |> }
   23.40 -        const "else", "./following-sibling::*[position()=1][name(.)='else']";
   23.41 -        if "$else" {
   23.42 +        const "alternative", "./following-sibling::*[position()=1][name(.)='alternative']";
   23.43 +        if "$alternative" {
   23.44          |> else {
   23.45 -        apply "$else/action|$else/transition|$else/condition";
   23.46 +        apply "$alternative/action|$alternative/transition|$alternative/condition";
   23.47          |> }
   23.48          }
   23.49          | }
    24.1 --- a/sync/generated/sync_fsm.c	Mon Mar 27 14:53:29 2017 +0200
    24.2 +++ b/sync/generated/sync_fsm.c	Tue Jun 06 18:00:40 2017 +0200
    24.3 @@ -56,11 +56,11 @@
    24.4          case InitState:
    24.5          {
    24.6              DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=InitState")
    24.7 -            *timeout = 0;
    24.8              switch (event) {
    24.9                  case Init:
   24.10                  {
   24.11                      DEBUG_LOG("FSM event", "sync_fsm.c, state=InitState", "event=Init")
   24.12 +                    *timeout = 0;
   24.13                      {
   24.14                          int cond_result = deviceGrouped(session);
   24.15                          #ifndef NDEBUG
   24.16 @@ -86,10 +86,10 @@
   24.17          case Sole:
   24.18          {
   24.19              DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=Sole")
   24.20 -            *timeout = 0;
   24.21              switch (event) {
   24.22                  case Init: 
   24.23                      DEBUG_LOG("FSM event", "sync_fsm.c, state=Sole", "event=Init") 
   24.24 +                    *timeout = 0;
   24.25                      break;
   24.26                  case KeyGen:
   24.27                  {
   24.28 @@ -100,7 +100,8 @@
   24.29                          return (int) invalid_out_of_memory;
   24.30                      if (status != PEP_STATUS_OK)
   24.31                          return (int) invalid_action;
   24.32 -                    break;
   24.33 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=Sole, event=KeyGen", "target=SoleWaiting")
   24.34 +                    return SoleWaiting;
   24.35                  }
   24.36                  case CannotDecrypt:
   24.37                  {
   24.38 @@ -111,7 +112,8 @@
   24.39                          return (int) invalid_out_of_memory;
   24.40                      if (status != PEP_STATUS_OK)
   24.41                          return (int) invalid_action;
   24.42 -                    break;
   24.43 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=Sole, event=CannotDecrypt", "target=SoleWaiting")
   24.44 +                    return SoleWaiting;
   24.45                  }
   24.46                  case Beacon:
   24.47                  {
   24.48 @@ -152,16 +154,91 @@
   24.49              }
   24.50              break;
   24.51          }
   24.52 +        case SoleWaiting:
   24.53 +        {
   24.54 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=SoleWaiting")
   24.55 +            switch (event) {
   24.56 +                case Init: 
   24.57 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=Init") 
   24.58 +                    *timeout = 60;
   24.59 +                    break;
   24.60 +                case KeyGen:
   24.61 +                {
   24.62 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=KeyGen")
   24.63 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleWaiting, event=KeyGen", "action=sendBeacon")
   24.64 +                    status = sendBeacon(session, state, NULL, NULL);
   24.65 +                    if (status == PEP_OUT_OF_MEMORY)
   24.66 +                        return (int) invalid_out_of_memory;
   24.67 +                    if (status != PEP_STATUS_OK)
   24.68 +                        return (int) invalid_action;
   24.69 +                    break;
   24.70 +                }
   24.71 +                case CannotDecrypt:
   24.72 +                {
   24.73 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=CannotDecrypt")
   24.74 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleWaiting, event=CannotDecrypt", "action=sendBeacon")
   24.75 +                    status = sendBeacon(session, state, NULL, NULL);
   24.76 +                    if (status == PEP_OUT_OF_MEMORY)
   24.77 +                        return (int) invalid_out_of_memory;
   24.78 +                    if (status != PEP_STATUS_OK)
   24.79 +                        return (int) invalid_action;
   24.80 +                    break;
   24.81 +                }
   24.82 +                case Beacon:
   24.83 +                {
   24.84 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=Beacon")
   24.85 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleWaiting, event=Beacon", "action=sendHandshakeRequest")
   24.86 +                    status = sendHandshakeRequest(session, state, partner, NULL);
   24.87 +                    if (status == PEP_OUT_OF_MEMORY)
   24.88 +                        return (int) invalid_out_of_memory;
   24.89 +                    if (status != PEP_STATUS_OK)
   24.90 +                        return (int) invalid_action;
   24.91 +                    session->sync_state_payload = malloc(sizeof(SoleBeaconed_state_payload_t));
   24.92 +                    assert(session->sync_state_payload);
   24.93 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
   24.94 +                    ((SoleBeaconed_state_payload_t*)session->sync_state_payload)->expected =
   24.95 +                        identity_dup(partner);
   24.96 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleWaiting, event=Beacon", "target=SoleBeaconed")
   24.97 +                    return SoleBeaconed;
   24.98 +                }
   24.99 +                case HandshakeRequest:
  24.100 +                {
  24.101 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=HandshakeRequest")
  24.102 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleWaiting, event=HandshakeRequest", "action=sendHandshakeRequest")
  24.103 +                    status = sendHandshakeRequest(session, state, partner, NULL);
  24.104 +                    if (status == PEP_OUT_OF_MEMORY)
  24.105 +                        return (int) invalid_out_of_memory;
  24.106 +                    if (status != PEP_STATUS_OK)
  24.107 +                        return (int) invalid_action;
  24.108 +                    session->sync_state_payload = malloc(sizeof(HandshakingSole_state_payload_t));
  24.109 +                    assert(session->sync_state_payload);
  24.110 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  24.111 +                    ((HandshakingSole_state_payload_t*)session->sync_state_payload)->expected =
  24.112 +                        identity_dup(partner);
  24.113 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleWaiting, event=HandshakeRequest", "target=HandshakingSole")
  24.114 +                    return HandshakingSole;
  24.115 +                }
  24.116 +                case Timeout:
  24.117 +                {
  24.118 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=Timeout")
  24.119 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleWaiting, event=Timeout", "target=Sole")
  24.120 +                    return Sole;
  24.121 +                }
  24.122 +                default:
  24.123 +                    return (DeviceState_state) invalid_event;
  24.124 +            }
  24.125 +            break;
  24.126 +        }
  24.127          case SoleBeaconed:
  24.128          {
  24.129              DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=SoleBeaconed")
  24.130              assert(session->sync_state_payload);
  24.131              if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  24.132              Identity expected = ((SoleBeaconed_state_payload_t*)session->sync_state_payload)->expected;
  24.133 -            *timeout = 600;
  24.134              switch (event) {
  24.135                  case Init: 
  24.136                      DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleBeaconed", "event=Init") 
  24.137 +                    *timeout = 600;
  24.138                      break;
  24.139                  case KeyGen:
  24.140                  {
  24.141 @@ -277,13 +354,13 @@
  24.142              assert(session->sync_state_payload);
  24.143              if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  24.144              Identity expected = ((HandshakingSole_state_payload_t*)session->sync_state_payload)->expected;
  24.145 -            *timeout = 600;
  24.146              switch (event) {
  24.147                  case Init:
  24.148                  {
  24.149                      DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingSole", "event=Init")
  24.150 +                    *timeout = 600;
  24.151                      {
  24.152 -                        int cond_result = keyElectionWon(session, partner);
  24.153 +                        int cond_result = keyElectionWon(session, expected);
  24.154                          #ifndef NDEBUG
  24.155                          char resstr[11] = {0,};
  24.156                          snprintf(resstr,10,"result=%d",cond_result);
  24.157 @@ -293,7 +370,7 @@
  24.158                              return cond_result;
  24.159                          if (cond_result) {
  24.160                          DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=Init", "action=notifyInitFormGroup")
  24.161 -                        status = notifyInitFormGroup(session, state, partner, NULL);
  24.162 +                        status = notifyInitFormGroup(session, state, expected, NULL);
  24.163                          if (status == PEP_OUT_OF_MEMORY)
  24.164                              return (int) invalid_out_of_memory;
  24.165                          if (status != PEP_STATUS_OK)
  24.166 @@ -301,7 +378,7 @@
  24.167                          }
  24.168                          else {
  24.169                          DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=Init", "action=notifyInitAddOurDevice")
  24.170 -                        status = notifyInitAddOurDevice(session, state, partner, NULL);
  24.171 +                        status = notifyInitAddOurDevice(session, state, expected, NULL);
  24.172                          if (status == PEP_OUT_OF_MEMORY)
  24.173                              return (int) invalid_out_of_memory;
  24.174                          if (status != PEP_STATUS_OK)
  24.175 @@ -427,7 +504,7 @@
  24.176                      DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingSole", "event=GroupKeys")
  24.177                      group_keys_extra_t* groupkeys = (group_keys_extra_t*)extra;
  24.178                      {
  24.179 -                        int cond_result = keyElectionWon(session, partner);
  24.180 +                        int cond_result = keyElectionWon(session, expected);
  24.181                          #ifndef NDEBUG
  24.182                          char resstr[11] = {0,};
  24.183                          snprintf(resstr,10,"result=%d",cond_result);
  24.184 @@ -439,12 +516,12 @@
  24.185                          }
  24.186                          else {
  24.187                          {
  24.188 -                            int cond_result = sameIdentities(session, partner, expected);
  24.189 +                            int cond_result = sameKeyAndAddress(session, partner, expected);
  24.190                              #ifndef NDEBUG
  24.191                              char resstr[11] = {0,};
  24.192                              snprintf(resstr,10,"result=%d",cond_result);
  24.193                              #endif
  24.194 -                            DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingSole, event=GroupKeys, condition=sameIdentities", resstr)
  24.195 +                            DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingSole, event=GroupKeys, condition=sameKeyAndAddress", resstr)
  24.196                              if (cond_result < 0)
  24.197                                  return cond_result;
  24.198                              if (cond_result) {
  24.199 @@ -502,22 +579,22 @@
  24.200              assert(session->sync_state_payload);
  24.201              if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  24.202              Identity expected = ((WaitForGroupKeysSole_state_payload_t*)session->sync_state_payload)->expected;
  24.203 -            *timeout = 600;
  24.204              switch (event) {
  24.205                  case Init: 
  24.206                      DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysSole", "event=Init") 
  24.207 +                    *timeout = 600;
  24.208                      break;
  24.209                  case GroupKeys:
  24.210                  {
  24.211                      DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysSole", "event=GroupKeys")
  24.212                      group_keys_extra_t* groupkeys = (group_keys_extra_t*)extra;
  24.213                      {
  24.214 -                        int cond_result = sameIdentities(session, partner, expected);
  24.215 +                        int cond_result = sameKeyAndAddress(session, partner, expected);
  24.216                          #ifndef NDEBUG
  24.217                          char resstr[11] = {0,};
  24.218                          snprintf(resstr,10,"result=%d",cond_result);
  24.219                          #endif
  24.220 -                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys, condition=sameIdentities", resstr)
  24.221 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys, condition=sameKeyAndAddress", resstr)
  24.222                          if (cond_result < 0)
  24.223                              return cond_result;
  24.224                          if (cond_result) {
  24.225 @@ -585,10 +662,10 @@
  24.226              if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  24.227              Identity expected = ((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->expected;
  24.228              group_keys_extra_t* groupkeys = ((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->groupkeys;
  24.229 -            *timeout = 600;
  24.230              switch (event) {
  24.231                  case Init: 
  24.232                      DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptSole", "event=Init") 
  24.233 +                    *timeout = 600;
  24.234                      break;
  24.235                  case HandshakeRejected:
  24.236                  {
  24.237 @@ -612,12 +689,12 @@
  24.238                  {
  24.239                      DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptSole", "event=HandshakeAccepted")
  24.240                      {
  24.241 -                        int cond_result = sameIdentities(session, partner, expected);
  24.242 +                        int cond_result = sameKeyAndAddress(session, partner, expected);
  24.243                          #ifndef NDEBUG
  24.244                          char resstr[11] = {0,};
  24.245                          snprintf(resstr,10,"result=%d",cond_result);
  24.246                          #endif
  24.247 -                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=WaitForAcceptSole, event=HandshakeAccepted, condition=sameIdentities", resstr)
  24.248 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=WaitForAcceptSole, event=HandshakeAccepted, condition=sameKeyAndAddress", resstr)
  24.249                          if (cond_result < 0)
  24.250                              return cond_result;
  24.251                          if (cond_result) {
  24.252 @@ -708,10 +785,10 @@
  24.253          case Grouped:
  24.254          {
  24.255              DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=Grouped")
  24.256 -            *timeout = 0;
  24.257              switch (event) {
  24.258                  case Init: 
  24.259                      DEBUG_LOG("FSM event", "sync_fsm.c, state=Grouped", "event=Init") 
  24.260 +                    *timeout = 0;
  24.261                      break;
  24.262                  case KeyGen:
  24.263                  {
  24.264 @@ -739,7 +816,8 @@
  24.265                          return (int) invalid_out_of_memory;
  24.266                      if (status != PEP_STATUS_OK)
  24.267                          return (int) invalid_action;
  24.268 -                    break;
  24.269 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=Grouped, event=CannotDecrypt", "target=GroupWaiting")
  24.270 +                    return GroupWaiting;
  24.271                  }
  24.272                  case UpdateRequest:
  24.273                  {
  24.274 @@ -803,16 +881,120 @@
  24.275              }
  24.276              break;
  24.277          }
  24.278 +        case GroupWaiting:
  24.279 +        {
  24.280 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=GroupWaiting")
  24.281 +            switch (event) {
  24.282 +                case Init: 
  24.283 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=Init") 
  24.284 +                    *timeout = 60;
  24.285 +                    break;
  24.286 +                case KeyGen:
  24.287 +                {
  24.288 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=KeyGen")
  24.289 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=KeyGen", "action=sendGroupUpdate")
  24.290 +                    status = sendGroupUpdate(session, state, NULL, NULL);
  24.291 +                    if (status == PEP_OUT_OF_MEMORY)
  24.292 +                        return (int) invalid_out_of_memory;
  24.293 +                    if (status != PEP_STATUS_OK)
  24.294 +                        return (int) invalid_action;
  24.295 +                    break;
  24.296 +                }
  24.297 +                case CannotDecrypt:
  24.298 +                {
  24.299 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=CannotDecrypt")
  24.300 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=CannotDecrypt", "action=sendUpdateRequest")
  24.301 +                    status = sendUpdateRequest(session, state, NULL, NULL);
  24.302 +                    if (status == PEP_OUT_OF_MEMORY)
  24.303 +                        return (int) invalid_out_of_memory;
  24.304 +                    if (status != PEP_STATUS_OK)
  24.305 +                        return (int) invalid_action;
  24.306 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=CannotDecrypt", "action=sendBeacon")
  24.307 +                    status = sendBeacon(session, state, NULL, NULL);
  24.308 +                    if (status == PEP_OUT_OF_MEMORY)
  24.309 +                        return (int) invalid_out_of_memory;
  24.310 +                    if (status != PEP_STATUS_OK)
  24.311 +                        return (int) invalid_action;
  24.312 +                    break;
  24.313 +                }
  24.314 +                case UpdateRequest:
  24.315 +                {
  24.316 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=UpdateRequest")
  24.317 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=UpdateRequest", "action=sendGroupUpdate")
  24.318 +                    status = sendGroupUpdate(session, state, NULL, NULL);
  24.319 +                    if (status == PEP_OUT_OF_MEMORY)
  24.320 +                        return (int) invalid_out_of_memory;
  24.321 +                    if (status != PEP_STATUS_OK)
  24.322 +                        return (int) invalid_action;
  24.323 +                    break;
  24.324 +                }
  24.325 +                case Beacon:
  24.326 +                {
  24.327 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=Beacon")
  24.328 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=Beacon", "action=sendHandshakeRequest")
  24.329 +                    status = sendHandshakeRequest(session, state, partner, NULL);
  24.330 +                    if (status == PEP_OUT_OF_MEMORY)
  24.331 +                        return (int) invalid_out_of_memory;
  24.332 +                    if (status != PEP_STATUS_OK)
  24.333 +                        return (int) invalid_action;
  24.334 +                    session->sync_state_payload = malloc(sizeof(GroupedBeaconed_state_payload_t));
  24.335 +                    assert(session->sync_state_payload);
  24.336 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  24.337 +                    ((GroupedBeaconed_state_payload_t*)session->sync_state_payload)->expected =
  24.338 +                        identity_dup(partner);
  24.339 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=GroupWaiting, event=Beacon", "target=GroupedBeaconed")
  24.340 +                    return GroupedBeaconed;
  24.341 +                }
  24.342 +                case HandshakeRequest:
  24.343 +                {
  24.344 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=HandshakeRequest")
  24.345 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=HandshakeRequest", "action=sendHandshakeRequest")
  24.346 +                    status = sendHandshakeRequest(session, state, partner, NULL);
  24.347 +                    if (status == PEP_OUT_OF_MEMORY)
  24.348 +                        return (int) invalid_out_of_memory;
  24.349 +                    if (status != PEP_STATUS_OK)
  24.350 +                        return (int) invalid_action;
  24.351 +                    session->sync_state_payload = malloc(sizeof(HandshakingGrouped_state_payload_t));
  24.352 +                    assert(session->sync_state_payload);
  24.353 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  24.354 +                    ((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected =
  24.355 +                        identity_dup(partner);
  24.356 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=GroupWaiting, event=HandshakeRequest", "target=HandshakingGrouped")
  24.357 +                    return HandshakingGrouped;
  24.358 +                }
  24.359 +                case GroupUpdate:
  24.360 +                {
  24.361 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=GroupUpdate")
  24.362 +                    identity_list* keys = (identity_list*)extra;
  24.363 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=GroupUpdate", "action=storeGroupUpdate")
  24.364 +                    status = storeGroupUpdate(session, state, partner, keys);
  24.365 +                    if (status == PEP_OUT_OF_MEMORY)
  24.366 +                        return (int) invalid_out_of_memory;
  24.367 +                    if (status != PEP_STATUS_OK)
  24.368 +                        return (int) invalid_action;
  24.369 +                    break;
  24.370 +                }
  24.371 +                case Timeout:
  24.372 +                {
  24.373 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=Timeout")
  24.374 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=GroupWaiting, event=Timeout", "target=Grouped")
  24.375 +                    return Grouped;
  24.376 +                }
  24.377 +                default:
  24.378 +                    return (DeviceState_state) invalid_event;
  24.379 +            }
  24.380 +            break;
  24.381 +        }
  24.382          case GroupedBeaconed:
  24.383          {
  24.384              DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=GroupedBeaconed")
  24.385              assert(session->sync_state_payload);
  24.386              if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  24.387              Identity expected = ((GroupedBeaconed_state_payload_t*)session->sync_state_payload)->expected;
  24.388 -            *timeout = 600;
  24.389              switch (event) {
  24.390                  case Init: 
  24.391                      DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=Init") 
  24.392 +                    *timeout = 600;
  24.393                      break;
  24.394                  case KeyGen:
  24.395                  {
  24.396 @@ -945,13 +1127,13 @@
  24.397              assert(session->sync_state_payload);
  24.398              if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  24.399              Identity expected = ((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected;
  24.400 -            *timeout = 600;
  24.401              switch (event) {
  24.402                  case Init:
  24.403                  {
  24.404                      DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingGrouped", "event=Init")
  24.405 +                    *timeout = 600;
  24.406                      {
  24.407 -                        int cond_result = keyElectionWon(session, partner);
  24.408 +                        int cond_result = keyElectionWon(session, expected);
  24.409                          #ifndef NDEBUG
  24.410                          char resstr[11] = {0,};
  24.411                          snprintf(resstr,10,"result=%d",cond_result);
  24.412 @@ -1076,29 +1258,43 @@
  24.413                      DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingGrouped", "event=GroupKeys")
  24.414                      group_keys_extra_t* groupkeys = (group_keys_extra_t*)extra;
  24.415                      {
  24.416 -                        int cond_result = sameIdentities(session, partner, expected);
  24.417 +                        int cond_result = keyElectionWon(session, expected);
  24.418                          #ifndef NDEBUG
  24.419                          char resstr[11] = {0,};
  24.420                          snprintf(resstr,10,"result=%d",cond_result);
  24.421                          #endif
  24.422 -                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingGrouped, event=GroupKeys, condition=sameIdentities", resstr)
  24.423 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingGrouped, event=GroupKeys, condition=keyElectionWon", resstr)
  24.424                          if (cond_result < 0)
  24.425                              return cond_result;
  24.426                          if (cond_result) {
  24.427 -                        assert(session->sync_state_payload);
  24.428 -                        if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  24.429 -                        free_identity(((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected);
  24.430 -                        free(session->sync_state_payload);
  24.431 -                        session->sync_state_payload = NULL;
  24.432 -                        session->sync_state_payload = malloc(sizeof(WaitForAcceptGrouped_state_payload_t));
  24.433 -                        assert(session->sync_state_payload);
  24.434 -                        if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  24.435 -                        ((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->expected =
  24.436 -                            identity_dup(partner);
  24.437 -                        ((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->groupkeys =
  24.438 -                            group_keys_extra_dup(groupkeys);
  24.439 -                        DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingGrouped, event=GroupKeys", "target=WaitForAcceptGrouped")
  24.440 -                        return WaitForAcceptGrouped;
  24.441 +                        }
  24.442 +                        else {
  24.443 +                        {
  24.444 +                            int cond_result = sameKeyAndAddress(session, partner, expected);
  24.445 +                            #ifndef NDEBUG
  24.446 +                            char resstr[11] = {0,};
  24.447 +                            snprintf(resstr,10,"result=%d",cond_result);
  24.448 +                            #endif
  24.449 +                            DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingGrouped, event=GroupKeys, condition=sameKeyAndAddress", resstr)
  24.450 +                            if (cond_result < 0)
  24.451 +                                return cond_result;
  24.452 +                            if (cond_result) {
  24.453 +                            assert(session->sync_state_payload);
  24.454 +                            if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  24.455 +                            free_identity(((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected);
  24.456 +                            free(session->sync_state_payload);
  24.457 +                            session->sync_state_payload = NULL;
  24.458 +                            session->sync_state_payload = malloc(sizeof(WaitForAcceptGrouped_state_payload_t));
  24.459 +                            assert(session->sync_state_payload);
  24.460 +                            if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
  24.461 +                            ((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->expected =
  24.462 +                                identity_dup(partner);
  24.463 +                            ((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->groupkeys =
  24.464 +                                group_keys_extra_dup(groupkeys);
  24.465 +                            DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingGrouped, event=GroupKeys", "target=WaitForAcceptGrouped")
  24.466 +                            return WaitForAcceptGrouped;
  24.467 +                            }
  24.468 +                        }
  24.469                          }
  24.470                      }
  24.471                      break;
  24.472 @@ -1155,10 +1351,10 @@
  24.473              assert(session->sync_state_payload);
  24.474              if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  24.475              Identity expected = ((WaitForGroupKeysGrouped_state_payload_t*)session->sync_state_payload)->expected;
  24.476 -            *timeout = 600;
  24.477              switch (event) {
  24.478                  case Init: 
  24.479                      DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysGrouped", "event=Init") 
  24.480 +                    *timeout = 600;
  24.481                      break;
  24.482                  case GroupKeys:
  24.483                  {
  24.484 @@ -1262,10 +1458,10 @@
  24.485              if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  24.486              Identity expected = ((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->expected;
  24.487              group_keys_extra_t* groupkeys = ((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->groupkeys;
  24.488 -            *timeout = 600;
  24.489              switch (event) {
  24.490                  case Init: 
  24.491                      DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptGrouped", "event=Init") 
  24.492 +                    *timeout = 600;
  24.493                      break;
  24.494                  case HandshakeRejected:
  24.495                  {
    25.1 --- a/sync/generated/sync_fsm.h	Mon Mar 27 14:53:29 2017 +0200
    25.2 +++ b/sync/generated/sync_fsm.h	Tue Jun 06 18:00:40 2017 +0200
    25.3 @@ -32,6 +32,7 @@
    25.4  int deviceGrouped(PEP_SESSION session);
    25.5  int keyElectionWon(PEP_SESSION session, Identity partner);
    25.6  int sameIdentities(PEP_SESSION session, Identity a, Identity b);
    25.7 +int sameKeyAndAddress(PEP_SESSION session, Identity a, Identity b);
    25.8  
    25.9  // states
   25.10  
   25.11 @@ -46,11 +47,13 @@
   25.12      DeviceState_state_NONE = 0,
   25.13      InitState, 
   25.14      Sole, 
   25.15 +    SoleWaiting, 
   25.16      SoleBeaconed, 
   25.17      HandshakingSole, 
   25.18      WaitForGroupKeysSole, 
   25.19      WaitForAcceptSole, 
   25.20      Grouped, 
   25.21 +    GroupWaiting, 
   25.22      GroupedBeaconed, 
   25.23      HandshakingGrouped, 
   25.24      WaitForGroupKeysGrouped, 
    26.1 --- a/sync/skeletons/sync_actions.c	Mon Mar 27 14:53:29 2017 +0200
    26.2 +++ b/sync/skeletons/sync_actions.c	Tue Jun 06 18:00:40 2017 +0200
    26.3 @@ -28,8 +28,8 @@
    26.4      PEP_STATUS status = PEP_STATUS_OK;
    26.5  
    26.6      assert(session);
    26.7 -    assert(partner);
    26.8 -    if (!(session && partner))
    26.9 +    assert(!partner);
   26.10 +    if (!(session && !partner))
   26.11          return PEP_ILLEGAL_VALUE;
   26.12  
   26.13      // working code
   26.14 @@ -65,8 +65,8 @@
   26.15      PEP_STATUS status = PEP_STATUS_OK;
   26.16  
   26.17      assert(session);
   26.18 -    assert(partner);
   26.19 -    if (!(session && partner))
   26.20 +    assert(!partner);
   26.21 +    if (!(session && !partner))
   26.22          return PEP_ILLEGAL_VALUE;
   26.23  
   26.24      // working code
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/test/external_revoke_test.cc	Tue Jun 06 18:00:40 2017 +0200
    27.3 @@ -0,0 +1,328 @@
    27.4 +// This file is under GNU General Public License 3.0
    27.5 +// see LICENSE.txt
    27.6 +
    27.7 +#include <stdlib.h>
    27.8 +#include <string.h>
    27.9 +#include <time.h>
   27.10 +#include "platform.h"
   27.11 +#include <iostream>
   27.12 +#include <fstream>
   27.13 +#include <assert.h>
   27.14 +#include "mime.h"
   27.15 +#include "message_api.h"
   27.16 +#include "test_util.h"
   27.17 +
   27.18 +using namespace std;
   27.19 +
   27.20 +int main() {
   27.21 +    cout << "\n*** external_revoke_test.cc ***\n\n";
   27.22 +
   27.23 +    PEP_SESSION session;
   27.24 +    
   27.25 +    cout << "calling init()\n";
   27.26 +    PEP_STATUS status = init(&session);   
   27.27 +    assert(status == PEP_STATUS_OK);
   27.28 +    assert(session);
   27.29 +    cout << "init() completed.\n";
   27.30 +
   27.31 +#ifndef NETPGP
   27.32 +    char* fprs[2];
   27.33 +
   27.34 +    const string fenris_pub_key = slurp("test_keys/pub/pep.test.fenris-0x6DBA13DA_pub.asc");
   27.35 +    const string fenris_priv_key = slurp("test_keys/priv/pep.test.fenris-0x6DBA13DA_priv.asc");
   27.36 +
   27.37 +    PEP_STATUS statuspub = import_key(session, fenris_pub_key.c_str(), fenris_pub_key.length(), NULL);
   27.38 +    PEP_STATUS statuspriv = import_key(session, fenris_priv_key.c_str(), fenris_priv_key.length(), NULL);
   27.39 +    assert(statuspub == PEP_STATUS_OK);
   27.40 +    assert(statuspriv == PEP_STATUS_OK);
   27.41 +
   27.42 +    // Create sender ID
   27.43 +    
   27.44 +    pEp_identity * me = new_identity("pep.test.fenris@notrealemail.eu", NULL, PEP_OWN_USERID, "Fenris Hawke");
   27.45 +    status = update_identity(session, me);
   27.46 +    status = trust_personal_key(session, me);
   27.47 +    status = update_identity(session, me);
   27.48 +    
   27.49 +    // Create key
   27.50 +
   27.51 +    cout << "Creating new id for : ";
   27.52 +    char *uniqname = strdup("AAAAtestuser@testdomain.org");
   27.53 +    srandom(time(NULL));
   27.54 +    for(int i=0; i < 4;i++)
   27.55 +        uniqname[i] += random() & 0xf;
   27.56 +    
   27.57 +    cout << uniqname << "\n";
   27.58 +    pEp_identity * recip1 = new_identity(uniqname, NULL, NULL, "Test User");
   27.59 +
   27.60 +    status = generate_keypair(session, recip1);
   27.61 +    
   27.62 +    cout << "Generated fingerprint ";
   27.63 +    cout << recip1->fpr << "\n";
   27.64 +
   27.65 +    fprs[0] = strdup(recip1->fpr);
   27.66 +    
   27.67 +    cout << endl << "*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*" << endl;
   27.68 +    cout << "Trust and revoke single key, ensure trust changes, then generate new key and ensure rating is correct." << endl;
   27.69 +    cout << "*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*" << endl << endl;
   27.70 +    
   27.71 +    cout << endl << "---------------------------------------------------------" << endl;
   27.72 +    cout << "1a. Encrypt message for trusted partner." << endl;
   27.73 +    cout << "---------------------------------------------------------" << endl << endl;
   27.74 +
   27.75 +    cout << "Trusting personal key for " << uniqname << endl;
   27.76 +    // Trust it
   27.77 +    recip1->me = false;
   27.78 +    status = update_identity(session, recip1);
   27.79 +    status = trust_personal_key(session, recip1);
   27.80 +    status = update_identity(session, recip1);
   27.81 +    
   27.82 +    // TODO: Check trust?
   27.83 +    cout << "Done! Trusted personal key with fpr " << recip1->fpr << " for " << uniqname << endl;
   27.84 +
   27.85 +    const char* r1_userid = (recip1->user_id ? strdup(recip1->user_id) : NULL);
   27.86 +
   27.87 +    
   27.88 +    // encrypt something to the key
   27.89 +    cout << "Creating message…\n";
   27.90 +    identity_list* to_list = new_identity_list(identity_dup(recip1)); // to bob
   27.91 +    message* outgoing_msg = new_message(PEP_dir_outgoing);
   27.92 +    assert(outgoing_msg);
   27.93 +    outgoing_msg->from = identity_dup(me);
   27.94 +    outgoing_msg->to = to_list;
   27.95 +    outgoing_msg->shortmsg = strdup("Greetings, humans!");
   27.96 +    outgoing_msg->longmsg = strdup("This is a test of the emergency message system. This is only a test. BEEP.");
   27.97 +    outgoing_msg->attachments = new_bloblist(NULL, 0, "application/octet-stream", NULL);
   27.98 +    cout << "Message created.\n";
   27.99 +
  27.100 +    message* encrypted_outgoing_msg = NULL;
  27.101 +
  27.102 +    cout << "Encrypting message to " << uniqname << "…\n";    
  27.103 +    status = encrypt_message(session, outgoing_msg, NULL, &encrypted_outgoing_msg, PEP_enc_PGP_MIME, 0);
  27.104 +    cout << "Encrypted message with status " << tl_status_string(status) << endl;
  27.105 +    // check status
  27.106 +    assert(status == PEP_STATUS_OK);
  27.107 +    assert(encrypted_outgoing_msg);
  27.108 +
  27.109 +    cout << "Checking message recipient comm_type from message." << endl;
  27.110 +    // check comm_type
  27.111 +    cout << "comm_type: " << tl_ct_string(encrypted_outgoing_msg->to->ident->comm_type) << endl;
  27.112 +    assert(encrypted_outgoing_msg->to->ident->comm_type == PEP_ct_OpenPGP);
  27.113 +    
  27.114 +    status = get_trust(session, recip1);
  27.115 +    
  27.116 +    cout << "Recip's trust DB comm_type = " << hex << tl_ct_string(recip1->comm_type) << endl;
  27.117 +    assert(recip1->comm_type == PEP_ct_OpenPGP); // FIXME: PEP_ct_pEp???
  27.118 +
  27.119 +    // decrypt message
  27.120 +    free_message(outgoing_msg);
  27.121 +    outgoing_msg = NULL;
  27.122 +
  27.123 +    stringlist_t* keylist = nullptr;
  27.124 +    PEP_rating rating;
  27.125 +    PEP_decrypt_flags_t flags;
  27.126 +
  27.127 +    cout << endl << "---------------------------------------------------------" << endl;
  27.128 +    cout << "1b. Decrypt message that was encrypted for trusted partner." << endl;
  27.129 +    cout << "---------------------------------------------------------" << endl << endl;
  27.130 +
  27.131 +    cout << "Decrypting message." << endl;
  27.132 +    status = decrypt_message(session, encrypted_outgoing_msg, &outgoing_msg, &keylist, &rating, &flags);
  27.133 +    cout << "Decrypted message with status " << tl_status_string(status) << endl;
  27.134 +    assert(status == PEP_STATUS_OK);
  27.135 +    assert(rating == PEP_rating_trusted);
  27.136 +
  27.137 +    // check rating
  27.138 +    cout << "Rating of decrypted message to trusted recip: " << tl_rating_string(rating) << endl;
  27.139 +    assert(rating == PEP_rating_trusted); // FIXME: trusted and anonymised?
  27.140 +    
  27.141 +    // check comm_type
  27.142 +    status = get_trust(session, recip1);
  27.143 +
  27.144 +    cout << "Recip's trust DB comm_type = " << tl_ct_string(recip1->comm_type) << endl;
  27.145 +    assert(recip1->comm_type == PEP_ct_OpenPGP); // FIXME: PEP_ct_pEp???
  27.146 +
  27.147 +    cout << endl << "---------------------------------------------------------" << endl;
  27.148 +    cout << "2a. Revoke key for (currently) trusted partner." << endl;
  27.149 +    cout << "---------------------------------------------------------" << endl << endl;
  27.150 +    // externally revoke key
  27.151 +    // (note - as of 23.5.17, revoke_key() doesn't touch the trust db, just the keyring, so we can do this)
  27.152 +
  27.153 +    cout << "Revoking key." << endl;
  27.154 +    status = get_identity(session, uniqname, r1_userid, &recip1);    
  27.155 +    status = revoke_key(session, recip1->fpr, "encrypt_for_identity_test");
  27.156 +    cout << "Status of revocation call for " << recip1->fpr << " is "<< tl_status_string(status) << endl;
  27.157 +
  27.158 +    // free messages
  27.159 +    free_message(outgoing_msg);
  27.160 +    free_message(encrypted_outgoing_msg);
  27.161 +    outgoing_msg = NULL;
  27.162 +    encrypted_outgoing_msg = NULL;
  27.163 +    
  27.164 +    // encrypt something to the key
  27.165 +    cout << "creating message…\n";
  27.166 +    to_list = new_identity_list(identity_dup(recip1)); // to bob
  27.167 +    outgoing_msg = new_message(PEP_dir_outgoing);
  27.168 +    assert(outgoing_msg);
  27.169 +    outgoing_msg->from = identity_dup(me);
  27.170 +    outgoing_msg->to = to_list;
  27.171 +    outgoing_msg->shortmsg = strdup("Greetings, humans!");
  27.172 +    outgoing_msg->longmsg = strdup("This is a test of the emergency message system. This is only a test. BEEP.");
  27.173 +    outgoing_msg->attachments = new_bloblist(NULL, 0, "application/octet-stream", NULL);
  27.174 +    cout << "message created.\n";
  27.175 +
  27.176 +    encrypted_outgoing_msg = NULL;
  27.177 +    message* decrypted_msg = NULL;
  27.178 +
  27.179 +    cout << endl << "---------------------------------------------------------" << endl;
  27.180 +    cout << "2b. Encrypt message for recip whose key has been externally revoked in the keyring, not the app." << endl;
  27.181 +    cout << "---------------------------------------------------------" << endl << endl;
  27.182 +
  27.183 +    status = encrypt_message(session, outgoing_msg, NULL, &encrypted_outgoing_msg, PEP_enc_PGP_MIME, 0);
  27.184 +    cout << "Encryption returns with status " << tl_status_string(status) << endl;
  27.185 +
  27.186 +    PEP_comm_type ct = (encrypted_outgoing_msg ? encrypted_outgoing_msg->to->ident->comm_type : outgoing_msg->to->ident->comm_type);
  27.187 +
  27.188 +    cout << endl << "---------------------------------------------------------" << endl;
  27.189 +    cout << "2c. Check trust of recip, whose only key has been revoked, once an encryption attempt has been made." << endl;
  27.190 +    cout << "---------------------------------------------------------" << endl << endl;
  27.191 +
  27.192 +    // check comm_type
  27.193 +    cout << "comm_type: " << tl_ct_string(ct) << endl;
  27.194 +    assert(ct == PEP_ct_key_revoked);
  27.195 +    
  27.196 +    status = get_trust(session, recip1);
  27.197 +
  27.198 +    cout << "Recip's trust DB comm_type = " << hex << tl_ct_string(recip1->comm_type) << endl;
  27.199 +    assert(recip1->comm_type == PEP_ct_key_revoked);
  27.200 +
  27.201 +    cout << endl << "---------------------------------------------------------" << endl;
  27.202 +    cout << "2d. Try to decrypt message that was encrypted for revoked key guy." << endl;
  27.203 +    cout << "---------------------------------------------------------" << endl << endl;
  27.204 +    // decrypt message
  27.205 +//    free_message(outgoing_msg);
  27.206 +//    outgoing_msg = NULL;
  27.207 +    // FIXME: Make this make more sense
  27.208 +    status = decrypt_message(session, outgoing_msg, &decrypted_msg, &keylist, &rating, &flags);
  27.209 +    cout << "Decryption returns with status " << tl_status_string(status) << endl;
  27.210 +    assert(status == PEP_UNENCRYPTED);
  27.211 +    
  27.212 +    // check rating
  27.213 +    cout << "Rating of decrypted message to trusted recip: " << tl_rating_string(rating) << endl;
  27.214 +    assert(rating == PEP_rating_unencrypted);
  27.215 +
  27.216 +    ct = (decrypted_msg ? decrypted_msg->to->ident->comm_type : outgoing_msg->to->ident->comm_type);
  27.217 +
  27.218 +    cout << "comm_type: " << tl_ct_string(ct) << endl;
  27.219 +    assert(ct == PEP_ct_key_revoked);
  27.220 +    
  27.221 +    status = get_trust(session, recip1);
  27.222 +    
  27.223 +    cout << "Recip's trust DB comm_type = " << hex << tl_ct_string(recip1->comm_type) << endl;
  27.224 +    assert(recip1->comm_type == PEP_ct_key_revoked);
  27.225 +
  27.226 +    free_message(encrypted_outgoing_msg);
  27.227 +    free_message(decrypted_msg);
  27.228 +    free_message(outgoing_msg);
  27.229 +    outgoing_msg = NULL;
  27.230 +    decrypted_msg = NULL;
  27.231 +    encrypted_outgoing_msg = NULL;
  27.232 +
  27.233 +    cout << endl << "---------------------------------------------------------" << endl;
  27.234 +    cout << "3a. Generate new key, but don't explicitly trust it." << endl;
  27.235 +    cout << "---------------------------------------------------------" << endl << endl;
  27.236 +
  27.237 +    // now: generate new key
  27.238 +    free(recip1->fpr);
  27.239 +    recip1->fpr = NULL;
  27.240 +    status = generate_keypair(session, recip1);
  27.241 +    
  27.242 +    cout << "Generated fingerprint \n";
  27.243 +    cout << recip1->fpr << "\n";
  27.244 +    fprs[1] = strdup(recip1->fpr);
  27.245 +
  27.246 +    // try again
  27.247 +    cout << endl << "---------------------------------------------------------" << endl;
  27.248 +    cout << "3b. Try to send something to the email address of our revoked friend, make sure a new key is used to encrypt." << endl;
  27.249 +    cout << "---------------------------------------------------------" << endl << endl;
  27.250 +    
  27.251 +    // encrypt something to the key
  27.252 +    cout << "Creating message…\n";
  27.253 +    to_list = new_identity_list(identity_dup(recip1)); // to bob
  27.254 +    outgoing_msg = new_message(PEP_dir_outgoing);
  27.255 +    assert(outgoing_msg);
  27.256 +    outgoing_msg->from = identity_dup(me);
  27.257 +    outgoing_msg->to = to_list;
  27.258 +    outgoing_msg->shortmsg = strdup("Greetings, humans!");
  27.259 +    outgoing_msg->longmsg = strdup("This is a test of the emergency message system. This is only a test. BEEP.");
  27.260 +    outgoing_msg->attachments = new_bloblist(NULL, 0, "application/octet-stream", NULL);
  27.261 +    cout << "Message created.\n";
  27.262 +
  27.263 +    status = encrypt_message(session, outgoing_msg, NULL, &encrypted_outgoing_msg, PEP_enc_PGP_MIME, 0);
  27.264 +
  27.265 +    ct = (encrypted_outgoing_msg ? encrypted_outgoing_msg->to->ident->comm_type : outgoing_msg->to->ident->comm_type);
  27.266 +
  27.267 +    // CHECK STATUS???
  27.268 +    cout << "Encryption returns with status " << tl_status_string(status) << endl;
  27.269 +
  27.270 +    // check comm_type
  27.271 +    cout << "comm_type: " << tl_ct_string(ct) << endl;
  27.272 +    assert(ct == PEP_ct_OpenPGP_unconfirmed);
  27.273 +    
  27.274 +    status = get_trust(session, recip1);
  27.275 +
  27.276 +    cout << "Recip's trust DB comm_type = " << hex << tl_ct_string(recip1->comm_type) << endl;
  27.277 +    assert(recip1->comm_type == PEP_ct_OpenPGP_unconfirmed);
  27.278 +
  27.279 +    // decrypt message
  27.280 +//    free_message(outgoing_msg);
  27.281 +//    outgoing_msg = NULL;
  27.282 +
  27.283 +    cout << endl << "---------------------------------------------------------" << endl;
  27.284 +    cout << "3c. Decrypt... that... message!" << endl;
  27.285 +    cout << "---------------------------------------------------------" << endl << endl;
  27.286 +
  27.287 +
  27.288 +    status = decrypt_message(session, encrypted_outgoing_msg, &decrypted_msg, &keylist, &rating, &flags);
  27.289 +    cout << "Decryption returns with status " << tl_status_string(status) << endl;
  27.290 +    assert(status == PEP_STATUS_OK);
  27.291 +
  27.292 +    // check rating
  27.293 +    cout << "Rating of decrypted message to trusted recip: " << tl_rating_string(rating) << endl;
  27.294 +    assert(rating == PEP_rating_reliable);
  27.295 +
  27.296 +    ct = (decrypted_msg ? decrypted_msg->to->ident->comm_type : outgoing_msg->to->ident->comm_type);
  27.297 +
  27.298 +    cout << "comm_type: " << tl_ct_string(ct) << endl;
  27.299 +    assert(ct == PEP_ct_OpenPGP_unconfirmed);
  27.300 +    
  27.301 +    status = get_trust(session, recip1);
  27.302 +    
  27.303 +    cout << "Recip's trust DB comm_type = " << hex << tl_ct_string(recip1->comm_type) << endl;
  27.304 +    assert(recip1->comm_type == PEP_ct_OpenPGP_unconfirmed);
  27.305 +
  27.306 +    free_message(encrypted_outgoing_msg);
  27.307 +    free_message(decrypted_msg);
  27.308 +    free_message(outgoing_msg);
  27.309 +    outgoing_msg = NULL;
  27.310 +    decrypted_msg = NULL;
  27.311 +    encrypted_outgoing_msg = NULL;
  27.312 +
  27.313 +    free_identity(me);
  27.314 +    free_identity(recip1);
  27.315 +    free(uniqname);
  27.316 +    
  27.317 +    delete_keypair(session, fprs[0]);    
  27.318 +    delete_keypair(session, fprs[1]);
  27.319 +    
  27.320 +    free(fprs[0]);
  27.321 +    free(fprs[1]);
  27.322 +    
  27.323 +#else
  27.324 +    cout << "Sorry, test is not defined for NETPGP at this time." << endl;
  27.325 +    
  27.326 +#endif
  27.327 +    
  27.328 +    release(session);
  27.329 +
  27.330 +    return 0;
  27.331 +}
    28.1 --- a/test/pEpEngineTest.cc	Mon Mar 27 14:53:29 2017 +0200
    28.2 +++ b/test/pEpEngineTest.cc	Tue Jun 06 18:00:40 2017 +0200
    28.3 @@ -26,7 +26,25 @@
    28.4          snprintf(buf,31, "%lu", u);
    28.5          return buf;
    28.6      }
    28.7 -}
    28.8 +    
    28.9 +    std::string status(PEP_STATUS status)
   28.10 +    {
   28.11 +        char buf[32] = {0};
   28.12 +        if(status==0)
   28.13 +        {
   28.14 +            return "PEP_STATUS_OK";
   28.15 +        }else{
   28.16 +            if(status>0)
   28.17 +            {
   28.18 +                snprintf(buf,31, "%u (0x%x)", status, status);
   28.19 +            }else{
   28.20 +                snprintf(buf,31, "%d", status);
   28.21 +            }
   28.22 +        }
   28.23 +        return buf;
   28.24 +    }
   28.25 +
   28.26 +} // end of anonymous namespace
   28.27  
   28.28  
   28.29  Buffer ReadFileIntoMem(const char *fname){
   28.30 @@ -66,13 +84,13 @@
   28.31      cout << "calling init()\n";
   28.32      PEP_STATUS init_result = init(&session);
   28.33      
   28.34 -    cout << "returning from init() with result == " << init_result << "\n";
   28.35 +    cout << "returning from init() with result == " << status(init_result) << endl;
   28.36      assert(init_result == PEP_STATUS_OK);
   28.37  
   28.38      PEP_SESSION second_session;
   28.39      cout << "second session test\n";
   28.40      PEP_STATUS second_init_result = init(&second_session);
   28.41 -    cout << "returning from second init() with result == " << second_init_result << "\n";
   28.42 +    cout << "returning from second init() with result == " << status(second_init_result) << endl;
   28.43      assert(second_init_result == PEP_STATUS_OK);
   28.44      assert(second_session);
   28.45      cout << "dropping second session\n";
   28.46 @@ -125,14 +143,14 @@
   28.47      cout << "calling decrypt_and_verify()\n";
   28.48      PEP_STATUS decrypt_result = decrypt_and_verify(session, cipher_buffer.data(), cipher_buffer.size(), NULL, 0, &buf_text, &buf_size, &keylist);
   28.49  
   28.50 -    cout << "returning from decrypt_and_verify() with result == 0x" << std::hex << decrypt_result << "\n";
   28.51 +    cout << "returning from decrypt_and_verify() with result == " << status(decrypt_result) << endl;
   28.52      assert(decrypt_result == PEP_DECRYPTED_AND_VERIFIED);
   28.53      assert(buf_text);
   28.54      assert(keylist);
   28.55  
   28.56      for (stringlist_t *_keylist=keylist; _keylist!=NULL; _keylist=_keylist->next) {
   28.57          assert(_keylist->value);
   28.58 -        cout << "signed with " << _keylist->value << "\n";
   28.59 +        cout << "signed with " << _keylist->value << endl;
   28.60      }
   28.61  
   28.62      free_stringlist(keylist);
   28.63 @@ -146,10 +164,10 @@
   28.64  
   28.65      cout << "\ncalling verify_text()\n";
   28.66      PEP_STATUS verify_result = verify_text(session, t1_buffer.data(), t1_buffer.size(), sig_buffer.data(), sig_buffer.size(), &keylist);
   28.67 -    cout << "returning from verify_text() with result == " << verify_result << "\n";
   28.68 +    cout << "returning from verify_text() with result == " << status(verify_result) << endl;
   28.69      assert(verify_result == PEP_VERIFIED || verify_result == PEP_VERIFIED_AND_TRUSTED);
   28.70      assert(keylist->value);
   28.71 -    cout << "signed with " << keylist->value << "\n";
   28.72 +    cout << "signed with " << keylist->value << endl;
   28.73      free_stringlist(keylist);
   28.74  
   28.75      const Buffer t2_buffer = ReadFileIntoMem("t2.txt");
   28.76 @@ -168,7 +186,7 @@
   28.77  
   28.78      cout << "\ncalling encrypt_and_sign()\n";
   28.79      PEP_STATUS encrypt_result = encrypt_and_sign(session, keylist, plain.c_str(), plain.length(), &buf_text, &buf_size);
   28.80 -    cout << "returning from encrypt_and_sign() with result == " << encrypt_result << "\n";
   28.81 +    cout << "returning from encrypt_and_sign() with result == " << status(encrypt_result) << endl;
   28.82      assert(encrypt_result == PEP_STATUS_OK);
   28.83      free_stringlist(keylist);
   28.84  
   28.85 @@ -182,12 +200,12 @@
   28.86      size_t wsize;
   28.87      trustword(session, 2342, "en", &word, &wsize);
   28.88      assert(word);
   28.89 -    cout << "the English trustword for 2342 is " << word << "\n";
   28.90 +    cout << "the English trustword for 2342 is " << word << endl;
   28.91      pEp_free(word);
   28.92      cout << "\nfinding French trustword for 2342...\n";
   28.93      trustword(session, 2342, "fr", &word, &wsize);
   28.94      assert(word);
   28.95 -    cout << "the French trustword for 2342 is " << word << "\n";
   28.96 +    cout << "the French trustword for 2342 is " << word << endl;
   28.97      pEp_free(word);
   28.98  
   28.99      const string fingerprint = "4942 2235 FC99 585B 891C  6653 0C7B 109B FA72 61F7";
  28.100 @@ -196,7 +214,7 @@
  28.101      cout << "\nfinding German trustwords for " << fingerprint << "...\n";
  28.102      trustwords(session, fingerprint.c_str(), "de", &words, &wsize, 5);
  28.103      assert(words);
  28.104 -    cout << words << "\n";
  28.105 +    cout << words << endl;
  28.106      pEp_free(words);
  28.107  
  28.108      pEp_identity* identity  = new_identity(
  28.109 @@ -213,11 +231,11 @@
  28.110      free_identity(identity);
  28.111      get_identity(session, "leon.schumacher@digitalekho.com", "23", &identity);
  28.112      assert(identity);
  28.113 -    cout << "set: " << identity->address << ", " << identity->fpr << ", " << identity->user_id << ", " << identity->username << "\n";
  28.114 +    cout << "set: " << identity->address << ", " << identity->fpr << ", " << identity->user_id << ", " << identity->username << endl;
  28.115  
  28.116      PEP_STATUS get_trust_result = get_trust(session, identity);
  28.117      assert(get_trust_result == PEP_STATUS_OK);
  28.118 -    cout << "trust of " << identity->user_id << " is " << identity->comm_type << "\n";
  28.119 +    cout << "trust of " << identity->user_id << " is " << identity->comm_type << endl;
  28.120  
  28.121      free_identity(identity);
  28.122  
  28.123 @@ -231,9 +249,9 @@
  28.124  
  28.125      assert(identity);
  28.126      PEP_STATUS generate_status = generate_keypair(session, identity);
  28.127 -    cout << "generate_keypair() exits with " << generate_status << "\n";
  28.128 +    cout << "generate_keypair() exits with " << status(generate_status) << endl;
  28.129      assert(generate_status == PEP_STATUS_OK);
  28.130 -    cout << "generated key is " << identity->fpr << "\n";
  28.131 +    cout << "generated key is " << identity->fpr << endl;
  28.132  
  28.133      const string key(identity->fpr);
  28.134      free_identity(identity);
  28.135 @@ -243,13 +261,13 @@
  28.136  
  28.137      cout << "export_key()\n\n";
  28.138      PEP_STATUS export_status = export_key(session, key.c_str(), &key_data, &size);
  28.139 -    cout << "export_key() exits with " << export_status << "\n";
  28.140 +    cout << "export_key() exits with " << status(export_status) << endl;
  28.141      assert(export_status == PEP_STATUS_OK);
  28.142      cout << key_data << "\n\n";
  28.143  
  28.144 -    cout << "deleting key pair " << key.c_str() << "\n";
  28.145 +    cout << "deleting key pair " << key.c_str() << endl;
  28.146      PEP_STATUS delete_status = delete_keypair(session, key.c_str());
  28.147 -    cout << "delete_keypair() exits with " << delete_status << "\n";
  28.148 +    cout << "delete_keypair() exits with " << status(delete_status) << endl;
  28.149      assert(delete_status == PEP_STATUS_OK);
  28.150      
  28.151      cout << "import_key()\n";
  28.152 @@ -262,31 +280,31 @@
  28.153  
  28.154      cout << "deleting key " << key.c_str() << " again\n";
  28.155      delete_status = delete_keypair(session, key.c_str());
  28.156 -    cout << "delete_keypair() exits with " << delete_status << "\n";
  28.157 +    cout << "delete_keypair() exits with " << status(delete_status) << endl;
  28.158      assert(delete_status == PEP_STATUS_OK);
  28.159  
  28.160      cout << "finding key for pep.test.john@pep-project.org\n";
  28.161      PEP_STATUS find_keys_status = find_keys(session, "pep.test.john@pep-project.org", &keylist);
  28.162 -    cout << "find_keys() exits with " << find_keys_status << "\n";
  28.163 +    cout << "find_keys() exits with " << status(find_keys_status) << endl;
  28.164      assert(find_keys_status == PEP_STATUS_OK);
  28.165      assert(keylist);
  28.166 -    cout << "found: " << keylist->value << "\n";
  28.167 +    cout << "found: " << keylist->value << endl;
  28.168      assert(keylist->next == NULL);
  28.169      free_stringlist(keylist);
  28.170  
  28.171      cout << "searching for vb@ulm.ccc.de on keyserver\n";
  28.172      PEP_STATUS recv_key_status = recv_key(session, "vb@ulm.ccc.de");
  28.173 -    cout << "recv_key() exits with " << recv_key_status << "\n";
  28.174 +    cout << "recv_key() exits with " << status(recv_key_status) << endl;
  28.175      assert(recv_key_status == PEP_STATUS_OK);
  28.176  
  28.177      cout << "sending vb@ulm.ccc.de to keyserver\n";
  28.178      PEP_STATUS send_key_status = send_key(session, "vb@ulm.ccc.de");
  28.179 -    cout << "send_key() exits with " << send_key_status << "\n";
  28.180 +    cout << "send_key() exits with " << status(send_key_status) << endl;
  28.181      assert(send_key_status == PEP_STATUS_OK);
  28.182  
  28.183      PEP_comm_type tcomm_type;
  28.184      PEP_STATUS tstatus = get_key_rating(session, "BFCDB7F301DEEEBBF947F29659BFF488C9C2EE39", &tcomm_type);
  28.185 -    cout << "get_key_rating() exits with " << tstatus << "\n";
  28.186 +    cout << "get_key_rating() exits with " << status(tstatus) << endl;
  28.187      assert(tstatus == PEP_STATUS_OK);
  28.188      assert(tcomm_type == PEP_ct_OpenPGP_unconfirmed);
  28.189      
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/test/test_keys/priv/pep.test.fenris-0x6DBA13DA_priv.asc	Tue Jun 06 18:00:40 2017 +0200
    29.3 @@ -0,0 +1,57 @@
    29.4 +-----BEGIN PGP PRIVATE KEY BLOCK-----
    29.5 +
    29.6 +lQOYBFkxkeMBCADJZK47Qcy/vek7kFa8IdXuyveM9LUKNbQpRm2fllhXdCNm7oL1
    29.7 +09WHZVjGHBX8DJk+I0v7YyYuMgILNNnipGUYfUsYHub33p7Sg0kNzNp0PK9hiKWN
    29.8 +lel4PgWYTQzm0eijXfaWIVL6LX+YeT6/OxeJbuXwmdyf/LsMiLOpaKD/4T1aRxeX
    29.9 ++RyiSFG7t42DTN1Xt82vR306IN+rx2Ucwnlh/THPn3TJk3Gw+f/13GZKJL6efe/u
   29.10 +9uhc91KVJYPGCcuIKsQ2Px69wq6odV80MvGfrkgxlrbMPDFRd6DXFbd4W8SXrOHa
   29.11 +M/5vCeKOgByIxG6Q/CtSWFaJD2AlYGlHGeGjABEBAAEAB/wIcQLokvJ9Gv26tGse
   29.12 +SaDI+JL1wpAQFH4vuLcBmHCtgb22I8szeKSbn0DgVO8K+JA3zYzyxY4lI414YMe9
   29.13 +OzzNkPrj0O/HdfpcQop+XJbPhnenc+3UiHMXyim734bp6eSBbH/YfR8YQ230uyhJ
   29.14 +JbXv2ckjk59uyU4h0V0Ofcc50mkM2ia8CCAx/g+q8wVYqRJ+A/f55xuZdgpxmv3l
   29.15 +EcuzgEfZK0oZRlG6UybnXxiDzCba7cbxt84yH9KeLr2KQwQ5KvoOd84zDiDJoe89
   29.16 +1DB3mrKOuCHZ5+s0KwlGSZYPD7nh3j+SBBgwaqV4/FcW7r367shbPZqMJQfNhhh8
   29.17 +PKWxBADY3qAXWZWUzk1d5fRluyXDa8oiTnMq1QMWOsUFQ3iTXAZ6m5ZGIT129PZk
   29.18 +KC72FPxjDewojayfj9KmHuOdgn0HCPi8l4J3mUtIN7Khp6MTaPusmx/kfOhdkGrM
   29.19 +/ggOG4sANpYoivV9J+FUUHKGNKCntm7cvQbFdGA5ImRcSWPy6QQA7bsw3wzSyAbW
   29.20 +6yrIcJhOUjOkyys8XwQi69zK4NJT/BUQCA1w+UyAkXXCEqsaZBpBjVJxu3+Z4P3J
   29.21 +veNyGxqWIoLPsND7B5wYW77hyQingud3+XytwIGsQbaXFYS6IPYjJ5LvQzW9mb1v
   29.22 +ZG7nRy7JA+zW/s7qVD/fJsYLzKg9oKsEAIDASmhIm97e5/WkUArVXz+8m6Tb3jS3
   29.23 +Wei+xPJXV0Mk0O5vnaYterqCU3cnsLs0YlWry4o3CJZLuY74gVu3vvR8bYnw9o8X
   29.24 +Lc4dFyPlB/SE0bA3ZycLxYLd4vto+yzG8n9aojTsEBYsmp6tG/zd/tucjdmuH4FD
   29.25 +ufaZCjpm5MaoSxe0S0ZlbnJpcyAoT3duIGtleSBmb3IgZXh0ZXJuYWwgcmV2b2tl
   29.26 +IHRlc3QpIDxwZXAudGVzdC5mZW5yaXNAbm90cmVhbGVtYWlsLmV1PokBOQQTAQgA
   29.27 +IwUCWTGR4wIbAwcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEDgGIfxtuhPa
   29.28 +LKsH+gIkhB03pT4MxqF5qCx+L+nvmUmXUdg486gBz6TdpZ2hQWiJU4LHlh79xtrn
   29.29 +dyPtn6SieaOQ2z5UQS0xRC+oV3VYKK9pANS+8p2cTuUNB0uaUdHOeAFH5JHrnCa3
   29.30 +4DOG3W+r7dXbjExaVKBmKxnUFiCT+ogfvkZHN8iKck3ssPbjNQah8JEuXgXFlVYN
   29.31 +jv2Qj6w+VhZ4vVsZvgZimIappfAxg3GWgtfFvFdQut/RCpbE35kBozBAGF2JJqut
   29.32 +1dukZDBHJDkOqt/dU6eVnmAd+YOsoqdB3F7PqjSzKz2D7fKIkmpbt3L2QQmRrx43
   29.33 +krjG9dMt3h90wHYIaJkNdEQl0UWdA5gEWTGR4wEIANPQKAZeaH6iHgZU6rQCcDbA
   29.34 +uCFWUynmd6W16iiwxz6PJL2ACqvgbdQ8wBWb3UGGl4uhI9Ksar9nz+L6mOPOTvEd
   29.35 +XThRCaVzIZNz5Znos9ao+DRcAibguPE14QNiBgxe1RhRz32Q3jdEcG6Sg2SZNMvA
   29.36 +mKNZKlkL2ERvFyFfdiexfesB4E/zh6lea2up87XwlMefSTPn2yOgi+fVl3bwCoyn
   29.37 +UlX51zF+OAGBdobihDTUuU8bPibJ2uN2ilqqVGziMU4SitDqulbXtH2AcUVoaCbe
   29.38 +NPdfnEGnWXTnG8s7s9IerScH8HUL8BgoDZqQl9b5bJphRq+Jq6NmVqHPft9VpsMA
   29.39 +EQEAAQAH/RIuBpFtXvinf345oZ9rqif46JTr7N1my5QshfmSGrfS32toZwITlDmo
   29.40 +MTBpnVb3b2Brp0B4zfy5s00fBypeVcY6J/sicXqC5Dncs7M/FthwzkToNMMTfKwv
   29.41 +XK3GpxA+v3mD5BQ57+i8dg33g1GKGM74K+GxUIIuExTkmA6kO+byHAbyxYcqF6/M
   29.42 +fezKPete0R11W5NnTKZO4WOX9oGCh/jUuyTQ+bbSzxx/ds61BYG7Hitgn82WW3d4
   29.43 +cskd6llYHLTANRk41yAUn7BWUaUUmPk2HIHUCh3nyjEVrOSO0PYwWyGSaQxJG1+W
   29.44 +9TG0728IDfNMKyq7c4/X1kvRI893jwkEAOFQaNBC8vChwZ3iM8oZBVOEPraPUrJE
   29.45 +ord3mrPEfqxD6Yc/ju4YdzLe3QPo27mCBW2e9/6u5GguhaZ5QA5Z8KGgYBrKZnLK
   29.46 +3A2ZM+jIto3zCfPZAPXl6zxKbZLq/0b0toBhVpNJiVHSqagBWKmg5CJYRHaadgCM
   29.47 +ozlpHScVNNPfBADwqQi5rHHrXeS5FvKxtXYh/Aow8QBhpCrDWaP4Vmrt5pZhv/yR
   29.48 +RT2Lm0/IfSzf9qNtb0syzn8i+qr5MxNfLy9c8Jov4Xk0WD+Qo32j9SbQPoU24aIN
   29.49 +5gweN+gVCh6XgjAugUPWBAuH/B1ghDtiCd6hzjxgW2ircImU7nK8QB8pnQP/SH2n
   29.50 +VaXIYg/p4Wi0tTSuV8KYiBvOuFkXcKR6uglLrrVf5s/+8H4PeKCU2h8yNOL5iiGK
   29.51 +RJBEIrdW2qiO6sAtrxKzQ1J7WktRdpUVIHmAd+Rba8/XRW1YuXuWAS6yOTx0xdOz
   29.52 +vBtMCku+OoHdO5qXzO5ubrkDhbOAY+T5sGK419hFyIkBHwQYAQgACQUCWTGR4wIb
   29.53 +DAAKCRA4BiH8bboT2liHB/0fZSrsLuKzfHkFhE8/qF7SxgWPH0vCi1N8BnbwnTDe
   29.54 +FzoSTjSGO9//NYMJlrPk4fUExasGLr+XBNBv8zHt+Ri5ws2XtkVwfP9HPcxh6iX7
   29.55 +aqvrVZbpiE90GQSNeDBzCRPOXWqg6vIJqRX8j++yLc+9VlFcYoMT/AmOUFsiF+ZP
   29.56 +Pt4+U27SmDn0WfbpvqFDXTqkzYF+r8Y+yBieHACJ7p/gvFchnNQjYU+d5qPMPoCP
   29.57 +P4Xqq9fnfBK5N7cxgM6dgJO7HZGzbkzjdeOwNFsX9NSyfYaUhiUDkO6t4jKKswWm
   29.58 +RlF/bzjhv+z0PM9qVKZzIOlH5inYGgFAJh8CbleKxYs6
   29.59 +=f8cO
   29.60 +-----END PGP PRIVATE KEY BLOCK-----
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/test/test_keys/pub/pep.test.fenris-0x6DBA13DA_pub.asc	Tue Jun 06 18:00:40 2017 +0200
    30.3 @@ -0,0 +1,30 @@
    30.4 +-----BEGIN PGP PUBLIC KEY BLOCK-----
    30.5 +
    30.6 +mQENBFkxkeMBCADJZK47Qcy/vek7kFa8IdXuyveM9LUKNbQpRm2fllhXdCNm7oL1
    30.7 +09WHZVjGHBX8DJk+I0v7YyYuMgILNNnipGUYfUsYHub33p7Sg0kNzNp0PK9hiKWN
    30.8 +lel4PgWYTQzm0eijXfaWIVL6LX+YeT6/OxeJbuXwmdyf/LsMiLOpaKD/4T1aRxeX
    30.9 ++RyiSFG7t42DTN1Xt82vR306IN+rx2Ucwnlh/THPn3TJk3Gw+f/13GZKJL6efe/u
   30.10 +9uhc91KVJYPGCcuIKsQ2Px69wq6odV80MvGfrkgxlrbMPDFRd6DXFbd4W8SXrOHa
   30.11 +M/5vCeKOgByIxG6Q/CtSWFaJD2AlYGlHGeGjABEBAAG0S0ZlbnJpcyAoT3duIGtl
   30.12 +eSBmb3IgZXh0ZXJuYWwgcmV2b2tlIHRlc3QpIDxwZXAudGVzdC5mZW5yaXNAbm90
   30.13 +cmVhbGVtYWlsLmV1PokBOQQTAQgAIwUCWTGR4wIbAwcLCQgHAwIBBhUIAgkKCwQW
   30.14 +AgMBAh4BAheAAAoJEDgGIfxtuhPaLKsH+gIkhB03pT4MxqF5qCx+L+nvmUmXUdg4
   30.15 +86gBz6TdpZ2hQWiJU4LHlh79xtrndyPtn6SieaOQ2z5UQS0xRC+oV3VYKK9pANS+
   30.16 +8p2cTuUNB0uaUdHOeAFH5JHrnCa34DOG3W+r7dXbjExaVKBmKxnUFiCT+ogfvkZH
   30.17 +N8iKck3ssPbjNQah8JEuXgXFlVYNjv2Qj6w+VhZ4vVsZvgZimIappfAxg3GWgtfF
   30.18 +vFdQut/RCpbE35kBozBAGF2JJqut1dukZDBHJDkOqt/dU6eVnmAd+YOsoqdB3F7P
   30.19 +qjSzKz2D7fKIkmpbt3L2QQmRrx43krjG9dMt3h90wHYIaJkNdEQl0UW5AQ0EWTGR
   30.20 +4wEIANPQKAZeaH6iHgZU6rQCcDbAuCFWUynmd6W16iiwxz6PJL2ACqvgbdQ8wBWb
   30.21 +3UGGl4uhI9Ksar9nz+L6mOPOTvEdXThRCaVzIZNz5Znos9ao+DRcAibguPE14QNi
   30.22 +Bgxe1RhRz32Q3jdEcG6Sg2SZNMvAmKNZKlkL2ERvFyFfdiexfesB4E/zh6lea2up
   30.23 +87XwlMefSTPn2yOgi+fVl3bwCoynUlX51zF+OAGBdobihDTUuU8bPibJ2uN2ilqq
   30.24 +VGziMU4SitDqulbXtH2AcUVoaCbeNPdfnEGnWXTnG8s7s9IerScH8HUL8BgoDZqQ
   30.25 +l9b5bJphRq+Jq6NmVqHPft9VpsMAEQEAAYkBHwQYAQgACQUCWTGR4wIbDAAKCRA4
   30.26 +BiH8bboT2liHB/0fZSrsLuKzfHkFhE8/qF7SxgWPH0vCi1N8BnbwnTDeFzoSTjSG
   30.27 +O9//NYMJlrPk4fUExasGLr+XBNBv8zHt+Ri5ws2XtkVwfP9HPcxh6iX7aqvrVZbp
   30.28 +iE90GQSNeDBzCRPOXWqg6vIJqRX8j++yLc+9VlFcYoMT/AmOUFsiF+ZPPt4+U27S
   30.29 +mDn0WfbpvqFDXTqkzYF+r8Y+yBieHACJ7p/gvFchnNQjYU+d5qPMPoCPP4Xqq9fn
   30.30 +fBK5N7cxgM6dgJO7HZGzbkzjdeOwNFsX9NSyfYaUhiUDkO6t4jKKswWmRlF/bzjh
   30.31 +v+z0PM9qVKZzIOlH5inYGgFAJh8CbleKxYs6
   30.32 +=LcZA
   30.33 +-----END PGP PUBLIC KEY BLOCK-----
    31.1 --- a/test/test_util.cc	Mon Mar 27 14:53:29 2017 +0200
    31.2 +++ b/test/test_util.cc	Tue Jun 06 18:00:40 2017 +0200
    31.3 @@ -1,4 +1,6 @@
    31.4  #include "pEpEngine_test.h"
    31.5 +#include "pEpEngine.h"
    31.6 +#include "message_api.h"
    31.7  #include <fstream>
    31.8  #include <sstream>
    31.9  #include <stdexcept>
   31.10 @@ -15,3 +17,237 @@
   31.11  	sstr << input.rdbuf();
   31.12  	return sstr.str();
   31.13  }
   31.14 +
   31.15 +const char* tl_status_string(PEP_STATUS status) {
   31.16 +    switch (status) {
   31.17 +        case PEP_STATUS_OK:
   31.18 +            return "PEP_STATUS_OK";
   31.19 +        case PEP_INIT_CANNOT_LOAD_GPGME:
   31.20 +            return "PEP_INIT_CANNOT_LOAD_GPGME";
   31.21 +        case PEP_INIT_GPGME_INIT_FAILED:
   31.22 +            return "PEP_INIT_GPGME_INIT_FAILED";
   31.23 +        case PEP_INIT_NO_GPG_HOME:
   31.24 +            return "PEP_INIT_NO_GPG_HOME";
   31.25 +        case PEP_INIT_NETPGP_INIT_FAILED:
   31.26 +            return "PEP_INIT_NETPGP_INIT_FAILED";
   31.27 +        case PEP_INIT_SQLITE3_WITHOUT_MUTEX:
   31.28 +            return "PEP_INIT_SQLITE3_WITHOUT_MUTEX";
   31.29 +        case PEP_INIT_CANNOT_OPEN_DB:
   31.30 +            return "PEP_INIT_CANNOT_OPEN_DB";
   31.31 +        case PEP_INIT_CANNOT_OPEN_SYSTEM_DB:
   31.32 +            return "PEP_INIT_CANNOT_OPEN_SYSTEM_DB";
   31.33 +        case PEP_KEY_NOT_FOUND:
   31.34 +            return "PEP_KEY_NOT_FOUND";
   31.35 +        case PEP_KEY_HAS_AMBIG_NAME:
   31.36 +            return "PEP_KEY_HAS_AMBIG_NAME";
   31.37 +        case PEP_GET_KEY_FAILED:
   31.38 +            return "PEP_GET_KEY_FAILED";
   31.39 +        case PEP_CANNOT_EXPORT_KEY:
   31.40 +            return "PEP_CANNOT_EXPORT_KEY";
   31.41 +        case PEP_CANNOT_EDIT_KEY:
   31.42 +            return "PEP_CANNOT_EDIT_KEY";
   31.43 +        case PEP_CANNOT_FIND_IDENTITY:
   31.44 +            return "PEP_CANNOT_FIND_IDENTITY";
   31.45 +        case PEP_CANNOT_SET_PERSON:
   31.46 +            return "PEP_CANNOT_SET_PERSON";
   31.47 +        case PEP_CANNOT_SET_PGP_KEYPAIR:
   31.48 +            return "PEP_CANNOT_SET_PGP_KEYPAIR";
   31.49 +        case PEP_CANNOT_SET_IDENTITY:
   31.50 +            return "PEP_CANNOT_SET_IDENTITY";
   31.51 +        case PEP_CANNOT_SET_TRUST:
   31.52 +            return "PEP_CANNOT_SET_TRUST";
   31.53 +        case PEP_KEY_BLACKLISTED:
   31.54 +            return "PEP_KEY_BLACKLISTED";
   31.55 +        case PEP_UNENCRYPTED:
   31.56 +            return "PEP_UNENCRYPTED";
   31.57 +        case PEP_VERIFIED:
   31.58 +            return "PEP_VERIFIED";
   31.59 +        case PEP_DECRYPTED:
   31.60 +            return "PEP_DECRYPTED";
   31.61 +        case PEP_DECRYPTED_AND_VERIFIED:
   31.62 +            return "PEP_DECRYPTED_AND_VERIFIED";
   31.63 +        case PEP_DECRYPT_WRONG_FORMAT:
   31.64 +            return "PEP_DECRYPT_WRONG_FORMAT";
   31.65 +        case PEP_DECRYPT_NO_KEY:
   31.66 +            return "PEP_DECRYPT_NO_KEY";
   31.67 +        case PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH:
   31.68 +            return "PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH";
   31.69 +        case PEP_VERIFY_NO_KEY:
   31.70 +            return "PEP_VERIFY_NO_KEY";
   31.71 +        case PEP_VERIFIED_AND_TRUSTED:
   31.72 +            return "PEP_VERIFIED_AND_TRUSTED";
   31.73 +        case PEP_CANNOT_DECRYPT_UNKNOWN:
   31.74 +            return "PEP_CANNOT_DECRYPT_UNKNOWN";
   31.75 +        case PEP_TRUSTWORD_NOT_FOUND:
   31.76 +            return "PEP_TRUSTWORD_NOT_FOUND";
   31.77 +        case PEP_TRUSTWORDS_FPR_WRONG_LENGTH:
   31.78 +            return "PEP_TRUSTWORDS_FPR_WRONG_LENGTH";
   31.79 +        case PEP_CANNOT_CREATE_KEY:
   31.80 +            return "PEP_CANNOT_CREATE_KEY";
   31.81 +        case PEP_CANNOT_SEND_KEY:
   31.82 +            return "PEP_CANNOT_SEND_KEY";
   31.83 +        case PEP_PHRASE_NOT_FOUND:
   31.84 +            return "PEP_PHRASE_NOT_FOUND";
   31.85 +        case PEP_SEND_FUNCTION_NOT_REGISTERED:
   31.86 +            return "PEP_SEND_FUNCTION_NOT_REGISTERED";
   31.87 +        case PEP_CONTRAINTS_VIOLATED:
   31.88 +            return "PEP_CONTRAINTS_VIOLATED";
   31.89 +        case PEP_CANNOT_ENCODE:
   31.90 +            return "PEP_CANNOT_ENCODE";
   31.91 +        case PEP_SYNC_NO_NOTIFY_CALLBACK:
   31.92 +            return "PEP_SYNC_NO_NOTIFY_CALLBACK";
   31.93 +        case PEP_SYNC_ILLEGAL_MESSAGE:
   31.94 +            return "PEP_SYNC_ILLEGAL_MESSAGE";
   31.95 +        case PEP_SYNC_NO_INJECT_CALLBACK:
   31.96 +            return "PEP_SYNC_NO_INJECT_CALLBACK";
   31.97 +        case PEP_SEQUENCE_VIOLATED:
   31.98 +            return "PEP_SEQUENCE_VIOLATED";
   31.99 +        case PEP_CANNOT_INCREASE_SEQUENCE:
  31.100 +            return "PEP_CANNOT_INCREASE_SEQUENCE";
  31.101 +        case PEP_CANNOT_SET_SEQUENCE_VALUE:
  31.102 +            return "PEP_CANNOT_SET_SEQUENCE_VALUE";
  31.103 +        case PEP_OWN_SEQUENCE:
  31.104 +            return "PEP_OWN_SEQUENCE";
  31.105 +        case PEP_SYNC_STATEMACHINE_ERROR:
  31.106 +            return "PEP_SYNC_STATEMACHINE_ERROR";
  31.107 +        case PEP_SYNC_NO_TRUST:
  31.108 +            return "PEP_SYNC_NO_TRUST";
  31.109 +        case PEP_STATEMACHINE_INVALID_STATE:
  31.110 +            return "PEP_STATEMACHINE_INVALID_STATE";
  31.111 +        case PEP_STATEMACHINE_INVALID_EVENT:
  31.112 +            return "PEP_STATEMACHINE_INVALID_EVENT";
  31.113 +        case PEP_STATEMACHINE_INVALID_CONDITION:
  31.114 +            return "PEP_STATEMACHINE_INVALID_CONDITION";
  31.115 +        case PEP_STATEMACHINE_INVALID_ACTION:
  31.116 +            return "PEP_STATEMACHINE_INVALID_ACTION";
  31.117 +        case PEP_STATEMACHINE_INHIBITED_EVENT:
  31.118 +            return "PEP_STATEMACHINE_INHIBITED_EVENT";
  31.119 +        case PEP_COMMIT_FAILED:
  31.120 +            return "PEP_COMMIT_FAILED";
  31.121 +        case PEP_MESSAGE_CONSUME:
  31.122 +            return "PEP_MESSAGE_CONSUME";
  31.123 +        case PEP_MESSAGE_IGNORE:
  31.124 +            return "PEP_MESSAGE_IGNORE";
  31.125 +        case PEP_RECORD_NOT_FOUND:
  31.126 +            return "PEP_RECORD_NOT_FOUND";
  31.127 +        case PEP_CANNOT_CREATE_TEMP_FILE:
  31.128 +            return "PEP_CANNOT_CREATE_TEMP_FILE";
  31.129 +        case PEP_ILLEGAL_VALUE:
  31.130 +            return "PEP_ILLEGAL_VALUE";
  31.131 +        case PEP_BUFFER_TOO_SMALL:
  31.132 +            return "PEP_BUFFER_TOO_SMALL";
  31.133 +        case PEP_OUT_OF_MEMORY:
  31.134 +            return "PEP_OUT_OF_MEMORY";
  31.135 +        case PEP_UNKNOWN_ERROR:
  31.136 +            return "PEP_UNKNOWN_ERROR";
  31.137 +        default:
  31.138 +            return "PEP_STATUS_OMGWTFBBQ - This means you're using a status the test lib doesn't know about!";
  31.139 +    }
  31.140 +}
  31.141 +const char* tl_rating_string(PEP_rating rating) {
  31.142 +    switch (rating) {
  31.143 +        case PEP_rating_undefined:
  31.144 +            return "PEP_rating_undefined";
  31.145 +        case PEP_rating_cannot_decrypt:
  31.146 +            return "PEP_rating_cannot_decrypt";
  31.147 +        case PEP_rating_have_no_key:
  31.148 +            return "PEP_rating_have_no_key";
  31.149 +        case PEP_rating_unencrypted:
  31.150 +            return "PEP_rating_unencrypted";
  31.151 +        case PEP_rating_unencrypted_for_some:
  31.152 +            return "PEP_rating_unencrypted_for_some";
  31.153 +        case PEP_rating_unreliable:
  31.154 +            return "PEP_rating_unreliable";
  31.155 +        case PEP_rating_reliable:
  31.156 +            return "PEP_rating_reliable";
  31.157 +        case PEP_rating_trusted:
  31.158 +            return "PEP_rating_trusted";
  31.159 +        case PEP_rating_trusted_and_anonymized:
  31.160 +            return "PEP_rating_trusted_and_anonymized";
  31.161 +        case PEP_rating_fully_anonymous:
  31.162 +            return "PEP_rating_fully_anonymous";
  31.163 +        case PEP_rating_mistrust:
  31.164 +            return "PEP_rating_mistrust";
  31.165 +        case PEP_rating_b0rken:
  31.166 +            return "PEP_rating_b0rken";
  31.167 +        case PEP_rating_under_attack:
  31.168 +            return "PEP_rating_under_attack";
  31.169 +        default:
  31.170 +            return "PEP_rating_OMGWTFBBQ - in other words, INVALID RATING VALUE!!!\n\nSomething bad is going on here, or a new rating value has been added to the enum and not the test function.";
  31.171 +    }
  31.172 +}
  31.173 +
  31.174 +const char* tl_ct_string(PEP_comm_type ct) {
  31.175 +    switch (ct) {
  31.176 +        case PEP_ct_unknown:
  31.177 +            return "PEP_ct_unknown";
  31.178 +        case PEP_ct_no_encryption:
  31.179 +            return "PEP_ct_no_encryption";
  31.180 +        case PEP_ct_no_encrypted_channel:
  31.181 +            return "PEP_ct_no_encrypted_channel";
  31.182 +        case PEP_ct_key_not_found:
  31.183 +            return "PEP_ct_key_not_found";
  31.184 +        case PEP_ct_key_expired:
  31.185 +            return "PEP_ct_key_expired";
  31.186 +        case PEP_ct_key_revoked:
  31.187 +            return "PEP_ct_key_revoked";
  31.188 +        case PEP_ct_key_b0rken:
  31.189 +            return "PEP_ct_key_b0rken";
  31.190 +        case PEP_ct_my_key_not_included:
  31.191 +            return "PEP_ct_my_key_not_included";
  31.192 +        case PEP_ct_security_by_obscurity:
  31.193 +            return "PEP_ct_security_by_obscurity";
  31.194 +        case PEP_ct_b0rken_crypto:
  31.195 +            return "PEP_ct_b0rken_crypto";
  31.196 +        case PEP_ct_key_too_short:
  31.197 +            return "PEP_ct_key_too_short";
  31.198 +        case PEP_ct_compromized:
  31.199 +            return "PEP_ct_compromized";
  31.200 +        case PEP_ct_mistrusted:
  31.201 +            return "PEP_ct_mistrusted";
  31.202 +        case PEP_ct_unconfirmed_encryption:
  31.203 +            return "PEP_ct_unconfirmed_encryption";
  31.204 +        case PEP_ct_OpenPGP_weak_unconfirmed:
  31.205 +            return "PEP_ct_OpenPGP_weak_unconfirmed";
  31.206 +        case PEP_ct_to_be_checked:
  31.207 +            return "PEP_ct_to_be_checked";
  31.208 +        case PEP_ct_SMIME_unconfirmed:
  31.209 +            return "PEP_ct_SMIME_unconfirmed";
  31.210 +        case PEP_ct_CMS_unconfirmed:
  31.211 +            return "PEP_ct_CMS_unconfirmed";
  31.212 +        case PEP_ct_strong_but_unconfirmed:
  31.213 +            return "PEP_ct_strong_but_unconfirmed";
  31.214 +        case PEP_ct_OpenPGP_unconfirmed:
  31.215 +            return "PEP_ct_OpenPGP_unconfirmed";
  31.216 +        case PEP_ct_OTR_unconfirmed:
  31.217 +            return "PEP_ct_OTR_unconfirmed";
  31.218 +        case PEP_ct_unconfirmed_enc_anon:
  31.219 +            return "PEP_ct_unconfirmed_enc_anon";
  31.220 +        case PEP_ct_pEp_unconfirmed:
  31.221 +            return "PEP_ct_pEp_unconfirmed";
  31.222 +        case PEP_ct_confirmed:
  31.223 +            return "PEP_ct_pEp_confirmed";
  31.224 +        case PEP_ct_confirmed_encryption:
  31.225 +            return "PEP_ct_confirmed_encryption";
  31.226 +        case PEP_ct_OpenPGP_weak:
  31.227 +            return "PEP_ct_OpenPGP_weak";
  31.228 +        case PEP_ct_to_be_checked_confirmed:
  31.229 +            return "PEP_ct_to_be_checked_confirmed";
  31.230 +        case PEP_ct_SMIME:
  31.231 +            return "PEP_ct_SMIME";
  31.232 +        case PEP_ct_CMS:
  31.233 +            return "PEP_ct_CMS";
  31.234 +        case PEP_ct_strong_encryption:
  31.235 +            return "PEP_ct_strong_encryption";
  31.236 +        case PEP_ct_OpenPGP:
  31.237 +            return "PEP_ct_OpenPGP";
  31.238 +        case PEP_ct_OTR:
  31.239 +            return "PEP_ct_OTR";
  31.240 +        case PEP_ct_confirmed_enc_anon:
  31.241 +            return "PEP_ct_confirmed_enc_anon";
  31.242 +        case PEP_ct_pEp:
  31.243 +            return "PEP_ct_pEp";
  31.244 +        default:
  31.245 +            return "PEP_ct_OMGWTFBBQ\n\nIn other words, comm type is invalid. Either something's corrupt or a new ct value has been added to the enum but not to the test function.";
  31.246 +    }
  31.247 +}
    32.1 --- a/test/test_util.h	Mon Mar 27 14:53:29 2017 +0200
    32.2 +++ b/test/test_util.h	Tue Jun 06 18:00:40 2017 +0200
    32.3 @@ -1,5 +1,16 @@
    32.4  #include <string>
    32.5 +#include "pEpEngine.h"
    32.6 +#include "message_api.h"
    32.7  
    32.8  // reads a whole file and returns it as std::string
    32.9  // throws std::runtime_error() if the file cannot be read. Empty file is not an error.
   32.10  std::string slurp(const std::string& filename);
   32.11 +
   32.12 +// Returns the string value of the input rating enum value. 
   32.13 +const char* tl_rating_string(PEP_rating rating);
   32.14 +
   32.15 +// Returns the string value of the input comm_type enum value. 
   32.16 +const char* tl_ct_string(PEP_comm_type ct);
   32.17 +
   32.18 +// Returns the string value of the input status enum value. 
   32.19 +const char* tl_status_string(PEP_STATUS status);
    33.1 --- a/test/trustwords_test.cc	Mon Mar 27 14:53:29 2017 +0200
    33.2 +++ b/test/trustwords_test.cc	Tue Jun 06 18:00:40 2017 +0200
    33.3 @@ -33,6 +33,12 @@
    33.4          "blargh",
    33.5          "Krista Grothoff");
    33.6      
    33.7 +    pEp_identity* identity2_with_spaces = new_identity(
    33.8 +        "krista@kgrothoff.org",
    33.9 +        " 62D4932086185C159 17B72D30571A FBCA    5493553   ",
   33.10 +        "blargh",
   33.11 +        "Krista Grothoff");
   33.12 +    
   33.13      string fingerprint1 = identity1->fpr;
   33.14      string fingerprint2 = identity2->fpr;
   33.15      char* words1 = nullptr;
   33.16 @@ -58,6 +64,11 @@
   33.17      get_trustwords(session, identity1, identity2, "de", &full_wordlist, &wsize_full, false);
   33.18      assert(full_wordlist);
   33.19      cout << full_wordlist << "\n";
   33.20 +
   33.21 +    cout << "\nfinding Englis trustwords for " << identity1->address << " and " << identity2->address << "... with spaces\n";
   33.22 +    get_trustwords(session, identity1, identity2_with_spaces, "en", &full_wordlist, &wsize_full, false);
   33.23 +    assert(full_wordlist);
   33.24 +    cout << full_wordlist << "\n";
   33.25      
   33.26      
   33.27      pEp_free(words1);
   33.28 @@ -79,6 +90,11 @@
   33.29      assert(full_wordlist);
   33.30      cout << full_wordlist << "\n";
   33.31  
   33.32 +    cout << "\nfinding English trustwords for " << identity2->address << " and " << identity2->address << "... with spaces\n";
   33.33 +    get_trustwords(session, identity2, identity2_with_spaces, "en", &full_wordlist, &wsize_full, false);
   33.34 +    assert(full_wordlist);
   33.35 +    cout << full_wordlist << "\n";
   33.36 +
   33.37      pEp_free(words1);
   33.38      words1 = nullptr;
   33.39      pEp_free(full_wordlist);
   33.40 @@ -101,6 +117,11 @@
   33.41      assert(full_wordlist);
   33.42      cout << full_wordlist << "\n";
   33.43      
   33.44 +    cout << "\nfinding English trustwords for " << identity2->address << " and " << identity2->address << "... with spaces\n";
   33.45 +    get_trustwords(session, identity2_with_spaces, identity1, "en", &full_wordlist, &wsize_full, false);
   33.46 +    assert(full_wordlist);
   33.47 +    cout << full_wordlist << "\n";
   33.48 +    
   33.49      pEp_free(words1);
   33.50      words1 = nullptr;
   33.51      pEp_free(words2);