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