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