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