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