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