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