src/pEpEngine.c
author Edouard Tisserant
Tue, 17 May 2016 17:19:19 +0200
changeset 641 ae3b959b3a7d
parent 633 a2a4ad55e19e
child 644 91574e3ca5fb
permissions -rw-r--r--
Use person.main_key_id
     1 #include "pEp_internal.h"
     2 #include "dynamic_api.h"
     3 #include "cryptotech.h"
     4 #include "transport.h"
     5 #include "blacklist.h"
     6 
     7 static int init_count = -1;
     8 
     9 DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
    10 {
    11     PEP_STATUS status = PEP_STATUS_OK;
    12     int int_result;
    13     static const char *sql_log;
    14     static const char *sql_trustword;
    15     static const char *sql_get_identity;
    16     static const char *sql_set_person;
    17     static const char *sql_set_pgp_keypair;
    18     static const char *sql_set_identity;
    19     static const char *sql_set_trust;
    20     static const char *sql_get_trust;
    21     static const char *sql_least_trust;
    22     static const char *sql_mark_as_compromized;
    23     static const char *sql_crashdump;
    24     static const char *sql_languagelist;
    25     static const char *sql_i18n_token;
    26 
    27     // blacklist
    28     static const char *sql_blacklist_add;
    29     static const char *sql_blacklist_delete;
    30     static const char *sql_blacklist_is_listed;
    31     static const char *sql_blacklist_retrieve;
    32 
    33     // Own keys
    34     static const char *sql_own_key_add;
    35     static const char *sql_own_key_is_listed;
    36     static const char *sql_own_key_retrieve;
    37 
    38     static const char *sql_sequence_value1;
    39     static const char *sql_sequence_value2;
    40 
    41     bool in_first = false;
    42 
    43     assert(sqlite3_threadsafe());
    44     if (!sqlite3_threadsafe())
    45         return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
    46 
    47     // a little race condition - but still a race condition
    48     // mitigated by calling caveat (see documentation)
    49 
    50     ++init_count;
    51     if (init_count == 0)
    52         in_first = true;
    53 
    54     assert(session);
    55     if (session == NULL)
    56         return PEP_ILLEGAL_VALUE;
    57 
    58     *session = NULL;
    59 
    60     pEpSession *_session = calloc(1, sizeof(pEpSession));
    61     assert(_session);
    62     if (_session == NULL)
    63         goto enomem;
    64 
    65     _session->version = PEP_ENGINE_VERSION;
    66 
    67     assert(LOCAL_DB);
    68     if (LOCAL_DB == NULL) {
    69         status = PEP_INIT_CANNOT_OPEN_DB;
    70         goto pep_error;
    71     }
    72 
    73     int_result = sqlite3_open_v2(
    74             LOCAL_DB,
    75             &_session->db,
    76             SQLITE_OPEN_READWRITE
    77                 | SQLITE_OPEN_CREATE
    78                 | SQLITE_OPEN_FULLMUTEX
    79                 | SQLITE_OPEN_PRIVATECACHE,
    80             NULL 
    81         );
    82 
    83     if (int_result != SQLITE_OK) {
    84         status = PEP_INIT_CANNOT_OPEN_DB;
    85         goto pep_error;
    86     }
    87 
    88     sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME);
    89 
    90     assert(SYSTEM_DB);
    91     if (SYSTEM_DB == NULL) {
    92         status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
    93         goto pep_error;
    94     }
    95 
    96     int_result = sqlite3_open_v2(
    97             SYSTEM_DB, &_session->system_db,
    98             SQLITE_OPEN_READONLY
    99                 | SQLITE_OPEN_FULLMUTEX
   100                 | SQLITE_OPEN_SHAREDCACHE,
   101             NULL
   102         );
   103 
   104     if (int_result != SQLITE_OK) {
   105         status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
   106         goto pep_error;
   107     }
   108 
   109     sqlite3_busy_timeout(_session->system_db, 1000);
   110 
   111     if (in_first) {
   112         int_result = sqlite3_exec(
   113             _session->db,
   114                 "create table if not exists version_info (\n"
   115                 "   id integer primary key,\n"
   116                 "   timestamp integer default (datetime('now')) ,\n"
   117                 "   version text,\n"
   118                 "   comment text\n"
   119                 ");\n"
   120                 "create table if not exists log (\n"
   121                 "   timestamp integer default (datetime('now')) ,\n"
   122                 "   title text not null,\n"
   123                 "   entity text not null,\n"
   124                 "   description text,\n"
   125                 "   comment text\n"
   126                 ");\n"
   127                 "create index if not exists log_timestamp on log (\n"
   128                 "   timestamp\n"
   129                 ");\n"
   130                 "create table if not exists pgp_keypair (\n"
   131                 "   fpr text primary key,\n"
   132                 "   public_id text unique,\n"
   133                 "   private_id text,\n"
   134                 "   created integer,\n"
   135                 "   expires integer,\n"
   136                 "   comment text\n"
   137                 ");\n"
   138                 "create index if not exists pgp_keypair_expires on pgp_keypair (\n"
   139                 "   expires\n"
   140                 ");\n"
   141                 "create table if not exists person (\n"
   142                 "   id text primary key,\n"
   143                 "   username text not null,\n"
   144                 "   main_key_id text\n"
   145                 "       references pgp_keypair (fpr)\n"
   146                 "       on delete set null,\n"
   147                 "   lang text,\n"
   148                 "   comment text\n"
   149                 ");\n"
   150                 "create table if not exists identity (\n"
   151                 "   address text,\n"
   152                 "   user_id text\n"
   153                 "       references person (id)\n"
   154                 "       on delete cascade,\n"
   155                 "   main_key_id text\n"
   156                 "       references pgp_keypair (fpr)\n"
   157                 "       on delete set null,\n"
   158                 "   comment text,\n"
   159                 "   primary key (address, user_id)\n"
   160                 ");\n"
   161                 "create table if not exists trust (\n"
   162                 "   user_id text not null\n"
   163                 "       references person (id)\n"
   164                 "       on delete cascade,\n"
   165                 "   pgp_keypair_fpr text not null\n"
   166                 "       references pgp_keypair (fpr)\n"
   167                 "       on delete cascade,\n"
   168                 "   comm_type integer not null,\n"
   169                 "   comment text\n"
   170                 ");\n"
   171                 "create unique index if not exists trust_index on trust (\n"
   172                 "   user_id,\n"
   173                 "   pgp_keypair_fpr\n"
   174                 ");\n"
   175                 // blacklist
   176                 "create table if not exists blacklist_keys (\n"
   177                 "   fpr text primary key\n"
   178                 ");\n"
   179                 // Own keys
   180                 "create table if not exists own_keys (\n"
   181                 "   fpr text primary key\n"
   182                 "       references pgp_keypair (fpr)\n"
   183                 "       on delete cascade\n"
   184                 ");\n"
   185                 // sequences
   186                 "create table if not exists sequences(\n"
   187                 "   name text primary key,\n"
   188                 "   value integer default 0\n"
   189                 ");\n"
   190                 ,
   191             NULL,
   192             NULL,
   193             NULL
   194         );
   195         assert(int_result == SQLITE_OK);
   196 
   197         int_result = sqlite3_exec(
   198             _session->db,
   199             "insert or replace into version_info (id, version) values (1, '1.1');",
   200             NULL,
   201             NULL,
   202             NULL
   203         );
   204         assert(int_result == SQLITE_OK);
   205 
   206         sql_log = "insert into log (title, entity, description, comment)"
   207                   "values (?1, ?2, ?3, ?4);";
   208 
   209         sql_get_identity =  "select fpr, username, comm_type, lang"
   210                             "   from identity"
   211                             "   join person on id = identity.user_id"
   212                             "   join pgp_keypair on fpr = identity.main_key_id"
   213                             "   join trust on id = trust.user_id"
   214                             "       and pgp_keypair_fpr = identity.main_key_id"
   215                             "   where address = ?1 and identity.user_id = ?2;";
   216 
   217         sql_trustword = "select id, word from wordlist where lang = lower(?1) "
   218                        "and id = ?2 ;";
   219 
   220         // Set person, but if already exist, only update.
   221         // if main_key_id already set, don't touch.
   222         sql_set_person = "insert or replace into person (id, username, lang, main_key_id)"
   223                          "  values (?1, ?2, ?3,"
   224                          "    (select coalesce((select main_key_id from person "
   225                          "      where id = ?1), ?4 ))) ;";
   226 
   227         sql_set_pgp_keypair = "insert or replace into pgp_keypair (fpr) "
   228                               "values (upper(replace(?1,' ',''))) ;";
   229 
   230         sql_set_identity = "insert or replace into identity (address, main_key_id, "
   231                            "user_id) values (?1, upper(replace(?2,' ','')), ?3) ;";
   232 
   233         sql_set_trust = "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type) "
   234                         "values (?1, upper(replace(?2,' ','')), ?3) ;";
   235 
   236         sql_get_trust = "select comm_type from trust where user_id = ?1 "
   237                         "and pgp_keypair_fpr = upper(replace(?2,' ','')) ;";
   238 
   239         sql_least_trust = "select min(comm_type) from trust where pgp_keypair_fpr = upper(replace(?1,' ','')) ;";
   240 
   241         sql_mark_as_compromized = "update trust not indexed set comm_type = 15"
   242                                   " where pgp_keypair_fpr = upper(replace(?1,' ','')) ;";
   243 
   244         sql_crashdump = "select timestamp, title, entity, description, comment"
   245                         " from log order by timestamp desc limit ?1 ;";
   246 
   247         sql_languagelist = "select i18n_language.lang, name, phrase from i18n_language join i18n_token using (lang) where i18n_token.id = 1000;" ;
   248 
   249         sql_i18n_token = "select phrase from i18n_token where lang = lower(?1) and id = ?2 ;";
   250 
   251         // blacklist
   252 
   253         sql_blacklist_add = "insert or replace into blacklist_keys (fpr) values (upper(replace(?1,' ',''))) ;"
   254                             "delete from identity where main_key_id = upper(replace(?1,' ','')) ;"
   255                             "delete from pgp_keypair where fpr = upper(replace(?1,' ','')) ;";
   256 
   257         sql_blacklist_delete = "delete from blacklist_keys where fpr = upper(replace(?1,' ','')) ;";
   258 
   259         sql_blacklist_is_listed = "select count(*) from blacklist_keys where fpr = upper(replace(?1,' ','')) ;";
   260 
   261         sql_blacklist_retrieve = "select * from blacklist_keys ;";
   262         
   263         // Own keys
   264         
   265         sql_own_key_add = "insert or replace into own_keys (fpr) "
   266                           "    values (upper(replace(?1,' ',''))) ;";
   267         
   268         sql_own_key_is_listed = "select count(*) from own_keys where fpr = upper(replace(?1,' ','')) ;";
   269 
   270         sql_own_key_retrieve = "select * from own_keys ;";
   271  
   272         sql_sequence_value1 = "insert or replace into sequences (name, value) "
   273                               "values (?1, "
   274                               "(select coalesce((select value + 1 from sequences "
   275                               "where name = ?1), 1 ))) ; ";
   276         sql_sequence_value2 = "select value from sequences where name = ?1 ;";
   277     }
   278 
   279     int_result = sqlite3_prepare_v2(_session->db, sql_log, (int)strlen(sql_log),
   280             &_session->log, NULL);
   281     assert(int_result == SQLITE_OK);
   282 
   283     int_result = sqlite3_prepare_v2(_session->system_db, sql_trustword,
   284             (int)strlen(sql_trustword), &_session->trustword, NULL);
   285     assert(int_result == SQLITE_OK);
   286 
   287     int_result = sqlite3_prepare_v2(_session->db, sql_get_identity,
   288             (int)strlen(sql_get_identity), &_session->get_identity, NULL);
   289     assert(int_result == SQLITE_OK);
   290 
   291     int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
   292             (int)strlen(sql_set_person), &_session->set_person, NULL);
   293     assert(int_result == SQLITE_OK);
   294 
   295     int_result = sqlite3_prepare_v2(_session->db, sql_set_pgp_keypair,
   296             (int)strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair, NULL);
   297     assert(int_result == SQLITE_OK);
   298 
   299     int_result = sqlite3_prepare_v2(_session->db, sql_set_identity,
   300             (int)strlen(sql_set_identity), &_session->set_identity, NULL);
   301     assert(int_result == SQLITE_OK);
   302 
   303     int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
   304             (int)strlen(sql_set_trust), &_session->set_trust, NULL);
   305     assert(int_result == SQLITE_OK);
   306 
   307     int_result = sqlite3_prepare_v2(_session->db, sql_get_trust,
   308             (int)strlen(sql_get_trust), &_session->get_trust, NULL);
   309     assert(int_result == SQLITE_OK);
   310 
   311     int_result = sqlite3_prepare_v2(_session->db, sql_least_trust,
   312             (int)strlen(sql_least_trust), &_session->least_trust, NULL);
   313     assert(int_result == SQLITE_OK);
   314 
   315     int_result = sqlite3_prepare_v2(_session->db, sql_mark_as_compromized,
   316             (int)strlen(sql_mark_as_compromized), &_session->mark_compromized, NULL);
   317     assert(int_result == SQLITE_OK);
   318 
   319     int_result = sqlite3_prepare_v2(_session->db, sql_crashdump,
   320             (int)strlen(sql_crashdump), &_session->crashdump, NULL);
   321     assert(int_result == SQLITE_OK);
   322 
   323     int_result = sqlite3_prepare_v2(_session->system_db, sql_languagelist,
   324             (int)strlen(sql_languagelist), &_session->languagelist, NULL);
   325     assert(int_result == SQLITE_OK);
   326 
   327     int_result = sqlite3_prepare_v2(_session->system_db, sql_i18n_token,
   328             (int)strlen(sql_i18n_token), &_session->i18n_token, NULL);
   329     assert(int_result == SQLITE_OK);
   330 
   331     // blacklist
   332 
   333     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_add,
   334             (int)strlen(sql_blacklist_add), &_session->blacklist_add, NULL);
   335     assert(int_result == SQLITE_OK);
   336 
   337     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_delete,
   338             (int)strlen(sql_blacklist_delete), &_session->blacklist_delete, NULL);
   339     assert(int_result == SQLITE_OK);
   340 
   341     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_is_listed,
   342             (int)strlen(sql_blacklist_is_listed), &_session->blacklist_is_listed, NULL);
   343     assert(int_result == SQLITE_OK);
   344 
   345     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_retrieve,
   346             (int)strlen(sql_blacklist_retrieve), &_session->blacklist_retrieve, NULL);
   347     assert(int_result == SQLITE_OK);
   348 
   349     // Own keys
   350     
   351     int_result = sqlite3_prepare_v2(_session->db, sql_own_key_add,
   352             (int)strlen(sql_own_key_add), &_session->own_key_add, NULL);
   353     assert(int_result == SQLITE_OK);
   354     
   355     int_result = sqlite3_prepare_v2(_session->db, sql_own_key_is_listed,
   356             (int)strlen(sql_own_key_is_listed), &_session->own_key_is_listed, NULL);
   357     assert(int_result == SQLITE_OK);
   358     
   359     int_result = sqlite3_prepare_v2(_session->db, sql_own_key_retrieve,
   360             (int)strlen(sql_own_key_retrieve), &_session->own_key_retrieve, NULL);
   361     assert(int_result == SQLITE_OK);
   362  
   363     // Sequence
   364 
   365     int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value1,
   366             (int)strlen(sql_sequence_value1), &_session->sequence_value1, NULL);
   367     assert(int_result == SQLITE_OK);
   368 
   369     int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value2,
   370             (int)strlen(sql_sequence_value2), &_session->sequence_value2, NULL);
   371     assert(int_result == SQLITE_OK);
   372 
   373     status = init_cryptotech(_session, in_first);
   374     if (status != PEP_STATUS_OK)
   375         goto pep_error;
   376 
   377     status = init_transport_system(_session, in_first);
   378     if (status != PEP_STATUS_OK)
   379         goto pep_error;
   380 
   381     status = log_event(_session, "init", "pEp " PEP_ENGINE_VERSION, NULL, NULL);
   382     if (status != PEP_STATUS_OK)
   383         goto pep_error;
   384 
   385     // runtime config
   386 
   387     _session->passive_mode = false;
   388     _session->unencrypted_subject = false;
   389 
   390     *session = _session;
   391     return PEP_STATUS_OK;
   392 
   393 enomem:
   394     status = PEP_OUT_OF_MEMORY;
   395 
   396 pep_error:
   397     release(_session);
   398     return status;
   399 }
   400 
   401 DYNAMIC_API void release(PEP_SESSION session)
   402 {
   403     bool out_last = false;
   404 
   405     assert(init_count >= 0);
   406     assert(session);
   407 
   408     if (!((init_count >= 0) && session))
   409         return;
   410 
   411     // a small race condition but still a race condition
   412     // mitigated by calling caveat (see documentation)
   413 
   414     if (init_count == 0)
   415         out_last = true;
   416     --init_count;
   417 
   418     if (session) {
   419         if (session->db) {
   420             if (session->log)
   421                 sqlite3_finalize(session->log);
   422             if (session->trustword)
   423                 sqlite3_finalize(session->trustword);
   424             if (session->get_identity)
   425                 sqlite3_finalize(session->get_identity);
   426             if (session->set_person)
   427                 sqlite3_finalize(session->set_person);
   428             if (session->set_pgp_keypair)
   429                 sqlite3_finalize(session->set_pgp_keypair);
   430             if (session->set_identity)
   431                 sqlite3_finalize(session->set_identity);
   432             if (session->set_trust)
   433                 sqlite3_finalize(session->set_trust);
   434             if (session->get_trust)
   435                 sqlite3_finalize(session->get_trust);
   436             if (session->least_trust)
   437                 sqlite3_finalize(session->least_trust);
   438             if (session->mark_compromized)
   439                 sqlite3_finalize(session->mark_compromized);
   440             if (session->crashdump)
   441                 sqlite3_finalize(session->crashdump);
   442             if (session->languagelist)
   443                 sqlite3_finalize(session->languagelist);
   444             if (session->i18n_token)
   445                 sqlite3_finalize(session->i18n_token);
   446             if (session->blacklist_add)
   447                 sqlite3_finalize(session->blacklist_add);
   448             if (session->blacklist_delete)
   449                 sqlite3_finalize(session->blacklist_delete);
   450             if (session->blacklist_is_listed)
   451                 sqlite3_finalize(session->blacklist_is_listed);
   452             if (session->blacklist_retrieve)
   453                 sqlite3_finalize(session->blacklist_retrieve);
   454 
   455             if (session->db)
   456                 sqlite3_close_v2(session->db);
   457             if (session->system_db)
   458                 sqlite3_close_v2(session->system_db);
   459         }
   460 
   461         release_transport_system(session, out_last);
   462         release_cryptotech(session, out_last);
   463 
   464         free(session);
   465     }
   466 }
   467 
   468 DYNAMIC_API void config_passive_mode(PEP_SESSION session, bool enable)
   469 {
   470     assert(session);
   471     session->passive_mode = enable;
   472 }
   473 
   474 DYNAMIC_API void config_unencrypted_subject(PEP_SESSION session, bool enable)
   475 {
   476     assert(session);
   477     session->unencrypted_subject = enable;
   478 }
   479 
   480 DYNAMIC_API PEP_STATUS log_event(
   481         PEP_SESSION session,
   482         const char *title,
   483         const char *entity,
   484         const char *description,
   485         const char *comment
   486     )
   487 {
   488     PEP_STATUS status = PEP_STATUS_OK;
   489     int result;
   490 
   491     assert(session);
   492     assert(title);
   493     assert(entity);
   494 
   495     if (!(session && title && entity))
   496         return PEP_ILLEGAL_VALUE;
   497 
   498     sqlite3_reset(session->log);
   499     sqlite3_bind_text(session->log, 1, title, -1, SQLITE_STATIC);
   500     sqlite3_bind_text(session->log, 2, entity, -1, SQLITE_STATIC);
   501     if (description)
   502         sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
   503     else
   504         sqlite3_bind_null(session->log, 3);
   505     if (comment)
   506         sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
   507     else
   508         sqlite3_bind_null(session->log, 4);
   509     do {
   510         result = sqlite3_step(session->log);
   511         assert(result == SQLITE_DONE || result == SQLITE_BUSY);
   512         if (result != SQLITE_DONE && result != SQLITE_BUSY)
   513             status = PEP_UNKNOWN_ERROR;
   514     } while (result == SQLITE_BUSY);
   515     sqlite3_reset(session->log);
   516 
   517     return status;
   518 }
   519 
   520 DYNAMIC_API PEP_STATUS trustword(
   521             PEP_SESSION session, uint16_t value, const char *lang,
   522             char **word, size_t *wsize
   523         )
   524 {
   525     PEP_STATUS status = PEP_STATUS_OK;
   526     int result;
   527 
   528     assert(session);
   529     assert(word);
   530     assert(wsize);
   531 
   532     if (!(session && word && wsize))
   533         return PEP_ILLEGAL_VALUE;
   534 
   535     *word = NULL;
   536     *wsize = 0;
   537 
   538     if (lang == NULL)
   539         lang = "en";
   540 
   541     assert((lang[0] >= 'A' && lang[0] <= 'Z')
   542             || (lang[0] >= 'a' && lang[0] <= 'z'));
   543     assert((lang[1] >= 'A' && lang[1] <= 'Z')
   544             || (lang[1] >= 'a' && lang[1] <= 'z'));
   545     assert(lang[2] == 0);
   546 
   547     sqlite3_reset(session->trustword);
   548     sqlite3_bind_text(session->trustword, 1, lang, -1, SQLITE_STATIC);
   549     sqlite3_bind_int(session->trustword, 2, value);
   550 
   551     result = sqlite3_step(session->trustword);
   552     if (result == SQLITE_ROW) {
   553         *word = strdup((const char *) sqlite3_column_text(session->trustword,
   554                     1));
   555         if (*word)
   556             *wsize = sqlite3_column_bytes(session->trustword, 1);
   557         else
   558             status = PEP_TRUSTWORD_NOT_FOUND;
   559     } else
   560         status = PEP_TRUSTWORD_NOT_FOUND;
   561 
   562     sqlite3_reset(session->trustword);
   563     return status;
   564 }
   565 
   566 DYNAMIC_API PEP_STATUS trustwords(
   567         PEP_SESSION session, const char *fingerprint, const char *lang,
   568         char **words, size_t *wsize, int max_words
   569     )
   570 {
   571     const char *source = fingerprint;
   572     char *buffer;
   573     char *dest;
   574     size_t fsize;
   575     PEP_STATUS _status;
   576 
   577     assert(session);
   578     assert(fingerprint);
   579     assert(words);
   580     assert(wsize);
   581     assert(max_words >= 0);
   582 
   583     if (!(session && fingerprint && words && wsize && max_words >= 0))
   584         return PEP_ILLEGAL_VALUE;
   585 
   586     *words = NULL;
   587     *wsize = 0;
   588 
   589     buffer = calloc(1, MAX_TRUSTWORDS_SPACE);
   590     assert(buffer);
   591     if (buffer == NULL)
   592         return PEP_OUT_OF_MEMORY;
   593     dest = buffer;
   594 
   595     fsize = strlen(fingerprint);
   596 
   597     if (!lang || !lang[0])
   598         lang = "en";
   599 
   600     assert((lang[0] >= 'A' && lang[0] <= 'Z')
   601             || (lang[0] >= 'a' && lang[0] <= 'z'));
   602     assert((lang[1] >= 'A' && lang[1] <= 'Z')
   603             || (lang[1] >= 'a' && lang[1] <= 'z'));
   604     assert(lang[2] == 0);
   605 
   606     int n_words = 0;
   607     while (source < fingerprint + fsize) {
   608         uint16_t value;
   609         char *word;
   610         size_t _wsize;
   611         int j;
   612 
   613         for (value=0, j=0; j < 4 && source < fingerprint + fsize; ) {
   614             if (*source >= 'a' && *source <= 'f')
   615                 value += (*source - 'a' + 10) << (3 - j++) * 4;
   616             else if (*source >= 'A' && *source <= 'F')
   617                 value += (*source - 'A' + 10) << (3 - j++) * 4;
   618             else if (*source >= '0' && *source <= '9')
   619                 value += (*source - '0') << (3 - j++) * 4;
   620             
   621             source++;
   622         }
   623 
   624         _status = trustword(session, value, lang, &word, &_wsize);
   625         if (_status == PEP_OUT_OF_MEMORY) {
   626             free(buffer);
   627             return PEP_OUT_OF_MEMORY;
   628         }
   629         if (word == NULL) {
   630             free(buffer);
   631             return PEP_TRUSTWORD_NOT_FOUND;
   632         }
   633 
   634         if (dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1) {
   635             strncpy(dest, word, _wsize);
   636             free(word);
   637             dest += _wsize;
   638         }
   639         else {
   640             free(word);
   641             break; // buffer full
   642         }
   643 
   644         if (source < fingerprint + fsize
   645                 && dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1)
   646             *dest++ = ' ';
   647 
   648         ++n_words;
   649         if (max_words && n_words >= max_words)
   650             break;
   651     }
   652 
   653     *words = buffer;
   654     *wsize = dest - buffer;
   655     return PEP_STATUS_OK;
   656 }
   657 
   658 pEp_identity *new_identity(
   659         const char *address, const char *fpr, const char *user_id,
   660         const char *username
   661     )
   662 {
   663     pEp_identity *result = calloc(1, sizeof(pEp_identity));
   664     assert(result);
   665     if (result) {
   666         if (address) {
   667             result->address = strdup(address);
   668             assert(result->address);
   669             if (result->address == NULL) {
   670                 free(result);
   671                 return NULL;
   672             }
   673         }
   674         if (fpr) {
   675             result->fpr = strdup(fpr);
   676             assert(result->fpr);
   677             if (result->fpr == NULL) {
   678                 free_identity(result);
   679                 return NULL;
   680             }
   681         }
   682         if (user_id) {
   683             result->user_id = strdup(user_id);
   684             assert(result->user_id);
   685             if (result->user_id == NULL) {
   686                 free_identity(result);
   687                 return NULL;
   688             }
   689         }
   690         if (username) {
   691             result->username = strdup(username);
   692             assert(result->username);
   693             if (result->username == NULL) {
   694                 free_identity(result);
   695                 return NULL;
   696             }
   697         }
   698     }
   699     return result;
   700 }
   701 
   702 pEp_identity *identity_dup(const pEp_identity *src)
   703 {
   704     assert(src);
   705 
   706     pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id, src->username);
   707     assert(dup);
   708     if (dup == NULL)
   709         return NULL;
   710     
   711     dup->comm_type = src->comm_type;
   712     dup->lang[0] = src->lang[0];
   713     dup->lang[1] = src->lang[1];
   714     dup->lang[2] = 0;
   715     dup->me = src->me;
   716 
   717     return dup;
   718 }
   719 
   720 void free_identity(pEp_identity *identity)
   721 {
   722     if (identity) {
   723         free(identity->address);
   724         free(identity->fpr);
   725         free(identity->user_id);
   726         free(identity->username);
   727         free(identity);
   728     }
   729 }
   730 
   731 DYNAMIC_API PEP_STATUS get_identity(
   732         PEP_SESSION session,
   733         const char *address,
   734         const char *user_id,
   735         pEp_identity **identity
   736     )
   737 {
   738     PEP_STATUS status = PEP_STATUS_OK;
   739     static pEp_identity *_identity;
   740     int result;
   741     const char *_lang;
   742 
   743     assert(session);
   744     assert(address);
   745     assert(address[0]);
   746     assert(identity);
   747 
   748     if (!(session && address && address[0] && identity))
   749         return PEP_ILLEGAL_VALUE;
   750 
   751     *identity = NULL;
   752 
   753     sqlite3_reset(session->get_identity);
   754     sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
   755     sqlite3_bind_text(session->get_identity, 2, user_id, -1, SQLITE_STATIC);
   756 
   757     result = sqlite3_step(session->get_identity);
   758     switch (result) {
   759     case SQLITE_ROW:
   760         _identity = new_identity(
   761                 address,
   762                 (const char *) sqlite3_column_text(session->get_identity, 0),
   763                 user_id,
   764                 (const char *) sqlite3_column_text(session->get_identity, 1)
   765                 );
   766         assert(_identity);
   767         if (_identity == NULL)
   768             return PEP_OUT_OF_MEMORY;
   769 
   770         _identity->comm_type = (PEP_comm_type) sqlite3_column_int(session->get_identity, 2);
   771         _lang = (const char *) sqlite3_column_text(session->get_identity, 3);
   772         if (_lang && _lang[0]) {
   773             assert(_lang[0] >= 'a' && _lang[0] <= 'z');
   774             assert(_lang[1] >= 'a' && _lang[1] <= 'z');
   775             assert(_lang[2] == 0);
   776             _identity->lang[0] = _lang[0];
   777             _identity->lang[1] = _lang[1];
   778             _identity->lang[2] = 0;
   779         }
   780         *identity = _identity;
   781         break;
   782     default:
   783         status = PEP_CANNOT_FIND_IDENTITY;
   784         *identity = NULL;
   785     }
   786 
   787     sqlite3_reset(session->get_identity);
   788     return status;
   789 }
   790 
   791 DYNAMIC_API PEP_STATUS set_identity(
   792         PEP_SESSION session, const pEp_identity *identity
   793     )
   794 {
   795     int result;
   796 
   797     assert(session);
   798     assert(identity);
   799     assert(identity->address);
   800     assert(identity->fpr);
   801     assert(identity->user_id);
   802     assert(identity->username);
   803 
   804     if (!(session && identity && identity->address && identity->fpr &&
   805                 identity->user_id && identity->username))
   806         return PEP_ILLEGAL_VALUE;
   807 
   808     bool listed;
   809     PEP_STATUS status = blacklist_is_listed(session, identity->fpr, &listed);
   810     assert(status == PEP_STATUS_OK);
   811     if (status != PEP_STATUS_OK)
   812         return status;
   813 
   814     if (listed)
   815         return PEP_KEY_BLACKLISTED;
   816 
   817     sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
   818 
   819     sqlite3_reset(session->set_person);
   820     sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
   821             SQLITE_STATIC);
   822     sqlite3_bind_text(session->set_person, 2, identity->username, -1,
   823             SQLITE_STATIC);
   824     if (identity->lang[0])
   825         sqlite3_bind_text(session->set_person, 3, identity->lang, 1,
   826                 SQLITE_STATIC);
   827     else
   828         sqlite3_bind_null(session->set_person, 3);
   829     sqlite3_bind_text(session->set_person, 4, identity->fpr, -1,
   830                       SQLITE_STATIC);
   831     result = sqlite3_step(session->set_person);
   832     sqlite3_reset(session->set_person);
   833     if (result != SQLITE_DONE) {
   834         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
   835         return PEP_CANNOT_SET_PERSON;
   836     }
   837 
   838     sqlite3_reset(session->set_pgp_keypair);
   839     sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
   840             SQLITE_STATIC);
   841     result = sqlite3_step(session->set_pgp_keypair);
   842     sqlite3_reset(session->set_pgp_keypair);
   843     if (result != SQLITE_DONE) {
   844         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
   845         return PEP_CANNOT_SET_PGP_KEYPAIR;
   846     }
   847 
   848     sqlite3_reset(session->set_identity);
   849     sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
   850             SQLITE_STATIC);
   851     sqlite3_bind_text(session->set_identity, 2, identity->fpr, -1,
   852             SQLITE_STATIC);
   853     sqlite3_bind_text(session->set_identity, 3, identity->user_id, -1,
   854             SQLITE_STATIC);
   855     result = sqlite3_step(session->set_identity);
   856     sqlite3_reset(session->set_identity);
   857     if (result != SQLITE_DONE) {
   858         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
   859         return PEP_CANNOT_SET_IDENTITY;
   860     }
   861 
   862     sqlite3_reset(session->set_trust);
   863     sqlite3_bind_text(session->set_trust, 1, identity->user_id, -1,
   864             SQLITE_STATIC);
   865     sqlite3_bind_text(session->set_trust, 2, identity->fpr, -1,
   866             SQLITE_STATIC);
   867     sqlite3_bind_int(session->set_trust, 3, identity->comm_type);
   868     result = sqlite3_step(session->set_trust);
   869     sqlite3_reset(session->set_trust);
   870     if (result != SQLITE_DONE) {
   871         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
   872         return PEP_CANNOT_SET_TRUST;
   873     }
   874 
   875     result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
   876     if (result == SQLITE_OK)
   877         return PEP_STATUS_OK;
   878     else
   879         return PEP_COMMIT_FAILED;
   880 }
   881 
   882 DYNAMIC_API PEP_STATUS mark_as_compromized(
   883         PEP_SESSION session,
   884         const char *fpr
   885     )
   886 {
   887     int result;
   888 
   889     assert(session);
   890     assert(fpr && fpr[0]);
   891 
   892     if (!(session && fpr && fpr[0]))
   893         return PEP_ILLEGAL_VALUE;
   894 
   895     sqlite3_reset(session->mark_compromized);
   896     sqlite3_bind_text(session->mark_compromized, 1, fpr, -1,
   897             SQLITE_STATIC);
   898     result = sqlite3_step(session->mark_compromized);
   899     sqlite3_reset(session->mark_compromized);
   900 
   901     if (result != SQLITE_DONE)
   902         return PEP_CANNOT_SET_TRUST;
   903 
   904     return PEP_STATUS_OK;
   905 }
   906 
   907 void pEp_free(void *p)
   908 {
   909     free(p);
   910 }
   911 
   912 DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
   913 {
   914     PEP_STATUS status = PEP_STATUS_OK;
   915     int result;
   916 
   917     assert(session);
   918     assert(identity);
   919     assert(identity->user_id);
   920     assert(identity->user_id[0]);
   921     assert(identity->fpr);
   922     assert(identity->fpr[0]);
   923 
   924     if (!(session && identity && identity->user_id && identity->user_id[0] &&
   925                 identity->fpr && identity->fpr[0]))
   926         return PEP_ILLEGAL_VALUE;
   927 
   928     identity->comm_type = PEP_ct_unknown;
   929 
   930     sqlite3_reset(session->get_trust);
   931     sqlite3_bind_text(session->get_trust, 1, identity->user_id, -1, SQLITE_STATIC);
   932     sqlite3_bind_text(session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
   933 
   934     result = sqlite3_step(session->get_trust);
   935     switch (result) {
   936     case SQLITE_ROW: {
   937         int comm_type = (PEP_comm_type) sqlite3_column_int(session->get_trust, 0);
   938         identity->comm_type = comm_type;
   939         break;
   940     }
   941  
   942     default:
   943         status = PEP_CANNOT_FIND_IDENTITY;
   944     }
   945 
   946     sqlite3_reset(session->get_trust);
   947     return status;
   948 }
   949 
   950 DYNAMIC_API PEP_STATUS least_trust(
   951         PEP_SESSION session,
   952         const char *fpr,
   953         PEP_comm_type *comm_type
   954     )
   955 {
   956     PEP_STATUS status = PEP_STATUS_OK;
   957     int result;
   958 
   959     assert(session);
   960     assert(fpr);
   961     assert(comm_type);
   962 
   963     if (!(session && fpr && comm_type))
   964         return PEP_ILLEGAL_VALUE;
   965 
   966     *comm_type = PEP_ct_unknown;
   967 
   968     sqlite3_reset(session->least_trust);
   969     sqlite3_bind_text(session->least_trust, 1, fpr, -1, SQLITE_STATIC);
   970 
   971     result = sqlite3_step(session->least_trust);
   972     switch (result) {
   973         case SQLITE_ROW: {
   974             int _comm_type = sqlite3_column_int(session->least_trust, 0);
   975             *comm_type = (PEP_comm_type) _comm_type;
   976             break;
   977         }
   978         default:
   979             status = PEP_CANNOT_FIND_IDENTITY;
   980     }
   981 
   982     sqlite3_reset(session->least_trust);
   983     return status;
   984 }
   985 
   986 DYNAMIC_API PEP_STATUS decrypt_and_verify(
   987     PEP_SESSION session, const char *ctext, size_t csize,
   988     char **ptext, size_t *psize, stringlist_t **keylist
   989     )
   990 {
   991     assert(session);
   992     assert(ctext);
   993     assert(csize);
   994     assert(ptext);
   995     assert(psize);
   996     assert(keylist);
   997 
   998     if (!(session && ctext && csize && ptext && psize && keylist && keylist))
   999         return PEP_ILLEGAL_VALUE;
  1000 
  1001     return session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(session, ctext, csize, ptext, psize, keylist);
  1002 }
  1003 
  1004 DYNAMIC_API PEP_STATUS encrypt_and_sign(
  1005     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
  1006     size_t psize, char **ctext, size_t *csize
  1007     )
  1008 {
  1009     assert(session);
  1010     assert(keylist);
  1011     assert(ptext);
  1012     assert(psize);
  1013     assert(ctext);
  1014     assert(csize);
  1015 
  1016     if (!(session && keylist && ptext && psize && ctext && csize))
  1017         return PEP_ILLEGAL_VALUE;
  1018 
  1019     return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session, keylist, ptext, psize, ctext, csize);
  1020 }
  1021 
  1022 DYNAMIC_API PEP_STATUS verify_text(
  1023     PEP_SESSION session, const char *text, size_t size,
  1024     const char *signature, size_t sig_size, stringlist_t **keylist
  1025     )
  1026 {
  1027     assert(session);
  1028     assert(text);
  1029     assert(size);
  1030     assert(signature);
  1031     assert(sig_size);
  1032     assert(keylist);
  1033 
  1034     if (!(session && text && size && signature && sig_size && keylist))
  1035         return PEP_ILLEGAL_VALUE;
  1036 
  1037     return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text, size, signature, sig_size, keylist);
  1038 }
  1039 
  1040 DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
  1041 {
  1042     assert(session);
  1043     assert(fpr);
  1044 
  1045     if (!(session && fpr))
  1046         return PEP_ILLEGAL_VALUE;
  1047 
  1048     return session->cryptotech[PEP_crypt_OpenPGP].delete_keypair(session, fpr);
  1049 }
  1050 
  1051 DYNAMIC_API PEP_STATUS export_key(
  1052         PEP_SESSION session, const char *fpr, char **key_data, size_t *size
  1053     )
  1054 {
  1055     assert(session);
  1056     assert(fpr);
  1057     assert(key_data);
  1058     assert(size);
  1059 
  1060     if (!(session && fpr && key_data && size))
  1061         return PEP_ILLEGAL_VALUE;
  1062 
  1063     return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr, key_data, size);
  1064 }
  1065 
  1066 DYNAMIC_API PEP_STATUS find_keys(
  1067         PEP_SESSION session, const char *pattern, stringlist_t **keylist
  1068     )
  1069 {
  1070     assert(session);
  1071     assert(pattern);
  1072     assert(keylist);
  1073 
  1074     if (!(session && pattern && keylist))
  1075         return PEP_ILLEGAL_VALUE;
  1076 
  1077     return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern, keylist);
  1078 }
  1079 
  1080 DYNAMIC_API PEP_STATUS generate_keypair(
  1081         PEP_SESSION session, pEp_identity *identity
  1082     )
  1083 {
  1084     assert(session);
  1085     assert(identity);
  1086     assert(identity->address);
  1087     assert(identity->fpr == NULL || identity->fpr[0] == 0);
  1088     assert(identity->username);
  1089 
  1090     if (!(session && identity && identity->address &&
  1091         (identity->fpr == NULL || identity->fpr[0] == 0) && identity->username))
  1092         return PEP_ILLEGAL_VALUE;
  1093 
  1094     return session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session, identity);
  1095 }
  1096 
  1097 DYNAMIC_API PEP_STATUS get_key_rating(
  1098         PEP_SESSION session,
  1099         const char *fpr,
  1100         PEP_comm_type *comm_type
  1101     )
  1102 {
  1103     assert(session);
  1104     assert(fpr);
  1105     assert(comm_type);
  1106 
  1107     if (!(session && fpr && comm_type))
  1108         return PEP_ILLEGAL_VALUE;
  1109 
  1110     return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr, comm_type);
  1111 }
  1112 
  1113 DYNAMIC_API PEP_STATUS import_key(PEP_SESSION session, const char *key_data, size_t size)
  1114 {
  1115     assert(session);
  1116     assert(key_data);
  1117 
  1118     if (!(session && key_data))
  1119         return PEP_ILLEGAL_VALUE;
  1120 
  1121     return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data, size);
  1122 }
  1123 
  1124 DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
  1125 {
  1126     assert(session);
  1127     assert(pattern);
  1128 
  1129     if (!(session && pattern))
  1130         return PEP_ILLEGAL_VALUE;
  1131 
  1132     return session->cryptotech[PEP_crypt_OpenPGP].recv_key(session, pattern);
  1133 }
  1134 
  1135 DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
  1136 {
  1137     assert(session);
  1138     assert(pattern);
  1139 
  1140     if (!(session && pattern))
  1141         return PEP_ILLEGAL_VALUE;
  1142 
  1143     return session->cryptotech[PEP_crypt_OpenPGP].send_key(session, pattern);
  1144 }
  1145 
  1146 DYNAMIC_API PEP_STATUS renew_key(
  1147         PEP_SESSION session,
  1148         const char *fpr,
  1149         const timestamp *ts
  1150     )
  1151 {
  1152     assert(session);
  1153     assert(fpr);
  1154 
  1155     if (!(session && fpr))
  1156         return PEP_ILLEGAL_VALUE;
  1157 
  1158     return session->cryptotech[PEP_crypt_OpenPGP].renew_key(session, fpr, ts);
  1159 }
  1160 
  1161 DYNAMIC_API PEP_STATUS revoke_key(
  1162         PEP_SESSION session,
  1163         const char *fpr,
  1164         const char *reason
  1165     )
  1166 {
  1167     assert(session);
  1168     assert(fpr);
  1169 
  1170     if (!(session && fpr))
  1171         return PEP_ILLEGAL_VALUE;
  1172 
  1173     return session->cryptotech[PEP_crypt_OpenPGP].revoke_key(session, fpr,
  1174             reason);
  1175 }
  1176 
  1177 DYNAMIC_API PEP_STATUS key_expired(
  1178         PEP_SESSION session,
  1179         const char *fpr,
  1180         bool *expired
  1181     )
  1182 {
  1183     assert(session);
  1184     assert(fpr);
  1185     assert(expired);
  1186 
  1187     if (!(session && fpr && expired))
  1188         return PEP_ILLEGAL_VALUE;
  1189 
  1190     return session->cryptotech[PEP_crypt_OpenPGP].key_expired(session, fpr,
  1191             expired);
  1192 }
  1193 
  1194 static void _clean_log_value(char *text)
  1195 {
  1196     if (text) {
  1197         for (char *c = text; *c; c++) {
  1198             if (*c < 32)
  1199                 *c = 32;
  1200             else if (*c == '"')
  1201                 *c = '\'';
  1202         }
  1203     }
  1204 }
  1205 
  1206 static char *_concat_string(char *str1, const char *str2, char delim)
  1207 {
  1208     str2 = str2 ? str2 : "";
  1209     size_t len1 = str1 ? strlen(str1) : 0;
  1210     size_t len2 = strlen(str2);
  1211     size_t len = len1 + len2 + 3;
  1212     char * result = realloc(str1, len + 1);
  1213 
  1214     if (result) {
  1215         result[len1] = '"';
  1216         strcpy(result + len1 + 1, str2);
  1217         _clean_log_value(result + len1 + 1);
  1218         result[len - 2] = '"';
  1219         result[len - 1] = delim;
  1220         result[len] = 0;
  1221     }
  1222     else {
  1223         free(str1);
  1224     }
  1225 
  1226     return result;
  1227 }
  1228 
  1229 DYNAMIC_API PEP_STATUS get_crashdump_log(
  1230         PEP_SESSION session,
  1231         int maxlines,
  1232         char **logdata
  1233     )
  1234 {
  1235     PEP_STATUS status = PEP_STATUS_OK;
  1236     char *_logdata= NULL;
  1237 
  1238     assert(session);
  1239     assert(maxlines >= 0 && maxlines <= CRASHDUMP_MAX_LINES);
  1240     assert(logdata);
  1241 
  1242     if (!(session && logdata && maxlines >= 0 && maxlines <=
  1243             CRASHDUMP_MAX_LINES))
  1244         return PEP_ILLEGAL_VALUE;
  1245 
  1246     *logdata = NULL;
  1247 
  1248     int limit = maxlines ? maxlines : CRASHDUMP_DEFAULT_LINES;
  1249     const char *timestamp = NULL;
  1250     const char *title = NULL;
  1251     const char *entity = NULL;
  1252     const char *desc = NULL;
  1253     const char *comment = NULL;
  1254 
  1255     sqlite3_reset(session->crashdump);
  1256     sqlite3_bind_int(session->crashdump, 1, limit);
  1257 
  1258     int result;
  1259 
  1260     do {
  1261         result = sqlite3_step(session->crashdump);
  1262         switch (result) {
  1263         case SQLITE_ROW:
  1264             timestamp = (const char *) sqlite3_column_text(session->crashdump, 0);
  1265             title   = (const char *) sqlite3_column_text(session->crashdump, 1);
  1266             entity  = (const char *) sqlite3_column_text(session->crashdump, 2);
  1267             desc    = (const char *) sqlite3_column_text(session->crashdump, 3);
  1268             comment = (const char *) sqlite3_column_text(session->crashdump, 4);
  1269 
  1270             _logdata = _concat_string(_logdata, timestamp, ',');
  1271             if (_logdata == NULL)
  1272                 goto enomem;
  1273 
  1274             _logdata = _concat_string(_logdata, title, ',');
  1275             if (_logdata == NULL)
  1276                 goto enomem;
  1277 
  1278             _logdata = _concat_string(_logdata, entity, ',');
  1279             if (_logdata == NULL)
  1280                 goto enomem;
  1281 
  1282             _logdata = _concat_string(_logdata, desc, ',');
  1283             if (_logdata == NULL)
  1284                 goto enomem;
  1285 
  1286             _logdata = _concat_string(_logdata, comment, '\n');
  1287             if (_logdata == NULL)
  1288                 goto enomem;
  1289 
  1290             break;
  1291 
  1292         case SQLITE_DONE:
  1293             break;
  1294 
  1295         default:
  1296             status = PEP_UNKNOWN_ERROR;
  1297             result = SQLITE_DONE;
  1298         }
  1299     } while (result != SQLITE_DONE);
  1300 
  1301     sqlite3_reset(session->crashdump);
  1302     if (status == PEP_STATUS_OK)
  1303         *logdata = _logdata;
  1304 
  1305     goto the_end;
  1306 
  1307 enomem:
  1308     status = PEP_OUT_OF_MEMORY;
  1309 
  1310 the_end:
  1311     return status;
  1312 }
  1313 
  1314 DYNAMIC_API PEP_STATUS get_languagelist(
  1315         PEP_SESSION session,
  1316         char **languages
  1317     )
  1318 {
  1319     PEP_STATUS status = PEP_STATUS_OK;
  1320     char *_languages= NULL;
  1321 
  1322     assert(session);
  1323     assert(languages);
  1324 
  1325     if (!(session && languages))
  1326         return PEP_ILLEGAL_VALUE;
  1327 
  1328     *languages = NULL;
  1329 
  1330     const char *lang = NULL;
  1331     const char *name = NULL;
  1332     const char *phrase = NULL;
  1333 
  1334     sqlite3_reset(session->languagelist);
  1335 
  1336     int result;
  1337 
  1338     do {
  1339         result = sqlite3_step(session->languagelist);
  1340         switch (result) {
  1341         case SQLITE_ROW:
  1342             lang = (const char *) sqlite3_column_text(session->languagelist, 0);
  1343             name = (const char *) sqlite3_column_text(session->languagelist, 1);
  1344             phrase = (const char *) sqlite3_column_text(session->languagelist, 2);
  1345 
  1346             _languages = _concat_string(_languages, lang, ',');
  1347             if (_languages == NULL)
  1348                 goto enomem;
  1349 
  1350             _languages = _concat_string(_languages, name, ',');
  1351             if (_languages == NULL)
  1352                 goto enomem;
  1353 
  1354             _languages = _concat_string(_languages, phrase, '\n');
  1355             if (_languages == NULL)
  1356                 goto enomem;
  1357 
  1358             break;
  1359 
  1360         case SQLITE_DONE:
  1361             break;
  1362 
  1363         default:
  1364             status = PEP_UNKNOWN_ERROR;
  1365             result = SQLITE_DONE;
  1366         }
  1367     } while (result != SQLITE_DONE);
  1368 
  1369     sqlite3_reset(session->languagelist);
  1370     if (status == PEP_STATUS_OK)
  1371         *languages = _languages;
  1372 
  1373     goto the_end;
  1374 
  1375 enomem:
  1376     status = PEP_OUT_OF_MEMORY;
  1377 
  1378 the_end:
  1379     return status;
  1380 }
  1381 
  1382 DYNAMIC_API PEP_STATUS get_phrase(
  1383         PEP_SESSION session,
  1384         const char *lang,
  1385         int phrase_id,
  1386         char **phrase
  1387     )
  1388 {
  1389     PEP_STATUS status = PEP_STATUS_OK;
  1390 
  1391     assert(session && lang && lang[0] && lang[1] && lang[2] == 0 && phrase);
  1392     if (!(session && lang && lang[0] && lang[1] && lang[2] == 0 && phrase))
  1393         return PEP_ILLEGAL_VALUE;
  1394 
  1395     *phrase = NULL;
  1396 
  1397     sqlite3_reset(session->i18n_token);
  1398     sqlite3_bind_text(session->i18n_token, 1, lang, -1, SQLITE_STATIC);
  1399     sqlite3_bind_int(session->i18n_token, 2, phrase_id);
  1400 
  1401     const char *_phrase = NULL;
  1402     int result;
  1403 
  1404     result = sqlite3_step(session->i18n_token);
  1405     switch (result) {
  1406     case SQLITE_ROW:
  1407         _phrase = (const char *) sqlite3_column_text(session->i18n_token, 0);
  1408         break;
  1409 
  1410     case SQLITE_DONE:
  1411         status = PEP_PHRASE_NOT_FOUND;
  1412         break;
  1413 
  1414     default:
  1415         status = PEP_UNKNOWN_ERROR;
  1416     }
  1417 
  1418     if (status == PEP_STATUS_OK) {
  1419         *phrase = strdup(_phrase);
  1420         if (*phrase == NULL)
  1421             goto enomem;
  1422     }
  1423 
  1424     sqlite3_reset(session->i18n_token);
  1425     goto the_end;
  1426 
  1427 enomem:
  1428     status = PEP_OUT_OF_MEMORY;
  1429 
  1430 the_end:
  1431     return status;
  1432 }
  1433 
  1434 DYNAMIC_API PEP_STATUS sequence_value(
  1435         PEP_SESSION session,
  1436         const char *name,
  1437         int64_t *value
  1438     )
  1439 {
  1440     PEP_STATUS status = PEP_STATUS_OK;
  1441     int result;
  1442 
  1443     assert(session);
  1444     assert(name);
  1445     assert(value);
  1446 
  1447     if (!(session && name && value))
  1448         return PEP_ILLEGAL_VALUE;
  1449 
  1450     *value = 0;
  1451 
  1452     sqlite3_reset(session->sequence_value1);
  1453     sqlite3_bind_text(session->sequence_value1, 1, name, -1, SQLITE_STATIC);
  1454     result = sqlite3_step(session->sequence_value1);
  1455     assert(result == SQLITE_DONE);
  1456     sqlite3_reset(session->sequence_value1);
  1457     if (result != SQLITE_DONE) {
  1458         status = PEP_UNKNOWN_ERROR;
  1459     }
  1460     else {
  1461         sqlite3_reset(session->sequence_value2);
  1462         sqlite3_bind_text(session->sequence_value2, 1, name, -1, SQLITE_STATIC);
  1463         result = sqlite3_step(session->sequence_value2);
  1464         switch (result) {
  1465             case SQLITE_ROW: {
  1466                 int64_t _value = (int64_t)
  1467                         sqlite3_column_int64(session->sequence_value2, 0);
  1468                 *value = _value;
  1469                 break;
  1470             }
  1471             default:
  1472                 status = PEP_UNKNOWN_ERROR;
  1473         }
  1474         sqlite3_reset(session->sequence_value2);
  1475     }
  1476     return status;
  1477 }
  1478 
  1479 DYNAMIC_API PEP_STATUS reset_peptest_hack(PEP_SESSION session)
  1480 {
  1481     assert(session);
  1482 
  1483     if (!session)
  1484         return PEP_ILLEGAL_VALUE;
  1485 
  1486     int int_result = sqlite3_exec(
  1487         session->db,
  1488         "delete from identity where address like '%@peptest.ch' ;",
  1489         NULL,
  1490         NULL,
  1491         NULL
  1492     );
  1493     assert(int_result == SQLITE_OK);
  1494 
  1495     return PEP_STATUS_OK;
  1496 }
  1497