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