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