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