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