src/pEpEngine.c
author Volker Birk <vb@pep.foundation>
Mon, 29 Aug 2016 17:39:35 +0200
branchkeysync
changeset 1091 0571ce4b97a2
parent 1090 c15ef7d00170
child 1103 aba4f9ea5bce
permissions -rw-r--r--
fixes
     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     _session->passive_mode = false;
   537     _session->unencrypted_subject = false;
   538 #ifdef ANDROID
   539     _session->use_only_own_private_keys = true;
   540 #elif TARGET_OS_IPHONE
   541     _session->use_only_own_private_keys = true;
   542 #else
   543     _session->use_only_own_private_keys = false;
   544 #endif
   545 
   546     *session = _session;
   547     return PEP_STATUS_OK;
   548 
   549 enomem:
   550     status = PEP_OUT_OF_MEMORY;
   551 
   552 pep_error:
   553     release(_session);
   554     return status;
   555 }
   556 
   557 DYNAMIC_API void release(PEP_SESSION session)
   558 {
   559     bool out_last = false;
   560 
   561     assert(init_count >= 0);
   562     assert(session);
   563 
   564     if (!((init_count >= 0) && session))
   565         return;
   566 
   567     // a small race condition but still a race condition
   568     // mitigated by calling caveat (see documentation)
   569 
   570     if (init_count == 0)
   571         out_last = true;
   572     --init_count;
   573 
   574     if (session) {
   575         if (session->sync_state != DeviceState_state_NONE)
   576             unregister_sync_callbacks(session);
   577 
   578         if (session->db) {
   579             if (session->log)
   580                 sqlite3_finalize(session->log);
   581             if (session->trustword)
   582                 sqlite3_finalize(session->trustword);
   583             if (session->get_identity)
   584                 sqlite3_finalize(session->get_identity);
   585             if (session->set_person)
   586                 sqlite3_finalize(session->set_person);
   587             if (session->set_pgp_keypair)
   588                 sqlite3_finalize(session->set_pgp_keypair);
   589             if (session->set_identity)
   590                 sqlite3_finalize(session->set_identity);
   591             if (session->set_identity_flags)
   592                 sqlite3_finalize(session->set_identity_flags);
   593             if (session->set_trust)
   594                 sqlite3_finalize(session->set_trust);
   595             if (session->get_trust)
   596                 sqlite3_finalize(session->get_trust);
   597             if (session->least_trust)
   598                 sqlite3_finalize(session->least_trust);
   599             if (session->mark_compromized)
   600                 sqlite3_finalize(session->mark_compromized);
   601             if (session->crashdump)
   602                 sqlite3_finalize(session->crashdump);
   603             if (session->languagelist)
   604                 sqlite3_finalize(session->languagelist);
   605             if (session->i18n_token)
   606                 sqlite3_finalize(session->i18n_token);
   607             if (session->blacklist_add)
   608                 sqlite3_finalize(session->blacklist_add);
   609             if (session->blacklist_delete)
   610                 sqlite3_finalize(session->blacklist_delete);
   611             if (session->blacklist_is_listed)
   612                 sqlite3_finalize(session->blacklist_is_listed);
   613             if (session->blacklist_retrieve)
   614                 sqlite3_finalize(session->blacklist_retrieve);
   615             if (session->own_key_is_listed)
   616                 sqlite3_finalize(session->own_key_is_listed);
   617             if (session->own_identities_retrieve)
   618                 sqlite3_finalize(session->own_identities_retrieve);
   619             if (session->sequence_value1)
   620                 sqlite3_finalize(session->sequence_value1);
   621             if (session->sequence_value2)
   622                 sqlite3_finalize(session->sequence_value2);
   623             if (session->sequence_value3)
   624                 sqlite3_finalize(session->sequence_value3);
   625             if (session->set_revoked)
   626                 sqlite3_finalize(session->set_revoked);
   627             if (session->get_revoked)
   628                 sqlite3_finalize(session->get_revoked);
   629 
   630             if (session->db)
   631                 sqlite3_close_v2(session->db);
   632             if (session->system_db)
   633                 sqlite3_close_v2(session->system_db);
   634         }
   635 
   636         release_transport_system(session, out_last);
   637         release_cryptotech(session, out_last);
   638 
   639         free(session);
   640     }
   641 }
   642 
   643 DYNAMIC_API void config_passive_mode(PEP_SESSION session, bool enable)
   644 {
   645     assert(session);
   646     session->passive_mode = enable;
   647 }
   648 
   649 DYNAMIC_API void config_unencrypted_subject(PEP_SESSION session, bool enable)
   650 {
   651     assert(session);
   652     session->unencrypted_subject = enable;
   653 }
   654 
   655 DYNAMIC_API void config_use_only_own_private_keys(PEP_SESSION session,
   656         bool enable)
   657 {
   658     assert(session);
   659     session->use_only_own_private_keys = enable;
   660 }
   661 
   662 DYNAMIC_API PEP_STATUS log_event(
   663         PEP_SESSION session,
   664         const char *title,
   665         const char *entity,
   666         const char *description,
   667         const char *comment
   668     )
   669 {
   670     PEP_STATUS status = PEP_STATUS_OK;
   671     int result;
   672 
   673     assert(session);
   674     assert(title);
   675     assert(entity);
   676 
   677     if (!(session && title && entity))
   678         return PEP_ILLEGAL_VALUE;
   679 
   680     sqlite3_reset(session->log);
   681     sqlite3_bind_text(session->log, 1, title, -1, SQLITE_STATIC);
   682     sqlite3_bind_text(session->log, 2, entity, -1, SQLITE_STATIC);
   683     if (description)
   684         sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
   685     else
   686         sqlite3_bind_null(session->log, 3);
   687     if (comment)
   688         sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
   689     else
   690         sqlite3_bind_null(session->log, 4);
   691     do {
   692         result = sqlite3_step(session->log);
   693         assert(result == SQLITE_DONE || result == SQLITE_BUSY);
   694         if (result != SQLITE_DONE && result != SQLITE_BUSY)
   695             status = PEP_UNKNOWN_ERROR;
   696     } while (result == SQLITE_BUSY);
   697     sqlite3_reset(session->log);
   698 
   699     return status;
   700 }
   701 
   702 DYNAMIC_API PEP_STATUS trustword(
   703             PEP_SESSION session, uint16_t value, const char *lang,
   704             char **word, size_t *wsize
   705         )
   706 {
   707     PEP_STATUS status = PEP_STATUS_OK;
   708 
   709     assert(session);
   710     assert(word);
   711     assert(wsize);
   712 
   713     if (!(session && word && wsize))
   714         return PEP_ILLEGAL_VALUE;
   715 
   716     *word = NULL;
   717     *wsize = 0;
   718 
   719     if (lang == NULL)
   720         lang = "en";
   721 
   722     assert((lang[0] >= 'A' && lang[0] <= 'Z')
   723             || (lang[0] >= 'a' && lang[0] <= 'z'));
   724     assert((lang[1] >= 'A' && lang[1] <= 'Z')
   725             || (lang[1] >= 'a' && lang[1] <= 'z'));
   726     assert(lang[2] == 0);
   727 
   728     sqlite3_reset(session->trustword);
   729     sqlite3_bind_text(session->trustword, 1, lang, -1, SQLITE_STATIC);
   730     sqlite3_bind_int(session->trustword, 2, value);
   731 
   732     const int result = sqlite3_step(session->trustword);
   733     if (result == SQLITE_ROW) {
   734         *word = strdup((const char *) sqlite3_column_text(session->trustword,
   735                     1));
   736         if (*word)
   737             *wsize = sqlite3_column_bytes(session->trustword, 1);
   738         else
   739             status = PEP_OUT_OF_MEMORY;
   740     } else
   741         status = PEP_TRUSTWORD_NOT_FOUND;
   742 
   743     sqlite3_reset(session->trustword);
   744     return status;
   745 }
   746 
   747 DYNAMIC_API PEP_STATUS trustwords(
   748         PEP_SESSION session, const char *fingerprint, const char *lang,
   749         char **words, size_t *wsize, int max_words
   750     )
   751 {
   752     const char *source = fingerprint;
   753     char *buffer;
   754     char *dest;
   755     size_t fsize;
   756 
   757     assert(session);
   758     assert(fingerprint);
   759     assert(words);
   760     assert(wsize);
   761     assert(max_words >= 0);
   762 
   763     if (!(session && fingerprint && words && wsize && max_words >= 0))
   764         return PEP_ILLEGAL_VALUE;
   765 
   766     *words = NULL;
   767     *wsize = 0;
   768 
   769     buffer = calloc(1, MAX_TRUSTWORDS_SPACE);
   770     assert(buffer);
   771     if (buffer == NULL)
   772         return PEP_OUT_OF_MEMORY;
   773     dest = buffer;
   774 
   775     fsize = strlen(fingerprint);
   776 
   777     if (!lang || !lang[0])
   778         lang = "en";
   779 
   780     assert((lang[0] >= 'A' && lang[0] <= 'Z')
   781             || (lang[0] >= 'a' && lang[0] <= 'z'));
   782     assert((lang[1] >= 'A' && lang[1] <= 'Z')
   783             || (lang[1] >= 'a' && lang[1] <= 'z'));
   784     assert(lang[2] == 0);
   785 
   786     int n_words = 0;
   787     while (source < fingerprint + fsize) {
   788         PEP_STATUS _status;
   789         uint16_t value;
   790         char *word;
   791         size_t _wsize;
   792         int j;
   793 
   794         for (value=0, j=0; j < 4 && source < fingerprint + fsize; ) {
   795             if (*source >= 'a' && *source <= 'f')
   796                 value += (*source - 'a' + 10) << (3 - j++) * 4;
   797             else if (*source >= 'A' && *source <= 'F')
   798                 value += (*source - 'A' + 10) << (3 - j++) * 4;
   799             else if (*source >= '0' && *source <= '9')
   800                 value += (*source - '0') << (3 - j++) * 4;
   801             
   802             source++;
   803         }
   804 
   805         _status = trustword(session, value, lang, &word, &_wsize);
   806         if (_status == PEP_OUT_OF_MEMORY) {
   807             free(buffer);
   808             return PEP_OUT_OF_MEMORY;
   809         }
   810         if (word == NULL) {
   811             free(buffer);
   812             return PEP_TRUSTWORD_NOT_FOUND;
   813         }
   814 
   815         if (dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1) {
   816             strncpy(dest, word, _wsize);
   817             free(word);
   818             dest += _wsize;
   819         }
   820         else {
   821             free(word);
   822             break; // buffer full
   823         }
   824 
   825         if (source < fingerprint + fsize
   826                 && dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1)
   827             *dest++ = ' ';
   828 
   829         ++n_words;
   830         if (max_words && n_words >= max_words)
   831             break;
   832     }
   833 
   834     *words = buffer;
   835     *wsize = dest - buffer;
   836     return PEP_STATUS_OK;
   837 }
   838 
   839 pEp_identity *new_identity(
   840         const char *address, const char *fpr, const char *user_id,
   841         const char *username
   842     )
   843 {
   844     pEp_identity *result = calloc(1, sizeof(pEp_identity));
   845     assert(result);
   846     if (result) {
   847         if (address) {
   848             result->address = strdup(address);
   849             assert(result->address);
   850             if (result->address == NULL) {
   851                 free(result);
   852                 return NULL;
   853             }
   854         }
   855         if (fpr) {
   856             result->fpr = strdup(fpr);
   857             assert(result->fpr);
   858             if (result->fpr == NULL) {
   859                 free_identity(result);
   860                 return NULL;
   861             }
   862         }
   863         if (user_id) {
   864             result->user_id = strdup(user_id);
   865             assert(result->user_id);
   866             if (result->user_id == NULL) {
   867                 free_identity(result);
   868                 return NULL;
   869             }
   870         }
   871         if (username) {
   872             result->username = strdup(username);
   873             assert(result->username);
   874             if (result->username == NULL) {
   875                 free_identity(result);
   876                 return NULL;
   877             }
   878         }
   879     }
   880     return result;
   881 }
   882 
   883 pEp_identity *identity_dup(const pEp_identity *src)
   884 {
   885     assert(src);
   886 
   887     pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id,
   888             src->username);
   889     assert(dup);
   890     if (dup == NULL)
   891         return NULL;
   892     
   893     dup->comm_type = src->comm_type;
   894     dup->lang[0] = src->lang[0];
   895     dup->lang[1] = src->lang[1];
   896     dup->lang[2] = 0;
   897     dup->me = src->me;
   898     dup->flags = src->flags;
   899 
   900     return dup;
   901 }
   902 
   903 void free_identity(pEp_identity *identity)
   904 {
   905     if (identity) {
   906         free(identity->address);
   907         free(identity->fpr);
   908         free(identity->user_id);
   909         free(identity->username);
   910         free(identity);
   911     }
   912 }
   913 
   914 DYNAMIC_API PEP_STATUS get_identity(
   915         PEP_SESSION session,
   916         const char *address,
   917         const char *user_id,
   918         pEp_identity **identity
   919     )
   920 {
   921     PEP_STATUS status = PEP_STATUS_OK;
   922     static pEp_identity *_identity;
   923 
   924     assert(session);
   925     assert(address);
   926     assert(address[0]);
   927     assert(identity);
   928 
   929     if (!(session && address && address[0] && identity))
   930         return PEP_ILLEGAL_VALUE;
   931 
   932     *identity = NULL;
   933 
   934     sqlite3_reset(session->get_identity);
   935     sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
   936     sqlite3_bind_text(session->get_identity, 2, user_id, -1, SQLITE_STATIC);
   937 
   938     const int result = sqlite3_step(session->get_identity);
   939     switch (result) {
   940     case SQLITE_ROW:
   941         _identity = new_identity(
   942                 address,
   943                 (const char *) sqlite3_column_text(session->get_identity, 0),
   944                 user_id,
   945                 (const char *) sqlite3_column_text(session->get_identity, 1)
   946                 );
   947         assert(_identity);
   948         if (_identity == NULL)
   949             return PEP_OUT_OF_MEMORY;
   950 
   951         _identity->comm_type = (PEP_comm_type)
   952             sqlite3_column_int(session->get_identity, 2);
   953         const char* const _lang = (const char *)
   954             sqlite3_column_text(session->get_identity, 3);
   955         if (_lang && _lang[0]) {
   956             assert(_lang[0] >= 'a' && _lang[0] <= 'z');
   957             assert(_lang[1] >= 'a' && _lang[1] <= 'z');
   958             assert(_lang[2] == 0);
   959             _identity->lang[0] = _lang[0];
   960             _identity->lang[1] = _lang[1];
   961             _identity->lang[2] = 0;
   962         }
   963         _identity->flags = (unsigned int)
   964             sqlite3_column_int(session->get_identity, 4);
   965         *identity = _identity;
   966         break;
   967     default:
   968         status = PEP_CANNOT_FIND_IDENTITY;
   969         *identity = NULL;
   970     }
   971 
   972     sqlite3_reset(session->get_identity);
   973     return status;
   974 }
   975 
   976 DYNAMIC_API PEP_STATUS set_identity(
   977         PEP_SESSION session, const pEp_identity *identity
   978     )
   979 {
   980     int result;
   981 
   982     assert(session);
   983     assert(identity);
   984     assert(identity->address);
   985     assert(identity->fpr);
   986     assert(identity->user_id);
   987     assert(identity->username);
   988 
   989     if (!(session && identity && identity->address && identity->fpr &&
   990                 identity->user_id && identity->username))
   991         return PEP_ILLEGAL_VALUE;
   992 
   993     bool listed;
   994     PEP_STATUS status = blacklist_is_listed(session, identity->fpr, &listed);
   995     assert(status == PEP_STATUS_OK);
   996     if (status != PEP_STATUS_OK)
   997         return status;
   998 
   999     if (listed)
  1000         return PEP_KEY_BLACKLISTED;
  1001 
  1002     sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
  1003 
  1004     if (identity->lang[0]) {
  1005         assert(identity->lang[0] >= 'a' && identity->lang[0] <= 'z');
  1006         assert(identity->lang[1] >= 'a' && identity->lang[1] <= 'z');
  1007         assert(identity->lang[2] == 0);
  1008     }
  1009 
  1010     sqlite3_reset(session->set_person);
  1011     sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
  1012             SQLITE_STATIC);
  1013     sqlite3_bind_text(session->set_person, 2, identity->username, -1,
  1014             SQLITE_STATIC);
  1015     if (identity->lang[0])
  1016         sqlite3_bind_text(session->set_person, 3, identity->lang, 2,
  1017                 SQLITE_STATIC);
  1018     else
  1019         sqlite3_bind_null(session->set_person, 3);
  1020     sqlite3_bind_text(session->set_person, 4, identity->fpr, -1,
  1021                       SQLITE_STATIC);
  1022     result = sqlite3_step(session->set_person);
  1023     sqlite3_reset(session->set_person);
  1024     if (result != SQLITE_DONE) {
  1025         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1026         return PEP_CANNOT_SET_PERSON;
  1027     }
  1028 
  1029     sqlite3_reset(session->set_pgp_keypair);
  1030     sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
  1031             SQLITE_STATIC);
  1032     result = sqlite3_step(session->set_pgp_keypair);
  1033     sqlite3_reset(session->set_pgp_keypair);
  1034     if (result != SQLITE_DONE) {
  1035         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1036         return PEP_CANNOT_SET_PGP_KEYPAIR;
  1037     }
  1038 
  1039     sqlite3_reset(session->set_identity);
  1040     sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
  1041             SQLITE_STATIC);
  1042     sqlite3_bind_text(session->set_identity, 2, identity->fpr, -1,
  1043             SQLITE_STATIC);
  1044     sqlite3_bind_text(session->set_identity, 3, identity->user_id, -1,
  1045             SQLITE_STATIC);
  1046     sqlite3_bind_int(session->set_identity, 4, identity->flags);
  1047     result = sqlite3_step(session->set_identity);
  1048     sqlite3_reset(session->set_identity);
  1049     if (result != SQLITE_DONE) {
  1050         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1051         return PEP_CANNOT_SET_IDENTITY;
  1052     }
  1053 
  1054     sqlite3_reset(session->set_trust);
  1055     sqlite3_bind_text(session->set_trust, 1, identity->user_id, -1,
  1056             SQLITE_STATIC);
  1057     sqlite3_bind_text(session->set_trust, 2, identity->fpr, -1,
  1058             SQLITE_STATIC);
  1059     sqlite3_bind_int(session->set_trust, 3, identity->comm_type);
  1060     result = sqlite3_step(session->set_trust);
  1061     sqlite3_reset(session->set_trust);
  1062     if (result != SQLITE_DONE) {
  1063         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1064         return PEP_CANNOT_SET_TRUST;
  1065     }
  1066 
  1067     result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
  1068     if (result == SQLITE_OK)
  1069         return PEP_STATUS_OK;
  1070     else
  1071         return PEP_COMMIT_FAILED;
  1072 }
  1073 
  1074 DYNAMIC_API PEP_STATUS set_identity_flags(
  1075         PEP_SESSION session,
  1076         pEp_identity *identity,
  1077         unsigned int flags
  1078     )
  1079 {
  1080     int result;
  1081 
  1082     assert(session);
  1083     assert(identity);
  1084     assert(identity->address);
  1085     assert(identity->user_id);
  1086 
  1087     if (!(session && identity && identity->address && identity->user_id))
  1088         return PEP_ILLEGAL_VALUE;
  1089 
  1090     sqlite3_reset(session->set_identity_flags);
  1091     sqlite3_bind_int(session->set_identity_flags, 1, flags);
  1092     sqlite3_bind_text(session->set_identity_flags, 2, identity->address, -1,
  1093             SQLITE_STATIC);
  1094     sqlite3_bind_text(session->set_identity_flags, 3, identity->user_id, -1,
  1095             SQLITE_STATIC);
  1096     result = sqlite3_step(session->set_identity_flags);
  1097     sqlite3_reset(session->set_identity_flags);
  1098     if (result != SQLITE_DONE)
  1099         return PEP_CANNOT_SET_IDENTITY;
  1100 
  1101     identity->flags = flags;
  1102     return PEP_STATUS_OK;
  1103 }
  1104 
  1105 DYNAMIC_API PEP_STATUS mark_as_compromized(
  1106         PEP_SESSION session,
  1107         const char *fpr
  1108     )
  1109 {
  1110     int result;
  1111 
  1112     assert(session);
  1113     assert(fpr && fpr[0]);
  1114 
  1115     if (!(session && fpr && fpr[0]))
  1116         return PEP_ILLEGAL_VALUE;
  1117 
  1118     sqlite3_reset(session->mark_compromized);
  1119     sqlite3_bind_text(session->mark_compromized, 1, fpr, -1,
  1120             SQLITE_STATIC);
  1121     result = sqlite3_step(session->mark_compromized);
  1122     sqlite3_reset(session->mark_compromized);
  1123 
  1124     if (result != SQLITE_DONE)
  1125         return PEP_CANNOT_SET_TRUST;
  1126 
  1127     return PEP_STATUS_OK;
  1128 }
  1129 
  1130 void pEp_free(void *p)
  1131 {
  1132     free(p);
  1133 }
  1134 
  1135 DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
  1136 {
  1137     PEP_STATUS status = PEP_STATUS_OK;
  1138     int result;
  1139 
  1140     assert(session);
  1141     assert(identity);
  1142     assert(identity->user_id);
  1143     assert(identity->user_id[0]);
  1144     assert(identity->fpr);
  1145     assert(identity->fpr[0]);
  1146 
  1147     if (!(session && identity && identity->user_id && identity->user_id[0] &&
  1148                 identity->fpr && identity->fpr[0]))
  1149         return PEP_ILLEGAL_VALUE;
  1150 
  1151     identity->comm_type = PEP_ct_unknown;
  1152 
  1153     sqlite3_reset(session->get_trust);
  1154     sqlite3_bind_text(session->get_trust, 1, identity->user_id, -1,
  1155             SQLITE_STATIC);
  1156     sqlite3_bind_text(session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
  1157 
  1158     result = sqlite3_step(session->get_trust);
  1159     switch (result) {
  1160     case SQLITE_ROW: {
  1161         int comm_type = (PEP_comm_type) sqlite3_column_int(session->get_trust,
  1162                 0);
  1163         identity->comm_type = comm_type;
  1164         break;
  1165     }
  1166  
  1167     default:
  1168         status = PEP_CANNOT_FIND_IDENTITY;
  1169     }
  1170 
  1171     sqlite3_reset(session->get_trust);
  1172     return status;
  1173 }
  1174 
  1175 DYNAMIC_API PEP_STATUS least_trust(
  1176         PEP_SESSION session,
  1177         const char *fpr,
  1178         PEP_comm_type *comm_type
  1179     )
  1180 {
  1181     PEP_STATUS status = PEP_STATUS_OK;
  1182     int result;
  1183 
  1184     assert(session);
  1185     assert(fpr);
  1186     assert(comm_type);
  1187 
  1188     if (!(session && fpr && comm_type))
  1189         return PEP_ILLEGAL_VALUE;
  1190 
  1191     *comm_type = PEP_ct_unknown;
  1192 
  1193     sqlite3_reset(session->least_trust);
  1194     sqlite3_bind_text(session->least_trust, 1, fpr, -1, SQLITE_STATIC);
  1195 
  1196     result = sqlite3_step(session->least_trust);
  1197     switch (result) {
  1198         case SQLITE_ROW: {
  1199             int _comm_type = sqlite3_column_int(session->least_trust, 0);
  1200             *comm_type = (PEP_comm_type) _comm_type;
  1201             break;
  1202         }
  1203         default:
  1204             status = PEP_CANNOT_FIND_IDENTITY;
  1205     }
  1206 
  1207     sqlite3_reset(session->least_trust);
  1208     return status;
  1209 }
  1210 
  1211 DYNAMIC_API PEP_STATUS decrypt_and_verify(
  1212     PEP_SESSION session, const char *ctext, size_t csize,
  1213     char **ptext, size_t *psize, stringlist_t **keylist
  1214     )
  1215 {
  1216     assert(session);
  1217     assert(ctext);
  1218     assert(csize);
  1219     assert(ptext);
  1220     assert(psize);
  1221     assert(keylist);
  1222 
  1223     if (!(session && ctext && csize && ptext && psize && keylist))
  1224         return PEP_ILLEGAL_VALUE;
  1225 
  1226     return session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(
  1227             session, ctext, csize, ptext, psize, keylist);
  1228 }
  1229 
  1230 DYNAMIC_API PEP_STATUS encrypt_and_sign(
  1231     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
  1232     size_t psize, char **ctext, size_t *csize
  1233     )
  1234 {
  1235     assert(session);
  1236     assert(keylist);
  1237     assert(ptext);
  1238     assert(psize);
  1239     assert(ctext);
  1240     assert(csize);
  1241 
  1242     if (!(session && keylist && ptext && psize && ctext && csize))
  1243         return PEP_ILLEGAL_VALUE;
  1244 
  1245     return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session,
  1246             keylist, ptext, psize, ctext, csize);
  1247 }
  1248 
  1249 DYNAMIC_API PEP_STATUS verify_text(
  1250     PEP_SESSION session, const char *text, size_t size,
  1251     const char *signature, size_t sig_size, stringlist_t **keylist
  1252     )
  1253 {
  1254     assert(session);
  1255     assert(text);
  1256     assert(size);
  1257     assert(signature);
  1258     assert(sig_size);
  1259     assert(keylist);
  1260 
  1261     if (!(session && text && size && signature && sig_size && keylist))
  1262         return PEP_ILLEGAL_VALUE;
  1263 
  1264     return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text,
  1265             size, signature, sig_size, keylist);
  1266 }
  1267 
  1268 DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
  1269 {
  1270     assert(session);
  1271     assert(fpr);
  1272 
  1273     if (!(session && fpr))
  1274         return PEP_ILLEGAL_VALUE;
  1275 
  1276     return session->cryptotech[PEP_crypt_OpenPGP].delete_keypair(session, fpr);
  1277 }
  1278 
  1279 DYNAMIC_API PEP_STATUS export_key(
  1280         PEP_SESSION session, const char *fpr, char **key_data, size_t *size
  1281     )
  1282 {
  1283     assert(session);
  1284     assert(fpr);
  1285     assert(key_data);
  1286     assert(size);
  1287 
  1288     if (!(session && fpr && key_data && size))
  1289         return PEP_ILLEGAL_VALUE;
  1290 
  1291     return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr,
  1292             key_data, size);
  1293 }
  1294 
  1295 DYNAMIC_API PEP_STATUS find_keys(
  1296         PEP_SESSION session, const char *pattern, stringlist_t **keylist
  1297     )
  1298 {
  1299     assert(session);
  1300     assert(pattern);
  1301     assert(keylist);
  1302 
  1303     if (!(session && pattern && keylist))
  1304         return PEP_ILLEGAL_VALUE;
  1305 
  1306     return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern,
  1307             keylist);
  1308 }
  1309 
  1310 
  1311 DYNAMIC_API PEP_STATUS generate_keypair(
  1312         PEP_SESSION session, pEp_identity *identity
  1313     )
  1314 {
  1315     assert(session);
  1316     assert(identity);
  1317     assert(identity->address);
  1318     assert(identity->fpr == NULL || identity->fpr[0] == 0);
  1319     assert(identity->username);
  1320 
  1321     if (!(session && identity && identity->address &&
  1322             (identity->fpr == NULL || identity->fpr[0] == 0) &&
  1323             identity->username))
  1324         return PEP_ILLEGAL_VALUE;
  1325 
  1326     PEP_STATUS status =
  1327         session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session,
  1328                 identity);
  1329     if (status != PEP_STATUS_OK)
  1330         return status;
  1331 
  1332     // if a state machine for keysync is in place, inject notify
  1333     if (session->sync_state != DeviceState_state_NONE)
  1334         status = fsm_DeviceState_inject(session, KeyGen, NULL, NULL);
  1335 
  1336     return status;
  1337 }
  1338 
  1339 DYNAMIC_API PEP_STATUS get_key_rating(
  1340         PEP_SESSION session,
  1341         const char *fpr,
  1342         PEP_comm_type *comm_type
  1343     )
  1344 {
  1345     assert(session);
  1346     assert(fpr);
  1347     assert(comm_type);
  1348 
  1349     if (!(session && fpr && comm_type))
  1350         return PEP_ILLEGAL_VALUE;
  1351 
  1352     return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr,
  1353             comm_type);
  1354 }
  1355 
  1356 DYNAMIC_API PEP_STATUS import_key(
  1357         PEP_SESSION session,
  1358         const char *key_data,
  1359         size_t size,
  1360         identity_list **private_keys
  1361     )
  1362 {
  1363     assert(session);
  1364     assert(key_data);
  1365 
  1366     if (!(session && key_data))
  1367         return PEP_ILLEGAL_VALUE;
  1368 
  1369     return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data,
  1370             size, private_keys);
  1371 }
  1372 
  1373 DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
  1374 {
  1375     assert(session);
  1376     assert(pattern);
  1377 
  1378     if (!(session && pattern))
  1379         return PEP_ILLEGAL_VALUE;
  1380 
  1381     return session->cryptotech[PEP_crypt_OpenPGP].recv_key(session, pattern);
  1382 }
  1383 
  1384 DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
  1385 {
  1386     assert(session);
  1387     assert(pattern);
  1388 
  1389     if (!(session && pattern))
  1390         return PEP_ILLEGAL_VALUE;
  1391 
  1392     return session->cryptotech[PEP_crypt_OpenPGP].send_key(session, pattern);
  1393 }
  1394 
  1395 DYNAMIC_API PEP_STATUS renew_key(
  1396         PEP_SESSION session,
  1397         const char *fpr,
  1398         const timestamp *ts
  1399     )
  1400 {
  1401     assert(session);
  1402     assert(fpr);
  1403 
  1404     if (!(session && fpr))
  1405         return PEP_ILLEGAL_VALUE;
  1406 
  1407     return session->cryptotech[PEP_crypt_OpenPGP].renew_key(session, fpr, ts);
  1408 }
  1409 
  1410 DYNAMIC_API PEP_STATUS revoke_key(
  1411         PEP_SESSION session,
  1412         const char *fpr,
  1413         const char *reason
  1414     )
  1415 {
  1416     assert(session);
  1417     assert(fpr);
  1418 
  1419     if (!(session && fpr))
  1420         return PEP_ILLEGAL_VALUE;
  1421 
  1422     return session->cryptotech[PEP_crypt_OpenPGP].revoke_key(session, fpr,
  1423             reason);
  1424 }
  1425 
  1426 DYNAMIC_API PEP_STATUS key_expired(
  1427         PEP_SESSION session,
  1428         const char *fpr,
  1429         const time_t when,
  1430         bool *expired
  1431     )
  1432 {
  1433     assert(session);
  1434     assert(fpr);
  1435     assert(expired);
  1436 
  1437     if (!(session && fpr && expired))
  1438         return PEP_ILLEGAL_VALUE;
  1439 
  1440     return session->cryptotech[PEP_crypt_OpenPGP].key_expired(session, fpr,
  1441             when, expired);
  1442 }
  1443 
  1444 DYNAMIC_API PEP_STATUS key_revoked(
  1445        PEP_SESSION session,
  1446        const char *fpr,
  1447        bool *revoked
  1448    )
  1449 {
  1450     assert(session);
  1451     assert(fpr);
  1452     assert(revoked);
  1453     
  1454     if (!(session && fpr && revoked))
  1455         return PEP_ILLEGAL_VALUE;
  1456     
  1457     return session->cryptotech[PEP_crypt_OpenPGP].key_revoked(session, fpr,
  1458             revoked);
  1459 }
  1460 
  1461 static void _clean_log_value(char *text)
  1462 {
  1463     if (text) {
  1464         for (char *c = text; *c; c++) {
  1465             if (*c < 32 && *c != '\n')
  1466                 *c = 32;
  1467             else if (*c == '"')
  1468                 *c = '\'';
  1469         }
  1470     }
  1471 }
  1472 
  1473 static char *_concat_string(char *str1, const char *str2, char delim)
  1474 {
  1475     str2 = str2 ? str2 : "";
  1476     size_t len1 = str1 ? strlen(str1) : 0;
  1477     size_t len2 = strlen(str2);
  1478     size_t len = len1 + len2 + 3;
  1479     char * result = realloc(str1, len + 1);
  1480 
  1481     if (result) {
  1482         result[len1] = '"';
  1483         strcpy(result + len1 + 1, str2);
  1484         result[len - 2] = '"';
  1485         result[len - 1] = delim;
  1486         result[len] = 0;
  1487     }
  1488     else {
  1489         free(str1);
  1490     }
  1491 
  1492     return result;
  1493 }
  1494 
  1495 DYNAMIC_API PEP_STATUS get_crashdump_log(
  1496         PEP_SESSION session,
  1497         int maxlines,
  1498         char **logdata
  1499     )
  1500 {
  1501     PEP_STATUS status = PEP_STATUS_OK;
  1502     char *_logdata= NULL;
  1503 
  1504     assert(session);
  1505     assert(maxlines >= 0 && maxlines <= CRASHDUMP_MAX_LINES);
  1506     assert(logdata);
  1507 
  1508     if (!(session && logdata && maxlines >= 0 && maxlines <=
  1509             CRASHDUMP_MAX_LINES))
  1510         return PEP_ILLEGAL_VALUE;
  1511 
  1512     *logdata = NULL;
  1513 
  1514     int limit = maxlines ? maxlines : CRASHDUMP_DEFAULT_LINES;
  1515     const char *timestamp = NULL;
  1516     const char *title = NULL;
  1517     const char *entity = NULL;
  1518     const char *desc = NULL;
  1519     const char *comment = NULL;
  1520 
  1521     sqlite3_reset(session->crashdump);
  1522     sqlite3_bind_int(session->crashdump, 1, limit);
  1523 
  1524     int result;
  1525 
  1526     do {
  1527         result = sqlite3_step(session->crashdump);
  1528         switch (result) {
  1529         case SQLITE_ROW:
  1530             timestamp = (const char *) sqlite3_column_text(session->crashdump,
  1531                     0);
  1532             title   = (const char *) sqlite3_column_text(session->crashdump,
  1533                     1);
  1534             entity  = (const char *) sqlite3_column_text(session->crashdump,
  1535                     2);
  1536             desc    = (const char *) sqlite3_column_text(session->crashdump,
  1537                     3);
  1538             comment = (const char *) sqlite3_column_text(session->crashdump,
  1539                     4);
  1540 
  1541             _logdata = _concat_string(_logdata, timestamp, ',');
  1542             if (_logdata == NULL)
  1543                 goto enomem;
  1544 
  1545             _logdata = _concat_string(_logdata, title, ',');
  1546             if (_logdata == NULL)
  1547                 goto enomem;
  1548 
  1549             _logdata = _concat_string(_logdata, entity, ',');
  1550             if (_logdata == NULL)
  1551                 goto enomem;
  1552 
  1553             _logdata = _concat_string(_logdata, desc, ',');
  1554             if (_logdata == NULL)
  1555                 goto enomem;
  1556 
  1557             _logdata = _concat_string(_logdata, comment, '\n');
  1558             if (_logdata == NULL)
  1559                 goto enomem;
  1560 
  1561             _clean_log_value(_logdata);
  1562             break;
  1563 
  1564         case SQLITE_DONE:
  1565             break;
  1566 
  1567         default:
  1568             status = PEP_UNKNOWN_ERROR;
  1569             result = SQLITE_DONE;
  1570         }
  1571     } while (result != SQLITE_DONE);
  1572 
  1573     sqlite3_reset(session->crashdump);
  1574     if (status == PEP_STATUS_OK)
  1575         *logdata = _logdata;
  1576 
  1577     goto the_end;
  1578 
  1579 enomem:
  1580     status = PEP_OUT_OF_MEMORY;
  1581 
  1582 the_end:
  1583     return status;
  1584 }
  1585 
  1586 DYNAMIC_API PEP_STATUS get_languagelist(
  1587         PEP_SESSION session,
  1588         char **languages
  1589     )
  1590 {
  1591     PEP_STATUS status = PEP_STATUS_OK;
  1592     char *_languages= NULL;
  1593 
  1594     assert(session);
  1595     assert(languages);
  1596 
  1597     if (!(session && languages))
  1598         return PEP_ILLEGAL_VALUE;
  1599 
  1600     *languages = NULL;
  1601 
  1602     const char *lang = NULL;
  1603     const char *name = NULL;
  1604     const char *phrase = NULL;
  1605 
  1606     sqlite3_reset(session->languagelist);
  1607 
  1608     int result;
  1609 
  1610     do {
  1611         result = sqlite3_step(session->languagelist);
  1612         switch (result) {
  1613         case SQLITE_ROW:
  1614             lang = (const char *) sqlite3_column_text(session->languagelist,
  1615                     0);
  1616             name = (const char *) sqlite3_column_text(session->languagelist,
  1617                     1);
  1618             phrase = (const char *) sqlite3_column_text(session->languagelist,
  1619                     2);
  1620 
  1621             _languages = _concat_string(_languages, lang, ',');
  1622             if (_languages == NULL)
  1623                 goto enomem;
  1624 
  1625             _languages = _concat_string(_languages, name, ',');
  1626             if (_languages == NULL)
  1627                 goto enomem;
  1628 
  1629             _languages = _concat_string(_languages, phrase, '\n');
  1630             if (_languages == NULL)
  1631                 goto enomem;
  1632 
  1633             break;
  1634 
  1635         case SQLITE_DONE:
  1636             break;
  1637 
  1638         default:
  1639             status = PEP_UNKNOWN_ERROR;
  1640             result = SQLITE_DONE;
  1641         }
  1642     } while (result != SQLITE_DONE);
  1643 
  1644     sqlite3_reset(session->languagelist);
  1645     if (status == PEP_STATUS_OK)
  1646         *languages = _languages;
  1647 
  1648     goto the_end;
  1649 
  1650 enomem:
  1651     status = PEP_OUT_OF_MEMORY;
  1652 
  1653 the_end:
  1654     return status;
  1655 }
  1656 
  1657 DYNAMIC_API PEP_STATUS get_phrase(
  1658         PEP_SESSION session,
  1659         const char *lang,
  1660         int phrase_id,
  1661         char **phrase
  1662     )
  1663 {
  1664     PEP_STATUS status = PEP_STATUS_OK;
  1665 
  1666     assert(session && lang && lang[0] && lang[1] && lang[2] == 0 && phrase);
  1667     if (!(session && lang && lang[0] && lang[1] && lang[2] == 0 && phrase))
  1668         return PEP_ILLEGAL_VALUE;
  1669 
  1670     *phrase = NULL;
  1671 
  1672     sqlite3_reset(session->i18n_token);
  1673     sqlite3_bind_text(session->i18n_token, 1, lang, -1, SQLITE_STATIC);
  1674     sqlite3_bind_int(session->i18n_token, 2, phrase_id);
  1675 
  1676     const char *_phrase = NULL;
  1677     int result;
  1678 
  1679     result = sqlite3_step(session->i18n_token);
  1680     switch (result) {
  1681     case SQLITE_ROW:
  1682         _phrase = (const char *) sqlite3_column_text(session->i18n_token, 0);
  1683         break;
  1684 
  1685     case SQLITE_DONE:
  1686         status = PEP_PHRASE_NOT_FOUND;
  1687         break;
  1688 
  1689     default:
  1690         status = PEP_UNKNOWN_ERROR;
  1691     }
  1692 
  1693     if (status == PEP_STATUS_OK) {
  1694         *phrase = strdup(_phrase);
  1695         if (*phrase == NULL)
  1696             goto enomem;
  1697     }
  1698 
  1699     sqlite3_reset(session->i18n_token);
  1700     goto the_end;
  1701 
  1702 enomem:
  1703     status = PEP_OUT_OF_MEMORY;
  1704 
  1705 the_end:
  1706     return status;
  1707 }
  1708 
  1709 static PEP_STATUS _get_sequence_value(PEP_SESSION session, const char *name,
  1710         int32_t *value)
  1711 {
  1712     assert(session && name && value);
  1713     if (!(session && name && value))
  1714         return PEP_ILLEGAL_VALUE;
  1715 
  1716     PEP_STATUS status = PEP_STATUS_OK;
  1717 
  1718     sqlite3_reset(session->sequence_value2);
  1719     sqlite3_bind_text(session->sequence_value2, 1, name, -1,
  1720             SQLITE_STATIC);
  1721     int result = sqlite3_step(session->sequence_value2);
  1722     switch (result) {
  1723         case SQLITE_ROW: {
  1724             int32_t _value = (int32_t)
  1725                     sqlite3_column_int(session->sequence_value2, 0);
  1726             int _own = (int)
  1727                     sqlite3_column_int(session->sequence_value2, 1);
  1728             *value = _value;
  1729             if (_own)
  1730                 status = PEP_OWN_SEQUENCE;
  1731             break;
  1732         }
  1733         case SQLITE_DONE:
  1734             status = PEP_RECORD_NOT_FOUND;
  1735             break;
  1736         default:
  1737             status = PEP_UNKNOWN_ERROR;
  1738     }
  1739     sqlite3_reset(session->sequence_value2);
  1740 
  1741     return status;
  1742 }
  1743 
  1744 static PEP_STATUS _increment_sequence_value(PEP_SESSION session,
  1745         const char *name, int own)
  1746 {
  1747     assert(session && name);
  1748     if (!(session && name))
  1749         return PEP_ILLEGAL_VALUE;
  1750 
  1751     sqlite3_reset(session->sequence_value1);
  1752     sqlite3_bind_text(session->sequence_value1, 1, name, -1, SQLITE_STATIC);
  1753     sqlite3_bind_int(session->sequence_value1, 2, own);
  1754     int result = sqlite3_step(session->sequence_value1);
  1755     assert(result == SQLITE_DONE);
  1756     sqlite3_reset(session->sequence_value1);
  1757     if (result == SQLITE_DONE)
  1758         return PEP_STATUS_OK;
  1759     else
  1760         return PEP_CANNOT_INCREASE_SEQUENCE;
  1761 }
  1762 
  1763 static PEP_STATUS _set_sequence_value(PEP_SESSION session,
  1764         const char *name, int32_t value, int own)
  1765 {
  1766     assert(session && name && value > 0);
  1767     if (!(session && name && value > 0))
  1768         return PEP_ILLEGAL_VALUE;
  1769 
  1770     sqlite3_reset(session->sequence_value3);
  1771     sqlite3_bind_text(session->sequence_value3, 1, name, -1, SQLITE_STATIC);
  1772     sqlite3_bind_int(session->sequence_value3, 2, value);
  1773     sqlite3_bind_int(session->sequence_value3, 3, own);
  1774     int result = sqlite3_step(session->sequence_value3);
  1775     assert(result == SQLITE_DONE);
  1776     sqlite3_reset(session->sequence_value3);
  1777     if (result == SQLITE_DONE)
  1778         return PEP_STATUS_OK;
  1779     else
  1780         return PEP_CANNOT_SET_SEQUENCE_VALUE;
  1781 }
  1782 
  1783 DYNAMIC_API PEP_STATUS sequence_value(
  1784         PEP_SESSION session,
  1785         char *name,
  1786         int32_t *value
  1787     )
  1788 {
  1789     PEP_STATUS status = PEP_STATUS_OK;
  1790 
  1791     assert(session);
  1792     assert(name && value && *value >= 0);
  1793 
  1794     if (!(session && name && value && *value >= 0))
  1795         return PEP_ILLEGAL_VALUE;
  1796 
  1797     int own = 0;
  1798     if (!name[0]) {
  1799         unsigned char uuid[16];
  1800         uuid_generate_random(uuid);
  1801         uuid_unparse_upper(uuid, name);
  1802         own = 1;
  1803     }
  1804     else {
  1805         if (name == sync_uuid || strcmp(name, sync_uuid) == 0)
  1806             own = 1;
  1807     }
  1808 
  1809     if (*value) {
  1810         int32_t old_value = 0;
  1811         status = _get_sequence_value(session, name, &old_value);
  1812         if (status != PEP_STATUS_OK && status != PEP_RECORD_NOT_FOUND)
  1813             return status;
  1814 
  1815         if (old_value >= *value) {
  1816             return PEP_SEQUENCE_VIOLATED;
  1817         }
  1818         else {
  1819             status = _set_sequence_value(session, name, *value, own);
  1820             return status;
  1821         }
  1822     }
  1823 
  1824     assert(*value == 0);
  1825     status = _increment_sequence_value(session, name, own);
  1826     if (status == PEP_STATUS_OK) {
  1827         status = _get_sequence_value(session, name, value);
  1828         assert(*value < INT32_MAX);
  1829         if (*value == INT32_MAX)
  1830             return PEP_CANNOT_INCREASE_SEQUENCE;
  1831     }
  1832     return status;
  1833 }
  1834 
  1835 DYNAMIC_API PEP_STATUS set_revoked(
  1836        PEP_SESSION session,
  1837        const char *revoked_fpr,
  1838        const char *replacement_fpr,
  1839        const uint64_t revocation_date
  1840     )
  1841 {
  1842     PEP_STATUS status = PEP_STATUS_OK;
  1843     
  1844     assert(session &&
  1845            revoked_fpr && revoked_fpr[0] &&
  1846            replacement_fpr && replacement_fpr[0]
  1847           );
  1848     
  1849     if (!(session &&
  1850           revoked_fpr && revoked_fpr[0] &&
  1851           replacement_fpr && replacement_fpr[0]
  1852          ))
  1853         return PEP_ILLEGAL_VALUE;
  1854     
  1855     sqlite3_reset(session->set_revoked);
  1856     sqlite3_bind_text(session->set_revoked, 1, revoked_fpr, -1, SQLITE_STATIC);
  1857     sqlite3_bind_text(session->set_revoked, 2, replacement_fpr, -1,
  1858             SQLITE_STATIC);
  1859     sqlite3_bind_int64(session->set_revoked, 3, revocation_date);
  1860 
  1861     int result;
  1862     
  1863     result = sqlite3_step(session->set_revoked);
  1864     switch (result) {
  1865         case SQLITE_DONE:
  1866             status = PEP_STATUS_OK;
  1867             break;
  1868             
  1869         default:
  1870             status = PEP_UNKNOWN_ERROR;
  1871     }
  1872     
  1873     sqlite3_reset(session->set_revoked);
  1874     return status;
  1875 }
  1876 
  1877 DYNAMIC_API PEP_STATUS get_revoked(
  1878         PEP_SESSION session,
  1879         const char *fpr,
  1880         char **revoked_fpr,
  1881         uint64_t *revocation_date
  1882     )
  1883 {
  1884     PEP_STATUS status = PEP_STATUS_OK;
  1885 
  1886     assert(session &&
  1887            revoked_fpr &&
  1888            fpr && fpr[0]
  1889           );
  1890     
  1891     if (!(session &&
  1892            revoked_fpr &&
  1893            fpr && fpr[0]
  1894           ))
  1895         return PEP_ILLEGAL_VALUE;
  1896 
  1897     *revoked_fpr = NULL;
  1898     *revocation_date = 0;
  1899 
  1900     sqlite3_reset(session->get_revoked);
  1901     sqlite3_bind_text(session->get_revoked, 1, fpr, -1, SQLITE_STATIC);
  1902 
  1903     int result;
  1904     
  1905     result = sqlite3_step(session->get_revoked);
  1906     switch (result) {
  1907         case SQLITE_ROW: {
  1908             *revoked_fpr = strdup((const char *)
  1909                     sqlite3_column_text(session->get_revoked, 0));
  1910             if(*revoked_fpr)
  1911                 *revocation_date = sqlite3_column_int64(session->get_revoked,
  1912                         1);
  1913             else
  1914                 status = PEP_OUT_OF_MEMORY;
  1915 
  1916             break;
  1917         }
  1918         default:
  1919             status = PEP_CANNOT_FIND_IDENTITY;
  1920     }
  1921 
  1922     sqlite3_reset(session->get_revoked);
  1923 
  1924     return status;
  1925 }
  1926 
  1927 PEP_STATUS key_created(
  1928         PEP_SESSION session,
  1929         const char *fpr,
  1930         time_t *created
  1931     )
  1932 {
  1933     assert(session && fpr && created);
  1934     if (!(session && fpr && created))
  1935         return PEP_ILLEGAL_VALUE;
  1936 
  1937     return session->cryptotech[PEP_crypt_OpenPGP].key_created(session, fpr,
  1938             created);
  1939 }
  1940 
  1941 DYNAMIC_API const char* get_engine_version() {
  1942     return PEP_ENGINE_VERSION;
  1943 }
  1944 
  1945 
  1946 DYNAMIC_API PEP_STATUS reset_peptest_hack(PEP_SESSION session)
  1947 {
  1948     assert(session);
  1949 
  1950     if (!session)
  1951         return PEP_ILLEGAL_VALUE;
  1952 
  1953     int int_result = sqlite3_exec(
  1954         session->db,
  1955         "delete from identity where address like '%@peptest.ch' ;",
  1956         NULL,
  1957         NULL,
  1958         NULL
  1959     );
  1960     assert(int_result == SQLITE_OK);
  1961 
  1962     return PEP_STATUS_OK;
  1963 }
  1964