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