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