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