src/pEpEngine.c
author Edouard Tisserant <edouard@pep-project.org>
Wed, 21 Dec 2016 10:47:27 +0100
changeset 1508 ab010a3b7894
parent 1507 cee84fad7f33
child 1513 e7f7e42385b5
permissions -rw-r--r--
ENGINE-137 make update_identity question stored fpr if there may be a more trustworthy key associated with that user_id
     1 #include "pEp_internal.h"
     2 #include "dynamic_api.h"
     3 #include "cryptotech.h"
     4 #include "transport.h"
     5 #include "blacklist.h"
     6 #include "sync_fsm.h"
     7 
     8 static int init_count = -1;
     9 
    10 static int user_version(void *_version, int count, char **text, char **name)
    11 {
    12     assert(_version);
    13     assert(count == 1);
    14     assert(text && text[0]);
    15     if (!(_version && count == 1 && text && text[0]))
    16         return -1;
    17 
    18     int *version = (int *) _version;
    19     *version = atoi(text[0]);
    20     return 0;
    21 }
    22 
    23 DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
    24 {
    25     PEP_STATUS status = PEP_STATUS_OK;
    26     int int_result;
    27     static const char *sql_log;
    28     static const char *sql_trustword;
    29     static const char *sql_get_identity;
    30     static const char *sql_set_person;
    31     static const char *sql_set_device_group;
    32     static const char *sql_get_device_group;
    33     static const char *sql_set_pgp_keypair;
    34     static const char *sql_set_identity;
    35     static const char *sql_set_identity_flags;
    36     static const char *sql_unset_identity_flags;
    37     static const char *sql_set_trust;
    38     static const char *sql_get_trust;
    39     static const char *sql_greater_trust_keys;
    40     static const char *sql_least_trust;
    41     static const char *sql_mark_as_compromized;
    42     static const char *sql_crashdump;
    43     static const char *sql_languagelist;
    44     static const char *sql_i18n_token;
    45 
    46     // blacklist
    47     static const char *sql_blacklist_add;
    48     static const char *sql_blacklist_delete;
    49     static const char *sql_blacklist_is_listed;
    50     static const char *sql_blacklist_retrieve;
    51     
    52     // Own keys
    53     static const char *sql_own_key_is_listed;
    54     static const char *sql_own_identities_retrieve;
    55     static const char *sql_own_keys_retrieve;
    56     static const char *sql_set_own_key;
    57 
    58     // Sequence
    59     static const char *sql_sequence_value1;
    60     static const char *sql_sequence_value2;
    61     static const char *sql_sequence_value3;
    62 
    63     // Revocation tracking
    64     static const char *sql_set_revoked;
    65     static const char *sql_get_revoked;
    66     
    67     bool in_first = false;
    68 
    69     assert(sqlite3_threadsafe());
    70     if (!sqlite3_threadsafe())
    71         return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
    72 
    73     // a little race condition - but still a race condition
    74     // mitigated by calling caveat (see documentation)
    75 
    76     ++init_count;
    77     if (init_count == 0)
    78         in_first = true;
    79 
    80     assert(session);
    81     if (session == NULL)
    82         return PEP_ILLEGAL_VALUE;
    83 
    84     *session = NULL;
    85 
    86     pEpSession *_session = calloc(1, sizeof(pEpSession));
    87     assert(_session);
    88     if (_session == NULL)
    89         goto enomem;
    90 
    91     _session->version = PEP_ENGINE_VERSION;
    92 
    93     assert(LOCAL_DB);
    94     if (LOCAL_DB == NULL) {
    95         status = PEP_INIT_CANNOT_OPEN_DB;
    96         goto pep_error;
    97     }
    98 
    99     int_result = sqlite3_open_v2(
   100             LOCAL_DB,
   101             &_session->db,
   102             SQLITE_OPEN_READWRITE
   103                 | SQLITE_OPEN_CREATE
   104                 | SQLITE_OPEN_FULLMUTEX
   105                 | SQLITE_OPEN_PRIVATECACHE,
   106             NULL 
   107         );
   108 
   109     if (int_result != SQLITE_OK) {
   110         status = PEP_INIT_CANNOT_OPEN_DB;
   111         goto pep_error;
   112     }
   113 
   114     sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME);
   115 
   116     assert(SYSTEM_DB);
   117     if (SYSTEM_DB == NULL) {
   118         status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
   119         goto pep_error;
   120     }
   121 
   122     int_result = sqlite3_open_v2(
   123             SYSTEM_DB, &_session->system_db,
   124             SQLITE_OPEN_READONLY
   125                 | SQLITE_OPEN_FULLMUTEX
   126                 | SQLITE_OPEN_SHAREDCACHE,
   127             NULL
   128         );
   129 
   130     if (int_result != SQLITE_OK) {
   131         status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
   132         goto pep_error;
   133     }
   134 
   135     sqlite3_busy_timeout(_session->system_db, 1000);
   136 
   137 // increment this when patching DDL
   138 #define _DDL_USER_VERSION "5"
   139 
   140     if (in_first) {
   141 
   142         int_result = sqlite3_exec(
   143             _session->db,
   144                 "create table if not exists version_info (\n"
   145                 "   id integer primary key,\n"
   146                 "   timestamp integer default (datetime('now')),\n"
   147                 "   version text,\n"
   148                 "   comment text\n"
   149                 ");\n",
   150                 NULL,
   151                 NULL,
   152                 NULL
   153         );
   154         int_result = sqlite3_exec(
   155             _session->db,
   156                 "PRAGMA application_id = 0x23423423;\n"
   157                 "create table if not exists log (\n"
   158                 "   timestamp integer default (datetime('now')),\n"
   159                 "   title text not null,\n"
   160                 "   entity text not null,\n"
   161                 "   description text,\n"
   162                 "   comment text\n"
   163                 ");\n"
   164                 "create index if not exists log_timestamp on log (\n"
   165                 "   timestamp\n"
   166                 ");\n"
   167                 "create table if not exists pgp_keypair (\n"
   168                 "   fpr text primary key,\n"
   169                 "   created integer,\n"
   170                 "   expires integer,\n"
   171                 "   comment text,\n"
   172                 "   flags integer default 0\n"
   173                 ");\n"
   174                 "create index if not exists pgp_keypair_expires on pgp_keypair (\n"
   175                 "   expires\n"
   176                 ");\n"
   177                 "create table if not exists person (\n"
   178                 "   id text primary key,\n"
   179                 "   username text not null,\n"
   180                 "   main_key_id text\n"
   181                 "       references pgp_keypair (fpr)\n"
   182                 "       on delete set null,\n"
   183                 "   lang text,\n"
   184                 "   comment text,\n"
   185                 "   device_group text\n"
   186                 ");\n"
   187                 "create table if not exists identity (\n"
   188                 "   address text,\n"
   189                 "   user_id text\n"
   190                 "       references person (id)\n"
   191                 "       on delete cascade,\n"
   192                 "   main_key_id text\n"
   193                 "       references pgp_keypair (fpr)\n"
   194                 "       on delete set null,\n"
   195                 "   comment text,\n"
   196                 "   flags integer default 0,"
   197                 "   primary key (address, user_id)\n"
   198                 ");\n"
   199                 "create table if not exists trust (\n"
   200                 "   user_id text not null\n"
   201                 "       references person (id)\n"
   202                 "       on delete cascade,\n"
   203                 "   pgp_keypair_fpr text not null\n"
   204                 "       references pgp_keypair (fpr)\n"
   205                 "       on delete cascade,\n"
   206                 "   comm_type integer not null,\n"
   207                 "   comment text,\n"
   208                 "   primary key (user_id, pgp_keypair_fpr)\n"
   209                 ");\n"
   210                 // blacklist
   211                 "create table if not exists blacklist_keys (\n"
   212                 "   fpr text primary key\n"
   213                 ");\n"
   214                 // sequences
   215                 "create table if not exists sequences(\n"
   216                 "   name text primary key,\n"
   217                 "   value integer default 0,\n"
   218                 "   own integer default 0\n"
   219                 ");\n"
   220                 "create table if not exists revoked_keys (\n"
   221                 "   revoked_fpr text primary key,\n"
   222                 "   replacement_fpr text not null\n"
   223                 "       references pgp_keypair (fpr)\n"
   224                 "       on delete cascade,\n"
   225                 "   revocation_date integer\n"
   226                 ");\n"
   227                 "create table if not exists own_keys (\n"
   228                 "   address text,\n"
   229                 "   user_id text,\n"
   230                 "   fpr text not null\n"
   231                 "       references pgp_keypair (fpr)\n"
   232                 "       on delete cascade,\n"
   233                 "   foreign key (address, user_id)\n"
   234                 "       references identity\n"
   235                 "       on delete cascade,\n"
   236                 "   check (user_id = '" PEP_OWN_USERID "')\n"
   237                 "   primary key (address, fpr)\n"
   238                 ");\n" 
   239                 ,
   240             NULL,
   241             NULL,
   242             NULL
   243         );
   244         assert(int_result == SQLITE_OK);
   245 
   246         int version;
   247         int_result = sqlite3_exec(
   248             _session->db,
   249             "pragma user_version;",
   250             user_version,
   251             &version,
   252             NULL
   253         );
   254         assert(int_result == SQLITE_OK);
   255 
   256         if (version < 1) {
   257             int_result = sqlite3_exec(
   258                 _session->db,
   259                 "alter table identity\n"
   260                 "   add column flags integer default 0;\n",
   261                 NULL,
   262                 NULL,
   263                 NULL
   264             );
   265         }
   266 
   267         if (version < 2) {
   268             int_result = sqlite3_exec(
   269                 _session->db,
   270                 "alter table pgp_keypair\n"
   271                 "   add column flags integer default 0;\n"
   272                 "alter table person\n"
   273                 "   add column device_group text;\n",
   274                 NULL,
   275                 NULL,
   276                 NULL
   277             );
   278         }
   279 
   280         if (version < 3) {
   281             int_result = sqlite3_exec(
   282                 _session->db,
   283                 "alter table sequences\n"
   284                 "   add column own integer default 0;\n",
   285                 NULL,
   286                 NULL,
   287                 NULL
   288             );
   289         }
   290 
   291         if (version < 5) {
   292             int_result = sqlite3_exec(
   293                 _session->db,
   294                 "delete from pgp_keypair where fpr = '';",
   295                 NULL,
   296                 NULL,
   297                 NULL
   298             );
   299             int_result = sqlite3_exec(
   300                 _session->db,
   301                 "delete from trust where pgp_keypair_fpr = '';",
   302                 NULL,
   303                 NULL,
   304                 NULL
   305             );
   306         }
   307 
   308         if (version < atoi(_DDL_USER_VERSION)) {
   309             int_result = sqlite3_exec(
   310                 _session->db,
   311                 "pragma user_version = "_DDL_USER_VERSION";\n"
   312                 "insert or replace into version_info (id, version)"
   313                     "values (1, '" PEP_ENGINE_VERSION "');",
   314                 NULL,
   315                 NULL,
   316                 NULL
   317             );
   318             assert(int_result == SQLITE_OK);
   319         }
   320 
   321         sql_log = "insert into log (title, entity, description, comment)"
   322                   "values (?1, ?2, ?3, ?4);";
   323 
   324         sql_get_identity =  "select fpr, username, comm_type, lang,"
   325                             "   identity.flags | pgp_keypair.flags"
   326                             "   from identity"
   327                             "   join person on id = identity.user_id"
   328                             "   join pgp_keypair on fpr = identity.main_key_id"
   329                             "   join trust on id = trust.user_id"
   330                             "       and pgp_keypair_fpr = identity.main_key_id"
   331                             "   where address = ?1 and identity.user_id = ?2;";
   332 
   333         sql_trustword = "select id, word from wordlist where lang = lower(?1) "
   334                        "and id = ?2 ;";
   335 
   336         // Set person, but if already exist, only update.
   337         // if main_key_id already set, don't touch.
   338         sql_set_person = "insert or replace into person (id, username, lang, main_key_id, device_group)"
   339                          "  values (?1, ?2, ?3,"
   340                          "    (select coalesce((select main_key_id from person "
   341                          "      where id = ?1), upper(replace(?4,' ','')))),"
   342                          "    (select device_group from person where id = ?1)) ;";
   343 
   344         sql_set_device_group = "update person set device_group = ?1 "
   345                                "where id = '" PEP_OWN_USERID "';";
   346 
   347         sql_get_device_group = "select device_group from person "
   348                                "where id = '" PEP_OWN_USERID "';";
   349 
   350         sql_set_pgp_keypair = "insert or replace into pgp_keypair (fpr) "
   351                               "values (upper(replace(?1,' ',''))) ;";
   352 
   353         sql_set_identity = "insert or replace into identity ("
   354                            " address, main_key_id, "
   355                            " user_id, flags"
   356                            ") values ("
   357                            " ?1,"
   358                            " upper(replace(?2,' ','')),"
   359                            " ?3,"
   360                            // " (select"
   361                            // "   coalesce("
   362                            // "    (select flags from identity"
   363                            // "     where address = ?1 and"
   364                            // "           user_id = ?3),"
   365                            // "    0)"
   366                            // " ) | (?4 & 255)"
   367                            /* set_identity ignores previous flags, and doesn't filter machine flags */
   368                            " ?4"
   369                            ");";
   370         
   371         sql_set_identity_flags = "update identity set flags = "
   372                                  "    ((?1 & 255) | (select flags from identity"
   373                                  "                   where address = ?2 and user_id = ?3)) "
   374                                  "where address = ?2 and user_id = ?3 ;";
   375 
   376         sql_unset_identity_flags = 
   377                                  "update identity set flags = "
   378                                  "    ( ~(?1 & 255) & (select flags from identity"
   379                                  "                   where address = ?2 and user_id = ?3)) "
   380                                  "where address = ?2 and user_id = ?3 ;";
   381 
   382         sql_set_trust = "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type) "
   383                         "values (?1, upper(replace(?2,' ','')), ?3) ;";
   384 
   385         sql_get_trust = "select comm_type from trust where user_id = ?1 "
   386                         "and pgp_keypair_fpr = upper(replace(?2,' ','')) ;";
   387 
   388         sql_greater_trust_keys = "select pgp_keypair_fpr from trust"
   389                                  "  where user_id = ?1"
   390                                  "    and comm_type > ?2"
   391                                  "    and (select count(*) from identity"
   392                                  "           where user_id = identity.user_id"
   393                                  "             and pgp_keypair_fpr = identity.main_key_id"
   394                                  "        ) = 0;";
   395 
   396         sql_least_trust = "select min(comm_type) from trust where pgp_keypair_fpr = upper(replace(?1,' ','')) ;";
   397 
   398         sql_mark_as_compromized = "update trust not indexed set comm_type = 15"
   399                                   " where pgp_keypair_fpr = upper(replace(?1,' ','')) ;";
   400 
   401         sql_crashdump = "select timestamp, title, entity, description, comment"
   402                         " from log order by timestamp desc limit ?1 ;";
   403 
   404         sql_languagelist = "select i18n_language.lang, name, phrase from i18n_language join i18n_token using (lang) where i18n_token.id = 1000;" ;
   405 
   406         sql_i18n_token = "select phrase from i18n_token where lang = lower(?1) and id = ?2 ;";
   407 
   408         // blacklist
   409 
   410         sql_blacklist_add = "insert or replace into blacklist_keys (fpr) values (upper(replace(?1,' ',''))) ;"
   411                             "delete from identity where main_key_id = upper(replace(?1,' ','')) ;"
   412                             "delete from pgp_keypair where fpr = upper(replace(?1,' ','')) ;";
   413 
   414         sql_blacklist_delete = "delete from blacklist_keys where fpr = upper(replace(?1,' ','')) ;";
   415 
   416         sql_blacklist_is_listed = "select count(*) from blacklist_keys where fpr = upper(replace(?1,' ','')) ;";
   417 
   418         sql_blacklist_retrieve = "select * from blacklist_keys ;";
   419                 
   420         // Own keys
   421         
   422         sql_own_key_is_listed = "select count(*) from ("
   423                                 " select main_key_id from person "
   424                                 "   where main_key_id = upper(replace(?1,' ',''))"
   425                                 "    and id = '" PEP_OWN_USERID "' "
   426                                 " union "
   427                                 "  select main_key_id from identity "
   428                                 "   where main_key_id = upper(replace(?1,' ',''))"
   429                                 "    and user_id = '" PEP_OWN_USERID "' );";
   430 
   431         sql_own_identities_retrieve =  
   432                             "select address, fpr, username, "
   433                             "   lang, identity.flags | pgp_keypair.flags"
   434                             "   from identity"
   435                             "   join person on id = identity.user_id"
   436                             "   join pgp_keypair on fpr = identity.main_key_id"
   437                             "   join trust on id = trust.user_id"
   438                             "       and pgp_keypair_fpr = identity.main_key_id"
   439                             "   where identity.user_id = '" PEP_OWN_USERID "'"
   440                             "       and (identity.flags & ?1) = 0;";
   441         
   442         sql_own_keys_retrieve =  
   443                             "select fpr from own_keys"
   444                             "   natural join identity"
   445                             "   where (identity.flags & ?1) = 0;";
   446 
   447         sql_set_own_key = "insert or replace into own_keys (address, user_id, fpr)"
   448                           " values (?1, '" PEP_OWN_USERID "', upper(replace(?2,' ','')));";
   449 
   450         sql_sequence_value1 = "insert or replace into sequences (name, value, own) "
   451                               "values (?1, "
   452                               "(select coalesce((select value + 1 from sequences "
   453                               "where name = ?1), 1 )), ?2) ; ";
   454         sql_sequence_value2 = "select value, own from sequences where name = ?1 ;";
   455         sql_sequence_value3 = "update sequences set value = ?2, own = ?3 where name = ?1 ;";
   456         
   457         sql_set_revoked =     "insert or replace into revoked_keys ("
   458                               "    revoked_fpr, replacement_fpr, revocation_date) "
   459                               "values (upper(replace(?1,' ','')),"
   460                               "        upper(replace(?2,' ','')),"
   461                               "        ?3) ;";
   462         
   463         sql_get_revoked =     "select revoked_fpr, revocation_date from revoked_keys"
   464                               "    where replacement_fpr = upper(replace(?1,' ','')) ;";
   465     }
   466 
   467     int_result = sqlite3_prepare_v2(_session->db, sql_log,
   468             (int)strlen(sql_log), &_session->log, NULL);
   469     assert(int_result == SQLITE_OK);
   470 
   471     int_result = sqlite3_prepare_v2(_session->system_db, sql_trustword,
   472             (int)strlen(sql_trustword), &_session->trustword, NULL);
   473     assert(int_result == SQLITE_OK);
   474 
   475     int_result = sqlite3_prepare_v2(_session->db, sql_get_identity,
   476             (int)strlen(sql_get_identity), &_session->get_identity, NULL);
   477     assert(int_result == SQLITE_OK);
   478 
   479     int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
   480             (int)strlen(sql_set_person), &_session->set_person, NULL);
   481     assert(int_result == SQLITE_OK);
   482 
   483     int_result = sqlite3_prepare_v2(_session->db, sql_set_device_group,
   484             (int)strlen(sql_set_device_group), &_session->set_device_group, NULL);
   485     assert(int_result == SQLITE_OK);
   486 
   487     int_result = sqlite3_prepare_v2(_session->db, sql_get_device_group,
   488             (int)strlen(sql_get_device_group), &_session->get_device_group, NULL);
   489     assert(int_result == SQLITE_OK);
   490 
   491     int_result = sqlite3_prepare_v2(_session->db, sql_set_pgp_keypair,
   492             (int)strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair,
   493             NULL);
   494     assert(int_result == SQLITE_OK);
   495 
   496     int_result = sqlite3_prepare_v2(_session->db, sql_set_identity,
   497             (int)strlen(sql_set_identity), &_session->set_identity, NULL);
   498     assert(int_result == SQLITE_OK);
   499 
   500     int_result = sqlite3_prepare_v2(_session->db, sql_set_identity_flags,
   501             (int)strlen(sql_set_identity_flags), &_session->set_identity_flags,
   502             NULL);
   503     assert(int_result == SQLITE_OK);
   504 
   505     int_result = sqlite3_prepare_v2(_session->db, sql_unset_identity_flags,
   506             (int)strlen(sql_unset_identity_flags), &_session->unset_identity_flags,
   507             NULL);
   508     assert(int_result == SQLITE_OK);
   509 
   510     int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
   511             (int)strlen(sql_set_trust), &_session->set_trust, NULL);
   512     assert(int_result == SQLITE_OK);
   513 
   514     int_result = sqlite3_prepare_v2(_session->db, sql_get_trust,
   515             (int)strlen(sql_get_trust), &_session->get_trust, NULL);
   516     assert(int_result == SQLITE_OK);
   517 
   518     int_result = sqlite3_prepare_v2(_session->db, sql_greater_trust_keys,
   519             (int)strlen(sql_greater_trust_keys), &_session->greater_trust_keys,
   520             NULL);
   521     assert(int_result == SQLITE_OK);
   522     
   523     int_result = sqlite3_prepare_v2(_session->db, sql_least_trust,
   524             (int)strlen(sql_least_trust), &_session->least_trust, NULL);
   525     assert(int_result == SQLITE_OK);
   526 
   527     int_result = sqlite3_prepare_v2(_session->db, sql_mark_as_compromized,
   528             (int)strlen(sql_mark_as_compromized), &_session->mark_compromized,
   529             NULL);
   530     assert(int_result == SQLITE_OK);
   531 
   532     int_result = sqlite3_prepare_v2(_session->db, sql_crashdump,
   533             (int)strlen(sql_crashdump), &_session->crashdump, NULL);
   534     assert(int_result == SQLITE_OK);
   535 
   536     int_result = sqlite3_prepare_v2(_session->system_db, sql_languagelist,
   537             (int)strlen(sql_languagelist), &_session->languagelist, NULL);
   538     assert(int_result == SQLITE_OK);
   539 
   540     int_result = sqlite3_prepare_v2(_session->system_db, sql_i18n_token,
   541             (int)strlen(sql_i18n_token), &_session->i18n_token, NULL);
   542     assert(int_result == SQLITE_OK);
   543 
   544     // blacklist
   545 
   546     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_add,
   547             (int)strlen(sql_blacklist_add), &_session->blacklist_add, NULL);
   548     assert(int_result == SQLITE_OK);
   549 
   550     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_delete,
   551             (int)strlen(sql_blacklist_delete), &_session->blacklist_delete,
   552             NULL);
   553     assert(int_result == SQLITE_OK);
   554 
   555     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_is_listed,
   556             (int)strlen(sql_blacklist_is_listed),
   557             &_session->blacklist_is_listed, NULL);
   558     assert(int_result == SQLITE_OK);
   559 
   560     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_retrieve,
   561             (int)strlen(sql_blacklist_retrieve), &_session->blacklist_retrieve,
   562             NULL);
   563     assert(int_result == SQLITE_OK);
   564     
   565     // Own keys
   566     
   567     int_result = sqlite3_prepare_v2(_session->db, sql_own_key_is_listed,
   568             (int)strlen(sql_own_key_is_listed), &_session->own_key_is_listed,
   569             NULL);
   570     assert(int_result == SQLITE_OK);
   571     
   572     int_result = sqlite3_prepare_v2(_session->db, sql_own_identities_retrieve,
   573             (int)strlen(sql_own_identities_retrieve),
   574             &_session->own_identities_retrieve, NULL);
   575     assert(int_result == SQLITE_OK);
   576  
   577     int_result = sqlite3_prepare_v2(_session->db, sql_own_keys_retrieve,
   578             (int)strlen(sql_own_keys_retrieve),
   579             &_session->own_keys_retrieve, NULL);
   580     assert(int_result == SQLITE_OK);
   581  
   582     int_result = sqlite3_prepare_v2(_session->db, sql_set_own_key,
   583             (int)strlen(sql_set_own_key),
   584             &_session->set_own_key, NULL);
   585     assert(int_result == SQLITE_OK);
   586  
   587     // Sequence
   588 
   589     int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value1,
   590             (int)strlen(sql_sequence_value1), &_session->sequence_value1,
   591             NULL);
   592     assert(int_result == SQLITE_OK);
   593 
   594     int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value2,
   595             (int)strlen(sql_sequence_value2), &_session->sequence_value2,
   596             NULL);
   597     assert(int_result == SQLITE_OK);
   598 
   599     int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value3,
   600             (int)strlen(sql_sequence_value3), &_session->sequence_value3,
   601             NULL);
   602     assert(int_result == SQLITE_OK);
   603 
   604     // Revocation tracking
   605     
   606     int_result = sqlite3_prepare_v2(_session->db, sql_set_revoked,
   607             (int)strlen(sql_set_revoked), &_session->set_revoked, NULL);
   608     assert(int_result == SQLITE_OK);
   609     
   610     int_result = sqlite3_prepare_v2(_session->db, sql_get_revoked,
   611             (int)strlen(sql_get_revoked), &_session->get_revoked, NULL);
   612     assert(int_result == SQLITE_OK);
   613     
   614     status = init_cryptotech(_session, in_first);
   615     if (status != PEP_STATUS_OK)
   616         goto pep_error;
   617 
   618     status = init_transport_system(_session, in_first);
   619     if (status != PEP_STATUS_OK)
   620         goto pep_error;
   621 
   622     status = log_event(_session, "init", "pEp " PEP_ENGINE_VERSION, NULL, NULL);
   623     if (status != PEP_STATUS_OK)
   624         goto pep_error;
   625 
   626     // runtime config
   627 
   628 #ifdef ANDROID
   629     _session->use_only_own_private_keys = true;
   630 #elif TARGET_OS_IPHONE
   631     _session->use_only_own_private_keys = true;
   632 #else
   633     _session->use_only_own_private_keys = false;
   634 #endif
   635 
   636     *session = _session;
   637     return PEP_STATUS_OK;
   638 
   639 enomem:
   640     status = PEP_OUT_OF_MEMORY;
   641 
   642 pep_error:
   643     release(_session);
   644     return status;
   645 }
   646 
   647 DYNAMIC_API void release(PEP_SESSION session)
   648 {
   649     bool out_last = false;
   650 
   651     assert(init_count >= 0);
   652     assert(session);
   653 
   654     if (!((init_count >= 0) && session))
   655         return;
   656 
   657     // a small race condition but still a race condition
   658     // mitigated by calling caveat (see documentation)
   659 
   660     if (init_count == 0)
   661         out_last = true;
   662     --init_count;
   663 
   664     if (session) {
   665         if (session->sync_state != DeviceState_state_NONE)
   666             unregister_sync_callbacks(session);
   667 
   668         if (session->db) {
   669             if (session->log)
   670                 sqlite3_finalize(session->log);
   671             if (session->trustword)
   672                 sqlite3_finalize(session->trustword);
   673             if (session->get_identity)
   674                 sqlite3_finalize(session->get_identity);
   675             if (session->set_person)
   676                 sqlite3_finalize(session->set_person);
   677             if (session->set_device_group)
   678                 sqlite3_finalize(session->set_device_group);
   679             if (session->get_device_group)
   680                 sqlite3_finalize(session->get_device_group);
   681             if (session->set_pgp_keypair)
   682                 sqlite3_finalize(session->set_pgp_keypair);
   683             if (session->set_identity)
   684                 sqlite3_finalize(session->set_identity);
   685             if (session->set_identity_flags)
   686                 sqlite3_finalize(session->set_identity_flags);
   687             if (session->unset_identity_flags)
   688                 sqlite3_finalize(session->unset_identity_flags);
   689             if (session->set_trust)
   690                 sqlite3_finalize(session->set_trust);
   691             if (session->get_trust)
   692                 sqlite3_finalize(session->get_trust);
   693             if (session->greater_trust_keys)
   694                 sqlite3_finalize(session->greater_trust_keys);
   695             if (session->least_trust)
   696                 sqlite3_finalize(session->least_trust);
   697             if (session->mark_compromized)
   698                 sqlite3_finalize(session->mark_compromized);
   699             if (session->crashdump)
   700                 sqlite3_finalize(session->crashdump);
   701             if (session->languagelist)
   702                 sqlite3_finalize(session->languagelist);
   703             if (session->i18n_token)
   704                 sqlite3_finalize(session->i18n_token);
   705             if (session->blacklist_add)
   706                 sqlite3_finalize(session->blacklist_add);
   707             if (session->blacklist_delete)
   708                 sqlite3_finalize(session->blacklist_delete);
   709             if (session->blacklist_is_listed)
   710                 sqlite3_finalize(session->blacklist_is_listed);
   711             if (session->blacklist_retrieve)
   712                 sqlite3_finalize(session->blacklist_retrieve);
   713             if (session->own_key_is_listed)
   714                 sqlite3_finalize(session->own_key_is_listed);
   715             if (session->own_identities_retrieve)
   716                 sqlite3_finalize(session->own_identities_retrieve);
   717             if (session->own_keys_retrieve)
   718                 sqlite3_finalize(session->own_keys_retrieve);
   719             if (session->set_own_key)
   720                 sqlite3_finalize(session->set_own_key);
   721             if (session->sequence_value1)
   722                 sqlite3_finalize(session->sequence_value1);
   723             if (session->sequence_value2)
   724                 sqlite3_finalize(session->sequence_value2);
   725             if (session->sequence_value3)
   726                 sqlite3_finalize(session->sequence_value3);
   727             if (session->set_revoked)
   728                 sqlite3_finalize(session->set_revoked);
   729             if (session->get_revoked)
   730                 sqlite3_finalize(session->get_revoked);
   731 
   732             if (session->db)
   733                 sqlite3_close_v2(session->db);
   734             if (session->system_db)
   735                 sqlite3_close_v2(session->system_db);
   736         }
   737 
   738         release_transport_system(session, out_last);
   739         release_cryptotech(session, out_last);
   740 
   741         free(session);
   742     }
   743 }
   744 
   745 DYNAMIC_API void config_passive_mode(PEP_SESSION session, bool enable)
   746 {
   747     assert(session);
   748     session->passive_mode = enable;
   749 }
   750 
   751 DYNAMIC_API void config_unencrypted_subject(PEP_SESSION session, bool enable)
   752 {
   753     assert(session);
   754     session->unencrypted_subject = enable;
   755 }
   756 
   757 DYNAMIC_API void config_use_only_own_private_keys(PEP_SESSION session,
   758         bool enable)
   759 {
   760     assert(session);
   761     session->use_only_own_private_keys = enable;
   762 }
   763 
   764 DYNAMIC_API void config_keep_sync_msg(PEP_SESSION session, bool enable)
   765 {
   766     assert(session);
   767     session->keep_sync_msg = enable;
   768 }
   769 
   770 DYNAMIC_API PEP_STATUS log_event(
   771         PEP_SESSION session,
   772         const char *title,
   773         const char *entity,
   774         const char *description,
   775         const char *comment
   776     )
   777 {
   778     PEP_STATUS status = PEP_STATUS_OK;
   779     int result;
   780 
   781     assert(session);
   782     assert(title);
   783     assert(entity);
   784 
   785     if (!(session && title && entity))
   786         return PEP_ILLEGAL_VALUE;
   787 
   788     sqlite3_reset(session->log);
   789     sqlite3_bind_text(session->log, 1, title, -1, SQLITE_STATIC);
   790     sqlite3_bind_text(session->log, 2, entity, -1, SQLITE_STATIC);
   791     if (description)
   792         sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
   793     else
   794         sqlite3_bind_null(session->log, 3);
   795     if (comment)
   796         sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
   797     else
   798         sqlite3_bind_null(session->log, 4);
   799     do {
   800         result = sqlite3_step(session->log);
   801         assert(result == SQLITE_DONE || result == SQLITE_BUSY);
   802         if (result != SQLITE_DONE && result != SQLITE_BUSY)
   803             status = PEP_UNKNOWN_ERROR;
   804     } while (result == SQLITE_BUSY);
   805     sqlite3_reset(session->log);
   806 
   807     return status;
   808 }
   809 
   810 DYNAMIC_API PEP_STATUS trustword(
   811             PEP_SESSION session, uint16_t value, const char *lang,
   812             char **word, size_t *wsize
   813         )
   814 {
   815     PEP_STATUS status = PEP_STATUS_OK;
   816 
   817     assert(session);
   818     assert(word);
   819     assert(wsize);
   820 
   821     if (!(session && word && wsize))
   822         return PEP_ILLEGAL_VALUE;
   823 
   824     *word = NULL;
   825     *wsize = 0;
   826 
   827     if (lang == NULL)
   828         lang = "en";
   829 
   830     assert((lang[0] >= 'A' && lang[0] <= 'Z')
   831             || (lang[0] >= 'a' && lang[0] <= 'z'));
   832     assert((lang[1] >= 'A' && lang[1] <= 'Z')
   833             || (lang[1] >= 'a' && lang[1] <= 'z'));
   834     assert(lang[2] == 0);
   835 
   836     sqlite3_reset(session->trustword);
   837     sqlite3_bind_text(session->trustword, 1, lang, -1, SQLITE_STATIC);
   838     sqlite3_bind_int(session->trustword, 2, value);
   839 
   840     const int result = sqlite3_step(session->trustword);
   841     if (result == SQLITE_ROW) {
   842         *word = strdup((const char *) sqlite3_column_text(session->trustword,
   843                     1));
   844         if (*word)
   845             *wsize = sqlite3_column_bytes(session->trustword, 1);
   846         else
   847             status = PEP_OUT_OF_MEMORY;
   848     } else
   849         status = PEP_TRUSTWORD_NOT_FOUND;
   850 
   851     sqlite3_reset(session->trustword);
   852     return status;
   853 }
   854 
   855 DYNAMIC_API PEP_STATUS trustwords(
   856         PEP_SESSION session, const char *fingerprint, const char *lang,
   857         char **words, size_t *wsize, int max_words
   858     )
   859 {
   860     const char *source = fingerprint;
   861     char *buffer;
   862     char *dest;
   863     size_t fsize;
   864 
   865     assert(session);
   866     assert(fingerprint);
   867     assert(words);
   868     assert(wsize);
   869     assert(max_words >= 0);
   870 
   871     if (!(session && fingerprint && words && wsize && max_words >= 0))
   872         return PEP_ILLEGAL_VALUE;
   873 
   874     *words = NULL;
   875     *wsize = 0;
   876 
   877     buffer = calloc(1, MAX_TRUSTWORDS_SPACE);
   878     assert(buffer);
   879     if (buffer == NULL)
   880         return PEP_OUT_OF_MEMORY;
   881     dest = buffer;
   882 
   883     fsize = strlen(fingerprint);
   884 
   885     if (!lang || !lang[0])
   886         lang = "en";
   887 
   888     assert((lang[0] >= 'A' && lang[0] <= 'Z')
   889             || (lang[0] >= 'a' && lang[0] <= 'z'));
   890     assert((lang[1] >= 'A' && lang[1] <= 'Z')
   891             || (lang[1] >= 'a' && lang[1] <= 'z'));
   892     assert(lang[2] == 0);
   893 
   894     int n_words = 0;
   895     while (source < fingerprint + fsize) {
   896         PEP_STATUS _status;
   897         uint16_t value;
   898         char *word;
   899         size_t _wsize;
   900         int j;
   901 
   902         for (value=0, j=0; j < 4 && source < fingerprint + fsize; ) {
   903             if (*source >= 'a' && *source <= 'f')
   904                 value += (*source - 'a' + 10) << (3 - j++) * 4;
   905             else if (*source >= 'A' && *source <= 'F')
   906                 value += (*source - 'A' + 10) << (3 - j++) * 4;
   907             else if (*source >= '0' && *source <= '9')
   908                 value += (*source - '0') << (3 - j++) * 4;
   909             
   910             source++;
   911         }
   912 
   913         _status = trustword(session, value, lang, &word, &_wsize);
   914         if (_status == PEP_OUT_OF_MEMORY) {
   915             free(buffer);
   916             return PEP_OUT_OF_MEMORY;
   917         }
   918         if (word == NULL) {
   919             free(buffer);
   920             return PEP_TRUSTWORD_NOT_FOUND;
   921         }
   922 
   923         if (dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1) {
   924             strncpy(dest, word, _wsize);
   925             free(word);
   926             dest += _wsize;
   927         }
   928         else {
   929             free(word);
   930             break; // buffer full
   931         }
   932 
   933         if (source < fingerprint + fsize
   934                 && dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1)
   935             *dest++ = ' ';
   936 
   937         ++n_words;
   938         if (max_words && n_words >= max_words)
   939             break;
   940     }
   941 
   942     *words = buffer;
   943     *wsize = dest - buffer;
   944     return PEP_STATUS_OK;
   945 }
   946 
   947 pEp_identity *new_identity(
   948         const char *address, const char *fpr, const char *user_id,
   949         const char *username
   950     )
   951 {
   952     pEp_identity *result = calloc(1, sizeof(pEp_identity));
   953     assert(result);
   954     if (result) {
   955         if (address) {
   956             result->address = strdup(address);
   957             assert(result->address);
   958             if (result->address == NULL) {
   959                 free(result);
   960                 return NULL;
   961             }
   962         }
   963         if (fpr) {
   964             result->fpr = strdup(fpr);
   965             assert(result->fpr);
   966             if (result->fpr == NULL) {
   967                 free_identity(result);
   968                 return NULL;
   969             }
   970         }
   971         if (user_id) {
   972             result->user_id = strdup(user_id);
   973             assert(result->user_id);
   974             if (result->user_id == NULL) {
   975                 free_identity(result);
   976                 return NULL;
   977             }
   978         }
   979         if (username) {
   980             result->username = strdup(username);
   981             assert(result->username);
   982             if (result->username == NULL) {
   983                 free_identity(result);
   984                 return NULL;
   985             }
   986         }
   987     }
   988     return result;
   989 }
   990 
   991 pEp_identity *identity_dup(const pEp_identity *src)
   992 {
   993     assert(src);
   994 
   995     pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id,
   996             src->username);
   997     assert(dup);
   998     if (dup == NULL)
   999         return NULL;
  1000     
  1001     dup->comm_type = src->comm_type;
  1002     dup->lang[0] = src->lang[0];
  1003     dup->lang[1] = src->lang[1];
  1004     dup->lang[2] = 0;
  1005     dup->me = src->me;
  1006     dup->flags = src->flags;
  1007 
  1008     return dup;
  1009 }
  1010 
  1011 void free_identity(pEp_identity *identity)
  1012 {
  1013     if (identity) {
  1014         free(identity->address);
  1015         free(identity->fpr);
  1016         free(identity->user_id);
  1017         free(identity->username);
  1018         free(identity);
  1019     }
  1020 }
  1021 
  1022 DYNAMIC_API PEP_STATUS get_identity(
  1023         PEP_SESSION session,
  1024         const char *address,
  1025         const char *user_id,
  1026         pEp_identity **identity
  1027     )
  1028 {
  1029     PEP_STATUS status = PEP_STATUS_OK;
  1030     static pEp_identity *_identity;
  1031 
  1032     assert(session);
  1033     assert(address);
  1034     assert(address[0]);
  1035     assert(identity);
  1036 
  1037     if (!(session && address && address[0] && identity))
  1038         return PEP_ILLEGAL_VALUE;
  1039 
  1040     *identity = NULL;
  1041 
  1042     sqlite3_reset(session->get_identity);
  1043     sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
  1044     sqlite3_bind_text(session->get_identity, 2, user_id, -1, SQLITE_STATIC);
  1045 
  1046     const int result = sqlite3_step(session->get_identity);
  1047     switch (result) {
  1048     case SQLITE_ROW:
  1049         _identity = new_identity(
  1050                 address,
  1051                 (const char *) sqlite3_column_text(session->get_identity, 0),
  1052                 user_id,
  1053                 (const char *) sqlite3_column_text(session->get_identity, 1)
  1054                 );
  1055         assert(_identity);
  1056         if (_identity == NULL)
  1057             return PEP_OUT_OF_MEMORY;
  1058 
  1059         _identity->comm_type = (PEP_comm_type)
  1060             sqlite3_column_int(session->get_identity, 2);
  1061         const char* const _lang = (const char *)
  1062             sqlite3_column_text(session->get_identity, 3);
  1063         if (_lang && _lang[0]) {
  1064             assert(_lang[0] >= 'a' && _lang[0] <= 'z');
  1065             assert(_lang[1] >= 'a' && _lang[1] <= 'z');
  1066             assert(_lang[2] == 0);
  1067             _identity->lang[0] = _lang[0];
  1068             _identity->lang[1] = _lang[1];
  1069             _identity->lang[2] = 0;
  1070         }
  1071         _identity->flags = (unsigned int)
  1072             sqlite3_column_int(session->get_identity, 4);
  1073         *identity = _identity;
  1074         break;
  1075     default:
  1076         status = PEP_CANNOT_FIND_IDENTITY;
  1077         *identity = NULL;
  1078     }
  1079 
  1080     sqlite3_reset(session->get_identity);
  1081     return status;
  1082 }
  1083 
  1084 DYNAMIC_API PEP_STATUS set_identity(
  1085         PEP_SESSION session, const pEp_identity *identity
  1086     )
  1087 {
  1088     int result;
  1089 
  1090     assert(session);
  1091     assert(identity);
  1092     assert(identity->address);
  1093     assert(identity->user_id);
  1094     assert(identity->username);
  1095 
  1096     if (!(session && identity && identity->address &&
  1097                 identity->user_id && identity->username))
  1098         return PEP_ILLEGAL_VALUE;
  1099 
  1100     bool listed;
  1101 
  1102     bool has_fpr = (identity->fpr && identity->fpr[0] != '\0');
  1103     
  1104     if (has_fpr) {    
  1105         // blacklist check
  1106         PEP_STATUS status = blacklist_is_listed(session, identity->fpr, &listed);
  1107         assert(status == PEP_STATUS_OK);
  1108         if (status != PEP_STATUS_OK)
  1109             return status;
  1110 
  1111         if (listed)
  1112             return PEP_KEY_BLACKLISTED;
  1113     }
  1114 
  1115     sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
  1116 
  1117     if (identity->lang[0]) {
  1118         assert(identity->lang[0] >= 'a' && identity->lang[0] <= 'z');
  1119         assert(identity->lang[1] >= 'a' && identity->lang[1] <= 'z');
  1120         assert(identity->lang[2] == 0);
  1121     }
  1122 
  1123     sqlite3_reset(session->set_person);
  1124     sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
  1125             SQLITE_STATIC);
  1126     sqlite3_bind_text(session->set_person, 2, identity->username, -1,
  1127             SQLITE_STATIC);
  1128     if (identity->lang[0])
  1129         sqlite3_bind_text(session->set_person, 3, identity->lang, 2,
  1130                 SQLITE_STATIC);
  1131     else
  1132         sqlite3_bind_null(session->set_person, 3);
  1133     sqlite3_bind_text(session->set_person, 4, identity->fpr, -1,
  1134                       SQLITE_STATIC);
  1135     result = sqlite3_step(session->set_person);
  1136     sqlite3_reset(session->set_person);
  1137     if (result != SQLITE_DONE) {
  1138         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1139         return PEP_CANNOT_SET_PERSON;
  1140     }
  1141 
  1142     if (has_fpr) {
  1143         sqlite3_reset(session->set_pgp_keypair);
  1144         sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
  1145                 SQLITE_STATIC);
  1146         result = sqlite3_step(session->set_pgp_keypair);
  1147         sqlite3_reset(session->set_pgp_keypair);
  1148         if (result != SQLITE_DONE) {
  1149             sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1150             return PEP_CANNOT_SET_PGP_KEYPAIR;
  1151         }
  1152     }
  1153 
  1154     sqlite3_reset(session->set_identity);
  1155     sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
  1156             SQLITE_STATIC);
  1157     sqlite3_bind_text(session->set_identity, 2, identity->fpr, -1,
  1158             SQLITE_STATIC);
  1159     sqlite3_bind_text(session->set_identity, 3, identity->user_id, -1,
  1160             SQLITE_STATIC);
  1161     sqlite3_bind_int(session->set_identity, 4, identity->flags);
  1162     result = sqlite3_step(session->set_identity);
  1163     sqlite3_reset(session->set_identity);
  1164     if (result != SQLITE_DONE) {
  1165         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1166         return PEP_CANNOT_SET_IDENTITY;
  1167     }
  1168 
  1169     if (has_fpr) {
  1170         if(strcmp(identity->user_id, PEP_OWN_USERID) == 0) {
  1171             sqlite3_reset(session->set_own_key);
  1172             sqlite3_bind_text(session->set_own_key, 1, identity->address, -1,
  1173                 SQLITE_STATIC);
  1174             sqlite3_bind_text(session->set_own_key, 2, identity->fpr, -1,
  1175                 SQLITE_STATIC);
  1176             result = sqlite3_step(session->set_own_key);
  1177             sqlite3_reset(session->set_own_key);
  1178             if (result != SQLITE_DONE) {
  1179                 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1180                 return PEP_CANNOT_SET_PGP_KEYPAIR;
  1181             }
  1182         }
  1183 
  1184         sqlite3_reset(session->set_trust);
  1185         sqlite3_bind_text(session->set_trust, 1, identity->user_id, -1,
  1186                 SQLITE_STATIC);
  1187         sqlite3_bind_text(session->set_trust, 2, identity->fpr, -1,
  1188                 SQLITE_STATIC);
  1189         sqlite3_bind_int(session->set_trust, 3, identity->comm_type);
  1190         result = sqlite3_step(session->set_trust);
  1191         sqlite3_reset(session->set_trust);
  1192         if (result != SQLITE_DONE) {
  1193             sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1194             return PEP_CANNOT_SET_TRUST;
  1195         }
  1196     }
  1197     
  1198     result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
  1199     if (result == SQLITE_OK)
  1200         return PEP_STATUS_OK;
  1201     else
  1202         return PEP_COMMIT_FAILED;
  1203 }
  1204 
  1205 DYNAMIC_API PEP_STATUS set_device_group(
  1206         PEP_SESSION session,
  1207         const char *group_name
  1208     )
  1209 {
  1210     int result;
  1211 
  1212     assert(session);
  1213     assert(group_name);
  1214 
  1215     if (!(session && group_name))
  1216         return PEP_ILLEGAL_VALUE;
  1217 
  1218     sqlite3_reset(session->set_device_group);
  1219     sqlite3_bind_text(session->set_device_group, 1, group_name, -1,
  1220             SQLITE_STATIC);
  1221     result = sqlite3_step(session->set_device_group);
  1222     sqlite3_reset(session->set_device_group);
  1223     if (result != SQLITE_DONE)
  1224         return PEP_CANNOT_SET_PERSON;
  1225 
  1226     return PEP_STATUS_OK;
  1227 }
  1228 
  1229 DYNAMIC_API PEP_STATUS get_device_group(PEP_SESSION session, char **group_name)
  1230 {
  1231     PEP_STATUS status = PEP_STATUS_OK;
  1232     int result;
  1233 
  1234     assert(session);
  1235     assert(group_name);
  1236 
  1237     if (!(session && group_name))
  1238         return PEP_ILLEGAL_VALUE;
  1239 
  1240     sqlite3_reset(session->get_device_group);
  1241 
  1242     result = sqlite3_step(session->get_device_group);
  1243     switch (result) {
  1244     case SQLITE_ROW: {
  1245         *group_name = strdup(
  1246             (const char *) sqlite3_column_text(session->get_device_group, 0));
  1247             if(*group_name == NULL)
  1248                 status = PEP_OUT_OF_MEMORY;
  1249         break;
  1250     }
  1251  
  1252     default:
  1253         status = PEP_RECORD_NOT_FOUND;
  1254     }
  1255 
  1256     sqlite3_reset(session->get_device_group);
  1257     return status;
  1258 }
  1259 
  1260 DYNAMIC_API PEP_STATUS set_identity_flags(
  1261         PEP_SESSION session,
  1262         pEp_identity *identity,
  1263         unsigned int flags
  1264     )
  1265 {
  1266     int result;
  1267 
  1268     assert(session);
  1269     assert(identity);
  1270     assert(identity->address);
  1271     assert(identity->user_id);
  1272 
  1273     if (!(session && identity && identity->address && identity->user_id))
  1274         return PEP_ILLEGAL_VALUE;
  1275 
  1276     sqlite3_reset(session->set_identity_flags);
  1277     sqlite3_bind_int(session->set_identity_flags, 1, flags);
  1278     sqlite3_bind_text(session->set_identity_flags, 2, identity->address, -1,
  1279             SQLITE_STATIC);
  1280     sqlite3_bind_text(session->set_identity_flags, 3, identity->user_id, -1,
  1281             SQLITE_STATIC);
  1282     result = sqlite3_step(session->set_identity_flags);
  1283     sqlite3_reset(session->set_identity_flags);
  1284     if (result != SQLITE_DONE)
  1285         return PEP_CANNOT_SET_IDENTITY;
  1286 
  1287     identity->flags |= flags;
  1288     return PEP_STATUS_OK;
  1289 }
  1290 
  1291 DYNAMIC_API PEP_STATUS unset_identity_flags(
  1292         PEP_SESSION session,
  1293         pEp_identity *identity,
  1294         unsigned int flags
  1295     )
  1296 {
  1297     int result;
  1298 
  1299     assert(session);
  1300     assert(identity);
  1301     assert(identity->address);
  1302     assert(identity->user_id);
  1303 
  1304     if (!(session && identity && identity->address && identity->user_id))
  1305         return PEP_ILLEGAL_VALUE;
  1306 
  1307     sqlite3_reset(session->unset_identity_flags);
  1308     sqlite3_bind_int(session->unset_identity_flags, 1, flags);
  1309     sqlite3_bind_text(session->unset_identity_flags, 2, identity->address, -1,
  1310             SQLITE_STATIC);
  1311     sqlite3_bind_text(session->unset_identity_flags, 3, identity->user_id, -1,
  1312             SQLITE_STATIC);
  1313     result = sqlite3_step(session->unset_identity_flags);
  1314     sqlite3_reset(session->unset_identity_flags);
  1315     if (result != SQLITE_DONE)
  1316         return PEP_CANNOT_SET_IDENTITY;
  1317 
  1318     identity->flags &= ~flags;
  1319     return PEP_STATUS_OK;
  1320 }
  1321 
  1322 DYNAMIC_API PEP_STATUS mark_as_compromized(
  1323         PEP_SESSION session,
  1324         const char *fpr
  1325     )
  1326 {
  1327     int result;
  1328 
  1329     assert(session);
  1330     assert(fpr && fpr[0]);
  1331 
  1332     if (!(session && fpr && fpr[0]))
  1333         return PEP_ILLEGAL_VALUE;
  1334 
  1335     sqlite3_reset(session->mark_compromized);
  1336     sqlite3_bind_text(session->mark_compromized, 1, fpr, -1,
  1337             SQLITE_STATIC);
  1338     result = sqlite3_step(session->mark_compromized);
  1339     sqlite3_reset(session->mark_compromized);
  1340 
  1341     if (result != SQLITE_DONE)
  1342         return PEP_CANNOT_SET_TRUST;
  1343 
  1344     return PEP_STATUS_OK;
  1345 }
  1346 
  1347 void pEp_free(void *p)
  1348 {
  1349     free(p);
  1350 }
  1351 
  1352 DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
  1353 {
  1354     PEP_STATUS status = PEP_STATUS_OK;
  1355     int result;
  1356 
  1357     assert(session);
  1358     assert(identity);
  1359     assert(identity->user_id);
  1360     assert(identity->user_id[0]);
  1361     assert(identity->fpr);
  1362     assert(identity->fpr[0]);
  1363 
  1364     if (!(session && identity && identity->user_id && identity->user_id[0] &&
  1365                 identity->fpr && identity->fpr[0]))
  1366         return PEP_ILLEGAL_VALUE;
  1367 
  1368     identity->comm_type = PEP_ct_unknown;
  1369 
  1370     sqlite3_reset(session->get_trust);
  1371     sqlite3_bind_text(session->get_trust, 1, identity->user_id, -1,
  1372             SQLITE_STATIC);
  1373     sqlite3_bind_text(session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
  1374 
  1375     result = sqlite3_step(session->get_trust);
  1376     switch (result) {
  1377     case SQLITE_ROW: {
  1378         int comm_type = (PEP_comm_type) sqlite3_column_int(session->get_trust,
  1379                 0);
  1380         identity->comm_type = comm_type;
  1381         break;
  1382     }
  1383  
  1384     default:
  1385         status = PEP_CANNOT_FIND_IDENTITY;
  1386     }
  1387 
  1388     sqlite3_reset(session->get_trust);
  1389     return status;
  1390 }
  1391 
  1392 DYNAMIC_API PEP_STATUS greater_trust_keys(
  1393         PEP_SESSION session,
  1394         const char *user_id,
  1395         PEP_comm_type min_comm_type,
  1396         stringlist_t **keylist
  1397     )
  1398 {
  1399     PEP_STATUS status = PEP_STATUS_OK;
  1400 
  1401     assert(session);
  1402     assert(keylist);
  1403 
  1404     if (!(session && keylist))
  1405         return PEP_ILLEGAL_VALUE;
  1406 
  1407     *keylist = NULL;
  1408     stringlist_t *_keylist = new_stringlist(NULL);
  1409     if (_keylist == NULL)
  1410         goto enomem;
  1411 
  1412     sqlite3_reset(session->greater_trust_keys);
  1413 
  1414     sqlite3_bind_text(session->greater_trust_keys, 1, user_id, -1, SQLITE_STATIC);
  1415     sqlite3_bind_int(session->greater_trust_keys, 2, min_comm_type);
  1416     int result;
  1417 
  1418     stringlist_t *_bl = _keylist;
  1419     do {
  1420         result = sqlite3_step(session->greater_trust_keys);
  1421         switch (result) {
  1422         case SQLITE_ROW:
  1423         {
  1424             const char *fpr = (const char *) sqlite3_column_text(session->greater_trust_keys, 0);
  1425 
  1426             _bl = stringlist_add(_bl, fpr);
  1427             if (_bl == NULL)
  1428                 goto enomem;
  1429 
  1430             break;
  1431         }
  1432         case SQLITE_DONE:
  1433             break;
  1434 
  1435         default:
  1436             status = PEP_UNKNOWN_ERROR;
  1437             result = SQLITE_DONE;
  1438         }
  1439     } while (result != SQLITE_DONE);
  1440 
  1441     sqlite3_reset(session->greater_trust_keys);
  1442     if (status == PEP_STATUS_OK)
  1443         *keylist = _keylist;
  1444     else
  1445         free_stringlist(_keylist);
  1446 
  1447     goto the_end;
  1448 
  1449 enomem:
  1450     free_stringlist(_keylist);
  1451     status = PEP_OUT_OF_MEMORY;
  1452 
  1453 the_end:
  1454     return status;
  1455 }
  1456 
  1457 DYNAMIC_API PEP_STATUS least_trust(
  1458         PEP_SESSION session,
  1459         const char *fpr,
  1460         PEP_comm_type *comm_type
  1461     )
  1462 {
  1463     PEP_STATUS status = PEP_STATUS_OK;
  1464     int result;
  1465 
  1466     assert(session);
  1467     assert(fpr);
  1468     assert(comm_type);
  1469 
  1470     if (!(session && fpr && comm_type))
  1471         return PEP_ILLEGAL_VALUE;
  1472 
  1473     *comm_type = PEP_ct_unknown;
  1474 
  1475     sqlite3_reset(session->least_trust);
  1476     sqlite3_bind_text(session->least_trust, 1, fpr, -1, SQLITE_STATIC);
  1477 
  1478     result = sqlite3_step(session->least_trust);
  1479     switch (result) {
  1480         case SQLITE_ROW: {
  1481             int _comm_type = sqlite3_column_int(session->least_trust, 0);
  1482             *comm_type = (PEP_comm_type) _comm_type;
  1483             break;
  1484         }
  1485         default:
  1486             status = PEP_CANNOT_FIND_IDENTITY;
  1487     }
  1488 
  1489     sqlite3_reset(session->least_trust);
  1490     return status;
  1491 }
  1492 
  1493 DYNAMIC_API PEP_STATUS decrypt_and_verify(
  1494     PEP_SESSION session, const char *ctext, size_t csize,
  1495     const char *dsigtext, size_t dsigsize,
  1496     char **ptext, size_t *psize, stringlist_t **keylist
  1497     )
  1498 {
  1499     assert(session);
  1500     assert(ctext);
  1501     assert(csize);
  1502     assert(ptext);
  1503     assert(psize);
  1504     assert(keylist);
  1505 
  1506     if (!(session && ctext && csize && ptext && psize && keylist))
  1507         return PEP_ILLEGAL_VALUE;
  1508 
  1509     return session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(
  1510             session, ctext, csize, dsigtext, dsigsize, ptext, psize, keylist);
  1511 }
  1512 
  1513 DYNAMIC_API PEP_STATUS encrypt_and_sign(
  1514     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
  1515     size_t psize, char **ctext, size_t *csize
  1516     )
  1517 {
  1518     assert(session);
  1519     assert(keylist);
  1520     assert(ptext);
  1521     assert(psize);
  1522     assert(ctext);
  1523     assert(csize);
  1524 
  1525     if (!(session && keylist && ptext && psize && ctext && csize))
  1526         return PEP_ILLEGAL_VALUE;
  1527 
  1528     return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session,
  1529             keylist, ptext, psize, ctext, csize);
  1530 }
  1531 
  1532 DYNAMIC_API PEP_STATUS verify_text(
  1533     PEP_SESSION session, const char *text, size_t size,
  1534     const char *signature, size_t sig_size, stringlist_t **keylist
  1535     )
  1536 {
  1537     assert(session);
  1538     assert(text);
  1539     assert(size);
  1540     assert(signature);
  1541     assert(sig_size);
  1542     assert(keylist);
  1543 
  1544     if (!(session && text && size && signature && sig_size && keylist))
  1545         return PEP_ILLEGAL_VALUE;
  1546 
  1547     return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text,
  1548             size, signature, sig_size, keylist);
  1549 }
  1550 
  1551 DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
  1552 {
  1553     assert(session);
  1554     assert(fpr);
  1555 
  1556     if (!(session && fpr))
  1557         return PEP_ILLEGAL_VALUE;
  1558 
  1559     return session->cryptotech[PEP_crypt_OpenPGP].delete_keypair(session, fpr);
  1560 }
  1561 
  1562 DYNAMIC_API PEP_STATUS export_key(
  1563         PEP_SESSION session, const char *fpr, char **key_data, size_t *size
  1564     )
  1565 {
  1566     assert(session);
  1567     assert(fpr);
  1568     assert(key_data);
  1569     assert(size);
  1570 
  1571     if (!(session && fpr && key_data && size))
  1572         return PEP_ILLEGAL_VALUE;
  1573 
  1574     return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr,
  1575             key_data, size, false);
  1576 }
  1577 
  1578 DYNAMIC_API PEP_STATUS export_secrect_key(
  1579         PEP_SESSION session, const char *fpr, char **key_data, size_t *size
  1580     )
  1581 {
  1582     assert(session);
  1583     assert(fpr);
  1584     assert(key_data);
  1585     assert(size);
  1586 
  1587     if (!(session && fpr && key_data && size))
  1588         return PEP_ILLEGAL_VALUE;
  1589 
  1590     // don't accept key IDs but full fingerprints only
  1591     if (strlen(fpr) < 16)
  1592         return PEP_ILLEGAL_VALUE;
  1593 
  1594     return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr,
  1595             key_data, size, true);
  1596 }
  1597 
  1598 DYNAMIC_API PEP_STATUS find_keys(
  1599         PEP_SESSION session, const char *pattern, stringlist_t **keylist
  1600     )
  1601 {
  1602     assert(session);
  1603     assert(pattern);
  1604     assert(keylist);
  1605 
  1606     if (!(session && pattern && keylist))
  1607         return PEP_ILLEGAL_VALUE;
  1608 
  1609     return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern,
  1610             keylist);
  1611 }
  1612 
  1613 
  1614 DYNAMIC_API PEP_STATUS generate_keypair(
  1615         PEP_SESSION session, pEp_identity *identity
  1616     )
  1617 {
  1618     assert(session);
  1619     assert(identity);
  1620     assert(identity->address);
  1621     assert(identity->fpr == NULL || identity->fpr[0] == 0);
  1622     assert(identity->username);
  1623 
  1624     if (!(session && identity && identity->address &&
  1625             (identity->fpr == NULL || identity->fpr[0] == 0) &&
  1626             identity->username))
  1627         return PEP_ILLEGAL_VALUE;
  1628 
  1629     PEP_STATUS status =
  1630         session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session,
  1631                 identity);
  1632     if (status != PEP_STATUS_OK)
  1633         return status;
  1634 
  1635     return status;
  1636 }
  1637 
  1638 DYNAMIC_API PEP_STATUS get_key_rating(
  1639         PEP_SESSION session,
  1640         const char *fpr,
  1641         PEP_comm_type *comm_type
  1642     )
  1643 {
  1644     assert(session);
  1645     assert(fpr);
  1646     assert(comm_type);
  1647 
  1648     if (!(session && fpr && comm_type))
  1649         return PEP_ILLEGAL_VALUE;
  1650 
  1651     return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr,
  1652             comm_type);
  1653 }
  1654 
  1655 DYNAMIC_API PEP_STATUS import_key(
  1656         PEP_SESSION session,
  1657         const char *key_data,
  1658         size_t size,
  1659         identity_list **private_keys
  1660     )
  1661 {
  1662     assert(session);
  1663     assert(key_data);
  1664 
  1665     if (!(session && key_data))
  1666         return PEP_ILLEGAL_VALUE;
  1667 
  1668     return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data,
  1669             size, private_keys);
  1670 }
  1671 
  1672 DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
  1673 {
  1674     assert(session);
  1675     assert(pattern);
  1676 
  1677     if (!(session && pattern))
  1678         return PEP_ILLEGAL_VALUE;
  1679 
  1680     return session->cryptotech[PEP_crypt_OpenPGP].recv_key(session, pattern);
  1681 }
  1682 
  1683 DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
  1684 {
  1685     assert(session);
  1686     assert(pattern);
  1687 
  1688     if (!(session && pattern))
  1689         return PEP_ILLEGAL_VALUE;
  1690 
  1691     return session->cryptotech[PEP_crypt_OpenPGP].send_key(session, pattern);
  1692 }
  1693 
  1694 DYNAMIC_API PEP_STATUS renew_key(
  1695         PEP_SESSION session,
  1696         const char *fpr,
  1697         const timestamp *ts
  1698     )
  1699 {
  1700     assert(session);
  1701     assert(fpr);
  1702 
  1703     if (!(session && fpr))
  1704         return PEP_ILLEGAL_VALUE;
  1705 
  1706     return session->cryptotech[PEP_crypt_OpenPGP].renew_key(session, fpr, ts);
  1707 }
  1708 
  1709 DYNAMIC_API PEP_STATUS revoke_key(
  1710         PEP_SESSION session,
  1711         const char *fpr,
  1712         const char *reason
  1713     )
  1714 {
  1715     assert(session);
  1716     assert(fpr);
  1717 
  1718     if (!(session && fpr))
  1719         return PEP_ILLEGAL_VALUE;
  1720 
  1721     return session->cryptotech[PEP_crypt_OpenPGP].revoke_key(session, fpr,
  1722             reason);
  1723 }
  1724 
  1725 DYNAMIC_API PEP_STATUS key_expired(
  1726         PEP_SESSION session,
  1727         const char *fpr,
  1728         const time_t when,
  1729         bool *expired
  1730     )
  1731 {
  1732     assert(session);
  1733     assert(fpr);
  1734     assert(expired);
  1735 
  1736     if (!(session && fpr && expired))
  1737         return PEP_ILLEGAL_VALUE;
  1738 
  1739     return session->cryptotech[PEP_crypt_OpenPGP].key_expired(session, fpr,
  1740             when, expired);
  1741 }
  1742 
  1743 DYNAMIC_API PEP_STATUS key_revoked(
  1744        PEP_SESSION session,
  1745        const char *fpr,
  1746        bool *revoked
  1747    )
  1748 {
  1749     assert(session);
  1750     assert(fpr);
  1751     assert(revoked);
  1752     
  1753     if (!(session && fpr && revoked))
  1754         return PEP_ILLEGAL_VALUE;
  1755     
  1756     return session->cryptotech[PEP_crypt_OpenPGP].key_revoked(session, fpr,
  1757             revoked);
  1758 }
  1759 
  1760 static void _clean_log_value(char *text)
  1761 {
  1762     if (text) {
  1763         for (char *c = text; *c; c++) {
  1764             if (*c < 32 && *c != '\n')
  1765                 *c = 32;
  1766             else if (*c == '"')
  1767                 *c = '\'';
  1768         }
  1769     }
  1770 }
  1771 
  1772 static char *_concat_string(char *str1, const char *str2, char delim)
  1773 {
  1774     str2 = str2 ? str2 : "";
  1775     size_t len1 = str1 ? strlen(str1) : 0;
  1776     size_t len2 = strlen(str2);
  1777     size_t len = len1 + len2 + 3;
  1778     char * result = realloc(str1, len + 1);
  1779 
  1780     if (result) {
  1781         result[len1] = '"';
  1782         strcpy(result + len1 + 1, str2);
  1783         result[len - 2] = '"';
  1784         result[len - 1] = delim;
  1785         result[len] = 0;
  1786     }
  1787     else {
  1788         free(str1);
  1789     }
  1790 
  1791     return result;
  1792 }
  1793 
  1794 DYNAMIC_API PEP_STATUS get_crashdump_log(
  1795         PEP_SESSION session,
  1796         int maxlines,
  1797         char **logdata
  1798     )
  1799 {
  1800     PEP_STATUS status = PEP_STATUS_OK;
  1801     char *_logdata= NULL;
  1802 
  1803     assert(session);
  1804     assert(maxlines >= 0 && maxlines <= CRASHDUMP_MAX_LINES);
  1805     assert(logdata);
  1806 
  1807     if (!(session && logdata && maxlines >= 0 && maxlines <=
  1808             CRASHDUMP_MAX_LINES))
  1809         return PEP_ILLEGAL_VALUE;
  1810 
  1811     *logdata = NULL;
  1812 
  1813     int limit = maxlines ? maxlines : CRASHDUMP_DEFAULT_LINES;
  1814     const char *timestamp = NULL;
  1815     const char *title = NULL;
  1816     const char *entity = NULL;
  1817     const char *desc = NULL;
  1818     const char *comment = NULL;
  1819 
  1820     sqlite3_reset(session->crashdump);
  1821     sqlite3_bind_int(session->crashdump, 1, limit);
  1822 
  1823     int result;
  1824 
  1825     do {
  1826         result = sqlite3_step(session->crashdump);
  1827         switch (result) {
  1828         case SQLITE_ROW:
  1829             timestamp = (const char *) sqlite3_column_text(session->crashdump,
  1830                     0);
  1831             title   = (const char *) sqlite3_column_text(session->crashdump,
  1832                     1);
  1833             entity  = (const char *) sqlite3_column_text(session->crashdump,
  1834                     2);
  1835             desc    = (const char *) sqlite3_column_text(session->crashdump,
  1836                     3);
  1837             comment = (const char *) sqlite3_column_text(session->crashdump,
  1838                     4);
  1839 
  1840             _logdata = _concat_string(_logdata, timestamp, ',');
  1841             if (_logdata == NULL)
  1842                 goto enomem;
  1843 
  1844             _logdata = _concat_string(_logdata, title, ',');
  1845             if (_logdata == NULL)
  1846                 goto enomem;
  1847 
  1848             _logdata = _concat_string(_logdata, entity, ',');
  1849             if (_logdata == NULL)
  1850                 goto enomem;
  1851 
  1852             _logdata = _concat_string(_logdata, desc, ',');
  1853             if (_logdata == NULL)
  1854                 goto enomem;
  1855 
  1856             _logdata = _concat_string(_logdata, comment, '\n');
  1857             if (_logdata == NULL)
  1858                 goto enomem;
  1859 
  1860             _clean_log_value(_logdata);
  1861             break;
  1862 
  1863         case SQLITE_DONE:
  1864             break;
  1865 
  1866         default:
  1867             status = PEP_UNKNOWN_ERROR;
  1868             result = SQLITE_DONE;
  1869         }
  1870     } while (result != SQLITE_DONE);
  1871 
  1872     sqlite3_reset(session->crashdump);
  1873     if (status == PEP_STATUS_OK)
  1874         *logdata = _logdata;
  1875 
  1876     goto the_end;
  1877 
  1878 enomem:
  1879     status = PEP_OUT_OF_MEMORY;
  1880 
  1881 the_end:
  1882     return status;
  1883 }
  1884 
  1885 DYNAMIC_API PEP_STATUS get_languagelist(
  1886         PEP_SESSION session,
  1887         char **languages
  1888     )
  1889 {
  1890     PEP_STATUS status = PEP_STATUS_OK;
  1891     char *_languages= NULL;
  1892 
  1893     assert(session);
  1894     assert(languages);
  1895 
  1896     if (!(session && languages))
  1897         return PEP_ILLEGAL_VALUE;
  1898 
  1899     *languages = NULL;
  1900 
  1901     const char *lang = NULL;
  1902     const char *name = NULL;
  1903     const char *phrase = NULL;
  1904 
  1905     sqlite3_reset(session->languagelist);
  1906 
  1907     int result;
  1908 
  1909     do {
  1910         result = sqlite3_step(session->languagelist);
  1911         switch (result) {
  1912         case SQLITE_ROW:
  1913             lang = (const char *) sqlite3_column_text(session->languagelist,
  1914                     0);
  1915             name = (const char *) sqlite3_column_text(session->languagelist,
  1916                     1);
  1917             phrase = (const char *) sqlite3_column_text(session->languagelist,
  1918                     2);
  1919 
  1920             _languages = _concat_string(_languages, lang, ',');
  1921             if (_languages == NULL)
  1922                 goto enomem;
  1923 
  1924             _languages = _concat_string(_languages, name, ',');
  1925             if (_languages == NULL)
  1926                 goto enomem;
  1927 
  1928             _languages = _concat_string(_languages, phrase, '\n');
  1929             if (_languages == NULL)
  1930                 goto enomem;
  1931 
  1932             break;
  1933 
  1934         case SQLITE_DONE:
  1935             break;
  1936 
  1937         default:
  1938             status = PEP_UNKNOWN_ERROR;
  1939             result = SQLITE_DONE;
  1940         }
  1941     } while (result != SQLITE_DONE);
  1942 
  1943     sqlite3_reset(session->languagelist);
  1944     if (status == PEP_STATUS_OK)
  1945         *languages = _languages;
  1946 
  1947     goto the_end;
  1948 
  1949 enomem:
  1950     status = PEP_OUT_OF_MEMORY;
  1951 
  1952 the_end:
  1953     return status;
  1954 }
  1955 
  1956 DYNAMIC_API PEP_STATUS get_phrase(
  1957         PEP_SESSION session,
  1958         const char *lang,
  1959         int phrase_id,
  1960         char **phrase
  1961     )
  1962 {
  1963     PEP_STATUS status = PEP_STATUS_OK;
  1964 
  1965     assert(session && lang && lang[0] && lang[1] && lang[2] == 0 && phrase);
  1966     if (!(session && lang && lang[0] && lang[1] && lang[2] == 0 && phrase))
  1967         return PEP_ILLEGAL_VALUE;
  1968 
  1969     *phrase = NULL;
  1970 
  1971     sqlite3_reset(session->i18n_token);
  1972     sqlite3_bind_text(session->i18n_token, 1, lang, -1, SQLITE_STATIC);
  1973     sqlite3_bind_int(session->i18n_token, 2, phrase_id);
  1974 
  1975     const char *_phrase = NULL;
  1976     int result;
  1977 
  1978     result = sqlite3_step(session->i18n_token);
  1979     switch (result) {
  1980     case SQLITE_ROW:
  1981         _phrase = (const char *) sqlite3_column_text(session->i18n_token, 0);
  1982         break;
  1983 
  1984     case SQLITE_DONE:
  1985         status = PEP_PHRASE_NOT_FOUND;
  1986         break;
  1987 
  1988     default:
  1989         status = PEP_UNKNOWN_ERROR;
  1990     }
  1991 
  1992     if (status == PEP_STATUS_OK) {
  1993         *phrase = strdup(_phrase);
  1994         if (*phrase == NULL)
  1995             goto enomem;
  1996     }
  1997 
  1998     sqlite3_reset(session->i18n_token);
  1999     goto the_end;
  2000 
  2001 enomem:
  2002     status = PEP_OUT_OF_MEMORY;
  2003 
  2004 the_end:
  2005     return status;
  2006 }
  2007 
  2008 static PEP_STATUS _get_sequence_value(PEP_SESSION session, const char *name,
  2009         int32_t *value)
  2010 {
  2011     assert(session && name && value);
  2012     if (!(session && name && value))
  2013         return PEP_ILLEGAL_VALUE;
  2014 
  2015     PEP_STATUS status = PEP_STATUS_OK;
  2016 
  2017     sqlite3_reset(session->sequence_value2);
  2018     sqlite3_bind_text(session->sequence_value2, 1, name, -1,
  2019             SQLITE_STATIC);
  2020     int result = sqlite3_step(session->sequence_value2);
  2021     switch (result) {
  2022         case SQLITE_ROW: {
  2023             int32_t _value = (int32_t)
  2024                     sqlite3_column_int(session->sequence_value2, 0);
  2025             int _own = (int)
  2026                     sqlite3_column_int(session->sequence_value2, 1);
  2027             *value = _value;
  2028             if (_own)
  2029                 status = PEP_OWN_SEQUENCE;
  2030             break;
  2031         }
  2032         case SQLITE_DONE:
  2033             status = PEP_RECORD_NOT_FOUND;
  2034             break;
  2035         default:
  2036             status = PEP_UNKNOWN_ERROR;
  2037     }
  2038     sqlite3_reset(session->sequence_value2);
  2039 
  2040     return status;
  2041 }
  2042 
  2043 static PEP_STATUS _increment_sequence_value(PEP_SESSION session,
  2044         const char *name, int own)
  2045 {
  2046     assert(session && name);
  2047     if (!(session && name))
  2048         return PEP_ILLEGAL_VALUE;
  2049 
  2050     sqlite3_reset(session->sequence_value1);
  2051     sqlite3_bind_text(session->sequence_value1, 1, name, -1, SQLITE_STATIC);
  2052     sqlite3_bind_int(session->sequence_value1, 2, own);
  2053     int result = sqlite3_step(session->sequence_value1);
  2054     assert(result == SQLITE_DONE);
  2055     sqlite3_reset(session->sequence_value1);
  2056     if (result == SQLITE_DONE)
  2057         return PEP_STATUS_OK;
  2058     else
  2059         return PEP_CANNOT_INCREASE_SEQUENCE;
  2060 }
  2061 
  2062 static PEP_STATUS _set_sequence_value(PEP_SESSION session,
  2063         const char *name, int32_t value, int own)
  2064 {
  2065     assert(session && name && value > 0);
  2066     if (!(session && name && value > 0))
  2067         return PEP_ILLEGAL_VALUE;
  2068 
  2069     sqlite3_reset(session->sequence_value3);
  2070     sqlite3_bind_text(session->sequence_value3, 1, name, -1, SQLITE_STATIC);
  2071     sqlite3_bind_int(session->sequence_value3, 2, value);
  2072     sqlite3_bind_int(session->sequence_value3, 3, own);
  2073     int result = sqlite3_step(session->sequence_value3);
  2074     assert(result == SQLITE_DONE);
  2075     sqlite3_reset(session->sequence_value3);
  2076     if (result == SQLITE_DONE)
  2077         return PEP_STATUS_OK;
  2078     else
  2079         return PEP_CANNOT_SET_SEQUENCE_VALUE;
  2080 }
  2081 
  2082 DYNAMIC_API PEP_STATUS sequence_value(
  2083         PEP_SESSION session,
  2084         char *name,
  2085         int32_t *value
  2086     )
  2087 {
  2088     PEP_STATUS status = PEP_STATUS_OK;
  2089 
  2090     assert(session);
  2091     assert(name && value && *value >= 0);
  2092 
  2093     if (!(session && name && value && *value >= 0))
  2094         return PEP_ILLEGAL_VALUE;
  2095 
  2096     int own = 0;
  2097     if (!name[0]) {
  2098         pEpUUID uuid;
  2099         uuid_generate_random(uuid);
  2100         uuid_unparse_upper(uuid, name);
  2101         own = 1;
  2102     }
  2103     else {
  2104         if (name == session->sync_uuid || strcmp(name, session->sync_uuid) == 0)
  2105             own = 1;
  2106     }
  2107 
  2108     if (*value) {
  2109         int32_t old_value = 0;
  2110         status = _get_sequence_value(session, name, &old_value);
  2111         if (status != PEP_STATUS_OK && status != PEP_RECORD_NOT_FOUND)
  2112             return status;
  2113 
  2114         if (old_value >= *value) {
  2115             return PEP_SEQUENCE_VIOLATED;
  2116         }
  2117         else {
  2118             status = _set_sequence_value(session, name, *value, own);
  2119             return status;
  2120         }
  2121     }
  2122 
  2123     assert(*value == 0);
  2124     status = _increment_sequence_value(session, name, own);
  2125     if (status == PEP_STATUS_OK) {
  2126         status = _get_sequence_value(session, name, value);
  2127         assert(*value < INT32_MAX);
  2128         if (*value == INT32_MAX)
  2129             return PEP_CANNOT_INCREASE_SEQUENCE;
  2130     }
  2131     return status;
  2132 }
  2133 
  2134 DYNAMIC_API PEP_STATUS set_revoked(
  2135        PEP_SESSION session,
  2136        const char *revoked_fpr,
  2137        const char *replacement_fpr,
  2138        const uint64_t revocation_date
  2139     )
  2140 {
  2141     PEP_STATUS status = PEP_STATUS_OK;
  2142     
  2143     assert(session &&
  2144            revoked_fpr && revoked_fpr[0] &&
  2145            replacement_fpr && replacement_fpr[0]
  2146           );
  2147     
  2148     if (!(session &&
  2149           revoked_fpr && revoked_fpr[0] &&
  2150           replacement_fpr && replacement_fpr[0]
  2151          ))
  2152         return PEP_ILLEGAL_VALUE;
  2153     
  2154     sqlite3_reset(session->set_revoked);
  2155     sqlite3_bind_text(session->set_revoked, 1, revoked_fpr, -1, SQLITE_STATIC);
  2156     sqlite3_bind_text(session->set_revoked, 2, replacement_fpr, -1,
  2157             SQLITE_STATIC);
  2158     sqlite3_bind_int64(session->set_revoked, 3, revocation_date);
  2159 
  2160     int result;
  2161     
  2162     result = sqlite3_step(session->set_revoked);
  2163     switch (result) {
  2164         case SQLITE_DONE:
  2165             status = PEP_STATUS_OK;
  2166             break;
  2167             
  2168         default:
  2169             status = PEP_UNKNOWN_ERROR;
  2170     }
  2171     
  2172     sqlite3_reset(session->set_revoked);
  2173     return status;
  2174 }
  2175 
  2176 DYNAMIC_API PEP_STATUS get_revoked(
  2177         PEP_SESSION session,
  2178         const char *fpr,
  2179         char **revoked_fpr,
  2180         uint64_t *revocation_date
  2181     )
  2182 {
  2183     PEP_STATUS status = PEP_STATUS_OK;
  2184 
  2185     assert(session &&
  2186            revoked_fpr &&
  2187            fpr && fpr[0]
  2188           );
  2189     
  2190     if (!(session &&
  2191            revoked_fpr &&
  2192            fpr && fpr[0]
  2193           ))
  2194         return PEP_ILLEGAL_VALUE;
  2195 
  2196     *revoked_fpr = NULL;
  2197     *revocation_date = 0;
  2198 
  2199     sqlite3_reset(session->get_revoked);
  2200     sqlite3_bind_text(session->get_revoked, 1, fpr, -1, SQLITE_STATIC);
  2201 
  2202     int result;
  2203     
  2204     result = sqlite3_step(session->get_revoked);
  2205     switch (result) {
  2206         case SQLITE_ROW: {
  2207             *revoked_fpr = strdup((const char *)
  2208                     sqlite3_column_text(session->get_revoked, 0));
  2209             if(*revoked_fpr)
  2210                 *revocation_date = sqlite3_column_int64(session->get_revoked,
  2211                         1);
  2212             else
  2213                 status = PEP_OUT_OF_MEMORY;
  2214 
  2215             break;
  2216         }
  2217         default:
  2218             status = PEP_CANNOT_FIND_IDENTITY;
  2219     }
  2220 
  2221     sqlite3_reset(session->get_revoked);
  2222 
  2223     return status;
  2224 }
  2225 
  2226 PEP_STATUS key_created(
  2227         PEP_SESSION session,
  2228         const char *fpr,
  2229         time_t *created
  2230     )
  2231 {
  2232     assert(session && fpr && created);
  2233     if (!(session && fpr && created))
  2234         return PEP_ILLEGAL_VALUE;
  2235 
  2236     return session->cryptotech[PEP_crypt_OpenPGP].key_created(session, fpr,
  2237             created);
  2238 }
  2239 
  2240 PEP_STATUS find_private_keys(PEP_SESSION session, const char* pattern,
  2241                              stringlist_t **keylist) {
  2242     assert(session && pattern && keylist);
  2243     if (!(session && pattern && keylist))
  2244         return PEP_ILLEGAL_VALUE;
  2245     
  2246     return session->cryptotech[PEP_crypt_OpenPGP].find_private_keys(session, pattern,
  2247                                                                     keylist);
  2248 }
  2249 
  2250 DYNAMIC_API const char* get_engine_version() {
  2251     return PEP_ENGINE_VERSION;
  2252 }
  2253 
  2254 
  2255 DYNAMIC_API PEP_STATUS reset_peptest_hack(PEP_SESSION session)
  2256 {
  2257     assert(session);
  2258 
  2259     if (!session)
  2260         return PEP_ILLEGAL_VALUE;
  2261 
  2262     int int_result = sqlite3_exec(
  2263         session->db,
  2264         "delete from identity where address like '%@peptest.ch' ;",
  2265         NULL,
  2266         NULL,
  2267         NULL
  2268     );
  2269     assert(int_result == SQLITE_OK);
  2270 
  2271     return PEP_STATUS_OK;
  2272 }