src/pEpEngine.c
author Edouard Tisserant <edouard@pep-project.org>
Fri, 30 Jun 2017 16:33:08 +0200
branchtest_diphoton
changeset 1903 c2a9a756b1f5
parent 1860 1975a3b9bc37
parent 1887 3feebd18c35f
child 2089 174f5577c0aa
permissions -rw-r--r--
Merged changes from default
     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->me = src->me;
  1150     dup->flags = src->flags;
  1151 
  1152     return dup;
  1153 }
  1154 
  1155 void free_identity(pEp_identity *identity)
  1156 {
  1157     if (identity) {
  1158         free(identity->address);
  1159         free(identity->fpr);
  1160         free(identity->user_id);
  1161         free(identity->username);
  1162         free(identity);
  1163     }
  1164 }
  1165 
  1166 DYNAMIC_API PEP_STATUS get_identity(
  1167         PEP_SESSION session,
  1168         const char *address,
  1169         const char *user_id,
  1170         pEp_identity **identity
  1171     )
  1172 {
  1173     PEP_STATUS status = PEP_STATUS_OK;
  1174     static pEp_identity *_identity;
  1175 
  1176     assert(session);
  1177     assert(address);
  1178     assert(address[0]);
  1179     assert(identity);
  1180 
  1181     if (!(session && address && address[0] && identity))
  1182         return PEP_ILLEGAL_VALUE;
  1183 
  1184     *identity = NULL;
  1185 
  1186     sqlite3_reset(session->get_identity);
  1187     sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
  1188     sqlite3_bind_text(session->get_identity, 2, user_id, -1, SQLITE_STATIC);
  1189 
  1190     const int result = sqlite3_step(session->get_identity);
  1191     switch (result) {
  1192     case SQLITE_ROW:
  1193         _identity = new_identity(
  1194                 address,
  1195                 (const char *) sqlite3_column_text(session->get_identity, 0),
  1196                 user_id,
  1197                 (const char *) sqlite3_column_text(session->get_identity, 1)
  1198                 );
  1199         assert(_identity);
  1200         if (_identity == NULL)
  1201             return PEP_OUT_OF_MEMORY;
  1202 
  1203         _identity->comm_type = (PEP_comm_type)
  1204             sqlite3_column_int(session->get_identity, 2);
  1205         const char* const _lang = (const char *)
  1206             sqlite3_column_text(session->get_identity, 3);
  1207         if (_lang && _lang[0]) {
  1208             assert(_lang[0] >= 'a' && _lang[0] <= 'z');
  1209             assert(_lang[1] >= 'a' && _lang[1] <= 'z');
  1210             assert(_lang[2] == 0);
  1211             _identity->lang[0] = _lang[0];
  1212             _identity->lang[1] = _lang[1];
  1213             _identity->lang[2] = 0;
  1214         }
  1215         _identity->flags = (unsigned int)
  1216             sqlite3_column_int(session->get_identity, 4);
  1217         *identity = _identity;
  1218         break;
  1219     default:
  1220         status = PEP_CANNOT_FIND_IDENTITY;
  1221         *identity = NULL;
  1222     }
  1223 
  1224     sqlite3_reset(session->get_identity);
  1225     return status;
  1226 }
  1227 
  1228 DYNAMIC_API PEP_STATUS set_identity(
  1229         PEP_SESSION session, const pEp_identity *identity
  1230     )
  1231 {
  1232     int result;
  1233 
  1234     assert(session);
  1235     assert(identity);
  1236     assert(identity->address);
  1237     assert(identity->user_id);
  1238     assert(identity->username);
  1239 
  1240     if (!(session && identity && identity->address &&
  1241                 identity->user_id && identity->username))
  1242         return PEP_ILLEGAL_VALUE;
  1243 
  1244     PEP_STATUS status = PEP_STATUS_OK;
  1245     
  1246     bool listed;
  1247 
  1248     bool has_fpr = (identity->fpr && identity->fpr[0] != '\0');
  1249     
  1250     if (has_fpr) {    
  1251         // blacklist check
  1252         status = blacklist_is_listed(session, identity->fpr, &listed);
  1253         assert(status == PEP_STATUS_OK);
  1254         if (status != PEP_STATUS_OK)
  1255             return status;
  1256 
  1257         if (listed)
  1258             return PEP_KEY_BLACKLISTED;
  1259     }
  1260 
  1261     sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
  1262 
  1263     if (identity->lang[0]) {
  1264         assert(identity->lang[0] >= 'a' && identity->lang[0] <= 'z');
  1265         assert(identity->lang[1] >= 'a' && identity->lang[1] <= 'z');
  1266         assert(identity->lang[2] == 0);
  1267     }
  1268 
  1269     sqlite3_reset(session->set_person);
  1270     sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
  1271             SQLITE_STATIC);
  1272     sqlite3_bind_text(session->set_person, 2, identity->username, -1,
  1273             SQLITE_STATIC);
  1274     if (identity->lang[0])
  1275         sqlite3_bind_text(session->set_person, 3, identity->lang, 2,
  1276                 SQLITE_STATIC);
  1277     else
  1278         sqlite3_bind_null(session->set_person, 3);
  1279     sqlite3_bind_text(session->set_person, 4, identity->fpr, -1,
  1280                       SQLITE_STATIC);
  1281     result = sqlite3_step(session->set_person);
  1282     sqlite3_reset(session->set_person);
  1283     if (result != SQLITE_DONE) {
  1284         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1285         return PEP_CANNOT_SET_PERSON;
  1286     }
  1287 
  1288     if (has_fpr) {
  1289         sqlite3_reset(session->set_pgp_keypair);
  1290         sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
  1291                 SQLITE_STATIC);
  1292         result = sqlite3_step(session->set_pgp_keypair);
  1293         sqlite3_reset(session->set_pgp_keypair);
  1294         if (result != SQLITE_DONE) {
  1295             sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1296             return PEP_CANNOT_SET_PGP_KEYPAIR;
  1297         }
  1298     }
  1299 
  1300     sqlite3_reset(session->set_identity);
  1301     sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
  1302             SQLITE_STATIC);
  1303     sqlite3_bind_text(session->set_identity, 2, identity->fpr, -1,
  1304             SQLITE_STATIC);
  1305     sqlite3_bind_text(session->set_identity, 3, identity->user_id, -1,
  1306             SQLITE_STATIC);
  1307     sqlite3_bind_int(session->set_identity, 4, identity->flags);
  1308     result = sqlite3_step(session->set_identity);
  1309     sqlite3_reset(session->set_identity);
  1310     if (result != SQLITE_DONE) {
  1311         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1312         return PEP_CANNOT_SET_IDENTITY;
  1313     }
  1314 
  1315     if (has_fpr) {
  1316         if(strcmp(identity->user_id, PEP_OWN_USERID) == 0) {
  1317             sqlite3_reset(session->set_own_key);
  1318             sqlite3_bind_text(session->set_own_key, 1, identity->address, -1,
  1319                 SQLITE_STATIC);
  1320             sqlite3_bind_text(session->set_own_key, 2, identity->fpr, -1,
  1321                 SQLITE_STATIC);
  1322             result = sqlite3_step(session->set_own_key);
  1323             sqlite3_reset(session->set_own_key);
  1324             if (result != SQLITE_DONE) {
  1325                 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1326                 return PEP_CANNOT_SET_PGP_KEYPAIR;
  1327             }
  1328         }
  1329 
  1330         // status = set_trust(session, identity->user_id, identity->fpr,
  1331         //                    identity->comm_type)
  1332         sqlite3_reset(session->set_trust);
  1333         sqlite3_bind_text(session->set_trust, 1, identity->user_id, -1,
  1334                 SQLITE_STATIC);
  1335         sqlite3_bind_text(session->set_trust, 2, identity->fpr, -1,
  1336                 SQLITE_STATIC);
  1337         sqlite3_bind_int(session->set_trust, 3, identity->comm_type);
  1338         result = sqlite3_step(session->set_trust);
  1339         sqlite3_reset(session->set_trust);
  1340         if (result != SQLITE_DONE) {
  1341             sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1342             return PEP_CANNOT_SET_TRUST;
  1343         }
  1344     }
  1345     
  1346     result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
  1347     if (result == SQLITE_OK)
  1348         return PEP_STATUS_OK;
  1349     else
  1350         return PEP_COMMIT_FAILED;
  1351 }
  1352 
  1353 PEP_STATUS replace_identities_fpr(PEP_SESSION session, 
  1354                                  const char* old_fpr, 
  1355                                  const char* new_fpr) 
  1356 {
  1357     assert(old_fpr);
  1358     assert(new_fpr);
  1359     
  1360     if (!old_fpr || !new_fpr)
  1361         return PEP_ILLEGAL_VALUE;
  1362             
  1363     sqlite3_reset(session->replace_identities_fpr);
  1364     sqlite3_bind_text(session->replace_identities_fpr, 1, new_fpr, -1,
  1365                       SQLITE_STATIC);
  1366     sqlite3_bind_text(session->replace_identities_fpr, 2, old_fpr, -1,
  1367                       SQLITE_STATIC);
  1368 
  1369     int result = sqlite3_step(session->replace_identities_fpr);
  1370     sqlite3_reset(session->replace_identities_fpr);
  1371     
  1372     if (result != SQLITE_DONE)
  1373         return PEP_CANNOT_SET_IDENTITY;
  1374 
  1375     return PEP_STATUS_OK;
  1376 }
  1377 
  1378 
  1379 PEP_STATUS update_trust_for_fpr(PEP_SESSION session, 
  1380                                 const char* fpr, 
  1381                                 PEP_comm_type comm_type)
  1382 {
  1383     if (!fpr)
  1384         return PEP_ILLEGAL_VALUE;
  1385         
  1386     sqlite3_reset(session->update_trust_for_fpr);
  1387     sqlite3_bind_int(session->update_trust_for_fpr, 1, comm_type);
  1388     sqlite3_bind_text(session->update_trust_for_fpr, 2, fpr, -1,
  1389             SQLITE_STATIC);
  1390     int result = sqlite3_step(session->update_trust_for_fpr);
  1391     sqlite3_reset(session->update_trust_for_fpr);
  1392     if (result != SQLITE_DONE) {
  1393         return PEP_CANNOT_SET_TRUST;
  1394     }
  1395     
  1396     return PEP_STATUS_OK;
  1397 }
  1398 
  1399 DYNAMIC_API PEP_STATUS set_device_group(
  1400         PEP_SESSION session,
  1401         const char *group_name
  1402     )
  1403 {
  1404     int result;
  1405 
  1406     assert(session);
  1407 
  1408     if (!(session && group_name))
  1409         return PEP_ILLEGAL_VALUE;
  1410 
  1411     sqlite3_reset(session->set_device_group);
  1412     if(group_name){
  1413         sqlite3_bind_text(session->set_device_group, 1, group_name, -1,
  1414                 SQLITE_STATIC);
  1415     } else {
  1416         sqlite3_bind_null(session->set_device_group, 1);
  1417     }
  1418 
  1419     result = sqlite3_step(session->set_device_group);
  1420     sqlite3_reset(session->set_device_group);
  1421     if (result != SQLITE_DONE)
  1422         return PEP_CANNOT_SET_PERSON;
  1423 
  1424     return PEP_STATUS_OK;
  1425 }
  1426 
  1427 DYNAMIC_API PEP_STATUS get_device_group(PEP_SESSION session, char **group_name)
  1428 {
  1429     PEP_STATUS status = PEP_STATUS_OK;
  1430     int result;
  1431 
  1432     assert(session);
  1433     assert(group_name);
  1434 
  1435     if (!(session && group_name))
  1436         return PEP_ILLEGAL_VALUE;
  1437 
  1438     sqlite3_reset(session->get_device_group);
  1439 
  1440     result = sqlite3_step(session->get_device_group);
  1441     switch (result) {
  1442     case SQLITE_ROW: {
  1443         const char *_group_name = (const char *)sqlite3_column_text(session->get_device_group, 0);
  1444         if(_group_name){
  1445             *group_name = strdup(_group_name);
  1446                 if(*group_name == NULL)
  1447                     status = PEP_OUT_OF_MEMORY;
  1448         }
  1449         break;
  1450     }
  1451  
  1452     default:
  1453         status = PEP_RECORD_NOT_FOUND;
  1454     }
  1455 
  1456     sqlite3_reset(session->get_device_group);
  1457     return status;
  1458 }
  1459 
  1460 DYNAMIC_API PEP_STATUS set_identity_flags(
  1461         PEP_SESSION session,
  1462         pEp_identity *identity,
  1463         unsigned int flags
  1464     )
  1465 {
  1466     int result;
  1467 
  1468     assert(session);
  1469     assert(identity);
  1470     assert(identity->address);
  1471     assert(identity->user_id);
  1472 
  1473     if (!(session && identity && identity->address && identity->user_id))
  1474         return PEP_ILLEGAL_VALUE;
  1475 
  1476     sqlite3_reset(session->set_identity_flags);
  1477     sqlite3_bind_int(session->set_identity_flags, 1, flags);
  1478     sqlite3_bind_text(session->set_identity_flags, 2, identity->address, -1,
  1479             SQLITE_STATIC);
  1480     sqlite3_bind_text(session->set_identity_flags, 3, identity->user_id, -1,
  1481             SQLITE_STATIC);
  1482     result = sqlite3_step(session->set_identity_flags);
  1483     sqlite3_reset(session->set_identity_flags);
  1484     if (result != SQLITE_DONE)
  1485         return PEP_CANNOT_SET_IDENTITY;
  1486 
  1487     identity->flags |= flags;
  1488     return PEP_STATUS_OK;
  1489 }
  1490 
  1491 DYNAMIC_API PEP_STATUS unset_identity_flags(
  1492         PEP_SESSION session,
  1493         pEp_identity *identity,
  1494         unsigned int flags
  1495     )
  1496 {
  1497     int result;
  1498 
  1499     assert(session);
  1500     assert(identity);
  1501     assert(identity->address);
  1502     assert(identity->user_id);
  1503 
  1504     if (!(session && identity && identity->address && identity->user_id))
  1505         return PEP_ILLEGAL_VALUE;
  1506 
  1507     // test_diphoton : dirty hack to prevent more than one sync enabled account
  1508     if (flags & PEP_idf_not_for_sync){
  1509         identity_list *own_identities = NULL;
  1510         if (_own_identities_retrieve(session, &own_identities, PEP_idf_not_for_sync) == PEP_STATUS_OK)
  1511             // if at least one _other_ own address is sync enabled, prevent unseting exclusion
  1512             for (identity_list *_i = own_identities; _i && _i->ident; _i = _i->next) {
  1513                 pEp_identity *me = _i->ident;
  1514                 if(me->address && strcmp(me->address, identity->address) != 0)
  1515                 flags &= ~PEP_idf_not_for_sync;
  1516                 break;
  1517             }
  1518         free_identity_list(own_identities);
  1519     }
  1520 
  1521     sqlite3_reset(session->unset_identity_flags);
  1522     sqlite3_bind_int(session->unset_identity_flags, 1, flags);
  1523     sqlite3_bind_text(session->unset_identity_flags, 2, identity->address, -1,
  1524             SQLITE_STATIC);
  1525     sqlite3_bind_text(session->unset_identity_flags, 3, identity->user_id, -1,
  1526             SQLITE_STATIC);
  1527     result = sqlite3_step(session->unset_identity_flags);
  1528     sqlite3_reset(session->unset_identity_flags);
  1529     if (result != SQLITE_DONE)
  1530         return PEP_CANNOT_SET_IDENTITY;
  1531 
  1532     identity->flags &= ~flags;
  1533     return PEP_STATUS_OK;
  1534 }
  1535 
  1536 DYNAMIC_API PEP_STATUS mark_as_compromized(
  1537         PEP_SESSION session,
  1538         const char *fpr
  1539     )
  1540 {
  1541     int result;
  1542 
  1543     assert(session);
  1544     assert(fpr && fpr[0]);
  1545 
  1546     if (!(session && fpr && fpr[0]))
  1547         return PEP_ILLEGAL_VALUE;
  1548 
  1549     sqlite3_reset(session->mark_compromized);
  1550     sqlite3_bind_text(session->mark_compromized, 1, fpr, -1,
  1551             SQLITE_STATIC);
  1552     result = sqlite3_step(session->mark_compromized);
  1553     sqlite3_reset(session->mark_compromized);
  1554 
  1555     if (result != SQLITE_DONE)
  1556         return PEP_CANNOT_SET_TRUST;
  1557 
  1558     return PEP_STATUS_OK;
  1559 }
  1560 
  1561 void pEp_free(void *p)
  1562 {
  1563     free(p);
  1564 }
  1565 
  1566 DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
  1567 {
  1568     PEP_STATUS status = PEP_STATUS_OK;
  1569     int result;
  1570 
  1571     assert(session);
  1572     assert(identity);
  1573     assert(identity->user_id);
  1574     assert(identity->user_id[0]);
  1575     assert(identity->fpr);
  1576     assert(identity->fpr[0]);
  1577 
  1578     if (!(session && identity && identity->user_id && identity->user_id[0] &&
  1579                 identity->fpr && identity->fpr[0]))
  1580         return PEP_ILLEGAL_VALUE;
  1581 
  1582     identity->comm_type = PEP_ct_unknown;
  1583 
  1584     sqlite3_reset(session->get_trust);
  1585     sqlite3_bind_text(session->get_trust, 1, identity->user_id, -1,
  1586             SQLITE_STATIC);
  1587     sqlite3_bind_text(session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
  1588 
  1589     result = sqlite3_step(session->get_trust);
  1590     switch (result) {
  1591     case SQLITE_ROW: {
  1592         int comm_type = (PEP_comm_type) sqlite3_column_int(session->get_trust,
  1593                 0);
  1594         identity->comm_type = comm_type;
  1595         break;
  1596     }
  1597  
  1598     default:
  1599         status = PEP_CANNOT_FIND_IDENTITY;
  1600     }
  1601 
  1602     sqlite3_reset(session->get_trust);
  1603     return status;
  1604 }
  1605 
  1606 DYNAMIC_API PEP_STATUS least_trust(
  1607         PEP_SESSION session,
  1608         const char *fpr,
  1609         PEP_comm_type *comm_type
  1610     )
  1611 {
  1612     PEP_STATUS status = PEP_STATUS_OK;
  1613     int result;
  1614 
  1615     assert(session);
  1616     assert(fpr);
  1617     assert(comm_type);
  1618 
  1619     if (!(session && fpr && comm_type))
  1620         return PEP_ILLEGAL_VALUE;
  1621 
  1622     *comm_type = PEP_ct_unknown;
  1623 
  1624     sqlite3_reset(session->least_trust);
  1625     sqlite3_bind_text(session->least_trust, 1, fpr, -1, SQLITE_STATIC);
  1626 
  1627     result = sqlite3_step(session->least_trust);
  1628     switch (result) {
  1629         case SQLITE_ROW: {
  1630             int _comm_type = sqlite3_column_int(session->least_trust, 0);
  1631             *comm_type = (PEP_comm_type) _comm_type;
  1632             break;
  1633         }
  1634         default:
  1635             // never reached because of sql min()
  1636             status = PEP_CANNOT_FIND_IDENTITY;
  1637     }
  1638 
  1639     sqlite3_reset(session->least_trust);
  1640     return status;
  1641 }
  1642 
  1643 DYNAMIC_API PEP_STATUS decrypt_and_verify(
  1644     PEP_SESSION session, const char *ctext, size_t csize,
  1645     const char *dsigtext, size_t dsigsize,
  1646     char **ptext, size_t *psize, stringlist_t **keylist
  1647     )
  1648 {
  1649     assert(session);
  1650     assert(ctext);
  1651     assert(csize);
  1652     assert(ptext);
  1653     assert(psize);
  1654     assert(keylist);
  1655 
  1656     if (!(session && ctext && csize && ptext && psize && keylist))
  1657         return PEP_ILLEGAL_VALUE;
  1658 
  1659     return session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(
  1660             session, ctext, csize, dsigtext, dsigsize, ptext, psize, keylist);
  1661 }
  1662 
  1663 DYNAMIC_API PEP_STATUS encrypt_and_sign(
  1664     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
  1665     size_t psize, char **ctext, size_t *csize
  1666     )
  1667 {
  1668     assert(session);
  1669     assert(keylist);
  1670     assert(ptext);
  1671     assert(psize);
  1672     assert(ctext);
  1673     assert(csize);
  1674 
  1675     if (!(session && keylist && ptext && psize && ctext && csize))
  1676         return PEP_ILLEGAL_VALUE;
  1677 
  1678     return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session,
  1679             keylist, ptext, psize, ctext, csize);
  1680 }
  1681 
  1682 PEP_STATUS encrypt_only(
  1683     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
  1684     size_t psize, char **ctext, size_t *csize
  1685     )
  1686 {
  1687     assert(session);
  1688     assert(keylist);
  1689     assert(ptext);
  1690     assert(psize);
  1691     assert(ctext);
  1692     assert(csize);
  1693 
  1694     if (!(session && keylist && ptext && psize && ctext && csize))
  1695         return PEP_ILLEGAL_VALUE;
  1696 
  1697     return session->cryptotech[PEP_crypt_OpenPGP].encrypt_only(session,
  1698             keylist, ptext, psize, ctext, csize);
  1699 }
  1700 
  1701 
  1702 DYNAMIC_API PEP_STATUS verify_text(
  1703     PEP_SESSION session, const char *text, size_t size,
  1704     const char *signature, size_t sig_size, stringlist_t **keylist
  1705     )
  1706 {
  1707     assert(session);
  1708     assert(text);
  1709     assert(size);
  1710     assert(signature);
  1711     assert(sig_size);
  1712     assert(keylist);
  1713 
  1714     if (!(session && text && size && signature && sig_size && keylist))
  1715         return PEP_ILLEGAL_VALUE;
  1716 
  1717     return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text,
  1718             size, signature, sig_size, keylist);
  1719 }
  1720 
  1721 DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
  1722 {
  1723     assert(session);
  1724     assert(fpr);
  1725 
  1726     if (!(session && fpr))
  1727         return PEP_ILLEGAL_VALUE;
  1728 
  1729     return session->cryptotech[PEP_crypt_OpenPGP].delete_keypair(session, fpr);
  1730 }
  1731 
  1732 DYNAMIC_API PEP_STATUS export_key(
  1733         PEP_SESSION session, const char *fpr, char **key_data, size_t *size
  1734     )
  1735 {
  1736     assert(session);
  1737     assert(fpr);
  1738     assert(key_data);
  1739     assert(size);
  1740 
  1741     if (!(session && fpr && key_data && size))
  1742         return PEP_ILLEGAL_VALUE;
  1743 
  1744     return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr,
  1745             key_data, size, false);
  1746 }
  1747 
  1748 DYNAMIC_API PEP_STATUS export_secrect_key(
  1749         PEP_SESSION session, const char *fpr, char **key_data, size_t *size
  1750     )
  1751 {
  1752     assert(session);
  1753     assert(fpr);
  1754     assert(key_data);
  1755     assert(size);
  1756 
  1757     if (!(session && fpr && key_data && size))
  1758         return PEP_ILLEGAL_VALUE;
  1759 
  1760     // don't accept key IDs but full fingerprints only
  1761     if (strlen(fpr) < 16)
  1762         return PEP_ILLEGAL_VALUE;
  1763 
  1764     return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr,
  1765             key_data, size, true);
  1766 }
  1767 
  1768 DYNAMIC_API PEP_STATUS find_keys(
  1769         PEP_SESSION session, const char *pattern, stringlist_t **keylist
  1770     )
  1771 {
  1772     assert(session);
  1773     assert(pattern);
  1774     assert(keylist);
  1775 
  1776     if (!(session && pattern && keylist))
  1777         return PEP_ILLEGAL_VALUE;
  1778 
  1779     return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern,
  1780             keylist);
  1781 }
  1782 
  1783 
  1784 DYNAMIC_API PEP_STATUS generate_keypair(
  1785         PEP_SESSION session, pEp_identity *identity
  1786     )
  1787 {
  1788     assert(session);
  1789     assert(identity);
  1790     assert(identity->address);
  1791     assert(identity->fpr == NULL || identity->fpr[0] == 0);
  1792     assert(identity->username);
  1793 
  1794     if (!(session && identity && identity->address &&
  1795             (identity->fpr == NULL || identity->fpr[0] == 0) &&
  1796             identity->username))
  1797         return PEP_ILLEGAL_VALUE;
  1798 
  1799     PEP_STATUS status =
  1800         session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session,
  1801                 identity);
  1802     if (status != PEP_STATUS_OK)
  1803         return status;
  1804 
  1805     return status;
  1806 }
  1807 
  1808 DYNAMIC_API PEP_STATUS get_key_rating(
  1809         PEP_SESSION session,
  1810         const char *fpr,
  1811         PEP_comm_type *comm_type
  1812     )
  1813 {
  1814     assert(session);
  1815     assert(fpr);
  1816     assert(comm_type);
  1817 
  1818     if (!(session && fpr && comm_type))
  1819         return PEP_ILLEGAL_VALUE;
  1820 
  1821     return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr,
  1822             comm_type);
  1823 }
  1824 
  1825 DYNAMIC_API PEP_STATUS import_key(
  1826         PEP_SESSION session,
  1827         const char *key_data,
  1828         size_t size,
  1829         identity_list **private_keys
  1830     )
  1831 {
  1832     assert(session);
  1833     assert(key_data);
  1834 
  1835     if (!(session && key_data))
  1836         return PEP_ILLEGAL_VALUE;
  1837 
  1838     return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data,
  1839             size, private_keys);
  1840 }
  1841 
  1842 DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
  1843 {
  1844     assert(session);
  1845     assert(pattern);
  1846 
  1847     if (!(session && pattern))
  1848         return PEP_ILLEGAL_VALUE;
  1849 
  1850     return session->cryptotech[PEP_crypt_OpenPGP].recv_key(session, pattern);
  1851 }
  1852 
  1853 DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
  1854 {
  1855     assert(session);
  1856     assert(pattern);
  1857 
  1858     if (!(session && pattern))
  1859         return PEP_ILLEGAL_VALUE;
  1860 
  1861     return session->cryptotech[PEP_crypt_OpenPGP].send_key(session, pattern);
  1862 }
  1863 
  1864 DYNAMIC_API PEP_STATUS renew_key(
  1865         PEP_SESSION session,
  1866         const char *fpr,
  1867         const timestamp *ts
  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].renew_key(session, fpr, ts);
  1877 }
  1878 
  1879 DYNAMIC_API PEP_STATUS revoke_key(
  1880         PEP_SESSION session,
  1881         const char *fpr,
  1882         const char *reason
  1883     )
  1884 {
  1885     assert(session);
  1886     assert(fpr);
  1887 
  1888     if (!(session && fpr))
  1889         return PEP_ILLEGAL_VALUE;
  1890 
  1891     return session->cryptotech[PEP_crypt_OpenPGP].revoke_key(session, fpr,
  1892             reason);
  1893 }
  1894 
  1895 DYNAMIC_API PEP_STATUS key_expired(
  1896         PEP_SESSION session,
  1897         const char *fpr,
  1898         const time_t when,
  1899         bool *expired
  1900     )
  1901 {
  1902     assert(session);
  1903     assert(fpr);
  1904     assert(expired);
  1905 
  1906     if (!(session && fpr && expired))
  1907         return PEP_ILLEGAL_VALUE;
  1908 
  1909     return session->cryptotech[PEP_crypt_OpenPGP].key_expired(session, fpr,
  1910             when, expired);
  1911 }
  1912 
  1913 DYNAMIC_API PEP_STATUS key_revoked(
  1914        PEP_SESSION session,
  1915        const char *fpr,
  1916        bool *revoked
  1917    )
  1918 {
  1919     assert(session);
  1920     assert(fpr);
  1921     assert(revoked);
  1922     
  1923     if (!(session && fpr && revoked))
  1924         return PEP_ILLEGAL_VALUE;
  1925     
  1926     return session->cryptotech[PEP_crypt_OpenPGP].key_revoked(session, fpr,
  1927             revoked);
  1928 }
  1929 
  1930 static void _clean_log_value(char *text)
  1931 {
  1932     if (text) {
  1933         for (char *c = text; *c; c++) {
  1934             if (*c < 32 && *c != '\n')
  1935                 *c = 32;
  1936             else if (*c == '"')
  1937                 *c = '\'';
  1938         }
  1939     }
  1940 }
  1941 
  1942 static char *_concat_string(char *str1, const char *str2, char delim)
  1943 {
  1944     str2 = str2 ? str2 : "";
  1945     size_t len1 = str1 ? strlen(str1) : 0;
  1946     size_t len2 = strlen(str2);
  1947     size_t len = len1 + len2 + 3;
  1948     char * result = realloc(str1, len + 1);
  1949 
  1950     if (result) {
  1951         result[len1] = '"';
  1952         strcpy(result + len1 + 1, str2);
  1953         result[len - 2] = '"';
  1954         result[len - 1] = delim;
  1955         result[len] = 0;
  1956     }
  1957     else {
  1958         free(str1);
  1959     }
  1960 
  1961     return result;
  1962 }
  1963 
  1964 DYNAMIC_API PEP_STATUS get_crashdump_log(
  1965         PEP_SESSION session,
  1966         int maxlines,
  1967         char **logdata
  1968     )
  1969 {
  1970     PEP_STATUS status = PEP_STATUS_OK;
  1971     char *_logdata= NULL;
  1972 
  1973     assert(session);
  1974     assert(maxlines >= 0 && maxlines <= CRASHDUMP_MAX_LINES);
  1975     assert(logdata);
  1976 
  1977     if (!(session && logdata && maxlines >= 0 && maxlines <=
  1978             CRASHDUMP_MAX_LINES))
  1979         return PEP_ILLEGAL_VALUE;
  1980 
  1981     *logdata = NULL;
  1982 
  1983     int limit = maxlines ? maxlines : CRASHDUMP_DEFAULT_LINES;
  1984     const char *timestamp = NULL;
  1985     const char *title = NULL;
  1986     const char *entity = NULL;
  1987     const char *desc = NULL;
  1988     const char *comment = NULL;
  1989 
  1990     sqlite3_reset(session->crashdump);
  1991     sqlite3_bind_int(session->crashdump, 1, limit);
  1992 
  1993     int result;
  1994 
  1995     do {
  1996         result = sqlite3_step(session->crashdump);
  1997         switch (result) {
  1998         case SQLITE_ROW:
  1999             timestamp = (const char *) sqlite3_column_text(session->crashdump,
  2000                     0);
  2001             title   = (const char *) sqlite3_column_text(session->crashdump,
  2002                     1);
  2003             entity  = (const char *) sqlite3_column_text(session->crashdump,
  2004                     2);
  2005             desc    = (const char *) sqlite3_column_text(session->crashdump,
  2006                     3);
  2007             comment = (const char *) sqlite3_column_text(session->crashdump,
  2008                     4);
  2009 
  2010             _logdata = _concat_string(_logdata, timestamp, ',');
  2011             if (_logdata == NULL)
  2012                 goto enomem;
  2013 
  2014             _logdata = _concat_string(_logdata, title, ',');
  2015             if (_logdata == NULL)
  2016                 goto enomem;
  2017 
  2018             _logdata = _concat_string(_logdata, entity, ',');
  2019             if (_logdata == NULL)
  2020                 goto enomem;
  2021 
  2022             _logdata = _concat_string(_logdata, desc, ',');
  2023             if (_logdata == NULL)
  2024                 goto enomem;
  2025 
  2026             _logdata = _concat_string(_logdata, comment, '\n');
  2027             if (_logdata == NULL)
  2028                 goto enomem;
  2029 
  2030             _clean_log_value(_logdata);
  2031             break;
  2032 
  2033         case SQLITE_DONE:
  2034             break;
  2035 
  2036         default:
  2037             status = PEP_UNKNOWN_ERROR;
  2038             result = SQLITE_DONE;
  2039         }
  2040     } while (result != SQLITE_DONE);
  2041 
  2042     sqlite3_reset(session->crashdump);
  2043     if (status == PEP_STATUS_OK)
  2044         *logdata = _logdata;
  2045 
  2046     goto the_end;
  2047 
  2048 enomem:
  2049     status = PEP_OUT_OF_MEMORY;
  2050 
  2051 the_end:
  2052     return ADD_TO_LOG(status);
  2053 }
  2054 
  2055 DYNAMIC_API PEP_STATUS get_languagelist(
  2056         PEP_SESSION session,
  2057         char **languages
  2058     )
  2059 {
  2060     PEP_STATUS status = PEP_STATUS_OK;
  2061     char *_languages= NULL;
  2062 
  2063     assert(session);
  2064     assert(languages);
  2065 
  2066     if (!(session && languages))
  2067         return PEP_ILLEGAL_VALUE;
  2068 
  2069     *languages = NULL;
  2070 
  2071     const char *lang = NULL;
  2072     const char *name = NULL;
  2073     const char *phrase = NULL;
  2074 
  2075     sqlite3_reset(session->languagelist);
  2076 
  2077     int result;
  2078 
  2079     do {
  2080         result = sqlite3_step(session->languagelist);
  2081         switch (result) {
  2082         case SQLITE_ROW:
  2083             lang = (const char *) sqlite3_column_text(session->languagelist,
  2084                     0);
  2085             name = (const char *) sqlite3_column_text(session->languagelist,
  2086                     1);
  2087             phrase = (const char *) sqlite3_column_text(session->languagelist,
  2088                     2);
  2089 
  2090             _languages = _concat_string(_languages, lang, ',');
  2091             if (_languages == NULL)
  2092                 goto enomem;
  2093 
  2094             _languages = _concat_string(_languages, name, ',');
  2095             if (_languages == NULL)
  2096                 goto enomem;
  2097 
  2098             _languages = _concat_string(_languages, phrase, '\n');
  2099             if (_languages == NULL)
  2100                 goto enomem;
  2101 
  2102             break;
  2103 
  2104         case SQLITE_DONE:
  2105             break;
  2106 
  2107         default:
  2108             status = PEP_UNKNOWN_ERROR;
  2109             result = SQLITE_DONE;
  2110         }
  2111     } while (result != SQLITE_DONE);
  2112 
  2113     sqlite3_reset(session->languagelist);
  2114     if (status == PEP_STATUS_OK)
  2115         *languages = _languages;
  2116 
  2117     goto the_end;
  2118 
  2119 enomem:
  2120     status = PEP_OUT_OF_MEMORY;
  2121 
  2122 the_end:
  2123     return status;
  2124 }
  2125 
  2126 DYNAMIC_API PEP_STATUS get_phrase(
  2127         PEP_SESSION session,
  2128         const char *lang,
  2129         int phrase_id,
  2130         char **phrase
  2131     )
  2132 {
  2133     PEP_STATUS status = PEP_STATUS_OK;
  2134 
  2135     assert(session && lang && lang[0] && lang[1] && lang[2] == 0 && phrase);
  2136     if (!(session && lang && lang[0] && lang[1] && lang[2] == 0 && phrase))
  2137         return PEP_ILLEGAL_VALUE;
  2138 
  2139     *phrase = NULL;
  2140 
  2141     sqlite3_reset(session->i18n_token);
  2142     sqlite3_bind_text(session->i18n_token, 1, lang, -1, SQLITE_STATIC);
  2143     sqlite3_bind_int(session->i18n_token, 2, phrase_id);
  2144 
  2145     const char *_phrase = NULL;
  2146     int result;
  2147 
  2148     result = sqlite3_step(session->i18n_token);
  2149     switch (result) {
  2150     case SQLITE_ROW:
  2151         _phrase = (const char *) sqlite3_column_text(session->i18n_token, 0);
  2152         break;
  2153 
  2154     case SQLITE_DONE:
  2155         status = PEP_PHRASE_NOT_FOUND;
  2156         break;
  2157 
  2158     default:
  2159         status = PEP_UNKNOWN_ERROR;
  2160     }
  2161 
  2162     if (status == PEP_STATUS_OK) {
  2163         *phrase = strdup(_phrase);
  2164         if (*phrase == NULL)
  2165             goto enomem;
  2166     }
  2167 
  2168     sqlite3_reset(session->i18n_token);
  2169     goto the_end;
  2170 
  2171 enomem:
  2172     status = PEP_OUT_OF_MEMORY;
  2173 
  2174 the_end:
  2175     return status;
  2176 }
  2177 
  2178 static PEP_STATUS _get_sequence_value(PEP_SESSION session, const char *name,
  2179         int32_t *value)
  2180 {
  2181     assert(session && name && value);
  2182     if (!(session && name && value))
  2183         return PEP_ILLEGAL_VALUE;
  2184 
  2185     PEP_STATUS status = PEP_STATUS_OK;
  2186 
  2187     sqlite3_reset(session->sequence_value2);
  2188     sqlite3_bind_text(session->sequence_value2, 1, name, -1,
  2189             SQLITE_STATIC);
  2190     int result = sqlite3_step(session->sequence_value2);
  2191     switch (result) {
  2192         case SQLITE_ROW: {
  2193             int32_t _value = (int32_t)
  2194                     sqlite3_column_int(session->sequence_value2, 0);
  2195             int _own = (int)
  2196                     sqlite3_column_int(session->sequence_value2, 1);
  2197             *value = _value;
  2198             if (_own)
  2199                 status = PEP_OWN_SEQUENCE;
  2200             break;
  2201         }
  2202         case SQLITE_DONE:
  2203             status = PEP_RECORD_NOT_FOUND;
  2204             break;
  2205         default:
  2206             status = PEP_UNKNOWN_ERROR;
  2207     }
  2208     sqlite3_reset(session->sequence_value2);
  2209 
  2210     return status;
  2211 }
  2212 
  2213 static PEP_STATUS _increment_sequence_value(PEP_SESSION session,
  2214         const char *name, int own)
  2215 {
  2216     assert(session && name);
  2217     if (!(session && name))
  2218         return PEP_ILLEGAL_VALUE;
  2219 
  2220     sqlite3_reset(session->sequence_value1);
  2221     sqlite3_bind_text(session->sequence_value1, 1, name, -1, SQLITE_STATIC);
  2222     sqlite3_bind_int(session->sequence_value1, 2, own);
  2223     int result = sqlite3_step(session->sequence_value1);
  2224     assert(result == SQLITE_DONE);
  2225     sqlite3_reset(session->sequence_value1);
  2226     if (result == SQLITE_DONE)
  2227         return PEP_STATUS_OK;
  2228     else
  2229         return PEP_CANNOT_INCREASE_SEQUENCE;
  2230 }
  2231 
  2232 static PEP_STATUS _set_sequence_value(PEP_SESSION session,
  2233         const char *name, int32_t value, int own)
  2234 {
  2235     assert(session && name && value > 0);
  2236     if (!(session && name && value > 0))
  2237         return PEP_ILLEGAL_VALUE;
  2238 
  2239     sqlite3_reset(session->sequence_value3);
  2240     sqlite3_bind_text(session->sequence_value3, 1, name, -1, SQLITE_STATIC);
  2241     sqlite3_bind_int(session->sequence_value3, 2, value);
  2242     sqlite3_bind_int(session->sequence_value3, 3, own);
  2243     int result = sqlite3_step(session->sequence_value3);
  2244     assert(result == SQLITE_DONE);
  2245     sqlite3_reset(session->sequence_value3);
  2246     if (result == SQLITE_DONE)
  2247         return PEP_STATUS_OK;
  2248     else
  2249         return PEP_CANNOT_SET_SEQUENCE_VALUE;
  2250 }
  2251 
  2252 DYNAMIC_API PEP_STATUS sequence_value(
  2253         PEP_SESSION session,
  2254         char *name,
  2255         int32_t *value
  2256     )
  2257 {
  2258     PEP_STATUS status = PEP_STATUS_OK;
  2259     int result;
  2260 
  2261     assert(session);
  2262     assert(name && value && *value >= 0);
  2263 
  2264     if (!(session && name && value && *value >= 0))
  2265         return PEP_ILLEGAL_VALUE;
  2266 
  2267     int own = 0;
  2268     if (!name[0]) {
  2269         pEpUUID uuid;
  2270         uuid_generate_random(uuid);
  2271         uuid_unparse_upper(uuid, name);
  2272         own = 1;
  2273     }
  2274     else {
  2275         if (name == session->sync_session->sync_uuid || 
  2276             strcmp(name, session->sync_session->sync_uuid) == 0)
  2277             own = 1;
  2278     }
  2279 
  2280     if (*value) {
  2281         sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
  2282         int32_t old_value = 0;
  2283         status = _get_sequence_value(session, name, &old_value);
  2284         if (status != PEP_STATUS_OK && status != PEP_RECORD_NOT_FOUND)
  2285         {
  2286             sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  2287             return status;
  2288         }
  2289 
  2290         if (old_value >= *value) {
  2291             sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  2292             return PEP_SEQUENCE_VIOLATED;
  2293         }
  2294         else {
  2295             status = _set_sequence_value(session, name, *value, own);
  2296             if (status == PEP_STATUS_OK) {
  2297                 result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
  2298                 if (result == SQLITE_OK)
  2299                     return PEP_STATUS_OK;
  2300                 else
  2301                     return PEP_COMMIT_FAILED;
  2302             } else {
  2303                 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  2304                 return status;
  2305             }
  2306         }
  2307     }
  2308 
  2309     assert(*value == 0);
  2310     sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
  2311     status = _increment_sequence_value(session, name, own);
  2312     if (status == PEP_STATUS_OK) {
  2313         status = _get_sequence_value(session, name, value);
  2314     }
  2315     if (status == PEP_STATUS_OK || status == PEP_OWN_SEQUENCE) {
  2316         result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
  2317         if (result == SQLITE_OK){
  2318             assert(*value < INT32_MAX);
  2319             if (*value == INT32_MAX){
  2320                 return PEP_CANNOT_INCREASE_SEQUENCE;
  2321             }
  2322             return status;
  2323         } else {
  2324             return PEP_COMMIT_FAILED;
  2325         }
  2326     } else {
  2327         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  2328         return status;
  2329     }
  2330     return status;
  2331 }
  2332 
  2333 DYNAMIC_API PEP_STATUS set_revoked(
  2334        PEP_SESSION session,
  2335        const char *revoked_fpr,
  2336        const char *replacement_fpr,
  2337        const uint64_t revocation_date
  2338     )
  2339 {
  2340     PEP_STATUS status = PEP_STATUS_OK;
  2341     
  2342     assert(session &&
  2343            revoked_fpr && revoked_fpr[0] &&
  2344            replacement_fpr && replacement_fpr[0]
  2345           );
  2346     
  2347     if (!(session &&
  2348           revoked_fpr && revoked_fpr[0] &&
  2349           replacement_fpr && replacement_fpr[0]
  2350          ))
  2351         return PEP_ILLEGAL_VALUE;
  2352     
  2353     sqlite3_reset(session->set_revoked);
  2354     sqlite3_bind_text(session->set_revoked, 1, revoked_fpr, -1, SQLITE_STATIC);
  2355     sqlite3_bind_text(session->set_revoked, 2, replacement_fpr, -1,
  2356             SQLITE_STATIC);
  2357     sqlite3_bind_int64(session->set_revoked, 3, revocation_date);
  2358 
  2359     int result;
  2360     
  2361     result = sqlite3_step(session->set_revoked);
  2362     switch (result) {
  2363         case SQLITE_DONE:
  2364             status = PEP_STATUS_OK;
  2365             break;
  2366             
  2367         default:
  2368             status = PEP_UNKNOWN_ERROR;
  2369     }
  2370     
  2371     sqlite3_reset(session->set_revoked);
  2372     return status;
  2373 }
  2374 
  2375 DYNAMIC_API PEP_STATUS get_revoked(
  2376         PEP_SESSION session,
  2377         const char *fpr,
  2378         char **revoked_fpr,
  2379         uint64_t *revocation_date
  2380     )
  2381 {
  2382     PEP_STATUS status = PEP_STATUS_OK;
  2383 
  2384     assert(session &&
  2385            revoked_fpr &&
  2386            fpr && fpr[0]
  2387           );
  2388     
  2389     if (!(session &&
  2390            revoked_fpr &&
  2391            fpr && fpr[0]
  2392           ))
  2393         return PEP_ILLEGAL_VALUE;
  2394 
  2395     *revoked_fpr = NULL;
  2396     *revocation_date = 0;
  2397 
  2398     sqlite3_reset(session->get_revoked);
  2399     sqlite3_bind_text(session->get_revoked, 1, fpr, -1, SQLITE_STATIC);
  2400 
  2401     int result;
  2402     
  2403     result = sqlite3_step(session->get_revoked);
  2404     switch (result) {
  2405         case SQLITE_ROW: {
  2406             *revoked_fpr = strdup((const char *)
  2407                     sqlite3_column_text(session->get_revoked, 0));
  2408             if(*revoked_fpr)
  2409                 *revocation_date = sqlite3_column_int64(session->get_revoked,
  2410                         1);
  2411             else
  2412                 status = PEP_OUT_OF_MEMORY;
  2413 
  2414             break;
  2415         }
  2416         default:
  2417             status = PEP_CANNOT_FIND_IDENTITY;
  2418     }
  2419 
  2420     sqlite3_reset(session->get_revoked);
  2421 
  2422     return status;
  2423 }
  2424 
  2425 PEP_STATUS key_created(
  2426         PEP_SESSION session,
  2427         const char *fpr,
  2428         time_t *created
  2429     )
  2430 {
  2431     assert(session && fpr && created);
  2432     if (!(session && fpr && created))
  2433         return PEP_ILLEGAL_VALUE;
  2434 
  2435     return session->cryptotech[PEP_crypt_OpenPGP].key_created(session, fpr,
  2436             created);
  2437 }
  2438 
  2439 PEP_STATUS find_private_keys(PEP_SESSION session, const char* pattern,
  2440                              stringlist_t **keylist) {
  2441     assert(session && keylist);
  2442     if (!(session && keylist))
  2443         return PEP_ILLEGAL_VALUE;
  2444     
  2445     return session->cryptotech[PEP_crypt_OpenPGP].find_private_keys(session, pattern,
  2446                                                                     keylist);
  2447 }
  2448 
  2449 DYNAMIC_API const char* get_engine_version() {
  2450     return PEP_ENGINE_VERSION;
  2451 }
  2452 
  2453 
  2454 DYNAMIC_API PEP_STATUS reset_peptest_hack(PEP_SESSION session)
  2455 {
  2456     assert(session);
  2457 
  2458     if (!session)
  2459         return PEP_ILLEGAL_VALUE;
  2460 
  2461     int int_result = sqlite3_exec(
  2462         session->db,
  2463         "delete from identity where address like '%@peptest.ch' ;",
  2464         NULL,
  2465         NULL,
  2466         NULL
  2467     );
  2468     assert(int_result == SQLITE_OK);
  2469 
  2470     if (int_result != SQLITE_OK)
  2471         return PEP_UNKNOWN_ERROR;
  2472 
  2473     return PEP_STATUS_OK;
  2474 }
  2475 
  2476 #ifdef DEBUG_ERRORSTACK
  2477 PEP_STATUS session_add_error(PEP_SESSION session, const char* file, unsigned line, PEP_STATUS status)
  2478 {
  2479     char logline[48];
  2480     if(status>0)
  2481     {
  2482         snprintf(logline,47, "%.24s:%u status=%u (0x%x)", file, line, status, status);
  2483     }else{
  2484         snprintf(logline,47, "%.24s:%u status=%i.", file, line, status);
  2485     }
  2486     stringlist_add(session->errorstack, logline); // logline is copied! :-)
  2487     return status;
  2488 }
  2489 
  2490 DYNAMIC_API const stringlist_t* get_errorstack(PEP_SESSION session)
  2491 {
  2492     return session->errorstack;
  2493 }
  2494 
  2495 DYNAMIC_API void clear_errorstack(PEP_SESSION session)
  2496 {
  2497     const int old_len = stringlist_length(session->errorstack);
  2498     char buf[48];
  2499     free_stringlist(session->errorstack);
  2500     snprintf(buf, 47, "(%i elements cleared)", old_len);
  2501     session->errorstack = new_stringlist(buf);
  2502 }
  2503 
  2504 #else
  2505 
  2506 static stringlist_t* dummy_errorstack = NULL;
  2507 
  2508 DYNAMIC_API const stringlist_t* get_errorstack(PEP_SESSION session)
  2509 {
  2510     if(dummy_errorstack == NULL)
  2511     {
  2512         dummy_errorstack = new_stringlist("( Please recompile pEpEngine with -DDEBUG_ERRORSTACK )");
  2513     }
  2514 
  2515     return dummy_errorstack;
  2516 }
  2517 
  2518 DYNAMIC_API void clear_errorstack(PEP_SESSION session)
  2519 {
  2520     // nothing to do here
  2521 }
  2522 
  2523 #endif