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