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