src/pEpEngine.c
author Edouard Tisserant <edouard@pep-project.org>
Tue, 15 Nov 2016 15:56:18 +0100
branchENGINE-140-reloaded
changeset 1394 8659157b681f
parent 1393 ee4bf9e19635
child 1395 c999b8c26dd1
permissions -rw-r--r--
ENGINE-140 #comment Added own_keys table, linking pgp_keypair to identity in case user_id = PEP_OWN_USERID.
Added related set_own_key and own_keys_retieve.
Updated set_identity, set_identity_flags and added unset_identity_flags, all doing bitwise logic to untouched keep flags accross calls.
Removed keys_retrieve_by_flag and PEP_kpf_own_key, now replaced by own_keys table.
Removed duplicated code seting _DDL_USER_VERSION in manageent DB.
Removed exists_empty_fpr_entry update_fprless_identity, and corresponding logic in set_identity()

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