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