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