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