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