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