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