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