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