src/pEpEngine.c
author Krista Bennett <krista@pep-project.org>
Wed, 13 Dec 2017 11:42:23 +0100
branchENGINE-289
changeset 2311 688b925c3e73
parent 2308 b7ef1c9005ae
child 2317 b80dd91c8869
permissions -rw-r--r--
ENGINE-289: shelving to work on another bug
     1 // This file is under GNU General Public License 3.0
     2 // see LICENSE.txt
     3 
     4 #include "pEp_internal.h"
     5 #include "dynamic_api.h"
     6 #include "cryptotech.h"
     7 #include "transport.h"
     8 #include "blacklist.h"
     9 
    10 #include <time.h>
    11 #include <stdlib.h>
    12 
    13 static volatile int init_count = -1;
    14 
    15 // sql overloaded functions - modified from sqlite3.c
    16 static void _sql_lower(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
    17     char *z1;
    18     const char *z2;
    19     int i, n;
    20     z2 = (char*)sqlite3_value_text(argv[0]);
    21     n = sqlite3_value_bytes(argv[0]);
    22     /* Verify that the call to _bytes() does not invalidate the _text() pointer */
    23     assert( z2==(char*)sqlite3_value_text(argv[0]) );
    24     if( z2 ){
    25         z1 = (char*)sqlite3_malloc(n+1);
    26         if( z1 ){
    27             for(i=0; i<n; i++){
    28                 char c = z2[i];
    29                 char c_mod = c | 0x20;
    30                 if (c_mod < 0x61 || c_mod > 0x7a)
    31                     c_mod = c;
    32                 z1[i] = c_mod;
    33             }
    34             z1[n] = '\0';
    35             sqlite3_result_text(ctx, z1, n, sqlite3_free);
    36         }
    37     }
    38 }
    39 
    40 
    41 // sql manipulation statements
    42 static const char *sql_log = 
    43     "insert into log (title, entity, description, comment)"
    44      "values (?1, ?2, ?3, ?4);";
    45 
    46 static const char *sql_trustword = 
    47     "select id, word from wordlist where lang = lower(?1) "
    48     "and id = ?2 ;";
    49 
    50 static const char *sql_get_identity =  
    51     "select fpr, username, comm_type, lang,"
    52     "   identity.flags | pgp_keypair.flags,"
    53     "   is_own"
    54     "   from identity"
    55     "   join person on id = identity.user_id"
    56     "   join pgp_keypair on fpr = identity.main_key_id"
    57     "   join trust on id = trust.user_id"
    58     "       and pgp_keypair_fpr = identity.main_key_id"    
    59     "   where (case when (address = ?1) then (1)"
    60     "               when (lower(address) = lower(?1)) then (1)"
    61     "               when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)"
    62     "               else 0"
    63     "          end) = 1"
    64     "   and identity.user_id = ?2;";
    65 
    66 static const char *sql_get_identity_without_fpr =  
    67     "select main_key_id, username, comm_type, lang,"
    68     "   identity.flags, is_own"
    69     "   from identity"
    70     "   join person on id = identity.user_id"
    71     "   where (case when (address = ?1) then (1)"
    72     "               when (lower(address) = lower(?1)) then (1)"
    73     "               when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)"
    74     "               else 0"
    75     "          end) = 1"
    76     "   and identity.user_id = ?2;";
    77 
    78 static const char *sql_replace_identities_fpr =  
    79     "update identity"
    80     "   set main_key_id = ?1 "
    81     "   where main_key_id = ?2 ;";
    82 
    83 // Set person, but if already exist, only update.
    84 // if main_key_id already set, don't touch.
    85 static const char *sql_set_person = 
    86     "insert or replace into person (id, username, lang, main_key_id, device_group)"
    87     "  values (?1, ?2, ?3,"
    88     "    (select coalesce((select main_key_id from person "
    89     "      where id = ?1), upper(replace(?4,' ','')))),"
    90     "    (select device_group from person where id = ?1)) ;";
    91 
    92 static const char *sql_set_device_group = 
    93     "update person set device_group = ?1 "
    94     "where id = ?2;";
    95 
    96 static const char *sql_get_device_group = 
    97     "select device_group from person "
    98     "where id = ?1;";
    99 
   100 static const char *sql_set_pgp_keypair = 
   101     "insert or replace into pgp_keypair (fpr) "
   102     "values (upper(replace(?1,' ',''))) ;";
   103 
   104 static const char *sql_set_identity = 
   105     "insert or replace into identity ("
   106     " address, main_key_id, "
   107     " user_id, flags, is_own"
   108     ") values ("
   109     " ?1,"
   110     " upper(replace(?2,' ','')),"
   111     " ?3,"
   112     // " (select"
   113     // "   coalesce("
   114     // "    (select flags from identity"
   115     // "     where address = ?1 and"
   116     // "           user_id = ?3),"
   117     // "    0)"
   118     // " ) | (?4 & 255)"
   119     /* set_identity ignores previous flags, and doesn't filter machine flags */
   120     " ?4,"
   121     " ?5"
   122     ");";
   123         
   124 static const char *sql_set_identity_flags = 
   125     "update identity set flags = "
   126     "    ((?1 & 255) | (select flags from identity"
   127     "                   where address = ?2 and user_id = ?3)) "
   128     "where address = ?2 and user_id = ?3 ;";
   129 
   130 static const char *sql_unset_identity_flags = 
   131     "update identity set flags = "
   132     "    ( ~(?1 & 255) & (select flags from identity"
   133     "                   where address = ?2 and user_id = ?3)) "
   134     "where address = ?2 and user_id = ?3 ;";
   135 
   136 static const char *sql_set_trust =
   137     "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type) "
   138     "values (?1, upper(replace(?2,' ','')), ?3) ;";
   139 
   140 static const char *sql_update_trust_for_fpr =
   141     "update trust "
   142     "set comm_type = ?1 "
   143     "where pgp_keypair_fpr = upper(replace(?2,' ','')) ;";
   144 
   145 static const char *sql_get_trust = 
   146     "select comm_type from trust where user_id = ?1 "
   147     "and pgp_keypair_fpr = upper(replace(?2,' ','')) ;";
   148 
   149 static const char *sql_least_trust = 
   150     "select min(comm_type) from trust where"
   151     " pgp_keypair_fpr = upper(replace(?1,' ',''))"
   152     " and comm_type != 0;"; // ignores PEP_ct_unknown
   153     // returns PEP_ct_unknown only when no known trust is recorded
   154 
   155 static const char *sql_mark_as_compromized = 
   156     "update trust not indexed set comm_type = 15"
   157     " where pgp_keypair_fpr = upper(replace(?1,' ','')) ;";
   158 
   159 static const char *sql_crashdump = 
   160     "select timestamp, title, entity, description, comment"
   161     " from log order by timestamp desc limit ?1 ;";
   162 
   163 static const char *sql_languagelist = 
   164     "select i18n_language.lang, name, phrase" 
   165     " from i18n_language join i18n_token using (lang) where i18n_token.id = 1000;" ;
   166 
   167 static const char *sql_i18n_token = 
   168     "select phrase from i18n_token where lang = lower(?1) and id = ?2 ;";
   169 
   170 
   171 // blacklist
   172 static const char *sql_blacklist_add = 
   173     "insert or replace into blacklist_keys (fpr) values (upper(replace(?1,' ',''))) ;"
   174     "delete from identity where main_key_id = upper(replace(?1,' ','')) ;"
   175     "delete from pgp_keypair where fpr = upper(replace(?1,' ','')) ;";
   176 
   177 static const char *sql_blacklist_delete =
   178     "delete from blacklist_keys where fpr = upper(replace(?1,' ','')) ;";
   179 
   180 static const char *sql_blacklist_is_listed = 
   181     "select count(*) from blacklist_keys where fpr = upper(replace(?1,' ','')) ;";
   182 
   183 static const char *sql_blacklist_retrieve = 
   184     "select * from blacklist_keys ;";
   185                 
   186 
   187 // Own keys
   188 // We only care if it's 0 or non-zero
   189 static const char *sql_own_key_is_listed = 
   190     "select count(*) from ("
   191     "   select pgp_keypair_fpr from trust"
   192     "      join identity on trust.user_id = identity.user_id"
   193     "      where pgp_keypair_fpr = upper(replace(?1,' ',''))"
   194     "           and identity.is_own = 1"
   195     ");";
   196 
   197 static const char *sql_own_identities_retrieve =  
   198     "select address, fpr, username, identity.user_id, "
   199     "   lang, identity.flags | pgp_keypair.flags"
   200     "   from identity"
   201     "   join person on id = identity.user_id"
   202     "   join pgp_keypair on fpr = identity.main_key_id"
   203     "   join trust on id = trust.user_id"
   204     "       and pgp_keypair_fpr = identity.main_key_id"
   205     "   where identity.is_own = 1"
   206     "       and (identity.flags & ?1) = 0;";
   207 
   208 static const char *sql_own_keys_retrieve = 
   209     "select pgp_keypair_fpr from trust"
   210     "   join identity on trust.user_id = identity.user_id"
   211     "   where identity.is_own = 1";
   212 
   213 static const char* sql_get_user_default_key =
   214     "select main_key_id from person" 
   215     "   where id = ?1;";
   216 
   217 static const char* sql_get_own_userid =
   218     "select id from person"
   219     "   join identity on id = identity.user_id"
   220     "   where identity.is_own = 1";
   221 
   222 // Sequence
   223 static const char *sql_sequence_value1 = 
   224     "insert or replace into sequences (name, value, own) "
   225     "values (?1, "
   226     "       (select coalesce((select value + 1 from sequences "
   227     "           where name = ?1), 1 )), "
   228     "       (select coalesce((select own or ?2 from sequences "
   229     "           where name = ?1), ?2))) ; ";
   230 
   231 static const char *sql_sequence_value2 = 
   232     "select value, own from sequences where name = ?1 ;";
   233 
   234 static const char *sql_sequence_value3 = 
   235     "insert or replace into sequences (name, value, own) "
   236     "values (?1, "
   237     "        ?2, "
   238     "       (select coalesce((select own or ?3 from sequences "
   239     "           where name = ?1), ?3))) ; ";
   240         
   241 // Revocation tracking
   242 static const char *sql_set_revoked =
   243     "insert or replace into revoked_keys ("
   244     "    revoked_fpr, replacement_fpr, revocation_date) "
   245     "values (upper(replace(?1,' ','')),"
   246     "        upper(replace(?2,' ','')),"
   247     "        ?3) ;";
   248         
   249 static const char *sql_get_revoked = 
   250     "select revoked_fpr, revocation_date from revoked_keys"
   251     "    where replacement_fpr = upper(replace(?1,' ','')) ;";
   252 
   253 static int user_version(void *_version, int count, char **text, char **name)
   254 {
   255     assert(_version);
   256     assert(count == 1);
   257     assert(text && text[0]);
   258     if (!(_version && count == 1 && text && text[0]))
   259         return -1;
   260 
   261     int *version = (int *) _version;
   262     *version = atoi(text[0]);
   263     return 0;
   264 }
   265 
   266 static int table_contains_column(PEP_SESSION session, const char* table_name,
   267                                                       const char* col_name) {
   268 
   269 
   270     if (!session || !table_name || !col_name)
   271         return -1;
   272         
   273     // Table names can't be SQL parameters, so we do it this way.
   274     
   275     // these two must be the same number.
   276     char sql_buf[500];
   277     const size_t max_q_len = 500;
   278     
   279     size_t t_size, c_size, q_size;
   280     
   281     const char* q1 = "SELECT "; // 7
   282     const char* q2 = " from "; // 6
   283     const char* q3 = ";";       // 1
   284     
   285     q_size = 14;
   286     t_size = strlen(table_name);
   287     c_size = strlen(col_name);
   288     
   289     size_t query_len = q_size + c_size + t_size + 1;
   290     
   291     if (query_len > max_q_len)
   292         return -1;
   293 
   294     strlcpy(sql_buf, q1, max_q_len);
   295     strlcat(sql_buf, col_name, max_q_len);
   296     strlcat(sql_buf, q2, max_q_len);
   297     strlcat(sql_buf, table_name, max_q_len);
   298     strlcat(sql_buf, q3, max_q_len);
   299 
   300     sqlite3_stmt *stmt; 
   301 
   302     sqlite3_prepare_v2(session->db, sql_buf, -1, &stmt, NULL);
   303 
   304     int retval = 0;
   305 
   306     int rc = sqlite3_step(stmt);  
   307     if (rc == SQLITE_DONE || rc == SQLITE_OK || rc == SQLITE_ROW) {
   308         retval = 1;
   309     }
   310 
   311     sqlite3_finalize(stmt);      
   312         
   313     return retval;
   314 }
   315 
   316 DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
   317 {
   318     PEP_STATUS status = PEP_STATUS_OK;
   319     int int_result;
   320     
   321     bool in_first = false;
   322     bool very_first = false;
   323 
   324     assert(sqlite3_threadsafe());
   325     if (!sqlite3_threadsafe())
   326         return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
   327 
   328     // a little race condition - but still a race condition
   329     // mitigated by calling caveat (see documentation)
   330 
   331     // this increment is made atomic IN THE ADAPTERS by
   332     // guarding the call to init with the appropriate mutex.
   333     int _count = ++init_count;
   334     if (_count == 0)
   335         in_first = true;
   336     
   337     // Race condition mitigated by calling caveat starts here :
   338     // If another call to init() preempts right now, then preemptive call
   339     // will have in_first false, will not create SQL tables, and following
   340     // calls relying on those tables will fail.
   341     //
   342     // Therefore, as above, adapters MUST guard init() with a mutex.
   343     // 
   344     // Therefore, first session
   345     // is to be created and last session to be deleted alone, and not
   346     // concurently to other sessions creation or deletion.
   347     // We expect adapters to enforce this either by implicitely creating a
   348     // client session, or by using synchronization primitive to protect
   349     // creation/deletion of first/last session from the app.
   350 
   351     assert(session);
   352     if (session == NULL)
   353         return PEP_ILLEGAL_VALUE;
   354 
   355     *session = NULL;
   356 
   357     pEpSession *_session = calloc(1, sizeof(pEpSession));
   358     assert(_session);
   359     if (_session == NULL)
   360         goto enomem;
   361 
   362     _session->version = PEP_ENGINE_VERSION;
   363 
   364 #ifdef DEBUG_ERRORSTACK
   365     _session->errorstack = new_stringlist("init()");
   366 #endif
   367 
   368     assert(LOCAL_DB);
   369     if (LOCAL_DB == NULL) {
   370         status = PEP_INIT_CANNOT_OPEN_DB;
   371         goto pep_error;
   372     }
   373 
   374     int_result = sqlite3_open_v2(
   375             LOCAL_DB,
   376             &_session->db,
   377             SQLITE_OPEN_READWRITE
   378                 | SQLITE_OPEN_CREATE
   379                 | SQLITE_OPEN_FULLMUTEX
   380                 | SQLITE_OPEN_PRIVATECACHE,
   381             NULL 
   382         );
   383 
   384     if (int_result != SQLITE_OK) {
   385         status = PEP_INIT_CANNOT_OPEN_DB;
   386         goto pep_error;
   387     }
   388 
   389     int_result = sqlite3_exec(
   390             _session->db,
   391             "PRAGMA locking_mode=NORMAL;\n"
   392             "PRAGMA journal_mode=WAL;\n",
   393             NULL,
   394             NULL,
   395             NULL
   396         );
   397 
   398 
   399     sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME);
   400 
   401     assert(SYSTEM_DB);
   402     if (SYSTEM_DB == NULL) {
   403         status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
   404         goto pep_error;
   405     }
   406 
   407     int_result = sqlite3_open_v2(
   408             SYSTEM_DB, &_session->system_db,
   409             SQLITE_OPEN_READONLY
   410                 | SQLITE_OPEN_FULLMUTEX
   411                 | SQLITE_OPEN_SHAREDCACHE,
   412             NULL
   413         );
   414 
   415     if (int_result != SQLITE_OK) {
   416         status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
   417         goto pep_error;
   418     }
   419 
   420     sqlite3_busy_timeout(_session->system_db, 1000);
   421 
   422 // increment this when patching DDL
   423 #define _DDL_USER_VERSION "6"
   424 
   425     if (in_first) {
   426 
   427         int_result = sqlite3_exec(
   428             _session->db,
   429                 "create table if not exists version_info (\n"
   430                 "   id integer primary key,\n"
   431                 "   timestamp integer default (datetime('now')),\n"
   432                 "   version text,\n"
   433                 "   comment text\n"
   434                 ");\n",
   435                 NULL,
   436                 NULL,
   437                 NULL
   438         );
   439         int_result = sqlite3_exec(
   440             _session->db,
   441                 "PRAGMA application_id = 0x23423423;\n"
   442                 "create table if not exists log (\n"
   443                 "   timestamp integer default (datetime('now')),\n"
   444                 "   title text not null,\n"
   445                 "   description text,\n"
   446                 "   entity text not null,\n"
   447                 "   comment text\n"
   448                 ");\n"
   449                 "create index if not exists log_timestamp on log (\n"
   450                 "   timestamp\n"
   451                 ");\n"
   452                 "create table if not exists pgp_keypair (\n"
   453                 "   fpr text primary key,\n"
   454                 "   created integer,\n"
   455                 "   expires integer,\n"
   456                 "   comment text,\n"
   457                 "   flags integer default 0\n"
   458                 ");\n"
   459                 "create index if not exists pgp_keypair_expires on pgp_keypair (\n"
   460                 "   expires\n"
   461                 ");\n"
   462                 "create table if not exists person (\n"
   463                 "   id text primary key,\n"
   464                 "   username text not null,\n"
   465                 "   main_key_id text\n"
   466                 "       references pgp_keypair (fpr)\n"
   467                 "       on delete set null,\n"
   468                 "   lang text,\n"
   469                 "   comment text,\n"
   470                 "   device_group text\n"
   471                 ");\n"
   472                 "create table if not exists identity (\n"
   473                 "   address text,\n"
   474                 "   user_id text\n"
   475                 "       references person (id)\n"
   476                 "       on delete cascade,\n"
   477                 "   main_key_id text\n"
   478                 "       references pgp_keypair (fpr)\n"
   479                 "       on delete set null,\n"
   480                 "   comment text,\n"
   481                 "   flags integer default 0,\n"
   482                 "   is_own integer default 0,\n"
   483                 "   primary key (address, user_id)\n"
   484                 ");\n"
   485                 "create table if not exists trust (\n"
   486                 "   user_id text not null\n"
   487                 "       references person (id)\n"
   488                 "       on delete cascade,\n"
   489                 "   pgp_keypair_fpr text not null\n"
   490                 "       references pgp_keypair (fpr)\n"
   491                 "       on delete cascade,\n"
   492                 "   comm_type integer not null,\n"
   493                 "   comment text,\n"
   494                 "   primary key (user_id, pgp_keypair_fpr)\n"
   495                 ");\n"
   496                 // blacklist
   497                 "create table if not exists blacklist_keys (\n"
   498                 "   fpr text primary key\n"
   499                 ");\n"
   500                 // sequences
   501                 "create table if not exists sequences(\n"
   502                 "   name text primary key,\n"
   503                 "   value integer default 0,\n"
   504                 "   own integer default 0\n"
   505                 ");\n"
   506                 "create table if not exists revoked_keys (\n"
   507                 "   revoked_fpr text primary key,\n"
   508                 "   replacement_fpr text not null\n"
   509                 "       references pgp_keypair (fpr)\n"
   510                 "       on delete cascade,\n"
   511                 "   revocation_date integer\n"
   512                 ");\n"
   513                 ,
   514             NULL,
   515             NULL,
   516             NULL
   517         );
   518         assert(int_result == SQLITE_OK);
   519 
   520         int version;
   521         int_result = sqlite3_exec(
   522             _session->db,
   523             "pragma user_version;",
   524             user_version,
   525             &version,
   526             NULL
   527         );
   528 
   529         assert(int_result == SQLITE_OK);
   530         
   531         void (*xFunc_lower)(sqlite3_context*,int,sqlite3_value**) = &_sql_lower;
   532         
   533         int_result = sqlite3_create_function_v2(
   534             _session->db,
   535             "lower",
   536             1,
   537             SQLITE_UTF8 | SQLITE_DETERMINISTIC,
   538             NULL,
   539             xFunc_lower,
   540             NULL,
   541             NULL,
   542             NULL);
   543         assert(int_result == SQLITE_OK);
   544         
   545         // Sometimes the user_version wasn't set correctly. Check to see if this
   546         // is really necessary...
   547         if (version == 1) {
   548             bool version_changed = true;
   549             
   550             if (table_contains_column(_session, "identity", "is_own") > 0) {
   551                 version = 6;
   552             }
   553             else if (table_contains_column(_session, "sequences", "own") > 0) {
   554                 version = 3;
   555             }
   556             else if (table_contains_column(_session, "pgp_keypair", "flags") > 0) {
   557                 version = 2;
   558             }
   559             else {
   560                 version_changed = false;
   561             }
   562             
   563             if (version_changed) {
   564                 // set it in the DB, finally. Yeesh.
   565                 char verbuf[21]; // enough digits for a max-sized 64 bit int, cmon. 
   566                 sprintf(verbuf,"%d",version);
   567                 
   568                 size_t query_size = strlen(verbuf) + 25;
   569                 char* query = calloc(query_size, 1);
   570                 
   571                 strlcpy(query, "pragma user_version = ", query_size);
   572                 strlcat(query, verbuf, query_size);
   573                 strlcat(query, ";", query_size);
   574                 
   575                 int_result = sqlite3_exec(
   576                     _session->db,
   577                     query,
   578                     user_version,
   579                     &version,
   580                     NULL
   581                 );
   582                 free(query);
   583             }
   584         }
   585 
   586 
   587         if(version != 0) { 
   588             // Version has been already set
   589 
   590             // Early mistake : version 0 shouldn't have existed.
   591             // Numbering should have started at 1 to detect newly created DB.
   592             // Version 0 DBs are not anymore compatible.
   593 
   594             // // Was version 0 compat code.
   595             // if (version < 1) {
   596             //     int_result = sqlite3_exec(
   597             //         _session->db,
   598             //         "alter table identity\n"
   599             //         "   add column flags integer default 0;\n",
   600             //         NULL,
   601             //         NULL,
   602             //         NULL
   603             //     );
   604             //     assert(int_result == SQLITE_OK);
   605             // }
   606             
   607             if (version < 2) {
   608                 int_result = sqlite3_exec(
   609                     _session->db,
   610                     "alter table pgp_keypair\n"
   611                     "   add column flags integer default 0;\n"
   612                     "alter table person\n"
   613                     "   add column device_group text;\n",
   614                     NULL,
   615                     NULL,
   616                     NULL
   617                 );
   618                 assert(int_result == SQLITE_OK);
   619             }
   620 
   621             if (version < 3) {
   622                 int_result = sqlite3_exec(
   623                     _session->db,
   624                     "alter table sequences\n"
   625                     "   add column own integer default 0;\n",
   626                     NULL,
   627                     NULL,
   628                     NULL
   629                 );
   630                 assert(int_result == SQLITE_OK);
   631             }
   632 
   633             if (version < 5) {
   634                 int_result = sqlite3_exec(
   635                     _session->db,
   636                     "delete from pgp_keypair where fpr = '';",
   637                     NULL,
   638                     NULL,
   639                     NULL
   640                 );
   641                 assert(int_result == SQLITE_OK);
   642                 int_result = sqlite3_exec(
   643                     _session->db,
   644                     "delete from trust where pgp_keypair_fpr = '';",
   645                     NULL,
   646                     NULL,
   647                     NULL
   648                 );
   649                 assert(int_result == SQLITE_OK);
   650             }
   651             
   652             if (version < 6) {
   653                 int_result = sqlite3_exec(
   654                     _session->db,
   655                     "alter table identity\n"
   656                     "   add column is_own integer default 0;\n",
   657                     NULL,
   658                     NULL,
   659                     NULL
   660                 );
   661                 assert(int_result == SQLITE_OK);                
   662                 int_result = sqlite3_exec(
   663                     _session->db,
   664                     "update identity\n"
   665                     "   set is_own = 1\n"
   666                     "   where (user_id = '" PEP_OWN_USERID "');\n",
   667                     NULL,
   668                     NULL,
   669                     NULL
   670                 );
   671                 assert(int_result == SQLITE_OK);                
   672             }
   673         }
   674         else { 
   675             // Version from DB was 0, it means this is initial setup.
   676             // DB has just been created, and all tables are empty.
   677             very_first = true;
   678         }
   679 
   680         if (version < atoi(_DDL_USER_VERSION)) {
   681             int_result = sqlite3_exec(
   682                 _session->db,
   683                 "pragma user_version = "_DDL_USER_VERSION";\n"
   684                 "insert or replace into version_info (id, version)"
   685                     "values (1, '" PEP_ENGINE_VERSION "');",
   686                 NULL,
   687                 NULL,
   688                 NULL
   689             );
   690             assert(int_result == SQLITE_OK);
   691         }
   692         
   693         // We need to init a few globals for message id that we'd rather not
   694         // calculate more than once.
   695         _init_globals();
   696     }
   697 
   698     int_result = sqlite3_prepare_v2(_session->db, sql_log,
   699             (int)strlen(sql_log), &_session->log, NULL);
   700     assert(int_result == SQLITE_OK);
   701 
   702     int_result = sqlite3_prepare_v2(_session->system_db, sql_trustword,
   703             (int)strlen(sql_trustword), &_session->trustword, NULL);
   704     assert(int_result == SQLITE_OK);
   705 
   706     int_result = sqlite3_prepare_v2(_session->db, sql_get_identity,
   707             (int)strlen(sql_get_identity), &_session->get_identity, NULL);
   708     assert(int_result == SQLITE_OK);
   709 
   710     int_result = sqlite3_prepare_v2(_session->db, sql_get_identity_without_fpr,
   711             (int)strlen(sql_get_identity_without_fpr), 
   712             &_session->get_identity_without_fpr, NULL);
   713     assert(int_result == SQLITE_OK);
   714 
   715     int_result = sqlite3_prepare_v2(_session->db, sql_get_user_default_key,
   716             (int)strlen(sql_get_user_default_key), &_session->get_user_default_key, NULL);
   717     assert(int_result == SQLITE_OK);
   718 
   719     int_result = sqlite3_prepare_v2(_session->db, sql_get_own_userid,
   720             (int)strlen(sql_get_own_userid), &_session->get_own_userid, NULL);
   721     assert(int_result == SQLITE_OK);
   722 
   723     int_result = sqlite3_prepare_v2(_session->db, sql_replace_identities_fpr,
   724             (int)strlen(sql_replace_identities_fpr), 
   725             &_session->replace_identities_fpr, NULL);
   726     assert(int_result == SQLITE_OK);
   727 
   728     int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
   729             (int)strlen(sql_set_person), &_session->set_person, NULL);
   730     assert(int_result == SQLITE_OK);
   731 
   732     int_result = sqlite3_prepare_v2(_session->db, sql_set_device_group,
   733             (int)strlen(sql_set_device_group), &_session->set_device_group, NULL);
   734     assert(int_result == SQLITE_OK);
   735 
   736     int_result = sqlite3_prepare_v2(_session->db, sql_get_device_group,
   737             (int)strlen(sql_get_device_group), &_session->get_device_group, NULL);
   738     assert(int_result == SQLITE_OK);
   739 
   740     int_result = sqlite3_prepare_v2(_session->db, sql_set_pgp_keypair,
   741             (int)strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair,
   742             NULL);
   743     assert(int_result == SQLITE_OK);
   744 
   745     int_result = sqlite3_prepare_v2(_session->db, sql_set_identity,
   746             (int)strlen(sql_set_identity), &_session->set_identity, NULL);
   747     assert(int_result == SQLITE_OK);
   748 
   749     int_result = sqlite3_prepare_v2(_session->db, sql_set_identity_flags,
   750             (int)strlen(sql_set_identity_flags), &_session->set_identity_flags,
   751             NULL);
   752     assert(int_result == SQLITE_OK);
   753 
   754     int_result = sqlite3_prepare_v2(_session->db, sql_unset_identity_flags,
   755             (int)strlen(sql_unset_identity_flags), &_session->unset_identity_flags,
   756             NULL);
   757     assert(int_result == SQLITE_OK);
   758 
   759     int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
   760             (int)strlen(sql_set_trust), &_session->set_trust, NULL);
   761     assert(int_result == SQLITE_OK);
   762 
   763     int_result = sqlite3_prepare_v2(_session->db, sql_update_trust_for_fpr,
   764             (int)strlen(sql_update_trust_for_fpr), &_session->update_trust_for_fpr, NULL);
   765     assert(int_result == SQLITE_OK);
   766 
   767     int_result = sqlite3_prepare_v2(_session->db, sql_get_trust,
   768             (int)strlen(sql_get_trust), &_session->get_trust, NULL);
   769     assert(int_result == SQLITE_OK);
   770 
   771     int_result = sqlite3_prepare_v2(_session->db, sql_least_trust,
   772             (int)strlen(sql_least_trust), &_session->least_trust, NULL);
   773     assert(int_result == SQLITE_OK);
   774 
   775     int_result = sqlite3_prepare_v2(_session->db, sql_mark_as_compromized,
   776             (int)strlen(sql_mark_as_compromized), &_session->mark_compromized,
   777             NULL);
   778     assert(int_result == SQLITE_OK);
   779 
   780     int_result = sqlite3_prepare_v2(_session->db, sql_crashdump,
   781             (int)strlen(sql_crashdump), &_session->crashdump, NULL);
   782     assert(int_result == SQLITE_OK);
   783 
   784     int_result = sqlite3_prepare_v2(_session->system_db, sql_languagelist,
   785             (int)strlen(sql_languagelist), &_session->languagelist, NULL);
   786     assert(int_result == SQLITE_OK);
   787 
   788     int_result = sqlite3_prepare_v2(_session->system_db, sql_i18n_token,
   789             (int)strlen(sql_i18n_token), &_session->i18n_token, NULL);
   790     assert(int_result == SQLITE_OK);
   791 
   792     // blacklist
   793 
   794     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_add,
   795             (int)strlen(sql_blacklist_add), &_session->blacklist_add, NULL);
   796     assert(int_result == SQLITE_OK);
   797 
   798     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_delete,
   799             (int)strlen(sql_blacklist_delete), &_session->blacklist_delete,
   800             NULL);
   801     assert(int_result == SQLITE_OK);
   802 
   803     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_is_listed,
   804             (int)strlen(sql_blacklist_is_listed),
   805             &_session->blacklist_is_listed, NULL);
   806     assert(int_result == SQLITE_OK);
   807 
   808     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_retrieve,
   809             (int)strlen(sql_blacklist_retrieve), &_session->blacklist_retrieve,
   810             NULL);
   811     assert(int_result == SQLITE_OK);
   812     
   813     // Own keys
   814     
   815     int_result = sqlite3_prepare_v2(_session->db, sql_own_key_is_listed,
   816             (int)strlen(sql_own_key_is_listed), &_session->own_key_is_listed,
   817             NULL);
   818     assert(int_result == SQLITE_OK);
   819     
   820     int_result = sqlite3_prepare_v2(_session->db, sql_own_identities_retrieve,
   821             (int)strlen(sql_own_identities_retrieve),
   822             &_session->own_identities_retrieve, NULL);
   823     assert(int_result == SQLITE_OK);
   824  
   825     int_result = sqlite3_prepare_v2(_session->db, sql_own_keys_retrieve,
   826             (int)strlen(sql_own_keys_retrieve),
   827             &_session->own_keys_retrieve, NULL);
   828     assert(int_result == SQLITE_OK);
   829  
   830     // int_result = sqlite3_prepare_v2(_session->db, sql_set_own_key,
   831     //         (int)strlen(sql_set_own_key),
   832     //         &_session->set_own_key, NULL);
   833     // assert(int_result == SQLITE_OK);
   834  
   835     // Sequence
   836 
   837     int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value1,
   838             (int)strlen(sql_sequence_value1), &_session->sequence_value1,
   839             NULL);
   840     assert(int_result == SQLITE_OK);
   841 
   842     int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value2,
   843             (int)strlen(sql_sequence_value2), &_session->sequence_value2,
   844             NULL);
   845     assert(int_result == SQLITE_OK);
   846 
   847     int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value3,
   848             (int)strlen(sql_sequence_value3), &_session->sequence_value3,
   849             NULL);
   850     assert(int_result == SQLITE_OK);
   851 
   852     // Revocation tracking
   853     
   854     int_result = sqlite3_prepare_v2(_session->db, sql_set_revoked,
   855             (int)strlen(sql_set_revoked), &_session->set_revoked, NULL);
   856     assert(int_result == SQLITE_OK);
   857     
   858     int_result = sqlite3_prepare_v2(_session->db, sql_get_revoked,
   859             (int)strlen(sql_get_revoked), &_session->get_revoked, NULL);
   860     assert(int_result == SQLITE_OK);
   861     
   862     status = init_cryptotech(_session, in_first);
   863     if (status != PEP_STATUS_OK)
   864         goto pep_error;
   865 
   866     status = init_transport_system(_session, in_first);
   867     if (status != PEP_STATUS_OK)
   868         goto pep_error;
   869 
   870     status = log_event(_session, "init", "pEp " PEP_ENGINE_VERSION, NULL, NULL);
   871     if (status != PEP_STATUS_OK)
   872         goto pep_error;
   873 
   874     // runtime config
   875 
   876 #ifdef ANDROID
   877 #elif TARGET_OS_IPHONE
   878 #else /* Desktop */
   879     if (very_first)
   880     {
   881         // On first run, all private keys already present in PGP keyring 
   882         // are taken as own in order to seamlessly integrate with
   883         // pre-existing GPG setup.
   884 
   885         ////////////////////////////// WARNING: ///////////////////////////
   886         // Considering all PGP priv keys as own is dangerous in case of 
   887         // re-initialization of pEp DB, while keeping PGP keyring as-is!
   888         //
   889         // Indeed, if pEpEngine did import spoofed private keys in previous
   890         // install, then those keys become automatically trusted in case 
   891         // pEp_management.db is deleted.
   892         //
   893         // A solution to distinguish bare GPG keyring from pEp keyring is
   894         // needed here. Then keys managed by pEpEngine wouldn't be
   895         // confused with GPG keys managed by the user through GPA.
   896         ///////////////////////////////////////////////////////////////////
   897         
   898         stringlist_t *keylist = NULL;
   899 
   900         status = find_private_keys(_session, NULL, &keylist);
   901         assert(status != PEP_OUT_OF_MEMORY);
   902         if (status == PEP_OUT_OF_MEMORY)
   903             return PEP_OUT_OF_MEMORY;
   904         
   905         if (keylist != NULL && keylist->value != NULL)
   906         {
   907             stringlist_t *_keylist;
   908             for (_keylist = keylist; _keylist && _keylist->value; _keylist = _keylist->next) {
   909                 status = set_own_key(_session, 
   910                                      "" /* address is unused in own_keys */,
   911                                      _keylist->value);
   912             }
   913         }
   914     }
   915 #endif
   916 
   917     // sync_session set to own session by default
   918     // sync_session is then never null on a valid session
   919     _session->sync_session = _session;
   920 
   921     *session = _session;
   922     
   923     // Note: Following statement is NOT for any cryptographic/secure functionality; it is
   924     //       ONLY used for some randomness in generated outer message ID, which are
   925     //       required by the RFC to be globally unique!
   926     srand(time(NULL));
   927     
   928     return PEP_STATUS_OK;
   929 
   930 enomem:
   931     status = PEP_OUT_OF_MEMORY;
   932 
   933 pep_error:
   934     release(_session);
   935     return status;
   936 }
   937 
   938 DYNAMIC_API void release(PEP_SESSION session)
   939 {
   940     bool out_last = false;
   941     int _count = --init_count;
   942     
   943     assert(_count >= -1);
   944     assert(session);
   945 
   946     if (!((_count >= -1) && session))
   947         return;
   948 
   949     // a small race condition but still a race condition
   950     // mitigated by calling caveat (see documentation)
   951     // (release() is to be guarded by a mutex by the caller)
   952     if (_count == -1)
   953         out_last = true;
   954 
   955     if (session) {
   956 
   957         if (session->db) {
   958             if (session->log)
   959                 sqlite3_finalize(session->log);
   960             if (session->trustword)
   961                 sqlite3_finalize(session->trustword);
   962             if (session->get_identity)
   963                 sqlite3_finalize(session->get_identity);
   964             if (session->get_identity_without_fpr)
   965                 sqlite3_finalize(session->get_identity_without_fpr);    
   966             if (session->get_user_default_key)
   967                 sqlite3_finalize(session->get_user_default_key);    
   968             if (session->get_own_userid)
   969                 sqlite3_finalize(session->get_own_userid);
   970             if (session->replace_identities_fpr)
   971                 sqlite3_finalize(session->replace_identities_fpr);        
   972             if (session->set_person)
   973                 sqlite3_finalize(session->set_person);
   974             if (session->set_device_group)
   975                 sqlite3_finalize(session->set_device_group);
   976             if (session->get_device_group)
   977                 sqlite3_finalize(session->get_device_group);
   978             if (session->set_pgp_keypair)
   979                 sqlite3_finalize(session->set_pgp_keypair);
   980             if (session->set_identity)
   981                 sqlite3_finalize(session->set_identity);
   982             if (session->set_identity_flags)
   983                 sqlite3_finalize(session->set_identity_flags);
   984             if (session->unset_identity_flags)
   985                 sqlite3_finalize(session->unset_identity_flags);
   986             if (session->set_trust)
   987                 sqlite3_finalize(session->set_trust);
   988             if (session->update_trust_for_fpr)
   989                 sqlite3_finalize(session->update_trust_for_fpr);
   990             if (session->get_trust)
   991                 sqlite3_finalize(session->get_trust);
   992             if (session->least_trust)
   993                 sqlite3_finalize(session->least_trust);
   994             if (session->mark_compromized)
   995                 sqlite3_finalize(session->mark_compromized);
   996             if (session->crashdump)
   997                 sqlite3_finalize(session->crashdump);
   998             if (session->languagelist)
   999                 sqlite3_finalize(session->languagelist);
  1000             if (session->i18n_token)
  1001                 sqlite3_finalize(session->i18n_token);
  1002             if (session->blacklist_add)
  1003                 sqlite3_finalize(session->blacklist_add);
  1004             if (session->blacklist_delete)
  1005                 sqlite3_finalize(session->blacklist_delete);
  1006             if (session->blacklist_is_listed)
  1007                 sqlite3_finalize(session->blacklist_is_listed);
  1008             if (session->blacklist_retrieve)
  1009                 sqlite3_finalize(session->blacklist_retrieve);
  1010             if (session->own_key_is_listed)
  1011                 sqlite3_finalize(session->own_key_is_listed);
  1012             if (session->own_identities_retrieve)
  1013                 sqlite3_finalize(session->own_identities_retrieve);
  1014             if (session->own_keys_retrieve)
  1015                 sqlite3_finalize(session->own_keys_retrieve);
  1016             // if (session->set_own_key)
  1017             //     sqlite3_finalize(session->set_own_key);
  1018             if (session->sequence_value1)
  1019                 sqlite3_finalize(session->sequence_value1);
  1020             if (session->sequence_value2)
  1021                 sqlite3_finalize(session->sequence_value2);
  1022             if (session->sequence_value3)
  1023                 sqlite3_finalize(session->sequence_value3);
  1024             if (session->set_revoked)
  1025                 sqlite3_finalize(session->set_revoked);
  1026             if (session->get_revoked)
  1027                 sqlite3_finalize(session->get_revoked);
  1028 
  1029             if (session->db)
  1030                 sqlite3_close_v2(session->db);
  1031             if (session->system_db)
  1032                 sqlite3_close_v2(session->system_db);
  1033         }
  1034 
  1035         release_transport_system(session, out_last);
  1036         release_cryptotech(session, out_last);
  1037 
  1038 #ifdef DEBUG_ERRORSTACK
  1039         free_stringlist(session->errorstack);
  1040 #endif
  1041         free(session);
  1042     }
  1043 }
  1044 
  1045 DYNAMIC_API void config_passive_mode(PEP_SESSION session, bool enable)
  1046 {
  1047     assert(session);
  1048     session->passive_mode = enable;
  1049 }
  1050 
  1051 DYNAMIC_API void config_unencrypted_subject(PEP_SESSION session, bool enable)
  1052 {
  1053     assert(session);
  1054     session->unencrypted_subject = enable;
  1055 }
  1056 
  1057 DYNAMIC_API void config_keep_sync_msg(PEP_SESSION session, bool enable)
  1058 {
  1059     assert(session);
  1060     session->keep_sync_msg = enable;
  1061 }
  1062 
  1063 DYNAMIC_API void config_service_log(PEP_SESSION session, bool enable)
  1064 {
  1065     assert(session);
  1066     session->service_log = enable;
  1067 }
  1068 
  1069 DYNAMIC_API PEP_STATUS log_event(
  1070         PEP_SESSION session,
  1071         const char *title,
  1072         const char *entity,
  1073         const char *description,
  1074         const char *comment
  1075     )
  1076 {
  1077     PEP_STATUS status = PEP_STATUS_OK;
  1078     int result;
  1079 
  1080     assert(session);
  1081     assert(title);
  1082     assert(entity);
  1083 
  1084     if (!(session && title && entity))
  1085         return PEP_ILLEGAL_VALUE;
  1086 
  1087     sqlite3_reset(session->log);
  1088     sqlite3_bind_text(session->log, 1, title, -1, SQLITE_STATIC);
  1089     sqlite3_bind_text(session->log, 2, entity, -1, SQLITE_STATIC);
  1090     if (description)
  1091         sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
  1092     else
  1093         sqlite3_bind_null(session->log, 3);
  1094     if (comment)
  1095         sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
  1096     else
  1097         sqlite3_bind_null(session->log, 4);
  1098     do {
  1099         result = sqlite3_step(session->log);
  1100         assert(result == SQLITE_DONE || result == SQLITE_BUSY);
  1101         if (result != SQLITE_DONE && result != SQLITE_BUSY)
  1102             status = PEP_UNKNOWN_ERROR;
  1103     } while (result == SQLITE_BUSY);
  1104     sqlite3_reset(session->log);
  1105 
  1106     return ADD_TO_LOG(status);
  1107 }
  1108 
  1109 DYNAMIC_API PEP_STATUS log_service(
  1110         PEP_SESSION session,
  1111         const char *title,
  1112         const char *entity,
  1113         const char *description,
  1114         const char *comment
  1115     )
  1116 {
  1117     assert(session);
  1118     if (!session)
  1119         return PEP_ILLEGAL_VALUE;
  1120 
  1121     if (session->service_log)
  1122         return log_event(session, title, entity, description, comment);
  1123     else
  1124         return PEP_STATUS_OK;
  1125 }
  1126 
  1127 DYNAMIC_API PEP_STATUS trustword(
  1128             PEP_SESSION session, uint16_t value, const char *lang,
  1129             char **word, size_t *wsize
  1130         )
  1131 {
  1132     PEP_STATUS status = PEP_STATUS_OK;
  1133 
  1134     assert(session);
  1135     assert(word);
  1136     assert(wsize);
  1137 
  1138     if (!(session && word && wsize))
  1139         return PEP_ILLEGAL_VALUE;
  1140 
  1141     *word = NULL;
  1142     *wsize = 0;
  1143 
  1144     if (lang == NULL)
  1145         lang = "en";
  1146 
  1147     assert((lang[0] >= 'A' && lang[0] <= 'Z')
  1148             || (lang[0] >= 'a' && lang[0] <= 'z'));
  1149     assert((lang[1] >= 'A' && lang[1] <= 'Z')
  1150             || (lang[1] >= 'a' && lang[1] <= 'z'));
  1151     assert(lang[2] == 0);
  1152 
  1153     sqlite3_reset(session->trustword);
  1154     sqlite3_bind_text(session->trustword, 1, lang, -1, SQLITE_STATIC);
  1155     sqlite3_bind_int(session->trustword, 2, value);
  1156 
  1157     const int result = sqlite3_step(session->trustword);
  1158     if (result == SQLITE_ROW) {
  1159         *word = strdup((const char *) sqlite3_column_text(session->trustword,
  1160                     1));
  1161         if (*word)
  1162             *wsize = sqlite3_column_bytes(session->trustword, 1);
  1163         else
  1164             status = PEP_OUT_OF_MEMORY;
  1165     } else
  1166         status = PEP_TRUSTWORD_NOT_FOUND;
  1167 
  1168     sqlite3_reset(session->trustword);
  1169     return status;
  1170 }
  1171 
  1172 DYNAMIC_API PEP_STATUS trustwords(
  1173         PEP_SESSION session, const char *fingerprint, const char *lang,
  1174         char **words, size_t *wsize, int max_words
  1175     )
  1176 {
  1177     const char *source = fingerprint;
  1178 
  1179     assert(session);
  1180     assert(fingerprint);
  1181     assert(words);
  1182     assert(wsize);
  1183     assert(max_words >= 0);
  1184 
  1185     if (!(session && fingerprint && words && wsize && max_words >= 0))
  1186         return PEP_ILLEGAL_VALUE;
  1187 
  1188     *words = NULL;
  1189     *wsize = 0;
  1190 
  1191     char *buffer = calloc(1, MAX_TRUSTWORDS_SPACE);
  1192     assert(buffer);
  1193     if (buffer == NULL)
  1194         return PEP_OUT_OF_MEMORY;
  1195     char *dest = buffer;
  1196 
  1197     const size_t fsize = strlen(fingerprint);
  1198 
  1199     if (!lang || !lang[0])
  1200         lang = "en";
  1201 
  1202     assert((lang[0] >= 'A' && lang[0] <= 'Z')
  1203             || (lang[0] >= 'a' && lang[0] <= 'z'));
  1204     assert((lang[1] >= 'A' && lang[1] <= 'Z')
  1205             || (lang[1] >= 'a' && lang[1] <= 'z'));
  1206     assert(lang[2] == 0);
  1207 
  1208     int n_words = 0;
  1209     while (source < fingerprint + fsize) {
  1210         PEP_STATUS _status;
  1211         uint16_t value;
  1212         char *word = NULL;
  1213         size_t _wsize = 0;
  1214         int j;
  1215 
  1216         for (value=0, j=0; j < 4 && source < fingerprint + fsize; ) {
  1217             if (*source >= 'a' && *source <= 'f')
  1218                 value += (*source - 'a' + 10) << (3 - j++) * 4;
  1219             else if (*source >= 'A' && *source <= 'F')
  1220                 value += (*source - 'A' + 10) << (3 - j++) * 4;
  1221             else if (*source >= '0' && *source <= '9')
  1222                 value += (*source - '0') << (3 - j++) * 4;
  1223             
  1224             source++;
  1225         }
  1226 
  1227         _status = trustword(session, value, lang, &word, &_wsize);
  1228         if (_status == PEP_OUT_OF_MEMORY) {
  1229             free(buffer);
  1230             return PEP_OUT_OF_MEMORY;
  1231         }
  1232         if (word == NULL) {
  1233             free(buffer);
  1234             return PEP_TRUSTWORD_NOT_FOUND;
  1235         }
  1236 
  1237         if (dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1) {
  1238             strncpy(dest, word, _wsize);
  1239             free(word);
  1240             dest += _wsize;
  1241         }
  1242         else {
  1243             free(word);
  1244             break; // buffer full
  1245         }
  1246 
  1247         if (source < fingerprint + fsize
  1248                 && dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1)
  1249             *dest++ = ' ';
  1250 
  1251         ++n_words;
  1252         if (max_words && n_words >= max_words)
  1253             break;
  1254     }
  1255 
  1256     *words = buffer;
  1257     *wsize = dest - buffer;
  1258     return PEP_STATUS_OK;
  1259 }
  1260 
  1261 pEp_identity *new_identity(
  1262         const char *address, const char *fpr, const char *user_id,
  1263         const char *username
  1264     )
  1265 {
  1266     pEp_identity *result = calloc(1, sizeof(pEp_identity));
  1267     assert(result);
  1268     if (result) {
  1269         if (address) {
  1270             result->address = strdup(address);
  1271             assert(result->address);
  1272             if (result->address == NULL) {
  1273                 free(result);
  1274                 return NULL;
  1275             }
  1276         }
  1277         if (fpr) {
  1278             result->fpr = strdup(fpr);
  1279             assert(result->fpr);
  1280             if (result->fpr == NULL) {
  1281                 free_identity(result);
  1282                 return NULL;
  1283             }
  1284         }
  1285         if (user_id) {
  1286             result->user_id = strdup(user_id);
  1287             assert(result->user_id);
  1288             if (result->user_id == NULL) {
  1289                 free_identity(result);
  1290                 return NULL;
  1291             }
  1292         }
  1293         if (username) {
  1294             result->username = strdup(username);
  1295             assert(result->username);
  1296             if (result->username == NULL) {
  1297                 free_identity(result);
  1298                 return NULL;
  1299             }
  1300         }
  1301     }
  1302     return result;
  1303 }
  1304 
  1305 pEp_identity *identity_dup(const pEp_identity *src)
  1306 {
  1307     assert(src);
  1308 
  1309     pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id,
  1310             src->username);
  1311     assert(dup);
  1312     if (dup == NULL)
  1313         return NULL;
  1314     
  1315     dup->comm_type = src->comm_type;
  1316     dup->lang[0] = src->lang[0];
  1317     dup->lang[1] = src->lang[1];
  1318     dup->lang[2] = 0;
  1319     dup->flags = src->flags;
  1320     dup->me = src->me;
  1321     
  1322     return dup;
  1323 }
  1324 
  1325 void free_identity(pEp_identity *identity)
  1326 {
  1327     if (identity) {
  1328         free(identity->address);
  1329         free(identity->fpr);
  1330         free(identity->user_id);
  1331         free(identity->username);
  1332         free(identity);
  1333     }
  1334 }
  1335 
  1336 DYNAMIC_API PEP_STATUS get_own_userid(
  1337         PEP_SESSION session, 
  1338         char** userid
  1339     )
  1340 {
  1341     assert(session);
  1342     assert(userid);
  1343     
  1344     if (!session || !userid)
  1345         return PEP_ILLEGAL_VALUE;
  1346         
  1347     PEP_STATUS status = PEP_STATUS_OK;
  1348     char* retval = NULL;
  1349     
  1350     sqlite3_reset(session->get_own_userid);
  1351 
  1352     const int result = sqlite3_step(session->get_own_userid);
  1353     const char* id;
  1354     
  1355     switch (result) {
  1356         case SQLITE_ROW:
  1357             id = (const char *) sqlite3_column_text(session->get_own_userid, 0);
  1358             if (!id) {
  1359                 // Shouldn't happen.
  1360                 status = PEP_UNKNOWN_ERROR;
  1361             }
  1362             else {
  1363                 retval = strdup(id);
  1364                 if (!retval)
  1365                     status = PEP_OUT_OF_MEMORY;
  1366             }
  1367             break;
  1368         default:
  1369             // Technically true, given how we find it, but FIXME we need a more descriptive error
  1370             status = PEP_CANNOT_FIND_IDENTITY;
  1371             *userid = NULL;
  1372     }
  1373 
  1374     *userid = retval;
  1375 
  1376     sqlite3_reset(session->get_own_userid);
  1377     
  1378     return status;
  1379 }
  1380 
  1381 
  1382 static PEP_STATUS _get_identity_internal(
  1383         PEP_SESSION session,
  1384         const char *address,
  1385         const char *user_id,
  1386         pEp_identity **identity,
  1387         sqlite3_stmt* get_id_stmt
  1388     )
  1389 {
  1390     PEP_STATUS status = PEP_STATUS_OK;
  1391     static pEp_identity *_identity;
  1392 
  1393     assert(session);
  1394     assert(address);
  1395     assert(address[0]);
  1396     assert(identity);
  1397 
  1398     if (!(session && address && address[0] && identity))
  1399         return PEP_ILLEGAL_VALUE;
  1400 
  1401     *identity = NULL;
  1402 
  1403     sqlite3_reset(get_id_stmt);
  1404     sqlite3_bind_text(get_id_stmt, 1, address, -1, SQLITE_STATIC);
  1405     sqlite3_bind_text(get_id_stmt, 2, user_id, -1, SQLITE_STATIC);
  1406 
  1407     const int result = sqlite3_step(get_id_stmt);
  1408     switch (result) {
  1409     case SQLITE_ROW:
  1410         _identity = new_identity(
  1411                 address,
  1412                 (const char *) sqlite3_column_text(get_id_stmt, 0),
  1413                 user_id,
  1414                 (const char *) sqlite3_column_text(get_id_stmt, 1)
  1415                 );
  1416         assert(_identity);
  1417         if (_identity == NULL)
  1418             return PEP_OUT_OF_MEMORY;
  1419 
  1420         _identity->comm_type = (PEP_comm_type)
  1421             sqlite3_column_int(get_id_stmt, 2);
  1422         const char* const _lang = (const char *)
  1423             sqlite3_column_text(get_id_stmt, 3);
  1424         if (_lang && _lang[0]) {
  1425             assert(_lang[0] >= 'a' && _lang[0] <= 'z');
  1426             assert(_lang[1] >= 'a' && _lang[1] <= 'z');
  1427             assert(_lang[2] == 0);
  1428             _identity->lang[0] = _lang[0];
  1429             _identity->lang[1] = _lang[1];
  1430             _identity->lang[2] = 0;
  1431         }
  1432         _identity->flags = (unsigned int)
  1433             sqlite3_column_int(get_id_stmt, 4);
  1434         _identity->me = (unsigned int)
  1435             sqlite3_column_int(get_id_stmt, 5);
  1436     
  1437         *identity = _identity;
  1438         break;
  1439     default:
  1440         status = PEP_CANNOT_FIND_IDENTITY;
  1441         *identity = NULL;
  1442     }
  1443 
  1444     sqlite3_reset(get_id_stmt);
  1445     return status;
  1446 }
  1447 
  1448 DYNAMIC_API PEP_STATUS get_identity(
  1449         PEP_SESSION session,
  1450         const char *address,
  1451         const char *user_id,
  1452         pEp_identity **identity
  1453     )
  1454 {
  1455     return _get_identity_internal(session, address, user_id, identity,
  1456                                   session->get_identity);
  1457 }
  1458 
  1459 PEP_STATUS get_identity_without_fpr(
  1460         PEP_SESSION session,
  1461         const char *address,
  1462         const char *user_id,
  1463         pEp_identity **identity
  1464     )
  1465 {
  1466     return _get_identity_internal(session, address, user_id, identity,
  1467                                   session->get_identity_without_fpr);
  1468 }
  1469 
  1470 
  1471 DYNAMIC_API PEP_STATUS set_identity(
  1472         PEP_SESSION session, const pEp_identity *identity
  1473     )
  1474 {
  1475     int result;
  1476 
  1477     assert(session);
  1478     assert(identity);
  1479     assert(identity->address);
  1480     assert(identity->user_id);
  1481     assert(identity->username);
  1482 
  1483     if (!(session && identity && identity->address &&
  1484                 identity->user_id && identity->username))
  1485         return PEP_ILLEGAL_VALUE;
  1486 
  1487     PEP_STATUS status = PEP_STATUS_OK;
  1488     
  1489     bool listed;
  1490 
  1491     bool has_fpr = (identity->fpr && identity->fpr[0] != '\0');
  1492     
  1493     if (has_fpr) {    
  1494         // blacklist check
  1495         status = blacklist_is_listed(session, identity->fpr, &listed);
  1496         assert(status == PEP_STATUS_OK);
  1497         if (status != PEP_STATUS_OK)
  1498             return status;
  1499 
  1500         if (listed)
  1501             return PEP_KEY_BLACKLISTED;
  1502     }
  1503 
  1504     sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
  1505 
  1506     if (identity->lang[0]) {
  1507         assert(identity->lang[0] >= 'a' && identity->lang[0] <= 'z');
  1508         assert(identity->lang[1] >= 'a' && identity->lang[1] <= 'z');
  1509         assert(identity->lang[2] == 0);
  1510     }
  1511 
  1512     sqlite3_reset(session->set_person);
  1513     sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
  1514             SQLITE_STATIC);
  1515     sqlite3_bind_text(session->set_person, 2, identity->username, -1,
  1516             SQLITE_STATIC);
  1517     if (identity->lang[0])
  1518         sqlite3_bind_text(session->set_person, 3, identity->lang, 2,
  1519                 SQLITE_STATIC);
  1520     else
  1521         sqlite3_bind_null(session->set_person, 3);
  1522     sqlite3_bind_text(session->set_person, 4, identity->fpr, -1,
  1523                       SQLITE_STATIC);
  1524     result = sqlite3_step(session->set_person);
  1525     sqlite3_reset(session->set_person);
  1526     if (result != SQLITE_DONE) {
  1527         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1528         return PEP_CANNOT_SET_PERSON;
  1529     }
  1530 
  1531     if (has_fpr) {
  1532         sqlite3_reset(session->set_pgp_keypair);
  1533         sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
  1534                 SQLITE_STATIC);
  1535         result = sqlite3_step(session->set_pgp_keypair);
  1536         sqlite3_reset(session->set_pgp_keypair);
  1537         if (result != SQLITE_DONE) {
  1538             sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1539             return PEP_CANNOT_SET_PGP_KEYPAIR;
  1540         }
  1541     }
  1542 
  1543     sqlite3_reset(session->set_identity);
  1544     sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
  1545             SQLITE_STATIC);
  1546     sqlite3_bind_text(session->set_identity, 2, identity->fpr, -1,
  1547             SQLITE_STATIC);
  1548     sqlite3_bind_text(session->set_identity, 3, identity->user_id, -1,
  1549             SQLITE_STATIC);
  1550     sqlite3_bind_int(session->set_identity, 4, identity->flags);
  1551     sqlite3_bind_int(session->set_identity, 5, identity->me);
  1552     result = sqlite3_step(session->set_identity);
  1553     sqlite3_reset(session->set_identity);
  1554     if (result != SQLITE_DONE) {
  1555         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1556         return PEP_CANNOT_SET_IDENTITY;
  1557     }
  1558 
  1559     if (has_fpr) {
  1560         sqlite3_reset(session->set_trust);
  1561         sqlite3_bind_text(session->set_trust, 1, identity->user_id, -1,
  1562                 SQLITE_STATIC);
  1563         sqlite3_bind_text(session->set_trust, 2, identity->fpr, -1,
  1564                 SQLITE_STATIC);
  1565         sqlite3_bind_int(session->set_trust, 3, identity->comm_type);
  1566         result = sqlite3_step(session->set_trust);
  1567         sqlite3_reset(session->set_trust);
  1568         if (result != SQLITE_DONE) {
  1569             sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1570             return PEP_CANNOT_SET_TRUST;
  1571         }
  1572     }
  1573     
  1574     result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
  1575     if (result == SQLITE_OK)
  1576         return PEP_STATUS_OK;
  1577     else
  1578         return PEP_COMMIT_FAILED;
  1579 }
  1580 
  1581 PEP_STATUS replace_identities_fpr(PEP_SESSION session, 
  1582                                  const char* old_fpr, 
  1583                                  const char* new_fpr) 
  1584 {
  1585     assert(old_fpr);
  1586     assert(new_fpr);
  1587     
  1588     if (!old_fpr || !new_fpr)
  1589         return PEP_ILLEGAL_VALUE;
  1590             
  1591     sqlite3_reset(session->replace_identities_fpr);
  1592     sqlite3_bind_text(session->replace_identities_fpr, 1, new_fpr, -1,
  1593                       SQLITE_STATIC);
  1594     sqlite3_bind_text(session->replace_identities_fpr, 2, old_fpr, -1,
  1595                       SQLITE_STATIC);
  1596 
  1597     int result = sqlite3_step(session->replace_identities_fpr);
  1598     sqlite3_reset(session->replace_identities_fpr);
  1599     
  1600     if (result != SQLITE_DONE)
  1601         return PEP_CANNOT_SET_IDENTITY;
  1602 
  1603     return PEP_STATUS_OK;
  1604 }
  1605 
  1606 
  1607 PEP_STATUS update_trust_for_fpr(PEP_SESSION session, 
  1608                                 const char* fpr, 
  1609                                 PEP_comm_type comm_type)
  1610 {
  1611     if (!fpr)
  1612         return PEP_ILLEGAL_VALUE;
  1613         
  1614     sqlite3_reset(session->update_trust_for_fpr);
  1615     sqlite3_bind_int(session->update_trust_for_fpr, 1, comm_type);
  1616     sqlite3_bind_text(session->update_trust_for_fpr, 2, fpr, -1,
  1617             SQLITE_STATIC);
  1618     int result = sqlite3_step(session->update_trust_for_fpr);
  1619     sqlite3_reset(session->update_trust_for_fpr);
  1620     if (result != SQLITE_DONE) {
  1621         return PEP_CANNOT_SET_TRUST;
  1622     }
  1623     
  1624     return PEP_STATUS_OK;
  1625 }
  1626 
  1627 DYNAMIC_API PEP_STATUS set_device_group(
  1628         PEP_SESSION session,
  1629         const char *group_name
  1630     )
  1631 {
  1632     int result;
  1633 
  1634     assert(session);
  1635 
  1636     if (!(session && group_name))
  1637         return PEP_ILLEGAL_VALUE;
  1638 
  1639     // 1. Get own user_id
  1640     char* user_id = NULL;
  1641     PEP_STATUS status = get_own_userid(session, &user_id);
  1642     
  1643     // No user_id is returned in this case, no need to free;
  1644     if (status != PEP_STATUS_OK)
  1645         return status;
  1646         
  1647     // 2. Set device group
  1648     sqlite3_reset(session->set_device_group);
  1649     if(group_name){
  1650         sqlite3_bind_text(session->set_device_group, 1, group_name, -1,
  1651                 SQLITE_STATIC);
  1652     } else {
  1653         sqlite3_bind_null(session->set_device_group, 1);
  1654     }
  1655     
  1656     sqlite3_bind_text(session->set_device_group, 2, user_id, -1,
  1657             SQLITE_STATIC);
  1658 
  1659     result = sqlite3_step(session->set_device_group);
  1660     sqlite3_reset(session->set_device_group);
  1661     
  1662     free(user_id);
  1663     
  1664     if (result != SQLITE_DONE)
  1665         return PEP_CANNOT_SET_PERSON;
  1666 
  1667     return PEP_STATUS_OK;
  1668 }
  1669 
  1670 DYNAMIC_API PEP_STATUS get_device_group(PEP_SESSION session, char **group_name)
  1671 {
  1672     PEP_STATUS status = PEP_STATUS_OK;
  1673     int result;
  1674 
  1675     assert(session);
  1676     assert(group_name);
  1677 
  1678     if (!(session && group_name))
  1679         return PEP_ILLEGAL_VALUE;
  1680 
  1681     // 1. Get own user_id
  1682     char* user_id = NULL;
  1683     status = get_own_userid(session, &user_id);
  1684     
  1685     // No user_id is returned in this case, no need to free;
  1686     if (status != PEP_STATUS_OK)
  1687         return status;
  1688 
  1689     // 2. get device group
  1690     sqlite3_reset(session->get_device_group);
  1691     sqlite3_bind_text(session->get_device_group, 1, user_id, -1,
  1692             SQLITE_STATIC);
  1693 
  1694     result = sqlite3_step(session->get_device_group);
  1695     switch (result) {
  1696     case SQLITE_ROW: {
  1697         const char *_group_name = (const char *)sqlite3_column_text(session->get_device_group, 0);
  1698         if(_group_name){
  1699             *group_name = strdup(_group_name);
  1700                 if(*group_name == NULL)
  1701                     status = PEP_OUT_OF_MEMORY;
  1702         }
  1703         break;
  1704     }
  1705  
  1706     default:
  1707         status = PEP_RECORD_NOT_FOUND;
  1708     }
  1709 
  1710     free(user_id);
  1711     sqlite3_reset(session->get_device_group);
  1712     return status;
  1713 }
  1714 
  1715 DYNAMIC_API PEP_STATUS set_identity_flags(
  1716         PEP_SESSION session,
  1717         pEp_identity *identity,
  1718         unsigned int flags
  1719     )
  1720 {
  1721     int result;
  1722 
  1723     assert(session);
  1724     assert(identity);
  1725     assert(identity->address);
  1726     assert(identity->user_id);
  1727 
  1728     if (!(session && identity && identity->address && identity->user_id))
  1729         return PEP_ILLEGAL_VALUE;
  1730 
  1731     sqlite3_reset(session->set_identity_flags);
  1732     sqlite3_bind_int(session->set_identity_flags, 1, flags);
  1733     sqlite3_bind_text(session->set_identity_flags, 2, identity->address, -1,
  1734             SQLITE_STATIC);
  1735     sqlite3_bind_text(session->set_identity_flags, 3, identity->user_id, -1,
  1736             SQLITE_STATIC);
  1737     result = sqlite3_step(session->set_identity_flags);
  1738     sqlite3_reset(session->set_identity_flags);
  1739     if (result != SQLITE_DONE)
  1740         return PEP_CANNOT_SET_IDENTITY;
  1741 
  1742     identity->flags |= flags;
  1743     return PEP_STATUS_OK;
  1744 }
  1745 
  1746 DYNAMIC_API PEP_STATUS unset_identity_flags(
  1747         PEP_SESSION session,
  1748         pEp_identity *identity,
  1749         unsigned int flags
  1750     )
  1751 {
  1752     int result;
  1753 
  1754     assert(session);
  1755     assert(identity);
  1756     assert(identity->address);
  1757     assert(identity->user_id);
  1758 
  1759     if (!(session && identity && identity->address && identity->user_id))
  1760         return PEP_ILLEGAL_VALUE;
  1761 
  1762     sqlite3_reset(session->unset_identity_flags);
  1763     sqlite3_bind_int(session->unset_identity_flags, 1, flags);
  1764     sqlite3_bind_text(session->unset_identity_flags, 2, identity->address, -1,
  1765             SQLITE_STATIC);
  1766     sqlite3_bind_text(session->unset_identity_flags, 3, identity->user_id, -1,
  1767             SQLITE_STATIC);
  1768     result = sqlite3_step(session->unset_identity_flags);
  1769     sqlite3_reset(session->unset_identity_flags);
  1770     if (result != SQLITE_DONE)
  1771         return PEP_CANNOT_SET_IDENTITY;
  1772 
  1773     identity->flags &= ~flags;
  1774     return PEP_STATUS_OK;
  1775 }
  1776 
  1777 DYNAMIC_API PEP_STATUS mark_as_compromized(
  1778         PEP_SESSION session,
  1779         const char *fpr
  1780     )
  1781 {
  1782     int result;
  1783 
  1784     assert(session);
  1785     assert(fpr && fpr[0]);
  1786 
  1787     if (!(session && fpr && fpr[0]))
  1788         return PEP_ILLEGAL_VALUE;
  1789 
  1790     sqlite3_reset(session->mark_compromized);
  1791     sqlite3_bind_text(session->mark_compromized, 1, fpr, -1,
  1792             SQLITE_STATIC);
  1793     result = sqlite3_step(session->mark_compromized);
  1794     sqlite3_reset(session->mark_compromized);
  1795 
  1796     if (result != SQLITE_DONE)
  1797         return PEP_CANNOT_SET_TRUST;
  1798 
  1799     return PEP_STATUS_OK;
  1800 }
  1801 
  1802 void pEp_free(void *p)
  1803 {
  1804     free(p);
  1805 }
  1806 
  1807 DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
  1808 {
  1809     PEP_STATUS status = PEP_STATUS_OK;
  1810     int result;
  1811 
  1812     assert(session);
  1813     assert(identity);
  1814     assert(identity->user_id);
  1815     assert(identity->user_id[0]);
  1816     assert(identity->fpr);
  1817     assert(identity->fpr[0]);
  1818 
  1819     if (!(session && identity && identity->user_id && identity->user_id[0] &&
  1820                 identity->fpr && identity->fpr[0]))
  1821         return PEP_ILLEGAL_VALUE;
  1822 
  1823     identity->comm_type = PEP_ct_unknown;
  1824 
  1825     sqlite3_reset(session->get_trust);
  1826     sqlite3_bind_text(session->get_trust, 1, identity->user_id, -1,
  1827             SQLITE_STATIC);
  1828     sqlite3_bind_text(session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
  1829 
  1830     result = sqlite3_step(session->get_trust);
  1831     switch (result) {
  1832     case SQLITE_ROW: {
  1833         int comm_type = (PEP_comm_type) sqlite3_column_int(session->get_trust,
  1834                 0);
  1835         identity->comm_type = comm_type;
  1836         break;
  1837     }
  1838  
  1839     default:
  1840         status = PEP_CANNOT_FIND_IDENTITY;
  1841     }
  1842 
  1843     sqlite3_reset(session->get_trust);
  1844     return status;
  1845 }
  1846 
  1847 DYNAMIC_API PEP_STATUS least_trust(
  1848         PEP_SESSION session,
  1849         const char *fpr,
  1850         PEP_comm_type *comm_type
  1851     )
  1852 {
  1853     PEP_STATUS status = PEP_STATUS_OK;
  1854     int result;
  1855 
  1856     assert(session);
  1857     assert(fpr);
  1858     assert(comm_type);
  1859 
  1860     if (!(session && fpr && comm_type))
  1861         return PEP_ILLEGAL_VALUE;
  1862 
  1863     *comm_type = PEP_ct_unknown;
  1864 
  1865     sqlite3_reset(session->least_trust);
  1866     sqlite3_bind_text(session->least_trust, 1, fpr, -1, SQLITE_STATIC);
  1867 
  1868     result = sqlite3_step(session->least_trust);
  1869     switch (result) {
  1870         case SQLITE_ROW: {
  1871             int _comm_type = sqlite3_column_int(session->least_trust, 0);
  1872             *comm_type = (PEP_comm_type) _comm_type;
  1873             break;
  1874         }
  1875         default:
  1876             // never reached because of sql min()
  1877             status = PEP_CANNOT_FIND_IDENTITY;
  1878     }
  1879 
  1880     sqlite3_reset(session->least_trust);
  1881     return status;
  1882 }
  1883 
  1884 DYNAMIC_API PEP_STATUS decrypt_and_verify(
  1885     PEP_SESSION session, const char *ctext, size_t csize,
  1886     const char *dsigtext, size_t dsigsize,
  1887     char **ptext, size_t *psize, stringlist_t **keylist
  1888     )
  1889 {
  1890     assert(session);
  1891     assert(ctext);
  1892     assert(csize);
  1893     assert(ptext);
  1894     assert(psize);
  1895     assert(keylist);
  1896 
  1897     if (!(session && ctext && csize && ptext && psize && keylist))
  1898         return PEP_ILLEGAL_VALUE;
  1899 
  1900     return session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(
  1901             session, ctext, csize, dsigtext, dsigsize, ptext, psize, keylist);
  1902 }
  1903 
  1904 DYNAMIC_API PEP_STATUS encrypt_and_sign(
  1905     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
  1906     size_t psize, char **ctext, size_t *csize
  1907     )
  1908 {
  1909     assert(session);
  1910     assert(keylist);
  1911     assert(ptext);
  1912     assert(psize);
  1913     assert(ctext);
  1914     assert(csize);
  1915 
  1916     if (!(session && keylist && ptext && psize && ctext && csize))
  1917         return PEP_ILLEGAL_VALUE;
  1918 
  1919     return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session,
  1920             keylist, ptext, psize, ctext, csize);
  1921 }
  1922 
  1923 PEP_STATUS encrypt_only(
  1924     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
  1925     size_t psize, char **ctext, size_t *csize
  1926     )
  1927 {
  1928     assert(session);
  1929     assert(keylist);
  1930     assert(ptext);
  1931     assert(psize);
  1932     assert(ctext);
  1933     assert(csize);
  1934 
  1935     if (!(session && keylist && ptext && psize && ctext && csize))
  1936         return PEP_ILLEGAL_VALUE;
  1937 
  1938     return session->cryptotech[PEP_crypt_OpenPGP].encrypt_only(session,
  1939             keylist, ptext, psize, ctext, csize);
  1940 }
  1941 
  1942 
  1943 DYNAMIC_API PEP_STATUS verify_text(
  1944     PEP_SESSION session, const char *text, size_t size,
  1945     const char *signature, size_t sig_size, stringlist_t **keylist
  1946     )
  1947 {
  1948     assert(session);
  1949     assert(text);
  1950     assert(size);
  1951     assert(signature);
  1952     assert(sig_size);
  1953     assert(keylist);
  1954 
  1955     if (!(session && text && size && signature && sig_size && keylist))
  1956         return PEP_ILLEGAL_VALUE;
  1957 
  1958     return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text,
  1959             size, signature, sig_size, keylist);
  1960 }
  1961 
  1962 DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
  1963 {
  1964     assert(session);
  1965     assert(fpr);
  1966 
  1967     if (!(session && fpr))
  1968         return PEP_ILLEGAL_VALUE;
  1969 
  1970     return session->cryptotech[PEP_crypt_OpenPGP].delete_keypair(session, fpr);
  1971 }
  1972 
  1973 DYNAMIC_API PEP_STATUS export_key(
  1974         PEP_SESSION session, const char *fpr, char **key_data, size_t *size
  1975     )
  1976 {
  1977     assert(session);
  1978     assert(fpr);
  1979     assert(key_data);
  1980     assert(size);
  1981 
  1982     if (!(session && fpr && key_data && size))
  1983         return PEP_ILLEGAL_VALUE;
  1984 
  1985     return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr,
  1986             key_data, size, false);
  1987 }
  1988 
  1989 DYNAMIC_API PEP_STATUS export_secrect_key(
  1990         PEP_SESSION session, const char *fpr, char **key_data, size_t *size
  1991     )
  1992 {
  1993     assert(session);
  1994     assert(fpr);
  1995     assert(key_data);
  1996     assert(size);
  1997 
  1998     if (!(session && fpr && key_data && size))
  1999         return PEP_ILLEGAL_VALUE;
  2000 
  2001     // don't accept key IDs but full fingerprints only
  2002     if (strlen(fpr) < 16)
  2003         return PEP_ILLEGAL_VALUE;
  2004 
  2005     return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr,
  2006             key_data, size, true);
  2007 }
  2008 
  2009 DYNAMIC_API PEP_STATUS find_keys(
  2010         PEP_SESSION session, const char *pattern, stringlist_t **keylist
  2011     )
  2012 {
  2013     assert(session);
  2014     assert(pattern);
  2015     assert(keylist);
  2016 
  2017     if (!(session && pattern && keylist))
  2018         return PEP_ILLEGAL_VALUE;
  2019 
  2020     return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern,
  2021             keylist);
  2022 }
  2023 
  2024 
  2025 DYNAMIC_API PEP_STATUS generate_keypair(
  2026         PEP_SESSION session, pEp_identity *identity
  2027     )
  2028 {
  2029     assert(session);
  2030     assert(identity);
  2031     assert(identity->address);
  2032     assert(identity->fpr == NULL || identity->fpr[0] == 0);
  2033     assert(identity->username);
  2034 
  2035     if (!(session && identity && identity->address &&
  2036             (identity->fpr == NULL || identity->fpr[0] == 0) &&
  2037             identity->username))
  2038         return PEP_ILLEGAL_VALUE;
  2039 
  2040     PEP_STATUS status =
  2041         session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session,
  2042                 identity);
  2043     if (status != PEP_STATUS_OK)
  2044         return status;
  2045 
  2046     return status;
  2047 }
  2048 
  2049 DYNAMIC_API PEP_STATUS get_key_rating(
  2050         PEP_SESSION session,
  2051         const char *fpr,
  2052         PEP_comm_type *comm_type
  2053     )
  2054 {
  2055     assert(session);
  2056     assert(fpr);
  2057     assert(comm_type);
  2058 
  2059     if (!(session && fpr && comm_type))
  2060         return PEP_ILLEGAL_VALUE;
  2061 
  2062     return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr,
  2063             comm_type);
  2064 }
  2065 
  2066 DYNAMIC_API PEP_STATUS import_key(
  2067         PEP_SESSION session,
  2068         const char *key_data,
  2069         size_t size,
  2070         identity_list **private_keys
  2071     )
  2072 {
  2073     assert(session);
  2074     assert(key_data);
  2075 
  2076     if (!(session && key_data))
  2077         return PEP_ILLEGAL_VALUE;
  2078 
  2079     return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data,
  2080             size, private_keys);
  2081 }
  2082 
  2083 DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
  2084 {
  2085     assert(session);
  2086     assert(pattern);
  2087 
  2088     if (!(session && pattern))
  2089         return PEP_ILLEGAL_VALUE;
  2090 
  2091     return session->cryptotech[PEP_crypt_OpenPGP].recv_key(session, pattern);
  2092 }
  2093 
  2094 DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
  2095 {
  2096     assert(session);
  2097     assert(pattern);
  2098 
  2099     if (!(session && pattern))
  2100         return PEP_ILLEGAL_VALUE;
  2101 
  2102     return session->cryptotech[PEP_crypt_OpenPGP].send_key(session, pattern);
  2103 }
  2104 
  2105 DYNAMIC_API PEP_STATUS renew_key(
  2106         PEP_SESSION session,
  2107         const char *fpr,
  2108         const timestamp *ts
  2109     )
  2110 {
  2111     assert(session);
  2112     assert(fpr);
  2113 
  2114     if (!(session && fpr))
  2115         return PEP_ILLEGAL_VALUE;
  2116 
  2117     return session->cryptotech[PEP_crypt_OpenPGP].renew_key(session, fpr, ts);
  2118 }
  2119 
  2120 DYNAMIC_API PEP_STATUS revoke_key(
  2121         PEP_SESSION session,
  2122         const char *fpr,
  2123         const char *reason
  2124     )
  2125 {
  2126     assert(session);
  2127     assert(fpr);
  2128 
  2129     if (!(session && fpr))
  2130         return PEP_ILLEGAL_VALUE;
  2131 
  2132     return session->cryptotech[PEP_crypt_OpenPGP].revoke_key(session, fpr,
  2133             reason);
  2134 }
  2135 
  2136 DYNAMIC_API PEP_STATUS key_expired(
  2137         PEP_SESSION session,
  2138         const char *fpr,
  2139         const time_t when,
  2140         bool *expired
  2141     )
  2142 {
  2143     assert(session);
  2144     assert(fpr);
  2145     assert(expired);
  2146 
  2147     if (!(session && fpr && expired))
  2148         return PEP_ILLEGAL_VALUE;
  2149 
  2150     return session->cryptotech[PEP_crypt_OpenPGP].key_expired(session, fpr,
  2151             when, expired);
  2152 }
  2153 
  2154 DYNAMIC_API PEP_STATUS key_revoked(
  2155        PEP_SESSION session,
  2156        const char *fpr,
  2157        bool *revoked
  2158    )
  2159 {
  2160     assert(session);
  2161     assert(fpr);
  2162     assert(revoked);
  2163     
  2164     if (!(session && fpr && revoked))
  2165         return PEP_ILLEGAL_VALUE;
  2166     
  2167     return session->cryptotech[PEP_crypt_OpenPGP].key_revoked(session, fpr,
  2168             revoked);
  2169 }
  2170 
  2171 static void _clean_log_value(char *text)
  2172 {
  2173     if (text) {
  2174         for (char *c = text; *c; c++) {
  2175             if (*c < 32 && *c != '\n')
  2176                 *c = 32;
  2177             else if (*c == '"')
  2178                 *c = '\'';
  2179         }
  2180     }
  2181 }
  2182 
  2183 static char *_concat_string(char *str1, const char *str2, char delim)
  2184 {
  2185     str2 = str2 ? str2 : "";
  2186     size_t len1 = str1 ? strlen(str1) : 0;
  2187     size_t len2 = strlen(str2);
  2188     size_t len = len1 + len2 + 3;
  2189     char * result = realloc(str1, len + 1);
  2190 
  2191     if (result) {
  2192         result[len1] = '"';
  2193         strcpy(result + len1 + 1, str2);
  2194         result[len - 2] = '"';
  2195         result[len - 1] = delim;
  2196         result[len] = 0;
  2197     }
  2198     else {
  2199         free(str1);
  2200     }
  2201 
  2202     return result;
  2203 }
  2204 
  2205 DYNAMIC_API PEP_STATUS get_crashdump_log(
  2206         PEP_SESSION session,
  2207         int maxlines,
  2208         char **logdata
  2209     )
  2210 {
  2211     PEP_STATUS status = PEP_STATUS_OK;
  2212     char *_logdata= NULL;
  2213 
  2214     assert(session);
  2215     assert(maxlines >= 0 && maxlines <= CRASHDUMP_MAX_LINES);
  2216     assert(logdata);
  2217 
  2218     if (!(session && logdata && maxlines >= 0 && maxlines <=
  2219             CRASHDUMP_MAX_LINES))
  2220         return PEP_ILLEGAL_VALUE;
  2221 
  2222     *logdata = NULL;
  2223 
  2224     int limit = maxlines ? maxlines : CRASHDUMP_DEFAULT_LINES;
  2225     const char *timestamp = NULL;
  2226     const char *title = NULL;
  2227     const char *entity = NULL;
  2228     const char *desc = NULL;
  2229     const char *comment = NULL;
  2230 
  2231     sqlite3_reset(session->crashdump);
  2232     sqlite3_bind_int(session->crashdump, 1, limit);
  2233 
  2234     int result;
  2235 
  2236     do {
  2237         result = sqlite3_step(session->crashdump);
  2238         switch (result) {
  2239         case SQLITE_ROW:
  2240             timestamp = (const char *) sqlite3_column_text(session->crashdump,
  2241                     0);
  2242             title   = (const char *) sqlite3_column_text(session->crashdump,
  2243                     1);
  2244             entity  = (const char *) sqlite3_column_text(session->crashdump,
  2245                     2);
  2246             desc    = (const char *) sqlite3_column_text(session->crashdump,
  2247                     3);
  2248             comment = (const char *) sqlite3_column_text(session->crashdump,
  2249                     4);
  2250 
  2251             _logdata = _concat_string(_logdata, timestamp, ',');
  2252             if (_logdata == NULL)
  2253                 goto enomem;
  2254 
  2255             _logdata = _concat_string(_logdata, title, ',');
  2256             if (_logdata == NULL)
  2257                 goto enomem;
  2258 
  2259             _logdata = _concat_string(_logdata, entity, ',');
  2260             if (_logdata == NULL)
  2261                 goto enomem;
  2262 
  2263             _logdata = _concat_string(_logdata, desc, ',');
  2264             if (_logdata == NULL)
  2265                 goto enomem;
  2266 
  2267             _logdata = _concat_string(_logdata, comment, '\n');
  2268             if (_logdata == NULL)
  2269                 goto enomem;
  2270 
  2271             _clean_log_value(_logdata);
  2272             break;
  2273 
  2274         case SQLITE_DONE:
  2275             break;
  2276 
  2277         default:
  2278             status = PEP_UNKNOWN_ERROR;
  2279             result = SQLITE_DONE;
  2280         }
  2281     } while (result != SQLITE_DONE);
  2282 
  2283     sqlite3_reset(session->crashdump);
  2284     if (status == PEP_STATUS_OK)
  2285         *logdata = _logdata;
  2286 
  2287     goto the_end;
  2288 
  2289 enomem:
  2290     status = PEP_OUT_OF_MEMORY;
  2291 
  2292 the_end:
  2293     return ADD_TO_LOG(status);
  2294 }
  2295 
  2296 DYNAMIC_API PEP_STATUS get_languagelist(
  2297         PEP_SESSION session,
  2298         char **languages
  2299     )
  2300 {
  2301     PEP_STATUS status = PEP_STATUS_OK;
  2302     char *_languages= NULL;
  2303 
  2304     assert(session);
  2305     assert(languages);
  2306 
  2307     if (!(session && languages))
  2308         return PEP_ILLEGAL_VALUE;
  2309 
  2310     *languages = NULL;
  2311 
  2312     const char *lang = NULL;
  2313     const char *name = NULL;
  2314     const char *phrase = NULL;
  2315 
  2316     sqlite3_reset(session->languagelist);
  2317 
  2318     int result;
  2319 
  2320     do {
  2321         result = sqlite3_step(session->languagelist);
  2322         switch (result) {
  2323         case SQLITE_ROW:
  2324             lang = (const char *) sqlite3_column_text(session->languagelist,
  2325                     0);
  2326             name = (const char *) sqlite3_column_text(session->languagelist,
  2327                     1);
  2328             phrase = (const char *) sqlite3_column_text(session->languagelist,
  2329                     2);
  2330 
  2331             _languages = _concat_string(_languages, lang, ',');
  2332             if (_languages == NULL)
  2333                 goto enomem;
  2334 
  2335             _languages = _concat_string(_languages, name, ',');
  2336             if (_languages == NULL)
  2337                 goto enomem;
  2338 
  2339             _languages = _concat_string(_languages, phrase, '\n');
  2340             if (_languages == NULL)
  2341                 goto enomem;
  2342 
  2343             break;
  2344 
  2345         case SQLITE_DONE:
  2346             break;
  2347 
  2348         default:
  2349             status = PEP_UNKNOWN_ERROR;
  2350             result = SQLITE_DONE;
  2351         }
  2352     } while (result != SQLITE_DONE);
  2353 
  2354     sqlite3_reset(session->languagelist);
  2355     if (status == PEP_STATUS_OK)
  2356         *languages = _languages;
  2357 
  2358     goto the_end;
  2359 
  2360 enomem:
  2361     status = PEP_OUT_OF_MEMORY;
  2362 
  2363 the_end:
  2364     return status;
  2365 }
  2366 
  2367 DYNAMIC_API PEP_STATUS get_phrase(
  2368         PEP_SESSION session,
  2369         const char *lang,
  2370         int phrase_id,
  2371         char **phrase
  2372     )
  2373 {
  2374     PEP_STATUS status = PEP_STATUS_OK;
  2375 
  2376     assert(session && lang && lang[0] && lang[1] && lang[2] == 0 && phrase);
  2377     if (!(session && lang && lang[0] && lang[1] && lang[2] == 0 && phrase))
  2378         return PEP_ILLEGAL_VALUE;
  2379 
  2380     *phrase = NULL;
  2381 
  2382     sqlite3_reset(session->i18n_token);
  2383     sqlite3_bind_text(session->i18n_token, 1, lang, -1, SQLITE_STATIC);
  2384     sqlite3_bind_int(session->i18n_token, 2, phrase_id);
  2385 
  2386     const char *_phrase = NULL;
  2387     int result;
  2388 
  2389     result = sqlite3_step(session->i18n_token);
  2390     switch (result) {
  2391     case SQLITE_ROW:
  2392         _phrase = (const char *) sqlite3_column_text(session->i18n_token, 0);
  2393         break;
  2394 
  2395     case SQLITE_DONE:
  2396         status = PEP_PHRASE_NOT_FOUND;
  2397         break;
  2398 
  2399     default:
  2400         status = PEP_UNKNOWN_ERROR;
  2401     }
  2402 
  2403     if (status == PEP_STATUS_OK) {
  2404         *phrase = strdup(_phrase);
  2405         if (*phrase == NULL)
  2406             goto enomem;
  2407     }
  2408 
  2409     sqlite3_reset(session->i18n_token);
  2410     goto the_end;
  2411 
  2412 enomem:
  2413     status = PEP_OUT_OF_MEMORY;
  2414 
  2415 the_end:
  2416     return status;
  2417 }
  2418 
  2419 static PEP_STATUS _get_sequence_value(PEP_SESSION session, const char *name,
  2420         int32_t *value)
  2421 {
  2422     assert(session && name && value);
  2423     if (!(session && name && value))
  2424         return PEP_ILLEGAL_VALUE;
  2425 
  2426     PEP_STATUS status = PEP_STATUS_OK;
  2427 
  2428     sqlite3_reset(session->sequence_value2);
  2429     sqlite3_bind_text(session->sequence_value2, 1, name, -1,
  2430             SQLITE_STATIC);
  2431     int result = sqlite3_step(session->sequence_value2);
  2432     switch (result) {
  2433         case SQLITE_ROW: {
  2434             int32_t _value = (int32_t)
  2435                     sqlite3_column_int(session->sequence_value2, 0);
  2436             int _own = (int)
  2437                     sqlite3_column_int(session->sequence_value2, 1);
  2438             *value = _value;
  2439             if (_own)
  2440                 status = PEP_OWN_SEQUENCE;
  2441             break;
  2442         }
  2443         case SQLITE_DONE:
  2444             status = PEP_RECORD_NOT_FOUND;
  2445             break;
  2446         default:
  2447             status = PEP_UNKNOWN_ERROR;
  2448     }
  2449     sqlite3_reset(session->sequence_value2);
  2450 
  2451     return status;
  2452 }
  2453 
  2454 static PEP_STATUS _increment_sequence_value(PEP_SESSION session,
  2455         const char *name, int own)
  2456 {
  2457     assert(session && name);
  2458     if (!(session && name))
  2459         return PEP_ILLEGAL_VALUE;
  2460 
  2461     sqlite3_reset(session->sequence_value1);
  2462     sqlite3_bind_text(session->sequence_value1, 1, name, -1, SQLITE_STATIC);
  2463     sqlite3_bind_int(session->sequence_value1, 2, own);
  2464     int result = sqlite3_step(session->sequence_value1);
  2465     assert(result == SQLITE_DONE);
  2466     sqlite3_reset(session->sequence_value1);
  2467     if (result == SQLITE_DONE)
  2468         return PEP_STATUS_OK;
  2469     else
  2470         return PEP_CANNOT_INCREASE_SEQUENCE;
  2471 }
  2472 
  2473 static PEP_STATUS _set_sequence_value(PEP_SESSION session,
  2474         const char *name, int32_t value, int own)
  2475 {
  2476     assert(session && name && value > 0);
  2477     if (!(session && name && value > 0))
  2478         return PEP_ILLEGAL_VALUE;
  2479 
  2480     sqlite3_reset(session->sequence_value3);
  2481     sqlite3_bind_text(session->sequence_value3, 1, name, -1, SQLITE_STATIC);
  2482     sqlite3_bind_int(session->sequence_value3, 2, value);
  2483     sqlite3_bind_int(session->sequence_value3, 3, own);
  2484     int result = sqlite3_step(session->sequence_value3);
  2485     assert(result == SQLITE_DONE);
  2486     sqlite3_reset(session->sequence_value3);
  2487     if (result == SQLITE_DONE)
  2488         return PEP_STATUS_OK;
  2489     else
  2490         return PEP_CANNOT_SET_SEQUENCE_VALUE;
  2491 }
  2492 
  2493 DYNAMIC_API PEP_STATUS sequence_value(
  2494         PEP_SESSION session,
  2495         char *name,
  2496         int32_t *value
  2497     )
  2498 {
  2499     PEP_STATUS status = PEP_STATUS_OK;
  2500     int result;
  2501 
  2502     assert(session);
  2503     assert(name && value && *value >= 0);
  2504 
  2505     if (!(session && name && value && *value >= 0))
  2506         return PEP_ILLEGAL_VALUE;
  2507 
  2508     int own = 0;
  2509     if (!name[0]) {
  2510         pEpUUID uuid;
  2511         uuid_generate_random(uuid);
  2512         uuid_unparse_upper(uuid, name);
  2513         own = 1;
  2514     }
  2515     else {
  2516         if (name == session->sync_session->sync_uuid || 
  2517             strcmp(name, session->sync_session->sync_uuid) == 0)
  2518             own = 1;
  2519     }
  2520 
  2521     if (*value) {
  2522         sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
  2523         int32_t old_value = 0;
  2524         status = _get_sequence_value(session, name, &old_value);
  2525         if (status != PEP_STATUS_OK && status != PEP_RECORD_NOT_FOUND)
  2526         {
  2527             sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  2528             return status;
  2529         }
  2530 
  2531         if (old_value >= *value) {
  2532             sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  2533             return PEP_SEQUENCE_VIOLATED;
  2534         }
  2535         else {
  2536             status = _set_sequence_value(session, name, *value, own);
  2537             if (status == PEP_STATUS_OK) {
  2538                 result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
  2539                 if (result == SQLITE_OK)
  2540                     return PEP_STATUS_OK;
  2541                 else
  2542                     return PEP_COMMIT_FAILED;
  2543             } else {
  2544                 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  2545                 return status;
  2546             }
  2547         }
  2548     }
  2549 
  2550     assert(*value == 0);
  2551     sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
  2552     status = _increment_sequence_value(session, name, own);
  2553     if (status == PEP_STATUS_OK) {
  2554         status = _get_sequence_value(session, name, value);
  2555     }
  2556     if (status == PEP_STATUS_OK || status == PEP_OWN_SEQUENCE) {
  2557         result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
  2558         if (result == SQLITE_OK){
  2559             assert(*value < INT32_MAX);
  2560             if (*value == INT32_MAX){
  2561                 return PEP_CANNOT_INCREASE_SEQUENCE;
  2562             }
  2563             return status;
  2564         } else {
  2565             return PEP_COMMIT_FAILED;
  2566         }
  2567     } else {
  2568         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  2569         return status;
  2570     }
  2571     return status;
  2572 }
  2573 
  2574 DYNAMIC_API PEP_STATUS set_revoked(
  2575        PEP_SESSION session,
  2576        const char *revoked_fpr,
  2577        const char *replacement_fpr,
  2578        const uint64_t revocation_date
  2579     )
  2580 {
  2581     PEP_STATUS status = PEP_STATUS_OK;
  2582     
  2583     assert(session &&
  2584            revoked_fpr && revoked_fpr[0] &&
  2585            replacement_fpr && replacement_fpr[0]
  2586           );
  2587     
  2588     if (!(session &&
  2589           revoked_fpr && revoked_fpr[0] &&
  2590           replacement_fpr && replacement_fpr[0]
  2591          ))
  2592         return PEP_ILLEGAL_VALUE;
  2593     
  2594     sqlite3_reset(session->set_revoked);
  2595     sqlite3_bind_text(session->set_revoked, 1, revoked_fpr, -1, SQLITE_STATIC);
  2596     sqlite3_bind_text(session->set_revoked, 2, replacement_fpr, -1,
  2597             SQLITE_STATIC);
  2598     sqlite3_bind_int64(session->set_revoked, 3, revocation_date);
  2599 
  2600     int result;
  2601     
  2602     result = sqlite3_step(session->set_revoked);
  2603     switch (result) {
  2604         case SQLITE_DONE:
  2605             status = PEP_STATUS_OK;
  2606             break;
  2607             
  2608         default:
  2609             status = PEP_UNKNOWN_ERROR;
  2610     }
  2611     
  2612     sqlite3_reset(session->set_revoked);
  2613     return status;
  2614 }
  2615 
  2616 DYNAMIC_API PEP_STATUS get_revoked(
  2617         PEP_SESSION session,
  2618         const char *fpr,
  2619         char **revoked_fpr,
  2620         uint64_t *revocation_date
  2621     )
  2622 {
  2623     PEP_STATUS status = PEP_STATUS_OK;
  2624 
  2625     assert(session &&
  2626            revoked_fpr &&
  2627            fpr && fpr[0]
  2628           );
  2629     
  2630     if (!(session &&
  2631            revoked_fpr &&
  2632            fpr && fpr[0]
  2633           ))
  2634         return PEP_ILLEGAL_VALUE;
  2635 
  2636     *revoked_fpr = NULL;
  2637     *revocation_date = 0;
  2638 
  2639     sqlite3_reset(session->get_revoked);
  2640     sqlite3_bind_text(session->get_revoked, 1, fpr, -1, SQLITE_STATIC);
  2641 
  2642     int result;
  2643     
  2644     result = sqlite3_step(session->get_revoked);
  2645     switch (result) {
  2646         case SQLITE_ROW: {
  2647             *revoked_fpr = strdup((const char *)
  2648                     sqlite3_column_text(session->get_revoked, 0));
  2649             if(*revoked_fpr)
  2650                 *revocation_date = sqlite3_column_int64(session->get_revoked,
  2651                         1);
  2652             else
  2653                 status = PEP_OUT_OF_MEMORY;
  2654 
  2655             break;
  2656         }
  2657         default:
  2658             status = PEP_CANNOT_FIND_IDENTITY;
  2659     }
  2660 
  2661     sqlite3_reset(session->get_revoked);
  2662 
  2663     return status;
  2664 }
  2665 
  2666 PEP_STATUS key_created(
  2667         PEP_SESSION session,
  2668         const char *fpr,
  2669         time_t *created
  2670     )
  2671 {
  2672     assert(session && fpr && created);
  2673     if (!(session && fpr && created))
  2674         return PEP_ILLEGAL_VALUE;
  2675 
  2676     return session->cryptotech[PEP_crypt_OpenPGP].key_created(session, fpr,
  2677             created);
  2678 }
  2679 
  2680 PEP_STATUS find_private_keys(PEP_SESSION session, const char* pattern,
  2681                              stringlist_t **keylist) {
  2682     assert(session && keylist);
  2683     if (!(session && keylist))
  2684         return PEP_ILLEGAL_VALUE;
  2685     
  2686     return session->cryptotech[PEP_crypt_OpenPGP].find_private_keys(session, pattern,
  2687                                                                     keylist);
  2688 }
  2689 
  2690 DYNAMIC_API const char* get_engine_version() {
  2691     return PEP_ENGINE_VERSION;
  2692 }
  2693 
  2694 
  2695 DYNAMIC_API PEP_STATUS reset_peptest_hack(PEP_SESSION session)
  2696 {
  2697     assert(session);
  2698 
  2699     if (!session)
  2700         return PEP_ILLEGAL_VALUE;
  2701 
  2702     int int_result = sqlite3_exec(
  2703         session->db,
  2704         "delete from identity where address like '%@peptest.ch' ;",
  2705         NULL,
  2706         NULL,
  2707         NULL
  2708     );
  2709     assert(int_result == SQLITE_OK);
  2710 
  2711     if (int_result != SQLITE_OK)
  2712         return PEP_UNKNOWN_ERROR;
  2713 
  2714     return PEP_STATUS_OK;
  2715 }
  2716 
  2717 #ifdef DEBUG_ERRORSTACK
  2718 PEP_STATUS session_add_error(PEP_SESSION session, const char* file, unsigned line, PEP_STATUS status)
  2719 {
  2720     char logline[48];
  2721     if(status>0)
  2722     {
  2723         snprintf(logline,47, "%.24s:%u status=%u (0x%x)", file, line, status, status);
  2724     }else{
  2725         snprintf(logline,47, "%.24s:%u status=%i.", file, line, status);
  2726     }
  2727     stringlist_add(session->errorstack, logline); // logline is copied! :-)
  2728     return status;
  2729 }
  2730 
  2731 DYNAMIC_API const stringlist_t* get_errorstack(PEP_SESSION session)
  2732 {
  2733     return session->errorstack;
  2734 }
  2735 
  2736 DYNAMIC_API void clear_errorstack(PEP_SESSION session)
  2737 {
  2738     const int old_len = stringlist_length(session->errorstack);
  2739     char buf[48];
  2740     free_stringlist(session->errorstack);
  2741     snprintf(buf, 47, "(%i elements cleared)", old_len);
  2742     session->errorstack = new_stringlist(buf);
  2743 }
  2744 
  2745 #else
  2746 
  2747 static stringlist_t* dummy_errorstack = NULL;
  2748 
  2749 DYNAMIC_API const stringlist_t* get_errorstack(PEP_SESSION session)
  2750 {
  2751     if(dummy_errorstack == NULL)
  2752     {
  2753         dummy_errorstack = new_stringlist("( Please recompile pEpEngine with -DDEBUG_ERRORSTACK )");
  2754     }
  2755 
  2756     return dummy_errorstack;
  2757 }
  2758 
  2759 DYNAMIC_API void clear_errorstack(PEP_SESSION session)
  2760 {
  2761     // nothing to do here
  2762 }
  2763 
  2764 #endif