src/keymanagement.c
author Krista Bennett <krista@pep-project.org>
Fri, 15 Dec 2017 12:49:03 +0100
branchENGINE-289
changeset 2317 b80dd91c8869
parent 2311 688b925c3e73
child 2319 93c84d8281d2
permissions -rw-r--r--
ENGINE-320: intermittent commit
     1 // This file is under GNU General Public License 3.0
     2 // see LICENSE.txt
     3 
     4 #include "platform.h"
     5 
     6 #include <string.h>
     7 #include <stdio.h>
     8 #include <stdlib.h>
     9 #include <assert.h>
    10 #include <ctype.h>
    11 
    12 #include "pEp_internal.h"
    13 #include "keymanagement.h"
    14 
    15 #include "sync_fsm.h"
    16 #include "blacklist.h"
    17 
    18 #ifndef EMPTYSTR
    19 #define EMPTYSTR(STR) ((STR) == NULL || (STR)[0] == '\0')
    20 #endif
    21 
    22 #define KEY_EXPIRE_DELTA (60 * 60 * 24 * 365)
    23 
    24 
    25 PEP_STATUS elect_pubkey(
    26         PEP_SESSION session, pEp_identity * identity
    27     )
    28 {
    29     PEP_STATUS status;
    30     stringlist_t *keylist = NULL;
    31     char *_fpr = "";
    32     identity->comm_type = PEP_ct_unknown;
    33 
    34     status = find_keys(session, identity->address, &keylist);
    35     assert(status != PEP_OUT_OF_MEMORY);
    36     if (status == PEP_OUT_OF_MEMORY)
    37         return PEP_OUT_OF_MEMORY;
    38 
    39     stringlist_t *_keylist;
    40     for (_keylist = keylist; _keylist && _keylist->value; _keylist = _keylist->next) {
    41         PEP_comm_type _comm_type_key;
    42 
    43         status = get_key_rating(session, _keylist->value, &_comm_type_key);
    44         assert(status != PEP_OUT_OF_MEMORY);
    45         if (status == PEP_OUT_OF_MEMORY) {
    46             free_stringlist(keylist);
    47             return PEP_OUT_OF_MEMORY;
    48         }
    49 
    50         if (_comm_type_key != PEP_ct_compromized &&
    51             _comm_type_key != PEP_ct_unknown)
    52         {
    53             if (identity->comm_type == PEP_ct_unknown ||
    54                 _comm_type_key > identity->comm_type)
    55             {
    56                 bool blacklisted;
    57                 status = blacklist_is_listed(session, _keylist->value, &blacklisted);
    58                 if (status == PEP_STATUS_OK && !blacklisted) {
    59                     identity->comm_type = _comm_type_key;
    60                     _fpr = _keylist->value;
    61                 }
    62             }
    63         }
    64     }
    65     
    66 //    if (_fpr) {
    67     free(identity->fpr);
    68 
    69     identity->fpr = strdup(_fpr);
    70     if (identity->fpr == NULL) {
    71         free_stringlist(keylist);
    72         return PEP_OUT_OF_MEMORY;
    73     }
    74 //    }
    75     free_stringlist(keylist);
    76     return PEP_STATUS_OK;
    77 }
    78 
    79 static PEP_STATUS validate_fpr(PEP_SESSION session, pEp_identity* ident) {
    80     
    81     char* fpr = ident->fpr;
    82     PEP_comm_type ct = ident->comm_type;
    83     bool done = false;
    84     
    85     bool revoked, expired;
    86     status = key_revoked(session, fpr, &revoked);    
    87     
    88     assert(status == PEP_STATUS_OK);
    89     if (status != PEP_STATUS_OK) {
    90          // only happens when there was a problem
    91          // retrieving key.
    92          ADD_TO_LOG(status);
    93      }
    94     
    95     status = key_expired(session, identity->fpr, 
    96                          time(NULL) + (7*24*3600), // In a week
    97                          &expired);
    98 
    99     assert(status == PEP_STATUS_OK);
   100     if (status != PEP_STATUS_OK)
   101          ADD_TO_LOG(status);
   102     
   103     char* retval = fpr;
   104     
   105     // FIXME: bits for pEp
   106     if (ident->me && (ct == PEP_ct_pEp) && !revoked && expired) {
   107         // extend key
   108         timestamp *ts = new_timestamp(time(NULL) + KEY_EXPIRE_DELTA);
   109         status = renew_key(session, fpr, ts);
   110         free_timestamp(ts);
   111 
   112         if (status == PEP_STATUS_OK) {
   113             // if key is valid (second check because pEp key might be extended above)
   114             //      Return fpr        
   115             status = key_expired(session, fpr, &expired);            
   116             // communicate key(?)
   117             done = true;
   118         }        
   119     }
   120     
   121     if (revoked)
   122         ct = PEP_ct_revoked; // not to be stored. To be used here.
   123     else if (expired)
   124         ct = PEP_ct_expired;
   125     
   126     switch (ct) {
   127         case PEP_ct_key_expired:
   128         case PEP_ct_key_revoked
   129         case PEP_ct_key_b0rken:
   130             // delete key from being default key for all users/identities
   131             ident->fpr = NULL;
   132         default:
   133             break;
   134     }            
   135 
   136     if (!(revoked || expired || !done))
   137         return PEP_STATUS_OK;
   138 
   139     return PEP_UNKNOWN_ERROR; // FIXME - better error
   140 }
   141 
   142 // Only call on retrieval of previously stored identity!
   143 // Also, we presume that if the stored_identity was sent in
   144 // without an fpr, there wasn't one in the trust DB for this
   145 // identity.
   146 PEP_STATUS get_valid_pubkey(PEP_STATUS session,
   147                             PEP_STATUS stored_identity) {
   148     
   149     PEP_STATUS status = PEP_STATUS_OK;
   150 
   151     if (!stored_identity || !stored_identity->user_id)
   152         return PEP_ILLEGAL_VALUE;
   153         
   154     char* stored_fpr = stored_identity->fpr;
   155     // Input: stored identity retrieved from database
   156     // if stored identity contains a default key
   157     if (stored_fpr) {
   158         status = validate_fpr(session, stored_identity);    
   159         if (status == PEP_STATUS_OK && stored_identity->fpr)
   160             return status;
   161     }
   162     // if no valid default stored identity key found
   163     // try to get default key for user_data
   164     sqlite3_reset(session->get_user_default_key);
   165     sqlite3_bind_text(session->get_user_default_key, 1, stored_identity->user_id, 
   166                       -1, SQLITE_STATIC);
   167     
   168     const int result = sqlite3_step(session->get_user_default_key);
   169     const char* user_fpr;
   170     bool found = false;
   171     if (result == SQLITE_ROW) {
   172         user_fpr = 
   173             (const char *) sqlite3_column_text(session->get_user_default_key, 0);
   174         if (user_fpr)
   175             found = true;
   176     }
   177     if (!found)
   178         return NULL;
   179          
   180     // There exists a default key for user, so validate
   181     // FIXME: we have to be able to validate comm_type too.
   182     retval = validate_fpr(session, user_fpr, WTF,
   183                           stored_identity->me);
   184     
   185     if (!retval) {
   186         
   187     }
   188                           
   189     return retval;
   190 }
   191 
   192 PEP_STATUS _myself(PEP_SESSION session, pEp_identity * identity, bool do_keygen, bool ignore_flags);
   193 
   194 DYNAMIC_API PEP_STATUS update_identity(
   195         PEP_SESSION session, pEp_identity * identity
   196     )
   197 {
   198     pEp_identity *stored_identity = NULL;
   199     pEp_identity *temp_id = NULL;
   200     PEP_STATUS status;
   201 
   202     assert(session);
   203     assert(identity);
   204     assert(!EMPTYSTR(identity->address));
   205 
   206     if (!(session && identity && !EMPTYSTR(identity->address)))
   207         return ADD_TO_LOG(PEP_ILLEGAL_VALUE);
   208 
   209     char* own_id = NULL;
   210     status = get_own_userid(session, &own_id);    
   211 
   212     // Is this me, temporary or not? If so, _myself() is the right call.
   213     if (identity->me || 
   214        (own_id && identity->user_id && (strcmp(own_id, identity->user_id) == 0))) 
   215     {
   216         status = _myself(session, identity, false, true);
   217         free(own_id);
   218         return status;
   219     }
   220 
   221     // We have, at least, an address.
   222     // Retrieve stored identity information!    
   223     pEp_identity* stored_ident = NULL;
   224     if (identity->user_id) {            
   225         // (we're gonna update the trust/fpr anyway, so we user the no-fpr variant)
   226         //      * do get_identity() to retrieve stored identity information
   227         status = get_identity_without_fpr(session, identity->address, identity->user_id, &stored_ident);
   228 
   229         // Before we start - if there was no stored identity, we should check to make sure we don't
   230         // have a stored identity with a temporary user_id that differs from the input user_id. This
   231         // happens in multithreaded environments sometimes.
   232         if (!stored_ident) {
   233             identity_list* id_list = NULL;
   234             status = get_identities_by_address(session, identity->address, &id_list);
   235 
   236             if (id_list) {
   237                 identity_list* id_curr = id_list;
   238                 while (id_curr) {
   239                     pEp_identity* this_id = id_curr->ident;
   240                     if (this_id) {
   241                         char* this_uid = this_id->user_id;
   242                         if (this_uid && (strstr(this_uid, "TOFU_") == this_uid)) {
   243                             // FIXME: should we also be fixing pEp_own_userId in this
   244                             // function here?
   245                             
   246                             // Ok, we have a temp ID. We have to replace this
   247                             // with the real ID.
   248                             status = replace_userid(this_uid, identity->user_id);
   249                             if (status != PEP_STATUS_OK) {
   250                                 free_identity_list(id_list);
   251                                 return status;
   252                             }
   253                                 
   254                             free(this_uid);
   255                             
   256                             // Reflect the change we just made to the DB
   257                             this_id->user_id = strdup(identity->user_id);
   258                             stored_ident = this_id;
   259                             // FIXME: free list.
   260                             break;
   261                         } 
   262                     }
   263                     id_curr = id_curr->next;
   264                 }
   265             }
   266         } 
   267         
   268         // Ok, now we start the real algorithm:
   269         if (identity->username) {
   270             /*
   271              * Retrieving information of an identity with username supplied
   272              *      Input: user_id, address, username
   273              */
   274             if (status == PEP_STATUS_OK && stored_ident) { 
   275                 //  * if identity available
   276                 //      * patch it with username
   277                 //          (note: this will happen when 
   278                 //           setting automatically below...)
   279                 //      * elect valid key for identity
   280                 //    * if valid key existS
   281                 //        * set return value's fpr
   282                 status = get_valid_pubkey(session, stored_ident);
   283                 if (status == PEP_STATUS_OK && stored_ident->fpr) {
   284                 //        * set identity comm_type from trust db (user_id, FPR)
   285                     status = get_trust(session, stored_ident);
   286                     if (status != PEP_STATUS_OK)
   287                         return status; // FIXME - free mem
   288                     if (identity->fpr && 
   289                              strcasecmp(stored_ident->fpr, identity->fpr) != 0) {
   290                         free(identity->fpr);
   291                         strdup(identity->fpr, stored_ident->fpr);
   292                         identity->comm_type = stored_ident->comm_type;
   293                     }
   294                 }
   295                 else {
   296                     return status; // Couldn't find a key.
   297                 }
   298                 //    * call set_identity() to store
   299                 status = set_identity(identity);
   300             }
   301             //  * else (identity unavailable)
   302             else {
   303             //      * create identity with user_id, address, username
   304             //    * search for a temporary identity for address and username
   305             //    * if temporary identity available
   306             //      * modify identity with username
   307             //    * else
   308             //    * call set_identity() to store
   309             //  * Return: modified or created identity
   310              // 
   311             }
   312         }
   313         else {
   314             /*
   315              * Retrieving information of an identity without username supplied
   316              *      Input: user_id, address
   317              */
   318             //    * doing get_identity() to retrieve stored identity information
   319             //    * if identity not available
   320             //      * return error status (identity not found)
   321             //    * else
   322             //      * elect valid key for identity (see below)
   323             //      * if valid key exists
   324             //        * set identity comm_type from trust db (user_id, FPR)
   325             //        * set return value's fpr
   326             //        * ...? (do we also set the stored fpr?)
   327             //      * Return: identity if available
   328 
   329             
   330         }
   331     }
   332     else if (identity->username) {
   333         /*
   334          * Temporary identity information with username supplied
   335             * Input: address, username (no others)
   336          */
   337          
   338         //  * Search for an identity with non-temporary user_id with that mapping
   339         //  * if one found
   340         //    * find valid key for identity (see below)
   341         //    * if valid key exists
   342         //      * set identity comm_type from trust db (user_id, FPR)
   343         //      * set return value's fpr
   344         //      * ...? (do we also set the stored fpr?)
   345         //    * Return this identity
   346         //  * if many found
   347         //    * Return the one with newest modification date (yes, this is a heuristics)
   348         //  * else
   349         //    * create temporary identity, store it, and Return this
   350     }
   351     else {
   352         /*
   353          * Temporary identity information without username suplied
   354             * Input: address (no others)
   355          */
   356          
   357         //    * Search for identity with this address
   358         //    * If exactly one found
   359         //      * elect valid key for identity (see below)
   360         //      * if valid key exists
   361         //        * set identity comm_type from trust db (user_id, FPR)
   362         //        * set return value's fpr
   363         //        * ...? (do we also set the stored fpr?)
   364         //      * Return this identity
   365         //    * else
   366         //      * return error status (too little information)
   367     }
   368 
   369 
   370     int _no_user_id = EMPTYSTR(identity->user_id);
   371     int _did_elect_new_key = 0;
   372 
   373     if (_no_user_id)
   374     {
   375         char* own_id = NULL;
   376         status = get_own_userid(session, &own_id);
   377         if (status == PEP_STATUS_OK && own_id) {
   378             status = get_identity(session, identity->address, own_id,
   379                     &stored_identity);
   380             if (status == PEP_STATUS_OK) {
   381                 free_identity(stored_identity);
   382                 identity->user_id = own_id;
   383                 return _myself(session, identity, false, true);
   384             }
   385         }
   386         
   387         free(identity->user_id);
   388 
   389         identity->user_id = calloc(1, strlen(identity->address) + 6);
   390         if (!identity->user_id)
   391         {
   392             return PEP_OUT_OF_MEMORY;
   393         }
   394         snprintf(identity->user_id, strlen(identity->address) + 6,
   395                  "TOFU_%s", identity->address);
   396     }
   397  
   398     status = get_identity(session,
   399                           identity->address,
   400                           identity->user_id,
   401                           &stored_identity);
   402     
   403     assert(status != PEP_OUT_OF_MEMORY);
   404     if (status == PEP_OUT_OF_MEMORY)
   405         goto exit_free;
   406 
   407     temp_id = identity_dup(identity);
   408     
   409     /* We don't take given fpr. 
   410        In case there's no acceptable stored fpr, it will be elected. */
   411     free(temp_id->fpr);
   412     temp_id->fpr = NULL;
   413     temp_id->comm_type = PEP_ct_unknown;
   414             
   415     if (stored_identity) {
   416         
   417         bool dont_use_stored_fpr = true;
   418 
   419         /* if we have a stored_identity fpr */
   420         if (!EMPTYSTR(stored_identity->fpr)) {
   421             bool revoked = false;
   422             status = key_revoked(session, stored_identity->fpr, &revoked);
   423             
   424             if (status != PEP_STATUS_OK || revoked)
   425                 dont_use_stored_fpr = true;
   426                 
   427             if (revoked) {
   428                 // Do stuff
   429                 status = update_trust_for_fpr(session, stored_identity->fpr, PEP_ct_key_revoked);
   430                 // What to do on failure? FIXME
   431                 status = replace_identities_fpr(session, stored_identity->fpr, "");
   432             }
   433             else {    
   434                 status = blacklist_is_listed(session, stored_identity->fpr, &dont_use_stored_fpr);
   435                 if (status != PEP_STATUS_OK)
   436                     dont_use_stored_fpr = true; 
   437             }
   438         }
   439             
   440 
   441         if (!dont_use_stored_fpr) {
   442             /* Check stored comm_type */
   443             PEP_comm_type _comm_type_key;
   444             status = get_key_rating(session, stored_identity->fpr, &_comm_type_key);
   445             assert(status != PEP_OUT_OF_MEMORY);
   446             if (status == PEP_OUT_OF_MEMORY) {
   447                 goto exit_free;
   448             }
   449             if (status == PEP_KEY_NOT_FOUND){
   450                 /* stored key was deleted from keyring. any other candidate ?*/
   451                 status = elect_pubkey(session, temp_id);
   452                 if (status != PEP_STATUS_OK) {
   453                     goto exit_free;
   454                 } else {
   455                     _did_elect_new_key = 1;
   456                 }
   457             } else {
   458                 temp_id->fpr = strdup(stored_identity->fpr);
   459                 assert(temp_id->fpr);
   460                 if (temp_id->fpr == NULL) {
   461                     status = PEP_OUT_OF_MEMORY;
   462                     goto exit_free;
   463                 }
   464 
   465                 if (_comm_type_key < PEP_ct_unconfirmed_encryption) {
   466                     /* if key not good anymore, 
   467                        downgrade eventually trusted comm_type */
   468                     temp_id->comm_type = _comm_type_key;
   469                 } else {
   470                     /* otherwise take stored comm_type as-is except if 
   471                        is unknown or is expired (but key not expired anymore) */
   472                     temp_id->comm_type = stored_identity->comm_type;
   473                     if (temp_id->comm_type == PEP_ct_unknown ||
   474                         temp_id->comm_type == PEP_ct_key_expired) {
   475                         temp_id->comm_type = _comm_type_key;
   476                     }
   477                 }
   478             }
   479         }
   480         else {
   481             status = elect_pubkey(session, temp_id);
   482             if (status != PEP_STATUS_OK){
   483                 goto exit_free;
   484             } else {
   485                 _did_elect_new_key = 1;
   486             }
   487         }
   488         
   489         /* ok, from here on out, use temp_id */
   490         
   491         
   492         /* At this point, we either have a non-blacklisted fpr we can work */
   493         /* with, or we've got nada.                                        */
   494 
   495         if (EMPTYSTR(temp_id->fpr)) {
   496             /* nada : set comm_type accordingly */
   497             temp_id->comm_type = PEP_ct_key_not_found;
   498         }
   499         
   500         if (EMPTYSTR(temp_id->username)) {
   501             free(temp_id->username);
   502             temp_id->username = strdup(stored_identity->username);
   503             assert(temp_id->username);
   504             if (temp_id->username == NULL){
   505                 status = PEP_OUT_OF_MEMORY;
   506                 goto exit_free;
   507             }
   508         }
   509 
   510         if (temp_id->lang[0] == 0) {
   511             temp_id->lang[0] = stored_identity->lang[0];
   512             temp_id->lang[1] = stored_identity->lang[1];
   513             temp_id->lang[2] = 0;
   514         }
   515 
   516         temp_id->flags = stored_identity->flags;
   517     }
   518     else /* stored_identity == NULL */ {
   519         temp_id->flags = 0;
   520 
   521         /* We elect a pubkey */
   522         status = elect_pubkey(session, temp_id);
   523         if (status != PEP_STATUS_OK)
   524             goto exit_free;
   525         
   526         /* Work with the elected key */
   527         if (!EMPTYSTR(temp_id->fpr)) {
   528             
   529             PEP_comm_type _comm_type_key = temp_id->comm_type;
   530             
   531             _did_elect_new_key = 1;
   532 
   533             // We don't want to lose a previous trust entry!!!
   534             status = get_trust(session, temp_id);
   535 
   536             bool has_trust_status = (status == PEP_STATUS_OK);
   537 
   538             if (!has_trust_status)
   539                 temp_id->comm_type = _comm_type_key;
   540         }
   541     }
   542 
   543     if (temp_id->fpr == NULL) {
   544         temp_id->fpr = strdup("");
   545         if (temp_id->fpr == NULL) {
   546             status = PEP_OUT_OF_MEMORY;
   547             goto exit_free;
   548         }
   549     }
   550     
   551     
   552     status = PEP_STATUS_OK;
   553 
   554     if (temp_id->comm_type != PEP_ct_unknown && !EMPTYSTR(temp_id->user_id)) {
   555 
   556         if (EMPTYSTR(temp_id->username)) { // mitigate
   557             free(temp_id->username);
   558             temp_id->username = strdup("Anonymous");
   559             assert(temp_id->username);
   560             if (temp_id->username == NULL){
   561                 status = PEP_OUT_OF_MEMORY;
   562                 goto exit_free;
   563             }
   564         }
   565 
   566         // Identity doesn't get stored if call was just about checking existing
   567         // user by address (i.e. no user id given but already stored)
   568         if (!(_no_user_id && stored_identity) || _did_elect_new_key)
   569         {
   570             status = set_identity(session, temp_id);
   571             assert(status == PEP_STATUS_OK);
   572             if (status != PEP_STATUS_OK) {
   573                 goto exit_free;
   574             }
   575         }
   576     }
   577 
   578     if (temp_id->comm_type != PEP_ct_compromized &&
   579             temp_id->comm_type < PEP_ct_strong_but_unconfirmed)
   580         if (session->examine_identity)
   581             session->examine_identity(temp_id, session->examine_management);
   582     
   583     /* ok, we got to the end. So we can assign the output identity */
   584     free(identity->address);
   585     identity->address = strdup(temp_id->address);
   586     free(identity->fpr);
   587     identity->fpr = strdup(temp_id->fpr);
   588     free(identity->user_id);
   589     identity->user_id = strdup(temp_id->user_id);
   590     free(identity->username);
   591     identity->username = strdup(temp_id->username ? temp_id->username : "Anonymous");
   592     identity->comm_type = temp_id->comm_type;
   593     identity->lang[0] = temp_id->lang[0];
   594     identity->lang[1] = temp_id->lang[1];
   595     identity->lang[2] = 0;
   596     identity->me = temp_id->me;
   597     identity->flags = temp_id->flags;
   598 
   599 exit_free :
   600     free_identity(stored_identity);
   601     free_identity(temp_id);
   602     
   603     return ADD_TO_LOG(status);
   604 }
   605 
   606 PEP_STATUS elect_ownkey(
   607         PEP_SESSION session, pEp_identity * identity
   608     )
   609 {
   610     PEP_STATUS status;
   611     stringlist_t *keylist = NULL;
   612 
   613     free(identity->fpr);
   614     identity->fpr = NULL;
   615 
   616     status = find_private_keys(session, identity->address, &keylist);
   617     assert(status != PEP_OUT_OF_MEMORY);
   618     if (status == PEP_OUT_OF_MEMORY)
   619         return PEP_OUT_OF_MEMORY;
   620     
   621     if (keylist != NULL && keylist->value != NULL)
   622     {
   623         char *_fpr = NULL;
   624         identity->comm_type = PEP_ct_unknown;
   625 
   626         stringlist_t *_keylist;
   627         for (_keylist = keylist; _keylist && _keylist->value; _keylist = _keylist->next) {
   628             bool is_own = false;
   629             
   630             status = own_key_is_listed(session, _keylist->value, &is_own);
   631             assert(status == PEP_STATUS_OK);
   632             if (status != PEP_STATUS_OK) {
   633                 free_stringlist(keylist);
   634                 return status;
   635             }
   636             
   637             if (is_own)
   638             {
   639                 PEP_comm_type _comm_type_key;
   640                 
   641                 status = get_key_rating(session, _keylist->value, &_comm_type_key);
   642                 assert(status != PEP_OUT_OF_MEMORY);
   643                 if (status == PEP_OUT_OF_MEMORY) {
   644                     free_stringlist(keylist);
   645                     return PEP_OUT_OF_MEMORY;
   646                 }
   647                 
   648                 if (_comm_type_key != PEP_ct_compromized &&
   649                     _comm_type_key != PEP_ct_unknown)
   650                 {
   651                     if (identity->comm_type == PEP_ct_unknown ||
   652                         _comm_type_key > identity->comm_type)
   653                     {
   654                         identity->comm_type = _comm_type_key;
   655                         _fpr = _keylist->value;
   656                     }
   657                 }
   658             }
   659         }
   660         
   661         if (_fpr)
   662         {
   663             identity->fpr = strdup(_fpr);
   664             assert(identity->fpr);
   665             if (identity->fpr == NULL)
   666             {
   667                 free_stringlist(keylist);
   668                 return PEP_OUT_OF_MEMORY;
   669             }
   670         }
   671         free_stringlist(keylist);
   672     }
   673     return PEP_STATUS_OK;
   674 }
   675 
   676 PEP_STATUS _has_usable_priv_key(PEP_SESSION session, char* fpr,
   677                                 bool* is_usable) {
   678     
   679     bool dont_use_fpr = true;
   680     
   681     PEP_STATUS status = blacklist_is_listed(session, fpr, &dont_use_fpr);
   682     if (status == PEP_STATUS_OK && !dont_use_fpr) {
   683         // Make sure there is a *private* key associated with this fpr
   684         bool has_private = false;
   685         status = contains_priv_key(session, fpr, &has_private);
   686 
   687         if (status == PEP_STATUS_OK)
   688             dont_use_fpr = !has_private;
   689     }
   690     
   691     *is_usable = !dont_use_fpr;
   692     
   693     return ADD_TO_LOG(status);
   694 }
   695 
   696 PEP_STATUS _myself(PEP_SESSION session, pEp_identity * identity, bool do_keygen, bool ignore_flags)
   697 {
   698     pEp_identity *stored_identity = NULL;
   699     PEP_STATUS status;
   700 
   701     assert(session);
   702     assert(identity);
   703     assert(!EMPTYSTR(identity->address));
   704 
   705     char* own_id = NULL;
   706     status = get_own_userid(session, &own_id);
   707 
   708 
   709     assert(EMPTYSTR(identity->user_id) ||
   710            (own_id && strcmp(identity->user_id, own_id) == 0) ||
   711            !own_id);
   712 
   713     if (!(session && identity && !EMPTYSTR(identity->address) &&
   714             (EMPTYSTR(identity->user_id) ||
   715             (own_id && strcmp(identity->user_id, own_id) == 0) ||
   716              !own_id)))
   717         return ADD_TO_LOG(PEP_ILLEGAL_VALUE);
   718 
   719     if (!own_id) {
   720         // check to see if we have ANY identity for this address... could have
   721         // happened due to race condition
   722     }
   723     
   724     identity->comm_type = PEP_ct_pEp;
   725     identity->me = true;
   726     if(ignore_flags)
   727         identity->flags = 0;
   728     
   729     if (EMPTYSTR(identity->user_id))
   730     {
   731         free(identity->user_id);
   732         identity->user_id = (own_id ? own_id : strdup(PEP_OWN_USERID));
   733         assert(identity->user_id);
   734         if (identity->user_id == NULL)
   735             return PEP_OUT_OF_MEMORY;
   736     }
   737 
   738     if (EMPTYSTR(identity->username))
   739     {
   740         free(identity->username);
   741         identity->username = strdup("Anonymous");
   742         assert(identity->username);
   743         if (identity->username == NULL)
   744             return PEP_OUT_OF_MEMORY;
   745     }
   746 
   747     DEBUG_LOG("myself", "debug", identity->address);
   748  
   749     status = get_identity(session,
   750                           identity->address,
   751                           identity->user_id,
   752                           &stored_identity);
   753     
   754     assert(status != PEP_OUT_OF_MEMORY);
   755     if (status == PEP_OUT_OF_MEMORY)
   756         return PEP_OUT_OF_MEMORY;
   757 
   758     bool dont_use_stored_fpr = true;
   759     bool dont_use_input_fpr = true;
   760         
   761     if (stored_identity)
   762     {
   763         if (EMPTYSTR(identity->fpr)) {
   764             
   765             bool has_private = false;
   766             
   767             status = _has_usable_priv_key(session, stored_identity->fpr, &has_private); 
   768             
   769             // N.B. has_private is never true if the returned status is not PEP_STATUS_OK
   770             if (has_private) {
   771                 identity->fpr = strdup(stored_identity->fpr);
   772                 assert(identity->fpr);
   773                 if (identity->fpr == NULL)
   774                 {
   775                     return PEP_OUT_OF_MEMORY;
   776                 }
   777                 dont_use_stored_fpr = false;
   778             }
   779         }
   780         
   781         identity->flags = (identity->flags & 255) | stored_identity->flags;
   782         free_identity(stored_identity);
   783     }
   784     
   785     if (dont_use_stored_fpr && !EMPTYSTR(identity->fpr))
   786     {
   787         // App must have a good reason to give fpr, such as explicit
   788         // import of private key, or similar.
   789 
   790         // Take given fpr as-is.
   791 
   792         // BUT:
   793         // First check to see if it's blacklisted or private part is missing?
   794         bool has_private = false;
   795         
   796         status = _has_usable_priv_key(session, identity->fpr, &has_private); 
   797         
   798         // N.B. has_private is never true if the returned status is not PEP_STATUS_OK
   799         if (has_private) {
   800             dont_use_input_fpr = false;
   801         }
   802     }
   803     
   804     // Ok, we failed to get keys either way, so let's elect one.
   805     if (dont_use_input_fpr && dont_use_stored_fpr)
   806     {
   807         status = elect_ownkey(session, identity);
   808         assert(status == PEP_STATUS_OK);
   809         if (status != PEP_STATUS_OK) {
   810             return ADD_TO_LOG(status);
   811         }
   812 
   813         bool has_private = false;
   814         if (identity->fpr) {
   815             // ok, we elected something.
   816             // elect_ownkey only returns private keys, so we don't check again.
   817             // Check to see if it's blacklisted
   818             bool listed;
   819             status = blacklist_is_listed(session, identity->fpr, &listed); 
   820 
   821             if (status == PEP_STATUS_OK)
   822                 has_private = !listed;
   823         }
   824         
   825         if (has_private) {
   826             dont_use_input_fpr = false;
   827         }
   828         else { // OK, we've tried everything. Time to generate new keys.
   829             free(identity->fpr); // It can stay in this state (unallocated) because we'll generate a new key 
   830             identity->fpr = NULL;
   831         }
   832     }
   833 
   834     bool revoked = false;
   835     char *r_fpr = NULL;
   836     if (!EMPTYSTR(identity->fpr))
   837     {
   838         status = key_revoked(session, identity->fpr, &revoked);
   839 
   840         if (status != PEP_STATUS_OK) 
   841         {
   842             return ADD_TO_LOG(status);
   843         }
   844     }
   845    
   846     if (EMPTYSTR(identity->fpr) || revoked)
   847     {
   848         if(!do_keygen){
   849             return ADD_TO_LOG(PEP_GET_KEY_FAILED);
   850         }
   851 
   852         if(revoked)
   853         {
   854             r_fpr = identity->fpr;
   855             identity->fpr = NULL;
   856         }
   857         
   858         DEBUG_LOG("generating key pair", "debug", identity->address);
   859         status = generate_keypair(session, identity);
   860         assert(status != PEP_OUT_OF_MEMORY);
   861         if (status != PEP_STATUS_OK) {
   862             char buf[11];
   863             snprintf(buf, 11, "%d", status);
   864             DEBUG_LOG("generating key pair failed", "debug", buf);
   865             if(revoked && r_fpr)
   866                 free(r_fpr);
   867             return ADD_TO_LOG(status);
   868         }
   869 
   870         
   871         if(revoked)
   872         {
   873             status = set_revoked(session, r_fpr,
   874                                  identity->fpr, time(NULL));
   875             free(r_fpr);
   876             if (status != PEP_STATUS_OK) {
   877                 return ADD_TO_LOG(status);
   878             }
   879         }
   880     }
   881     else
   882     {
   883         bool expired;
   884         status = key_expired(session, identity->fpr, 
   885                              time(NULL) + (7*24*3600), // In a week
   886                              &expired);
   887 
   888         assert(status == PEP_STATUS_OK);
   889         if (status != PEP_STATUS_OK) {
   890             return ADD_TO_LOG(status);
   891         }
   892 
   893         if (status == PEP_STATUS_OK && expired) {
   894             timestamp *ts = new_timestamp(time(NULL) + KEY_EXPIRE_DELTA);
   895             renew_key(session, identity->fpr, ts);
   896             free_timestamp(ts);
   897         }
   898     }
   899 
   900     if (!identity->username)
   901         identity->username = strdup("");
   902     
   903     status = set_identity(session, identity);
   904     assert(status == PEP_STATUS_OK);
   905     if (status != PEP_STATUS_OK) {
   906         return status;
   907     }
   908 
   909     return ADD_TO_LOG(PEP_STATUS_OK);
   910 }
   911 
   912 DYNAMIC_API PEP_STATUS initialise_own_identities(PEP_SESSION session,
   913                                                  identity_list* my_idents) {
   914     PEP_STATUS status = PEP_STATUS_OK;
   915     if (!session)
   916         return PEP_ILLEGAL_VALUE;
   917         
   918     char* stored_own_userid = NULL;
   919     get_own_userid(session, &stored_own_userid);
   920     
   921     identity_list* ident_curr = my_idents;
   922     while (ident_curr) {
   923         pEp_identity* ident = ident_curr->ident;
   924         if (!ident)
   925             return PEP_ILLEGAL_VALUE;
   926             
   927         if (stored_own_userid) {
   928             if (!ident->user_id) 
   929                 ident->user_id = strdup(stored_own_userid);
   930             else if (strcmp(stored_own_userid, ident->user_id) != 0)
   931                 return PEP_ILLEGAL_VALUE;
   932         }
   933         else if (!ident->user_id) {
   934             stored_own_userid = PEP_OWN_USERID;
   935             ident->user_id = strdup(PEP_OWN_USERID);
   936         }
   937         
   938         ident->me = true; // Just in case.
   939         
   940         // Ok, do it...
   941         status = set_identity(session, ident);
   942         if (status != PEP_STATUS_OK)
   943             return status;
   944         
   945         ident_curr = ident_curr->next;
   946     }
   947     
   948     return status;
   949 }
   950 
   951 DYNAMIC_API PEP_STATUS myself(PEP_SESSION session, pEp_identity * identity)
   952 {
   953     return ADD_TO_LOG(_myself(session, identity, true, false));
   954 }
   955 
   956 DYNAMIC_API PEP_STATUS register_examine_function(
   957         PEP_SESSION session, 
   958         examine_identity_t examine_identity,
   959         void *management
   960     )
   961 {
   962     assert(session);
   963     if (!session)
   964         return PEP_ILLEGAL_VALUE;
   965 
   966     session->examine_management = management;
   967     session->examine_identity = examine_identity;
   968 
   969     return PEP_STATUS_OK;
   970 }
   971 
   972 DYNAMIC_API PEP_STATUS do_keymanagement(
   973         retrieve_next_identity_t retrieve_next_identity,
   974         void *management
   975     )
   976 {
   977     PEP_SESSION session;
   978     pEp_identity *identity;
   979     PEP_STATUS status;
   980 
   981     assert(retrieve_next_identity);
   982     assert(management);
   983 
   984     if (!retrieve_next_identity || !management)
   985         return PEP_ILLEGAL_VALUE;
   986 
   987     status = init(&session);
   988     assert(status == PEP_STATUS_OK);
   989     if (status != PEP_STATUS_OK)
   990         return status;
   991 
   992     log_event(session, "keymanagement thread started", "pEp engine", NULL, NULL);
   993 
   994     while ((identity = retrieve_next_identity(management))) 
   995     {
   996         assert(identity->address);
   997         if(identity->address)
   998         {
   999             DEBUG_LOG("do_keymanagement", "retrieve_next_identity", identity->address);
  1000 
  1001             if (_identity_me(identity)) {
  1002                 status = myself(session, identity);
  1003             } else {
  1004                 status = recv_key(session, identity->address);
  1005             }
  1006 
  1007             assert(status != PEP_OUT_OF_MEMORY);
  1008             if(status == PEP_OUT_OF_MEMORY)
  1009                 return PEP_OUT_OF_MEMORY;
  1010         }
  1011         free_identity(identity);
  1012     }
  1013 
  1014     log_event(session, "keymanagement thread shutdown", "pEp engine", NULL, NULL);
  1015 
  1016     release(session);
  1017     return PEP_STATUS_OK;
  1018 }
  1019 
  1020 DYNAMIC_API PEP_STATUS key_mistrusted(
  1021         PEP_SESSION session,
  1022         pEp_identity *ident
  1023     )
  1024 {
  1025     PEP_STATUS status = PEP_STATUS_OK;
  1026 
  1027     assert(session);
  1028     assert(ident);
  1029     assert(!EMPTYSTR(ident->fpr));
  1030 
  1031     if (!(session && ident && ident->fpr))
  1032         return PEP_ILLEGAL_VALUE;
  1033 
  1034     if (_identity_me(ident))
  1035     {
  1036         revoke_key(session, ident->fpr, NULL);
  1037         myself(session, ident);
  1038     }
  1039     else
  1040     {
  1041         // for undo
  1042         if (session->cached_mistrusted)
  1043             free(session->cached_mistrusted);
  1044         session->cached_mistrusted = identity_dup(ident);
  1045         status = mark_as_compromized(session, ident->fpr);
  1046     }
  1047 
  1048     return status;
  1049 }
  1050 
  1051 DYNAMIC_API PEP_STATUS undo_last_mistrust(PEP_SESSION session) {
  1052     assert(session);
  1053     
  1054     if (!session)
  1055         return PEP_ILLEGAL_VALUE;
  1056     
  1057     PEP_STATUS status = PEP_STATUS_OK;
  1058         
  1059     pEp_identity* cached_ident = session->cached_mistrusted;
  1060     
  1061     if (!cached_ident)
  1062         status = PEP_CANNOT_FIND_IDENTITY;
  1063     else {
  1064         status = set_identity(session, cached_ident);            
  1065         free_identity(session->cached_mistrusted);
  1066     }
  1067     
  1068     session->cached_mistrusted = NULL;
  1069 
  1070     return status;
  1071 }
  1072 
  1073 DYNAMIC_API PEP_STATUS key_reset_trust(
  1074         PEP_SESSION session,
  1075         pEp_identity *ident
  1076     )
  1077 {
  1078     PEP_STATUS status = PEP_STATUS_OK;
  1079 
  1080     assert(session);
  1081     assert(ident);
  1082     assert(!_identity_me(ident));
  1083     assert(!EMPTYSTR(ident->fpr));
  1084     assert(!EMPTYSTR(ident->address));
  1085     assert(!EMPTYSTR(ident->user_id));
  1086 
  1087     if (!(session && ident && !_identity_me(ident) && ident->fpr && ident->address &&
  1088             ident->user_id))
  1089         return PEP_ILLEGAL_VALUE;
  1090 
  1091     status = update_identity(session, ident);
  1092     if (status != PEP_STATUS_OK)
  1093         return status;
  1094 
  1095     if (ident->comm_type == PEP_ct_mistrusted)
  1096         ident->comm_type = PEP_ct_unknown;
  1097     else
  1098         ident->comm_type &= ~PEP_ct_confirmed;
  1099 
  1100     status = set_identity(session, ident);
  1101     if (status != PEP_STATUS_OK)
  1102         return status;
  1103 
  1104     if (ident->comm_type == PEP_ct_unknown)
  1105         status = update_identity(session, ident);
  1106     return status;
  1107 }
  1108 
  1109 DYNAMIC_API PEP_STATUS trust_personal_key(
  1110         PEP_SESSION session,
  1111         pEp_identity *ident
  1112     )
  1113 {
  1114     PEP_STATUS status = PEP_STATUS_OK;
  1115 
  1116     assert(session);
  1117     assert(ident);
  1118     assert(!EMPTYSTR(ident->address));
  1119     assert(!EMPTYSTR(ident->user_id));
  1120     assert(!EMPTYSTR(ident->fpr));
  1121 
  1122     if (!ident || EMPTYSTR(ident->address) || EMPTYSTR(ident->user_id) ||
  1123             EMPTYSTR(ident->fpr))
  1124         return PEP_ILLEGAL_VALUE;
  1125 
  1126     status = update_identity(session, ident);
  1127     if (status != PEP_STATUS_OK)
  1128         return status;
  1129 
  1130     if (ident->comm_type > PEP_ct_strong_but_unconfirmed) {
  1131         ident->comm_type |= PEP_ct_confirmed;
  1132         status = set_identity(session, ident);
  1133     }
  1134     else {
  1135         // MISSING: S/MIME has to be handled depending on trusted CAs
  1136         status = PEP_CANNOT_SET_TRUST;
  1137     }
  1138 
  1139     return status;
  1140 }
  1141 
  1142 DYNAMIC_API PEP_STATUS own_key_is_listed(
  1143         PEP_SESSION session,
  1144         const char *fpr,
  1145         bool *listed
  1146     )
  1147 {
  1148     PEP_STATUS status = PEP_STATUS_OK;
  1149     int count;
  1150     
  1151     assert(session && fpr && fpr[0] && listed);
  1152     
  1153     if (!(session && fpr && fpr[0] && listed))
  1154         return PEP_ILLEGAL_VALUE;
  1155     
  1156     *listed = false;
  1157     
  1158     sqlite3_reset(session->own_key_is_listed);
  1159     sqlite3_bind_text(session->own_key_is_listed, 1, fpr, -1, SQLITE_STATIC);
  1160     
  1161     int result;
  1162     
  1163     result = sqlite3_step(session->own_key_is_listed);
  1164     switch (result) {
  1165         case SQLITE_ROW:
  1166             count = sqlite3_column_int(session->own_key_is_listed, 0);
  1167             *listed = count > 0;
  1168             status = PEP_STATUS_OK;
  1169             break;
  1170             
  1171         default:
  1172             status = PEP_UNKNOWN_ERROR;
  1173     }
  1174     
  1175     sqlite3_reset(session->own_key_is_listed);
  1176     return status;
  1177 }
  1178 
  1179 PEP_STATUS _own_identities_retrieve(
  1180         PEP_SESSION session,
  1181         identity_list **own_identities,
  1182         identity_flags_t excluded_flags
  1183       )
  1184 {
  1185     PEP_STATUS status = PEP_STATUS_OK;
  1186     
  1187     assert(session && own_identities);
  1188     if (!(session && own_identities))
  1189         return PEP_ILLEGAL_VALUE;
  1190     
  1191     *own_identities = NULL;
  1192     identity_list *_own_identities = new_identity_list(NULL);
  1193     if (_own_identities == NULL)
  1194         goto enomem;
  1195     
  1196     sqlite3_reset(session->own_identities_retrieve);
  1197     
  1198     int result;
  1199     // address, fpr, username, user_id, comm_type, lang, flags
  1200     const char *address = NULL;
  1201     const char *fpr = NULL;
  1202     const char *username = NULL;
  1203     const char *user_id = NULL;
  1204     PEP_comm_type comm_type = PEP_ct_unknown;
  1205     const char *lang = NULL;
  1206     unsigned int flags = 0;
  1207     
  1208     identity_list *_bl = _own_identities;
  1209     do {
  1210         sqlite3_bind_int(session->own_identities_retrieve, 1, excluded_flags);
  1211         result = sqlite3_step(session->own_identities_retrieve);
  1212         switch (result) {
  1213             case SQLITE_ROW:
  1214                 address = (const char *)
  1215                     sqlite3_column_text(session->own_identities_retrieve, 0);
  1216                 fpr = (const char *)
  1217                     sqlite3_column_text(session->own_identities_retrieve, 1);
  1218                 user_id = (const char *)
  1219                     sqlite3_column_text(session->own_identities_retrieve, 2);
  1220                 username = (const char *)
  1221                     sqlite3_column_text(session->own_identities_retrieve, 3);
  1222                 comm_type = PEP_ct_pEp;
  1223                 lang = (const char *)
  1224                     sqlite3_column_text(session->own_identities_retrieve, 4);
  1225                 flags = (unsigned int)
  1226                     sqlite3_column_int(session->own_identities_retrieve, 5);
  1227 
  1228                 pEp_identity *ident = new_identity(address, fpr, user_id, username);
  1229                 if (!ident)
  1230                     goto enomem;
  1231                 ident->comm_type = comm_type;
  1232                 if (lang && lang[0]) {
  1233                     ident->lang[0] = lang[0];
  1234                     ident->lang[1] = lang[1];
  1235                     ident->lang[2] = 0;
  1236                 }
  1237                 ident->me = true;
  1238                 ident->flags = flags;
  1239 
  1240                 _bl = identity_list_add(_bl, ident);
  1241                 if (_bl == NULL) {
  1242                     free_identity(ident);
  1243                     goto enomem;
  1244                 }
  1245                 
  1246                 break;
  1247                 
  1248             case SQLITE_DONE:
  1249                 break;
  1250                 
  1251             default:
  1252                 status = PEP_UNKNOWN_ERROR;
  1253                 result = SQLITE_DONE;
  1254         }
  1255     } while (result != SQLITE_DONE);
  1256     
  1257     sqlite3_reset(session->own_identities_retrieve);
  1258     if (status == PEP_STATUS_OK)
  1259         *own_identities = _own_identities;
  1260     else
  1261         free_identity_list(_own_identities);
  1262     
  1263     goto the_end;
  1264     
  1265 enomem:
  1266     free_identity_list(_own_identities);
  1267     status = PEP_OUT_OF_MEMORY;
  1268     
  1269 the_end:
  1270     return status;
  1271 }
  1272 
  1273 DYNAMIC_API PEP_STATUS own_identities_retrieve(
  1274         PEP_SESSION session,
  1275         identity_list **own_identities
  1276       )
  1277 {
  1278     return _own_identities_retrieve(session, own_identities, 0);
  1279 }
  1280 
  1281 PEP_STATUS _own_keys_retrieve(
  1282         PEP_SESSION session,
  1283         stringlist_t **keylist,
  1284         identity_flags_t excluded_flags
  1285       )
  1286 {
  1287     PEP_STATUS status = PEP_STATUS_OK;
  1288     
  1289     assert(session && keylist);
  1290     if (!(session && keylist))
  1291         return PEP_ILLEGAL_VALUE;
  1292     
  1293     *keylist = NULL;
  1294     stringlist_t *_keylist = NULL;
  1295     
  1296     sqlite3_reset(session->own_keys_retrieve);
  1297     
  1298     int result;
  1299     char *fpr = NULL;
  1300     
  1301     stringlist_t *_bl = _keylist;
  1302     do {
  1303         sqlite3_bind_int(session->own_keys_retrieve, 1, excluded_flags);
  1304         result = sqlite3_step(session->own_keys_retrieve);
  1305         switch (result) {
  1306             case SQLITE_ROW:
  1307                 fpr = strdup((const char *) sqlite3_column_text(session->own_keys_retrieve, 0));
  1308                 if(fpr == NULL)
  1309                     goto enomem;
  1310 
  1311                 _bl = stringlist_add(_bl, fpr);
  1312                 if (_bl == NULL) {
  1313                     free(fpr);
  1314                     goto enomem;
  1315                 }
  1316                 if (_keylist == NULL)
  1317                     _keylist = _bl;
  1318                 
  1319                 break;
  1320                 
  1321             case SQLITE_DONE:
  1322                 break;
  1323                 
  1324             default:
  1325                 status = PEP_UNKNOWN_ERROR;
  1326                 result = SQLITE_DONE;
  1327         }
  1328     } while (result != SQLITE_DONE);
  1329     
  1330     sqlite3_reset(session->own_keys_retrieve);
  1331     if (status == PEP_STATUS_OK)
  1332         *keylist = _keylist;
  1333     else
  1334         free_stringlist(_keylist);
  1335     
  1336     goto the_end;
  1337     
  1338 enomem:
  1339     free_stringlist(_keylist);
  1340     status = PEP_OUT_OF_MEMORY;
  1341     
  1342 the_end:
  1343     return status;
  1344 }
  1345 
  1346 DYNAMIC_API PEP_STATUS own_keys_retrieve(PEP_SESSION session, stringlist_t **keylist)
  1347 {
  1348     return _own_keys_retrieve(session, keylist, 0);
  1349 }
  1350 
  1351 // FIXME: should it be be used when sync receive old keys ? (ENGINE-145)
  1352 DYNAMIC_API PEP_STATUS set_own_key(
  1353        PEP_SESSION session,
  1354        const char *address,
  1355        const char *fpr
  1356     )
  1357 {
  1358     PEP_STATUS status = PEP_STATUS_OK;
  1359     
  1360     assert(session &&
  1361            address &&
  1362            fpr && fpr[0]
  1363           );
  1364     
  1365     if (!(session &&
  1366           address &&
  1367           fpr && fpr[0]
  1368          ))
  1369         return PEP_ILLEGAL_VALUE;
  1370             
  1371             
  1372     // First see if we have it in own identities already, AND we retrieve
  1373     // our own user_id
  1374     pEp_identity* my_id = NULL;
  1375     identity_list* my_identities = NULL;
  1376     char* my_user_id = NULL;
  1377     status = own_identities_retrieve(session, &my_identities);
  1378     
  1379     if (status == PEP_STATUS_OK) {
  1380         if (my_identities) {
  1381             if (!(my_identities->ident && my_identities->ident->user_id))
  1382                 return PEP_ILLEGAL_VALUE;
  1383 
  1384             my_user_id = strdup(my_identities->ident->user_id);
  1385 
  1386             if (!my_user_id) 
  1387                 return PEP_OUT_OF_MEMORY;
  1388             
  1389             // Probably cheaper than all the strcmps if there are many,
  1390             // plus this avoids the capitalisation and . problems:
  1391             
  1392             status = get_identity(session, my_user_id, address, &my_id);
  1393             
  1394             if (status == PEP_STATUS_OK && my_id) {
  1395                 if (my_id->fpr && strcasecmp(my_id->fpr, fpr) == 0) {
  1396                     // We're done. It was already here.
  1397                     // FIXME: Do we check trust/revocation/?
  1398                     goto pep_free;
  1399                 }            
  1400             }
  1401             
  1402             // Otherwise, we see if there's a binding for this user_id/key
  1403             // in the trust DB
  1404             
  1405             // If there's an id w/ user_id + address
  1406             if (my_id) {
  1407                 free(my_id->fpr);
  1408                 my_id->fpr = my_user_id;
  1409                 my_id->comm_type = PEP_ct_pEp;
  1410                 my_id->me = true; // just in case? 
  1411             }
  1412             else { // Else, we need a new identity
  1413                 my_id = new_identity(address, fpr, my_user_id, NULL); 
  1414                 if (status != PEP_STATUS_OK)
  1415                     goto pep_free; 
  1416                 my_id->me = true;
  1417                 my_id->comm_type = PEP_ct_pEp;
  1418             }
  1419         }
  1420         else {
  1421             // I think the prerequisite should be that at least one own identity
  1422             // already in the DB, so REALLY look at this.
  1423             return PEP_CANNOT_FIND_IDENTITY;
  1424         }
  1425         
  1426         status = set_identity(session, my_id);
  1427     }  
  1428     
  1429 pep_free:
  1430     free(my_id);
  1431     free(my_user_id);
  1432     return status;
  1433 }
  1434 
  1435 PEP_STATUS contains_priv_key(PEP_SESSION session, const char *fpr,
  1436                              bool *has_private) {
  1437 
  1438     assert(session);
  1439     assert(fpr);
  1440     assert(has_private);
  1441     
  1442     if (!(session && fpr && has_private))
  1443         return PEP_ILLEGAL_VALUE;
  1444 
  1445     return session->cryptotech[PEP_crypt_OpenPGP].contains_priv_key(session, fpr, has_private);
  1446 }