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