src/keymanagement.c
author Volker Birk <vb@pep.foundation>
Thu, 01 Sep 2016 17:55:03 +0200
branchkeysync
changeset 1111 3c46dc58096d
parent 1080 59f4dd88605c
child 1140 c11cfcd37237
permissions -rw-r--r--
merging
     1 #include "platform.h"
     2 
     3 #include <string.h>
     4 #include <stdio.h>
     5 #include <stdlib.h>
     6 #include <assert.h>
     7 #include <ctype.h>
     8 
     9 #include "pEp_internal.h"
    10 #include "keymanagement.h"
    11 
    12 #ifndef EMPTYSTR
    13 #define EMPTYSTR(STR) ((STR) == NULL || (STR)[0] == '\0')
    14 #endif
    15 
    16 #define KEY_EXPIRE_DELTA (60 * 60 * 24 * 365)
    17 
    18 // Space tolerant and case insensitive fingerprint string compare
    19 static int _same_fpr(
    20         const char* fpra,
    21         size_t fpras,
    22         const char* fprb,
    23         size_t fprbs
    24     )
    25 {
    26     size_t ai = 0;
    27     size_t bi = 0;
    28     
    29     do
    30     {
    31         if(fpra[ai] == 0 || fprb[bi] == 0)
    32         {
    33             return 0;
    34         }
    35         else if(fpra[ai] == ' ')
    36         {
    37             ai++;
    38         }
    39         else if(fprb[bi] == ' ')
    40         {
    41             bi++;
    42         }
    43         else if(toupper(fpra[ai]) == toupper(fprb[bi]))
    44         {
    45             ai++;
    46             bi++;
    47         }
    48         else
    49         {
    50             return 0;
    51         }
    52         
    53     }
    54     while(ai < fpras && bi < fprbs);
    55     
    56     return ai == fpras && bi == fprbs;
    57 }
    58 
    59 PEP_STATUS elect_pubkey(
    60         PEP_SESSION session, pEp_identity * identity
    61     )
    62 {
    63     PEP_STATUS status;
    64     stringlist_t *keylist;
    65     char *_fpr = NULL;
    66     identity->comm_type = PEP_ct_unknown;
    67 
    68     status = find_keys(session, identity->address, &keylist);
    69     assert(status != PEP_OUT_OF_MEMORY);
    70     if (status == PEP_OUT_OF_MEMORY)
    71         return PEP_OUT_OF_MEMORY;
    72 
    73     stringlist_t *_keylist;
    74     for (_keylist = keylist; _keylist && _keylist->value; _keylist = _keylist->next) {
    75         PEP_comm_type _comm_type_key;
    76 
    77         status = get_key_rating(session, _keylist->value, &_comm_type_key);
    78         assert(status != PEP_OUT_OF_MEMORY);
    79         if (status == PEP_OUT_OF_MEMORY) {
    80             free_stringlist(keylist);
    81             return PEP_OUT_OF_MEMORY;
    82         }
    83 
    84         if (_comm_type_key != PEP_ct_compromized &&
    85             _comm_type_key != PEP_ct_unknown)
    86         {
    87             if (identity->comm_type == PEP_ct_unknown ||
    88                 _comm_type_key > identity->comm_type)
    89             {
    90                 identity->comm_type = _comm_type_key;
    91                 _fpr = _keylist->value;
    92             }
    93         }
    94     }
    95 
    96     if (_fpr) {
    97         free(identity->fpr);
    98 
    99         identity->fpr = strdup(_fpr);
   100         if (identity->fpr == NULL) {
   101             free_stringlist(keylist);
   102             return PEP_OUT_OF_MEMORY;
   103         }
   104     }
   105     free_stringlist(keylist);
   106     return PEP_STATUS_OK;
   107 }
   108 
   109 DYNAMIC_API PEP_STATUS update_identity(
   110         PEP_SESSION session, pEp_identity * identity
   111     )
   112 {
   113     pEp_identity *stored_identity;
   114     PEP_STATUS status;
   115 
   116     assert(session);
   117     assert(identity);
   118     assert(!EMPTYSTR(identity->address));
   119 
   120     if (!(session && identity && !EMPTYSTR(identity->address)))
   121         return PEP_ILLEGAL_VALUE;
   122 
   123     if (identity->me || (identity->user_id && strcmp(identity->user_id, PEP_OWN_USERID) == 0)) {
   124         identity->me = true;
   125         return myself(session, identity);
   126     }
   127 
   128     int _no_user_id = EMPTYSTR(identity->user_id);
   129 
   130     if (_no_user_id)
   131     {
   132         status = get_identity(session, identity->address, PEP_OWN_USERID,
   133                 &stored_identity);
   134         if (status == PEP_STATUS_OK) {
   135             free_identity(stored_identity);
   136             return myself(session, identity);
   137         }
   138 
   139         free(identity->user_id);
   140 
   141         identity->user_id = calloc(1, strlen(identity->address) + 6);
   142         if (!identity->user_id)
   143         {
   144             return PEP_OUT_OF_MEMORY;
   145         }
   146         snprintf(identity->user_id, strlen(identity->address) + 6,
   147                  "TOFU_%s", identity->address);
   148     }
   149  
   150     status = get_identity(session,
   151                           identity->address,
   152                           identity->user_id,
   153                           &stored_identity);
   154     
   155     assert(status != PEP_OUT_OF_MEMORY);
   156     if (status == PEP_OUT_OF_MEMORY)
   157         goto exit_free;
   158 
   159     if (stored_identity) {
   160         PEP_comm_type _comm_type_key;
   161         status = get_key_rating(session, stored_identity->fpr, &_comm_type_key);
   162         assert(status != PEP_OUT_OF_MEMORY);
   163         if (status == PEP_OUT_OF_MEMORY)
   164             goto exit_free;
   165 
   166         if (EMPTYSTR(identity->username)) {
   167             free(identity->username);
   168             identity->username = strdup(stored_identity->username);
   169             assert(identity->username);
   170             if (identity->username == NULL){
   171                 status = PEP_OUT_OF_MEMORY;
   172                 goto exit_free;
   173             }
   174         }
   175 
   176         if (EMPTYSTR(identity->fpr)) {
   177             identity->fpr = strdup(stored_identity->fpr);
   178             assert(identity->fpr);
   179             if (identity->fpr == NULL)
   180                 return PEP_OUT_OF_MEMORY;
   181             if (_comm_type_key < PEP_ct_unconfirmed_encryption) {
   182                 PEP_STATUS status = elect_pubkey(session, identity);
   183                 if (status != PEP_STATUS_OK)
   184                     goto exit_free;
   185             }
   186             else {
   187                 identity->comm_type = stored_identity->comm_type;
   188             }
   189         }
   190         else /* !EMPTYSTR(identity->fpr) */ {
   191             if (_same_fpr(identity->fpr,
   192                           strlen(identity->fpr),
   193                           stored_identity->fpr,
   194                           strlen(stored_identity->fpr))) {
   195                 if (_comm_type_key < PEP_ct_unconfirmed_encryption) {
   196                     identity->comm_type = _comm_type_key;
   197                 }else{
   198                     identity->comm_type = stored_identity->comm_type;
   199                     if (identity->comm_type == PEP_ct_unknown) {
   200                         identity->comm_type = _comm_type_key;
   201                     }
   202                 }
   203             } else {
   204                 status = get_trust(session, identity);
   205                 assert(status != PEP_OUT_OF_MEMORY);
   206                 if (status == PEP_OUT_OF_MEMORY)
   207                     goto exit_free;
   208                 if (identity->comm_type < stored_identity->comm_type)
   209                     identity->comm_type = PEP_ct_unknown;
   210             }
   211         }
   212 
   213         if (identity->lang[0] == 0) {
   214             identity->lang[0] = stored_identity->lang[0];
   215             identity->lang[1] = stored_identity->lang[1];
   216             identity->lang[2] = 0;
   217         }
   218 
   219         identity->flags = stored_identity->flags;
   220     }
   221     else /* stored_identity == NULL */ {
   222         identity->flags = 0;
   223 
   224         if (!EMPTYSTR(identity->fpr)) {
   225             PEP_comm_type _comm_type_key;
   226 
   227             status = get_key_rating(session, identity->fpr, &_comm_type_key);
   228             assert(status != PEP_OUT_OF_MEMORY);
   229             if (status == PEP_OUT_OF_MEMORY)
   230                 goto exit_free;
   231 
   232             identity->comm_type = _comm_type_key;
   233         }
   234         else /* EMPTYSTR(identity->fpr) */ {
   235             PEP_STATUS status = elect_pubkey(session, identity);
   236             if (status != PEP_STATUS_OK)
   237                 goto exit_free;
   238         }
   239     }
   240 
   241     status = PEP_STATUS_OK;
   242 
   243     if (identity->comm_type != PEP_ct_unknown && !EMPTYSTR(identity->user_id)) {
   244         assert(!EMPTYSTR(identity->username)); // this should not happen
   245 
   246         if (EMPTYSTR(identity->username)) { // mitigate
   247             free(identity->username);
   248             identity->username = strdup("anonymous");
   249             assert(identity->username);
   250             if (identity->username == NULL){
   251                 status = PEP_OUT_OF_MEMORY;
   252                 goto exit_free;
   253             }
   254         }
   255 
   256         // Identity doesn't get stored if call was just about checking existing
   257         // user by address (i.e. no user id given but already stored)
   258         if (!(_no_user_id && stored_identity))
   259         {
   260             status = set_identity(session, identity);
   261             assert(status == PEP_STATUS_OK);
   262             if (status != PEP_STATUS_OK) {
   263                 goto exit_free;
   264             }
   265         }
   266     }
   267 
   268     if (identity->comm_type != PEP_ct_compromized &&
   269             identity->comm_type < PEP_ct_strong_but_unconfirmed)
   270         if (session->examine_identity)
   271             session->examine_identity(identity, session->examine_management);
   272 
   273 exit_free :
   274     
   275     if (stored_identity){
   276         free_identity(stored_identity);
   277     }
   278 
   279     return status;
   280 }
   281 
   282 PEP_STATUS elect_ownkey(
   283         PEP_SESSION session, pEp_identity * identity
   284     )
   285 {
   286     PEP_STATUS status;
   287     stringlist_t *keylist = NULL;
   288 
   289     free(identity->fpr);
   290     identity->fpr = NULL;
   291 
   292     status = find_keys(session, identity->address, &keylist);
   293     assert(status != PEP_OUT_OF_MEMORY);
   294     if (status == PEP_OUT_OF_MEMORY)
   295         return PEP_OUT_OF_MEMORY;
   296     
   297     if (keylist != NULL && keylist->value != NULL)
   298     {
   299         char *_fpr = NULL;
   300         identity->comm_type = PEP_ct_unknown;
   301 
   302         stringlist_t *_keylist;
   303         for (_keylist = keylist; _keylist && _keylist->value; _keylist = _keylist->next) {
   304             bool is_own = false;
   305             
   306             if (session->use_only_own_private_keys)
   307             {
   308                 status = own_key_is_listed(session, _keylist->value, &is_own);
   309                 assert(status == PEP_STATUS_OK);
   310                 if (status != PEP_STATUS_OK) {
   311                     free_stringlist(keylist);
   312                     return status;
   313                 }
   314             }
   315 
   316             // TODO : also accept synchronized device group keys ?
   317             
   318             if (!session->use_only_own_private_keys || is_own)
   319             {
   320                 PEP_comm_type _comm_type_key;
   321                 
   322                 status = get_key_rating(session, _keylist->value, &_comm_type_key);
   323                 assert(status != PEP_OUT_OF_MEMORY);
   324                 if (status == PEP_OUT_OF_MEMORY) {
   325                     free_stringlist(keylist);
   326                     return PEP_OUT_OF_MEMORY;
   327                 }
   328                 
   329                 if (_comm_type_key != PEP_ct_compromized &&
   330                     _comm_type_key != PEP_ct_unknown)
   331                 {
   332                     if (identity->comm_type == PEP_ct_unknown ||
   333                         _comm_type_key > identity->comm_type)
   334                     {
   335                         identity->comm_type = _comm_type_key;
   336                         _fpr = _keylist->value;
   337                     }
   338                 }
   339             }
   340         }
   341         
   342         if (_fpr)
   343         {
   344             identity->fpr = strdup(_fpr);
   345             assert(identity->fpr);
   346             if (identity->fpr == NULL)
   347             {
   348                 free_stringlist(keylist);
   349                 return PEP_OUT_OF_MEMORY;
   350             }
   351         }
   352         free_stringlist(keylist);
   353     }
   354     return PEP_STATUS_OK;
   355 }
   356 
   357 DYNAMIC_API PEP_STATUS myself(PEP_SESSION session, pEp_identity * identity)
   358 {
   359     pEp_identity *stored_identity;
   360     PEP_STATUS status;
   361 
   362     assert(session);
   363     assert(identity);
   364     assert(!EMPTYSTR(identity->address));
   365 
   366     assert(EMPTYSTR(identity->user_id) ||
   367            strcmp(identity->user_id, PEP_OWN_USERID) == 0);
   368 
   369     if (!(session && identity && !EMPTYSTR(identity->address) &&
   370             (EMPTYSTR(identity->user_id) ||
   371             strcmp(identity->user_id, PEP_OWN_USERID) == 0)))
   372         return PEP_ILLEGAL_VALUE;
   373 
   374     identity->comm_type = PEP_ct_pEp;
   375     identity->me = true;
   376     
   377     if (EMPTYSTR(identity->user_id))
   378     {
   379         free(identity->user_id);
   380         identity->user_id = strdup(PEP_OWN_USERID);
   381         assert(identity->user_id);
   382         if (identity->user_id == NULL)
   383             return PEP_OUT_OF_MEMORY;
   384     }
   385 
   386     DEBUG_LOG("myself", "debug", identity->address);
   387  
   388     status = get_identity(session,
   389                           identity->address,
   390                           identity->user_id,
   391                           &stored_identity);
   392     
   393     assert(status != PEP_OUT_OF_MEMORY);
   394     if (status == PEP_OUT_OF_MEMORY)
   395         return PEP_OUT_OF_MEMORY;
   396     
   397     if (stored_identity)
   398     {
   399         if (EMPTYSTR(identity->fpr)) {
   400             identity->fpr = strdup(stored_identity->fpr);
   401             assert(identity->fpr);
   402             if (identity->fpr == NULL)
   403             {
   404                 return PEP_OUT_OF_MEMORY;
   405             }
   406         }
   407 
   408         identity->flags = stored_identity->flags;
   409     }
   410     else if (!EMPTYSTR(identity->fpr))
   411     {
   412         // App must have a good reason to give fpr, such as explicit
   413         // import of private key, or similar.
   414 
   415         // Take given fpr as-is.
   416 
   417         identity->flags = 0;
   418     }
   419     else
   420     {
   421         status = elect_ownkey(session, identity);
   422         assert(status == PEP_STATUS_OK);
   423         if (status != PEP_STATUS_OK) {
   424             return status;
   425         }
   426 
   427         identity->flags = 0;
   428     }
   429 
   430     bool revoked = false;
   431     char *r_fpr = NULL;
   432     if (!EMPTYSTR(identity->fpr))
   433     {
   434         status = key_revoked(session, identity->fpr, &revoked);
   435 
   436         // Forces re-election if key is missing and own-key-only not forced
   437         if (!session->use_only_own_private_keys && status == PEP_KEY_NOT_FOUND) 
   438         {
   439             status = elect_ownkey(session, identity);
   440             assert(status == PEP_STATUS_OK);
   441             if (status != PEP_STATUS_OK) {
   442                 return status;
   443             }
   444         } 
   445         else if (status != PEP_STATUS_OK) 
   446         {
   447             return status;
   448         }
   449     }
   450     
   451     if (EMPTYSTR(identity->fpr) || revoked)
   452     {        
   453         if(revoked)
   454         {
   455             r_fpr = identity->fpr;
   456             identity->fpr = NULL;
   457         }
   458         
   459         DEBUG_LOG("generating key pair", "debug", identity->address);
   460         status = generate_keypair(session, identity);
   461         assert(status != PEP_OUT_OF_MEMORY);
   462         if (status != PEP_STATUS_OK) {
   463             char buf[11];
   464             snprintf(buf, 11, "%d", status);
   465             DEBUG_LOG("generating key pair failed", "debug", buf);
   466             if(revoked && r_fpr)
   467                 free(r_fpr);
   468             return status;
   469         }
   470         
   471         if(revoked)
   472         {
   473             status = set_revoked(session, r_fpr,
   474                                  identity->fpr, time(NULL));
   475             free(r_fpr);
   476             if (status != PEP_STATUS_OK) {
   477                 return status;
   478             }
   479         }
   480     }
   481     else
   482     {
   483         bool expired;
   484         status = key_expired(session, identity->fpr, 
   485                              time(NULL) + (7*24*3600), // In a week
   486                              &expired);
   487 
   488         assert(status == PEP_STATUS_OK);
   489         if (status != PEP_STATUS_OK) {
   490             return status;
   491         }
   492 
   493         if (status == PEP_STATUS_OK && expired) {
   494             timestamp *ts = new_timestamp(time(NULL) + KEY_EXPIRE_DELTA);
   495             renew_key(session, identity->fpr, ts);
   496             free_timestamp(ts);
   497         }
   498     }
   499 
   500     status = set_identity(session, identity);
   501     assert(status == PEP_STATUS_OK);
   502     if (status != PEP_STATUS_OK) {
   503         return status;
   504     }
   505 
   506     return PEP_STATUS_OK;
   507 
   508 }
   509 
   510 DYNAMIC_API PEP_STATUS register_examine_function(
   511         PEP_SESSION session, 
   512         examine_identity_t examine_identity,
   513         void *management
   514     )
   515 {
   516     assert(session);
   517     if (!session)
   518         return PEP_ILLEGAL_VALUE;
   519 
   520     session->examine_management = management;
   521     session->examine_identity = examine_identity;
   522 
   523     return PEP_STATUS_OK;
   524 }
   525 
   526 DYNAMIC_API PEP_STATUS do_keymanagement(
   527         retrieve_next_identity_t retrieve_next_identity,
   528         void *management
   529     )
   530 {
   531     PEP_SESSION session;
   532     pEp_identity *identity;
   533     PEP_STATUS status;
   534 
   535     assert(retrieve_next_identity);
   536     assert(management);
   537 
   538     if (!retrieve_next_identity || !management)
   539         return PEP_ILLEGAL_VALUE;
   540 
   541     status = init(&session);
   542     assert(status == PEP_STATUS_OK);
   543     if (status != PEP_STATUS_OK)
   544         return status;
   545 
   546     log_event(session, "keymanagement thread started", "pEp engine", NULL, NULL);
   547 
   548     while ((identity = retrieve_next_identity(management))) 
   549     {
   550         assert(identity->address);
   551         if(identity->address)
   552         {
   553             DEBUG_LOG("do_keymanagement", "retrieve_next_identity", identity->address);
   554 
   555             if (identity->me) {
   556                 status = myself(session, identity);
   557             } else {
   558                 status = recv_key(session, identity->address);
   559             }
   560 
   561             assert(status != PEP_OUT_OF_MEMORY);
   562             if(status == PEP_OUT_OF_MEMORY)
   563                 return PEP_OUT_OF_MEMORY;
   564         }
   565         free_identity(identity);
   566     }
   567 
   568     log_event(session, "keymanagement thread shutdown", "pEp engine", NULL, NULL);
   569 
   570     release(session);
   571     return PEP_STATUS_OK;
   572 }
   573 
   574 DYNAMIC_API PEP_STATUS key_compromized(
   575         PEP_SESSION session,
   576         pEp_identity *ident
   577     )
   578 {
   579     PEP_STATUS status = PEP_STATUS_OK;
   580 
   581     assert(session);
   582     assert(ident);
   583     assert(!EMPTYSTR(ident->fpr));
   584 
   585     if (!(session && ident && ident->fpr))
   586         return PEP_ILLEGAL_VALUE;
   587 
   588     if (ident->me)
   589     {
   590         revoke_key(session, ident->fpr, NULL);
   591         myself(session, ident);
   592     }
   593     else
   594     {
   595         status = mark_as_compromized(session, ident->fpr);
   596     }
   597 
   598     return status;
   599 }
   600 
   601 DYNAMIC_API PEP_STATUS key_reset_trust(
   602         PEP_SESSION session,
   603         pEp_identity *ident
   604     )
   605 {
   606     PEP_STATUS status = PEP_STATUS_OK;
   607 
   608     assert(session);
   609     assert(ident);
   610     assert(!ident->me);
   611     assert(!EMPTYSTR(ident->fpr));
   612     assert(!EMPTYSTR(ident->address));
   613     assert(!EMPTYSTR(ident->user_id));
   614 
   615     if (!(session && ident && !ident->me && ident->fpr && ident->address &&
   616             ident->user_id))
   617         return PEP_ILLEGAL_VALUE;
   618 
   619     status = update_identity(session, ident);
   620     if (status != PEP_STATUS_OK)
   621         return status;
   622 
   623     if (ident->comm_type == PEP_ct_mistrusted)
   624         ident->comm_type = PEP_ct_unknown;
   625     else
   626         ident->comm_type &= ~PEP_ct_confirmed;
   627 
   628     status = set_identity(session, ident);
   629     if (status != PEP_STATUS_OK)
   630         return status;
   631 
   632     if (ident->comm_type == PEP_ct_unknown)
   633         status = update_identity(session, ident);
   634     return status;
   635 }
   636 
   637 DYNAMIC_API PEP_STATUS trust_personal_key(
   638         PEP_SESSION session,
   639         pEp_identity *ident
   640     )
   641 {
   642     PEP_STATUS status = PEP_STATUS_OK;
   643 
   644     assert(session);
   645     assert(ident);
   646     assert(!EMPTYSTR(ident->address));
   647     assert(!EMPTYSTR(ident->user_id));
   648     assert(!EMPTYSTR(ident->fpr));
   649     assert(!ident->me);
   650 
   651     if (!ident || EMPTYSTR(ident->address) || EMPTYSTR(ident->user_id) ||
   652             EMPTYSTR(ident->fpr) || ident->me)
   653         return PEP_ILLEGAL_VALUE;
   654 
   655     status = update_identity(session, ident);
   656     if (status != PEP_STATUS_OK)
   657         return status;
   658 
   659     if (ident->comm_type > PEP_ct_strong_but_unconfirmed) {
   660         ident->comm_type |= PEP_ct_confirmed;
   661         status = set_identity(session, ident);
   662     }
   663     else {
   664         // MISSING: S/MIME has to be handled depending on trusted CAs
   665         status = PEP_CANNOT_SET_TRUST;
   666     }
   667 
   668     return status;
   669 }
   670 
   671 DYNAMIC_API PEP_STATUS own_key_is_listed(
   672         PEP_SESSION session,
   673         const char *fpr,
   674         bool *listed
   675     )
   676 {
   677     PEP_STATUS status = PEP_STATUS_OK;
   678     int count;
   679     
   680     assert(session && fpr && fpr[0] && listed);
   681     
   682     if (!(session && fpr && fpr[0] && listed))
   683         return PEP_ILLEGAL_VALUE;
   684     
   685     *listed = false;
   686     
   687     sqlite3_reset(session->own_key_is_listed);
   688     sqlite3_bind_text(session->own_key_is_listed, 1, fpr, -1, SQLITE_STATIC);
   689     
   690     int result;
   691     
   692     result = sqlite3_step(session->own_key_is_listed);
   693     switch (result) {
   694         case SQLITE_ROW:
   695             count = sqlite3_column_int(session->own_key_is_listed, 0);
   696             *listed = count > 0;
   697             status = PEP_STATUS_OK;
   698             break;
   699             
   700         default:
   701             status = PEP_UNKNOWN_ERROR;
   702     }
   703     
   704     sqlite3_reset(session->own_key_is_listed);
   705     return status;
   706 }
   707 
   708 DYNAMIC_API PEP_STATUS own_identities_retrieve(
   709         PEP_SESSION session,
   710         identity_list **own_identities
   711       )
   712 {
   713     PEP_STATUS status = PEP_STATUS_OK;
   714     
   715     assert(session && own_identities);
   716     if (!(session && own_identities))
   717         return PEP_ILLEGAL_VALUE;
   718     
   719     *own_identities = NULL;
   720     identity_list *_own_identities = new_identity_list(NULL);
   721     if (_own_identities == NULL)
   722         goto enomem;
   723     
   724     sqlite3_reset(session->own_identities_retrieve);
   725     
   726     int result;
   727     // address, fpr, username, user_id, comm_type, lang, flags
   728     const char *address = NULL;
   729     const char *fpr = NULL;
   730     const char *username = NULL;
   731     const char *user_id = NULL;
   732     PEP_comm_type comm_type = PEP_ct_unknown;
   733     const char *lang = NULL;
   734     unsigned int flags = 0;
   735     
   736     identity_list *_bl = _own_identities;
   737     do {
   738         result = sqlite3_step(session->own_identities_retrieve);
   739         switch (result) {
   740             case SQLITE_ROW:
   741                 address = (const char *)
   742                     sqlite3_column_text(session->own_identities_retrieve, 0);
   743                 fpr = (const char *)
   744                     sqlite3_column_text(session->own_identities_retrieve, 1);
   745                 user_id = PEP_OWN_USERID;
   746                 username = (const char *)
   747                     sqlite3_column_text(session->own_identities_retrieve, 2);
   748                 comm_type = PEP_ct_pEp;
   749                 lang = (const char *)
   750                     sqlite3_column_text(session->own_identities_retrieve, 3);
   751                 flags = (unsigned int)
   752                     sqlite3_column_int(session->own_key_is_listed, 4);
   753 
   754                 pEp_identity *ident = new_identity(address, fpr, user_id, username);
   755                 if (!ident)
   756                     goto enomem;
   757                 ident->comm_type = comm_type;
   758                 if (lang && lang[0]) {
   759                     ident->lang[0] = lang[0];
   760                     ident->lang[1] = lang[1];
   761                     ident->lang[2] = 0;
   762                 }
   763                 ident->me = true;
   764                 ident->flags = flags;
   765 
   766                 _bl = identity_list_add(_bl, ident);
   767                 if (_bl == NULL) {
   768                     free_identity(ident);
   769                     goto enomem;
   770                 }
   771                 
   772                 break;
   773                 
   774             case SQLITE_DONE:
   775                 break;
   776                 
   777             default:
   778                 status = PEP_UNKNOWN_ERROR;
   779                 result = SQLITE_DONE;
   780         }
   781     } while (result != SQLITE_DONE);
   782     
   783     sqlite3_reset(session->own_identities_retrieve);
   784     if (status == PEP_STATUS_OK)
   785         *own_identities = _own_identities;
   786     else
   787         free_identity_list(_own_identities);
   788     
   789     goto the_end;
   790     
   791 enomem:
   792     free_identity_list(_own_identities);
   793     status = PEP_OUT_OF_MEMORY;
   794     
   795 the_end:
   796     return status;
   797 }
   798