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