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