src/pEpEngine.c
author Krista Bennett <krista@pep-project.org>
Fri, 15 Dec 2017 12:49:03 +0100
branchENGINE-289
changeset 2317 b80dd91c8869
parent 2311 688b925c3e73
child 2324 de5b5578fc16
permissions -rw-r--r--
ENGINE-320: intermittent commit
     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 
    10 #include <time.h>
    11 #include <stdlib.h>
    12 
    13 static volatile int init_count = -1;
    14 
    15 // sql overloaded functions - modified from sqlite3.c
    16 static void _sql_lower(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
    17     char *z1;
    18     const char *z2;
    19     int i, n;
    20     z2 = (char*)sqlite3_value_text(argv[0]);
    21     n = sqlite3_value_bytes(argv[0]);
    22     /* Verify that the call to _bytes() does not invalidate the _text() pointer */
    23     assert( z2==(char*)sqlite3_value_text(argv[0]) );
    24     if( z2 ){
    25         z1 = (char*)sqlite3_malloc(n+1);
    26         if( z1 ){
    27             for(i=0; i<n; i++){
    28                 char c = z2[i];
    29                 char c_mod = c | 0x20;
    30                 if (c_mod < 0x61 || c_mod > 0x7a)
    31                     c_mod = c;
    32                 z1[i] = c_mod;
    33             }
    34             z1[n] = '\0';
    35             sqlite3_result_text(ctx, z1, n, sqlite3_free);
    36         }
    37     }
    38 }
    39 
    40 
    41 // sql manipulation statements
    42 static const char *sql_log = 
    43     "insert into log (title, entity, description, comment)"
    44      "values (?1, ?2, ?3, ?4);";
    45 
    46 static const char *sql_trustword = 
    47     "select id, word from wordlist where lang = lower(?1) "
    48     "and id = ?2 ;";
    49 
    50 static const char *sql_get_identity =  
    51     "select fpr, username, comm_type, lang,"
    52     "   identity.flags | pgp_keypair.flags,"
    53     "   is_own"
    54     "   from identity"
    55     "   join person on id = identity.user_id"
    56     "   join pgp_keypair on fpr = identity.main_key_id"
    57     "   join trust on id = trust.user_id"
    58     "       and pgp_keypair_fpr = identity.main_key_id"    
    59     "   where (case when (address = ?1) then (1)"
    60     "               when (lower(address) = lower(?1)) then (1)"
    61     "               when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)"
    62     "               else 0"
    63     "          end) = 1"
    64     "   and identity.user_id = ?2;";
    65 
    66 static const char *sql_get_identity_without_fpr =  
    67     "select main_key_id, username, comm_type, lang,"
    68     "   identity.flags, is_own"
    69     "   from identity"
    70     "   join person on id = identity.user_id"
    71     "   where (case when (address = ?1) then (1)"
    72     "               when (lower(address) = lower(?1)) then (1)"
    73     "               when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)"
    74     "               else 0"
    75     "          end) = 1"
    76     "   and identity.user_id = ?2;";
    77 
    78 static const char *sql_get_identities_by_address =  
    79     "select main_key_id, username, comm_type, lang,"
    80     "   identity.flags, is_own"
    81     "   from identity"
    82     "   where (case when (address = ?1) then (1)"
    83     "               when (lower(address) = lower(?1)) then (1)"
    84     "               when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)"
    85     "               else 0"
    86     "          end) = 1;";
    87 
    88 static const char *sql_replace_identities_fpr =  
    89     "update identity"
    90     "   set main_key_id = ?1 "
    91     "   where main_key_id = ?2 ;";
    92 
    93 // Set person, but if already exist, only update.
    94 // if main_key_id already set, don't touch.
    95 static const char *sql_set_person = 
    96     "insert or replace into person (id, username, lang, main_key_id, device_group)"
    97     "  values (?1, ?2, ?3,"
    98     "    (select coalesce((select main_key_id from person "
    99     "      where id = ?1), upper(replace(?4,' ','')))),"
   100     "    (select device_group from person where id = ?1)) ;";
   101 
   102 static const char *sql_set_device_group = 
   103     "update person set device_group = ?1 "
   104     "where id = ?2;";
   105 
   106 static const char *sql_get_device_group = 
   107     "select device_group from person "
   108     "where id = ?1;";
   109 
   110 static const char *sql_set_pgp_keypair = 
   111     "insert or replace into pgp_keypair (fpr) "
   112     "values (upper(replace(?1,' ',''))) ;";
   113 
   114 static const char *sql_set_identity = 
   115     "insert or replace into identity ("
   116     " address, main_key_id, "
   117     " user_id, flags, is_own"
   118     ") values ("
   119     " ?1,"
   120     " upper(replace(?2,' ','')),"
   121     " ?3,"
   122     // " (select"
   123     // "   coalesce("
   124     // "    (select flags from identity"
   125     // "     where address = ?1 and"
   126     // "           user_id = ?3),"
   127     // "    0)"
   128     // " ) | (?4 & 255)"
   129     /* set_identity ignores previous flags, and doesn't filter machine flags */
   130     " ?4,"
   131     " ?5"
   132     ");";
   133         
   134 static const char *sql_set_identity_flags = 
   135     "update identity set flags = "
   136     "    ((?1 & 255) | (select flags from identity"
   137     "                   where address = ?2 and user_id = ?3)) "
   138     "where address = ?2 and user_id = ?3 ;";
   139 
   140 static const char *sql_unset_identity_flags = 
   141     "update identity set flags = "
   142     "    ( ~(?1 & 255) & (select flags from identity"
   143     "                   where address = ?2 and user_id = ?3)) "
   144     "where address = ?2 and user_id = ?3 ;";
   145 
   146 static const char *sql_set_trust =
   147     "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type) "
   148     "values (?1, upper(replace(?2,' ','')), ?3) ;";
   149 
   150 static const char *sql_update_trust_for_fpr =
   151     "update trust "
   152     "set comm_type = ?1 "
   153     "where pgp_keypair_fpr = upper(replace(?2,' ','')) ;";
   154 
   155 static const char *sql_get_trust = 
   156     "select comm_type from trust where user_id = ?1 "
   157     "and pgp_keypair_fpr = upper(replace(?2,' ','')) ;";
   158 
   159 static const char *sql_least_trust = 
   160     "select min(comm_type) from trust where"
   161     " pgp_keypair_fpr = upper(replace(?1,' ',''))"
   162     " and comm_type != 0;"; // ignores PEP_ct_unknown
   163     // returns PEP_ct_unknown only when no known trust is recorded
   164 
   165 static const char *sql_mark_as_compromized = 
   166     "update trust not indexed set comm_type = 15"
   167     " where pgp_keypair_fpr = upper(replace(?1,' ','')) ;";
   168 
   169 static const char *sql_crashdump = 
   170     "select timestamp, title, entity, description, comment"
   171     " from log order by timestamp desc limit ?1 ;";
   172 
   173 static const char *sql_languagelist = 
   174     "select i18n_language.lang, name, phrase" 
   175     " from i18n_language join i18n_token using (lang) where i18n_token.id = 1000;" ;
   176 
   177 static const char *sql_i18n_token = 
   178     "select phrase from i18n_token where lang = lower(?1) and id = ?2 ;";
   179 
   180 // This will cascade to identity and trust
   181 static const char* sql_replace_userid =
   182     "update id from person"
   183     "   set id = ?1"
   184     "   where id = ?2;";
   185 
   186 // blacklist
   187 static const char *sql_blacklist_add = 
   188     "insert or replace into blacklist_keys (fpr) values (upper(replace(?1,' ',''))) ;"
   189     "delete from identity where main_key_id = upper(replace(?1,' ','')) ;"
   190     "delete from pgp_keypair where fpr = upper(replace(?1,' ','')) ;";
   191 
   192 static const char *sql_blacklist_delete =
   193     "delete from blacklist_keys where fpr = upper(replace(?1,' ','')) ;";
   194 
   195 static const char *sql_blacklist_is_listed = 
   196     "select count(*) from blacklist_keys where fpr = upper(replace(?1,' ','')) ;";
   197 
   198 static const char *sql_blacklist_retrieve = 
   199     "select * from blacklist_keys ;";
   200                 
   201 
   202 // Own keys
   203 // We only care if it's 0 or non-zero
   204 static const char *sql_own_key_is_listed = 
   205     "select count(*) from ("
   206     "   select pgp_keypair_fpr from trust"
   207     "      join identity on trust.user_id = identity.user_id"
   208     "      where pgp_keypair_fpr = upper(replace(?1,' ',''))"
   209     "           and identity.is_own = 1"
   210     ");";
   211 
   212 static const char *sql_own_identities_retrieve =  
   213     "select address, fpr, username, identity.user_id, "
   214     "   lang, identity.flags | pgp_keypair.flags"
   215     "   from identity"
   216     "   join person on id = identity.user_id"
   217     "   join pgp_keypair on fpr = identity.main_key_id"
   218     "   join trust on id = trust.user_id"
   219     "       and pgp_keypair_fpr = identity.main_key_id"
   220     "   where identity.is_own = 1"
   221     "       and (identity.flags & ?1) = 0;";
   222 
   223 static const char *sql_own_keys_retrieve = 
   224     "select pgp_keypair_fpr from trust"
   225     "   join identity on trust.user_id = identity.user_id"
   226     "   where identity.is_own = 1";
   227 
   228 static const char* sql_get_user_default_key =
   229     "select main_key_id from person" 
   230     "   where id = ?1;";
   231 
   232 static const char* sql_get_own_userid =
   233     "select id from person"
   234     "   join identity on id = identity.user_id"
   235     "   where identity.is_own = 1";
   236 
   237 // Sequence
   238 static const char *sql_sequence_value1 = 
   239     "insert or replace into sequences (name, value, own) "
   240     "values (?1, "
   241     "       (select coalesce((select value + 1 from sequences "
   242     "           where name = ?1), 1 )), "
   243     "       (select coalesce((select own or ?2 from sequences "
   244     "           where name = ?1), ?2))) ; ";
   245 
   246 static const char *sql_sequence_value2 = 
   247     "select value, own from sequences where name = ?1 ;";
   248 
   249 static const char *sql_sequence_value3 = 
   250     "insert or replace into sequences (name, value, own) "
   251     "values (?1, "
   252     "        ?2, "
   253     "       (select coalesce((select own or ?3 from sequences "
   254     "           where name = ?1), ?3))) ; ";
   255         
   256 // Revocation tracking
   257 static const char *sql_set_revoked =
   258     "insert or replace into revoked_keys ("
   259     "    revoked_fpr, replacement_fpr, revocation_date) "
   260     "values (upper(replace(?1,' ','')),"
   261     "        upper(replace(?2,' ','')),"
   262     "        ?3) ;";
   263         
   264 static const char *sql_get_revoked = 
   265     "select revoked_fpr, revocation_date from revoked_keys"
   266     "    where replacement_fpr = upper(replace(?1,' ','')) ;";
   267 
   268 static int user_version(void *_version, int count, char **text, char **name)
   269 {
   270     assert(_version);
   271     assert(count == 1);
   272     assert(text && text[0]);
   273     if (!(_version && count == 1 && text && text[0]))
   274         return -1;
   275 
   276     int *version = (int *) _version;
   277     *version = atoi(text[0]);
   278     return 0;
   279 }
   280 
   281 static int table_contains_column(PEP_SESSION session, const char* table_name,
   282                                                       const char* col_name) {
   283 
   284 
   285     if (!session || !table_name || !col_name)
   286         return -1;
   287         
   288     // Table names can't be SQL parameters, so we do it this way.
   289     
   290     // these two must be the same number.
   291     char sql_buf[500];
   292     const size_t max_q_len = 500;
   293     
   294     size_t t_size, c_size, q_size;
   295     
   296     const char* q1 = "SELECT "; // 7
   297     const char* q2 = " from "; // 6
   298     const char* q3 = ";";       // 1
   299     
   300     q_size = 14;
   301     t_size = strlen(table_name);
   302     c_size = strlen(col_name);
   303     
   304     size_t query_len = q_size + c_size + t_size + 1;
   305     
   306     if (query_len > max_q_len)
   307         return -1;
   308 
   309     strlcpy(sql_buf, q1, max_q_len);
   310     strlcat(sql_buf, col_name, max_q_len);
   311     strlcat(sql_buf, q2, max_q_len);
   312     strlcat(sql_buf, table_name, max_q_len);
   313     strlcat(sql_buf, q3, max_q_len);
   314 
   315     sqlite3_stmt *stmt; 
   316 
   317     sqlite3_prepare_v2(session->db, sql_buf, -1, &stmt, NULL);
   318 
   319     int retval = 0;
   320 
   321     int rc = sqlite3_step(stmt);  
   322     if (rc == SQLITE_DONE || rc == SQLITE_OK || rc == SQLITE_ROW) {
   323         retval = 1;
   324     }
   325 
   326     sqlite3_finalize(stmt);      
   327         
   328     return retval;
   329 }
   330 
   331 DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
   332 {
   333     PEP_STATUS status = PEP_STATUS_OK;
   334     int int_result;
   335     
   336     bool in_first = false;
   337     bool very_first = false;
   338 
   339     assert(sqlite3_threadsafe());
   340     if (!sqlite3_threadsafe())
   341         return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
   342 
   343     // a little race condition - but still a race condition
   344     // mitigated by calling caveat (see documentation)
   345 
   346     // this increment is made atomic IN THE ADAPTERS by
   347     // guarding the call to init with the appropriate mutex.
   348     int _count = ++init_count;
   349     if (_count == 0)
   350         in_first = true;
   351     
   352     // Race condition mitigated by calling caveat starts here :
   353     // If another call to init() preempts right now, then preemptive call
   354     // will have in_first false, will not create SQL tables, and following
   355     // calls relying on those tables will fail.
   356     //
   357     // Therefore, as above, adapters MUST guard init() with a mutex.
   358     // 
   359     // Therefore, first session
   360     // is to be created and last session to be deleted alone, and not
   361     // concurently to other sessions creation or deletion.
   362     // We expect adapters to enforce this either by implicitely creating a
   363     // client session, or by using synchronization primitive to protect
   364     // creation/deletion of first/last session from the app.
   365 
   366     assert(session);
   367     if (session == NULL)
   368         return PEP_ILLEGAL_VALUE;
   369 
   370     *session = NULL;
   371 
   372     pEpSession *_session = calloc(1, sizeof(pEpSession));
   373     assert(_session);
   374     if (_session == NULL)
   375         goto enomem;
   376 
   377     _session->version = PEP_ENGINE_VERSION;
   378 
   379 #ifdef DEBUG_ERRORSTACK
   380     _session->errorstack = new_stringlist("init()");
   381 #endif
   382 
   383     assert(LOCAL_DB);
   384     if (LOCAL_DB == NULL) {
   385         status = PEP_INIT_CANNOT_OPEN_DB;
   386         goto pep_error;
   387     }
   388 
   389     int_result = sqlite3_open_v2(
   390             LOCAL_DB,
   391             &_session->db,
   392             SQLITE_OPEN_READWRITE
   393                 | SQLITE_OPEN_CREATE
   394                 | SQLITE_OPEN_FULLMUTEX
   395                 | SQLITE_OPEN_PRIVATECACHE,
   396             NULL 
   397         );
   398 
   399     if (int_result != SQLITE_OK) {
   400         status = PEP_INIT_CANNOT_OPEN_DB;
   401         goto pep_error;
   402     }
   403 
   404     int_result = sqlite3_exec(
   405             _session->db,
   406             "PRAGMA locking_mode=NORMAL;\n"
   407             "PRAGMA journal_mode=WAL;\n",
   408             NULL,
   409             NULL,
   410             NULL
   411         );
   412 
   413 
   414     sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME);
   415 
   416     assert(SYSTEM_DB);
   417     if (SYSTEM_DB == NULL) {
   418         status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
   419         goto pep_error;
   420     }
   421 
   422     int_result = sqlite3_open_v2(
   423             SYSTEM_DB, &_session->system_db,
   424             SQLITE_OPEN_READONLY
   425                 | SQLITE_OPEN_FULLMUTEX
   426                 | SQLITE_OPEN_SHAREDCACHE,
   427             NULL
   428         );
   429 
   430     if (int_result != SQLITE_OK) {
   431         status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
   432         goto pep_error;
   433     }
   434 
   435     sqlite3_busy_timeout(_session->system_db, 1000);
   436 
   437 // increment this when patching DDL
   438 #define _DDL_USER_VERSION "6"
   439 
   440     if (in_first) {
   441 
   442         int_result = sqlite3_exec(
   443             _session->db,
   444                 "create table if not exists version_info (\n"
   445                 "   id integer primary key,\n"
   446                 "   timestamp integer default (datetime('now')),\n"
   447                 "   version text,\n"
   448                 "   comment text\n"
   449                 ");\n",
   450                 NULL,
   451                 NULL,
   452                 NULL
   453         );
   454         int_result = sqlite3_exec(
   455             _session->db,
   456                 "PRAGMA application_id = 0x23423423;\n"
   457                 "create table if not exists log (\n"
   458                 "   timestamp integer default (datetime('now')),\n"
   459                 "   title text not null,\n"
   460                 "   description text,\n"
   461                 "   entity text not null,\n"
   462                 "   comment text\n"
   463                 ");\n"
   464                 "create index if not exists log_timestamp on log (\n"
   465                 "   timestamp\n"
   466                 ");\n"
   467                 "create table if not exists pgp_keypair (\n"
   468                 "   fpr text primary key,\n"
   469                 "   created integer,\n"
   470                 "   expires integer,\n"
   471                 "   comment text,\n"
   472                 "   flags integer default 0\n"
   473                 ");\n"
   474                 "create index if not exists pgp_keypair_expires on pgp_keypair (\n"
   475                 "   expires\n"
   476                 ");\n"
   477                 "create table if not exists person (\n"
   478                 "   id text primary key,\n"
   479                 "   username text not null,\n"
   480                 "   main_key_id text\n"
   481                 "       references pgp_keypair (fpr)\n"
   482                 "       on delete set null,\n"
   483                 "   lang text,\n"
   484                 "   comment text,\n"
   485                 "   device_group text\n"
   486                 ");\n"
   487                 "create table if not exists identity (\n"
   488                 "   address text,\n"
   489                 "   user_id text\n"
   490                 "       references person (id)\n"
   491                 "       on delete cascade on update cascade,\n"
   492                 "   main_key_id text\n"
   493                 "       references pgp_keypair (fpr)\n"
   494                 "       on delete set null,\n"
   495                 "   comment text,\n"
   496                 "   flags integer default 0,\n"
   497                 "   is_own integer default 0,\n"
   498                 "   primary key (address, user_id)\n"
   499                 ");\n"
   500                 "create table if not exists trust (\n"
   501                 "   user_id text not null\n"
   502                 "       references person (id)\n"
   503                 "       on delete cascade on update cascade,\n"
   504                 "   pgp_keypair_fpr text not null\n"
   505                 "       references pgp_keypair (fpr)\n"
   506                 "       on delete cascade,\n"
   507                 "   comm_type integer not null,\n"
   508                 "   comment text,\n"
   509                 "   primary key (user_id, pgp_keypair_fpr)\n"
   510                 ");\n"
   511                 // blacklist
   512                 "create table if not exists blacklist_keys (\n"
   513                 "   fpr text primary key\n"
   514                 ");\n"
   515                 // sequences
   516                 "create table if not exists sequences(\n"
   517                 "   name text primary key,\n"
   518                 "   value integer default 0,\n"
   519                 "   own integer default 0\n"
   520                 ");\n"
   521                 "create table if not exists revoked_keys (\n"
   522                 "   revoked_fpr text primary key,\n"
   523                 "   replacement_fpr text not null\n"
   524                 "       references pgp_keypair (fpr)\n"
   525                 "       on delete cascade,\n"
   526                 "   revocation_date integer\n"
   527                 ");\n"
   528                 ,
   529             NULL,
   530             NULL,
   531             NULL
   532         );
   533         assert(int_result == SQLITE_OK);
   534 
   535         int version;
   536         int_result = sqlite3_exec(
   537             _session->db,
   538             "pragma user_version;",
   539             user_version,
   540             &version,
   541             NULL
   542         );
   543 
   544         assert(int_result == SQLITE_OK);
   545         
   546         void (*xFunc_lower)(sqlite3_context*,int,sqlite3_value**) = &_sql_lower;
   547         
   548         int_result = sqlite3_create_function_v2(
   549             _session->db,
   550             "lower",
   551             1,
   552             SQLITE_UTF8 | SQLITE_DETERMINISTIC,
   553             NULL,
   554             xFunc_lower,
   555             NULL,
   556             NULL,
   557             NULL);
   558         assert(int_result == SQLITE_OK);
   559         
   560         // Sometimes the user_version wasn't set correctly. Check to see if this
   561         // is really necessary...
   562         if (version == 1) {
   563             bool version_changed = true;
   564             
   565             if (table_contains_column(_session, "identity", "is_own") > 0) {
   566                 version = 6;
   567             }
   568             else if (table_contains_column(_session, "sequences", "own") > 0) {
   569                 version = 3;
   570             }
   571             else if (table_contains_column(_session, "pgp_keypair", "flags") > 0) {
   572                 version = 2;
   573             }
   574             else {
   575                 version_changed = false;
   576             }
   577             
   578             if (version_changed) {
   579                 // set it in the DB, finally. Yeesh.
   580                 char verbuf[21]; // enough digits for a max-sized 64 bit int, cmon. 
   581                 sprintf(verbuf,"%d",version);
   582                 
   583                 size_t query_size = strlen(verbuf) + 25;
   584                 char* query = calloc(query_size, 1);
   585                 
   586                 strlcpy(query, "pragma user_version = ", query_size);
   587                 strlcat(query, verbuf, query_size);
   588                 strlcat(query, ";", query_size);
   589                 
   590                 int_result = sqlite3_exec(
   591                     _session->db,
   592                     query,
   593                     user_version,
   594                     &version,
   595                     NULL
   596                 );
   597                 free(query);
   598             }
   599         }
   600 
   601 
   602         if(version != 0) { 
   603             // Version has been already set
   604 
   605             // Early mistake : version 0 shouldn't have existed.
   606             // Numbering should have started at 1 to detect newly created DB.
   607             // Version 0 DBs are not anymore compatible.
   608 
   609             // // Was version 0 compat code.
   610             // if (version < 1) {
   611             //     int_result = sqlite3_exec(
   612             //         _session->db,
   613             //         "alter table identity\n"
   614             //         "   add column flags integer default 0;\n",
   615             //         NULL,
   616             //         NULL,
   617             //         NULL
   618             //     );
   619             //     assert(int_result == SQLITE_OK);
   620             // }
   621             
   622             if (version < 2) {
   623                 int_result = sqlite3_exec(
   624                     _session->db,
   625                     "alter table pgp_keypair\n"
   626                     "   add column flags integer default 0;\n"
   627                     "alter table person\n"
   628                     "   add column device_group text;\n",
   629                     NULL,
   630                     NULL,
   631                     NULL
   632                 );
   633                 assert(int_result == SQLITE_OK);
   634             }
   635 
   636             if (version < 3) {
   637                 int_result = sqlite3_exec(
   638                     _session->db,
   639                     "alter table sequences\n"
   640                     "   add column own integer default 0;\n",
   641                     NULL,
   642                     NULL,
   643                     NULL
   644                 );
   645                 assert(int_result == SQLITE_OK);
   646             }
   647 
   648             if (version < 5) {
   649                 int_result = sqlite3_exec(
   650                     _session->db,
   651                     "delete from pgp_keypair where fpr = '';",
   652                     NULL,
   653                     NULL,
   654                     NULL
   655                 );
   656                 assert(int_result == SQLITE_OK);
   657                 int_result = sqlite3_exec(
   658                     _session->db,
   659                     "delete from trust where pgp_keypair_fpr = '';",
   660                     NULL,
   661                     NULL,
   662                     NULL
   663                 );
   664                 assert(int_result == SQLITE_OK);
   665             }
   666             
   667             if (version < 6) {
   668                 int_result = sqlite3_exec(
   669                     _session->db,
   670                     "alter table identity\n"
   671                     "   add column is_own integer default 0;\n",
   672                     NULL,
   673                     NULL,
   674                     NULL
   675                 );
   676                 assert(int_result == SQLITE_OK);                
   677                 int_result = sqlite3_exec(
   678                     _session->db,
   679                     "update identity\n"
   680                     "   set is_own = 1\n"
   681                     "   where (user_id = '" PEP_OWN_USERID "');\n",
   682                     NULL,
   683                     NULL,
   684                     NULL
   685                 );
   686                 assert(int_result == SQLITE_OK);    
   687 
   688                 // Turns out that just adding "on update cascade" in
   689                 // sqlite is a PITA. We need to be able to cascade
   690                 // person->id replacements (for temp ids like "TOFU_")
   691                 // so here we go...
   692                 int_result = sqlite3_exec(
   693                     "PRAGMA foreign_keys=off;\n"
   694                     "BEGIN TRANSACTION;\n"
   695                     "ALTER TABLE identity RENAME TO _identity_old;\n"
   696                     "create table identity (\n"
   697                     "   address text,\n"
   698                     "   user_id text\n"
   699                     "       references person (id)\n"
   700                     "       on delete cascade on update cascade,\n"
   701                     "   main_key_id text\n"
   702                     "       references pgp_keypair (fpr)\n"
   703                     "       on delete set null,\n"
   704                     "   comment text,\n"
   705                     "   flags integer default 0,\n"
   706                     "   is_own integer default 0,\n"
   707                     "   primary key (address, user_id)\n"
   708                     ");\n"
   709                     "INSERT INTO identity SELECT * FROM _identity_old;\n"
   710                     "DROP TABLE _identity_old;\n"
   711                     "ALTER TABLE trust RENAME TO _trust_old;\n"
   712                     "create table trust (\n"
   713                     "   user_id text not null\n"
   714                     "       references person (id)\n"
   715                     "       on delete cascade on update cascade,\n"
   716                     "   pgp_keypair_fpr text not null\n"
   717                     "       references pgp_keypair (fpr)\n"
   718                     "       on delete cascade,\n"
   719                     "   comm_type integer not null,\n"
   720                     "   comment text,\n"
   721                     "   primary key (user_id, pgp_keypair_fpr)\n"
   722                     ");\n"
   723                     "INSERT INTO trust SELECT * FROM _trust_old;\n"
   724                     "DROP TABLE _trust_old;\n"
   725                     "COMMIT;\n"
   726                     "\n"
   727                     "PRAGMA foreign_keys=on;\n",
   728                     NULL,
   729                     NULL,
   730                     NULL
   731                 );
   732                 assert(int_result == SQLITE_OK);    
   733             }
   734         }
   735         else { 
   736             // Version from DB was 0, it means this is initial setup.
   737             // DB has just been created, and all tables are empty.
   738             very_first = true;
   739         }
   740 
   741         if (version < atoi(_DDL_USER_VERSION)) {
   742             int_result = sqlite3_exec(
   743                 _session->db,
   744                 "pragma user_version = "_DDL_USER_VERSION";\n"
   745                 "insert or replace into version_info (id, version)"
   746                     "values (1, '" PEP_ENGINE_VERSION "');",
   747                 NULL,
   748                 NULL,
   749                 NULL
   750             );
   751             assert(int_result == SQLITE_OK);
   752         }
   753         
   754         // We need to init a few globals for message id that we'd rather not
   755         // calculate more than once.
   756         _init_globals();
   757     }
   758 
   759     int_result = sqlite3_prepare_v2(_session->db, sql_log,
   760             (int)strlen(sql_log), &_session->log, NULL);
   761     assert(int_result == SQLITE_OK);
   762 
   763     int_result = sqlite3_prepare_v2(_session->system_db, sql_trustword,
   764             (int)strlen(sql_trustword), &_session->trustword, NULL);
   765     assert(int_result == SQLITE_OK);
   766 
   767     int_result = sqlite3_prepare_v2(_session->db, sql_get_identity,
   768             (int)strlen(sql_get_identity), &_session->get_identity, NULL);
   769     assert(int_result == SQLITE_OK);
   770 
   771     int_result = sqlite3_prepare_v2(_session->db, sql_get_identity_without_fpr,
   772             (int)strlen(sql_get_identity_without_fpr), 
   773             &_session->get_identity_without_fpr, NULL);
   774     assert(int_result == SQLITE_OK);
   775 
   776     int_result = sqlite3_prepare_v2(_session->db, sql_get_identities_by_address,
   777             (int)strlen(sql_get_identities_by_address), 
   778             &_session->get_identities_by_address, NULL);
   779     assert(int_result == SQLITE_OK);
   780 
   781     int_result = sqlite3_prepare_v2(_session->db, sql_get_user_default_key,
   782             (int)strlen(sql_get_user_default_key), &_session->get_user_default_key, NULL);
   783     assert(int_result == SQLITE_OK);
   784 
   785     int_result = sqlite3_prepare_v2(_session->db, sql_get_own_userid,
   786             (int)strlen(sql_get_own_userid), &_session->get_own_userid, NULL);
   787     assert(int_result == SQLITE_OK);
   788 
   789     int_result = sqlite3_prepare_v2(_session->db, sql_replace_identities_fpr,
   790             (int)strlen(sql_replace_identities_fpr), 
   791             &_session->replace_identities_fpr, NULL);
   792     assert(int_result == SQLITE_OK);
   793 
   794     int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
   795             (int)strlen(sql_set_person), &_session->set_person, NULL);
   796     assert(int_result == SQLITE_OK);
   797 
   798     int_result = sqlite3_prepare_v2(_session->db, sql_set_device_group,
   799             (int)strlen(sql_set_device_group), &_session->set_device_group, NULL);
   800     assert(int_result == SQLITE_OK);
   801 
   802     int_result = sqlite3_prepare_v2(_session->db, sql_get_device_group,
   803             (int)strlen(sql_get_device_group), &_session->get_device_group, NULL);
   804     assert(int_result == SQLITE_OK);
   805 
   806     int_result = sqlite3_prepare_v2(_session->db, sql_set_pgp_keypair,
   807             (int)strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair,
   808             NULL);
   809     assert(int_result == SQLITE_OK);
   810 
   811     int_result = sqlite3_prepare_v2(_session->db, sql_set_identity,
   812             (int)strlen(sql_set_identity), &_session->set_identity, NULL);
   813     assert(int_result == SQLITE_OK);
   814 
   815     int_result = sqlite3_prepare_v2(_session->db, sql_set_identity_flags,
   816             (int)strlen(sql_set_identity_flags), &_session->set_identity_flags,
   817             NULL);
   818     assert(int_result == SQLITE_OK);
   819 
   820     int_result = sqlite3_prepare_v2(_session->db, sql_unset_identity_flags,
   821             (int)strlen(sql_unset_identity_flags), &_session->unset_identity_flags,
   822             NULL);
   823     assert(int_result == SQLITE_OK);
   824 
   825     int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
   826             (int)strlen(sql_set_trust), &_session->set_trust, NULL);
   827     assert(int_result == SQLITE_OK);
   828 
   829     int_result = sqlite3_prepare_v2(_session->db, sql_update_trust_for_fpr,
   830             (int)strlen(sql_update_trust_for_fpr), &_session->update_trust_for_fpr, NULL);
   831     assert(int_result == SQLITE_OK);
   832 
   833     int_result = sqlite3_prepare_v2(_session->db, sql_get_trust,
   834             (int)strlen(sql_get_trust), &_session->get_trust, NULL);
   835     assert(int_result == SQLITE_OK);
   836 
   837     int_result = sqlite3_prepare_v2(_session->db, sql_least_trust,
   838             (int)strlen(sql_least_trust), &_session->least_trust, NULL);
   839     assert(int_result == SQLITE_OK);
   840 
   841     int_result = sqlite3_prepare_v2(_session->db, sql_mark_as_compromized,
   842             (int)strlen(sql_mark_as_compromized), &_session->mark_compromized,
   843             NULL);
   844     assert(int_result == SQLITE_OK);
   845 
   846     int_result = sqlite3_prepare_v2(_session->db, sql_crashdump,
   847             (int)strlen(sql_crashdump), &_session->crashdump, NULL);
   848     assert(int_result == SQLITE_OK);
   849 
   850     int_result = sqlite3_prepare_v2(_session->system_db, sql_languagelist,
   851             (int)strlen(sql_languagelist), &_session->languagelist, NULL);
   852     assert(int_result == SQLITE_OK);
   853 
   854     int_result = sqlite3_prepare_v2(_session->system_db, sql_i18n_token,
   855             (int)strlen(sql_i18n_token), &_session->i18n_token, NULL);
   856     assert(int_result == SQLITE_OK);
   857     
   858     int_result = sqlite3_prepare_v2(_session->system_db, sql_replace_userid,
   859             (int)strlen(sql_replace_userid), &_session->replace_userid, NULL);
   860     assert(int_result == SQLITE_OK);
   861 
   862     // blacklist
   863 
   864     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_add,
   865             (int)strlen(sql_blacklist_add), &_session->blacklist_add, NULL);
   866     assert(int_result == SQLITE_OK);
   867 
   868     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_delete,
   869             (int)strlen(sql_blacklist_delete), &_session->blacklist_delete,
   870             NULL);
   871     assert(int_result == SQLITE_OK);
   872 
   873     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_is_listed,
   874             (int)strlen(sql_blacklist_is_listed),
   875             &_session->blacklist_is_listed, NULL);
   876     assert(int_result == SQLITE_OK);
   877 
   878     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_retrieve,
   879             (int)strlen(sql_blacklist_retrieve), &_session->blacklist_retrieve,
   880             NULL);
   881     assert(int_result == SQLITE_OK);
   882     
   883     // Own keys
   884     
   885     int_result = sqlite3_prepare_v2(_session->db, sql_own_key_is_listed,
   886             (int)strlen(sql_own_key_is_listed), &_session->own_key_is_listed,
   887             NULL);
   888     assert(int_result == SQLITE_OK);
   889     
   890     int_result = sqlite3_prepare_v2(_session->db, sql_own_identities_retrieve,
   891             (int)strlen(sql_own_identities_retrieve),
   892             &_session->own_identities_retrieve, NULL);
   893     assert(int_result == SQLITE_OK);
   894  
   895     int_result = sqlite3_prepare_v2(_session->db, sql_own_keys_retrieve,
   896             (int)strlen(sql_own_keys_retrieve),
   897             &_session->own_keys_retrieve, NULL);
   898     assert(int_result == SQLITE_OK);
   899  
   900     // int_result = sqlite3_prepare_v2(_session->db, sql_set_own_key,
   901     //         (int)strlen(sql_set_own_key),
   902     //         &_session->set_own_key, NULL);
   903     // assert(int_result == SQLITE_OK);
   904  
   905     // Sequence
   906 
   907     int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value1,
   908             (int)strlen(sql_sequence_value1), &_session->sequence_value1,
   909             NULL);
   910     assert(int_result == SQLITE_OK);
   911 
   912     int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value2,
   913             (int)strlen(sql_sequence_value2), &_session->sequence_value2,
   914             NULL);
   915     assert(int_result == SQLITE_OK);
   916 
   917     int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value3,
   918             (int)strlen(sql_sequence_value3), &_session->sequence_value3,
   919             NULL);
   920     assert(int_result == SQLITE_OK);
   921 
   922     // Revocation tracking
   923     
   924     int_result = sqlite3_prepare_v2(_session->db, sql_set_revoked,
   925             (int)strlen(sql_set_revoked), &_session->set_revoked, NULL);
   926     assert(int_result == SQLITE_OK);
   927     
   928     int_result = sqlite3_prepare_v2(_session->db, sql_get_revoked,
   929             (int)strlen(sql_get_revoked), &_session->get_revoked, NULL);
   930     assert(int_result == SQLITE_OK);
   931     
   932     status = init_cryptotech(_session, in_first);
   933     if (status != PEP_STATUS_OK)
   934         goto pep_error;
   935 
   936     status = init_transport_system(_session, in_first);
   937     if (status != PEP_STATUS_OK)
   938         goto pep_error;
   939 
   940     status = log_event(_session, "init", "pEp " PEP_ENGINE_VERSION, NULL, NULL);
   941     if (status != PEP_STATUS_OK)
   942         goto pep_error;
   943 
   944     // runtime config
   945 
   946 #ifdef ANDROID
   947 #elif TARGET_OS_IPHONE
   948 #else /* Desktop */
   949     if (very_first)
   950     {
   951         // On first run, all private keys already present in PGP keyring 
   952         // are taken as own in order to seamlessly integrate with
   953         // pre-existing GPG setup.
   954 
   955         ////////////////////////////// WARNING: ///////////////////////////
   956         // Considering all PGP priv keys as own is dangerous in case of 
   957         // re-initialization of pEp DB, while keeping PGP keyring as-is!
   958         //
   959         // Indeed, if pEpEngine did import spoofed private keys in previous
   960         // install, then those keys become automatically trusted in case 
   961         // pEp_management.db is deleted.
   962         //
   963         // A solution to distinguish bare GPG keyring from pEp keyring is
   964         // needed here. Then keys managed by pEpEngine wouldn't be
   965         // confused with GPG keys managed by the user through GPA.
   966         ///////////////////////////////////////////////////////////////////
   967         
   968         stringlist_t *keylist = NULL;
   969 
   970         status = find_private_keys(_session, NULL, &keylist);
   971         assert(status != PEP_OUT_OF_MEMORY);
   972         if (status == PEP_OUT_OF_MEMORY)
   973             return PEP_OUT_OF_MEMORY;
   974         
   975         if (keylist != NULL && keylist->value != NULL)
   976         {
   977             stringlist_t *_keylist;
   978             for (_keylist = keylist; _keylist && _keylist->value; _keylist = _keylist->next) {
   979                 status = set_own_key(_session, 
   980                                      "" /* address is unused in own_keys */,
   981                                      _keylist->value);
   982             }
   983         }
   984     }
   985 #endif
   986 
   987     // sync_session set to own session by default
   988     // sync_session is then never null on a valid session
   989     _session->sync_session = _session;
   990 
   991     *session = _session;
   992     
   993     // Note: Following statement is NOT for any cryptographic/secure functionality; it is
   994     //       ONLY used for some randomness in generated outer message ID, which are
   995     //       required by the RFC to be globally unique!
   996     srand(time(NULL));
   997     
   998     return PEP_STATUS_OK;
   999 
  1000 enomem:
  1001     status = PEP_OUT_OF_MEMORY;
  1002 
  1003 pep_error:
  1004     release(_session);
  1005     return status;
  1006 }
  1007 
  1008 DYNAMIC_API void release(PEP_SESSION session)
  1009 {
  1010     bool out_last = false;
  1011     int _count = --init_count;
  1012     
  1013     assert(_count >= -1);
  1014     assert(session);
  1015 
  1016     if (!((_count >= -1) && session))
  1017         return;
  1018 
  1019     // a small race condition but still a race condition
  1020     // mitigated by calling caveat (see documentation)
  1021     // (release() is to be guarded by a mutex by the caller)
  1022     if (_count == -1)
  1023         out_last = true;
  1024 
  1025     if (session) {
  1026 
  1027         if (session->db) {
  1028             if (session->log)
  1029                 sqlite3_finalize(session->log);
  1030             if (session->trustword)
  1031                 sqlite3_finalize(session->trustword);
  1032             if (session->get_identity)
  1033                 sqlite3_finalize(session->get_identity);
  1034             if (session->get_identity_without_fpr)
  1035                 sqlite3_finalize(session->get_identity_without_fpr);
  1036             if (session->get_identities_by_address)
  1037                 sqlite3_finalize(session->get_identities_by_address);            
  1038             if (session->get_user_default_key)
  1039                 sqlite3_finalize(session->get_user_default_key);    
  1040             if (session->get_own_userid)
  1041                 sqlite3_finalize(session->get_own_userid);
  1042             if (session->replace_identities_fpr)
  1043                 sqlite3_finalize(session->replace_identities_fpr);        
  1044             if (session->set_person)
  1045                 sqlite3_finalize(session->set_person);
  1046             if (session->set_device_group)
  1047                 sqlite3_finalize(session->set_device_group);
  1048             if (session->get_device_group)
  1049                 sqlite3_finalize(session->get_device_group);
  1050             if (session->set_pgp_keypair)
  1051                 sqlite3_finalize(session->set_pgp_keypair);
  1052             if (session->set_identity)
  1053                 sqlite3_finalize(session->set_identity);
  1054             if (session->set_identity_flags)
  1055                 sqlite3_finalize(session->set_identity_flags);
  1056             if (session->unset_identity_flags)
  1057                 sqlite3_finalize(session->unset_identity_flags);
  1058             if (session->set_trust)
  1059                 sqlite3_finalize(session->set_trust);
  1060             if (session->update_trust_for_fpr)
  1061                 sqlite3_finalize(session->update_trust_for_fpr);
  1062             if (session->get_trust)
  1063                 sqlite3_finalize(session->get_trust);
  1064             if (session->least_trust)
  1065                 sqlite3_finalize(session->least_trust);
  1066             if (session->mark_compromized)
  1067                 sqlite3_finalize(session->mark_compromized);
  1068             if (session->crashdump)
  1069                 sqlite3_finalize(session->crashdump);
  1070             if (session->languagelist)
  1071                 sqlite3_finalize(session->languagelist);
  1072             if (session->i18n_token)
  1073                 sqlite3_finalize(session->i18n_token);
  1074             if (session->replace_userid)
  1075                 sqlite3_finalize(session->replace_userid);
  1076             if (session->blacklist_add)
  1077                 sqlite3_finalize(session->blacklist_add);
  1078             if (session->blacklist_delete)
  1079                 sqlite3_finalize(session->blacklist_delete);
  1080             if (session->blacklist_is_listed)
  1081                 sqlite3_finalize(session->blacklist_is_listed);
  1082             if (session->blacklist_retrieve)
  1083                 sqlite3_finalize(session->blacklist_retrieve);
  1084             if (session->own_key_is_listed)
  1085                 sqlite3_finalize(session->own_key_is_listed);
  1086             if (session->own_identities_retrieve)
  1087                 sqlite3_finalize(session->own_identities_retrieve);
  1088             if (session->own_keys_retrieve)
  1089                 sqlite3_finalize(session->own_keys_retrieve);
  1090             // if (session->set_own_key)
  1091             //     sqlite3_finalize(session->set_own_key);
  1092             if (session->sequence_value1)
  1093                 sqlite3_finalize(session->sequence_value1);
  1094             if (session->sequence_value2)
  1095                 sqlite3_finalize(session->sequence_value2);
  1096             if (session->sequence_value3)
  1097                 sqlite3_finalize(session->sequence_value3);
  1098             if (session->set_revoked)
  1099                 sqlite3_finalize(session->set_revoked);
  1100             if (session->get_revoked)
  1101                 sqlite3_finalize(session->get_revoked);
  1102 
  1103             if (session->db)
  1104                 sqlite3_close_v2(session->db);
  1105             if (session->system_db)
  1106                 sqlite3_close_v2(session->system_db);
  1107         }
  1108 
  1109         release_transport_system(session, out_last);
  1110         release_cryptotech(session, out_last);
  1111 
  1112 #ifdef DEBUG_ERRORSTACK
  1113         free_stringlist(session->errorstack);
  1114 #endif
  1115         free(session);
  1116     }
  1117 }
  1118 
  1119 DYNAMIC_API void config_passive_mode(PEP_SESSION session, bool enable)
  1120 {
  1121     assert(session);
  1122     session->passive_mode = enable;
  1123 }
  1124 
  1125 DYNAMIC_API void config_unencrypted_subject(PEP_SESSION session, bool enable)
  1126 {
  1127     assert(session);
  1128     session->unencrypted_subject = enable;
  1129 }
  1130 
  1131 DYNAMIC_API void config_keep_sync_msg(PEP_SESSION session, bool enable)
  1132 {
  1133     assert(session);
  1134     session->keep_sync_msg = enable;
  1135 }
  1136 
  1137 DYNAMIC_API void config_service_log(PEP_SESSION session, bool enable)
  1138 {
  1139     assert(session);
  1140     session->service_log = enable;
  1141 }
  1142 
  1143 DYNAMIC_API PEP_STATUS log_event(
  1144         PEP_SESSION session,
  1145         const char *title,
  1146         const char *entity,
  1147         const char *description,
  1148         const char *comment
  1149     )
  1150 {
  1151     PEP_STATUS status = PEP_STATUS_OK;
  1152     int result;
  1153 
  1154     assert(session);
  1155     assert(title);
  1156     assert(entity);
  1157 
  1158     if (!(session && title && entity))
  1159         return PEP_ILLEGAL_VALUE;
  1160 
  1161     sqlite3_reset(session->log);
  1162     sqlite3_bind_text(session->log, 1, title, -1, SQLITE_STATIC);
  1163     sqlite3_bind_text(session->log, 2, entity, -1, SQLITE_STATIC);
  1164     if (description)
  1165         sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
  1166     else
  1167         sqlite3_bind_null(session->log, 3);
  1168     if (comment)
  1169         sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
  1170     else
  1171         sqlite3_bind_null(session->log, 4);
  1172     do {
  1173         result = sqlite3_step(session->log);
  1174         assert(result == SQLITE_DONE || result == SQLITE_BUSY);
  1175         if (result != SQLITE_DONE && result != SQLITE_BUSY)
  1176             status = PEP_UNKNOWN_ERROR;
  1177     } while (result == SQLITE_BUSY);
  1178     sqlite3_reset(session->log);
  1179 
  1180     return ADD_TO_LOG(status);
  1181 }
  1182 
  1183 DYNAMIC_API PEP_STATUS log_service(
  1184         PEP_SESSION session,
  1185         const char *title,
  1186         const char *entity,
  1187         const char *description,
  1188         const char *comment
  1189     )
  1190 {
  1191     assert(session);
  1192     if (!session)
  1193         return PEP_ILLEGAL_VALUE;
  1194 
  1195     if (session->service_log)
  1196         return log_event(session, title, entity, description, comment);
  1197     else
  1198         return PEP_STATUS_OK;
  1199 }
  1200 
  1201 DYNAMIC_API PEP_STATUS trustword(
  1202             PEP_SESSION session, uint16_t value, const char *lang,
  1203             char **word, size_t *wsize
  1204         )
  1205 {
  1206     PEP_STATUS status = PEP_STATUS_OK;
  1207 
  1208     assert(session);
  1209     assert(word);
  1210     assert(wsize);
  1211 
  1212     if (!(session && word && wsize))
  1213         return PEP_ILLEGAL_VALUE;
  1214 
  1215     *word = NULL;
  1216     *wsize = 0;
  1217 
  1218     if (lang == NULL)
  1219         lang = "en";
  1220 
  1221     assert((lang[0] >= 'A' && lang[0] <= 'Z')
  1222             || (lang[0] >= 'a' && lang[0] <= 'z'));
  1223     assert((lang[1] >= 'A' && lang[1] <= 'Z')
  1224             || (lang[1] >= 'a' && lang[1] <= 'z'));
  1225     assert(lang[2] == 0);
  1226 
  1227     sqlite3_reset(session->trustword);
  1228     sqlite3_bind_text(session->trustword, 1, lang, -1, SQLITE_STATIC);
  1229     sqlite3_bind_int(session->trustword, 2, value);
  1230 
  1231     const int result = sqlite3_step(session->trustword);
  1232     if (result == SQLITE_ROW) {
  1233         *word = strdup((const char *) sqlite3_column_text(session->trustword,
  1234                     1));
  1235         if (*word)
  1236             *wsize = sqlite3_column_bytes(session->trustword, 1);
  1237         else
  1238             status = PEP_OUT_OF_MEMORY;
  1239     } else
  1240         status = PEP_TRUSTWORD_NOT_FOUND;
  1241 
  1242     sqlite3_reset(session->trustword);
  1243     return status;
  1244 }
  1245 
  1246 DYNAMIC_API PEP_STATUS trustwords(
  1247         PEP_SESSION session, const char *fingerprint, const char *lang,
  1248         char **words, size_t *wsize, int max_words
  1249     )
  1250 {
  1251     const char *source = fingerprint;
  1252 
  1253     assert(session);
  1254     assert(fingerprint);
  1255     assert(words);
  1256     assert(wsize);
  1257     assert(max_words >= 0);
  1258 
  1259     if (!(session && fingerprint && words && wsize && max_words >= 0))
  1260         return PEP_ILLEGAL_VALUE;
  1261 
  1262     *words = NULL;
  1263     *wsize = 0;
  1264 
  1265     char *buffer = calloc(1, MAX_TRUSTWORDS_SPACE);
  1266     assert(buffer);
  1267     if (buffer == NULL)
  1268         return PEP_OUT_OF_MEMORY;
  1269     char *dest = buffer;
  1270 
  1271     const size_t fsize = strlen(fingerprint);
  1272 
  1273     if (!lang || !lang[0])
  1274         lang = "en";
  1275 
  1276     assert((lang[0] >= 'A' && lang[0] <= 'Z')
  1277             || (lang[0] >= 'a' && lang[0] <= 'z'));
  1278     assert((lang[1] >= 'A' && lang[1] <= 'Z')
  1279             || (lang[1] >= 'a' && lang[1] <= 'z'));
  1280     assert(lang[2] == 0);
  1281 
  1282     int n_words = 0;
  1283     while (source < fingerprint + fsize) {
  1284         PEP_STATUS _status;
  1285         uint16_t value;
  1286         char *word = NULL;
  1287         size_t _wsize = 0;
  1288         int j;
  1289 
  1290         for (value=0, j=0; j < 4 && source < fingerprint + fsize; ) {
  1291             if (*source >= 'a' && *source <= 'f')
  1292                 value += (*source - 'a' + 10) << (3 - j++) * 4;
  1293             else if (*source >= 'A' && *source <= 'F')
  1294                 value += (*source - 'A' + 10) << (3 - j++) * 4;
  1295             else if (*source >= '0' && *source <= '9')
  1296                 value += (*source - '0') << (3 - j++) * 4;
  1297             
  1298             source++;
  1299         }
  1300 
  1301         _status = trustword(session, value, lang, &word, &_wsize);
  1302         if (_status == PEP_OUT_OF_MEMORY) {
  1303             free(buffer);
  1304             return PEP_OUT_OF_MEMORY;
  1305         }
  1306         if (word == NULL) {
  1307             free(buffer);
  1308             return PEP_TRUSTWORD_NOT_FOUND;
  1309         }
  1310 
  1311         if (dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1) {
  1312             strncpy(dest, word, _wsize);
  1313             free(word);
  1314             dest += _wsize;
  1315         }
  1316         else {
  1317             free(word);
  1318             break; // buffer full
  1319         }
  1320 
  1321         if (source < fingerprint + fsize
  1322                 && dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1)
  1323             *dest++ = ' ';
  1324 
  1325         ++n_words;
  1326         if (max_words && n_words >= max_words)
  1327             break;
  1328     }
  1329 
  1330     *words = buffer;
  1331     *wsize = dest - buffer;
  1332     return PEP_STATUS_OK;
  1333 }
  1334 
  1335 pEp_identity *new_identity(
  1336         const char *address, const char *fpr, const char *user_id,
  1337         const char *username
  1338     )
  1339 {
  1340     pEp_identity *result = calloc(1, sizeof(pEp_identity));
  1341     assert(result);
  1342     if (result) {
  1343         if (address) {
  1344             result->address = strdup(address);
  1345             assert(result->address);
  1346             if (result->address == NULL) {
  1347                 free(result);
  1348                 return NULL;
  1349             }
  1350         }
  1351         if (fpr) {
  1352             result->fpr = strdup(fpr);
  1353             assert(result->fpr);
  1354             if (result->fpr == NULL) {
  1355                 free_identity(result);
  1356                 return NULL;
  1357             }
  1358         }
  1359         if (user_id) {
  1360             result->user_id = strdup(user_id);
  1361             assert(result->user_id);
  1362             if (result->user_id == NULL) {
  1363                 free_identity(result);
  1364                 return NULL;
  1365             }
  1366         }
  1367         if (username) {
  1368             result->username = strdup(username);
  1369             assert(result->username);
  1370             if (result->username == NULL) {
  1371                 free_identity(result);
  1372                 return NULL;
  1373             }
  1374         }
  1375     }
  1376     return result;
  1377 }
  1378 
  1379 pEp_identity *identity_dup(const pEp_identity *src)
  1380 {
  1381     assert(src);
  1382 
  1383     pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id,
  1384             src->username);
  1385     assert(dup);
  1386     if (dup == NULL)
  1387         return NULL;
  1388     
  1389     dup->comm_type = src->comm_type;
  1390     dup->lang[0] = src->lang[0];
  1391     dup->lang[1] = src->lang[1];
  1392     dup->lang[2] = 0;
  1393     dup->flags = src->flags;
  1394     dup->me = src->me;
  1395     
  1396     return dup;
  1397 }
  1398 
  1399 void free_identity(pEp_identity *identity)
  1400 {
  1401     if (identity) {
  1402         free(identity->address);
  1403         free(identity->fpr);
  1404         free(identity->user_id);
  1405         free(identity->username);
  1406         free(identity);
  1407     }
  1408 }
  1409 
  1410 DYNAMIC_API PEP_STATUS get_own_userid(
  1411         PEP_SESSION session, 
  1412         char** userid
  1413     )
  1414 {
  1415     assert(session);
  1416     assert(userid);
  1417     
  1418     if (!session || !userid)
  1419         return PEP_ILLEGAL_VALUE;
  1420         
  1421     PEP_STATUS status = PEP_STATUS_OK;
  1422     char* retval = NULL;
  1423     
  1424     sqlite3_reset(session->get_own_userid);
  1425 
  1426     const int result = sqlite3_step(session->get_own_userid);
  1427     const char* id;
  1428     
  1429     switch (result) {
  1430         case SQLITE_ROW:
  1431             id = (const char *) sqlite3_column_text(session->get_own_userid, 0);
  1432             if (!id) {
  1433                 // Shouldn't happen.
  1434                 status = PEP_UNKNOWN_ERROR;
  1435             }
  1436             else {
  1437                 retval = strdup(id);
  1438                 if (!retval)
  1439                     status = PEP_OUT_OF_MEMORY;
  1440             }
  1441             break;
  1442         default:
  1443             // Technically true, given how we find it, but FIXME we need a more descriptive error
  1444             status = PEP_CANNOT_FIND_IDENTITY;
  1445             *userid = NULL;
  1446     }
  1447 
  1448     *userid = retval;
  1449 
  1450     sqlite3_reset(session->get_own_userid);
  1451     
  1452     return status;
  1453 }
  1454 
  1455 static PEP_STATUS _get_identity_internal(
  1456         PEP_SESSION session,
  1457         const char *address,
  1458         const char *user_id,
  1459         pEp_identity **identity,
  1460         sqlite3_stmt* get_id_stmt
  1461     )
  1462 {
  1463     PEP_STATUS status = PEP_STATUS_OK;
  1464     static pEp_identity *_identity;
  1465 
  1466     assert(session);
  1467     assert(address);
  1468     assert(address[0]);
  1469     assert(identity);
  1470 
  1471     if (!(session && address && address[0] && identity))
  1472         return PEP_ILLEGAL_VALUE;
  1473 
  1474     *identity = NULL;
  1475 
  1476     sqlite3_reset(get_id_stmt);
  1477     sqlite3_bind_text(get_id_stmt, 1, address, -1, SQLITE_STATIC);
  1478     sqlite3_bind_text(get_id_stmt, 2, user_id, -1, SQLITE_STATIC);
  1479 
  1480     const int result = sqlite3_step(get_id_stmt);
  1481     switch (result) {
  1482     case SQLITE_ROW:
  1483         _identity = new_identity(
  1484                 address,
  1485                 (const char *) sqlite3_column_text(get_id_stmt, 0),
  1486                 user_id,
  1487                 (const char *) sqlite3_column_text(get_id_stmt, 1)
  1488                 );
  1489         assert(_identity);
  1490         if (_identity == NULL)
  1491             return PEP_OUT_OF_MEMORY;
  1492 
  1493         _identity->comm_type = (PEP_comm_type)
  1494             sqlite3_column_int(get_id_stmt, 2);
  1495         const char* const _lang = (const char *)
  1496             sqlite3_column_text(get_id_stmt, 3);
  1497         if (_lang && _lang[0]) {
  1498             assert(_lang[0] >= 'a' && _lang[0] <= 'z');
  1499             assert(_lang[1] >= 'a' && _lang[1] <= 'z');
  1500             assert(_lang[2] == 0);
  1501             _identity->lang[0] = _lang[0];
  1502             _identity->lang[1] = _lang[1];
  1503             _identity->lang[2] = 0;
  1504         }
  1505         _identity->flags = (unsigned int)
  1506             sqlite3_column_int(get_id_stmt, 4);
  1507         _identity->me = (unsigned int)
  1508             sqlite3_column_int(get_id_stmt, 5);
  1509     
  1510         *identity = _identity;
  1511         break;
  1512     default:
  1513         status = PEP_CANNOT_FIND_IDENTITY;
  1514         *identity = NULL;
  1515     }
  1516 
  1517     sqlite3_reset(get_id_stmt);
  1518     return status;
  1519 }
  1520 
  1521 DYNAMIC_API PEP_STATUS get_identity(
  1522         PEP_SESSION session,
  1523         const char *address,
  1524         const char *user_id,
  1525         pEp_identity **identity
  1526     )
  1527 {
  1528     return _get_identity_internal(session, address, user_id, identity,
  1529                                   session->get_identity);
  1530 }
  1531 
  1532 PEP_STATUS get_identity_without_fpr(
  1533         PEP_SESSION session,
  1534         const char *address,
  1535         const char *user_id,
  1536         pEp_identity **identity
  1537     )
  1538 {
  1539     return _get_identity_internal(session, address, user_id, identity,
  1540                                   session->get_identity_without_fpr);
  1541 }
  1542 
  1543 PEP_STATUS get_identities_by_address(
  1544         PEP_SESSION session,
  1545         const char *address,
  1546         identity_list** id_list
  1547     )
  1548 {
  1549     pEp_identity* ident;
  1550 
  1551     assert(session);
  1552     assert(address);
  1553     assert(address[0]);
  1554     assert(id_list);
  1555 
  1556     if (!(session && address && address[0] && id_list))
  1557         return PEP_ILLEGAL_VALUE;
  1558 
  1559     *id_list = NULL;
  1560     identity_list* ident_list = NULL;
  1561 
  1562     sqlite3_reset(sql->get_identities_by_address);
  1563     sqlite3_bind_text(sql->get_identities_by_address, 1, address, -1, SQLITE_STATIC);
  1564     int result;
  1565 
  1566     while ((result = sqlite3_step(sql->get_identities_by_address)) == SQLITE_ROW) {
  1567         
  1568         ident = new_identity(
  1569                 address,
  1570                 (const char *) sqlite3_column_text(sql->get_identities_by_address, 0),
  1571                 user_id,
  1572                 (const char *) sqlite3_column_text(sql->get_identities_by_address, 1)
  1573                 );
  1574         assert(_identity);
  1575         if (ident == NULL)
  1576             return PEP_OUT_OF_MEMORY;
  1577 
  1578         ident->comm_type = (PEP_comm_type)
  1579             sqlite3_column_int(sql->get_identities_by_address, 2);
  1580         const char* const _lang = (const char *)
  1581             sqlite3_column_text(sql->get_identities_by_address, 3);
  1582         if (_lang && _lang[0]) {
  1583             assert(_lang[0] >= 'a' && _lang[0] <= 'z');
  1584             assert(_lang[1] >= 'a' && _lang[1] <= 'z');
  1585             assert(_lang[2] == 0);
  1586             _identity->lang[0] = _lang[0];
  1587             _identity->lang[1] = _lang[1];
  1588             _identity->lang[2] = 0;
  1589         }
  1590         ident->flags = (unsigned int)
  1591             sqlite3_column_int(sql->get_identities_by_address, 4);
  1592         ident->me = (unsigned int)
  1593             sqlite3_column_int(sql->get_identities_by_address, 5);
  1594     
  1595         if (ident_list)
  1596             identity_list_add(ident_list, ident);
  1597         else
  1598             ident_list = new_identity_list(ident);
  1599     }
  1600 
  1601     sqlite3_reset(sql->get_identities_by_address);
  1602     
  1603     *id_list = ident_list;
  1604     
  1605     if (!ident_list)
  1606         return PEP_CANNOT_FIND_IDENTITY;
  1607     
  1608     return PEP_STATUS_OK;
  1609 }
  1610 
  1611 
  1612 DYNAMIC_API PEP_STATUS set_identity(
  1613         PEP_SESSION session, const pEp_identity *identity
  1614     )
  1615 {
  1616     int result;
  1617 
  1618     assert(session);
  1619     assert(identity);
  1620     assert(identity->address);
  1621     assert(identity->user_id);
  1622     assert(identity->username);
  1623 
  1624     if (!(session && identity && identity->address &&
  1625                 identity->user_id && identity->username))
  1626         return PEP_ILLEGAL_VALUE;
  1627 
  1628     PEP_STATUS status = PEP_STATUS_OK;
  1629     
  1630     bool listed;
  1631 
  1632     bool has_fpr = (identity->fpr && identity->fpr[0] != '\0');
  1633     
  1634     if (has_fpr) {    
  1635         // blacklist check
  1636         status = blacklist_is_listed(session, identity->fpr, &listed);
  1637         assert(status == PEP_STATUS_OK);
  1638         if (status != PEP_STATUS_OK)
  1639             return status;
  1640 
  1641         if (listed)
  1642             return PEP_KEY_BLACKLISTED;
  1643     }
  1644 
  1645     sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
  1646 
  1647     if (identity->lang[0]) {
  1648         assert(identity->lang[0] >= 'a' && identity->lang[0] <= 'z');
  1649         assert(identity->lang[1] >= 'a' && identity->lang[1] <= 'z');
  1650         assert(identity->lang[2] == 0);
  1651     }
  1652 
  1653     sqlite3_reset(session->set_person);
  1654     sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
  1655             SQLITE_STATIC);
  1656     sqlite3_bind_text(session->set_person, 2, identity->username, -1,
  1657             SQLITE_STATIC);
  1658     if (identity->lang[0])
  1659         sqlite3_bind_text(session->set_person, 3, identity->lang, 2,
  1660                 SQLITE_STATIC);
  1661     else
  1662         sqlite3_bind_null(session->set_person, 3);
  1663     sqlite3_bind_text(session->set_person, 4, identity->fpr, -1,
  1664                       SQLITE_STATIC);
  1665     result = sqlite3_step(session->set_person);
  1666     sqlite3_reset(session->set_person);
  1667     if (result != SQLITE_DONE) {
  1668         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1669         return PEP_CANNOT_SET_PERSON;
  1670     }
  1671 
  1672     if (has_fpr) {
  1673         sqlite3_reset(session->set_pgp_keypair);
  1674         sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
  1675                 SQLITE_STATIC);
  1676         result = sqlite3_step(session->set_pgp_keypair);
  1677         sqlite3_reset(session->set_pgp_keypair);
  1678         if (result != SQLITE_DONE) {
  1679             sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1680             return PEP_CANNOT_SET_PGP_KEYPAIR;
  1681         }
  1682     }
  1683 
  1684     sqlite3_reset(session->set_identity);
  1685     sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
  1686             SQLITE_STATIC);
  1687     sqlite3_bind_text(session->set_identity, 2, identity->fpr, -1,
  1688             SQLITE_STATIC);
  1689     sqlite3_bind_text(session->set_identity, 3, identity->user_id, -1,
  1690             SQLITE_STATIC);
  1691     sqlite3_bind_int(session->set_identity, 4, identity->flags);
  1692     sqlite3_bind_int(session->set_identity, 5, identity->me);
  1693     result = sqlite3_step(session->set_identity);
  1694     sqlite3_reset(session->set_identity);
  1695     if (result != SQLITE_DONE) {
  1696         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1697         return PEP_CANNOT_SET_IDENTITY;
  1698     }
  1699 
  1700     if (has_fpr) {
  1701         sqlite3_reset(session->set_trust);
  1702         sqlite3_bind_text(session->set_trust, 1, identity->user_id, -1,
  1703                 SQLITE_STATIC);
  1704         sqlite3_bind_text(session->set_trust, 2, identity->fpr, -1,
  1705                 SQLITE_STATIC);
  1706         sqlite3_bind_int(session->set_trust, 3, identity->comm_type);
  1707         result = sqlite3_step(session->set_trust);
  1708         sqlite3_reset(session->set_trust);
  1709         if (result != SQLITE_DONE) {
  1710             sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1711             return PEP_CANNOT_SET_TRUST;
  1712         }
  1713     }
  1714     
  1715     result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
  1716     if (result == SQLITE_OK)
  1717         return PEP_STATUS_OK;
  1718     else
  1719         return PEP_COMMIT_FAILED;
  1720 }
  1721 
  1722 PEP_STATUS replace_identities_fpr(PEP_SESSION session, 
  1723                                  const char* old_fpr, 
  1724                                  const char* new_fpr) 
  1725 {
  1726     assert(old_fpr);
  1727     assert(new_fpr);
  1728     
  1729     if (!old_fpr || !new_fpr)
  1730         return PEP_ILLEGAL_VALUE;
  1731             
  1732     sqlite3_reset(session->replace_identities_fpr);
  1733     sqlite3_bind_text(session->replace_identities_fpr, 1, new_fpr, -1,
  1734                       SQLITE_STATIC);
  1735     sqlite3_bind_text(session->replace_identities_fpr, 2, old_fpr, -1,
  1736                       SQLITE_STATIC);
  1737 
  1738     int result = sqlite3_step(session->replace_identities_fpr);
  1739     sqlite3_reset(session->replace_identities_fpr);
  1740     
  1741     if (result != SQLITE_DONE)
  1742         return PEP_CANNOT_SET_IDENTITY;
  1743 
  1744     return PEP_STATUS_OK;
  1745 }
  1746 
  1747 
  1748 PEP_STATUS update_trust_for_fpr(PEP_SESSION session, 
  1749                                 const char* fpr, 
  1750                                 PEP_comm_type comm_type)
  1751 {
  1752     if (!fpr)
  1753         return PEP_ILLEGAL_VALUE;
  1754         
  1755     sqlite3_reset(session->update_trust_for_fpr);
  1756     sqlite3_bind_int(session->update_trust_for_fpr, 1, comm_type);
  1757     sqlite3_bind_text(session->update_trust_for_fpr, 2, fpr, -1,
  1758             SQLITE_STATIC);
  1759     int result = sqlite3_step(session->update_trust_for_fpr);
  1760     sqlite3_reset(session->update_trust_for_fpr);
  1761     if (result != SQLITE_DONE) {
  1762         return PEP_CANNOT_SET_TRUST;
  1763     }
  1764     
  1765     return PEP_STATUS_OK;
  1766 }
  1767 
  1768 DYNAMIC_API PEP_STATUS set_device_group(
  1769         PEP_SESSION session,
  1770         const char *group_name
  1771     )
  1772 {
  1773     int result;
  1774 
  1775     assert(session);
  1776 
  1777     if (!(session && group_name))
  1778         return PEP_ILLEGAL_VALUE;
  1779 
  1780     // 1. Get own user_id
  1781     char* user_id = NULL;
  1782     PEP_STATUS status = get_own_userid(session, &user_id);
  1783     
  1784     // No user_id is returned in this case, no need to free;
  1785     if (status != PEP_STATUS_OK)
  1786         return status;
  1787         
  1788     // 2. Set device group
  1789     sqlite3_reset(session->set_device_group);
  1790     if(group_name){
  1791         sqlite3_bind_text(session->set_device_group, 1, group_name, -1,
  1792                 SQLITE_STATIC);
  1793     } else {
  1794         sqlite3_bind_null(session->set_device_group, 1);
  1795     }
  1796     
  1797     sqlite3_bind_text(session->set_device_group, 2, user_id, -1,
  1798             SQLITE_STATIC);
  1799 
  1800     result = sqlite3_step(session->set_device_group);
  1801     sqlite3_reset(session->set_device_group);
  1802     
  1803     free(user_id);
  1804     
  1805     if (result != SQLITE_DONE)
  1806         return PEP_CANNOT_SET_PERSON;
  1807 
  1808     return PEP_STATUS_OK;
  1809 }
  1810 
  1811 DYNAMIC_API PEP_STATUS get_device_group(PEP_SESSION session, char **group_name)
  1812 {
  1813     PEP_STATUS status = PEP_STATUS_OK;
  1814     int result;
  1815 
  1816     assert(session);
  1817     assert(group_name);
  1818 
  1819     if (!(session && group_name))
  1820         return PEP_ILLEGAL_VALUE;
  1821 
  1822     // 1. Get own user_id
  1823     char* user_id = NULL;
  1824     status = get_own_userid(session, &user_id);
  1825     
  1826     // No user_id is returned in this case, no need to free;
  1827     if (status != PEP_STATUS_OK)
  1828         return status;
  1829 
  1830     // 2. get device group
  1831     sqlite3_reset(session->get_device_group);
  1832     sqlite3_bind_text(session->get_device_group, 1, user_id, -1,
  1833             SQLITE_STATIC);
  1834 
  1835     result = sqlite3_step(session->get_device_group);
  1836     switch (result) {
  1837     case SQLITE_ROW: {
  1838         const char *_group_name = (const char *)sqlite3_column_text(session->get_device_group, 0);
  1839         if(_group_name){
  1840             *group_name = strdup(_group_name);
  1841                 if(*group_name == NULL)
  1842                     status = PEP_OUT_OF_MEMORY;
  1843         }
  1844         break;
  1845     }
  1846  
  1847     default:
  1848         status = PEP_RECORD_NOT_FOUND;
  1849     }
  1850 
  1851     free(user_id);
  1852     sqlite3_reset(session->get_device_group);
  1853     return status;
  1854 }
  1855 
  1856 DYNAMIC_API PEP_STATUS set_identity_flags(
  1857         PEP_SESSION session,
  1858         pEp_identity *identity,
  1859         unsigned int flags
  1860     )
  1861 {
  1862     int result;
  1863 
  1864     assert(session);
  1865     assert(identity);
  1866     assert(identity->address);
  1867     assert(identity->user_id);
  1868 
  1869     if (!(session && identity && identity->address && identity->user_id))
  1870         return PEP_ILLEGAL_VALUE;
  1871 
  1872     sqlite3_reset(session->set_identity_flags);
  1873     sqlite3_bind_int(session->set_identity_flags, 1, flags);
  1874     sqlite3_bind_text(session->set_identity_flags, 2, identity->address, -1,
  1875             SQLITE_STATIC);
  1876     sqlite3_bind_text(session->set_identity_flags, 3, identity->user_id, -1,
  1877         result = sqlite3_step(session->set_identity_flags);
  1878             SQLITE_STATIC);
  1879     sqlite3_reset(session->set_identity_flags);
  1880     if (result != SQLITE_DONE)
  1881         return PEP_CANNOT_SET_IDENTITY;
  1882 
  1883     identity->flags |= flags;
  1884     return PEP_STATUS_OK;
  1885 }
  1886 
  1887 DYNAMIC_API PEP_STATUS unset_identity_flags(
  1888         PEP_SESSION session,
  1889         pEp_identity *identity,
  1890         unsigned int flags
  1891     )
  1892 {
  1893     int result;
  1894 
  1895     assert(session);
  1896     assert(identity);
  1897     assert(identity->address);
  1898     assert(identity->user_id);
  1899 
  1900     if (!(session && identity && identity->address && identity->user_id))
  1901         return PEP_ILLEGAL_VALUE;
  1902 
  1903     sqlite3_reset(session->unset_identity_flags);
  1904     sqlite3_bind_int(session->unset_identity_flags, 1, flags);
  1905     sqlite3_bind_text(session->unset_identity_flags, 2, identity->address, -1,
  1906             SQLITE_STATIC);
  1907     sqlite3_bind_text(session->unset_identity_flags, 3, identity->user_id, -1,
  1908             SQLITE_STATIC);
  1909     result = sqlite3_step(session->unset_identity_flags);
  1910     sqlite3_reset(session->unset_identity_flags);
  1911     if (result != SQLITE_DONE)
  1912         return PEP_CANNOT_SET_IDENTITY;
  1913 
  1914     identity->flags &= ~flags;
  1915     return PEP_STATUS_OK;
  1916 }
  1917 
  1918 
  1919 PEP_STATUS replace_userid(PEP_SESSION session, const char* old_uid,
  1920                               const char* new_uid) {
  1921     assert(session);
  1922     assert(old_uid);
  1923     assert(new_uid);
  1924     
  1925     if (!session || !old_uid || !new_uid)
  1926         return PEP_ILLEGAL_VALUE;
  1927 
  1928 
  1929     int result;
  1930 
  1931     sqlite3_reset(session->replace_userid);
  1932     sqlite3_bind_text(session->replace_userid, 1, new_id, -1,
  1933             SQLITE_STATIC);
  1934     sqlite3_bind_text(session->replace_userid, 2, old_id, -1,
  1935             SQLITE_STATIC);
  1936     result = sqlite3_step(session->replace);
  1937     sqlite3_reset(session->replace);
  1938     if (result != SQLITE_DONE)
  1939         return PEP_CANNOT_SET_PERSON; // May need clearer retval
  1940 
  1941     return PEP_STATUS_OK;
  1942 }
  1943 
  1944 
  1945 DYNAMIC_API PEP_STATUS mark_as_compromized(
  1946         PEP_SESSION session,
  1947         const char *fpr
  1948     )
  1949 {
  1950     int result;
  1951 
  1952     assert(session);
  1953     assert(fpr && fpr[0]);
  1954 
  1955     if (!(session && fpr && fpr[0]))
  1956         return PEP_ILLEGAL_VALUE;
  1957 
  1958     sqlite3_reset(session->mark_compromized);
  1959     sqlite3_bind_text(session->mark_compromized, 1, fpr, -1,
  1960             SQLITE_STATIC);
  1961     result = sqlite3_step(session->mark_compromized);
  1962     sqlite3_reset(session->mark_compromized);
  1963 
  1964     if (result != SQLITE_DONE)
  1965         return PEP_CANNOT_SET_TRUST;
  1966 
  1967     return PEP_STATUS_OK;
  1968 }
  1969 
  1970 void pEp_free(void *p)
  1971 {
  1972     free(p);
  1973 }
  1974 
  1975 DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
  1976 {
  1977     PEP_STATUS status = PEP_STATUS_OK;
  1978     int result;
  1979 
  1980     assert(session);
  1981     assert(identity);
  1982     assert(identity->user_id);
  1983     assert(identity->user_id[0]);
  1984     assert(identity->fpr);
  1985     assert(identity->fpr[0]);
  1986 
  1987     if (!(session && identity && identity->user_id && identity->user_id[0] &&
  1988                 identity->fpr && identity->fpr[0]))
  1989         return PEP_ILLEGAL_VALUE;
  1990 
  1991     identity->comm_type = PEP_ct_unknown;
  1992 
  1993     sqlite3_reset(session->get_trust);
  1994     sqlite3_bind_text(session->get_trust, 1, identity->user_id, -1,
  1995             SQLITE_STATIC);
  1996     sqlite3_bind_text(session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
  1997 
  1998     result = sqlite3_step(session->get_trust);
  1999     switch (result) {
  2000     case SQLITE_ROW: {
  2001         int comm_type = (PEP_comm_type) sqlite3_column_int(session->get_trust,
  2002                 0);
  2003         identity->comm_type = comm_type;
  2004         break;
  2005     }
  2006  
  2007     default:
  2008         status = PEP_CANNOT_FIND_IDENTITY;
  2009     }
  2010 
  2011     sqlite3_reset(session->get_trust);
  2012     return status;
  2013 }
  2014 
  2015 DYNAMIC_API PEP_STATUS least_trust(
  2016         PEP_SESSION session,
  2017         const char *fpr,
  2018         PEP_comm_type *comm_type
  2019     )
  2020 {
  2021     PEP_STATUS status = PEP_STATUS_OK;
  2022     int result;
  2023 
  2024     assert(session);
  2025     assert(fpr);
  2026     assert(comm_type);
  2027 
  2028     if (!(session && fpr && comm_type))
  2029         return PEP_ILLEGAL_VALUE;
  2030 
  2031     *comm_type = PEP_ct_unknown;
  2032 
  2033     sqlite3_reset(session->least_trust);
  2034     sqlite3_bind_text(session->least_trust, 1, fpr, -1, SQLITE_STATIC);
  2035 
  2036     result = sqlite3_step(session->least_trust);
  2037     switch (result) {
  2038         case SQLITE_ROW: {
  2039             int _comm_type = sqlite3_column_int(session->least_trust, 0);
  2040             *comm_type = (PEP_comm_type) _comm_type;
  2041             break;
  2042         }
  2043         default:
  2044             // never reached because of sql min()
  2045             status = PEP_CANNOT_FIND_IDENTITY;
  2046     }
  2047 
  2048     sqlite3_reset(session->least_trust);
  2049     return status;
  2050 }
  2051 
  2052 DYNAMIC_API PEP_STATUS decrypt_and_verify(
  2053     PEP_SESSION session, const char *ctext, size_t csize,
  2054     const char *dsigtext, size_t dsigsize,
  2055     char **ptext, size_t *psize, stringlist_t **keylist
  2056     )
  2057 {
  2058     assert(session);
  2059     assert(ctext);
  2060     assert(csize);
  2061     assert(ptext);
  2062     assert(psize);
  2063     assert(keylist);
  2064 
  2065     if (!(session && ctext && csize && ptext && psize && keylist))
  2066         return PEP_ILLEGAL_VALUE;
  2067 
  2068     return session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(
  2069             session, ctext, csize, dsigtext, dsigsize, ptext, psize, keylist);
  2070 }
  2071 
  2072 DYNAMIC_API PEP_STATUS encrypt_and_sign(
  2073     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
  2074     size_t psize, char **ctext, size_t *csize
  2075     )
  2076 {
  2077     assert(session);
  2078     assert(keylist);
  2079     assert(ptext);
  2080     assert(psize);
  2081     assert(ctext);
  2082     assert(csize);
  2083 
  2084     if (!(session && keylist && ptext && psize && ctext && csize))
  2085         return PEP_ILLEGAL_VALUE;
  2086 
  2087     return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session,
  2088             keylist, ptext, psize, ctext, csize);
  2089 }
  2090 
  2091 PEP_STATUS encrypt_only(
  2092     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
  2093     size_t psize, char **ctext, size_t *csize
  2094     )
  2095 {
  2096     assert(session);
  2097     assert(keylist);
  2098     assert(ptext);
  2099     assert(psize);
  2100     assert(ctext);
  2101     assert(csize);
  2102 
  2103     if (!(session && keylist && ptext && psize && ctext && csize))
  2104         return PEP_ILLEGAL_VALUE;
  2105 
  2106     return session->cryptotech[PEP_crypt_OpenPGP].encrypt_only(session,
  2107             keylist, ptext, psize, ctext, csize);
  2108 }
  2109 
  2110 
  2111 DYNAMIC_API PEP_STATUS verify_text(
  2112     PEP_SESSION session, const char *text, size_t size,
  2113     const char *signature, size_t sig_size, stringlist_t **keylist
  2114     )
  2115 {
  2116     assert(session);
  2117     assert(text);
  2118     assert(size);
  2119     assert(signature);
  2120     assert(sig_size);
  2121     assert(keylist);
  2122 
  2123     if (!(session && text && size && signature && sig_size && keylist))
  2124         return PEP_ILLEGAL_VALUE;
  2125 
  2126     return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text,
  2127             size, signature, sig_size, keylist);
  2128 }
  2129 
  2130 DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
  2131 {
  2132     assert(session);
  2133     assert(fpr);
  2134 
  2135     if (!(session && fpr))
  2136         return PEP_ILLEGAL_VALUE;
  2137 
  2138     return session->cryptotech[PEP_crypt_OpenPGP].delete_keypair(session, fpr);
  2139 }
  2140 
  2141 DYNAMIC_API PEP_STATUS export_key(
  2142         PEP_SESSION session, const char *fpr, char **key_data, size_t *size
  2143     )
  2144 {
  2145     assert(session);
  2146     assert(fpr);
  2147     assert(key_data);
  2148     assert(size);
  2149 
  2150     if (!(session && fpr && key_data && size))
  2151         return PEP_ILLEGAL_VALUE;
  2152 
  2153     return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr,
  2154             key_data, size, false);
  2155 }
  2156 
  2157 DYNAMIC_API PEP_STATUS export_secrect_key(
  2158         PEP_SESSION session, const char *fpr, char **key_data, size_t *size
  2159     )
  2160 {
  2161     assert(session);
  2162     assert(fpr);
  2163     assert(key_data);
  2164     assert(size);
  2165 
  2166     if (!(session && fpr && key_data && size))
  2167         return PEP_ILLEGAL_VALUE;
  2168 
  2169     // don't accept key IDs but full fingerprints only
  2170     if (strlen(fpr) < 16)
  2171         return PEP_ILLEGAL_VALUE;
  2172 
  2173     return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr,
  2174             key_data, size, true);
  2175 }
  2176 
  2177 DYNAMIC_API PEP_STATUS find_keys(
  2178         PEP_SESSION session, const char *pattern, stringlist_t **keylist
  2179     )
  2180 {
  2181     assert(session);
  2182     assert(pattern);
  2183     assert(keylist);
  2184 
  2185     if (!(session && pattern && keylist))
  2186         return PEP_ILLEGAL_VALUE;
  2187 
  2188     return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern,
  2189             keylist);
  2190 }
  2191 
  2192 
  2193 DYNAMIC_API PEP_STATUS generate_keypair(
  2194         PEP_SESSION session, pEp_identity *identity
  2195     )
  2196 {
  2197     assert(session);
  2198     assert(identity);
  2199     assert(identity->address);
  2200     assert(identity->fpr == NULL || identity->fpr[0] == 0);
  2201     assert(identity->username);
  2202 
  2203     if (!(session && identity && identity->address &&
  2204             (identity->fpr == NULL || identity->fpr[0] == 0) &&
  2205             identity->username))
  2206         return PEP_ILLEGAL_VALUE;
  2207 
  2208     PEP_STATUS status =
  2209         session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session,
  2210                 identity);
  2211     if (status != PEP_STATUS_OK)
  2212         return status;
  2213 
  2214     return status;
  2215 }
  2216 
  2217 DYNAMIC_API PEP_STATUS get_key_rating(
  2218         PEP_SESSION session,
  2219         const char *fpr,
  2220         PEP_comm_type *comm_type
  2221     )
  2222 {
  2223     assert(session);
  2224     assert(fpr);
  2225     assert(comm_type);
  2226 
  2227     if (!(session && fpr && comm_type))
  2228         return PEP_ILLEGAL_VALUE;
  2229 
  2230     return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr,
  2231             comm_type);
  2232 }
  2233 
  2234 DYNAMIC_API PEP_STATUS import_key(
  2235         PEP_SESSION session,
  2236         const char *key_data,
  2237         size_t size,
  2238         identity_list **private_keys
  2239     )
  2240 {
  2241     assert(session);
  2242     assert(key_data);
  2243 
  2244     if (!(session && key_data))
  2245         return PEP_ILLEGAL_VALUE;
  2246 
  2247     return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data,
  2248             size, private_keys);
  2249 }
  2250 
  2251 DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
  2252 {
  2253     assert(session);
  2254     assert(pattern);
  2255 
  2256     if (!(session && pattern))
  2257         return PEP_ILLEGAL_VALUE;
  2258 
  2259     return session->cryptotech[PEP_crypt_OpenPGP].recv_key(session, pattern);
  2260 }
  2261 
  2262 DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
  2263 {
  2264     assert(session);
  2265     assert(pattern);
  2266 
  2267     if (!(session && pattern))
  2268         return PEP_ILLEGAL_VALUE;
  2269 
  2270     return session->cryptotech[PEP_crypt_OpenPGP].send_key(session, pattern);
  2271 }
  2272 
  2273 DYNAMIC_API PEP_STATUS renew_key(
  2274         PEP_SESSION session,
  2275         const char *fpr,
  2276         const timestamp *ts
  2277     )
  2278 {
  2279     assert(session);
  2280     assert(fpr);
  2281 
  2282     if (!(session && fpr))
  2283         return PEP_ILLEGAL_VALUE;
  2284 
  2285     return session->cryptotech[PEP_crypt_OpenPGP].renew_key(session, fpr, ts);
  2286 }
  2287 
  2288 DYNAMIC_API PEP_STATUS revoke_key(
  2289         PEP_SESSION session,
  2290         const char *fpr,
  2291         const char *reason
  2292     )
  2293 {
  2294     assert(session);
  2295     assert(fpr);
  2296 
  2297     if (!(session && fpr))
  2298         return PEP_ILLEGAL_VALUE;
  2299 
  2300     return session->cryptotech[PEP_crypt_OpenPGP].revoke_key(session, fpr,
  2301             reason);
  2302 }
  2303 
  2304 DYNAMIC_API PEP_STATUS key_expired(
  2305         PEP_SESSION session,
  2306         const char *fpr,
  2307         const time_t when,
  2308         bool *expired
  2309     )
  2310 {
  2311     assert(session);
  2312     assert(fpr);
  2313     assert(expired);
  2314 
  2315     if (!(session && fpr && expired))
  2316         return PEP_ILLEGAL_VALUE;
  2317 
  2318     return session->cryptotech[PEP_crypt_OpenPGP].key_expired(session, fpr,
  2319             when, expired);
  2320 }
  2321 
  2322 DYNAMIC_API PEP_STATUS key_revoked(
  2323        PEP_SESSION session,
  2324        const char *fpr,
  2325        bool *revoked
  2326    )
  2327 {
  2328     assert(session);
  2329     assert(fpr);
  2330     assert(revoked);
  2331     
  2332     if (!(session && fpr && revoked))
  2333         return PEP_ILLEGAL_VALUE;
  2334     
  2335     return session->cryptotech[PEP_crypt_OpenPGP].key_revoked(session, fpr,
  2336             revoked);
  2337 }
  2338 
  2339 static void _clean_log_value(char *text)
  2340 {
  2341     if (text) {
  2342         for (char *c = text; *c; c++) {
  2343             if (*c < 32 && *c != '\n')
  2344                 *c = 32;
  2345             else if (*c == '"')
  2346                 *c = '\'';
  2347         }
  2348     }
  2349 }
  2350 
  2351 static char *_concat_string(char *str1, const char *str2, char delim)
  2352 {
  2353     str2 = str2 ? str2 : "";
  2354     size_t len1 = str1 ? strlen(str1) : 0;
  2355     size_t len2 = strlen(str2);
  2356     size_t len = len1 + len2 + 3;
  2357     char * result = realloc(str1, len + 1);
  2358 
  2359     if (result) {
  2360         result[len1] = '"';
  2361         strcpy(result + len1 + 1, str2);
  2362         result[len - 2] = '"';
  2363         result[len - 1] = delim;
  2364         result[len] = 0;
  2365     }
  2366     else {
  2367         free(str1);
  2368     }
  2369 
  2370     return result;
  2371 }
  2372 
  2373 DYNAMIC_API PEP_STATUS get_crashdump_log(
  2374         PEP_SESSION session,
  2375         int maxlines,
  2376         char **logdata
  2377     )
  2378 {
  2379     PEP_STATUS status = PEP_STATUS_OK;
  2380     char *_logdata= NULL;
  2381 
  2382     assert(session);
  2383     assert(maxlines >= 0 && maxlines <= CRASHDUMP_MAX_LINES);
  2384     assert(logdata);
  2385 
  2386     if (!(session && logdata && maxlines >= 0 && maxlines <=
  2387             CRASHDUMP_MAX_LINES))
  2388         return PEP_ILLEGAL_VALUE;
  2389 
  2390     *logdata = NULL;
  2391 
  2392     int limit = maxlines ? maxlines : CRASHDUMP_DEFAULT_LINES;
  2393     const char *timestamp = NULL;
  2394     const char *title = NULL;
  2395     const char *entity = NULL;
  2396     const char *desc = NULL;
  2397     const char *comment = NULL;
  2398 
  2399     sqlite3_reset(session->crashdump);
  2400     sqlite3_bind_int(session->crashdump, 1, limit);
  2401 
  2402     int result;
  2403 
  2404     do {
  2405         result = sqlite3_step(session->crashdump);
  2406         switch (result) {
  2407         case SQLITE_ROW:
  2408             timestamp = (const char *) sqlite3_column_text(session->crashdump,
  2409                     0);
  2410             title   = (const char *) sqlite3_column_text(session->crashdump,
  2411                     1);
  2412             entity  = (const char *) sqlite3_column_text(session->crashdump,
  2413                     2);
  2414             desc    = (const char *) sqlite3_column_text(session->crashdump,
  2415                     3);
  2416             comment = (const char *) sqlite3_column_text(session->crashdump,
  2417                     4);
  2418 
  2419             _logdata = _concat_string(_logdata, timestamp, ',');
  2420             if (_logdata == NULL)
  2421                 goto enomem;
  2422 
  2423             _logdata = _concat_string(_logdata, title, ',');
  2424             if (_logdata == NULL)
  2425                 goto enomem;
  2426 
  2427             _logdata = _concat_string(_logdata, entity, ',');
  2428             if (_logdata == NULL)
  2429                 goto enomem;
  2430 
  2431             _logdata = _concat_string(_logdata, desc, ',');
  2432             if (_logdata == NULL)
  2433                 goto enomem;
  2434 
  2435             _logdata = _concat_string(_logdata, comment, '\n');
  2436             if (_logdata == NULL)
  2437                 goto enomem;
  2438 
  2439             _clean_log_value(_logdata);
  2440             break;
  2441 
  2442         case SQLITE_DONE:
  2443             break;
  2444 
  2445         default:
  2446             status = PEP_UNKNOWN_ERROR;
  2447             result = SQLITE_DONE;
  2448         }
  2449     } while (result != SQLITE_DONE);
  2450 
  2451     sqlite3_reset(session->crashdump);
  2452     if (status == PEP_STATUS_OK)
  2453         *logdata = _logdata;
  2454 
  2455     goto the_end;
  2456 
  2457 enomem:
  2458     status = PEP_OUT_OF_MEMORY;
  2459 
  2460 the_end:
  2461     return ADD_TO_LOG(status);
  2462 }
  2463 
  2464 DYNAMIC_API PEP_STATUS get_languagelist(
  2465         PEP_SESSION session,
  2466         char **languages
  2467     )
  2468 {
  2469     PEP_STATUS status = PEP_STATUS_OK;
  2470     char *_languages= NULL;
  2471 
  2472     assert(session);
  2473     assert(languages);
  2474 
  2475     if (!(session && languages))
  2476         return PEP_ILLEGAL_VALUE;
  2477 
  2478     *languages = NULL;
  2479 
  2480     const char *lang = NULL;
  2481     const char *name = NULL;
  2482     const char *phrase = NULL;
  2483 
  2484     sqlite3_reset(session->languagelist);
  2485 
  2486     int result;
  2487 
  2488     do {
  2489         result = sqlite3_step(session->languagelist);
  2490         switch (result) {
  2491         case SQLITE_ROW:
  2492             lang = (const char *) sqlite3_column_text(session->languagelist,
  2493                     0);
  2494             name = (const char *) sqlite3_column_text(session->languagelist,
  2495                     1);
  2496             phrase = (const char *) sqlite3_column_text(session->languagelist,
  2497                     2);
  2498 
  2499             _languages = _concat_string(_languages, lang, ',');
  2500             if (_languages == NULL)
  2501                 goto enomem;
  2502 
  2503             _languages = _concat_string(_languages, name, ',');
  2504             if (_languages == NULL)
  2505                 goto enomem;
  2506 
  2507             _languages = _concat_string(_languages, phrase, '\n');
  2508             if (_languages == NULL)
  2509                 goto enomem;
  2510 
  2511             break;
  2512 
  2513         case SQLITE_DONE:
  2514             break;
  2515 
  2516         default:
  2517             status = PEP_UNKNOWN_ERROR;
  2518             result = SQLITE_DONE;
  2519         }
  2520     } while (result != SQLITE_DONE);
  2521 
  2522     sqlite3_reset(session->languagelist);
  2523     if (status == PEP_STATUS_OK)
  2524         *languages = _languages;
  2525 
  2526     goto the_end;
  2527 
  2528 enomem:
  2529     status = PEP_OUT_OF_MEMORY;
  2530 
  2531 the_end:
  2532     return status;
  2533 }
  2534 
  2535 DYNAMIC_API PEP_STATUS get_phrase(
  2536         PEP_SESSION session,
  2537         const char *lang,
  2538         int phrase_id,
  2539         char **phrase
  2540     )
  2541 {
  2542     PEP_STATUS status = PEP_STATUS_OK;
  2543 
  2544     assert(session && lang && lang[0] && lang[1] && lang[2] == 0 && phrase);
  2545     if (!(session && lang && lang[0] && lang[1] && lang[2] == 0 && phrase))
  2546         return PEP_ILLEGAL_VALUE;
  2547 
  2548     *phrase = NULL;
  2549 
  2550     sqlite3_reset(session->i18n_token);
  2551     sqlite3_bind_text(session->i18n_token, 1, lang, -1, SQLITE_STATIC);
  2552     sqlite3_bind_int(session->i18n_token, 2, phrase_id);
  2553 
  2554     const char *_phrase = NULL;
  2555     int result;
  2556 
  2557     result = sqlite3_step(session->i18n_token);
  2558     switch (result) {
  2559     case SQLITE_ROW:
  2560         _phrase = (const char *) sqlite3_column_text(session->i18n_token, 0);
  2561         break;
  2562 
  2563     case SQLITE_DONE:
  2564         status = PEP_PHRASE_NOT_FOUND;
  2565         break;
  2566 
  2567     default:
  2568         status = PEP_UNKNOWN_ERROR;
  2569     }
  2570 
  2571     if (status == PEP_STATUS_OK) {
  2572         *phrase = strdup(_phrase);
  2573         if (*phrase == NULL)
  2574             goto enomem;
  2575     }
  2576 
  2577     sqlite3_reset(session->i18n_token);
  2578     goto the_end;
  2579 
  2580 enomem:
  2581     status = PEP_OUT_OF_MEMORY;
  2582 
  2583 the_end:
  2584     return status;
  2585 }
  2586 
  2587 static PEP_STATUS _get_sequence_value(PEP_SESSION session, const char *name,
  2588         int32_t *value)
  2589 {
  2590     assert(session && name && value);
  2591     if (!(session && name && value))
  2592         return PEP_ILLEGAL_VALUE;
  2593 
  2594     PEP_STATUS status = PEP_STATUS_OK;
  2595 
  2596     sqlite3_reset(session->sequence_value2);
  2597     sqlite3_bind_text(session->sequence_value2, 1, name, -1,
  2598             SQLITE_STATIC);
  2599     int result = sqlite3_step(session->sequence_value2);
  2600     switch (result) {
  2601         case SQLITE_ROW: {
  2602             int32_t _value = (int32_t)
  2603                     sqlite3_column_int(session->sequence_value2, 0);
  2604             int _own = (int)
  2605                     sqlite3_column_int(session->sequence_value2, 1);
  2606             *value = _value;
  2607             if (_own)
  2608                 status = PEP_OWN_SEQUENCE;
  2609             break;
  2610         }
  2611         case SQLITE_DONE:
  2612             status = PEP_RECORD_NOT_FOUND;
  2613             break;
  2614         default:
  2615             status = PEP_UNKNOWN_ERROR;
  2616     }
  2617     sqlite3_reset(session->sequence_value2);
  2618 
  2619     return status;
  2620 }
  2621 
  2622 static PEP_STATUS _increment_sequence_value(PEP_SESSION session,
  2623         const char *name, int own)
  2624 {
  2625     assert(session && name);
  2626     if (!(session && name))
  2627         return PEP_ILLEGAL_VALUE;
  2628 
  2629     sqlite3_reset(session->sequence_value1);
  2630     sqlite3_bind_text(session->sequence_value1, 1, name, -1, SQLITE_STATIC);
  2631     sqlite3_bind_int(session->sequence_value1, 2, own);
  2632     int result = sqlite3_step(session->sequence_value1);
  2633     assert(result == SQLITE_DONE);
  2634     sqlite3_reset(session->sequence_value1);
  2635     if (result == SQLITE_DONE)
  2636         return PEP_STATUS_OK;
  2637     else
  2638         return PEP_CANNOT_INCREASE_SEQUENCE;
  2639 }
  2640 
  2641 static PEP_STATUS _set_sequence_value(PEP_SESSION session,
  2642         const char *name, int32_t value, int own)
  2643 {
  2644     assert(session && name && value > 0);
  2645     if (!(session && name && value > 0))
  2646         return PEP_ILLEGAL_VALUE;
  2647 
  2648     sqlite3_reset(session->sequence_value3);
  2649     sqlite3_bind_text(session->sequence_value3, 1, name, -1, SQLITE_STATIC);
  2650     sqlite3_bind_int(session->sequence_value3, 2, value);
  2651     sqlite3_bind_int(session->sequence_value3, 3, own);
  2652     int result = sqlite3_step(session->sequence_value3);
  2653     assert(result == SQLITE_DONE);
  2654     sqlite3_reset(session->sequence_value3);
  2655     if (result == SQLITE_DONE)
  2656         return PEP_STATUS_OK;
  2657     else
  2658         return PEP_CANNOT_SET_SEQUENCE_VALUE;
  2659 }
  2660 
  2661 DYNAMIC_API PEP_STATUS sequence_value(
  2662         PEP_SESSION session,
  2663         char *name,
  2664         int32_t *value
  2665     )
  2666 {
  2667     PEP_STATUS status = PEP_STATUS_OK;
  2668     int result;
  2669 
  2670     assert(session);
  2671     assert(name && value && *value >= 0);
  2672 
  2673     if (!(session && name && value && *value >= 0))
  2674         return PEP_ILLEGAL_VALUE;
  2675 
  2676     int own = 0;
  2677     if (!name[0]) {
  2678         pEpUUID uuid;
  2679         uuid_generate_random(uuid);
  2680         uuid_unparse_upper(uuid, name);
  2681         own = 1;
  2682     }
  2683     else {
  2684         if (name == session->sync_session->sync_uuid || 
  2685             strcmp(name, session->sync_session->sync_uuid) == 0)
  2686             own = 1;
  2687     }
  2688 
  2689     if (*value) {
  2690         sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
  2691         int32_t old_value = 0;
  2692         status = _get_sequence_value(session, name, &old_value);
  2693         if (status != PEP_STATUS_OK && status != PEP_RECORD_NOT_FOUND)
  2694         {
  2695             sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  2696             return status;
  2697         }
  2698 
  2699         if (old_value >= *value) {
  2700             sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  2701             return PEP_SEQUENCE_VIOLATED;
  2702         }
  2703         else {
  2704             status = _set_sequence_value(session, name, *value, own);
  2705             if (status == PEP_STATUS_OK) {
  2706                 result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
  2707                 if (result == SQLITE_OK)
  2708                     return PEP_STATUS_OK;
  2709                 else
  2710                     return PEP_COMMIT_FAILED;
  2711             } else {
  2712                 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  2713                 return status;
  2714             }
  2715         }
  2716     }
  2717 
  2718     assert(*value == 0);
  2719     sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
  2720     status = _increment_sequence_value(session, name, own);
  2721     if (status == PEP_STATUS_OK) {
  2722         status = _get_sequence_value(session, name, value);
  2723     }
  2724     if (status == PEP_STATUS_OK || status == PEP_OWN_SEQUENCE) {
  2725         result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
  2726         if (result == SQLITE_OK){
  2727             assert(*value < INT32_MAX);
  2728             if (*value == INT32_MAX){
  2729                 return PEP_CANNOT_INCREASE_SEQUENCE;
  2730             }
  2731             return status;
  2732         } else {
  2733             return PEP_COMMIT_FAILED;
  2734         }
  2735     } else {
  2736         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  2737         return status;
  2738     }
  2739     return status;
  2740 }
  2741 
  2742 DYNAMIC_API PEP_STATUS set_revoked(
  2743        PEP_SESSION session,
  2744        const char *revoked_fpr,
  2745        const char *replacement_fpr,
  2746        const uint64_t revocation_date
  2747     )
  2748 {
  2749     PEP_STATUS status = PEP_STATUS_OK;
  2750     
  2751     assert(session &&
  2752            revoked_fpr && revoked_fpr[0] &&
  2753            replacement_fpr && replacement_fpr[0]
  2754           );
  2755     
  2756     if (!(session &&
  2757           revoked_fpr && revoked_fpr[0] &&
  2758           replacement_fpr && replacement_fpr[0]
  2759          ))
  2760         return PEP_ILLEGAL_VALUE;
  2761     
  2762     sqlite3_reset(session->set_revoked);
  2763     sqlite3_bind_text(session->set_revoked, 1, revoked_fpr, -1, SQLITE_STATIC);
  2764     sqlite3_bind_text(session->set_revoked, 2, replacement_fpr, -1,
  2765             SQLITE_STATIC);
  2766     sqlite3_bind_int64(session->set_revoked, 3, revocation_date);
  2767 
  2768     int result;
  2769     
  2770     result = sqlite3_step(session->set_revoked);
  2771     switch (result) {
  2772         case SQLITE_DONE:
  2773             status = PEP_STATUS_OK;
  2774             break;
  2775             
  2776         default:
  2777             status = PEP_UNKNOWN_ERROR;
  2778     }
  2779     
  2780     sqlite3_reset(session->set_revoked);
  2781     return status;
  2782 }
  2783 
  2784 DYNAMIC_API PEP_STATUS get_revoked(
  2785         PEP_SESSION session,
  2786         const char *fpr,
  2787         char **revoked_fpr,
  2788         uint64_t *revocation_date
  2789     )
  2790 {
  2791     PEP_STATUS status = PEP_STATUS_OK;
  2792 
  2793     assert(session &&
  2794            revoked_fpr &&
  2795            fpr && fpr[0]
  2796           );
  2797     
  2798     if (!(session &&
  2799            revoked_fpr &&
  2800            fpr && fpr[0]
  2801           ))
  2802         return PEP_ILLEGAL_VALUE;
  2803 
  2804     *revoked_fpr = NULL;
  2805     *revocation_date = 0;
  2806 
  2807     sqlite3_reset(session->get_revoked);
  2808     sqlite3_bind_text(session->get_revoked, 1, fpr, -1, SQLITE_STATIC);
  2809 
  2810     int result;
  2811     
  2812     result = sqlite3_step(session->get_revoked);
  2813     switch (result) {
  2814         case SQLITE_ROW: {
  2815             *revoked_fpr = strdup((const char *)
  2816                     sqlite3_column_text(session->get_revoked, 0));
  2817             if(*revoked_fpr)
  2818                 *revocation_date = sqlite3_column_int64(session->get_revoked,
  2819                         1);
  2820             else
  2821                 status = PEP_OUT_OF_MEMORY;
  2822 
  2823             break;
  2824         }
  2825         default:
  2826             status = PEP_CANNOT_FIND_IDENTITY;
  2827     }
  2828 
  2829     sqlite3_reset(session->get_revoked);
  2830 
  2831     return status;
  2832 }
  2833 
  2834 PEP_STATUS key_created(
  2835         PEP_SESSION session,
  2836         const char *fpr,
  2837         time_t *created
  2838     )
  2839 {
  2840     assert(session && fpr && created);
  2841     if (!(session && fpr && created))
  2842         return PEP_ILLEGAL_VALUE;
  2843 
  2844     return session->cryptotech[PEP_crypt_OpenPGP].key_created(session, fpr,
  2845             created);
  2846 }
  2847 
  2848 PEP_STATUS find_private_keys(PEP_SESSION session, const char* pattern,
  2849                              stringlist_t **keylist) {
  2850     assert(session && keylist);
  2851     if (!(session && keylist))
  2852         return PEP_ILLEGAL_VALUE;
  2853     
  2854     return session->cryptotech[PEP_crypt_OpenPGP].find_private_keys(session, pattern,
  2855                                                                     keylist);
  2856 }
  2857 
  2858 DYNAMIC_API const char* get_engine_version() {
  2859     return PEP_ENGINE_VERSION;
  2860 }
  2861 
  2862 
  2863 DYNAMIC_API PEP_STATUS reset_peptest_hack(PEP_SESSION session)
  2864 {
  2865     assert(session);
  2866 
  2867     if (!session)
  2868         return PEP_ILLEGAL_VALUE;
  2869 
  2870     int int_result = sqlite3_exec(
  2871         session->db,
  2872         "delete from identity where address like '%@peptest.ch' ;",
  2873         NULL,
  2874         NULL,
  2875         NULL
  2876     );
  2877     assert(int_result == SQLITE_OK);
  2878 
  2879     if (int_result != SQLITE_OK)
  2880         return PEP_UNKNOWN_ERROR;
  2881 
  2882     return PEP_STATUS_OK;
  2883 }
  2884 
  2885 #ifdef DEBUG_ERRORSTACK
  2886 PEP_STATUS session_add_error(PEP_SESSION session, const char* file, unsigned line, PEP_STATUS status)
  2887 {
  2888     char logline[48];
  2889     if(status>0)
  2890     {
  2891         snprintf(logline,47, "%.24s:%u status=%u (0x%x)", file, line, status, status);
  2892     }else{
  2893         snprintf(logline,47, "%.24s:%u status=%i.", file, line, status);
  2894     }
  2895     stringlist_add(session->errorstack, logline); // logline is copied! :-)
  2896     return status;
  2897 }
  2898 
  2899 DYNAMIC_API const stringlist_t* get_errorstack(PEP_SESSION session)
  2900 {
  2901     return session->errorstack;
  2902 }
  2903 
  2904 DYNAMIC_API void clear_errorstack(PEP_SESSION session)
  2905 {
  2906     const int old_len = stringlist_length(session->errorstack);
  2907     char buf[48];
  2908     free_stringlist(session->errorstack);
  2909     snprintf(buf, 47, "(%i elements cleared)", old_len);
  2910     session->errorstack = new_stringlist(buf);
  2911 }
  2912 
  2913 #else
  2914 
  2915 static stringlist_t* dummy_errorstack = NULL;
  2916 
  2917 DYNAMIC_API const stringlist_t* get_errorstack(PEP_SESSION session)
  2918 {
  2919     if(dummy_errorstack == NULL)
  2920     {
  2921         dummy_errorstack = new_stringlist("( Please recompile pEpEngine with -DDEBUG_ERRORSTACK )");
  2922     }
  2923 
  2924     return dummy_errorstack;
  2925 }
  2926 
  2927 DYNAMIC_API void clear_errorstack(PEP_SESSION session)
  2928 {
  2929     // nothing to do here
  2930 }
  2931 
  2932 #endif