LCOV - code coverage report
Current view: top level - g10 - tofu.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 790 1461 54.1 %
Date: 2016-11-29 15:00:56 Functions: 37 49 75.5 %

          Line data    Source code
       1             : /* tofu.c - TOFU trust model.
       2             :  * Copyright (C) 2015, 2016 g10 Code GmbH
       3             :  *
       4             :  * This file is part of GnuPG.
       5             :  *
       6             :  * GnuPG is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * GnuPG is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License
      17             :  * along with this program; if not, see <https://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : /* TODO:
      21             : 
      22             :    - Format the fingerprints nicely when printing (similar to gpg
      23             :      --list-keys)
      24             :  */
      25             : 
      26             : #include <config.h>
      27             : #include <stdio.h>
      28             : #include <sys/stat.h>
      29             : #include <stdarg.h>
      30             : #include <sqlite3.h>
      31             : #include <time.h>
      32             : 
      33             : #include "gpg.h"
      34             : #include "types.h"
      35             : #include "logging.h"
      36             : #include "stringhelp.h"
      37             : #include "options.h"
      38             : #include "mbox-util.h"
      39             : #include "i18n.h"
      40             : #include "ttyio.h"
      41             : #include "trustdb.h"
      42             : #include "mkdir_p.h"
      43             : #include "gpgsql.h"
      44             : #include "status.h"
      45             : #include "sqrtu32.h"
      46             : 
      47             : #include "tofu.h"
      48             : 
      49             : 
      50             : #define CONTROL_L ('L' - 'A' + 1)
      51             : 
      52             : /* Number of signed messages required to indicate that enough history
      53             :  * is available for basic trust.  */
      54             : #define BASIC_TRUST_THRESHOLD  10
      55             : /* Number of signed messages required to indicate that a lot of
      56             :  * history is available.  */
      57             : #define FULL_TRUST_THRESHOLD  100
      58             : 
      59             : 
      60             : /* A struct with data pertaining to the tofu DB.  There is one such
      61             :    struct per session and it is cached in session's ctrl structure.
      62             :    To initialize this or get the current singleton, call opendbs().
      63             :    There is no need to explicitly release it; cleanup is done when the
      64             :    CTRL object is released.  */
      65             : struct tofu_dbs_s
      66             : {
      67             :   sqlite3 *db;
      68             :   char *want_lock_file;
      69             :   time_t want_lock_file_ctime;
      70             : 
      71             :   struct
      72             :   {
      73             :     sqlite3_stmt *savepoint_batch;
      74             :     sqlite3_stmt *savepoint_batch_commit;
      75             : 
      76             :     sqlite3_stmt *record_binding_get_old_policy;
      77             :     sqlite3_stmt *record_binding_update;
      78             :     sqlite3_stmt *get_policy_select_policy_and_conflict;
      79             :     sqlite3_stmt *get_trust_bindings_with_this_email;
      80             :     sqlite3_stmt *get_trust_gather_other_user_ids;
      81             :     sqlite3_stmt *get_trust_gather_signature_stats;
      82             :     sqlite3_stmt *get_trust_gather_encryption_stats;
      83             :     sqlite3_stmt *register_already_seen;
      84             :     sqlite3_stmt *register_signature;
      85             :     sqlite3_stmt *register_encryption;
      86             :   } s;
      87             : 
      88             :   int in_batch_transaction;
      89             :   int in_transaction;
      90             :   time_t batch_update_started;
      91             : };
      92             : 
      93             : 
      94             : #define STRINGIFY(s) STRINGIFY2(s)
      95             : #define STRINGIFY2(s) #s
      96             : 
      97             : /* The grouping parameters when collecting signature statistics.  */
      98             : 
      99             : /* If a message is signed a couple of hours in the future, just assume
     100             :    some clock skew.  */
     101             : #define TIME_AGO_FUTURE_IGNORE (2 * 60 * 60)
     102             : /* Days.  */
     103             : #define TIME_AGO_UNIT_SMALL (24 * 60 * 60)
     104             : #define TIME_AGO_SMALL_THRESHOLD (7 * TIME_AGO_UNIT_SMALL)
     105             : /* Months.  */
     106             : #define TIME_AGO_UNIT_MEDIUM (30 * 24 * 60 * 60)
     107             : #define TIME_AGO_MEDIUM_THRESHOLD (2 * TIME_AGO_UNIT_MEDIUM)
     108             : /* Years.  */
     109             : #define TIME_AGO_UNIT_LARGE (365 * 24 * 60 * 60)
     110             : #define TIME_AGO_LARGE_THRESHOLD (2 * TIME_AGO_UNIT_LARGE)
     111             : 
     112             : /* Local prototypes.  */
     113             : static gpg_error_t end_transaction (ctrl_t ctrl, int only_batch);
     114             : static char *email_from_user_id (const char *user_id);
     115             : 
     116             : 
     117             : 
     118             : const char *
     119          80 : tofu_policy_str (enum tofu_policy policy)
     120             : {
     121          80 :   switch (policy)
     122             :     {
     123           0 :     case TOFU_POLICY_NONE: return "none";
     124          35 :     case TOFU_POLICY_AUTO: return "auto";
     125          19 :     case TOFU_POLICY_GOOD: return "good";
     126           7 :     case TOFU_POLICY_UNKNOWN: return "unknown";
     127           9 :     case TOFU_POLICY_BAD: return "bad";
     128          10 :     case TOFU_POLICY_ASK: return "ask";
     129           0 :     default: return "???";
     130             :     }
     131             : }
     132             : 
     133             : /* Convert a binding policy (e.g., TOFU_POLICY_BAD) to a trust level
     134             :    (e.g., TRUST_BAD) in light of the current configuration.  */
     135             : int
     136         179 : tofu_policy_to_trust_level (enum tofu_policy policy)
     137             : {
     138         179 :   if (policy == TOFU_POLICY_AUTO)
     139             :     /* If POLICY is AUTO, fallback to OPT.TOFU_DEFAULT_POLICY.  */
     140          83 :     policy = opt.tofu_default_policy;
     141             : 
     142         179 :   switch (policy)
     143             :     {
     144             :     case TOFU_POLICY_AUTO:
     145             :       /* If POLICY and OPT.TOFU_DEFAULT_POLICY are both AUTO, default
     146             :          to marginal trust.  */
     147          83 :       return TRUST_MARGINAL;
     148             :     case TOFU_POLICY_GOOD:
     149          46 :       return TRUST_FULLY;
     150             :     case TOFU_POLICY_UNKNOWN:
     151          22 :       return TRUST_UNKNOWN;
     152             :     case TOFU_POLICY_BAD:
     153          28 :       return TRUST_NEVER;
     154             :     case TOFU_POLICY_ASK:
     155           0 :       return TRUST_UNKNOWN;
     156             :     default:
     157           0 :       log_bug ("Bad value for trust policy: %d\n",
     158           0 :                opt.tofu_default_policy);
     159             :       return 0;
     160             :     }
     161             : }
     162             : 
     163             : 
     164             : 
     165             : /* Start a transaction on DB.  If ONLY_BATCH is set, then this will
     166             :    start a batch transaction if we haven't started a batch transaction
     167             :    and one has been requested.  */
     168             : static gpg_error_t
     169         416 : begin_transaction (ctrl_t ctrl, int only_batch)
     170             : {
     171         416 :   tofu_dbs_t dbs = ctrl->tofu.dbs;
     172             :   int rc;
     173         416 :   char *err = NULL;
     174             : 
     175         416 :   log_assert (dbs);
     176             : 
     177             :   /* If we've been in batch update mode for a while (on average, more
     178             :    * than 500 ms), to prevent starving other gpg processes, we drop
     179             :    * and retake the batch lock.
     180             :    *
     181             :    * Note: gnupg_get_time has a one second resolution, if we wanted a
     182             :    * higher resolution, we could use npth_clock_gettime.  */
     183         416 :   if (/* No real transactions.  */
     184         416 :       dbs->in_transaction == 0
     185             :       /* There is an open batch transaction.  */
     186         390 :       && dbs->in_batch_transaction
     187             :       /* And some time has gone by since it was started.  */
     188         239 :       && dbs->batch_update_started != gnupg_get_time ())
     189             :     {
     190             :       struct stat statbuf;
     191             : 
     192             :       /* If we are in a batch update, then batch updates better have
     193             :          been enabled.  */
     194           0 :       log_assert (ctrl->tofu.batch_updated_wanted);
     195             : 
     196             :       /* Check if another process wants to run.  (We just ignore any
     197             :        * stat failure.  A waiter might have to wait a bit longer, but
     198             :        * otherwise there should be no impact.)  */
     199           0 :       if (stat (dbs->want_lock_file, &statbuf) == 0
     200           0 :           && statbuf.st_ctime != dbs->want_lock_file_ctime)
     201             :         {
     202           0 :           end_transaction (ctrl, 2);
     203             : 
     204             :           /* Yield to allow another process a chance to run.  Note:
     205             :            * testing suggests that anything less than a 100ms tends to
     206             :            * not result in the other process getting the lock.  */
     207           0 :           gnupg_usleep (100000);
     208             :         }
     209             :       else
     210           0 :         dbs->batch_update_started = gnupg_get_time ();
     211             :     }
     212             : 
     213         416 :   if (/* We don't have an open batch transaction.  */
     214         416 :       !dbs->in_batch_transaction
     215         151 :       && (/* Batch mode is enabled or we are starting a new transaction.  */
     216         177 :           ctrl->tofu.batch_updated_wanted || dbs->in_transaction == 0))
     217             :     {
     218             :       struct stat statbuf;
     219             : 
     220             :       /* We are in batch mode, but we don't have an open batch
     221             :        * transaction.  Since the batch save point must be the outer
     222             :        * save point, it must be taken before the inner save point.  */
     223         151 :       log_assert (dbs->in_transaction == 0);
     224             : 
     225         151 :       rc = gpgsql_stepx (dbs->db, &dbs->s.savepoint_batch,
     226             :                           NULL, NULL, &err,
     227             :                           "begin immediate transaction;", GPGSQL_ARG_END);
     228         151 :       if (rc)
     229             :         {
     230           0 :           log_error (_("error beginning transaction on TOFU database: %s\n"),
     231             :                      err);
     232           0 :           sqlite3_free (err);
     233           0 :           return gpg_error (GPG_ERR_GENERAL);
     234             :         }
     235             : 
     236         151 :       dbs->in_batch_transaction = 1;
     237         151 :       dbs->batch_update_started = gnupg_get_time ();
     238             : 
     239         151 :       if (stat (dbs->want_lock_file, &statbuf) == 0)
     240           0 :         dbs->want_lock_file_ctime = statbuf.st_ctime;
     241             :     }
     242             : 
     243         416 :   if (only_batch)
     244         181 :     return 0;
     245             : 
     246         235 :   log_assert (dbs->in_transaction >= 0);
     247         235 :   dbs->in_transaction ++;
     248             : 
     249         235 :   rc = gpgsql_exec_printf (dbs->db, NULL, NULL, &err,
     250             :                            "savepoint inner%d;",
     251             :                            dbs->in_transaction);
     252         235 :   if (rc)
     253             :     {
     254           0 :       log_error (_("error beginning transaction on TOFU database: %s\n"),
     255             :                  err);
     256           0 :       sqlite3_free (err);
     257           0 :       return gpg_error (GPG_ERR_GENERAL);
     258             :     }
     259             : 
     260         235 :   return 0;
     261             : }
     262             : 
     263             : 
     264             : /* Commit a transaction.  If ONLY_BATCH is 1, then this only ends the
     265             :  * batch transaction if we have left batch mode.  If ONLY_BATCH is 2,
     266             :  * this commits any open batch transaction even if we are still in
     267             :  * batch mode.  */
     268             : static gpg_error_t
     269         623 : end_transaction (ctrl_t ctrl, int only_batch)
     270             : {
     271         623 :   tofu_dbs_t dbs = ctrl->tofu.dbs;
     272             :   int rc;
     273         623 :   char *err = NULL;
     274             : 
     275         623 :   if (only_batch || (! only_batch && dbs->in_transaction == 1))
     276             :     {
     277         597 :       if (!dbs)
     278          39 :         return 0;  /* Shortcut to allow for easier cleanup code.  */
     279             : 
     280             :       /* If we are releasing the batch transaction, then we better not
     281             :          be in a normal transaction.  */
     282         558 :       if (only_batch)
     283         349 :         log_assert (dbs->in_transaction == 0);
     284             : 
     285         558 :       if (/* Batch mode disabled?  */
     286         862 :           (!ctrl->tofu.batch_updated_wanted || only_batch == 2)
     287             :           /* But, we still have an open batch transaction?  */
     288         254 :           && dbs->in_batch_transaction)
     289             :         {
     290             :           /* The batch transaction is still in open, but we've left
     291             :            * batch mode.  */
     292         151 :           dbs->in_batch_transaction = 0;
     293         151 :           dbs->in_transaction = 0;
     294             : 
     295         151 :           rc = gpgsql_stepx (dbs->db, &dbs->s.savepoint_batch_commit,
     296             :                              NULL, NULL, &err,
     297             :                              "commit transaction;", GPGSQL_ARG_END);
     298         151 :           if (rc)
     299             :             {
     300           0 :               log_error (_("error committing transaction on TOFU database: %s\n"),
     301             :                          err);
     302           0 :               sqlite3_free (err);
     303           0 :               return gpg_error (GPG_ERR_GENERAL);
     304             :             }
     305             : 
     306         151 :           return 0;
     307             :         }
     308             : 
     309         407 :       if (only_batch)
     310         224 :         return 0;
     311             :     }
     312             : 
     313         209 :   log_assert (dbs);
     314         209 :   log_assert (dbs->in_transaction > 0);
     315             : 
     316         209 :   rc = gpgsql_exec_printf (dbs->db, NULL, NULL, &err,
     317             :                            "release inner%d;", dbs->in_transaction);
     318             : 
     319         209 :   dbs->in_transaction --;
     320             : 
     321         209 :   if (rc)
     322             :     {
     323           0 :       log_error (_("error committing transaction on TOFU database: %s\n"),
     324             :                  err);
     325           0 :       sqlite3_free (err);
     326           0 :       return gpg_error (GPG_ERR_GENERAL);
     327             :     }
     328             : 
     329         209 :   return 0;
     330             : }
     331             : 
     332             : 
     333             : static gpg_error_t
     334           0 : rollback_transaction (ctrl_t ctrl)
     335             : {
     336           0 :   tofu_dbs_t dbs = ctrl->tofu.dbs;
     337             :   int rc;
     338           0 :   char *err = NULL;
     339             : 
     340           0 :   log_assert (dbs);
     341           0 :   log_assert (dbs->in_transaction > 0);
     342             : 
     343             :   /* Be careful to not undo any progress made by closed transactions in
     344             :      batch mode.  */
     345           0 :   rc = gpgsql_exec_printf (dbs->db, NULL, NULL, &err,
     346             :                            "rollback to inner%d;",
     347             :                            dbs->in_transaction);
     348             : 
     349           0 :   dbs->in_transaction --;
     350             : 
     351           0 :   if (rc)
     352             :     {
     353           0 :       log_error (_("error rolling back transaction on TOFU database: %s\n"),
     354             :                  err);
     355           0 :       sqlite3_free (err);
     356           0 :       return gpg_error (GPG_ERR_GENERAL);
     357             :     }
     358             : 
     359           0 :   return 0;
     360             : }
     361             : 
     362             : void
     363         285 : tofu_begin_batch_update (ctrl_t ctrl)
     364             : {
     365         285 :   ctrl->tofu.batch_updated_wanted ++;
     366         285 : }
     367             : 
     368             : void
     369         285 : tofu_end_batch_update (ctrl_t ctrl)
     370             : {
     371         285 :   log_assert (ctrl->tofu.batch_updated_wanted > 0);
     372         285 :   ctrl->tofu.batch_updated_wanted --;
     373         285 :   end_transaction (ctrl, 1);
     374         285 : }
     375             : 
     376             : /* Suspend any extant batch transaction (it is safe to call this even
     377             :    no batch transaction has been started).  Note: you cannot suspend a
     378             :    batch transaction if you are in a normal transaction.  The batch
     379             :    transaction can be resumed explicitly by calling
     380             :    tofu_resume_batch_transaction or implicitly by starting a normal
     381             :    transaction.  */
     382             : static void
     383           0 : tofu_suspend_batch_transaction (ctrl_t ctrl)
     384             : {
     385           0 :   end_transaction (ctrl, 2);
     386           0 : }
     387             : 
     388             : /* Resume a batch transaction if there is no extant batch transaction
     389             :    and one has been requested using tofu_begin_batch_transaction.  */
     390             : static void
     391         181 : tofu_resume_batch_transaction (ctrl_t ctrl)
     392             : {
     393         181 :   begin_transaction (ctrl, 1);
     394         181 : }
     395             : 
     396             : 
     397             : 
     398             : /* Wrapper around strtol which prints a warning in case of a
     399             :  * conversion error.  On success the converted value is stored at
     400             :  * R_VALUE and 0 is returned; on error FALLBACK is stored at R_VALUE
     401             :  * and an error code is returned.  */
     402             : static gpg_error_t
     403         538 : string_to_long (long *r_value, const char *string, long fallback, int line)
     404             : {
     405             :   gpg_error_t err;
     406         538 :   char *tail = NULL;
     407             : 
     408         538 :   gpg_err_set_errno (0);
     409         538 :   *r_value = strtol (string, &tail, 0);
     410         538 :   if (errno || !(!strcmp (tail, ".0") || !*tail))
     411             :     {
     412           0 :       err = errno? gpg_error_from_errno (errno) : gpg_error (GPG_ERR_BAD_DATA);
     413           0 :       log_debug ("%s:%d: "
     414             :                  "strtol failed for DB returned string (tail=%.10s): %s\n",
     415             :                  __FILE__, line, tail, gpg_strerror (err));
     416           0 :       *r_value = fallback;
     417             :     }
     418             :   else
     419         538 :     err = 0;
     420             : 
     421         538 :   return err;
     422             : }
     423             : 
     424             : 
     425             : /* Wrapper around strtoul which prints a warning in case of a
     426             :  * conversion error.  On success the converted value is stored at
     427             :  * R_VALUE and 0 is returned; on error FALLBACK is stored at R_VALUE
     428             :  * and an error code is returned.  */
     429             : static gpg_error_t
     430         662 : string_to_ulong (unsigned long *r_value, const char *string,
     431             :                  unsigned long fallback, int line)
     432             : {
     433             :   gpg_error_t err;
     434         662 :   char *tail = NULL;
     435             : 
     436         662 :   gpg_err_set_errno (0);
     437         662 :   *r_value = strtoul (string, &tail, 0);
     438         662 :   if (errno || !(!strcmp (tail, ".0") || !*tail))
     439             :     {
     440           0 :       err = errno? gpg_error_from_errno (errno) : gpg_error (GPG_ERR_BAD_DATA);
     441           0 :       log_debug ("%s:%d: "
     442             :                  "strtoul failed for DB returned string (tail=%.10s): %s\n",
     443             :                  __FILE__, line, tail, gpg_strerror (err));
     444           0 :       *r_value = fallback;
     445             :     }
     446             :   else
     447         662 :     err = 0;
     448             : 
     449         662 :   return err;
     450             : }
     451             : 
     452             : 
     453             : 
     454             : /* Collect results of a select count (*) ...; style query.  Aborts if
     455             :    the argument is not a valid integer (or real of the form X.0).  */
     456             : static int
     457         236 : get_single_unsigned_long_cb (void *cookie, int argc, char **argv,
     458             :                              char **azColName)
     459             : {
     460         236 :   unsigned long int *count = cookie;
     461             : 
     462             :   (void) azColName;
     463             : 
     464         236 :   log_assert (argc == 1);
     465             : 
     466         236 :   if (string_to_ulong (count, argv[0], 0, __LINE__))
     467           0 :     return 1; /* Abort.  */
     468         236 :   return 0;
     469             : }
     470             : 
     471             : static int
     472          30 : get_single_unsigned_long_cb2 (void *cookie, int argc, char **argv,
     473             :                              char **azColName, sqlite3_stmt *stmt)
     474             : {
     475             :   (void) stmt;
     476          30 :   return get_single_unsigned_long_cb (cookie, argc, argv, azColName);
     477             : }
     478             : 
     479             : /* We expect a single integer column whose name is "version".  COOKIE
     480             :    must point to an int.  This function always aborts.  On error or a
     481             :    if the version is bad, sets *VERSION to -1.  */
     482             : static int
     483          97 : version_check_cb (void *cookie, int argc, char **argv, char **azColName)
     484             : {
     485          97 :   int *version = cookie;
     486             : 
     487          97 :   if (argc != 1 || strcmp (azColName[0], "version") != 0)
     488             :     {
     489           0 :       *version = -1;
     490           0 :       return 1;
     491             :     }
     492             : 
     493          97 :   if (strcmp (argv[0], "1") == 0)
     494          97 :     *version = 1;
     495             :   else
     496             :     {
     497           0 :       log_error (_("unsupported TOFU database version: %s\n"), argv[0]);
     498           0 :       *version = -1;
     499             :     }
     500             : 
     501             :   /* Don't run again.  */
     502          97 :   return 1;
     503             : }
     504             : 
     505             : static int
     506         103 : check_utks (sqlite3 *db)
     507             : {
     508             :   int rc;
     509         103 :   char *err = NULL;
     510             :   struct key_item *utks;
     511             :   struct key_item *ki;
     512             :   int utk_count;
     513         103 :   char *utks_string = NULL;
     514             :   char keyid_str[16+1];
     515         103 :   long utks_unchanged = 0;
     516             : 
     517             :   /* An early version of the v1 format did not include the list of
     518             :    * known ultimately trusted keys.
     519             :    *
     520             :    * This list is used to detect when the set of ultimately trusted
     521             :    * keys changes.  We need to detect this to invalidate the effective
     522             :    * policy, which can change if an ultimately trusted key is added or
     523             :    * removed.  */
     524         103 :   rc = sqlite3_exec (db,
     525             :                      "create table if not exists ultimately_trusted_keys"
     526             :                      " (keyid);\n",
     527             :                      NULL, NULL, &err);
     528         103 :   if (rc)
     529             :     {
     530           0 :       log_error (_("error creating 'ultimately_trusted_keys' TOFU table: %s\n"),
     531             :                  err);
     532           0 :       sqlite3_free (err);
     533           0 :       goto out;
     534             :     }
     535             : 
     536             : 
     537         103 :   utks = tdb_utks ();
     538         103 :   for (ki = utks, utk_count = 0; ki; ki = ki->next, utk_count ++)
     539             :     ;
     540             : 
     541         103 :   if (utk_count)
     542             :     {
     543             :       /* Build a list of keyids of the form "XXX","YYY","ZZZ".  */
     544          15 :       int len = (1 + 16 + 1 + 1) * utk_count;
     545          15 :       int o = 0;
     546             : 
     547          15 :       utks_string = xmalloc (len);
     548          15 :       *utks_string = 0;
     549          30 :       for (ki = utks, utk_count = 0; ki; ki = ki->next, utk_count ++)
     550             :         {
     551          15 :           utks_string[o ++] = '\'';
     552          15 :           format_keyid (ki->kid, KF_LONG,
     553             :                         keyid_str, sizeof (keyid_str));
     554          15 :           memcpy (&utks_string[o], keyid_str, 16);
     555          15 :           o += 16;
     556          15 :           utks_string[o ++] = '\'';
     557          15 :           utks_string[o ++] = ',';
     558             :         }
     559          15 :       utks_string[o - 1] = 0;
     560          15 :       log_assert (o == len);
     561             :     }
     562             : 
     563         103 :   rc = gpgsql_exec_printf
     564             :     (db, get_single_unsigned_long_cb, &utks_unchanged, &err,
     565             :      "select"
     566             :      /* Removed UTKs?  (Known UTKs in current UTKs.)  */
     567             :      "  ((select count(*) from ultimately_trusted_keys"
     568             :      "     where (keyid in (%s))) == %d)"
     569             :      " and"
     570             :      /* New UTKs?  */
     571             :      "  ((select count(*) from ultimately_trusted_keys"
     572             :      "     where keyid not in (%s)) == 0);",
     573             :      utks_string ? utks_string : "",
     574             :      utk_count,
     575             :      utks_string ? utks_string : "");
     576         103 :   xfree (utks_string);
     577         103 :   if (rc)
     578             :     {
     579           0 :       log_error (_("TOFU DB error"));
     580           0 :       print_further_info ("checking if ultimately trusted keys changed: %s",
     581             :                          err);
     582           0 :       sqlite3_free (err);
     583           0 :       goto out;
     584             :     }
     585             : 
     586         103 :   if (utks_unchanged)
     587          97 :     goto out;
     588             : 
     589           6 :   if (DBG_TRUST)
     590           0 :     log_debug ("TOFU: ultimately trusted keys changed.\n");
     591             : 
     592             :   /* Given that the set of ultimately trusted keys
     593             :    * changed, clear any cached policies.  */
     594           6 :   rc = gpgsql_exec_printf
     595             :     (db, NULL, NULL, &err,
     596             :      "update bindings set effective_policy = %d;",
     597             :      TOFU_POLICY_NONE);
     598           6 :   if (rc)
     599             :     {
     600           0 :       log_error (_("TOFU DB error"));
     601           0 :       print_further_info ("clearing cached policies: %s", err);
     602           0 :       sqlite3_free (err);
     603           0 :       goto out;
     604             :     }
     605             : 
     606             :   /* Now, update the UTK table.  */
     607           6 :   rc = sqlite3_exec (db,
     608             :                      "drop table ultimately_trusted_keys;",
     609             :                      NULL, NULL, &err);
     610           6 :   if (rc)
     611             :     {
     612           0 :       log_error (_("TOFU DB error"));
     613           0 :       print_further_info ("dropping ultimately_trusted_keys: %s", err);
     614           0 :       sqlite3_free (err);
     615           0 :       goto out;
     616             :     }
     617             : 
     618           6 :   rc = sqlite3_exec (db,
     619             :                      "create table if not exists"
     620             :                      " ultimately_trusted_keys (keyid);\n",
     621             :                      NULL, NULL, &err);
     622           6 :   if (rc)
     623             :     {
     624           0 :       log_error (_("TOFU DB error"));
     625           0 :       print_further_info ("creating ultimately_trusted_keys: %s", err);
     626           0 :       sqlite3_free (err);
     627           0 :       goto out;
     628             :     }
     629             : 
     630          10 :   for (ki = utks; ki; ki = ki->next)
     631             :     {
     632           4 :       format_keyid (ki->kid, KF_LONG,
     633             :                     keyid_str, sizeof (keyid_str));
     634           4 :       rc = gpgsql_exec_printf
     635             :         (db, NULL, NULL, &err,
     636             :          "insert into ultimately_trusted_keys values ('%s');",
     637             :          keyid_str);
     638           4 :       if (rc)
     639             :         {
     640           0 :           log_error (_("TOFU DB error"));
     641           0 :           print_further_info ("updating ultimately_trusted_keys: %s",
     642             :                               err);
     643           0 :           sqlite3_free (err);
     644           0 :           goto out;
     645             :         }
     646             :     }
     647             : 
     648             :  out:
     649         103 :   return rc;
     650             : }
     651             : 
     652             : /* If the DB is new, initialize it.  Otherwise, check the DB's
     653             :    version.
     654             : 
     655             :    Return 0 if the database is okay and 1 otherwise.  */
     656             : static int
     657         103 : initdb (sqlite3 *db)
     658             : {
     659         103 :   char *err = NULL;
     660             :   int rc;
     661             :   unsigned long int count;
     662         103 :   int version = -1;
     663             : 
     664         103 :   rc = sqlite3_exec (db, "begin transaction;", NULL, NULL, &err);
     665         103 :   if (rc)
     666             :     {
     667           0 :       log_error (_("error beginning transaction on TOFU database: %s\n"),
     668             :                  err);
     669           0 :       sqlite3_free (err);
     670           0 :       return 1;
     671             :     }
     672             : 
     673             :   /* If the DB has no tables, then assume this is a new DB that needs
     674             :      to be initialized.  */
     675         103 :   rc = sqlite3_exec (db,
     676             :                      "select count(*) from sqlite_master where type='table';",
     677             :                      get_single_unsigned_long_cb, &count, &err);
     678         103 :   if (rc)
     679             :     {
     680           0 :       log_error (_("error reading TOFU database: %s\n"), err);
     681           0 :       print_further_info ("query available tables");
     682           0 :       sqlite3_free (err);
     683           0 :       goto out;
     684             :     }
     685         103 :   else if (count != 0)
     686             :     /* Assume that the DB is already initialized.  Make sure the
     687             :        version is okay.  */
     688             :     {
     689          97 :       rc = sqlite3_exec (db, "select version from version;", version_check_cb,
     690             :                          &version, &err);
     691          97 :       if (rc == SQLITE_ABORT && version == 1)
     692             :         /* Happy, happy, joy, joy.  */
     693             :         {
     694          97 :           sqlite3_free (err);
     695          97 :           rc = 0;
     696          97 :           goto out;
     697             :         }
     698           0 :       else if (rc == SQLITE_ABORT && version == -1)
     699             :         /* Unsupported version.  */
     700             :         {
     701             :           /* An error message was already displayed.  */
     702           0 :           sqlite3_free (err);
     703           0 :           goto out;
     704             :         }
     705           0 :       else if (rc)
     706             :         /* Some error.  */
     707             :         {
     708           0 :           log_error (_("error determining TOFU database's version: %s\n"), err);
     709           0 :           sqlite3_free (err);
     710           0 :           goto out;
     711             :         }
     712             :       else
     713             :         {
     714             :           /* Unexpected success.  This can only happen if there are no
     715             :              rows.  (select returned 0, but expected ABORT.)  */
     716           0 :           log_error (_("error determining TOFU database's version: %s\n"),
     717             :                      gpg_strerror (GPG_ERR_NO_DATA));
     718           0 :           rc = 1;
     719           0 :           goto out;
     720             :         }
     721             :     }
     722             : 
     723             :   /* Create the version table.  */
     724           6 :   rc = sqlite3_exec (db,
     725             :                      "create table version (version INTEGER);",
     726             :                      NULL, NULL, &err);
     727           6 :   if (rc)
     728             :     {
     729           0 :       log_error (_("error initializing TOFU database: %s\n"), err);
     730           0 :       print_further_info ("create version");
     731           0 :       sqlite3_free (err);
     732           0 :       goto out;
     733             :     }
     734             : 
     735             :   /* Initialize the version table, which contains a single integer
     736             :      value.  */
     737           6 :   rc = sqlite3_exec (db,
     738             :                      "insert into version values (1);",
     739             :                      NULL, NULL, &err);
     740           6 :   if (rc)
     741             :     {
     742           0 :       log_error (_("error initializing TOFU database: %s\n"), err);
     743           0 :       print_further_info ("insert version");
     744           0 :       sqlite3_free (err);
     745           0 :       goto out;
     746             :     }
     747             : 
     748             :   /* The list of <fingerprint, email> bindings and auxiliary data.
     749             :    *
     750             :    *  OID is a unique ID identifying this binding (and used by the
     751             :    *    signatures table, see below).  Note: OIDs will never be
     752             :    *    reused.
     753             :    *
     754             :    *  FINGERPRINT: The key's fingerprint.
     755             :    *
     756             :    *  EMAIL: The normalized email address.
     757             :    *
     758             :    *  USER_ID: The unmodified user id from which EMAIL was extracted.
     759             :    *
     760             :    *  TIME: The time this binding was first observed.
     761             :    *
     762             :    *  POLICY: The trust policy (TOFU_POLICY_BAD, etc. as an integer).
     763             :    *
     764             :    *  CONFLICT is either NULL or a fingerprint.  Assume that we have
     765             :    *    a binding <0xdeadbeef, foo@example.com> and then we observe
     766             :    *    <0xbaddecaf, foo@example.com>.  There two bindings conflict
     767             :    *    (they have the same email address).  When we observe the
     768             :    *    latter binding, we warn the user about the conflict and ask
     769             :    *    for a policy decision about the new binding.  We also change
     770             :    *    the old binding's policy to ask if it was auto.  So that we
     771             :    *     know why this occurred, we also set conflict to 0xbaddecaf.
     772             :    */
     773           6 :   rc = gpgsql_exec_printf
     774             :       (db, NULL, NULL, &err,
     775             :        "create table bindings\n"
     776             :        " (oid INTEGER PRIMARY KEY AUTOINCREMENT,\n"
     777             :        "  fingerprint TEXT, email TEXT, user_id TEXT, time INTEGER,\n"
     778             :        "  policy INTEGER CHECK (policy in (%d, %d, %d, %d, %d)),\n"
     779             :        "  conflict STRING,\n"
     780             :        "  unique (fingerprint, email));\n"
     781             :        "create index bindings_fingerprint_email\n"
     782             :        " on bindings (fingerprint, email);\n"
     783             :        "create index bindings_email on bindings (email);\n",
     784             :        TOFU_POLICY_AUTO, TOFU_POLICY_GOOD, TOFU_POLICY_UNKNOWN,
     785             :        TOFU_POLICY_BAD, TOFU_POLICY_ASK);
     786           6 :   if (rc)
     787             :     {
     788           0 :       log_error (_("error initializing TOFU database: %s\n"), err);
     789           0 :       print_further_info ("create bindings");
     790           0 :       sqlite3_free (err);
     791           0 :       goto out;
     792             :     }
     793             : 
     794             :   /* The signatures that we have observed.
     795             :    *
     796             :    * BINDING refers to a record in the bindings table, which
     797             :    * describes the binding (i.e., this is a foreign key that
     798             :    * references bindings.oid).
     799             :    *
     800             :    * SIG_DIGEST is the digest stored in the signature.
     801             :    *
     802             :    * SIG_TIME is the timestamp stored in the signature.
     803             :    *
     804             :    * ORIGIN is a free-form string that describes who fed this
     805             :    * signature to GnuPG (e.g., email:claws).
     806             :    *
     807             :    * TIME is the time this signature was registered.  */
     808           6 :   rc = sqlite3_exec (db,
     809             :                          "create table signatures "
     810             :                          " (binding INTEGER NOT NULL, sig_digest TEXT,"
     811             :                          "  origin TEXT, sig_time INTEGER, time INTEGER,"
     812             :                          "  primary key (binding, sig_digest, origin));",
     813             :                          NULL, NULL, &err);
     814           6 :   if (rc)
     815             :     {
     816           0 :       log_error (_("error initializing TOFU database: %s\n"), err);
     817           0 :       print_further_info ("create signatures");
     818           0 :       sqlite3_free (err);
     819           0 :       goto out;
     820             :     }
     821             : 
     822             :  out:
     823         103 :   if (! rc)
     824             :     {
     825             :       /* Early version of the v1 format did not include the encryption
     826             :          table.  Add it.  */
     827         103 :       rc = sqlite3_exec (db,
     828             :                          "create table if not exists encryptions"
     829             :                          " (binding INTEGER NOT NULL,"
     830             :                          "  time INTEGER);"
     831             :                          "create index if not exists encryptions_binding"
     832             :                          " on encryptions (binding);\n",
     833             :                          NULL, NULL, &err);
     834         103 :       if (rc)
     835             :         {
     836           0 :           log_error (_("error creating 'encryptions' TOFU table: %s\n"),
     837             :                      err);
     838           0 :           sqlite3_free (err);
     839             :         }
     840             :     }
     841         103 :   if (! rc)
     842             :     {
     843             :       /* The effective policy for a binding.  If a key is ultimately
     844             :        * trusted, then the effective policy of all of its bindings is
     845             :        * good.  Likewise if a key is signed by an ultimately trusted
     846             :        * key, etc.  If the effective policy is NONE, then we need to
     847             :        * recompute the effective policy.  Otherwise, the effective
     848             :        * policy is considered to be up to date, i.e., effective_policy
     849             :        * is a cache of the computed policy.  */
     850         103 :       rc = gpgsql_exec_printf
     851             :         (db, NULL, NULL, &err,
     852             :          "alter table bindings"
     853             :          " add column effective_policy INTEGER"
     854             :          " DEFAULT %d"
     855             :          " CHECK (effective_policy in (%d, %d, %d, %d, %d, %d));",
     856             :          TOFU_POLICY_NONE,
     857             :          TOFU_POLICY_NONE, TOFU_POLICY_AUTO, TOFU_POLICY_GOOD,
     858             :          TOFU_POLICY_UNKNOWN, TOFU_POLICY_BAD, TOFU_POLICY_ASK);
     859         103 :       if (rc)
     860             :         {
     861          97 :           if (rc == SQLITE_ERROR)
     862             :             /* Almost certainly "duplicate column name", which we can
     863             :              * safely ignore.  */
     864          97 :             rc = 0;
     865             :           else
     866           0 :             log_error (_("adding column effective_policy to bindings DB: %s\n"),
     867             :                        err);
     868          97 :           sqlite3_free (err);
     869             :         }
     870             :     }
     871             : 
     872         103 :   if (! rc)
     873         103 :     rc = check_utks (db);
     874             : 
     875         103 :   if (rc)
     876             :     {
     877           0 :       rc = sqlite3_exec (db, "rollback;", NULL, NULL, &err);
     878           0 :       if (rc)
     879             :         {
     880           0 :           log_error (_("error rolling back transaction on TOFU database: %s\n"),
     881             :                      err);
     882           0 :           sqlite3_free (err);
     883             :         }
     884           0 :       return 1;
     885             :     }
     886             :   else
     887             :     {
     888         103 :       rc = sqlite3_exec (db, "end transaction;", NULL, NULL, &err);
     889         103 :       if (rc)
     890             :         {
     891           0 :           log_error (_("error committing transaction on TOFU database: %s\n"),
     892             :                      err);
     893           0 :           sqlite3_free (err);
     894           0 :           return 1;
     895             :         }
     896         103 :       return 0;
     897             :     }
     898             : }
     899             : 
     900             : static int
     901           0 : busy_handler (void *cookie, int call_count)
     902             : {
     903           0 :   ctrl_t ctrl = cookie;
     904           0 :   tofu_dbs_t dbs = ctrl->tofu.dbs;
     905             : 
     906             :   (void) call_count;
     907             : 
     908             :   /* Update the want-lock-file time stamp (specifically, the ctime) so
     909             :    * that the current owner knows that we (well, someone) want the
     910             :    * lock.  */
     911           0 :   if (dbs)
     912             :     {
     913             :       /* Note: we don't fail if we can't create the lock file: this
     914             :        * process will have to wait a bit longer, but otherwise nothing
     915             :        * horrible should happen.  */
     916             : 
     917             :       estream_t fp;
     918             : 
     919           0 :       fp = es_fopen (dbs->want_lock_file, "w");
     920           0 :       if (! fp)
     921           0 :         log_debug ("TOFU: Error opening '%s': %s\n",
     922           0 :                    dbs->want_lock_file, strerror (errno));
     923             :       else
     924           0 :         es_fclose (fp);
     925             :     }
     926             : 
     927             :   /* Call again.  */
     928           0 :   return 1;
     929             : }
     930             : 
     931             : /* Create a new DB handle.  Returns NULL on error.  */
     932             : /* FIXME: Change to return an error code for better reporting by the
     933             :    caller.  */
     934             : static tofu_dbs_t
     935         269 : opendbs (ctrl_t ctrl)
     936             : {
     937             :   char *filename;
     938             :   sqlite3 *db;
     939             :   int rc;
     940             : 
     941         269 :   if (!ctrl->tofu.dbs)
     942             :     {
     943         103 :       filename = make_filename (gnupg_homedir (), "tofu.db", NULL);
     944             : 
     945         103 :       rc = sqlite3_open (filename, &db);
     946         103 :       if (rc)
     947             :         {
     948           0 :           log_error (_("error opening TOFU database '%s': %s\n"),
     949             :                      filename, sqlite3_errmsg (db));
     950             :           /* Even if an error occurs, DB is guaranteed to be valid.  */
     951           0 :           sqlite3_close (db);
     952           0 :           db = NULL;
     953             :         }
     954             : 
     955             :       /* If a DB is locked wait up to 5 seconds for the lock to be cleared
     956             :          before failing.  */
     957         103 :       if (db)
     958             :         {
     959         103 :           sqlite3_busy_timeout (db, 5 * 1000);
     960         103 :           sqlite3_busy_handler (db, busy_handler, ctrl);
     961             :         }
     962             : 
     963         103 :       if (db && initdb (db))
     964             :         {
     965           0 :           sqlite3_close (db);
     966           0 :           db = NULL;
     967             :         }
     968             : 
     969         103 :       if (db)
     970             :         {
     971         103 :           ctrl->tofu.dbs = xmalloc_clear (sizeof *ctrl->tofu.dbs);
     972         103 :           ctrl->tofu.dbs->db = db;
     973         103 :           ctrl->tofu.dbs->want_lock_file = xasprintf ("%s-want-lock", filename);
     974             :         }
     975             : 
     976         103 :       xfree (filename);
     977             :     }
     978             :   else
     979         166 :     log_assert (ctrl->tofu.dbs->db);
     980             : 
     981         269 :   return ctrl->tofu.dbs;
     982             : }
     983             : 
     984             : 
     985             : /* Release all of the resources associated with the DB handle.  */
     986             : void
     987        1177 : tofu_closedbs (ctrl_t ctrl)
     988             : {
     989             :   tofu_dbs_t dbs;
     990             :   sqlite3_stmt **statements;
     991             : 
     992        1177 :   dbs = ctrl->tofu.dbs;
     993        1177 :   if (!dbs)
     994        2251 :     return;  /* Not initialized.  */
     995             : 
     996         103 :   log_assert (dbs->in_transaction == 0);
     997             : 
     998         103 :   end_transaction (ctrl, 2);
     999             : 
    1000             :   /* Arghh, that is a surprising use of the struct.  */
    1001        1442 :   for (statements = (void *) &dbs->s;
    1002        1339 :        (void *) statements < (void *) &(&dbs->s)[1];
    1003        1236 :        statements ++)
    1004        1236 :     sqlite3_finalize (*statements);
    1005             : 
    1006         103 :   sqlite3_close (dbs->db);
    1007         103 :   xfree (dbs->want_lock_file);
    1008         103 :   xfree (dbs);
    1009         103 :   ctrl->tofu.dbs = NULL;
    1010             : }
    1011             : 
    1012             : 
    1013             : /* Collect results of a select min (foo) ...; style query.  Aborts if
    1014             :    the argument is not a valid integer (or real of the form X.0).  */
    1015             : static int
    1016           4 : get_single_long_cb (void *cookie, int argc, char **argv, char **azColName)
    1017             : {
    1018           4 :   long *count = cookie;
    1019             : 
    1020             :   (void) azColName;
    1021             : 
    1022           4 :   log_assert (argc == 1);
    1023             : 
    1024           4 :   if (string_to_long (count, argv[0], 0, __LINE__))
    1025           0 :     return 1; /* Abort.  */
    1026             : 
    1027           4 :   return 0;
    1028             : }
    1029             : 
    1030             : static int
    1031           4 : get_single_long_cb2 (void *cookie, int argc, char **argv, char **azColName,
    1032             :                      sqlite3_stmt *stmt)
    1033             : {
    1034             :   (void) stmt;
    1035           4 :   return get_single_long_cb (cookie, argc, argv, azColName);
    1036             : }
    1037             : 
    1038             : /* Record (or update) a trust policy about a (possibly new)
    1039             :    binding.
    1040             : 
    1041             :    If SHOW_OLD is set, the binding's old policy is displayed.  */
    1042             : static gpg_error_t
    1043          37 : record_binding (tofu_dbs_t dbs, const char *fingerprint, const char *email,
    1044             :                 const char *user_id,
    1045             :                 enum tofu_policy policy, enum tofu_policy effective_policy,
    1046             :                 const char *conflict, int set_conflict,
    1047             :                 int show_old, time_t now)
    1048             : {
    1049          37 :   char *fingerprint_pp = format_hexfingerprint (fingerprint, NULL, 0);
    1050             :   gpg_error_t rc;
    1051          37 :   char *err = NULL;
    1052             : 
    1053          37 :   if (! (policy == TOFU_POLICY_AUTO
    1054           8 :          || policy == TOFU_POLICY_GOOD
    1055           6 :          || policy == TOFU_POLICY_UNKNOWN
    1056           4 :          || policy == TOFU_POLICY_BAD
    1057             :          || policy == TOFU_POLICY_ASK))
    1058           0 :     log_bug ("%s: Bad value for policy (%d)!\n", __func__, policy);
    1059             : 
    1060             : 
    1061          37 :   if (DBG_TRUST || show_old)
    1062             :     {
    1063             :       /* Get the old policy.  Since this is just for informational
    1064             :        * purposes, there is no need to start a transaction or to die
    1065             :        * if there is a failure.  */
    1066             : 
    1067             :       /* policy_old needs to be a long and not an enum tofu_policy,
    1068             :          because we pass it by reference to get_single_long_cb2, which
    1069             :          expects a long.  */
    1070           5 :       long policy_old = TOFU_POLICY_NONE;
    1071             : 
    1072           5 :       rc = gpgsql_stepx
    1073             :         (dbs->db, &dbs->s.record_binding_get_old_policy,
    1074             :          get_single_long_cb2, &policy_old, &err,
    1075             :          "select policy from bindings where fingerprint = ? and email = ?",
    1076             :          GPGSQL_ARG_STRING, fingerprint, GPGSQL_ARG_STRING, email,
    1077             :          GPGSQL_ARG_END);
    1078           5 :       if (rc)
    1079             :         {
    1080           0 :           log_debug ("TOFU: Error reading from binding database"
    1081             :                      " (reading policy for <key: %s, user id: %s>): %s\n",
    1082             :                      fingerprint, email, err);
    1083           0 :           sqlite3_free (err);
    1084             :         }
    1085             : 
    1086           5 :       if (policy_old != TOFU_POLICY_NONE)
    1087           4 :         (show_old ? log_info : log_debug)
    1088             :           ("Changing TOFU trust policy for binding"
    1089             :            " <key: %s, user id: %s> from %s to %s.\n",
    1090             :            fingerprint, show_old ? user_id : email,
    1091             :            tofu_policy_str (policy_old),
    1092             :            tofu_policy_str (policy));
    1093             :       else
    1094           1 :         (show_old ? log_info : log_debug)
    1095             :           ("Setting TOFU trust policy for new binding"
    1096             :            " <key: %s, user id: %s> to %s.\n",
    1097             :            fingerprint, show_old ? user_id : email,
    1098             :            tofu_policy_str (policy));
    1099             :     }
    1100             : 
    1101          37 :   if (opt.dry_run)
    1102             :     {
    1103           0 :       log_info ("TOFU database update skipped due to --dry-run\n");
    1104           0 :       rc = 0;
    1105           0 :       goto leave;
    1106             :     }
    1107             : 
    1108          37 :   rc = gpgsql_stepx
    1109             :     (dbs->db, &dbs->s.record_binding_update, NULL, NULL, &err,
    1110             :      "insert or replace into bindings\n"
    1111             :      " (oid, fingerprint, email, user_id, time,"
    1112             :      "  policy, conflict, effective_policy)\n"
    1113             :      " values (\n"
    1114             :      /* If we don't explicitly reuse the OID, then SQLite will
    1115             :       * reallocate a new one.  We just need to search for the OID
    1116             :       * based on the fingerprint and email since they are unique.  */
    1117             :      "  (select oid from bindings where fingerprint = ? and email = ?),\n"
    1118             :      "  ?, ?, ?, ?, ?,"
    1119             :      /* If SET_CONFLICT is 0, then preserve conflict's current value.  */
    1120             :      "  case ?"
    1121             :      "    when 0 then"
    1122             :      "      (select conflict from bindings where fingerprint = ? and email = ?)"
    1123             :      "    else ?"
    1124             :      "  end,"
    1125             :      "  ?);",
    1126             :      /* oid subquery.  */
    1127             :      GPGSQL_ARG_STRING, fingerprint, GPGSQL_ARG_STRING, email,
    1128             :      /* values 2 through 6.  */
    1129             :      GPGSQL_ARG_STRING, fingerprint, GPGSQL_ARG_STRING, email,
    1130             :      GPGSQL_ARG_STRING, user_id,
    1131             :      GPGSQL_ARG_LONG_LONG, (long long) now,
    1132             :      GPGSQL_ARG_INT, (int) policy,
    1133             :      /* conflict subquery.  */
    1134             :      GPGSQL_ARG_INT, set_conflict ? 1 : 0,
    1135             :      GPGSQL_ARG_STRING, fingerprint, GPGSQL_ARG_STRING, email,
    1136             :      GPGSQL_ARG_STRING, conflict ? conflict : "",
    1137             :      GPGSQL_ARG_INT, (int) effective_policy,
    1138             :      GPGSQL_ARG_END);
    1139          37 :   if (rc)
    1140             :     {
    1141           0 :       log_error (_("error updating TOFU database: %s\n"), err);
    1142           0 :       print_further_info (" insert bindings <key: %s, user id: %s> = %s",
    1143             :                           fingerprint, email, tofu_policy_str (policy));
    1144           0 :       sqlite3_free (err);
    1145           0 :       goto leave;
    1146             :     }
    1147             : 
    1148             :  leave:
    1149          37 :   xfree (fingerprint_pp);
    1150          37 :   return rc;
    1151             : }
    1152             : 
    1153             : 
    1154             : /* Collect the strings returned by a query in a simple string list.
    1155             :    Any NULL values are converted to the empty string.
    1156             : 
    1157             :    If a result has 3 rows and each row contains two columns, then the
    1158             :    results are added to the list as follows (the value is parentheses
    1159             :    is the 1-based index in the final list):
    1160             : 
    1161             :      row 1, col 2 (6)
    1162             :      row 1, col 1 (5)
    1163             :      row 2, col 2 (4)
    1164             :      row 2, col 1 (3)
    1165             :      row 3, col 2 (2)
    1166             :      row 3, col 1 (1)
    1167             : 
    1168             :    This is because add_to_strlist pushes the results onto the front of
    1169             :    the list.  The end result is that the rows are backwards, but the
    1170             :    columns are in the expected order.  */
    1171             : static int
    1172         496 : strings_collect_cb (void *cookie, int argc, char **argv, char **azColName)
    1173             : {
    1174             :   int i;
    1175         496 :   strlist_t *strlist = cookie;
    1176             : 
    1177             :   (void) azColName;
    1178             : 
    1179        1810 :   for (i = argc - 1; i >= 0; i --)
    1180        1314 :     add_to_strlist (strlist, argv[i] ? argv[i] : "");
    1181             : 
    1182         496 :   return 0;
    1183             : }
    1184             : 
    1185             : static int
    1186         354 : strings_collect_cb2 (void *cookie, int argc, char **argv, char **azColName,
    1187             :                      sqlite3_stmt *stmt)
    1188             : {
    1189             :   (void) stmt;
    1190         354 :   return strings_collect_cb (cookie, argc, argv, azColName);
    1191             : 
    1192             : }
    1193             : 
    1194             : /* Auxiliary data structure to collect statistics about
    1195             :    signatures.  */
    1196             : struct signature_stats
    1197             : {
    1198             :   struct signature_stats *next;
    1199             : 
    1200             :   /* The user-assigned policy for this binding.  */
    1201             :   enum tofu_policy policy;
    1202             : 
    1203             :   /* How long ago the signature was created (rounded to a multiple of
    1204             :      TIME_AGO_UNIT_SMALL, etc.).  */
    1205             :   long time_ago;
    1206             :   /* Number of signatures during this time.  */
    1207             :   unsigned long count;
    1208             : 
    1209             :   /* If the corresponding key/user id has been expired / revoked.  */
    1210             :   int is_expired;
    1211             :   int is_revoked;
    1212             : 
    1213             :   /* The key that generated this signature.  */
    1214             :   char fingerprint[1];
    1215             : };
    1216             : 
    1217             : static void
    1218           0 : signature_stats_free (struct signature_stats *stats)
    1219             : {
    1220           0 :   while (stats)
    1221             :     {
    1222           0 :       struct signature_stats *next = stats->next;
    1223           0 :       xfree (stats);
    1224           0 :       stats = next;
    1225             :     }
    1226           0 : }
    1227             : 
    1228             : static void
    1229           0 : signature_stats_prepend (struct signature_stats **statsp,
    1230             :                          const char *fingerprint,
    1231             :                          enum tofu_policy policy,
    1232             :                          long time_ago,
    1233             :                          unsigned long count)
    1234             : {
    1235           0 :   struct signature_stats *stats =
    1236           0 :     xmalloc_clear (sizeof (*stats) + strlen (fingerprint));
    1237             : 
    1238           0 :   stats->next = *statsp;
    1239           0 :   *statsp = stats;
    1240             : 
    1241           0 :   strcpy (stats->fingerprint, fingerprint);
    1242           0 :   stats->policy = policy;
    1243           0 :   stats->time_ago = time_ago;
    1244           0 :   stats->count = count;
    1245           0 : }
    1246             : 
    1247             : 
    1248             : /* Process rows that contain the four columns:
    1249             : 
    1250             :      <fingerprint, policy, time ago, count>.  */
    1251             : static int
    1252           0 : signature_stats_collect_cb (void *cookie, int argc, char **argv,
    1253             :                             char **azColName, sqlite3_stmt *stmt)
    1254             : {
    1255           0 :   struct signature_stats **statsp = cookie;
    1256           0 :   int i = 0;
    1257             :   enum tofu_policy policy;
    1258             :   long time_ago;
    1259             :   unsigned long count;
    1260             :   long along;
    1261             : 
    1262             :   (void) azColName;
    1263             :   (void) stmt;
    1264             : 
    1265           0 :   i ++;
    1266             : 
    1267           0 :   if (string_to_long (&along, argv[i], 0, __LINE__))
    1268           0 :     return 1;  /* Abort */
    1269           0 :   policy = along;
    1270           0 :   i ++;
    1271             : 
    1272           0 :   if (! argv[i])
    1273           0 :     time_ago = 0;
    1274             :   else
    1275             :     {
    1276           0 :       if (string_to_long (&time_ago, argv[i], 0, __LINE__))
    1277           0 :         return 1; /* Abort.  */
    1278             :     }
    1279           0 :   i ++;
    1280             : 
    1281             :   /* If time_ago is NULL, then we had no messages, but we still have a
    1282             :      single row, which count(*) turns into 1.  */
    1283           0 :   if (! argv[i - 1])
    1284           0 :     count = 0;
    1285             :   else
    1286             :     {
    1287           0 :       if (string_to_ulong (&count, argv[i], 0, __LINE__))
    1288           0 :         return 1; /* Abort */
    1289             :     }
    1290           0 :   i ++;
    1291             : 
    1292           0 :   log_assert (argc == i);
    1293             : 
    1294           0 :   signature_stats_prepend (statsp, argv[0], policy, time_ago, count);
    1295             : 
    1296           0 :   return 0;
    1297             : }
    1298             : 
    1299             : /* Convert from seconds to time units.
    1300             : 
    1301             :    Note: T should already be a multiple of TIME_AGO_UNIT_SMALL or
    1302             :    TIME_AGO_UNIT_MEDIUM or TIME_AGO_UNIT_LARGE.  */
    1303             : signed long
    1304           0 : time_ago_scale (signed long t)
    1305             : {
    1306           0 :   if (t < TIME_AGO_UNIT_MEDIUM)
    1307           0 :     return t / TIME_AGO_UNIT_SMALL;
    1308           0 :   if (t < TIME_AGO_UNIT_LARGE)
    1309           0 :     return t / TIME_AGO_UNIT_MEDIUM;
    1310           0 :   return t / TIME_AGO_UNIT_LARGE;
    1311             : }
    1312             : 
    1313             : 
    1314             : /* Format the first part of a conflict message and return that as a
    1315             :  * malloced string.  */
    1316             : static char *
    1317           0 : format_conflict_msg_part1 (int policy, strlist_t conflict_set,
    1318             :                            const char *email)
    1319             : {
    1320             :   estream_t fp;
    1321             :   char *fingerprint;
    1322             :   char *tmpstr, *text;
    1323             : 
    1324           0 :   log_assert (conflict_set);
    1325           0 :   fingerprint = conflict_set->d;
    1326             : 
    1327           0 :   fp = es_fopenmem (0, "rw,samethread");
    1328           0 :   if (!fp)
    1329           0 :     log_fatal ("error creating memory stream: %s\n",
    1330             :                gpg_strerror (gpg_error_from_syserror()));
    1331             : 
    1332           0 :   if (policy == TOFU_POLICY_NONE)
    1333             :     {
    1334           0 :       es_fprintf (fp,
    1335           0 :                   _("This is the first time the email address \"%s\" is "
    1336             :                     "being used with key %s."),
    1337             :                   email, fingerprint);
    1338           0 :       es_fputs ("  ", fp);
    1339             :     }
    1340           0 :   else if (policy == TOFU_POLICY_ASK && conflict_set->next)
    1341             :     {
    1342           0 :       int conflicts = strlist_length (conflict_set);
    1343           0 :       es_fprintf (fp, _("The email address \"%s\" is associated with %d keys!"),
    1344             :                   email, conflicts);
    1345           0 :       if (opt.verbose)
    1346           0 :         es_fprintf (fp,
    1347           0 :                     _("  Since this binding's policy was 'auto', it has been "
    1348             :                       "changed to 'ask'."));
    1349           0 :       es_fputs ("  ", fp);
    1350             :     }
    1351             : 
    1352           0 :   es_fprintf (fp,
    1353           0 :               _("Please indicate whether this email address should"
    1354             :                 " be associated with key %s or whether you think someone"
    1355             :                 " is impersonating \"%s\"."),
    1356             :               fingerprint, email);
    1357           0 :   es_fputc ('\n', fp);
    1358             : 
    1359           0 :   es_fputc (0, fp);
    1360           0 :   if (es_fclose_snatch (fp, (void **)&tmpstr, NULL))
    1361           0 :     log_fatal ("error snatching memory stream\n");
    1362           0 :   text = format_text (tmpstr, 0, 72, 80);
    1363           0 :   es_free (tmpstr);
    1364             : 
    1365           0 :   return text;
    1366             : }
    1367             : 
    1368             : 
    1369             : /* Return 1 if A signed B and B signed A.  */
    1370             : static int
    1371          47 : cross_sigs (const char *email, kbnode_t a, kbnode_t b)
    1372             : {
    1373             :   int i;
    1374             : 
    1375          47 :   PKT_public_key *a_pk = a->pkt->pkt.public_key;
    1376          47 :   PKT_public_key *b_pk = b->pkt->pkt.public_key;
    1377             : 
    1378             :   char a_keyid[33];
    1379             :   char b_keyid[33];
    1380             : 
    1381          47 :   if (DBG_TRUST)
    1382             :     {
    1383           0 :       format_keyid (pk_main_keyid (a_pk),
    1384             :                     KF_LONG, a_keyid, sizeof (a_keyid));
    1385           0 :       format_keyid (pk_main_keyid (b_pk),
    1386             :                     KF_LONG, b_keyid, sizeof (b_keyid));
    1387             :     }
    1388             : 
    1389          67 :   for (i = 0; i < 2; i ++)
    1390             :     {
    1391             :       /* See if SIGNER signed SIGNEE.  */
    1392             : 
    1393          65 :       kbnode_t signer = i == 0 ? a : b;
    1394          65 :       kbnode_t signee = i == 0 ? b : a;
    1395             : 
    1396          65 :       PKT_public_key *signer_pk = signer->pkt->pkt.public_key;
    1397          65 :       u32 *signer_kid = pk_main_keyid (signer_pk);
    1398             :       kbnode_t n;
    1399             : 
    1400          65 :       int saw_email = 0;
    1401             : 
    1402             :       /* Iterate over SIGNEE's keyblock and see if there is a valid
    1403             :          signature from SIGNER.  */
    1404         413 :       for (n = signee; n; n = n->next)
    1405             :         {
    1406             :           PKT_signature *sig;
    1407             : 
    1408         368 :           if (n->pkt->pkttype == PKT_USER_ID)
    1409             :             {
    1410          86 :               if (saw_email)
    1411             :                 /* We're done: we've processed all signatures on the
    1412             :                    user id.  */
    1413           0 :                 break;
    1414             :               else
    1415             :                 {
    1416             :                   /* See if this is the matching user id.  */
    1417          86 :                   PKT_user_id *user_id = n->pkt->pkt.user_id;
    1418          86 :                   char *email2 = email_from_user_id (user_id->name);
    1419             : 
    1420          86 :                   if (strcmp (email, email2) == 0)
    1421          65 :                     saw_email = 1;
    1422             : 
    1423          86 :                   xfree (email2);
    1424             :                 }
    1425             :             }
    1426             : 
    1427         368 :           if (! saw_email)
    1428         128 :             continue;
    1429             : 
    1430         240 :           if (n->pkt->pkttype != PKT_SIGNATURE)
    1431         110 :             continue;
    1432             : 
    1433         130 :           sig = n->pkt->pkt.signature;
    1434             : 
    1435         240 :           if (! (sig->sig_class == 0x10
    1436         110 :                  || sig->sig_class == 0x11
    1437         110 :                  || sig->sig_class == 0x12
    1438         110 :                  || sig->sig_class == 0x13))
    1439             :             /* Not a signature over a user id.  */
    1440          45 :             continue;
    1441             : 
    1442             :           /* SIG is on SIGNEE's keyblock.  If SIG was generated by the
    1443             :              signer, then it's a match.  */
    1444          85 :           if (keyid_cmp (sig->keyid, signer_kid) == 0)
    1445             :             /* Match!  */
    1446          20 :             break;
    1447             :         }
    1448          65 :       if (! n)
    1449             :         /* We didn't find a signature from signer over signee.  */
    1450             :         {
    1451          45 :           if (DBG_TRUST)
    1452           0 :             log_debug ("No cross sig between %s and %s\n",
    1453             :                        a_keyid, b_keyid);
    1454          45 :           return 0;
    1455             :         }
    1456             :     }
    1457             : 
    1458             :   /* A signed B and B signed A.  */
    1459           2 :   if (DBG_TRUST)
    1460           0 :     log_debug ("Cross sig between %s and %s\n",
    1461             :                a_keyid, b_keyid);
    1462             : 
    1463           2 :   return 1;
    1464             : }
    1465             : 
    1466             : /* Return whether the key was signed by an ultimately trusted key.  */
    1467             : static int
    1468          52 : signed_by_utk (const char *email, kbnode_t a)
    1469             : {
    1470             :   kbnode_t n;
    1471          52 :   int saw_email = 0;
    1472             : 
    1473         365 :   for (n = a; n; n = n->next)
    1474             :     {
    1475             :       PKT_signature *sig;
    1476             : 
    1477         319 :       if (n->pkt->pkttype == PKT_USER_ID)
    1478             :         {
    1479          72 :           if (saw_email)
    1480             :             /* We're done: we've processed all signatures on the
    1481             :                user id.  */
    1482           2 :             break;
    1483             :           else
    1484             :             {
    1485             :               /* See if this is the matching user id.  */
    1486          70 :               PKT_user_id *user_id = n->pkt->pkt.user_id;
    1487          70 :               char *email2 = email_from_user_id (user_id->name);
    1488             : 
    1489          70 :               if (strcmp (email, email2) == 0)
    1490          52 :                 saw_email = 1;
    1491             : 
    1492          70 :               xfree (email2);
    1493             :             }
    1494             :         }
    1495             : 
    1496         317 :       if (! saw_email)
    1497         106 :         continue;
    1498             : 
    1499         211 :       if (n->pkt->pkttype != PKT_SIGNATURE)
    1500          98 :         continue;
    1501             : 
    1502         113 :       sig = n->pkt->pkt.signature;
    1503             : 
    1504         211 :       if (! (sig->sig_class == 0x10
    1505          98 :              || sig->sig_class == 0x11
    1506          98 :              || sig->sig_class == 0x12
    1507          98 :              || sig->sig_class == 0x13))
    1508             :         /* Not a signature over a user id.  */
    1509          46 :         continue;
    1510             : 
    1511             :       /* SIG is on SIGNEE's keyblock.  If SIG was generated by the
    1512             :          signer, then it's a match.  */
    1513          67 :       if (tdb_keyid_is_utk (sig->keyid))
    1514             :         {
    1515             :           /* Match!  */
    1516           4 :           if (DBG_TRUST)
    1517           0 :             log_debug ("TOFU: %s is signed by an ultimately trusted key.\n",
    1518           0 :                        pk_keyid_str (a->pkt->pkt.public_key));
    1519             : 
    1520           4 :           return 1;
    1521             :         }
    1522             :     }
    1523             : 
    1524          48 :   if (DBG_TRUST)
    1525           0 :     log_debug ("TOFU: %s is NOT signed by an ultimately trusted key.\n",
    1526           0 :                pk_keyid_str (a->pkt->pkt.public_key));
    1527             : 
    1528          48 :   return 0;
    1529             : }
    1530             : 
    1531             : 
    1532             : enum
    1533             :   {
    1534             :     BINDING_NEW = 1 << 0,
    1535             :     BINDING_CONFLICT = 1 << 1,
    1536             :     BINDING_EXPIRED = 1 << 2,
    1537             :     BINDING_REVOKED = 1 << 3
    1538             :   };
    1539             : 
    1540             : 
    1541             : /* Ask the user about the binding.  There are three ways we could end
    1542             :  * up here:
    1543             :  *
    1544             :  *   - This is a new binding and there is a conflict
    1545             :  *     (policy == TOFU_POLICY_NONE && conflict_set_count > 1),
    1546             :  *
    1547             :  *   - This is a new binding and opt.tofu_default_policy is set to
    1548             :  *     ask.  (policy == TOFU_POLICY_NONE && opt.tofu_default_policy ==
    1549             :  *     TOFU_POLICY_ASK), or,
    1550             :  *
    1551             :  *   - The policy is ask (the user deferred last time) (policy ==
    1552             :  *     TOFU_POLICY_ASK).
    1553             :  *
    1554             :  * Note: this function must not be called while in a transaction!
    1555             :  *
    1556             :  * CONFLICT_SET includes all of the conflicting bindings
    1557             :  * with FINGERPRINT first.  FLAGS is a bit-wise or of
    1558             :  * BINDING_NEW, etc.
    1559             :  */
    1560             : static void
    1561           0 : ask_about_binding (ctrl_t ctrl,
    1562             :                    enum tofu_policy *policy,
    1563             :                    int *trust_level,
    1564             :                    strlist_t conflict_set,
    1565             :                    const char *fingerprint,
    1566             :                    const char *email,
    1567             :                    const char *user_id,
    1568             :                    time_t now)
    1569             : {
    1570             :   tofu_dbs_t dbs;
    1571             :   strlist_t iter;
    1572           0 :   int conflict_set_count = strlist_length (conflict_set);
    1573           0 :   char *sqerr = NULL;
    1574             :   int rc;
    1575             :   estream_t fp;
    1576           0 :   strlist_t other_user_ids = NULL;
    1577           0 :   struct signature_stats *stats = NULL;
    1578           0 :   struct signature_stats *stats_iter = NULL;
    1579           0 :   char *prompt = NULL;
    1580             :   char *choices;
    1581             : 
    1582           0 :   dbs = ctrl->tofu.dbs;
    1583           0 :   log_assert (dbs);
    1584           0 :   log_assert (dbs->in_transaction == 0);
    1585             : 
    1586           0 :   fp = es_fopenmem (0, "rw,samethread");
    1587           0 :   if (!fp)
    1588           0 :     log_fatal ("error creating memory stream: %s\n",
    1589             :                gpg_strerror (gpg_error_from_syserror()));
    1590             : 
    1591             :   {
    1592           0 :     char *text = format_conflict_msg_part1 (*policy, conflict_set, email);
    1593           0 :     es_fputs (text, fp);
    1594           0 :     es_fputc ('\n', fp);
    1595           0 :     xfree (text);
    1596             :   }
    1597             : 
    1598           0 :   begin_transaction (ctrl, 0);
    1599             : 
    1600             :   /* Find other user ids associated with this key and whether the
    1601             :    * bindings are marked as good or bad.  */
    1602           0 :   rc = gpgsql_stepx
    1603             :     (dbs->db, &dbs->s.get_trust_gather_other_user_ids,
    1604             :      strings_collect_cb2, &other_user_ids, &sqerr,
    1605             :      "select user_id, policy from bindings where fingerprint = ?;",
    1606             :      GPGSQL_ARG_STRING, fingerprint, GPGSQL_ARG_END);
    1607           0 :   if (rc)
    1608             :     {
    1609           0 :       log_error (_("error gathering other user IDs: %s\n"), sqerr);
    1610           0 :       sqlite3_free (sqerr);
    1611           0 :       sqerr = NULL;
    1612           0 :       rc = gpg_error (GPG_ERR_GENERAL);
    1613             :     }
    1614             : 
    1615           0 :   if (other_user_ids)
    1616             :     {
    1617             :       strlist_t strlist_iter;
    1618             : 
    1619           0 :       es_fprintf (fp, _("This key's user IDs:\n"));
    1620           0 :       for (strlist_iter = other_user_ids;
    1621             :            strlist_iter;
    1622           0 :            strlist_iter = strlist_iter->next)
    1623             :         {
    1624           0 :           char *other_user_id = strlist_iter->d;
    1625             :           char *other_thing;
    1626             :           enum tofu_policy other_policy;
    1627             : 
    1628           0 :           log_assert (strlist_iter->next);
    1629           0 :           strlist_iter = strlist_iter->next;
    1630           0 :           other_thing = strlist_iter->d;
    1631             : 
    1632           0 :           other_policy = atoi (other_thing);
    1633             : 
    1634           0 :           es_fprintf (fp, "  %s (", other_user_id);
    1635           0 :           es_fprintf (fp, _("policy: %s"), tofu_policy_str (other_policy));
    1636           0 :           es_fprintf (fp, ")\n");
    1637             :         }
    1638           0 :       es_fprintf (fp, "\n");
    1639             : 
    1640           0 :       free_strlist (other_user_ids);
    1641             :     }
    1642             : 
    1643             :   /* Get the stats for all the keys in CONFLICT_SET.  */
    1644           0 :   strlist_rev (&conflict_set);
    1645           0 :   for (iter = conflict_set; iter && ! rc; iter = iter->next)
    1646             :     {
    1647             : #define STATS_SQL(table, time, sign)                         \
    1648             :          "select fingerprint, policy, time_ago, count(*)\n" \
    1649             :          " from\n" \
    1650             :          "  (select bindings.*,\n" \
    1651             :          "     "sign" case\n" \
    1652             :          "       when delta ISNULL then 1\n" \
    1653             :          /* From the future (but if its just a couple of hours in the \
    1654             :           * future don't turn it into a warning)?  Or should we use \
    1655             :           * small, medium or large units?  (Note: whatever we do, we \
    1656             :           * keep the value in seconds.  Then when we group, everything \
    1657             :           * that rounds to the same number of seconds is grouped.)  */ \
    1658             :          "      when delta < -("STRINGIFY (TIME_AGO_FUTURE_IGNORE)") then 2\n" \
    1659             :          "      when delta < ("STRINGIFY (TIME_AGO_SMALL_THRESHOLD)")\n" \
    1660             :          "       then 3\n" \
    1661             :          "      when delta < ("STRINGIFY (TIME_AGO_MEDIUM_THRESHOLD)")\n" \
    1662             :          "       then 4\n" \
    1663             :          "      when delta < ("STRINGIFY (TIME_AGO_LARGE_THRESHOLD)")\n" \
    1664             :          "       then 5\n" \
    1665             :          "      else 6\n" \
    1666             :          "     end time_ago,\n" \
    1667             :          "    delta time_ago_raw\n" \
    1668             :          "   from bindings\n" \
    1669             :          "   left join\n" \
    1670             :          "     (select *,\n" \
    1671             :          "        cast(? - " time " as real) delta\n" \
    1672             :          "       from " table ") ss\n" \
    1673             :          "    on ss.binding = bindings.oid)\n" \
    1674             :          " where email = ? and fingerprint = ?\n" \
    1675             :          " group by time_ago\n" \
    1676             :          /* Make sure the current key is first.  */ \
    1677             :          " order by time_ago desc;\n"
    1678             : 
    1679             :       /* Use the time when we saw the signature, not when the
    1680             :          signature was created as that can be forged.  */
    1681           0 :       rc = gpgsql_stepx
    1682             :         (dbs->db, &dbs->s.get_trust_gather_signature_stats,
    1683             :          signature_stats_collect_cb, &stats, &sqerr,
    1684             :          STATS_SQL ("signatures", "time", ""),
    1685             :          GPGSQL_ARG_LONG_LONG, (long long) now,
    1686             :          GPGSQL_ARG_STRING, email,
    1687           0 :          GPGSQL_ARG_STRING, iter->d,
    1688             :          GPGSQL_ARG_END);
    1689           0 :       if (rc)
    1690             :         {
    1691           0 :           rc = gpg_error (GPG_ERR_GENERAL);
    1692           0 :           break;
    1693             :         }
    1694             : 
    1695           0 :       if (!stats || strcmp (iter->d, stats->fingerprint) != 0)
    1696             :         /* No stats for this binding.  Add a dummy entry.  */
    1697           0 :         signature_stats_prepend (&stats, iter->d, TOFU_POLICY_AUTO, 1, 1);
    1698             : 
    1699           0 :       rc = gpgsql_stepx
    1700             :         (dbs->db, &dbs->s.get_trust_gather_encryption_stats,
    1701             :          signature_stats_collect_cb, &stats, &sqerr,
    1702             :          STATS_SQL ("encryptions", "time", "-"),
    1703             :          GPGSQL_ARG_LONG_LONG, (long long) now,
    1704             :          GPGSQL_ARG_STRING, email,
    1705           0 :          GPGSQL_ARG_STRING, iter->d,
    1706             :          GPGSQL_ARG_END);
    1707           0 :       if (rc)
    1708             :         {
    1709           0 :           rc = gpg_error (GPG_ERR_GENERAL);
    1710           0 :           break;
    1711             :         }
    1712             : 
    1713             : #undef STATS_SQL
    1714             : 
    1715           0 :       if (!stats || strcmp (iter->d, stats->fingerprint) != 0
    1716           0 :           || stats->time_ago > 0)
    1717             :         /* No stats for this binding.  Add a dummy entry.  */
    1718           0 :         signature_stats_prepend (&stats, iter->d, TOFU_POLICY_AUTO, -1, 1);
    1719             :     }
    1720           0 :   end_transaction (ctrl, 0);
    1721           0 :   strlist_rev (&conflict_set);
    1722           0 :   if (rc)
    1723             :     {
    1724             :       strlist_t strlist_iter;
    1725             : 
    1726           0 :       log_error (_("error gathering signature stats: %s\n"), sqerr);
    1727           0 :       sqlite3_free (sqerr);
    1728           0 :       sqerr = NULL;
    1729             : 
    1730           0 :       es_fprintf (fp, ngettext("The email address \"%s\" is"
    1731             :                                " associated with %d key:\n",
    1732             :                                "The email address \"%s\" is"
    1733             :                                " associated with %d keys:\n",
    1734             :                                conflict_set_count),
    1735             :                   email, conflict_set_count);
    1736           0 :       for (strlist_iter = conflict_set;
    1737             :            strlist_iter;
    1738           0 :            strlist_iter = strlist_iter->next)
    1739           0 :         es_fprintf (fp, "  %s\n", strlist_iter->d);
    1740             :     }
    1741             :   else
    1742             :     {
    1743           0 :       char *key = NULL;
    1744             :       strlist_t binding;
    1745           0 :       int seen_in_past = 0;
    1746             : 
    1747           0 :       es_fprintf (fp, _("Statistics for keys"
    1748             :                         " with the email address \"%s\":\n"),
    1749             :                   email);
    1750           0 :       for (stats_iter = stats; stats_iter; stats_iter = stats_iter->next)
    1751             :         {
    1752             : #if 0
    1753             :           log_debug ("%s: time_ago: %ld; count: %ld\n",
    1754             :                      stats_iter->fingerprint,
    1755             :                      stats_iter->time_ago,
    1756             :                      stats_iter->count);
    1757             : #endif
    1758             : 
    1759           0 :           if (! key || strcmp (key, stats_iter->fingerprint))
    1760             :             {
    1761             :               int this_key;
    1762             :               char *key_pp;
    1763             : 
    1764           0 :               key = stats_iter->fingerprint;
    1765           0 :               this_key = strcmp (key, fingerprint) == 0;
    1766           0 :               key_pp = format_hexfingerprint (key, NULL, 0);
    1767           0 :               es_fprintf (fp, "  %s (", key_pp);
    1768             : 
    1769             :               /* Find the associated binding.  */
    1770           0 :               for (binding = conflict_set;
    1771             :                    binding;
    1772           0 :                    binding = binding->next)
    1773           0 :                 if (strcmp (key, binding->d) == 0)
    1774           0 :                   break;
    1775           0 :               log_assert (binding);
    1776             : 
    1777           0 :               if ((binding->flags & BINDING_REVOKED))
    1778             :                 {
    1779           0 :                   es_fprintf (fp, _("revoked"));
    1780           0 :                   es_fprintf (fp, _(", "));
    1781             :                 }
    1782           0 :               else if ((binding->flags & BINDING_EXPIRED))
    1783             :                 {
    1784           0 :                   es_fprintf (fp, _("expired"));
    1785           0 :                   es_fprintf (fp, _(", "));
    1786             :                 }
    1787             : 
    1788           0 :               if (this_key)
    1789           0 :                 es_fprintf (fp, _("this key"));
    1790             :               else
    1791           0 :                 es_fprintf (fp, _("policy: %s"),
    1792             :                             tofu_policy_str (stats_iter->policy));
    1793           0 :               es_fputs ("):\n", fp);
    1794           0 :               xfree (key_pp);
    1795             : 
    1796           0 :               seen_in_past = 0;
    1797             :             }
    1798             : 
    1799           0 :           if (labs(stats_iter->time_ago) == 1)
    1800             :             {
    1801             :               /* The 1 in this case is the NULL entry.  */
    1802           0 :               log_assert (stats_iter->count == 1);
    1803           0 :               stats_iter->count = 0;
    1804             :             }
    1805           0 :           seen_in_past += stats_iter->count;
    1806             : 
    1807           0 :           es_fputs ("    ", fp);
    1808             :           /* TANSLATORS: This string is concatenated with one of
    1809             :            * the day/week/month strings to form one sentence.  */
    1810           0 :           if (stats_iter->time_ago > 0)
    1811           0 :             es_fprintf (fp, ngettext("Verified %d message",
    1812             :                                      "Verified %d messages",
    1813             :                                      seen_in_past), seen_in_past);
    1814             :           else
    1815           0 :             es_fprintf (fp, ngettext("Encrypted %d message",
    1816             :                                      "Encrypted %d messages",
    1817             :                                      seen_in_past), seen_in_past);
    1818             : 
    1819           0 :           if (!stats_iter->count)
    1820           0 :             es_fputs (".", fp);
    1821           0 :           else if (labs(stats_iter->time_ago) == 2)
    1822             :             {
    1823           0 :               es_fprintf (fp, "in the future.");
    1824             :               /* Reset it.  */
    1825           0 :               seen_in_past = 0;
    1826             :             }
    1827             :           else
    1828             :             {
    1829           0 :               if (labs(stats_iter->time_ago) == 3)
    1830           0 :                 es_fprintf (fp, ngettext(" over the past day.",
    1831             :                                          " over the past %d days.",
    1832             :                                          TIME_AGO_SMALL_THRESHOLD
    1833             :                                          / TIME_AGO_UNIT_SMALL),
    1834             :                             TIME_AGO_SMALL_THRESHOLD
    1835             :                             / TIME_AGO_UNIT_SMALL);
    1836           0 :               else if (labs(stats_iter->time_ago) == 4)
    1837           0 :                 es_fprintf (fp, ngettext(" over the past month.",
    1838             :                                          " over the past %d months.",
    1839             :                                          TIME_AGO_MEDIUM_THRESHOLD
    1840             :                                          / TIME_AGO_UNIT_MEDIUM),
    1841             :                             TIME_AGO_MEDIUM_THRESHOLD
    1842             :                             / TIME_AGO_UNIT_MEDIUM);
    1843           0 :               else if (labs(stats_iter->time_ago) == 5)
    1844           0 :                 es_fprintf (fp, ngettext(" over the past year.",
    1845             :                                          " over the past %d years.",
    1846             :                                          TIME_AGO_LARGE_THRESHOLD
    1847             :                                          / TIME_AGO_UNIT_LARGE),
    1848             :                             TIME_AGO_LARGE_THRESHOLD
    1849             :                             / TIME_AGO_UNIT_LARGE);
    1850           0 :               else if (labs(stats_iter->time_ago) == 6)
    1851           0 :                 es_fprintf (fp, _(" in the past."));
    1852             :               else
    1853           0 :                 log_assert (! "Broken SQL.\n");
    1854             :             }
    1855           0 :           es_fputs ("\n", fp);
    1856             :         }
    1857             :     }
    1858             : 
    1859           0 :   if (conflict_set_count > 1 || (conflict_set->flags & BINDING_CONFLICT))
    1860             :     {
    1861             :       /* This is a conflict.  */
    1862             : 
    1863             :       /* TRANSLATORS: Please translate the text found in the source
    1864             :        * file below.  We don't directly internationalize that text so
    1865             :        * that we can tweak it without breaking translations.  */
    1866           0 :       char *text = _("TOFU detected a binding conflict");
    1867             :       char *textbuf;
    1868           0 :       if (!strcmp (text, "TOFU detected a binding conflict"))
    1869             :         {
    1870             :           /* No translation.  Use the English text.  */
    1871           0 :           text =
    1872             :             "Normally, an email address is associated with a single key.  "
    1873             :             "However, people sometimes generate a new key if "
    1874             :             "their key is too old or they think it might be compromised.  "
    1875             :             "Alternatively, a new key may indicate a man-in-the-middle "
    1876             :             "attack!  Before accepting this association, you should talk to or "
    1877             :             "call the person to make sure this new key is legitimate.";
    1878             :         }
    1879           0 :       textbuf = format_text (text, 0, 72, 80);
    1880           0 :       es_fprintf (fp, "\n%s\n", textbuf);
    1881           0 :       xfree (textbuf);
    1882             :     }
    1883             : 
    1884           0 :   es_fputc ('\n', fp);
    1885             : 
    1886             :   /* Add a NUL terminator.  */
    1887           0 :   es_fputc (0, fp);
    1888           0 :   if (es_fclose_snatch (fp, (void **) &prompt, NULL))
    1889           0 :     log_fatal ("error snatching memory stream\n");
    1890             : 
    1891             :   /* I think showing the large message once is sufficient.  If we
    1892             :    * would move it right before the cpr_get many lines will scroll
    1893             :    * away and the user might not realize that he merely entered a
    1894             :    * wrong choise (because he does not see that either).  As a small
    1895             :    * benefit we allow C-L to redisplay everything.  */
    1896           0 :   tty_printf ("%s", prompt);
    1897             : 
    1898             :   /* Suspend any transaction: it could take a while until the user
    1899             :      responds.  */
    1900           0 :   tofu_suspend_batch_transaction (ctrl);
    1901             :   while (1)
    1902             :     {
    1903             :       char *response;
    1904             : 
    1905             :       /* TRANSLATORS: Two letters (normally the lower and upper case
    1906             :        * version of the hotkey) for each of the five choices.  If
    1907             :        * there is only one choice in your language, repeat it.  */
    1908           0 :       choices = _("gG" "aA" "uU" "rR" "bB");
    1909           0 :       if (strlen (choices) != 10)
    1910           0 :         log_bug ("Bad TOFU conflict translation!  Please report.");
    1911             : 
    1912           0 :       response = cpr_get
    1913             :         ("tofu.conflict",
    1914           0 :          _("(G)ood, (A)ccept once, (U)nknown, (R)eject once, (B)ad? "));
    1915           0 :       trim_spaces (response);
    1916           0 :       cpr_kill_prompt ();
    1917           0 :       if (*response == CONTROL_L)
    1918           0 :         tty_printf ("%s", prompt);
    1919           0 :       else if (!response[0])
    1920             :         /* Default to unknown.  Don't save it.  */
    1921             :         {
    1922           0 :           tty_printf (_("Defaulting to unknown."));
    1923           0 :           *policy = TOFU_POLICY_UNKNOWN;
    1924           0 :           break;
    1925             :         }
    1926           0 :       else if (!response[1])
    1927             :         {
    1928           0 :           char *choice = strchr (choices, *response);
    1929             : 
    1930           0 :           if (choice)
    1931             :             {
    1932           0 :               int c = ((size_t) choice - (size_t) choices) / 2;
    1933             : 
    1934           0 :               switch (c)
    1935             :                 {
    1936             :                 case 0: /* Good.  */
    1937           0 :                   *policy = TOFU_POLICY_GOOD;
    1938           0 :                   *trust_level = tofu_policy_to_trust_level (*policy);
    1939           0 :                   break;
    1940             :                 case 1: /* Accept once.  */
    1941           0 :                   *policy = TOFU_POLICY_ASK;
    1942           0 :                   *trust_level = tofu_policy_to_trust_level (TOFU_POLICY_GOOD);
    1943           0 :                   break;
    1944             :                 case 2: /* Unknown.  */
    1945           0 :                   *policy = TOFU_POLICY_UNKNOWN;
    1946           0 :                   *trust_level = tofu_policy_to_trust_level (*policy);
    1947           0 :                   break;
    1948             :                 case 3: /* Reject once.  */
    1949           0 :                   *policy = TOFU_POLICY_ASK;
    1950           0 :                   *trust_level = tofu_policy_to_trust_level (TOFU_POLICY_BAD);
    1951           0 :                   break;
    1952             :                 case 4: /* Bad.  */
    1953           0 :                   *policy = TOFU_POLICY_BAD;
    1954           0 :                   *trust_level = tofu_policy_to_trust_level (*policy);
    1955           0 :                   break;
    1956             :                 default:
    1957           0 :                   log_bug ("c should be between 0 and 4 but it is %d!", c);
    1958             :                 }
    1959             : 
    1960           0 :               if (record_binding (dbs, fingerprint, email, user_id,
    1961             :                                   *policy, TOFU_POLICY_NONE, NULL, 0, 0, now))
    1962             :                 {
    1963             :                   /* If there's an error registering the
    1964             :                    * binding, don't save the signature.  */
    1965           0 :                   *trust_level = _tofu_GET_TRUST_ERROR;
    1966             :                 }
    1967           0 :               break;
    1968             :             }
    1969             :         }
    1970           0 :       xfree (response);
    1971           0 :     }
    1972             : 
    1973           0 :   tofu_resume_batch_transaction (ctrl);
    1974             : 
    1975           0 :   xfree (prompt);
    1976             : 
    1977           0 :   signature_stats_free (stats);
    1978           0 : }
    1979             : 
    1980             : /* Return the set of keys that conflict with the binding <fingerprint,
    1981             :    email> (including the binding itself, which will be first in the
    1982             :    list).  For each returned key also sets BINDING_NEW, etc.  */
    1983             : static strlist_t
    1984          48 : build_conflict_set (tofu_dbs_t dbs,
    1985             :                     PKT_public_key *pk, const char *fingerprint,
    1986             :                     const char *email)
    1987             : {
    1988             :   gpg_error_t rc;
    1989             :   char *sqerr;
    1990          48 :   strlist_t conflict_set = NULL;
    1991             :   int conflict_set_count;
    1992             :   strlist_t iter;
    1993             :   kbnode_t *kb_all;
    1994             :   KEYDB_HANDLE hd;
    1995             :   int i;
    1996             : 
    1997             :   /* Get the fingerprints of any bindings that share the email address
    1998             :    * and whether the bindings have a known conflict.
    1999             :    *
    2000             :    * Note: if the binding in question is in the DB, it will also be
    2001             :    * returned.  Thus, if the result set is empty, then <email,
    2002             :    * fingerprint> is a new binding.  */
    2003          48 :   rc = gpgsql_stepx
    2004             :     (dbs->db, &dbs->s.get_trust_bindings_with_this_email,
    2005             :      strings_collect_cb2, &conflict_set, &sqerr,
    2006             :      "select"
    2007             :      /* A binding should only appear once, but try not to break in the
    2008             :       * case of corruption.  */
    2009             :      "  fingerprint || case sum(conflict NOTNULL) when 0 then '' else '!' end"
    2010             :      " from bindings where email = ?"
    2011             :      "  group by fingerprint"
    2012             :      /* Make sure the current key comes first in the result list (if
    2013             :         it is present).  */
    2014             :      "  order by fingerprint = ? asc, fingerprint desc;",
    2015             :      GPGSQL_ARG_STRING, email,
    2016             :      GPGSQL_ARG_STRING, fingerprint,
    2017             :      GPGSQL_ARG_END);
    2018          48 :   if (rc)
    2019             :     {
    2020           0 :       log_error (_("error reading TOFU database: %s\n"), sqerr);
    2021           0 :       print_further_info ("listing fingerprints");
    2022           0 :       sqlite3_free (sqerr);
    2023           0 :       rc = gpg_error (GPG_ERR_GENERAL);
    2024           0 :       return NULL;
    2025             :     }
    2026             : 
    2027             :   /* Set BINDING_CONFLICT if the binding has a known conflict.  This
    2028             :    * allows us to distinguish between bindings where the user
    2029             :    * explicitly set the policy to ask and bindings where we set the
    2030             :    * policy to ask due to a conflict.  */
    2031         135 :   for (iter = conflict_set; iter; iter = iter->next)
    2032             :     {
    2033          87 :       int l = strlen (iter->d);
    2034          87 :       if (!(l == 2 * MAX_FINGERPRINT_LEN
    2035             :             || l == 2 * MAX_FINGERPRINT_LEN + 1))
    2036             :         {
    2037           0 :           log_error (_("TOFU db corruption detected.\n"));
    2038           0 :           print_further_info ("fingerprint '%s' is not %d characters long",
    2039           0 :                               iter->d, 2 * MAX_FINGERPRINT_LEN);
    2040             :         }
    2041             : 
    2042          87 :       if (l >= 1 && iter->d[l - 1] == '!')
    2043             :         {
    2044          86 :           iter->flags |= BINDING_CONFLICT;
    2045             :           /* Remove the !.  */
    2046          86 :           iter->d[l - 1] = 0;
    2047             :         }
    2048             :     }
    2049             : 
    2050             :   /* If the current binding has not yet been recorded, add it to the
    2051             :    * list.  (The order by above ensures that if it is present, it will
    2052             :    * be first.)  */
    2053          48 :   if (! (conflict_set && strcmp (conflict_set->d, fingerprint) == 0))
    2054             :     {
    2055           8 :       add_to_strlist (&conflict_set, fingerprint);
    2056           8 :       conflict_set->flags |= BINDING_NEW;
    2057             :     }
    2058             : 
    2059          48 :   conflict_set_count = strlist_length (conflict_set);
    2060             : 
    2061             :   /* Eliminate false conflicts.  */
    2062             : 
    2063          48 :   if (conflict_set_count == 1)
    2064             :     /* We only have a single key.  There are no false conflicts to
    2065             :        eliminate.  But, we do need to set the flags.  */
    2066             :     {
    2067          11 :       if (pk->has_expired)
    2068           0 :         conflict_set->flags |= BINDING_EXPIRED;
    2069          11 :       if (pk->flags.revoked)
    2070           0 :         conflict_set->flags |= BINDING_REVOKED;
    2071             : 
    2072          11 :       return conflict_set;
    2073             :     }
    2074             : 
    2075             :   /* If two keys have cross signatures, then they are controlled by
    2076             :    * the same person and thus are not in conflict.  */
    2077          37 :   kb_all = xcalloc (sizeof (kb_all[0]), conflict_set_count);
    2078          37 :   hd = keydb_new ();
    2079         158 :   for (i = 0, iter = conflict_set;
    2080             :        i < conflict_set_count;
    2081          84 :        i ++, iter = iter->next)
    2082             :     {
    2083          84 :       char *fp = iter->d;
    2084             :       KEYDB_SEARCH_DESC desc;
    2085             :       kbnode_t kb;
    2086             :       PKT_public_key *binding_pk;
    2087             :       kbnode_t n;
    2088             :       int found_user_id;
    2089             : 
    2090          84 :       rc = keydb_search_reset (hd);
    2091          84 :       if (rc)
    2092             :         {
    2093           0 :           log_error (_("resetting keydb: %s\n"),
    2094             :                      gpg_strerror (rc));
    2095           0 :           continue;
    2096             :         }
    2097             : 
    2098          84 :       rc = classify_user_id (fp, &desc, 0);
    2099          84 :       if (rc)
    2100             :         {
    2101           0 :           log_error (_("error parsing key specification '%s': %s\n"),
    2102             :                      fp, gpg_strerror (rc));
    2103           0 :           continue;
    2104             :         }
    2105             : 
    2106          84 :       rc = keydb_search (hd, &desc, 1, NULL);
    2107          84 :       if (rc)
    2108             :         {
    2109             :           /* Note: it is entirely possible that we don't have the key
    2110             :              corresponding to an entry in the TOFU DB.  This can
    2111             :              happen if we merge two TOFU DBs, but not the key
    2112             :              rings.  */
    2113           0 :           log_info (_("key \"%s\" not found: %s\n"),
    2114             :                     fp, gpg_strerror (rc));
    2115           0 :           continue;
    2116             :         }
    2117             : 
    2118          84 :       rc = keydb_get_keyblock (hd, &kb);
    2119          84 :       if (rc)
    2120             :         {
    2121           0 :           log_error (_("error reading keyblock: %s\n"),
    2122             :                      gpg_strerror (rc));
    2123           0 :           print_further_info ("fingerprint: %s", fp);
    2124           0 :           continue;
    2125             :         }
    2126             : 
    2127          84 :       merge_keys_and_selfsig (kb);
    2128             : 
    2129          84 :       log_assert (kb->pkt->pkttype == PKT_PUBLIC_KEY);
    2130             : 
    2131          84 :       kb_all[i] = kb;
    2132             : 
    2133             :       /* Since we have the key block, use this opportunity to figure
    2134             :        * out if the binding is expired or revoked.  */
    2135          84 :       binding_pk = kb->pkt->pkt.public_key;
    2136             : 
    2137             :       /* The binding is always expired/revoked if the key is
    2138             :        * expired/revoked.  */
    2139          84 :       if (binding_pk->has_expired)
    2140           0 :         iter->flags |= BINDING_EXPIRED;
    2141          84 :       if (binding_pk->flags.revoked)
    2142           0 :         iter->flags |= BINDING_REVOKED;
    2143             : 
    2144             :       /* The binding is also expired/revoked if the user id is
    2145             :        * expired/revoked.  */
    2146          84 :       n = kb;
    2147          84 :       found_user_id = 0;
    2148         273 :       while ((n = find_next_kbnode (n, PKT_USER_ID)) && ! found_user_id)
    2149             :         {
    2150         105 :           PKT_user_id *user_id2 = n->pkt->pkt.user_id;
    2151             :           char *email2;
    2152             : 
    2153         105 :           if (user_id2->attrib_data)
    2154           0 :             continue;
    2155             : 
    2156         105 :           email2 = email_from_user_id (user_id2->name);
    2157             : 
    2158         105 :           if (strcmp (email, email2) == 0)
    2159             :             {
    2160          84 :               found_user_id = 1;
    2161             : 
    2162          84 :               if (user_id2->is_revoked)
    2163           0 :                 iter->flags |= BINDING_REVOKED;
    2164          84 :               if (user_id2->is_expired)
    2165           0 :                 iter->flags |= BINDING_EXPIRED;
    2166             :             }
    2167             : 
    2168         105 :           xfree (email2);
    2169             :         }
    2170             : 
    2171          84 :       if (! found_user_id)
    2172             :         {
    2173           0 :           log_info (_("TOFU db corruption detected.\n"));
    2174           0 :           print_further_info ("user id '%s' not on key block '%s'",
    2175             :                               email, fingerprint);
    2176             :         }
    2177             :     }
    2178          37 :   keydb_release (hd);
    2179             : 
    2180             :   /* Now that we have the key blocks, check for cross sigs.  */
    2181             :   {
    2182             :     int j;
    2183             :     strlist_t *prevp;
    2184             :     strlist_t iter_next;
    2185          37 :     int die[conflict_set_count];
    2186             : 
    2187          37 :     memset (die, 0, sizeof (die));
    2188             : 
    2189         121 :     for (i = 0; i < conflict_set_count; i ++)
    2190             :       {
    2191             :         /* Look for cross sigs between this key (i == 0) or a key
    2192             :          * that has cross sigs with i == 0 (i.e., transitively) */
    2193          84 :         if (! (i == 0 || die[i]))
    2194          45 :           continue;
    2195             : 
    2196          86 :         for (j = i + 1; j < conflict_set_count; j ++)
    2197             :           /* Be careful: we might not have a key block for a key.  */
    2198          47 :           if (kb_all[i] && kb_all[j] && cross_sigs (email, kb_all[i], kb_all[j]))
    2199           2 :             die[j] = 1;
    2200             :       }
    2201             : 
    2202             :     /* Free unconflicting bindings (and all of the key blocks).  */
    2203         158 :     for (iter = conflict_set, prevp = &conflict_set, i = 0;
    2204             :          iter;
    2205          84 :          iter = iter_next, i ++)
    2206             :       {
    2207          84 :         iter_next = iter->next;
    2208             : 
    2209          84 :         release_kbnode (kb_all[i]);
    2210             : 
    2211          84 :         if (die[i])
    2212             :           {
    2213           2 :             *prevp = iter_next;
    2214           2 :             iter->next = NULL;
    2215           2 :             free_strlist (iter);
    2216           2 :             conflict_set_count --;
    2217             :           }
    2218             :         else
    2219             :           {
    2220          82 :             prevp = &iter->next;
    2221             :           }
    2222             :       }
    2223             : 
    2224             :     /* We shouldn't have removed the head.  */
    2225          37 :     log_assert (conflict_set);
    2226          37 :     log_assert (conflict_set_count >= 1);
    2227             :   }
    2228          37 :   xfree (kb_all);
    2229             : 
    2230          37 :   if (DBG_TRUST)
    2231             :     {
    2232           0 :       log_debug ("binding <key: %s, email: %s> conflicts:\n",
    2233             :                  fingerprint, email);
    2234           0 :       for (iter = conflict_set; iter; iter = iter->next)
    2235             :         {
    2236           0 :           log_debug ("  %s:%s%s%s%s\n",
    2237           0 :                      iter->d,
    2238           0 :                      (iter->flags & BINDING_NEW) ? " new" : "",
    2239           0 :                      (iter->flags & BINDING_CONFLICT) ? " known_conflict" : "",
    2240           0 :                      (iter->flags & BINDING_EXPIRED) ? " expired" : "",
    2241           0 :                      (iter->flags & BINDING_REVOKED) ? " revoked" : "");
    2242             :         }
    2243             :     }
    2244             : 
    2245          37 :   return conflict_set;
    2246             : }
    2247             : 
    2248             : 
    2249             : /* Return the effective policy for the binding <FINGERPRINT, EMAIL>
    2250             :  * (email has already been normalized) and any conflict information in
    2251             :  * *CONFLICT_SETP, if CONFLICT_SETP is not NULL.  Returns
    2252             :  * _tofu_GET_POLICY_ERROR if an error occurs.  */
    2253             : static enum tofu_policy
    2254         275 : get_policy (tofu_dbs_t dbs, PKT_public_key *pk,
    2255             :             const char *fingerprint, const char *user_id, const char *email,
    2256             :             strlist_t *conflict_setp, time_t now)
    2257             : {
    2258             :   int rc;
    2259         275 :   char *err = NULL;
    2260         275 :   strlist_t results = NULL;
    2261         275 :   enum tofu_policy policy = _tofu_GET_POLICY_ERROR;
    2262         275 :   enum tofu_policy effective_policy_orig = TOFU_POLICY_NONE;
    2263         275 :   enum tofu_policy effective_policy = _tofu_GET_POLICY_ERROR;
    2264             :   long along;
    2265         275 :   char *conflict_orig = NULL;
    2266         275 :   char *conflict = NULL;
    2267         275 :   strlist_t conflict_set = NULL;
    2268             :   int conflict_set_count;
    2269             : 
    2270             :   /* Check if the <FINGERPRINT, EMAIL> binding is known
    2271             :      (TOFU_POLICY_NONE cannot appear in the DB.  Thus, if POLICY is
    2272             :      still TOFU_POLICY_NONE after executing the query, then the
    2273             :      result set was empty.)  */
    2274         275 :   rc = gpgsql_stepx (dbs->db, &dbs->s.get_policy_select_policy_and_conflict,
    2275             :                       strings_collect_cb2, &results, &err,
    2276             :                       "select policy, conflict, effective_policy from bindings\n"
    2277             :                       " where fingerprint = ? and email = ?",
    2278             :                       GPGSQL_ARG_STRING, fingerprint,
    2279             :                       GPGSQL_ARG_STRING, email,
    2280             :                       GPGSQL_ARG_END);
    2281         275 :   if (rc)
    2282             :     {
    2283           0 :       log_error (_("error reading TOFU database: %s\n"), err);
    2284           0 :       print_further_info ("reading the policy");
    2285           0 :       sqlite3_free (err);
    2286           0 :       rc = gpg_error (GPG_ERR_GENERAL);
    2287           0 :       goto out;
    2288             :     }
    2289             : 
    2290         275 :   if (strlist_length (results) == 0)
    2291             :     {
    2292             :       /* No results.  Use the defaults.  */
    2293           8 :       policy = TOFU_POLICY_NONE;
    2294           8 :       effective_policy = TOFU_POLICY_NONE;
    2295             :     }
    2296         267 :   else if (strlist_length (results) == 3)
    2297             :     {
    2298             :       /* Parse and sanity check the results.  */
    2299             : 
    2300         267 :       if (string_to_long (&along, results->d, 0, __LINE__))
    2301             :         {
    2302           0 :           log_error (_("error reading TOFU database: %s\n"),
    2303             :                      gpg_strerror (GPG_ERR_BAD_DATA));
    2304           0 :           print_further_info ("bad value for policy: %s", results->d);
    2305           0 :           goto out;
    2306             :         }
    2307         267 :       policy = along;
    2308             : 
    2309         267 :       if (! (policy == TOFU_POLICY_AUTO
    2310          84 :              || policy == TOFU_POLICY_GOOD
    2311          59 :              || policy == TOFU_POLICY_UNKNOWN
    2312          34 :              || policy == TOFU_POLICY_BAD
    2313             :              || policy == TOFU_POLICY_ASK))
    2314             :         {
    2315           0 :           log_error (_("error reading TOFU database: %s\n"),
    2316             :                      gpg_strerror (GPG_ERR_DB_CORRUPTED));
    2317           0 :           print_further_info ("invalid value for policy (%d)", policy);
    2318           0 :           effective_policy = _tofu_GET_POLICY_ERROR;
    2319           0 :           goto out;
    2320             :         }
    2321             : 
    2322         267 :       if (*results->next->d)
    2323          38 :         conflict = xstrdup (results->next->d);
    2324             : 
    2325         267 :       if (string_to_long (&along, results->next->next->d, 0, __LINE__))
    2326             :         {
    2327           0 :           log_error (_("error reading TOFU database: %s\n"),
    2328             :                      gpg_strerror (GPG_ERR_BAD_DATA));
    2329           0 :           print_further_info ("bad value for effective policy: %s",
    2330           0 :                               results->next->next->d);
    2331           0 :           goto out;
    2332             :         }
    2333         267 :       effective_policy = along;
    2334             : 
    2335         297 :       if (! (effective_policy == TOFU_POLICY_NONE
    2336         245 :              || effective_policy == TOFU_POLICY_AUTO
    2337         138 :              || effective_policy == TOFU_POLICY_GOOD
    2338          85 :              || effective_policy == TOFU_POLICY_UNKNOWN
    2339          61 :              || effective_policy == TOFU_POLICY_BAD
    2340             :              || effective_policy == TOFU_POLICY_ASK))
    2341             :         {
    2342           0 :           log_error (_("error reading TOFU database: %s\n"),
    2343             :                      gpg_strerror (GPG_ERR_DB_CORRUPTED));
    2344           0 :           print_further_info ("invalid value for effective_policy (%d)",
    2345             :                               effective_policy);
    2346           0 :           effective_policy = _tofu_GET_POLICY_ERROR;
    2347           0 :           goto out;
    2348             :         }
    2349             :     }
    2350             :   else
    2351             :     {
    2352             :       /* The result has the wrong form.  */
    2353             : 
    2354           0 :       log_error (_("error reading TOFU database: %s\n"),
    2355             :                  gpg_strerror (GPG_ERR_BAD_DATA));
    2356           0 :       print_further_info ("reading policy: expected 3 columns, got %d\n",
    2357             :                           strlist_length (results));
    2358           0 :       goto out;
    2359             :     }
    2360             : 
    2361             :   /* Save the effective policy and conflict so we know if we changed
    2362             :    * them.  */
    2363         275 :   effective_policy_orig = effective_policy;
    2364         275 :   conflict_orig = conflict;
    2365             : 
    2366             :   /* Unless there is a conflict, if the effective policy is cached,
    2367             :    * just return it.  The reason we don't do this when there is a
    2368             :    * conflict is because of the following scenario: assume A and B
    2369             :    * conflict and B has signed A's key.  Now, later we import A's
    2370             :    * signature on B.  We need to recheck A, but the signature was on
    2371             :    * B, i.e., when B changes, we invalidate B's effective policy, but
    2372             :    * we also need to invalidate A's effective policy.  Instead, we
    2373             :    * assume that conflicts are rare and don't optimize for them, which
    2374             :    * would complicate the code.  */
    2375         275 :   if (effective_policy != TOFU_POLICY_NONE && !conflict)
    2376         215 :     goto out;
    2377             : 
    2378             :   /* If the user explicitly set the policy, then respect that.  */
    2379          60 :   if (policy != TOFU_POLICY_AUTO && policy != TOFU_POLICY_NONE)
    2380             :     {
    2381           5 :       effective_policy = policy;
    2382           5 :       goto out;
    2383             :     }
    2384             : 
    2385             :   /* Unless proven wrong, assume the effective policy is 'auto'.  */
    2386          55 :   effective_policy = TOFU_POLICY_AUTO;
    2387             : 
    2388             :   /* See if the key is ultimately trusted.  */
    2389             :   {
    2390             :     u32 kid[2];
    2391             : 
    2392          55 :     keyid_from_pk (pk, kid);
    2393          55 :     if (tdb_keyid_is_utk (kid))
    2394             :       {
    2395           3 :         effective_policy = TOFU_POLICY_GOOD;
    2396           3 :         goto out;
    2397             :       }
    2398             :   }
    2399             : 
    2400             :   /* See if the key is signed by an ultimately trusted key.  */
    2401             :   {
    2402          52 :     int fingerprint_raw_len = strlen (fingerprint) / 2;
    2403          52 :     char fingerprint_raw[fingerprint_raw_len];
    2404          52 :     int len = 0;
    2405             : 
    2406          52 :     if (fingerprint_raw_len != 20
    2407         156 :         || ((len = hex2bin (fingerprint,
    2408          52 :                             fingerprint_raw, fingerprint_raw_len))
    2409          52 :             != strlen (fingerprint)))
    2410             :       {
    2411           0 :         if (DBG_TRUST)
    2412           0 :           log_debug ("TOFU: Bad fingerprint: %s (len: %zd, parsed: %d)\n",
    2413             :                      fingerprint, strlen (fingerprint), len);
    2414             :       }
    2415             :     else
    2416             :       {
    2417             :         int lookup_err;
    2418             :         kbnode_t kb;
    2419             : 
    2420         104 :         lookup_err = get_pubkey_byfprint (NULL, &kb,
    2421          52 :                                           fingerprint_raw,
    2422             :                                           fingerprint_raw_len);
    2423          52 :         if (lookup_err)
    2424             :           {
    2425           0 :             if (DBG_TRUST)
    2426           0 :               log_debug ("TOFU: Looking up %s: %s\n",
    2427             :                          fingerprint, gpg_strerror (lookup_err));
    2428             :           }
    2429             :         else
    2430             :           {
    2431          52 :             int is_signed_by_utk = signed_by_utk (email, kb);
    2432          52 :             release_kbnode (kb);
    2433          52 :             if (is_signed_by_utk)
    2434             :               {
    2435           4 :                 effective_policy = TOFU_POLICY_GOOD;
    2436           4 :                 goto out;
    2437             :               }
    2438             :           }
    2439             :       }
    2440             :   }
    2441             : 
    2442             :   /* Check for any conflicts / see if a previously discovered conflict
    2443             :    * disappeared.  The latter can happen if the conflicting bindings
    2444             :    * are now cross signed, for instance.  */
    2445             : 
    2446          48 :   conflict_set = build_conflict_set (dbs, pk, fingerprint, email);
    2447          48 :   conflict_set_count = strlist_length (conflict_set);
    2448          48 :   if (conflict_set_count == 0)
    2449             :     {
    2450             :       /* build_conflict_set should always at least return the current
    2451             :          binding.  Something went wrong.  */
    2452           0 :       effective_policy = _tofu_GET_POLICY_ERROR;
    2453           0 :       goto out;
    2454             :     }
    2455             : 
    2456          48 :   if (conflict_set_count == 1
    2457          13 :       && (conflict_set->flags & BINDING_NEW))
    2458             :     {
    2459             :       /* We've never observed a binding with this email address and we
    2460             :        * have a default policy, which is not to ask the user.  */
    2461             : 
    2462             :       /* If we've seen this binding, then we've seen this email and
    2463             :        * policy couldn't possibly be TOFU_POLICY_NONE.  */
    2464           5 :       log_assert (policy == TOFU_POLICY_NONE);
    2465             : 
    2466           5 :       if (DBG_TRUST)
    2467           0 :         log_debug ("TOFU: New binding <key: %s, user id: %s>, no conflict.\n",
    2468             :                    fingerprint, email);
    2469             : 
    2470           5 :       effective_policy = TOFU_POLICY_AUTO;
    2471           5 :       goto out;
    2472             :     }
    2473             : 
    2474          43 :   if (conflict_set_count == 1
    2475           8 :       && (conflict_set->flags & BINDING_CONFLICT))
    2476             :     {
    2477             :       /* No known conflicts now, but there was a conflict.  This means
    2478             :        * at some point, there was a conflict and we changed this
    2479             :        * binding's policy to ask and set the conflicting key.  The
    2480             :        * conflict can go away if there is not a cross sig between the
    2481             :        * two keys.  In this case, just silently clear the conflict and
    2482             :        * reset the policy to auto.  */
    2483             : 
    2484           8 :       if (DBG_TRUST)
    2485           0 :         log_debug ("TOFU: binding <key: %s, user id: %s> had a conflict, but it's been resolved (probably via  cross sig).\n",
    2486             :                    fingerprint, email);
    2487             : 
    2488           8 :       effective_policy = TOFU_POLICY_AUTO;
    2489           8 :       conflict = NULL;
    2490             : 
    2491           8 :       goto out;
    2492             :     }
    2493             : 
    2494          35 :   if (conflict_set_count == 1)
    2495             :     {
    2496             :       /* No conflicts and never marked as conflicting.  */
    2497             : 
    2498           0 :       log_assert (!conflict);
    2499             : 
    2500           0 :       effective_policy = TOFU_POLICY_AUTO;
    2501             : 
    2502           0 :       goto out;
    2503             :     }
    2504             : 
    2505             :   /* There is a conflicting key.  */
    2506          35 :   log_assert (conflict_set_count > 1);
    2507          35 :   effective_policy = TOFU_POLICY_ASK;
    2508          35 :   conflict = xstrdup (conflict_set->next->d);
    2509             : 
    2510             :  out:
    2511         275 :   log_assert (policy == _tofu_GET_POLICY_ERROR
    2512             :               || policy == TOFU_POLICY_NONE
    2513             :               || policy == TOFU_POLICY_AUTO
    2514             :               || policy == TOFU_POLICY_GOOD
    2515             :               || policy == TOFU_POLICY_UNKNOWN
    2516             :               || policy == TOFU_POLICY_BAD
    2517             :               || policy == TOFU_POLICY_ASK);
    2518             :   /* Everything but NONE.  */
    2519         275 :   log_assert (effective_policy == _tofu_GET_POLICY_ERROR
    2520             :               || effective_policy == TOFU_POLICY_AUTO
    2521             :               || effective_policy == TOFU_POLICY_GOOD
    2522             :               || effective_policy == TOFU_POLICY_UNKNOWN
    2523             :               || effective_policy == TOFU_POLICY_BAD
    2524             :               || effective_policy == TOFU_POLICY_ASK);
    2525             : 
    2526         275 :   if (effective_policy != TOFU_POLICY_ASK && conflict)
    2527           5 :     conflict = NULL;
    2528             : 
    2529             :   /* If we don't have a record of this binding, its effective policy
    2530             :    * changed, or conflict changed, update the DB.  */
    2531         275 :   if (effective_policy != _tofu_GET_POLICY_ERROR
    2532         275 :       && (/* New binding.  */
    2533             :           policy == TOFU_POLICY_NONE
    2534             :           /* effective_policy changed.  */
    2535         267 :           || effective_policy != effective_policy_orig
    2536             :           /* conflict changed.  */
    2537         244 :           || (conflict != conflict_orig
    2538          29 :               && (!conflict || !conflict_orig
    2539          29 :                   || strcmp (conflict, conflict_orig) != 0))))
    2540             :     {
    2541          32 :       if (record_binding (dbs, fingerprint, email, user_id,
    2542             :                           policy == TOFU_POLICY_NONE ? TOFU_POLICY_AUTO : policy,
    2543             :                           effective_policy, conflict, 1, 0, now) != 0)
    2544           0 :         log_error (_("error setting TOFU binding's policy"
    2545             :                      " to %s\n"), tofu_policy_str (policy));
    2546             :     }
    2547             : 
    2548             :   /* If the caller wants the set of conflicts, return it.  */
    2549         275 :   if (effective_policy == TOFU_POLICY_ASK && conflict_setp)
    2550             :     {
    2551          25 :       if (! conflict_set)
    2552           0 :         conflict_set = build_conflict_set (dbs, pk, fingerprint, email);
    2553          25 :       *conflict_setp = conflict_set;
    2554             :     }
    2555             :   else
    2556             :     {
    2557         250 :       free_strlist (conflict_set);
    2558             : 
    2559         250 :       if (conflict_setp)
    2560         179 :         *conflict_setp = NULL;
    2561             :     }
    2562             : 
    2563         275 :   xfree (conflict_orig);
    2564         275 :   if (conflict != conflict_orig)
    2565          42 :     xfree (conflict);
    2566         275 :   free_strlist (results);
    2567             : 
    2568         275 :   return effective_policy;
    2569             : }
    2570             : 
    2571             : 
    2572             : /* Return the trust level (TRUST_NEVER, etc.) for the binding
    2573             :  * <FINGERPRINT, EMAIL> (email is already normalized).  If no policy
    2574             :  * is registered, returns TOFU_POLICY_NONE.  If an error occurs,
    2575             :  * returns _tofu_GET_TRUST_ERROR.
    2576             :  *
    2577             :  * PK is the public key object for FINGERPRINT.
    2578             :  *
    2579             :  * USER_ID is the unadulterated user id.
    2580             :  *
    2581             :  * If MAY_ASK is set, then we may interact with the user.  This is
    2582             :  * necessary if there is a conflict or the binding's policy is
    2583             :  * TOFU_POLICY_ASK.  In the case of a conflict, we set the new
    2584             :  * conflicting binding's policy to TOFU_POLICY_ASK.  In either case,
    2585             :  * we return TRUST_UNDEFINED.  Note: if MAY_ASK is set, then this
    2586             :  * function must not be called while in a transaction!  */
    2587             : static enum tofu_policy
    2588         219 : get_trust (ctrl_t ctrl, PKT_public_key *pk,
    2589             :            const char *fingerprint, const char *email,
    2590             :            const char *user_id, int may_ask, time_t now)
    2591             : {
    2592         219 :   tofu_dbs_t dbs = ctrl->tofu.dbs;
    2593         219 :   int in_transaction = 0;
    2594             :   enum tofu_policy policy;
    2595             :   int rc;
    2596         219 :   char *sqerr = NULL;
    2597         219 :   strlist_t conflict_set = NULL;
    2598         219 :   int trust_level = TRUST_UNKNOWN;
    2599             :   strlist_t iter;
    2600             : 
    2601         219 :   log_assert (dbs);
    2602             : 
    2603         219 :   if (may_ask)
    2604          30 :     log_assert (dbs->in_transaction == 0);
    2605             : 
    2606         219 :   if (opt.batch)
    2607         219 :     may_ask = 0;
    2608             : 
    2609         219 :   log_assert (pk_is_primary (pk));
    2610             : 
    2611             :   /* Make sure _tofu_GET_TRUST_ERROR isn't equal to any of the trust
    2612             :      levels.  */
    2613             :   log_assert (_tofu_GET_TRUST_ERROR != TRUST_UNKNOWN
    2614             :               && _tofu_GET_TRUST_ERROR != TRUST_EXPIRED
    2615             :               && _tofu_GET_TRUST_ERROR != TRUST_UNDEFINED
    2616             :               && _tofu_GET_TRUST_ERROR != TRUST_NEVER
    2617             :               && _tofu_GET_TRUST_ERROR != TRUST_MARGINAL
    2618             :               && _tofu_GET_TRUST_ERROR != TRUST_FULLY
    2619             :               && _tofu_GET_TRUST_ERROR != TRUST_ULTIMATE);
    2620             : 
    2621             :   /* If the key is ultimately trusted, there is nothing to do.  */
    2622             :   {
    2623             :     u32 kid[2];
    2624             : 
    2625         219 :     keyid_from_pk (pk, kid);
    2626         219 :     if (tdb_keyid_is_utk (kid))
    2627             :       {
    2628          15 :         trust_level = TRUST_ULTIMATE;
    2629          15 :         goto out;
    2630             :       }
    2631             :   }
    2632             : 
    2633         204 :   begin_transaction (ctrl, 0);
    2634         204 :   in_transaction = 1;
    2635             : 
    2636         204 :   policy = get_policy (dbs, pk, fingerprint, user_id, email, &conflict_set, now);
    2637         204 :   if (policy == TOFU_POLICY_AUTO)
    2638             :     {
    2639          89 :       policy = opt.tofu_default_policy;
    2640          89 :       if (DBG_TRUST)
    2641           0 :         log_debug ("TOFU: binding <key: %s, user id: %s>'s policy is"
    2642             :                    " auto (default: %s).\n",
    2643             :                    fingerprint, email,
    2644             :                    tofu_policy_str (opt.tofu_default_policy));
    2645             :     }
    2646         204 :   switch (policy)
    2647             :     {
    2648             :     case TOFU_POLICY_AUTO:
    2649             :     case TOFU_POLICY_GOOD:
    2650             :     case TOFU_POLICY_UNKNOWN:
    2651             :     case TOFU_POLICY_BAD:
    2652             :       /* The saved judgement is auto -> auto, good, unknown or bad.
    2653             :        * We don't need to ask the user anything.  */
    2654         179 :       if (DBG_TRUST)
    2655           0 :         log_debug ("TOFU: Known binding <key: %s, user id: %s>'s policy: %s\n",
    2656             :                    fingerprint, email, tofu_policy_str (policy));
    2657         179 :       trust_level = tofu_policy_to_trust_level (policy);
    2658         179 :       goto out;
    2659             : 
    2660             :     case TOFU_POLICY_ASK:
    2661             :       /* We need to ask the user what to do.  */
    2662          25 :       break;
    2663             : 
    2664             :     case _tofu_GET_POLICY_ERROR:
    2665           0 :       trust_level = _tofu_GET_TRUST_ERROR;
    2666           0 :       goto out;
    2667             : 
    2668             :     default:
    2669           0 :       log_bug ("%s: Impossible value for policy (%d)\n", __func__, policy);
    2670             :     }
    2671             : 
    2672             : 
    2673             :   /* We get here if:
    2674             :    *
    2675             :    *   1. The saved policy is auto and the default policy is ask
    2676             :    *      (get_policy() == TOFU_POLICY_AUTO
    2677             :    *       && opt.tofu_default_policy == TOFU_POLICY_ASK)
    2678             :    *
    2679             :    *   2. The saved policy is ask (either last time the user selected
    2680             :    *      accept once or reject once or there was a conflict and this
    2681             :    *      binding's policy was changed from auto to ask)
    2682             :    *      (policy == TOFU_POLICY_ASK).
    2683             :    */
    2684          25 :   log_assert (policy == TOFU_POLICY_ASK);
    2685             : 
    2686          25 :   if (may_ask)
    2687             :     {
    2688             :       /* We can't be in a normal transaction in ask_about_binding.  */
    2689           0 :       end_transaction (ctrl, 0);
    2690           0 :       in_transaction = 0;
    2691             : 
    2692             :       /* If we get here, we need to ask the user about the binding.  */
    2693           0 :       ask_about_binding (ctrl,
    2694             :                          &policy,
    2695             :                          &trust_level,
    2696             :                          conflict_set,
    2697             :                          fingerprint,
    2698             :                          email,
    2699             :                          user_id,
    2700             :                          now);
    2701             :     }
    2702             :   else
    2703          25 :     trust_level = TRUST_UNDEFINED;
    2704             : 
    2705             :   /* Mark any conflicting bindings that have an automatic policy as
    2706             :    * now requiring confirmation.  Note: we do this after we ask for
    2707             :    * confirmation so that when the current policy is printed, it is
    2708             :    * correct.  */
    2709          25 :   if (! in_transaction)
    2710             :     {
    2711           0 :       begin_transaction (ctrl, 0);
    2712           0 :       in_transaction = 1;
    2713             :     }
    2714             : 
    2715             :   /* The conflict set should always contain at least one element:
    2716             :    * the current key.  */
    2717          25 :   log_assert (conflict_set);
    2718             : 
    2719          57 :   for (iter = conflict_set->next; iter; iter = iter->next)
    2720             :     {
    2721             :       /* We don't immediately set the effective policy to 'ask,
    2722             :          because  */
    2723          32 :       rc = gpgsql_exec_printf
    2724             :         (dbs->db, NULL, NULL, &sqerr,
    2725             :          "update bindings set effective_policy = %d, conflict = %Q"
    2726             :          " where email = %Q and fingerprint = %Q and effective_policy != %d;",
    2727             :          TOFU_POLICY_NONE, fingerprint,
    2728          32 :          email, iter->d, TOFU_POLICY_ASK);
    2729          32 :       if (rc)
    2730             :         {
    2731           0 :           log_error (_("error changing TOFU policy: %s\n"), sqerr);
    2732           0 :           print_further_info ("binding: <key: %s, user id: %s>",
    2733             :                               fingerprint, user_id);
    2734           0 :           sqlite3_free (sqerr);
    2735           0 :           sqerr = NULL;
    2736           0 :           rc = gpg_error (GPG_ERR_GENERAL);
    2737             :         }
    2738          32 :       else if (DBG_TRUST)
    2739           0 :         log_debug ("Set %s to conflict with %s\n",
    2740           0 :                    iter->d, fingerprint);
    2741             :     }
    2742             : 
    2743             :  out:
    2744         219 :   if (in_transaction)
    2745         204 :     end_transaction (ctrl, 0);
    2746             : 
    2747         219 :   free_strlist (conflict_set);
    2748             : 
    2749         219 :   return trust_level;
    2750             : }
    2751             : 
    2752             : 
    2753             : /* Return a malloced string of the form
    2754             :  *    "7 months, 1 day, 5 minutes, 0 seconds"
    2755             :  * The caller should replace all '~' in the returned string by a space
    2756             :  * and also free the returned string.
    2757             :  *
    2758             :  * This is actually a bad hack which may not work correctly with all
    2759             :  * languages.
    2760             :  */
    2761             : static char *
    2762          26 : time_ago_str (long long int t)
    2763             : {
    2764             :   estream_t fp;
    2765          26 :   int years = 0;
    2766          26 :   int months = 0;
    2767          26 :   int days = 0;
    2768          26 :   int hours = 0;
    2769          26 :   int minutes = 0;
    2770          26 :   int seconds = 0;
    2771             : 
    2772             :   /* The number of units that we've printed so far.  */
    2773          26 :   int count = 0;
    2774             :   /* The first unit that we printed (year = 0, month = 1,
    2775             :      etc.).  */
    2776          26 :   int first = -1;
    2777             :   /* The current unit.  */
    2778          26 :   int i = 0;
    2779             : 
    2780             :   char *str;
    2781             : 
    2782             :   /* It would be nice to use a macro to do this, but gettext
    2783             :      works on the unpreprocessed code.  */
    2784             : #define MIN_SECS (60)
    2785             : #define HOUR_SECS (60 * MIN_SECS)
    2786             : #define DAY_SECS (24 * HOUR_SECS)
    2787             : #define MONTH_SECS (30 * DAY_SECS)
    2788             : #define YEAR_SECS (365 * DAY_SECS)
    2789             : 
    2790          26 :   if (t > YEAR_SECS)
    2791             :     {
    2792           0 :       years = t / YEAR_SECS;
    2793           0 :       t -= years * YEAR_SECS;
    2794             :     }
    2795          26 :   if (t > MONTH_SECS)
    2796             :     {
    2797           0 :       months = t / MONTH_SECS;
    2798           0 :       t -= months * MONTH_SECS;
    2799             :     }
    2800          26 :   if (t > DAY_SECS)
    2801             :     {
    2802           0 :       days = t / DAY_SECS;
    2803           0 :       t -= days * DAY_SECS;
    2804             :     }
    2805          26 :   if (t > HOUR_SECS)
    2806             :     {
    2807           0 :       hours = t / HOUR_SECS;
    2808           0 :       t -= hours * HOUR_SECS;
    2809             :     }
    2810          26 :   if (t > MIN_SECS)
    2811             :     {
    2812           0 :       minutes = t / MIN_SECS;
    2813           0 :       t -= minutes * MIN_SECS;
    2814             :     }
    2815          26 :   seconds = t;
    2816             : 
    2817             : #undef MIN_SECS
    2818             : #undef HOUR_SECS
    2819             : #undef DAY_SECS
    2820             : #undef MONTH_SECS
    2821             : #undef YEAR_SECS
    2822             : 
    2823          26 :   fp = es_fopenmem (0, "rw,samethread");
    2824          26 :   if (! fp)
    2825           0 :     log_fatal ("error creating memory stream: %s\n",
    2826             :                gpg_strerror (gpg_error_from_syserror()));
    2827             : 
    2828          26 :   if (years)
    2829             :     {
    2830             :       /* TRANSLATORS: The tilde ('~') is used here to indicate a
    2831             :        * non-breakable space  */
    2832           0 :       es_fprintf (fp, ngettext("%d~year", "%d~years", years), years);
    2833           0 :       count ++;
    2834           0 :       first = i;
    2835             :     }
    2836          26 :   i ++;
    2837          26 :   if ((first == -1 || i - first <= 3) && count <= 0 && months)
    2838             :     {
    2839           0 :       if (count)
    2840           0 :         es_fprintf (fp, ", ");
    2841           0 :       es_fprintf (fp, ngettext("%d~month", "%d~months", months), months);
    2842           0 :       count ++;
    2843           0 :       first = i;
    2844             :     }
    2845          26 :   i ++;
    2846          26 :   if ((first == -1 || i - first <= 3) && count <= 0 && days)
    2847             :     {
    2848           0 :       if (count)
    2849           0 :         es_fprintf (fp, ", ");
    2850           0 :       es_fprintf (fp, ngettext("%d~day", "%d~days", days), days);
    2851           0 :       count ++;
    2852           0 :       first = i;
    2853             :     }
    2854          26 :   i ++;
    2855          26 :   if ((first == -1 || i - first <= 3) && count <= 0 && hours)
    2856             :     {
    2857           0 :       if (count)
    2858           0 :         es_fprintf (fp, ", ");
    2859           0 :       es_fprintf (fp, ngettext("%d~hour", "%d~hours", hours), hours);
    2860           0 :       count ++;
    2861           0 :       first = i;
    2862             :     }
    2863          26 :   i ++;
    2864          26 :   if ((first == -1 || i - first <= 3) && count <= 0 && minutes)
    2865             :     {
    2866           0 :       if (count)
    2867           0 :         es_fprintf (fp, ", ");
    2868           0 :       es_fprintf (fp, ngettext("%d~minute", "%d~minutes", minutes), minutes);
    2869           0 :       count ++;
    2870           0 :       first = i;
    2871             :     }
    2872          26 :   i ++;
    2873          26 :   if ((first == -1 || i - first <= 3) && count <= 0)
    2874             :     {
    2875          26 :       if (count)
    2876           0 :         es_fprintf (fp, ", ");
    2877          26 :       es_fprintf (fp, ngettext("%d~second", "%d~seconds", seconds), seconds);
    2878             :     }
    2879             : 
    2880          26 :   es_fputc (0, fp);
    2881          26 :   if (es_fclose_snatch (fp, (void **) &str, NULL))
    2882           0 :     log_fatal ("error snatching memory stream\n");
    2883             : 
    2884          26 :   return str;
    2885             : }
    2886             : 
    2887             : 
    2888             : /* If FP is NULL, write TOFU_STATS status line.  If FP is not NULL
    2889             :  * write a "tfs" record to that stream. */
    2890             : static void
    2891          71 : write_stats_status (estream_t fp,
    2892             :                     enum tofu_policy policy,
    2893             :                     unsigned long signature_count,
    2894             :                     unsigned long signature_first_seen,
    2895             :                     unsigned long signature_most_recent,
    2896             :                     unsigned long encryption_count,
    2897             :                     unsigned long encryption_first_done,
    2898             :                     unsigned long encryption_most_recent)
    2899             : {
    2900             :   int summary;
    2901             :   int validity;
    2902             :   unsigned long messages;
    2903             : 
    2904             :   /* Use the euclidean distance (m = sqrt(a^2 + b^2)) rather then the
    2905             :      sum of the magnitudes (m = a + b) to ensure a balance between
    2906             :      verified signatures and encrypted messages.  */
    2907          71 :   messages = sqrtu32 (signature_count * signature_count
    2908             :                       + encryption_count * encryption_count);
    2909             : 
    2910          71 :   if (messages < 1)
    2911           9 :     validity = 1; /* Key without history.  */
    2912          62 :   else if (messages < 2 * BASIC_TRUST_THRESHOLD)
    2913          62 :     validity = 2; /* Key with too little history.  */
    2914           0 :   else if (messages < 2 * FULL_TRUST_THRESHOLD)
    2915           0 :     validity = 3; /* Key with enough history for basic trust.  */
    2916             :   else
    2917           0 :     validity = 4; /* Key with a lot of history.  */
    2918             : 
    2919          71 :   if (policy == TOFU_POLICY_ASK)
    2920          10 :     summary = 0; /* Key requires attention.  */
    2921             :   else
    2922          61 :     summary = validity;
    2923             : 
    2924          71 :   if (fp)
    2925             :     {
    2926          45 :       es_fprintf (fp, "tfs:1:%d:%lu:%lu:%s:%lu:%lu:%lu:%lu:%d:\n",
    2927             :                   summary, signature_count, encryption_count,
    2928             :                   tofu_policy_str (policy),
    2929             :                   signature_first_seen, signature_most_recent,
    2930             :                   encryption_first_done, encryption_most_recent,
    2931             :                   validity);
    2932             :     }
    2933             :   else
    2934             :     {
    2935          26 :       write_status_printf (STATUS_TOFU_STATS,
    2936             :                            "%d %lu %lu %s %lu %lu %lu %lu %d",
    2937             :                            summary,
    2938             :                            signature_count,
    2939             :                            encryption_count,
    2940             :                            tofu_policy_str (policy),
    2941             :                            signature_first_seen,
    2942             :                            signature_most_recent,
    2943             :                            encryption_first_done,
    2944             :                            encryption_most_recent,
    2945             :                            validity);
    2946             :     }
    2947          71 : }
    2948             : 
    2949             : /* Note: If OUTFP is not NULL, this function merely prints a "tfs" record
    2950             :  * to OUTFP.
    2951             :  *
    2952             :  * Returns whether the caller should call show_warning after iterating
    2953             :  * over all user ids.
    2954             :  */
    2955             : static int
    2956          71 : show_statistics (tofu_dbs_t dbs, PKT_public_key *pk, const char *fingerprint,
    2957             :                  const char *email, const char *user_id,
    2958             :                  estream_t outfp, time_t now)
    2959             : {
    2960          71 :   enum tofu_policy policy =
    2961             :     get_policy (dbs, pk, fingerprint, user_id, email, NULL, now);
    2962             : 
    2963             :   char *fingerprint_pp;
    2964             :   int rc;
    2965          71 :   strlist_t strlist = NULL;
    2966          71 :   char *err = NULL;
    2967             : 
    2968          71 :   unsigned long signature_first_seen = 0;
    2969          71 :   unsigned long signature_most_recent = 0;
    2970          71 :   unsigned long signature_count = 0;
    2971          71 :   unsigned long encryption_first_done = 0;
    2972          71 :   unsigned long encryption_most_recent = 0;
    2973          71 :   unsigned long encryption_count = 0;
    2974             : 
    2975          71 :   int show_warning = 0;
    2976             : 
    2977             :   (void) user_id;
    2978             : 
    2979          71 :   fingerprint_pp = format_hexfingerprint (fingerprint, NULL, 0);
    2980             : 
    2981             :   /* Get the signature stats.  */
    2982          71 :   rc = gpgsql_exec_printf
    2983             :     (dbs->db, strings_collect_cb, &strlist, &err,
    2984             :      "select count (*), min (signatures.time), max (signatures.time)\n"
    2985             :      " from signatures\n"
    2986             :      " left join bindings on signatures.binding = bindings.oid\n"
    2987             :      " where fingerprint = %Q and email = %Q;",
    2988             :      fingerprint, email);
    2989          71 :   if (rc)
    2990             :     {
    2991           0 :       log_error (_("error reading TOFU database: %s\n"), err);
    2992           0 :       print_further_info ("getting signature statistics");
    2993           0 :       sqlite3_free (err);
    2994           0 :       rc = gpg_error (GPG_ERR_GENERAL);
    2995           0 :       goto out;
    2996             :     }
    2997             : 
    2998          71 :   if (strlist)
    2999             :     {
    3000             :       /* We expect exactly 3 elements.  */
    3001          71 :       log_assert (strlist->next);
    3002          71 :       log_assert (strlist->next->next);
    3003          71 :       log_assert (! strlist->next->next->next);
    3004             : 
    3005          71 :       string_to_ulong (&signature_count, strlist->d, -1, __LINE__);
    3006          71 :       string_to_ulong (&signature_first_seen, strlist->next->d, -1, __LINE__);
    3007          71 :       string_to_ulong (&signature_most_recent,
    3008          71 :                        strlist->next->next->d, -1, __LINE__);
    3009             : 
    3010          71 :       free_strlist (strlist);
    3011          71 :       strlist = NULL;
    3012             :     }
    3013             : 
    3014             :   /* Get the encryption stats.  */
    3015          71 :   rc = gpgsql_exec_printf
    3016             :     (dbs->db, strings_collect_cb, &strlist, &err,
    3017             :      "select count (*), min (encryptions.time), max (encryptions.time)\n"
    3018             :      " from encryptions\n"
    3019             :      " left join bindings on encryptions.binding = bindings.oid\n"
    3020             :      " where fingerprint = %Q and email = %Q;",
    3021             :      fingerprint, email);
    3022          71 :   if (rc)
    3023             :     {
    3024           0 :       log_error (_("error reading TOFU database: %s\n"), err);
    3025           0 :       print_further_info ("getting encryption statistics");
    3026           0 :       sqlite3_free (err);
    3027           0 :       rc = gpg_error (GPG_ERR_GENERAL);
    3028           0 :       goto out;
    3029             :     }
    3030             : 
    3031          71 :   if (strlist)
    3032             :     {
    3033             :       /* We expect exactly 3 elements.  */
    3034          71 :       log_assert (strlist->next);
    3035          71 :       log_assert (strlist->next->next);
    3036          71 :       log_assert (! strlist->next->next->next);
    3037             : 
    3038          71 :       string_to_ulong (&encryption_count, strlist->d, -1, __LINE__);
    3039          71 :       string_to_ulong (&encryption_first_done, strlist->next->d, -1, __LINE__);
    3040          71 :       string_to_ulong (&encryption_most_recent,
    3041          71 :                        strlist->next->next->d, -1, __LINE__);
    3042             : 
    3043          71 :       free_strlist (strlist);
    3044          71 :       strlist = NULL;
    3045             :     }
    3046             : 
    3047          71 :   if (!outfp)
    3048          26 :     write_status_text_and_buffer (STATUS_TOFU_USER, fingerprint,
    3049             :                                   email, strlen (email), 0);
    3050             : 
    3051          71 :   write_stats_status (outfp, policy,
    3052             :                       signature_count,
    3053             :                       signature_first_seen,
    3054             :                       signature_most_recent,
    3055             :                       encryption_count,
    3056             :                       encryption_first_done,
    3057             :                       encryption_most_recent);
    3058             : 
    3059          71 :   if (!outfp)
    3060             :     {
    3061             :       estream_t fp;
    3062             :       char *msg;
    3063             : 
    3064          26 :       fp = es_fopenmem (0, "rw,samethread");
    3065          26 :       if (! fp)
    3066           0 :         log_fatal ("error creating memory stream: %s\n",
    3067             :                    gpg_strerror (gpg_error_from_syserror()));
    3068             : 
    3069          26 :       es_fprintf (fp, _("%s: "), email);
    3070             : 
    3071          26 :       if (signature_count == 0)
    3072             :         {
    3073           0 :           es_fprintf (fp, _("Verified %ld signatures"), 0L);
    3074           0 :           es_fputc ('\n', fp);
    3075             :         }
    3076             :       else
    3077             :         {
    3078          26 :           char *first_seen_ago_str = time_ago_str (now - signature_first_seen);
    3079             : 
    3080             :           /* TRANSLATORS: The final %s is replaced by a string like
    3081             :              "7 months, 1 day, 5 minutes, 0 seconds". */
    3082          52 :           es_fprintf (fp,
    3083          26 :                       ngettext("Verified %ld signature in the past %s",
    3084             :                                "Verified %ld signatures in the past %s",
    3085             :                                signature_count),
    3086             :                       signature_count, first_seen_ago_str);
    3087             : 
    3088          26 :           xfree (first_seen_ago_str);
    3089             :         }
    3090             : 
    3091          26 :       if (encryption_count == 0)
    3092             :         {
    3093          26 :           es_fprintf (fp, _(", and encrypted %ld messages"), 0L);
    3094             :         }
    3095             :       else
    3096             :         {
    3097           0 :           char *first_done_ago_str = time_ago_str (now - encryption_first_done);
    3098             : 
    3099             :           /* TRANSLATORS: The final %s is replaced by a string like
    3100             :              "7 months, 1 day, 5 minutes, 0 seconds". */
    3101           0 :           es_fprintf (fp,
    3102           0 :                       ngettext(", and encrypted %ld message in the past %s",
    3103             :                                ", and encrypted %ld messages in the past %s",
    3104             :                                encryption_count),
    3105             :                       encryption_count, first_done_ago_str);
    3106             : 
    3107           0 :           xfree (first_done_ago_str);
    3108             :         }
    3109             : 
    3110          26 :       if (opt.verbose)
    3111             :         {
    3112           0 :           es_fputs ("  ", fp);
    3113           0 :           es_fputc ('(', fp);
    3114           0 :           es_fprintf (fp, _("policy: %s"), tofu_policy_str (policy));
    3115           0 :           es_fputs (").\n", fp);
    3116             :         }
    3117             :       else
    3118          26 :         es_fputs (".\n", fp);
    3119             : 
    3120             : 
    3121             :       {
    3122             :         char *tmpmsg, *p;
    3123          26 :         es_fputc (0, fp);
    3124          26 :         if (es_fclose_snatch (fp, (void **) &tmpmsg, NULL))
    3125           0 :           log_fatal ("error snatching memory stream\n");
    3126          26 :         msg = format_text (tmpmsg, 0, 72, 80);
    3127          26 :         es_free (tmpmsg);
    3128             : 
    3129             :         /* Print a status line but suppress the trailing LF.
    3130             :          * Spaces are not percent escaped. */
    3131          26 :         if (*msg)
    3132          26 :           write_status_buffer (STATUS_TOFU_STATS_LONG,
    3133          26 :                                msg, strlen (msg)-1, -1);
    3134             : 
    3135             :         /* Remove the non-breaking space markers.  */
    3136        2203 :         for (p=msg; *p; p++)
    3137        2177 :           if (*p == '~')
    3138          26 :             *p = ' ';
    3139             :       }
    3140             : 
    3141          26 :       log_string (GPGRT_LOG_INFO, msg);
    3142          26 :       xfree (msg);
    3143             : 
    3144          26 :       if (policy == TOFU_POLICY_AUTO)
    3145             :         {
    3146          18 :           if (signature_count == 0)
    3147           0 :             log_info (_("Warning: we have yet to see"
    3148             :                         " a message signed using this key and user id!\n"));
    3149          18 :           else if (signature_count == 1)
    3150           4 :             log_info (_("Warning: we've only seen one message"
    3151             :                         " signed using this key and user id!\n"));
    3152             : 
    3153          18 :           if (encryption_count == 0)
    3154          18 :             log_info (_("Warning: you have yet to encrypt"
    3155             :                         " a message to this key!\n"));
    3156           0 :           else if (encryption_count == 1)
    3157           0 :             log_info (_("Warning: you have only encrypted"
    3158             :                         " one message to this key!\n"));
    3159             : 
    3160             :           /* Cf. write_stats_status  */
    3161          18 :           if (sqrtu32 (encryption_count * encryption_count
    3162             :                        + signature_count * signature_count)
    3163             :               < 2 * BASIC_TRUST_THRESHOLD)
    3164          18 :             show_warning = 1;
    3165             :         }
    3166             :     }
    3167             : 
    3168             :  out:
    3169          71 :   xfree (fingerprint_pp);
    3170             : 
    3171          71 :   return show_warning;
    3172             : }
    3173             : 
    3174             : static void
    3175          17 : show_warning (const char *fingerprint, strlist_t user_id_list)
    3176             : {
    3177             :   char *set_policy_command;
    3178             :   char *text;
    3179             :   char *tmpmsg;
    3180             : 
    3181          17 :   set_policy_command =
    3182             :     xasprintf ("gpg --tofu-policy bad %s", fingerprint);
    3183             : 
    3184          17 :   tmpmsg = xasprintf
    3185          17 :     (ngettext
    3186             :      ("Warning: if you think you've seen more signatures "
    3187             :       "by this key and user id, then this key might be a "
    3188             :       "forgery!  Carefully examine the email address for small "
    3189             :       "variations.  If the key is suspect, then use\n"
    3190             :       "  %s\n"
    3191             :       "to mark it as being bad.\n",
    3192             :       "Warning: if you think you've seen more signatures "
    3193             :       "by this key and these user ids, then this key might be a "
    3194             :       "forgery!  Carefully examine the email addresses for small "
    3195             :       "variations.  If the key is suspect, then use\n"
    3196             :       "  %s\n"
    3197             :       "to mark it as being bad.\n",
    3198          17 :       strlist_length (user_id_list)),
    3199             :      set_policy_command);
    3200             : 
    3201          17 :   text = format_text (tmpmsg, 0, 72, 80);
    3202          17 :   xfree (tmpmsg);
    3203          17 :   log_string (GPGRT_LOG_INFO, text);
    3204          17 :   xfree (text);
    3205             : 
    3206          17 :   es_free (set_policy_command);
    3207          17 : }
    3208             : 
    3209             : 
    3210             : /* Extract the email address from a user id and normalize it.  If the
    3211             :    user id doesn't contain an email address, then we use the whole
    3212             :    user_id and normalize that.  The returned string must be freed.  */
    3213             : static char *
    3214         530 : email_from_user_id (const char *user_id)
    3215             : {
    3216         530 :   char *email = mailbox_from_userid (user_id);
    3217         530 :   if (! email)
    3218             :     {
    3219             :       /* Hmm, no email address was provided or we are out of core.  Just
    3220             :          take the lower-case version of the whole user id.  It could be
    3221             :          a hostname, for instance.  */
    3222         203 :       email = ascii_strlwr (xstrdup (user_id));
    3223             :     }
    3224             : 
    3225         530 :   return email;
    3226             : }
    3227             : 
    3228             : /* Register the signature with the bindings <fingerprint, USER_ID>,
    3229             :    for each USER_ID in USER_ID_LIST.  The fingerprint is taken from
    3230             :    the primary key packet PK.
    3231             : 
    3232             :    SIG_DIGEST_BIN is the binary representation of the message's
    3233             :    digest.  SIG_DIGEST_BIN_LEN is its length.
    3234             : 
    3235             :    SIG_TIME is the time that the signature was generated.
    3236             : 
    3237             :    ORIGIN is a free-formed string describing the origin of the
    3238             :    signature.  If this was from an email and the Claws MUA was used,
    3239             :    then this should be something like: "email:claws".  If this is
    3240             :    NULL, the default is simply "unknown".
    3241             : 
    3242             :    If MAY_ASK is 1, then this function may interact with the user.
    3243             :    This is necessary if there is a conflict or the binding's policy is
    3244             :    TOFU_POLICY_ASK.
    3245             : 
    3246             :    This function returns 0 on success and an error code if an error
    3247             :    occurred.  */
    3248             : gpg_error_t
    3249          26 : tofu_register_signature (ctrl_t ctrl,
    3250             :                          PKT_public_key *pk, strlist_t user_id_list,
    3251             :                          const byte *sig_digest_bin, int sig_digest_bin_len,
    3252             :                          time_t sig_time, const char *origin)
    3253             : {
    3254          26 :   time_t now = gnupg_get_time ();
    3255             :   gpg_error_t rc;
    3256             :   tofu_dbs_t dbs;
    3257          26 :   char *fingerprint = NULL;
    3258             :   strlist_t user_id;
    3259          26 :   char *email = NULL;
    3260          26 :   char *err = NULL;
    3261             :   char *sig_digest;
    3262             :   unsigned long c;
    3263             : 
    3264          26 :   dbs = opendbs (ctrl);
    3265          26 :   if (! dbs)
    3266             :     {
    3267           0 :       rc = gpg_error (GPG_ERR_GENERAL);
    3268           0 :       log_error (_("error opening TOFU database: %s\n"),
    3269             :                  gpg_strerror (rc));
    3270           0 :       return rc;
    3271             :     }
    3272             : 
    3273             :   /* We do a query and then an insert.  Make sure they are atomic
    3274             :      by wrapping them in a transaction.  */
    3275          26 :   rc = begin_transaction (ctrl, 0);
    3276          26 :   if (rc)
    3277           0 :     return rc;
    3278             : 
    3279          26 :   log_assert (pk_is_primary (pk));
    3280             : 
    3281          26 :   sig_digest = make_radix64_string (sig_digest_bin, sig_digest_bin_len);
    3282          26 :   fingerprint = hexfingerprint (pk, NULL, 0);
    3283             : 
    3284          26 :   if (! origin)
    3285             :     /* The default origin is simply "unknown".  */
    3286           0 :     origin = "unknown";
    3287             : 
    3288          56 :   for (user_id = user_id_list; user_id; user_id = user_id->next)
    3289             :     {
    3290          30 :       email = email_from_user_id (user_id->d);
    3291             : 
    3292          30 :       if (DBG_TRUST)
    3293           0 :         log_debug ("TOFU: Registering signature %s with binding"
    3294             :                    " <key: %s, user id: %s>\n",
    3295             :                    sig_digest, fingerprint, email);
    3296             : 
    3297             :       /* Make sure the binding exists and record any TOFU
    3298             :          conflicts.  */
    3299          30 :       if (get_trust (ctrl, pk, fingerprint, email, user_id->d, 0, now)
    3300             :           == _tofu_GET_TRUST_ERROR)
    3301             :         {
    3302           0 :           rc = gpg_error (GPG_ERR_GENERAL);
    3303           0 :           xfree (email);
    3304           0 :           break;
    3305             :         }
    3306             : 
    3307             :       /* If we've already seen this signature before, then don't add
    3308             :          it again.  */
    3309          30 :       rc = gpgsql_stepx
    3310             :         (dbs->db, &dbs->s.register_already_seen,
    3311             :          get_single_unsigned_long_cb2, &c, &err,
    3312             :          "select count (*)\n"
    3313             :          " from signatures left join bindings\n"
    3314             :          "  on signatures.binding = bindings.oid\n"
    3315             :          " where fingerprint = ? and email = ? and sig_time = ?\n"
    3316             :          "  and sig_digest = ?",
    3317             :          GPGSQL_ARG_STRING, fingerprint, GPGSQL_ARG_STRING, email,
    3318             :          GPGSQL_ARG_LONG_LONG, (long long) sig_time,
    3319             :          GPGSQL_ARG_STRING, sig_digest,
    3320             :          GPGSQL_ARG_END);
    3321          30 :       if (rc)
    3322             :         {
    3323           0 :           log_error (_("error reading TOFU database: %s\n"), err);
    3324           0 :           print_further_info ("checking existence");
    3325           0 :           sqlite3_free (err);
    3326           0 :           rc = gpg_error (GPG_ERR_GENERAL);
    3327             :         }
    3328          30 :       else if (c > 1)
    3329             :         /* Duplicates!  This should not happen.  In particular,
    3330             :            because <fingerprint, email, sig_time, sig_digest> is the
    3331             :            primary key!  */
    3332           0 :         log_debug ("SIGNATURES DB contains duplicate records"
    3333             :                    " <key: %s, email: %s, time: 0x%lx, sig: %s,"
    3334             :                    " origin: %s>."
    3335             :                    "  Please report.\n",
    3336             :                    fingerprint, email, (unsigned long) sig_time,
    3337             :                    sig_digest, origin);
    3338          30 :       else if (c == 1)
    3339             :         {
    3340          18 :           if (DBG_TRUST)
    3341           0 :             log_debug ("Already observed the signature and binding"
    3342             :                        " <key: %s, email: %s, time: 0x%lx, sig: %s,"
    3343             :                        " origin: %s>\n",
    3344             :                        fingerprint, email, (unsigned long) sig_time,
    3345             :                        sig_digest, origin);
    3346             :         }
    3347          12 :       else if (opt.dry_run)
    3348             :         {
    3349           0 :           log_info ("TOFU database update skipped due to --dry-run\n");
    3350             :         }
    3351             :       else
    3352             :         /* This is the first time that we've seen this signature and
    3353             :            binding.  Record it.  */
    3354             :         {
    3355          12 :           if (DBG_TRUST)
    3356           0 :             log_debug ("TOFU: Saving signature"
    3357             :                        " <key: %s, user id: %s, sig: %s>\n",
    3358             :                        fingerprint, email, sig_digest);
    3359             : 
    3360          12 :           log_assert (c == 0);
    3361             : 
    3362          12 :           rc = gpgsql_stepx
    3363             :             (dbs->db, &dbs->s.register_signature, NULL, NULL, &err,
    3364             :              "insert into signatures\n"
    3365             :              " (binding, sig_digest, origin, sig_time, time)\n"
    3366             :              " values\n"
    3367             :              " ((select oid from bindings\n"
    3368             :              "    where fingerprint = ? and email = ?),\n"
    3369             :              "  ?, ?, ?, ?);",
    3370             :              GPGSQL_ARG_STRING, fingerprint, GPGSQL_ARG_STRING, email,
    3371             :              GPGSQL_ARG_STRING, sig_digest, GPGSQL_ARG_STRING, origin,
    3372             :              GPGSQL_ARG_LONG_LONG, (long long) sig_time,
    3373             :              GPGSQL_ARG_LONG_LONG, (long long) now,
    3374             :              GPGSQL_ARG_END);
    3375          12 :           if (rc)
    3376             :             {
    3377           0 :               log_error (_("error updating TOFU database: %s\n"), err);
    3378           0 :               print_further_info ("insert signatures");
    3379           0 :               sqlite3_free (err);
    3380           0 :               rc = gpg_error (GPG_ERR_GENERAL);
    3381             :             }
    3382             :         }
    3383             : 
    3384          30 :       xfree (email);
    3385             : 
    3386          30 :       if (rc)
    3387           0 :         break;
    3388             :     }
    3389             : 
    3390          26 :   if (rc)
    3391           0 :     rollback_transaction (ctrl);
    3392             :   else
    3393          26 :     rc = end_transaction (ctrl, 0);
    3394             : 
    3395          26 :   xfree (fingerprint);
    3396          26 :   xfree (sig_digest);
    3397             : 
    3398          26 :   return rc;
    3399             : }
    3400             : 
    3401             : gpg_error_t
    3402           0 : tofu_register_encryption (ctrl_t ctrl,
    3403             :                           PKT_public_key *pk, strlist_t user_id_list,
    3404             :                           int may_ask)
    3405             : {
    3406           0 :   time_t now = gnupg_get_time ();
    3407           0 :   gpg_error_t rc = 0;
    3408             :   tofu_dbs_t dbs;
    3409           0 :   kbnode_t kb = NULL;
    3410           0 :   int free_user_id_list = 0;
    3411           0 :   char *fingerprint = NULL;
    3412             :   strlist_t user_id;
    3413           0 :   char *err = NULL;
    3414             : 
    3415           0 :   dbs = opendbs (ctrl);
    3416           0 :   if (! dbs)
    3417             :     {
    3418           0 :       rc = gpg_error (GPG_ERR_GENERAL);
    3419           0 :       log_error (_("error opening TOFU database: %s\n"),
    3420             :                  gpg_strerror (rc));
    3421           0 :       return rc;
    3422             :     }
    3423             : 
    3424           0 :   if (/* We need the key block to find the primary key.  */
    3425           0 :       ! pk_is_primary (pk)
    3426             :       /* We need the key block to find all user ids.  */
    3427           0 :       || ! user_id_list)
    3428           0 :     kb = get_pubkeyblock (pk->keyid);
    3429             : 
    3430             :   /* Make sure PK is a primary key.  */
    3431           0 :   if (! pk_is_primary (pk))
    3432           0 :     pk = kb->pkt->pkt.public_key;
    3433             : 
    3434           0 :   if (! user_id_list)
    3435             :     {
    3436             :       /* Use all non-revoked user ids.  Do use expired user ids.  */
    3437           0 :       kbnode_t n = kb;
    3438             : 
    3439           0 :       while ((n = find_next_kbnode (n, PKT_USER_ID)))
    3440             :         {
    3441           0 :           PKT_user_id *uid = n->pkt->pkt.user_id;
    3442             : 
    3443           0 :           if (uid->is_revoked)
    3444           0 :             continue;
    3445             : 
    3446           0 :           add_to_strlist (&user_id_list, uid->name);
    3447             :         }
    3448             : 
    3449           0 :       free_user_id_list = 1;
    3450             : 
    3451           0 :       if (! user_id_list)
    3452           0 :         log_info (_("WARNING: Encrypting to %s, which has no"
    3453             :                     "non-revoked user ids.\n"),
    3454           0 :                   keystr (pk->keyid));
    3455             :     }
    3456             : 
    3457           0 :   fingerprint = hexfingerprint (pk, NULL, 0);
    3458             : 
    3459           0 :   tofu_begin_batch_update (ctrl);
    3460           0 :   tofu_resume_batch_transaction (ctrl);
    3461             : 
    3462           0 :   for (user_id = user_id_list; user_id; user_id = user_id->next)
    3463             :     {
    3464           0 :       char *email = email_from_user_id (user_id->d);
    3465             : 
    3466             :       /* Make sure the binding exists and that we recognize any
    3467             :          conflicts.  */
    3468           0 :       int tl = get_trust (ctrl, pk, fingerprint, email, user_id->d,
    3469             :                           may_ask, now);
    3470           0 :       if (tl == _tofu_GET_TRUST_ERROR)
    3471             :         {
    3472             :           /* An error.  */
    3473           0 :           rc = gpg_error (GPG_ERR_GENERAL);
    3474           0 :           xfree (email);
    3475           0 :           goto die;
    3476             :         }
    3477             : 
    3478           0 :       rc = gpgsql_stepx
    3479             :         (dbs->db, &dbs->s.register_encryption, NULL, NULL, &err,
    3480             :          "insert into encryptions\n"
    3481             :          " (binding, time)\n"
    3482             :          " values\n"
    3483             :          " ((select oid from bindings\n"
    3484             :          "    where fingerprint = ? and email = ?),\n"
    3485             :          "  ?);",
    3486             :          GPGSQL_ARG_STRING, fingerprint, GPGSQL_ARG_STRING, email,
    3487             :          GPGSQL_ARG_LONG_LONG, (long long) now,
    3488             :          GPGSQL_ARG_END);
    3489           0 :       if (rc)
    3490             :         {
    3491           0 :           log_error (_("error updating TOFU database: %s\n"), err);
    3492           0 :           print_further_info ("insert encryption");
    3493           0 :           sqlite3_free (err);
    3494           0 :           rc = gpg_error (GPG_ERR_GENERAL);
    3495             :         }
    3496             : 
    3497           0 :       xfree (email);
    3498             :     }
    3499             : 
    3500             :  die:
    3501           0 :   tofu_end_batch_update (ctrl);
    3502             : 
    3503           0 :   if (kb)
    3504           0 :     release_kbnode (kb);
    3505             : 
    3506           0 :   if (free_user_id_list)
    3507           0 :     free_strlist (user_id_list);
    3508             : 
    3509           0 :   xfree (fingerprint);
    3510             : 
    3511           0 :   return rc;
    3512             : }
    3513             : 
    3514             : 
    3515             : /* Combine a trust level returned from the TOFU trust model with a
    3516             :    trust level returned by the PGP trust model.  This is primarily of
    3517             :    interest when the trust model is tofu+pgp (TM_TOFU_PGP).
    3518             : 
    3519             :    This function ors together the upper bits (the values not covered
    3520             :    by TRUST_MASK, i.e., TRUST_FLAG_REVOKED, etc.).  */
    3521             : int
    3522         291 : tofu_wot_trust_combine (int tofu_base, int wot_base)
    3523             : {
    3524         291 :   int tofu = tofu_base & TRUST_MASK;
    3525         291 :   int wot = wot_base & TRUST_MASK;
    3526         291 :   int upper = (tofu_base & ~TRUST_MASK) | (wot_base & ~TRUST_MASK);
    3527             : 
    3528         291 :   log_assert (tofu == TRUST_UNKNOWN
    3529             :               || tofu == TRUST_EXPIRED
    3530             :               || tofu == TRUST_UNDEFINED
    3531             :               || tofu == TRUST_NEVER
    3532             :               || tofu == TRUST_MARGINAL
    3533             :               || tofu == TRUST_FULLY
    3534             :               || tofu == TRUST_ULTIMATE);
    3535         291 :   log_assert (wot == TRUST_UNKNOWN
    3536             :               || wot == TRUST_EXPIRED
    3537             :               || wot == TRUST_UNDEFINED
    3538             :               || wot == TRUST_NEVER
    3539             :               || wot == TRUST_MARGINAL
    3540             :               || wot == TRUST_FULLY
    3541             :               || wot == TRUST_ULTIMATE);
    3542             : 
    3543             :   /* We first consider negative trust policys.  These trump positive
    3544             :      trust policies.  */
    3545         291 :   if (tofu == TRUST_NEVER || wot == TRUST_NEVER)
    3546             :     /* TRUST_NEVER trumps everything else.  */
    3547          28 :     return upper | TRUST_NEVER;
    3548         263 :   if (tofu == TRUST_EXPIRED || wot == TRUST_EXPIRED)
    3549             :     /* TRUST_EXPIRED trumps everything but TRUST_NEVER.  */
    3550           0 :     return upper | TRUST_EXPIRED;
    3551             : 
    3552             :   /* Now we only have positive or neutral trust policies.  We take
    3553             :      the max.  */
    3554         263 :   if (tofu == TRUST_ULTIMATE)
    3555          11 :     return upper | TRUST_ULTIMATE | TRUST_FLAG_TOFU_BASED;
    3556         252 :   if (wot == TRUST_ULTIMATE)
    3557           7 :     return upper | TRUST_ULTIMATE;
    3558             : 
    3559         245 :   if (tofu == TRUST_FULLY)
    3560          39 :     return upper | TRUST_FULLY | TRUST_FLAG_TOFU_BASED;
    3561         206 :   if (wot == TRUST_FULLY)
    3562           0 :     return upper | TRUST_FULLY;
    3563             : 
    3564         206 :   if (tofu == TRUST_MARGINAL)
    3565          63 :     return upper | TRUST_MARGINAL | TRUST_FLAG_TOFU_BASED;
    3566         143 :   if (wot == TRUST_MARGINAL)
    3567           0 :     return upper | TRUST_MARGINAL;
    3568             : 
    3569         143 :   if (tofu == TRUST_UNDEFINED)
    3570          18 :     return upper | TRUST_UNDEFINED | TRUST_FLAG_TOFU_BASED;
    3571         125 :   if (wot == TRUST_UNDEFINED)
    3572           0 :     return upper | TRUST_UNDEFINED;
    3573             : 
    3574         125 :   return upper | TRUST_UNKNOWN;
    3575             : }
    3576             : 
    3577             : 
    3578             : /* Write a "tfs" record for a --with-colons listing.  */
    3579             : gpg_error_t
    3580          45 : tofu_write_tfs_record (ctrl_t ctrl, estream_t fp,
    3581             :                        PKT_public_key *pk, const char *user_id)
    3582             : {
    3583          45 :   time_t now = gnupg_get_time ();
    3584             :   gpg_error_t err;
    3585             :   tofu_dbs_t dbs;
    3586             :   char *fingerprint;
    3587             :   char *email;
    3588             : 
    3589          45 :   if (!*user_id)
    3590           0 :     return 0;  /* No TOFU stats possible for an empty ID.  */
    3591             : 
    3592          45 :   dbs = opendbs (ctrl);
    3593          45 :   if (!dbs)
    3594             :     {
    3595           0 :       err = gpg_error (GPG_ERR_GENERAL);
    3596           0 :       log_error (_("error opening TOFU database: %s\n"), gpg_strerror (err));
    3597           0 :       return err;
    3598             :     }
    3599             : 
    3600          45 :   fingerprint = hexfingerprint (pk, NULL, 0);
    3601          45 :   email = email_from_user_id (user_id);
    3602             : 
    3603          45 :   show_statistics (dbs, pk, fingerprint, email, user_id, fp, now);
    3604             : 
    3605          45 :   xfree (email);
    3606          45 :   xfree (fingerprint);
    3607          45 :   return 0;
    3608             : }
    3609             : 
    3610             : 
    3611             : /* Return the validity (TRUST_NEVER, etc.) of the bindings
    3612             :    <FINGERPRINT, USER_ID>, for each USER_ID in USER_ID_LIST.  If
    3613             :    USER_ID_LIST->FLAG is set, then the id is considered to be expired.
    3614             : 
    3615             :    PK is the primary key packet.
    3616             : 
    3617             :    If MAY_ASK is 1 and the policy is TOFU_POLICY_ASK, then the user
    3618             :    will be prompted to choose a policy.  If MAY_ASK is 0 and the
    3619             :    policy is TOFU_POLICY_ASK, then TRUST_UNKNOWN is returned.
    3620             : 
    3621             :    Returns TRUST_UNDEFINED if an error occurs.  */
    3622             : int
    3623         181 : tofu_get_validity (ctrl_t ctrl, PKT_public_key *pk, strlist_t user_id_list,
    3624             :                    int may_ask)
    3625             : {
    3626         181 :   time_t now = gnupg_get_time ();
    3627             :   tofu_dbs_t dbs;
    3628         181 :   char *fingerprint = NULL;
    3629             :   strlist_t user_id;
    3630         181 :   int trust_level = TRUST_UNKNOWN;
    3631         181 :   int bindings = 0;
    3632         181 :   int bindings_valid = 0;
    3633         181 :   int need_warning = 0;
    3634             : 
    3635         181 :   dbs = opendbs (ctrl);
    3636         181 :   if (! dbs)
    3637             :     {
    3638           0 :       log_error (_("error opening TOFU database: %s\n"),
    3639             :                  gpg_strerror (GPG_ERR_GENERAL));
    3640           0 :       return TRUST_UNDEFINED;
    3641             :     }
    3642             : 
    3643         181 :   fingerprint = hexfingerprint (pk, NULL, 0);
    3644             : 
    3645         181 :   tofu_begin_batch_update (ctrl);
    3646             :   /* Start the batch transaction now.  */
    3647         181 :   tofu_resume_batch_transaction (ctrl);
    3648             : 
    3649         370 :   for (user_id = user_id_list; user_id; user_id = user_id->next, bindings ++)
    3650             :     {
    3651         189 :       char *email = email_from_user_id (user_id->d);
    3652             : 
    3653             :       /* Always call get_trust to make sure the binding is
    3654             :          registered.  */
    3655         189 :       int tl = get_trust (ctrl, pk, fingerprint, email, user_id->d,
    3656             :                           may_ask, now);
    3657         189 :       if (tl == _tofu_GET_TRUST_ERROR)
    3658             :         {
    3659             :           /* An error.  */
    3660           0 :           trust_level = TRUST_UNDEFINED;
    3661           0 :           xfree (email);
    3662           0 :           goto die;
    3663             :         }
    3664             : 
    3665         189 :       if (DBG_TRUST)
    3666           0 :         log_debug ("TOFU: validity for <key: %s, user id: %s>: %s%s.\n",
    3667             :                    fingerprint, email,
    3668             :                    trust_value_to_string (tl),
    3669           0 :                    user_id->flags ? " (but expired)" : "");
    3670             : 
    3671         189 :       if (user_id->flags)
    3672           0 :         tl = TRUST_EXPIRED;
    3673             : 
    3674         189 :       if (tl != TRUST_EXPIRED)
    3675         189 :         bindings_valid ++;
    3676             : 
    3677         189 :       if (may_ask && tl != TRUST_ULTIMATE && tl != TRUST_EXPIRED)
    3678          26 :         need_warning |=
    3679          26 :           show_statistics (dbs, pk, fingerprint, email, user_id->d, NULL, now);
    3680             : 
    3681         189 :       if (tl == TRUST_NEVER)
    3682          28 :         trust_level = TRUST_NEVER;
    3683         161 :       else if (tl == TRUST_EXPIRED)
    3684             :         /* Ignore expired bindings in the trust calculation.  */
    3685             :         ;
    3686         161 :       else if (tl > trust_level)
    3687             :         {
    3688             :           /* The expected values: */
    3689         133 :           log_assert (tl == TRUST_UNKNOWN || tl == TRUST_UNDEFINED
    3690             :                       || tl == TRUST_MARGINAL || tl == TRUST_FULLY
    3691             :                       || tl == TRUST_ULTIMATE);
    3692             : 
    3693             :           /* We assume the following ordering:  */
    3694             :           log_assert (TRUST_UNKNOWN < TRUST_UNDEFINED);
    3695             :           log_assert (TRUST_UNDEFINED < TRUST_MARGINAL);
    3696             :           log_assert (TRUST_MARGINAL < TRUST_FULLY);
    3697             :           log_assert (TRUST_FULLY < TRUST_ULTIMATE);
    3698             : 
    3699         133 :           trust_level = tl;
    3700             :         }
    3701             : 
    3702         189 :       xfree (email);
    3703             :     }
    3704             : 
    3705         181 :   if (need_warning)
    3706          17 :     show_warning (fingerprint, user_id_list);
    3707             : 
    3708             :  die:
    3709         181 :   tofu_end_batch_update (ctrl);
    3710             : 
    3711         181 :   xfree (fingerprint);
    3712             : 
    3713         181 :   if (bindings_valid == 0)
    3714             :     {
    3715           0 :       if (DBG_TRUST)
    3716           0 :         log_debug ("no (of %d) valid bindings."
    3717             :                    "  Can't get TOFU validity for this set of user ids.\n",
    3718             :                    bindings);
    3719           0 :       return TRUST_NEVER;
    3720             :     }
    3721             : 
    3722         181 :   return trust_level;
    3723             : }
    3724             : 
    3725             : /* Set the policy for all non-revoked user ids in the keyblock KB to
    3726             :    POLICY.
    3727             : 
    3728             :    If no key is available with the specified key id, then this
    3729             :    function returns GPG_ERR_NO_PUBKEY.
    3730             : 
    3731             :    Returns 0 on success and an error code otherwise.  */
    3732             : gpg_error_t
    3733           5 : tofu_set_policy (ctrl_t ctrl, kbnode_t kb, enum tofu_policy policy)
    3734             : {
    3735             :   gpg_error_t err;
    3736           5 :   time_t now = gnupg_get_time ();
    3737             :   tofu_dbs_t dbs;
    3738             :   PKT_public_key *pk;
    3739           5 :   char *fingerprint = NULL;
    3740             : 
    3741           5 :   log_assert (kb->pkt->pkttype == PKT_PUBLIC_KEY);
    3742           5 :   pk = kb->pkt->pkt.public_key;
    3743             : 
    3744           5 :   dbs = opendbs (ctrl);
    3745           5 :   if (! dbs)
    3746             :     {
    3747           0 :       log_error (_("error opening TOFU database: %s\n"),
    3748             :                  gpg_strerror (GPG_ERR_GENERAL));
    3749           0 :       return gpg_error (GPG_ERR_GENERAL);
    3750             :     }
    3751             : 
    3752           5 :   if (DBG_TRUST)
    3753           0 :     log_debug ("Setting TOFU policy for %s to %s\n",
    3754           0 :                keystr (pk->keyid), tofu_policy_str (policy));
    3755           5 :   if (! pk_is_primary (pk))
    3756           0 :     log_bug ("%s: Passed a subkey, but expecting a primary key.\n", __func__);
    3757             : 
    3758           5 :   fingerprint = hexfingerprint (pk, NULL, 0);
    3759             : 
    3760           5 :   begin_transaction (ctrl, 0);
    3761             : 
    3762          30 :   for (; kb; kb = kb->next)
    3763             :     {
    3764             :       PKT_user_id *user_id;
    3765             :       char *email;
    3766             : 
    3767          25 :       if (kb->pkt->pkttype != PKT_USER_ID)
    3768          20 :         continue;
    3769             : 
    3770           5 :       user_id = kb->pkt->pkt.user_id;
    3771           5 :       if (user_id->is_revoked)
    3772             :         /* Skip revoked user ids.  (Don't skip expired user ids, the
    3773             :            expiry can be changed.)  */
    3774           0 :         continue;
    3775             : 
    3776           5 :       email = email_from_user_id (user_id->name);
    3777             : 
    3778           5 :       err = record_binding (dbs, fingerprint, email, user_id->name,
    3779             :                             policy, TOFU_POLICY_NONE, NULL, 0, 1, now);
    3780           5 :       if (err)
    3781             :         {
    3782           0 :           log_error (_("error setting policy for key %s, user id \"%s\": %s"),
    3783             :                      fingerprint, email, gpg_strerror (err));
    3784           0 :           xfree (email);
    3785           0 :           break;
    3786             :         }
    3787             : 
    3788           5 :       xfree (email);
    3789             :     }
    3790             : 
    3791           5 :   if (err)
    3792           0 :     rollback_transaction (ctrl);
    3793             :   else
    3794           5 :     end_transaction (ctrl, 0);
    3795             : 
    3796           5 :   xfree (fingerprint);
    3797           5 :   return err;
    3798             : }
    3799             : 
    3800             : /* Set the TOFU policy for all non-revoked user ids in the KEY with
    3801             :    the key id KEYID to POLICY.
    3802             : 
    3803             :    If no key is available with the specified key id, then this
    3804             :    function returns GPG_ERR_NO_PUBKEY.
    3805             : 
    3806             :    Returns 0 on success and an error code otherwise.  */
    3807             : gpg_error_t
    3808           0 : tofu_set_policy_by_keyid (ctrl_t ctrl, u32 *keyid, enum tofu_policy policy)
    3809             : {
    3810           0 :   kbnode_t keyblock = get_pubkeyblock (keyid);
    3811           0 :   if (! keyblock)
    3812           0 :     return gpg_error (GPG_ERR_NO_PUBKEY);
    3813             : 
    3814           0 :   return tofu_set_policy (ctrl, keyblock, policy);
    3815             : }
    3816             : 
    3817             : /* Return the TOFU policy for the specified binding in *POLICY.  If no
    3818             :    policy has been set for the binding, sets *POLICY to
    3819             :    TOFU_POLICY_NONE.
    3820             : 
    3821             :    PK is a primary public key and USER_ID is a user id.
    3822             : 
    3823             :    Returns 0 on success and an error code otherwise.  */
    3824             : gpg_error_t
    3825           0 : tofu_get_policy (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *user_id,
    3826             :                  enum tofu_policy *policy)
    3827             : {
    3828           0 :   time_t now = gnupg_get_time ();
    3829             :   tofu_dbs_t dbs;
    3830             :   char *fingerprint;
    3831             :   char *email;
    3832             : 
    3833             :   /* Make sure PK is a primary key.  */
    3834           0 :   log_assert (pk_is_primary (pk));
    3835             : 
    3836           0 :   dbs = opendbs (ctrl);
    3837           0 :   if (! dbs)
    3838             :     {
    3839           0 :       log_error (_("error opening TOFU database: %s\n"),
    3840             :                  gpg_strerror (GPG_ERR_GENERAL));
    3841           0 :       return gpg_error (GPG_ERR_GENERAL);
    3842             :     }
    3843             : 
    3844           0 :   fingerprint = hexfingerprint (pk, NULL, 0);
    3845             : 
    3846           0 :   email = email_from_user_id (user_id->name);
    3847             : 
    3848           0 :   *policy = get_policy (dbs, pk, fingerprint, user_id->name, email, NULL, now);
    3849             : 
    3850           0 :   xfree (email);
    3851           0 :   xfree (fingerprint);
    3852           0 :   if (*policy == _tofu_GET_POLICY_ERROR)
    3853           0 :     return gpg_error (GPG_ERR_GENERAL);
    3854           0 :   return 0;
    3855             : }
    3856             : 
    3857             : gpg_error_t
    3858          12 : tofu_notice_key_changed (ctrl_t ctrl, kbnode_t kb)
    3859             : {
    3860             :   tofu_dbs_t dbs;
    3861             :   PKT_public_key *pk;
    3862             :   char *fingerprint;
    3863          12 :   char *sqlerr = NULL;
    3864             :   int rc;
    3865             : 
    3866             :   /* Make sure PK is a primary key.  */
    3867          12 :   setup_main_keyids (kb);
    3868          12 :   pk = kb->pkt->pkt.public_key;
    3869          12 :   log_assert (pk_is_primary (pk));
    3870             : 
    3871          12 :   dbs = opendbs (ctrl);
    3872          12 :   if (! dbs)
    3873             :     {
    3874           0 :       log_error (_("error opening TOFU database: %s\n"),
    3875             :                  gpg_strerror (GPG_ERR_GENERAL));
    3876           0 :       return gpg_error (GPG_ERR_GENERAL);
    3877             :     }
    3878             : 
    3879          12 :   fingerprint = hexfingerprint (pk, NULL, 0);
    3880             : 
    3881          12 :   rc = gpgsql_stepx (dbs->db, NULL, NULL, NULL, &sqlerr,
    3882             :                      "update bindings set effective_policy = ?"
    3883             :                      " where fingerprint = ?;",
    3884             :                      GPGSQL_ARG_INT, (int) TOFU_POLICY_NONE,
    3885             :                      GPGSQL_ARG_STRING, fingerprint,
    3886             :                      GPGSQL_ARG_END);
    3887          12 :   xfree (fingerprint);
    3888             : 
    3889          12 :   if (rc == _tofu_GET_POLICY_ERROR)
    3890           0 :     return gpg_error (GPG_ERR_GENERAL);
    3891          12 :   return 0;
    3892             : }

Generated by: LCOV version 1.11