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