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