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 : }
|