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