merged in default ENGINE-329
authorKrista Bennett <krista@pep-project.org>
Thu, 25 Jan 2018 14:10:02 +0100
branchENGINE-329
changeset 24514de19faa36b3
parent 2417 9a6230237b1a
parent 2450 719ec5a51303
child 2456 713e5eead807
merged in default
src/pgp_gpg.c
     1.1 --- a/build-mac/pEpEngine.xcodeproj/project.pbxproj	Fri Jan 19 14:04:57 2018 +0100
     1.2 +++ b/build-mac/pEpEngine.xcodeproj/project.pbxproj	Thu Jan 25 14:10:02 2018 +0100
     1.3 @@ -7,6 +7,8 @@
     1.4  	objects = {
     1.5  
     1.6  /* Begin PBXBuildFile section */
     1.7 +		430BCC482015EE800077E998 /* pEp_string.h in Headers */ = {isa = PBXBuildFile; fileRef = 430BCC462015EE800077E998 /* pEp_string.h */; };
     1.8 +		430BCC492015EE800077E998 /* pEp_string.c in Sources */ = {isa = PBXBuildFile; fileRef = 430BCC472015EE800077E998 /* pEp_string.c */; };
     1.9  		430D258B1C9ED75A00B94535 /* blacklist.c in Sources */ = {isa = PBXBuildFile; fileRef = 430D258A1C9ED75A00B94535 /* blacklist.c */; };
    1.10  		4354FF651D6EDF300033069C /* sync_impl.c in Sources */ = {isa = PBXBuildFile; fileRef = 4354FF641D6EDF300033069C /* sync_impl.c */; };
    1.11  		4354FF691D6EE1A70033069C /* NULL.c in Sources */ = {isa = PBXBuildFile; fileRef = 4354FF681D6EE1A70033069C /* NULL.c */; };
    1.12 @@ -189,6 +191,8 @@
    1.13  /* End PBXCopyFilesBuildPhase section */
    1.14  
    1.15  /* Begin PBXFileReference section */
    1.16 +		430BCC462015EE800077E998 /* pEp_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pEp_string.h; path = ../src/pEp_string.h; sourceTree = "<group>"; };
    1.17 +		430BCC472015EE800077E998 /* pEp_string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pEp_string.c; path = ../src/pEp_string.c; sourceTree = "<group>"; };
    1.18  		430D258A1C9ED75A00B94535 /* blacklist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = blacklist.c; path = ../src/blacklist.c; sourceTree = "<group>"; };
    1.19  		4346F86A1ECB38E700381CBE /* sync_app.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sync_app.h; path = ../src/sync_app.h; sourceTree = "<group>"; };
    1.20  		4354FF641D6EDF300033069C /* sync_impl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_impl.c; path = ../src/sync_impl.c; sourceTree = "<group>"; };
    1.21 @@ -508,6 +512,8 @@
    1.22  		64A8264B1B455C5600EECAF0 /* srcref */ = {
    1.23  			isa = PBXGroup;
    1.24  			children = (
    1.25 +				430BCC472015EE800077E998 /* pEp_string.c */,
    1.26 +				430BCC462015EE800077E998 /* pEp_string.h */,
    1.27  				43F6921C1F164A47009418F5 /* resource_id.c */,
    1.28  				43BA0F451D7964750059172F /* asn1_helper.c */,
    1.29  				4354FF641D6EDF300033069C /* sync_impl.c */,
    1.30 @@ -617,6 +623,7 @@
    1.31  				646C41481D510D2C00C63EFF /* sync_fsm.h in Headers */,
    1.32  				64A8268C1B455D9D00EECAF0 /* pEpEngine.h in Headers */,
    1.33  				646C41091D510CD800C63EFF /* constr_TYPE.h in Headers */,
    1.34 +				430BCC482015EE800077E998 /* pEp_string.h in Headers */,
    1.35  				646C410D1D510CD800C63EFF /* der_encoder.h in Headers */,
    1.36  				646C41231D510CD800C63EFF /* NativeEnumerated.h in Headers */,
    1.37  				646C41071D510CD800C63EFF /* constr_SET_OF.h in Headers */,
    1.38 @@ -852,6 +859,7 @@
    1.39  				646C412A1D510CD800C63EFF /* per_encoder.c in Sources */,
    1.40  				646C412E1D510CD800C63EFF /* per_support.c in Sources */,
    1.41  				64A826781B455D0800EECAF0 /* bloblist.c in Sources */,
    1.42 +				430BCC492015EE800077E998 /* pEp_string.c in Sources */,
    1.43  				646C41041D510CD800C63EFF /* constr_SEQUENCE.c in Sources */,
    1.44  				64A826881B455D0800EECAF0 /* timestamp.c in Sources */,
    1.45  				646C41221D510CD800C63EFF /* NativeEnumerated.c in Sources */,
     2.1 --- a/src/keymanagement.c	Fri Jan 19 14:04:57 2018 +0100
     2.2 +++ b/src/keymanagement.c	Thu Jan 25 14:10:02 2018 +0100
     2.3 @@ -15,13 +15,8 @@
     2.4  #include "sync_fsm.h"
     2.5  #include "blacklist.h"
     2.6  
     2.7 -#ifndef EMPTYSTR
     2.8 -#define EMPTYSTR(STR) ((STR) == NULL || (STR)[0] == '\0')
     2.9 -#endif
    2.10 -
    2.11  #define KEY_EXPIRE_DELTA (60 * 60 * 24 * 365)
    2.12  
    2.13 -
    2.14  static bool key_matches_address(PEP_SESSION session, const char* address,
    2.15                                  const char* fpr) {
    2.16      if (!session || !address || !fpr)
    2.17 @@ -1056,7 +1051,16 @@
    2.18          if (session->cached_mistrusted)
    2.19              free(session->cached_mistrusted);
    2.20          session->cached_mistrusted = identity_dup(ident);
    2.21 -        status = mark_as_compromized(session, ident->fpr);
    2.22 +        
    2.23 +        // set mistrust for this user_id/keypair (even if there's not an
    2.24 +        // identity set yet, this is important, as we need to record the mistrust
    2.25 +        // action)
    2.26 +        status = set_trust(session, ident->user_id, ident->fpr, PEP_ct_mistrusted);
    2.27 +        if (status == PEP_STATUS_OK)
    2.28 +            // cascade that mistrust for anyone using this key
    2.29 +            status = mark_as_compromized(session, ident->fpr);
    2.30 +        if (status == PEP_STATUS_OK)
    2.31 +            status = remove_fpr_as_default(session, ident->fpr);
    2.32      }
    2.33  
    2.34      return status;
    2.35 @@ -1093,30 +1097,70 @@
    2.36  
    2.37      assert(session);
    2.38      assert(ident);
    2.39 -    assert(!ident->me);
    2.40      assert(!EMPTYSTR(ident->fpr));
    2.41      assert(!EMPTYSTR(ident->address));
    2.42      assert(!EMPTYSTR(ident->user_id));
    2.43  
    2.44 -    if (!(session && ident && !ident->me && ident->fpr && ident->address &&
    2.45 +    if (!(session && ident && ident->fpr && ident->fpr[0] != '\0' && ident->address &&
    2.46              ident->user_id))
    2.47          return PEP_ILLEGAL_VALUE;
    2.48  
    2.49 -    status = update_identity(session, ident);
    2.50 +    // we do not change the input struct at ALL.
    2.51 +    pEp_identity* input_copy = identity_dup(ident);
    2.52 +    
    2.53 +    pEp_identity* tmp_ident = NULL;
    2.54 +    
    2.55 +    status = get_trust(session, input_copy);
    2.56 +    
    2.57      if (status != PEP_STATUS_OK)
    2.58 -        return status;
    2.59 +        goto pep_free;
    2.60 +        
    2.61 +    PEP_comm_type new_trust = PEP_ct_unknown;
    2.62  
    2.63 -    if (ident->comm_type == PEP_ct_mistrusted)
    2.64 -        ident->comm_type = PEP_ct_unknown;
    2.65 -    else
    2.66 -        ident->comm_type &= ~PEP_ct_confirmed;
    2.67 +    if (input_copy->comm_type != PEP_ct_mistrusted)
    2.68 +        new_trust = input_copy->comm_type & ~PEP_ct_confirmed;
    2.69  
    2.70 -    status = set_identity(session, ident);
    2.71 +    status = set_trust(session, ident->user_id, ident->fpr, new_trust);
    2.72 +    
    2.73      if (status != PEP_STATUS_OK)
    2.74 -        return status;
    2.75 +        goto pep_free;
    2.76  
    2.77 -    if (ident->comm_type == PEP_ct_unknown)
    2.78 -        status = update_identity(session, ident);
    2.79 +        
    2.80 +    input_copy->comm_type = new_trust;
    2.81 +        
    2.82 +    tmp_ident = new_identity(ident->address, NULL, ident->user_id, NULL);
    2.83 +
    2.84 +    if (!tmp_ident)
    2.85 +        return PEP_OUT_OF_MEMORY;
    2.86 +    
    2.87 +    status = update_identity(session, tmp_ident);
    2.88 +    
    2.89 +    if (status != PEP_STATUS_OK)
    2.90 +        goto pep_free;
    2.91 +    
    2.92 +    // remove as default if necessary
    2.93 +    if (strcmp(tmp_ident->fpr, ident->fpr) == 0) {
    2.94 +        free(tmp_ident->fpr);
    2.95 +        tmp_ident->fpr = NULL;
    2.96 +        tmp_ident->comm_type = PEP_ct_unknown;
    2.97 +        status = set_identity(session, tmp_ident);
    2.98 +        if (status != PEP_STATUS_OK)
    2.99 +            goto pep_free;
   2.100 +    }
   2.101 +    
   2.102 +    char* user_default = NULL;
   2.103 +    status = get_main_user_fpr(session, tmp_ident->user_id, &user_default);
   2.104 +    
   2.105 +    if (!EMPTYSTR(user_default)) {
   2.106 +        if (strcmp(user_default, ident->fpr) == 0)
   2.107 +            status = refresh_userid_default_key(session, ident->user_id);
   2.108 +        if (status != PEP_STATUS_OK)
   2.109 +            goto pep_free;    
   2.110 +    }
   2.111 +            
   2.112 +pep_free:
   2.113 +    free_identity(tmp_ident);
   2.114 +    free_identity(input_copy);
   2.115      return status;
   2.116  }
   2.117  
   2.118 @@ -1137,18 +1181,99 @@
   2.119              EMPTYSTR(ident->fpr))
   2.120          return PEP_ILLEGAL_VALUE;
   2.121  
   2.122 -    status = update_identity(session, ident);
   2.123 -    if (status != PEP_STATUS_OK)
   2.124 -        return status;
   2.125 +    //bool ident_has_trusted_default = false;
   2.126 +    char* ident_default_fpr = NULL;
   2.127  
   2.128 -    if (ident->comm_type > PEP_ct_strong_but_unconfirmed) {
   2.129 -        ident->comm_type |= PEP_ct_confirmed;
   2.130 -        status = set_identity(session, ident);
   2.131 -    }
   2.132 -    else {
   2.133 -        // MISSING: S/MIME has to be handled depending on trusted CAs
   2.134 -        status = PEP_CANNOT_SET_TRUST;
   2.135 -    }
   2.136 +    // Before we do anything, be sure the input fpr is even eligible to be trusted
   2.137 +    PEP_comm_type input_default_ct = PEP_ct_unknown;
   2.138 +    status = get_key_rating(session, ident->fpr, &input_default_ct);
   2.139 +    if (input_default_ct < PEP_ct_strong_but_unconfirmed)
   2.140 +        return PEP_KEY_UNSUITABLE;
   2.141 +
   2.142 +    // Save the input fpr
   2.143 +    char* cached_fpr = strdup(ident->fpr);
   2.144 +    ident->fpr = NULL;
   2.145 +
   2.146 +    bool me = is_me(session, ident);
   2.147 +
   2.148 +    if (me)
   2.149 +        return myself(session, ident); // FIXME: Not the right thing if we 
   2.150 +                                       // don't always replace user default!!!
   2.151 +
   2.152 +    // First, set up a temp trusted identity for the input fpr without a comm type;
   2.153 +    pEp_identity* tmp_id = new_identity(ident->address, cached_fpr, ident->user_id, NULL);
   2.154 +    status = validate_fpr(session, tmp_id);
   2.155 +        
   2.156 +    if (status == PEP_STATUS_OK) {
   2.157 +        // Validate fpr gets trust DB or, when that fails, key comm type. we checked
   2.158 +        // above that the key was ok. (not revoked or expired), but we want the max.
   2.159 +        tmp_id->comm_type = _MAX(tmp_id->comm_type, input_default_ct) | PEP_ct_confirmed;
   2.160 +                                       
   2.161 +        // Get the default identity without setting the fpr
   2.162 +        status = update_identity(session, ident);
   2.163 +        ident_default_fpr = strdup(ident->fpr);
   2.164 +
   2.165 +        if (status == PEP_STATUS_OK) {
   2.166 +            bool trusted_default = false;
   2.167 +
   2.168 +            // If there's no default, or the default is different from the input...
   2.169 +            if (EMPTYSTR(ident_default_fpr) || strcmp(cached_fpr, ident_default_fpr) != 0) {
   2.170 +                
   2.171 +                // If the default fpr (if there is one) is trusted and key is strong enough,
   2.172 +                // don't replace, we just set the trusted bit on this key for this user_id...
   2.173 +                // (If there's no default fpr, this won't be true anyway.)
   2.174 +                if (ident->comm_type >= PEP_ct_strong_but_unconfirmed && 
   2.175 +                    (ident->comm_type & PEP_ct_confirmed)) {                        
   2.176 +
   2.177 +                    trusted_default = true;
   2.178 +                                    
   2.179 +                    status = set_trust(session, tmp_id->user_id, cached_fpr, tmp_id->comm_type);
   2.180 +                    input_default_ct = tmp_id->comm_type;                    
   2.181 +                }
   2.182 +                else {
   2.183 +                    free(ident->fpr);
   2.184 +                    ident->fpr = strdup(cached_fpr);
   2.185 +                    ident->comm_type = tmp_id->comm_type;
   2.186 +                    status = set_identity(session, ident); // replace identity default            
   2.187 +                }
   2.188 +            }
   2.189 +            else { // we're setting this on the default fpr
   2.190 +                ident->comm_type = tmp_id->comm_type;
   2.191 +                status = set_identity(session, ident);
   2.192 +                trusted_default = true;
   2.193 +            }
   2.194 +            if (status == PEP_STATUS_OK && !trusted_default) {
   2.195 +                // Ok, there wasn't a trusted default, so we replaced. Thus, we also
   2.196 +                // make sure there's a trusted default on the user_id. If there
   2.197 +                // is not, we make this the default.
   2.198 +                char* user_default = NULL;
   2.199 +                status = get_main_user_fpr(session, ident->user_id, &user_default);
   2.200 +            
   2.201 +                if (status == PEP_STATUS_OK && user_default) {
   2.202 +                    pEp_identity* tmp_user_ident = new_identity(ident->address, 
   2.203 +                                                                user_default, 
   2.204 +                                                                ident->user_id, 
   2.205 +                                                                NULL);
   2.206 +                    if (!tmp_user_ident)
   2.207 +                        status = PEP_OUT_OF_MEMORY;
   2.208 +                    else {
   2.209 +                        status = validate_fpr(session, tmp_user_ident);
   2.210 +                        
   2.211 +                        if (status != PEP_STATUS_OK ||
   2.212 +                            tmp_user_ident->comm_type < PEP_ct_strong_but_unconfirmed ||
   2.213 +                            !(tmp_user_ident->comm_type & PEP_ct_confirmed)) 
   2.214 +                        {
   2.215 +                            char* trusted_fpr = (trusted_default ? ident_default_fpr : cached_fpr);
   2.216 +                            status = replace_main_user_fpr(session, ident->user_id, trusted_fpr);
   2.217 +                        } 
   2.218 +                    }
   2.219 +                }
   2.220 +            }
   2.221 +        }
   2.222 +        free(ident_default_fpr);
   2.223 +        free(cached_fpr);
   2.224 +        free_identity(tmp_id);
   2.225 +    }    
   2.226  
   2.227      return status;
   2.228  }
     3.1 --- a/src/keymanagement.h	Fri Jan 19 14:04:57 2018 +0100
     3.2 +++ b/src/keymanagement.h	Thu Jan 25 14:10:02 2018 +0100
     3.3 @@ -189,6 +189,15 @@
     3.4  //  parameters:
     3.5  //      session (in)        session to use
     3.6  //      ident (in)          person and key which was compromised
     3.7 +//  caveat:
     3.8 +//      ident is INPUT ONLY. If you want updated trust on the identity, you'll have
     3.9 +//      to call update_identity or myself respectively after this.
    3.10 +//      N.B. If you are calling this on a key that is the identity or user default,
    3.11 +//      it will be removed as the default key for ANY identity and user for which
    3.12 +//      it is the default. Please keep in mind that the undo in undo_last_mistrust
    3.13 +//      will only undo the current identity's / it's user's default, not any
    3.14 +//      other identities which may be impacted (this will not affect most use
    3.15 +//      cases)
    3.16  
    3.17  DYNAMIC_API PEP_STATUS key_mistrusted(
    3.18          PEP_SESSION session,
    3.19 @@ -214,7 +223,7 @@
    3.20  DYNAMIC_API PEP_STATUS undo_last_mistrust(PEP_SESSION session);
    3.21  
    3.22  
    3.23 -// trust_personal_key() - mark a key as trusted with a person
    3.24 +// trust_personal_key() - mark a key as trusted for a user
    3.25  //
    3.26  //  parameters:
    3.27  //      session (in)        session to use
    3.28 @@ -222,6 +231,11 @@
    3.29  //
    3.30  //  caveat:
    3.31  //      the fields user_id, address and fpr must be supplied
    3.32 +//      for non-own users, this will 1) set the trust bit on its comm type in the DN,
    3.33 +//      2) set this key as the identity default if the current identity default
    3.34 +//      is not trusted, and 3) set this key as the user default if the current
    3.35 +//      user default is not trusted.
    3.36 +//      For an own user, this is simply a call to myself().
    3.37  
    3.38  DYNAMIC_API PEP_STATUS trust_personal_key(
    3.39          PEP_SESSION session,
    3.40 @@ -229,12 +243,18 @@
    3.41      );
    3.42  
    3.43  
    3.44 -// key_reset_trust() - undo trust_personal_key and key_mistrusted() for keys
    3.45 -//                     we don't own
    3.46 -//
    3.47 +// key_reset_trust() - reset trust bit or explicitly mistrusted status for an identity and
    3.48 +//                     its accompanying key/user_id pair.
    3.49  //  parameters:
    3.50  //      session (in)        session to use
    3.51 -//      ident (in)          person and key which was compromized
    3.52 +//      ident (in)          identity for person and key whose trust status is to be reset
    3.53 +//
    3.54 +//  caveat:
    3.55 +//      ident is INPUT ONLY. If you want updated trust on the identity, you'll have
    3.56 +//      to call update_identity or myself respectively after this.
    3.57 +//      N.B. If you are calling this on a key that is the identity or user default,
    3.58 +//      it will be removed as the default key for the identity and user (but is still
    3.59 +//      available for key election, it is just not the cached default anymore)
    3.60  
    3.61  DYNAMIC_API PEP_STATUS key_reset_trust(
    3.62          PEP_SESSION session,
     4.1 --- a/src/message_api.c	Fri Jan 19 14:04:57 2018 +0100
     4.2 +++ b/src/message_api.c	Thu Jan 25 14:10:02 2018 +0100
     4.3 @@ -933,7 +933,10 @@
     4.4      for (id_list_ptr = list; id_list_ptr; id_list_ptr = id_list_ptr->next) {
     4.5          pEp_identity* curr_identity = id_list_ptr->ident;
     4.6          if (curr_identity) {
     4.7 -            status = update_identity(session, curr_identity);
     4.8 +            if (!is_me(session, curr_identity))
     4.9 +                status = update_identity(session, curr_identity);
    4.10 +            else
    4.11 +                status = myself(session, curr_identity);
    4.12          if (status == PEP_ILLEGAL_VALUE || status == PEP_OUT_OF_MEMORY)
    4.13              return status;
    4.14          }
    4.15 @@ -1230,13 +1233,17 @@
    4.16      return rating;
    4.17  }
    4.18  
    4.19 +// Internal function WARNING:
    4.20 +// Only call this on an ident that might have its FPR set from retrieval!
    4.21 +// (or on one without an fpr)
    4.22 +// We do not want myself() setting the fpr here.
    4.23  static PEP_comm_type _get_comm_type(
    4.24      PEP_SESSION session,
    4.25      PEP_comm_type max_comm_type,
    4.26      pEp_identity *ident
    4.27      )
    4.28  {
    4.29 -    PEP_STATUS status = update_identity(session, ident);
    4.30 +    PEP_STATUS status = PEP_STATUS_OK;
    4.31  
    4.32      if (max_comm_type == PEP_ct_compromized)
    4.33          return PEP_ct_compromized;
    4.34 @@ -1244,6 +1251,11 @@
    4.35      if (max_comm_type == PEP_ct_mistrusted)
    4.36          return PEP_ct_mistrusted;
    4.37  
    4.38 +    if (!is_me(session, ident))
    4.39 +        status = update_identity(session, ident);
    4.40 +    else
    4.41 +        status = myself(session, ident);
    4.42 +
    4.43      if (status == PEP_STATUS_OK) {
    4.44          if (ident->comm_type == PEP_ct_compromized)
    4.45              return PEP_ct_compromized;
    4.46 @@ -1499,7 +1511,16 @@
    4.47              return PEP_ILLEGAL_VALUE;
    4.48          }
    4.49  
    4.50 -        PEP_STATUS _status = update_identity(session, _il->ident);
    4.51 +        PEP_STATUS _status = PEP_STATUS_OK;
    4.52 +        if (!is_me(session, _il->ident)) {
    4.53 +            _status = update_identity(session, _il->ident);
    4.54 +            if (_status == PEP_CANNOT_FIND_IDENTITY) {
    4.55 +                _il->ident->comm_type = PEP_ct_key_not_found;
    4.56 +                _status = PEP_STATUS_OK;
    4.57 +            }
    4.58 +        }
    4.59 +        else
    4.60 +            _status = myself(session, _il->ident);
    4.61          if (_status != PEP_STATUS_OK) {
    4.62              status = _status;
    4.63              GOTO(pep_error);
    4.64 @@ -1520,7 +1541,16 @@
    4.65      else
    4.66      {
    4.67          for (_il = src->to; _il && _il->ident; _il = _il->next) {
    4.68 -            PEP_STATUS _status = update_identity(session, _il->ident);
    4.69 +            PEP_STATUS _status = PEP_STATUS_OK;
    4.70 +            if (!is_me(session, _il->ident)) {
    4.71 +                _status = update_identity(session, _il->ident);
    4.72 +                if (_status == PEP_CANNOT_FIND_IDENTITY) {
    4.73 +                    _il->ident->comm_type = PEP_ct_key_not_found;
    4.74 +                    _status = PEP_STATUS_OK;
    4.75 +                }
    4.76 +            }
    4.77 +            else
    4.78 +                _status = myself(session, _il->ident);
    4.79              if (_status != PEP_STATUS_OK) {
    4.80                  status = _status;
    4.81                  GOTO(pep_error);
    4.82 @@ -1540,7 +1570,16 @@
    4.83          }
    4.84  
    4.85          for (_il = src->cc; _il && _il->ident; _il = _il->next) {
    4.86 -            PEP_STATUS _status = update_identity(session, _il->ident);
    4.87 +            PEP_STATUS _status = PEP_STATUS_OK;
    4.88 +            if (!is_me(session, _il->ident)) {
    4.89 +                _status = update_identity(session, _il->ident);
    4.90 +                if (_status == PEP_CANNOT_FIND_IDENTITY) {
    4.91 +                    _il->ident->comm_type = PEP_ct_key_not_found;
    4.92 +                    _status = PEP_STATUS_OK;
    4.93 +                }
    4.94 +            }
    4.95 +            else
    4.96 +                _status = myself(session, _il->ident);
    4.97              if (_status != PEP_STATUS_OK)
    4.98              {
    4.99                  status = _status;
   4.100 @@ -1792,7 +1831,10 @@
   4.101      PEP_STATUS status;
   4.102  
   4.103      if (src->from && src->from->address) {
   4.104 -        status = update_identity(session, src->from);
   4.105 +        if (!is_me(session, src->from))
   4.106 +            status = update_identity(session, src->from);
   4.107 +        else
   4.108 +            status = myself(session, src->from);
   4.109          if (status == PEP_STATUS_OK
   4.110                  && is_a_pEpmessage(src)
   4.111                  && src->from->comm_type >= PEP_ct_OpenPGP_unconfirmed
   4.112 @@ -2002,7 +2044,6 @@
   4.113              status = get_trust(session, _sender);
   4.114              if (_sender->comm_type == PEP_ct_unknown) {
   4.115                  get_key_rating(session, fpr, &_sender->comm_type);
   4.116 -                
   4.117              }
   4.118              if (_sender->comm_type != PEP_ct_unknown) {
   4.119                  *rating = keylist_rating(session, recipients, 
   4.120 @@ -2603,8 +2644,12 @@
   4.121                                              // FIXME: free msg, but check references
   4.122                                              src = msg = inner_message;
   4.123                                              
   4.124 -                                            if (src->from)
   4.125 -                                                update_identity(session, src->from);
   4.126 +                                            if (src->from) {
   4.127 +                                                if (!is_me(session, src->from))
   4.128 +                                                    update_identity(session, (src->from));
   4.129 +                                                else
   4.130 +                                                    myself(session, src->from);
   4.131 +                                            }
   4.132                                              break;        
   4.133                                          }
   4.134                                          else { // should never happen
   4.135 @@ -2762,8 +2807,12 @@
   4.136      for (il = identities; il != NULL; il = il->next)
   4.137      {
   4.138          if (il->ident)
   4.139 -        {
   4.140 -            PEP_STATUS status = update_identity(session, il->ident);
   4.141 +        {   
   4.142 +            PEP_STATUS status = PEP_STATUS_OK;
   4.143 +            if (!is_me(session, il->ident))
   4.144 +                status = update_identity(session, il->ident);
   4.145 +            else
   4.146 +                status = myself(session, il->ident);
   4.147              if (status == PEP_STATUS_OK)
   4.148              {
   4.149                  *max_comm_type = _get_comm_type(session, *max_comm_type,
   4.150 @@ -3205,14 +3254,15 @@
   4.151  
   4.152      // MIME decode message delivers only addresses. We need more.
   4.153      if (tmp_msg->from) {
   4.154 -        status = update_identity(session, tmp_msg->from);
   4.155 +        if (!is_me(session, tmp_msg->from))
   4.156 +            status = update_identity(session, (tmp_msg->from));
   4.157 +        else
   4.158 +            status = myself(session, tmp_msg->from);
   4.159 +
   4.160          if (status == PEP_ILLEGAL_VALUE || status == PEP_OUT_OF_MEMORY)
   4.161              GOTO(pep_error);
   4.162      }
   4.163  
   4.164 -    // Own identities can be retrieved here where they would otherwise
   4.165 -    // fail because we lack all other information. This is ok and even
   4.166 -    // desired. FIXME: IS it?
   4.167      status = update_identity_recip_list(session, tmp_msg->to);
   4.168      if (status != PEP_STATUS_OK)
   4.169          GOTO(pep_error);
   4.170 @@ -3510,7 +3560,11 @@
   4.171      }
   4.172  got_keylist:
   4.173  
   4.174 -    status = update_identity(session, msg->from);
   4.175 +    if (!is_me(session, msg->from))
   4.176 +        status = update_identity(session, msg->from);
   4.177 +    else
   4.178 +        status = myself(session, msg->from);
   4.179 +
   4.180      if (status != PEP_STATUS_OK)
   4.181          GOTO(pep_error);
   4.182  
     5.1 --- a/src/pEpEngine.c	Fri Jan 19 14:04:57 2018 +0100
     5.2 +++ b/src/pEpEngine.c	Thu Jan 25 14:10:02 2018 +0100
     5.3 @@ -113,6 +113,27 @@
     5.4      "update person set id = ?1 " 
     5.5      "where id = ?2;";
     5.6  
     5.7 +static const char *sql_replace_main_user_fpr =  
     5.8 +    "update person "
     5.9 +    "   set main_key_id = ?1 "
    5.10 +    "   where id = ?2 ;";
    5.11 +
    5.12 +static const char *sql_get_main_user_fpr =  
    5.13 +    "select main_key_id from person"
    5.14 +    "   where id = ?1 ;";
    5.15 +
    5.16 +static const char *sql_refresh_userid_default_key =
    5.17 +    "update person "
    5.18 +    "   set main_key_id = "
    5.19 +    "       (select identity.main_key_id from identity "
    5.20 +    "           join trust on trust.user_id = identity.user_id "
    5.21 +    "               and trust.pgp_keypair_fpr = identity.main_key_id "
    5.22 +    "           join person on identity.user_id = identity.user_id "
    5.23 +    "       where identity.user_id = ?1 "
    5.24 +    "       order by trust.comm_type desc "
    5.25 +    "       limit 1) "
    5.26 +    "where id = ?1 ; ";
    5.27 +
    5.28  static const char *sql_get_device_group = 
    5.29      "select device_group from person "
    5.30      "where id = ?1;";
    5.31 @@ -175,7 +196,7 @@
    5.32  static const char *sql_mark_as_compromized = 
    5.33      "update trust not indexed set comm_type = 15"
    5.34      " where pgp_keypair_fpr = upper(replace(?1,' ','')) ;";
    5.35 -
    5.36 +    
    5.37  static const char *sql_crashdump = 
    5.38      "select timestamp, title, entity, description, comment"
    5.39      " from log order by timestamp desc limit ?1 ;";
    5.40 @@ -823,6 +844,18 @@
    5.41              (int)strlen(sql_replace_userid), &_session->replace_userid, NULL);
    5.42      assert(int_result == SQLITE_OK);
    5.43  
    5.44 +    int_result = sqlite3_prepare_v2(_session->db, sql_replace_main_user_fpr,
    5.45 +            (int)strlen(sql_replace_main_user_fpr), &_session->replace_main_user_fpr, NULL);
    5.46 +    assert(int_result == SQLITE_OK);
    5.47 +
    5.48 +    int_result = sqlite3_prepare_v2(_session->db, sql_get_main_user_fpr,
    5.49 +            (int)strlen(sql_get_main_user_fpr), &_session->get_main_user_fpr, NULL);
    5.50 +    assert(int_result == SQLITE_OK);
    5.51 +
    5.52 +    int_result = sqlite3_prepare_v2(_session->db, sql_refresh_userid_default_key,
    5.53 +            (int)strlen(sql_refresh_userid_default_key), &_session->refresh_userid_default_key, NULL);
    5.54 +    assert(int_result == SQLITE_OK);
    5.55 +
    5.56      int_result = sqlite3_prepare_v2(_session->db, sql_replace_identities_fpr,
    5.57              (int)strlen(sql_replace_identities_fpr), 
    5.58              &_session->replace_identities_fpr, NULL);
    5.59 @@ -981,9 +1014,6 @@
    5.60  
    5.61      // runtime config
    5.62  
    5.63 -#ifdef ANDROID
    5.64 -#elif TARGET_OS_IPHONE
    5.65 -#else /* Desktop */
    5.66      if (very_first)
    5.67      {
    5.68          // On first run, all private keys already present in PGP keyring 
    5.69 @@ -996,7 +1026,7 @@
    5.70          //
    5.71          // Indeed, if pEpEngine did import spoofed private keys in previous
    5.72          // install, then those keys become automatically trusted in case 
    5.73 -        // pEp_management.db is deleted.
    5.74 +        // management.db is deleted.
    5.75          //
    5.76          // A solution to distinguish bare GPG keyring from pEp keyring is
    5.77          // needed here. Then keys managed by pEpEngine wouldn't be
    5.78 @@ -1020,7 +1050,6 @@
    5.79              }
    5.80          }
    5.81      }
    5.82 -#endif
    5.83  
    5.84      // sync_session set to own session by default
    5.85      // sync_session is then never null on a valid session
    5.86 @@ -1117,6 +1146,12 @@
    5.87                  sqlite3_finalize(session->i18n_token);
    5.88              if (session->replace_userid)
    5.89                  sqlite3_finalize(session->replace_userid);
    5.90 +            if (session->replace_main_user_fpr)
    5.91 +                sqlite3_finalize(session->replace_main_user_fpr);                
    5.92 +            if (session->get_main_user_fpr)
    5.93 +                sqlite3_finalize(session->get_main_user_fpr);
    5.94 +            if (session->refresh_userid_default_key)
    5.95 +                sqlite3_finalize(session->refresh_userid_default_key);
    5.96              if (session->blacklist_add)
    5.97                  sqlite3_finalize(session->blacklist_add);
    5.98              if (session->blacklist_delete)
    5.99 @@ -1791,7 +1826,7 @@
   5.100      bool has_fpr = (identity->fpr && identity->fpr[0] != '\0');
   5.101      
   5.102      if (has_fpr) {    
   5.103 -        // blacklist check
   5.104 +        // blacklist check - FIXME: ENGINE-294 will remove
   5.105          status = blacklist_is_listed(session, identity->fpr, &listed);
   5.106          assert(status == PEP_STATUS_OK);
   5.107          if (status != PEP_STATUS_OK)
   5.108 @@ -2092,8 +2127,8 @@
   5.109      sqlite3_reset(session->unset_identity_flags);
   5.110      if (result != SQLITE_DONE)
   5.111          return PEP_CANNOT_SET_IDENTITY;
   5.112 -
   5.113 -    identity->flags &= ~flags;
   5.114 +        identity->flags &= ~flags;
   5.115 +
   5.116      return PEP_STATUS_OK;
   5.117  }
   5.118  
   5.119 @@ -2123,6 +2158,89 @@
   5.120      return PEP_STATUS_OK;
   5.121  }
   5.122  
   5.123 +PEP_STATUS refresh_userid_default_key(PEP_SESSION session, const char* user_id) {
   5.124 +    assert(session);
   5.125 +    assert(user_id);
   5.126 +    
   5.127 +    if (!session || !user_id)
   5.128 +        return PEP_ILLEGAL_VALUE;
   5.129 +
   5.130 +    int result;
   5.131 +
   5.132 +    sqlite3_reset(session->refresh_userid_default_key);
   5.133 +    sqlite3_bind_text(session->refresh_userid_default_key, 1, user_id, -1,
   5.134 +            SQLITE_STATIC);
   5.135 +    result = sqlite3_step(session->refresh_userid_default_key);
   5.136 +    sqlite3_reset(session->refresh_userid_default_key);
   5.137 +    if (result != SQLITE_DONE)
   5.138 +        return PEP_CANNOT_SET_PERSON;
   5.139 +
   5.140 +    return PEP_STATUS_OK;    
   5.141 +}
   5.142 +
   5.143 +PEP_STATUS replace_main_user_fpr(PEP_SESSION session, const char* user_id,
   5.144 +                                 const char* new_fpr) {
   5.145 +    assert(session);
   5.146 +    assert(user_id);
   5.147 +    assert(new_fpr);
   5.148 +    
   5.149 +    if (!session || !user_id || !new_fpr)
   5.150 +        return PEP_ILLEGAL_VALUE;
   5.151 +
   5.152 +    int result;
   5.153 +
   5.154 +    sqlite3_reset(session->replace_main_user_fpr);
   5.155 +    sqlite3_bind_text(session->replace_main_user_fpr, 1, new_fpr, -1,
   5.156 +            SQLITE_STATIC);
   5.157 +    sqlite3_bind_text(session->replace_main_user_fpr, 2, user_id, -1,
   5.158 +            SQLITE_STATIC);
   5.159 +    result = sqlite3_step(session->replace_main_user_fpr);
   5.160 +    sqlite3_reset(session->replace_main_user_fpr);
   5.161 +    if (result != SQLITE_DONE)
   5.162 +        return PEP_CANNOT_SET_PERSON;
   5.163 +
   5.164 +    return PEP_STATUS_OK;
   5.165 +}
   5.166 +
   5.167 +PEP_STATUS get_main_user_fpr(PEP_SESSION session, 
   5.168 +                             const char* user_id,
   5.169 +                             char** main_fpr)
   5.170 +{
   5.171 +    PEP_STATUS status = PEP_STATUS_OK;
   5.172 +    int result;
   5.173 +    
   5.174 +    assert(session);
   5.175 +    assert(user_id);
   5.176 +    assert(main_fpr);
   5.177 +    
   5.178 +    if (!(session && user_id && user_id[0] && main_fpr))
   5.179 +        return PEP_ILLEGAL_VALUE;
   5.180 +        
   5.181 +    *main_fpr = NULL;
   5.182 +    
   5.183 +    sqlite3_reset(session->get_main_user_fpr);
   5.184 +    sqlite3_bind_text(session->get_main_user_fpr, 1, user_id, -1,
   5.185 +                      SQLITE_STATIC);
   5.186 +    result = sqlite3_step(session->get_main_user_fpr);
   5.187 +    switch (result) {
   5.188 +    case SQLITE_ROW: {
   5.189 +        const char* _fpr = 
   5.190 +            (const char *) sqlite3_column_text(session->get_main_user_fpr, 0);
   5.191 +        if (_fpr)
   5.192 +            *main_fpr = strdup(_fpr);
   5.193 +        if (!(*main_fpr))
   5.194 +            status = PEP_OUT_OF_MEMORY;
   5.195 +        break;
   5.196 +    }
   5.197 +    default:
   5.198 +        status = PEP_CANNOT_FIND_PERSON;
   5.199 +    }
   5.200 +
   5.201 +    sqlite3_reset(session->get_main_user_fpr);
   5.202 +    return status;
   5.203 +}
   5.204 +
   5.205 +
   5.206  DYNAMIC_API PEP_STATUS mark_as_compromized(
   5.207          PEP_SESSION session,
   5.208          const char *fpr
   5.209 @@ -2153,6 +2271,36 @@
   5.210      free(p);
   5.211  }
   5.212  
   5.213 +PEP_STATUS set_trust(PEP_SESSION session, 
   5.214 +                     const char* user_id,
   5.215 +                     const char* fpr, 
   5.216 +                     PEP_comm_type comm_type) 
   5.217 +{
   5.218 +    assert(session);
   5.219 +    assert(user_id);
   5.220 +    assert(fpr);
   5.221 +    
   5.222 +    if (!session || !user_id || user_id[0] == '\0' || !fpr || fpr[0] == '\0')
   5.223 +        return PEP_ILLEGAL_VALUE;
   5.224 +        
   5.225 +    int result;
   5.226 +                
   5.227 +    sqlite3_reset(session->set_trust);
   5.228 +    sqlite3_bind_text(session->set_trust, 1, user_id, -1,
   5.229 +            SQLITE_STATIC);
   5.230 +    sqlite3_bind_text(session->set_trust, 2, fpr, -1,
   5.231 +            SQLITE_STATIC);
   5.232 +    sqlite3_bind_int(session->set_trust, 3, comm_type);
   5.233 +    result = sqlite3_step(session->set_trust);
   5.234 +    assert(result == SQLITE_DONE);
   5.235 +    sqlite3_reset(session->set_trust);
   5.236 +    if (result != SQLITE_DONE)
   5.237 +        return PEP_CANNOT_SET_TRUST;
   5.238 +
   5.239 +    return PEP_STATUS_OK;
   5.240 +}
   5.241 +
   5.242 +
   5.243  DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
   5.244  {
   5.245      PEP_STATUS status = PEP_STATUS_OK;
     6.1 --- a/src/pEpEngine.h	Fri Jan 19 14:04:57 2018 +0100
     6.2 +++ b/src/pEpEngine.h	Thu Jan 25 14:10:02 2018 +0100
     6.3 @@ -37,6 +37,9 @@
     6.4      PEP_INIT_GPGME_INIT_FAILED                      = 0x0111,
     6.5      PEP_INIT_NO_GPG_HOME                            = 0x0112,
     6.6      PEP_INIT_NETPGP_INIT_FAILED                     = 0x0113,
     6.7 +    PEP_INIT_CANNOT_DETERMINE_GPG_VERSION           = 0x0114,
     6.8 +    PEP_INIT_UNSUPPORTED_GPG_VERSION                = 0x0115,
     6.9 +    PEP_INIT_CANNOT_CONFIG_GPG_AGENT                = 0x0116,
    6.10  
    6.11      PEP_INIT_SQLITE3_WITHOUT_MUTEX                  = 0x0120,
    6.12      PEP_INIT_CANNOT_OPEN_DB                         = 0x0121,
    6.13 @@ -55,6 +58,7 @@
    6.14      PEP_CANNOT_SET_IDENTITY                         = 0x0383,
    6.15      PEP_CANNOT_SET_TRUST                            = 0x0384,
    6.16      PEP_KEY_BLACKLISTED                             = 0x0385,
    6.17 +    PEP_CANNOT_FIND_PERSON                          = 0x0386,
    6.18      
    6.19      PEP_CANNOT_FIND_ALIAS                           = 0x0391,
    6.20      PEP_CANNOT_SET_ALIAS                            = 0x0392,
    6.21 @@ -665,6 +669,7 @@
    6.22          const char* default_id,
    6.23          const char* alias_id);
    6.24  
    6.25 +
    6.26  // set_device_group() - update own person's device group
    6.27  //
    6.28  //    parameters:
    6.29 @@ -1214,7 +1219,16 @@
    6.30  PEP_STATUS remove_fpr_as_default(PEP_SESSION session, 
    6.31                                      const char* fpr);
    6.32                                
    6.33 +                                    
    6.34 +PEP_STATUS get_main_user_fpr(PEP_SESSION session, 
    6.35 +                             const char* user_id,
    6.36 +                             char** main_fpr);
    6.37 +
    6.38 +PEP_STATUS replace_main_user_fpr(PEP_SESSION session, const char* user_id,
    6.39 +                              const char* new_fpr);
    6.40      
    6.41 +PEP_STATUS refresh_userid_default_key(PEP_SESSION session, const char* user_id);
    6.42 +
    6.43  #ifdef __cplusplus
    6.44  }
    6.45  #endif
     7.1 --- a/src/pEp_internal.h	Fri Jan 19 14:04:57 2018 +0100
     7.2 +++ b/src/pEp_internal.h	Thu Jan 25 14:10:02 2018 +0100
     7.3 @@ -126,6 +126,9 @@
     7.4      sqlite3_stmt *get_identity_without_trust_check;
     7.5      sqlite3_stmt *get_identities_by_address;
     7.6      sqlite3_stmt *replace_identities_fpr;
     7.7 +    sqlite3_stmt *replace_main_user_fpr;
     7.8 +    sqlite3_stmt *get_main_user_fpr;
     7.9 +    sqlite3_stmt *refresh_userid_default_key;
    7.10      sqlite3_stmt *remove_fpr_as_default;
    7.11      sqlite3_stmt *set_person;
    7.12      sqlite3_stmt *set_device_group;
    7.13 @@ -387,6 +390,18 @@
    7.14      return retval;
    7.15  }
    7.16  
    7.17 +#ifndef EMPTYSTR
    7.18 +#define EMPTYSTR(STR) ((STR) == NULL || (STR)[0] == '\0')
    7.19 +#endif
    7.20 +
    7.21 +#ifndef _MIN
    7.22 +#define _MIN(A, B) ((B) > (A) ? (A) : (B))
    7.23 +#endif
    7.24 +#ifndef _MAX
    7.25 +#define _MAX(A, B) ((B) > (A) ? (B) : (A))
    7.26 +#endif
    7.27 +
    7.28 +
    7.29  // These are globals used in generating message IDs and should only be
    7.30  // computed once, as they're either really constants or OS-dependent
    7.31  
     8.1 --- a/src/pEp_string.c	Fri Jan 19 14:04:57 2018 +0100
     8.2 +++ b/src/pEp_string.c	Thu Jan 25 14:10:02 2018 +0100
     8.3 @@ -1,6 +1,7 @@
     8.4  // This file is under GNU General Public License 3.0
     8.5  // see LICENSE.txt
     8.6  
     8.7 +#include "platform.h"
     8.8  #include "pEp_string.h"
     8.9  
    8.10  #include <stdlib.h>
    8.11 @@ -8,10 +9,6 @@
    8.12  
    8.13  DYNAMIC_API char * new_string(const char *src, size_t len)
    8.14  {
    8.15 -    assert(src || len);
    8.16 -    if (!(src || len))
    8.17 -        return NULL;
    8.18 -
    8.19      char *s = NULL;
    8.20      if (src) {
    8.21          if (len)
    8.22 @@ -21,7 +18,7 @@
    8.23          assert(s);
    8.24      }
    8.25      else {
    8.26 -        s = calloc(1, len);
    8.27 +        s = calloc(1, len + 1);
    8.28          assert(s);
    8.29      }
    8.30  
     9.1 --- a/src/pEp_string.h	Fri Jan 19 14:04:57 2018 +0100
     9.2 +++ b/src/pEp_string.h	Thu Jan 25 14:10:02 2018 +0100
     9.3 @@ -20,12 +20,9 @@
     9.4  //  return value:
     9.5  //      pointer to string object or NULL if out of memory
     9.6  //
     9.7 -//  caveat:
     9.8 -//      one of the two parameters has to be set at least
     9.9 -//
    9.10  //  calling with str and len is equivalent to strndup()
    9.11  //  calling with str but len=0 is equivalent to strdup()
    9.12 -//  calling with str=NULL and len is equivalent to calloc()
    9.13 +//  calling with str=NULL is equivalent to calloc()
    9.14  
    9.15  DYNAMIC_API char * new_string(const char *src, size_t len);
    9.16  
    10.1 --- a/src/pgp_gpg.c	Fri Jan 19 14:04:57 2018 +0100
    10.2 +++ b/src/pgp_gpg.c	Thu Jan 25 14:10:02 2018 +0100
    10.3 @@ -174,6 +174,55 @@
    10.4      return false;
    10.5  }
    10.6  
    10.7 +static PEP_STATUS _version_test(const char *s)
    10.8 +{
    10.9 +    char *_s = strdup(s);
   10.10 +    if (!_s)
   10.11 +        return PEP_OUT_OF_MEMORY;
   10.12 +
   10.13 +    int major;
   10.14 +    int minor;
   10.15 +    int revision;
   10.16 +
   10.17 +    char *lasts = NULL;
   10.18 +    char *p = strtok_r(_s, ".", &lasts);
   10.19 +    if (!p)
   10.20 +        goto unsupported;
   10.21 +    else
   10.22 +        major = atoi(p);
   10.23 +
   10.24 +    p = strtok_r(NULL, ".", &lasts);
   10.25 +    if (!p)
   10.26 +        goto unsupported;
   10.27 +    else
   10.28 +        minor = atoi(p);
   10.29 +
   10.30 +    p = strtok_r(NULL, ".", &lasts);
   10.31 +    if (!p)
   10.32 +        goto unsupported;
   10.33 +    else
   10.34 +        revision = atoi(p);
   10.35 +
   10.36 +    free(_s);
   10.37 +    _s = NULL;
   10.38 +
   10.39 +    if (major > 2)
   10.40 +        return PEP_STATUS_OK;
   10.41 +
   10.42 +    if (major == 2 && minor > 1)
   10.43 +        return PEP_STATUS_OK;
   10.44 +
   10.45 +    if (major == 2 && minor == 0 && revision == 30)
   10.46 +        return PEP_STATUS_OK;
   10.47 +
   10.48 +    if (major == 2 && minor == 1 && revision >= 17)
   10.49 +        return PEP_STATUS_OK;
   10.50 +
   10.51 +unsupported:
   10.52 +    free(_s);
   10.53 +    return PEP_INIT_UNSUPPORTED_GPG_VERSION;
   10.54 +}
   10.55 +
   10.56  PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
   10.57  {
   10.58      PEP_STATUS status = PEP_STATUS_OK;
   10.59 @@ -208,7 +257,7 @@
   10.60          free_stringlist(conf_values);
   10.61  
   10.62          assert(bResult);
   10.63 -        if(!bResult){
   10.64 +        if (!bResult) {
   10.65              status = PEP_INIT_NO_GPG_HOME;
   10.66              goto pep_error;
   10.67          }
   10.68 @@ -225,8 +274,8 @@
   10.69          free_stringlist(conf_values);
   10.70  
   10.71          assert(bResult);
   10.72 -        if(!bResult){
   10.73 -            status = PEP_INIT_NO_GPG_HOME; /* FIXME: Wrong error here? */
   10.74 +        if (!bResult) {
   10.75 +            status = PEP_INIT_CANNOT_CONFIG_GPG_AGENT;
   10.76              goto pep_error;
   10.77          }
   10.78  
   10.79 @@ -238,6 +287,25 @@
   10.80  
   10.81          memset(&gpg, 0, sizeof(struct gpg_s));
   10.82  
   10.83 +        gpg.gpgme_get_engine_info
   10.84 +            = (gpgme_get_engine_info_t) (intptr_t) dlsym(gpgme,
   10.85 +            "gpgme_get_engine_info");
   10.86 +        assert(gpg.gpgme_get_engine_info);
   10.87 +
   10.88 +        gpgme_engine_info_t info;
   10.89 +        int err = gpg.gpgme_get_engine_info(&info);
   10.90 +        assert(err == GPG_ERR_NO_ERROR);
   10.91 +        if (err != GPG_ERR_NO_ERROR)
   10.92 +            return PEP_OUT_OF_MEMORY;
   10.93 +
   10.94 +        assert(info->version);
   10.95 +        if (!info->version)
   10.96 +            return PEP_INIT_CANNOT_DETERMINE_GPG_VERSION;
   10.97 +
   10.98 +        status = _version_test(info->version);
   10.99 +        if (status != PEP_STATUS_OK)
  10.100 +            return status;
  10.101 +
  10.102          gpg.gpgme_set_locale
  10.103              = (gpgme_set_locale_t) (intptr_t) dlsym(gpgme,
  10.104              "gpgme_set_locale");
  10.105 @@ -256,11 +324,6 @@
  10.106              = (gpgme_release_t) (intptr_t) dlsym(gpgme, "gpgme_release");
  10.107          assert(gpg.gpgme_release);
  10.108  
  10.109 -        gpg.gpgme_get_engine_info
  10.110 -            = (gpgme_get_engine_info_t) (intptr_t) dlsym(gpgme,
  10.111 -            "gpgme_get_engine_info");
  10.112 -        assert(gpg.gpgme_get_engine_info);
  10.113 -
  10.114          gpg.gpgme_set_protocol
  10.115              = (gpgme_set_protocol_t) (intptr_t) dlsym(gpgme,
  10.116              "gpgme_set_protocol");
    11.1 --- a/src/pgp_gpg.h	Fri Jan 19 14:04:57 2018 +0100
    11.2 +++ b/src/pgp_gpg.h	Thu Jan 25 14:10:02 2018 +0100
    11.3 @@ -42,7 +42,7 @@
    11.4      );
    11.5  
    11.6  PEP_STATUS pgp_list_keyinfo(
    11.7 -    PEP_SESSION session, const char* pattern, stringpair_list_t** keyinfo_list
    11.8 +        PEP_SESSION session, const char* pattern, stringpair_list_t** keyinfo_list
    11.9      );
   11.10  
   11.11  PEP_STATUS pgp_generate_keypair(
    12.1 --- a/src/platform_windows.h	Fri Jan 19 14:04:57 2018 +0100
    12.2 +++ b/src/platform_windows.h	Thu Jan 25 14:10:02 2018 +0100
    12.3 @@ -86,7 +86,7 @@
    12.4  int uuid_parse(char *in, pEpUUID uu);
    12.5  void uuid_unparse_upper(pEpUUID uu, uuid_string_t out);
    12.6  
    12.7 -#ifndef inline
    12.8 +#ifndef __cplusplus
    12.9  #define inline __inline
   12.10  #endif
   12.11  
    13.1 --- a/test/test_util.cc	Fri Jan 19 14:04:57 2018 +0100
    13.2 +++ b/test/test_util.cc	Thu Jan 25 14:10:02 2018 +0100
    13.3 @@ -1,5 +1,6 @@
    13.4  #include "pEpEngine_test.h"
    13.5  #include "pEpEngine.h"
    13.6 +#include "pEp_internal.h"
    13.7  #include "message_api.h"
    13.8  #include <fstream>
    13.9  #include <sstream>
   13.10 @@ -30,6 +31,13 @@
   13.11      outfile.close();
   13.12  }
   13.13  
   13.14 +char* get_new_uuid() {
   13.15 +    char* new_uuid = (char*)calloc(37, 1);
   13.16 +    pEpUUID uuid;
   13.17 +    uuid_generate_random(uuid);
   13.18 +    uuid_unparse_upper(uuid, new_uuid);
   13.19 +    return new_uuid;
   13.20 +}
   13.21  
   13.22  const char* tl_status_string(PEP_STATUS status) {
   13.23      switch (status) {
    14.1 --- a/test/test_util.h	Fri Jan 19 14:04:57 2018 +0100
    14.2 +++ b/test/test_util.h	Thu Jan 25 14:10:02 2018 +0100
    14.3 @@ -18,3 +18,6 @@
    14.4  
    14.5  // Returns the string value of the input status enum value. 
    14.6  const char* tl_status_string(PEP_STATUS status);
    14.7 +
    14.8 +// Grabs a new uuid for your randomish string needs.
    14.9 +char* get_new_uuid();
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/test/trust_manipulation_test.cc	Thu Jan 25 14:10:02 2018 +0100
    15.3 @@ -0,0 +1,114 @@
    15.4 +// This file is under GNU General Public License 3.0
    15.5 +// see LICENSE.txt
    15.6 +
    15.7 +#include <stdlib.h>
    15.8 +#include <string.h>
    15.9 +#include <time.h>
   15.10 +#include "platform.h"
   15.11 +#include <iostream>
   15.12 +#include <fstream>
   15.13 +#include <assert.h>
   15.14 +#include "mime.h"
   15.15 +#include "message_api.h"
   15.16 +#include "test_util.h"
   15.17 +
   15.18 +using namespace std;
   15.19 +
   15.20 +int main() {
   15.21 +    cout << "\n*** trust manipulation test ***\n\n";
   15.22 +
   15.23 +    PEP_SESSION session;
   15.24 +
   15.25 +    char* user_id = get_new_uuid();
   15.26 +    
   15.27 +    cout << "calling init()\n";
   15.28 +    PEP_STATUS status = init(&session);   
   15.29 +    assert(status == PEP_STATUS_OK);
   15.30 +    assert(session);
   15.31 +    cout << "init() completed.\n";
   15.32 +
   15.33 +    cout << "creating id for : ";
   15.34 +    char *uniqname = strdup("AAAAtestuser@testdomain.org");
   15.35 +    srandom(time(NULL));
   15.36 +    for(int i=0; i < 4;i++)
   15.37 +        uniqname[i] += random() & 0xf;
   15.38 +    
   15.39 +    cout << uniqname << "\n";
   15.40 +    pEp_identity * user = new_identity(uniqname, NULL, user_id, "Test User");
   15.41 +    status = generate_keypair(session, user);
   15.42 +    assert(user->fpr);
   15.43 +
   15.44 +    char* keypair1 = strdup(user->fpr);
   15.45 +    cout << "generated fingerprint \n";
   15.46 +    cout << user->fpr << "\n";
   15.47 +
   15.48 +    cout << "Setting key 1 (" << user->fpr << ") as the default for the identity." << endl;
   15.49 +    // Put identity in the DB
   15.50 +    status = set_identity(session, user);
   15.51 +
   15.52 +    cout << "creating second keypair for : " << uniqname << endl;
   15.53 +    
   15.54 +    pEp_identity * user_again = new_identity(uniqname, NULL, user_id, "Test User");
   15.55 +    status = generate_keypair(session, user_again);
   15.56 +    assert(user_again->fpr);
   15.57 +
   15.58 +    char* keypair2 = strdup(user_again->fpr);
   15.59 +    cout << "generated fingerprint \n";
   15.60 +    cout << user_again->fpr << "\n";
   15.61 +
   15.62 +    assert(strcmp(user->fpr, user_again->fpr) != 0);
   15.63 +    update_identity(session, user);
   15.64 +    assert(strcmp(user->fpr, keypair1) == 0);
   15.65 +    cout << "Key 1 (" << user->fpr << ") is still the default for the identity after update_identity." << endl;
   15.66 +
   15.67 +    // First, trust the SECOND key; make sure it replaces as the default
   15.68 +    cout << "Set trust bit for key 2 (" << keypair2 << ") and ensure it replaces key 1 as the default." << endl;
   15.69 +    status = trust_personal_key(session, user_again);
   15.70 +    status = update_identity(session, user);
   15.71 +    assert(user->comm_type == PEP_ct_OpenPGP);
   15.72 +    assert(strcmp(user->fpr, keypair2) == 0);
   15.73 +    cout << "Key 2 (" << user->fpr << ") is now the default for the identity after update_identity, and its comm_type is PEP_ct_OpenPGP (trust bit set!)." << endl;
   15.74 +
   15.75 +    cout << "Now make key 2 not trusted (which also removes it as a default everywhere)." << endl;
   15.76 +    status = key_reset_trust(session, user);
   15.77 +    status = get_trust(session, user);
   15.78 +    assert(strcmp(user->fpr, keypair2) == 0);
   15.79 +    assert(user->comm_type == PEP_ct_OpenPGP_unconfirmed);
   15.80 +    cout << "Key 2 is untrusted in the DB." << endl;
   15.81 +
   15.82 +    cout << "Now let's mistrust key 2 in the DB." << endl;
   15.83 +    // Now let's mistrust the second key.
   15.84 +    status = key_mistrusted(session, user);
   15.85 +    status = get_trust(session, user);
   15.86 +    assert(strcmp(user->fpr, keypair2) == 0);
   15.87 +    assert(user->comm_type == PEP_ct_mistrusted);
   15.88 +    cout << "Hoorah, we now do not trust key 2. (We never liked key 2 anyway.)" << endl;
   15.89 +    cout << "Now we call update_identity to see what gifts it gives us (should be key 1 with key 1's initial trust.)" << endl;    
   15.90 +    status = update_identity(session, user);
   15.91 +    assert(strcmp(user->fpr, keypair1) == 0);
   15.92 +    assert(user->comm_type == PEP_ct_OpenPGP_unconfirmed);
   15.93 +    cout << "Yup, got key 1, and the trust status is PEP_ct_OpenPGP_unconfirmed." << endl;
   15.94 +    
   15.95 +    cout << "Let's mistrust key 1 too. It's been acting shifty lately." << endl;
   15.96 +    status = key_mistrusted(session, user);
   15.97 +    status = get_trust(session, user);
   15.98 +    assert(strcmp(user->fpr, keypair1) == 0);
   15.99 +    assert(user->comm_type == PEP_ct_mistrusted);
  15.100 +    cout << "Hoorah, we now do not trust key 1. (TRUST NO ONE)" << endl;
  15.101 +    cout << "Now we call update_identity to see what gifts it gives us (should be an empty key and a key not found comm_type.)" << endl;    
  15.102 +    status = update_identity(session, user);
  15.103 +    assert(user->fpr == NULL);
  15.104 +    assert(user->comm_type == PEP_ct_key_not_found);
  15.105 +    cout << "Yup, we trust no keys from " << uniqname << endl;
  15.106 +    
  15.107 +    cout << "TODO: Add cases where we have multiple user_ids addressing a single key, and multiple identities with that key + mistrust" << endl;
  15.108 +    cout << "Passed all of our exciting messing with the trust DB. Moving on..." << endl;
  15.109 + 
  15.110 +    free(user_id);
  15.111 +    free(keypair1);
  15.112 +    free(uniqname);
  15.113 +    free_identity(user);
  15.114 +    release(session);
  15.115 +    
  15.116 +    return 0;
  15.117 +}