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