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