Line data Source code
1 : /* tdbio.c - trust database I/O operations
2 : * Copyright (C) 1998-2002, 2012 Free Software Foundation, Inc.
3 : * Copyright (C) 1998-2015 Werner Koch
4 : *
5 : * This file is part of GnuPG.
6 : *
7 : * GnuPG is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU General Public License as published by
9 : * the Free Software Foundation; either version 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * GnuPG is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License
18 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <config.h>
22 : #include <stdio.h>
23 : #include <stdlib.h>
24 : #include <string.h>
25 : #include <errno.h>
26 : #include <assert.h>
27 : #include <sys/types.h>
28 : #include <sys/stat.h>
29 : #include <fcntl.h>
30 : #include <unistd.h>
31 :
32 : #include "gpg.h"
33 : #include "status.h"
34 : #include "iobuf.h"
35 : #include "util.h"
36 : #include "options.h"
37 : #include "main.h"
38 : #include "i18n.h"
39 : #include "trustdb.h"
40 : #include "tdbio.h"
41 :
42 : #if defined(HAVE_DOSISH_SYSTEM) && !defined(ftruncate)
43 : #define ftruncate chsize
44 : #endif
45 :
46 : #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
47 : #define MY_O_BINARY O_BINARY
48 : #else
49 : #define MY_O_BINARY 0
50 : #endif
51 :
52 : /* We use ERRNO despite that the cegcc provided open/read/write
53 : functions don't set ERRNO - at least show that ERRNO does not make
54 : sense. */
55 : #ifdef HAVE_W32CE_SYSTEM
56 : #undef strerror
57 : #define strerror(a) ("[errno not available]")
58 : #endif
59 :
60 : /*
61 : * Yes, this is a very simple implementation. We should really
62 : * use a page aligned buffer and read complete pages.
63 : * To implement a simple trannsaction system, this is sufficient.
64 : */
65 : typedef struct cache_ctrl_struct *CACHE_CTRL;
66 : struct cache_ctrl_struct
67 : {
68 : CACHE_CTRL next;
69 : struct {
70 : unsigned used:1;
71 : unsigned dirty:1;
72 : } flags;
73 : ulong recno;
74 : char data[TRUST_RECORD_LEN];
75 : };
76 :
77 : /* Size of the cache. The SOFT value is the general one. While in a
78 : transaction this may not be sufficient and thus we may increase it
79 : then up to the HARD limit. */
80 : #define MAX_CACHE_ENTRIES_SOFT 200
81 : #define MAX_CACHE_ENTRIES_HARD 10000
82 :
83 :
84 : /* The cache is controlled by these variables. */
85 : static CACHE_CTRL cache_list;
86 : static int cache_entries;
87 : static int cache_is_dirty;
88 :
89 :
90 : /* An object to pass infomation to cmp_krec_fpr. */
91 : struct cmp_krec_fpr_struct
92 : {
93 : int pubkey_algo;
94 : const char *fpr;
95 : int fprlen;
96 : };
97 :
98 : /* An object used to pass infomation to cmp_[s]dir. */
99 : struct cmp_xdir_struct
100 : {
101 : int pubkey_algo;
102 : u32 keyid[2];
103 : };
104 :
105 :
106 : /* The name of the trustdb file. */
107 : static char *db_name;
108 :
109 : /* The handle for locking the trustdb file and a flag to record
110 : whether a lock has been taken. */
111 : static dotlock_t lockhandle;
112 : static int is_locked;
113 :
114 : /* The file descriptor of the trustdb. */
115 : static int db_fd = -1;
116 :
117 : /* A flag indicating that a transaction is active. */
118 : static int in_transaction;
119 :
120 :
121 :
122 : static void open_db (void);
123 :
124 :
125 :
126 : /*
127 : * Take a lock on the trustdb file name. I a lock file can't be
128 : * created the function terminates the process. Excvept for a
129 : * different return code the function does nothing if the lock has
130 : * already been taken.
131 : *
132 : * Returns: True if lock already exists, False if the lock has
133 : * actually been taken.
134 : */
135 : static int
136 5 : take_write_lock (void)
137 : {
138 5 : if (!lockhandle)
139 3 : lockhandle = dotlock_create (db_name, 0);
140 5 : if (!lockhandle)
141 0 : log_fatal ( _("can't create lock for '%s'\n"), db_name );
142 :
143 5 : if (!is_locked)
144 : {
145 4 : if (dotlock_take (lockhandle, -1) )
146 0 : log_fatal ( _("can't lock '%s'\n"), db_name );
147 : else
148 4 : is_locked = 1;
149 4 : return 0;
150 : }
151 : else
152 1 : return 1;
153 : }
154 :
155 :
156 : /*
157 : * Release a lock from the trustdb file unless the global option
158 : * --lock-once has been used.
159 : */
160 : static void
161 4 : release_write_lock (void)
162 : {
163 4 : if (!opt.lock_once)
164 4 : if (!dotlock_release (lockhandle))
165 4 : is_locked = 0;
166 4 : }
167 :
168 : /*************************************
169 : ************* record cache **********
170 : *************************************/
171 :
172 : /*
173 : * Get the data from the record cache and return a pointer into that
174 : * cache. Caller should copy the returned data. NULL is returned on
175 : * a cache miss.
176 : */
177 : static const char *
178 11975 : get_record_from_cache (ulong recno)
179 : {
180 : CACHE_CTRL r;
181 :
182 12546 : for (r = cache_list; r; r = r->next)
183 : {
184 625 : if (r->flags.used && r->recno == recno)
185 54 : return r->data;
186 : }
187 11921 : return NULL;
188 : }
189 :
190 :
191 : /*
192 : * Write a cached item back to the trustdb file.
193 : *
194 : * Returns: 0 on success or an error code.
195 : */
196 : static int
197 36 : write_cache_item (CACHE_CTRL r)
198 : {
199 : gpg_error_t err;
200 : int n;
201 :
202 36 : if (lseek (db_fd, r->recno * TRUST_RECORD_LEN, SEEK_SET) == -1)
203 : {
204 0 : err = gpg_error_from_syserror ();
205 0 : log_error (_("trustdb rec %lu: lseek failed: %s\n"),
206 0 : r->recno, strerror (errno));
207 0 : return err;
208 : }
209 36 : n = write (db_fd, r->data, TRUST_RECORD_LEN);
210 36 : if (n != TRUST_RECORD_LEN)
211 : {
212 0 : err = gpg_error_from_syserror ();
213 0 : log_error (_("trustdb rec %lu: write failed (n=%d): %s\n"),
214 0 : r->recno, n, strerror (errno) );
215 0 : return err;
216 : }
217 36 : r->flags.dirty = 0;
218 36 : return 0;
219 : }
220 :
221 :
222 : /*
223 : * Put data into the cache. This function may flush
224 : * some cache entries if the cache is filled up.
225 : *
226 : * Returns: 0 on success or an error code.
227 : */
228 : static int
229 36 : put_record_into_cache (ulong recno, const char *data)
230 : {
231 : CACHE_CTRL r, unused;
232 36 : int dirty_count = 0;
233 36 : int clean_count = 0;
234 :
235 : /* See whether we already cached this one. */
236 504 : for (unused = NULL, r = cache_list; r; r = r->next)
237 : {
238 469 : if (!r->flags.used)
239 : {
240 0 : if (!unused)
241 0 : unused = r;
242 : }
243 469 : else if (r->recno == recno)
244 : {
245 1 : if (!r->flags.dirty)
246 : {
247 : /* Hmmm: should we use a copy and compare? */
248 1 : if (memcmp (r->data, data, TRUST_RECORD_LEN))
249 : {
250 1 : r->flags.dirty = 1;
251 1 : cache_is_dirty = 1;
252 : }
253 : }
254 1 : memcpy (r->data, data, TRUST_RECORD_LEN);
255 1 : return 0;
256 : }
257 468 : if (r->flags.used)
258 : {
259 468 : if (r->flags.dirty)
260 439 : dirty_count++;
261 : else
262 29 : clean_count++;
263 : }
264 : }
265 :
266 : /* Not in the cache: add a new entry. */
267 35 : if (unused)
268 : {
269 : /* Reuse this entry. */
270 0 : r = unused;
271 0 : r->flags.used = 1;
272 0 : r->recno = recno;
273 0 : memcpy (r->data, data, TRUST_RECORD_LEN);
274 0 : r->flags.dirty = 1;
275 0 : cache_is_dirty = 1;
276 0 : cache_entries++;
277 0 : return 0;
278 : }
279 :
280 : /* See whether we reached the limit. */
281 35 : if (cache_entries < MAX_CACHE_ENTRIES_SOFT)
282 : {
283 : /* No: Put into cache. */
284 35 : r = xmalloc (sizeof *r);
285 35 : r->flags.used = 1;
286 35 : r->recno = recno;
287 35 : memcpy (r->data, data, TRUST_RECORD_LEN);
288 35 : r->flags.dirty = 1;
289 35 : r->next = cache_list;
290 35 : cache_list = r;
291 35 : cache_is_dirty = 1;
292 35 : cache_entries++;
293 35 : return 0;
294 : }
295 :
296 : /* Cache is full: discard some clean entries. */
297 0 : if (clean_count)
298 : {
299 : int n;
300 :
301 : /* We discard a third of the clean entries. */
302 0 : n = clean_count / 3;
303 0 : if (!n)
304 0 : n = 1;
305 :
306 0 : for (unused = NULL, r = cache_list; r; r = r->next)
307 : {
308 0 : if (r->flags.used && !r->flags.dirty)
309 : {
310 0 : if (!unused)
311 0 : unused = r;
312 0 : r->flags.used = 0;
313 0 : cache_entries--;
314 0 : if (!--n)
315 0 : break;
316 : }
317 : }
318 :
319 : /* Now put into the cache. */
320 0 : assert (unused);
321 0 : r = unused;
322 0 : r->flags.used = 1;
323 0 : r->recno = recno;
324 0 : memcpy (r->data, data, TRUST_RECORD_LEN);
325 0 : r->flags.dirty = 1;
326 0 : cache_is_dirty = 1;
327 0 : cache_entries++;
328 0 : return 0;
329 : }
330 :
331 : /* No clean entries: We have to flush some dirty entries. */
332 0 : if (in_transaction)
333 : {
334 : /* But we can't do this while in a transaction. Thus we
335 : * increase the cache size instead. */
336 0 : if (cache_entries < MAX_CACHE_ENTRIES_HARD)
337 : {
338 0 : if (opt.debug && !(cache_entries % 100))
339 0 : log_debug ("increasing tdbio cache size\n");
340 0 : r = xmalloc (sizeof *r);
341 0 : r->flags.used = 1;
342 0 : r->recno = recno;
343 0 : memcpy (r->data, data, TRUST_RECORD_LEN);
344 0 : r->flags.dirty = 1;
345 0 : r->next = cache_list;
346 0 : cache_list = r;
347 0 : cache_is_dirty = 1;
348 0 : cache_entries++;
349 0 : return 0;
350 : }
351 : /* Hard limit for the cache size reached. */
352 0 : log_info (_("trustdb transaction too large\n"));
353 0 : return GPG_ERR_RESOURCE_LIMIT;
354 : }
355 :
356 0 : if (dirty_count)
357 : {
358 : int n;
359 :
360 : /* Discard some dirty entries. */
361 0 : n = dirty_count / 5;
362 0 : if (!n)
363 0 : n = 1;
364 :
365 0 : take_write_lock ();
366 0 : for (unused = NULL, r = cache_list; r; r = r->next)
367 : {
368 0 : if (r->flags.used && r->flags.dirty)
369 : {
370 : int rc;
371 :
372 0 : rc = write_cache_item (r);
373 0 : if (rc)
374 0 : return rc;
375 0 : if (!unused)
376 0 : unused = r;
377 0 : r->flags.used = 0;
378 0 : cache_entries--;
379 0 : if (!--n)
380 0 : break;
381 : }
382 : }
383 0 : release_write_lock ();
384 :
385 : /* Now put into the cache. */
386 0 : assert (unused);
387 0 : r = unused;
388 0 : r->flags.used = 1;
389 0 : r->recno = recno;
390 0 : memcpy (r->data, data, TRUST_RECORD_LEN);
391 0 : r->flags.dirty = 1;
392 0 : cache_is_dirty = 1;
393 0 : cache_entries++;
394 0 : return 0;
395 : }
396 :
397 : /* We should never reach this. */
398 0 : BUG();
399 : }
400 :
401 :
402 : /* Return true if the cache is dirty. */
403 : int
404 0 : tdbio_is_dirty()
405 : {
406 0 : return cache_is_dirty;
407 : }
408 :
409 :
410 : /*
411 : * Flush the cache. This cannot be used while in a transaction.
412 : */
413 : int
414 5 : tdbio_sync()
415 : {
416 : CACHE_CTRL r;
417 5 : int did_lock = 0;
418 :
419 5 : if( db_fd == -1 )
420 0 : open_db();
421 5 : if( in_transaction )
422 0 : log_bug("tdbio: syncing while in transaction\n");
423 :
424 5 : if( !cache_is_dirty )
425 1 : return 0;
426 :
427 4 : if (!take_write_lock ())
428 3 : did_lock = 1;
429 :
430 40 : for( r = cache_list; r; r = r->next ) {
431 36 : if( r->flags.used && r->flags.dirty ) {
432 36 : int rc = write_cache_item( r );
433 36 : if( rc )
434 0 : return rc;
435 : }
436 : }
437 4 : cache_is_dirty = 0;
438 4 : if (did_lock)
439 3 : release_write_lock ();
440 :
441 4 : return 0;
442 : }
443 :
444 :
445 : #if 0 /* Not yet used. */
446 : /*
447 : * Simple transactions system:
448 : * Everything between begin_transaction and end/cancel_transaction
449 : * is not immediatly written but at the time of end_transaction.
450 : *
451 : * NOTE: The transaction code is disabled in the 1.2 branch, as it is
452 : * not yet used.
453 : */
454 : int
455 : tdbio_begin_transaction () /* Not yet used. */
456 : {
457 : int rc;
458 :
459 : if (in_transaction)
460 : log_bug ("tdbio: nested transactions\n");
461 : /* Flush everything out. */
462 : rc = tdbio_sync();
463 : if (rc)
464 : return rc;
465 : in_transaction = 1;
466 : return 0;
467 : }
468 :
469 : int
470 : tdbio_end_transaction () /* Not yet used. */
471 : {
472 : int rc;
473 :
474 : if (!in_transaction)
475 : log_bug ("tdbio: no active transaction\n");
476 : take_write_lock ();
477 : gnupg_block_all_signals ();
478 : in_transaction = 0;
479 : rc = tdbio_sync();
480 : gnupg_unblock_all_signals();
481 : release_write_lock ();
482 : return rc;
483 : }
484 :
485 : int
486 : tdbio_cancel_transaction () /* Not yet used. */
487 : {
488 : CACHE_CTRL r;
489 :
490 : if (!in_transaction)
491 : log_bug ("tdbio: no active transaction\n");
492 :
493 : /* Remove all dirty marked entries, so that the original ones are
494 : * read back the next time. */
495 : if (cache_is_dirty)
496 : {
497 : for (r = cache_list; r; r = r->next)
498 : {
499 : if (r->flags.used && r->flags.dirty)
500 : {
501 : r->flags.used = 0;
502 : cache_entries--;
503 : }
504 : }
505 : cache_is_dirty = 0;
506 : }
507 :
508 : in_transaction = 0;
509 : return 0;
510 : }
511 : #endif /* Not yet used. */
512 :
513 :
514 :
515 : /********************************************************
516 : **************** cached I/O functions ******************
517 : ********************************************************/
518 :
519 : /* The cleanup handler for this module. */
520 : static void
521 537 : cleanup (void)
522 : {
523 537 : if (is_locked)
524 : {
525 0 : if (!dotlock_release (lockhandle))
526 0 : is_locked = 0;
527 : }
528 537 : }
529 :
530 :
531 : /*
532 : * Update an existing trustdb record. The caller must call
533 : * tdbio_sync.
534 : *
535 : * Returns: 0 on success or an error code.
536 : */
537 : int
538 0 : tdbio_update_version_record (void)
539 : {
540 : TRUSTREC rec;
541 : int rc;
542 :
543 0 : memset (&rec, 0, sizeof rec);
544 :
545 0 : rc = tdbio_read_record (0, &rec, RECTYPE_VER);
546 0 : if (!rc)
547 : {
548 0 : rec.r.ver.created = make_timestamp();
549 0 : rec.r.ver.marginals = opt.marginals_needed;
550 0 : rec.r.ver.completes = opt.completes_needed;
551 0 : rec.r.ver.cert_depth = opt.max_cert_depth;
552 0 : rec.r.ver.trust_model = opt.trust_model;
553 0 : rec.r.ver.min_cert_level = opt.min_cert_level;
554 0 : rc=tdbio_write_record(&rec);
555 : }
556 :
557 0 : return rc;
558 : }
559 :
560 :
561 : /*
562 : * Create and write the trustdb version record.
563 : *
564 : * Returns: 0 on success or an error code.
565 : */
566 : static int
567 1 : create_version_record (void)
568 : {
569 : TRUSTREC rec;
570 : int rc;
571 :
572 1 : memset (&rec, 0, sizeof rec);
573 1 : rec.r.ver.version = 3;
574 1 : rec.r.ver.created = make_timestamp ();
575 1 : rec.r.ver.marginals = opt.marginals_needed;
576 1 : rec.r.ver.completes = opt.completes_needed;
577 1 : rec.r.ver.cert_depth = opt.max_cert_depth;
578 1 : if (opt.trust_model == TM_PGP || opt.trust_model == TM_CLASSIC)
579 0 : rec.r.ver.trust_model = opt.trust_model;
580 : else
581 1 : rec.r.ver.trust_model = TM_PGP;
582 1 : rec.r.ver.min_cert_level = opt.min_cert_level;
583 1 : rec.rectype = RECTYPE_VER;
584 1 : rec.recnum = 0;
585 1 : rc = tdbio_write_record (&rec);
586 1 : if (!rc)
587 1 : tdbio_sync ();
588 1 : return rc;
589 : }
590 :
591 :
592 : /*
593 : * Set the file name for the trustdb to NEW_DBNAME and if CREATE is
594 : * true create that file. If NEW_DBNAME is NULL a default name is
595 : * used, if the it does not contain a path component separator ('/')
596 : * the global GnuPG home directory is used.
597 : *
598 : * Returns: 0 on success or an error code.
599 : *
600 : * On the first call this function registers an atexit handler.
601 : *
602 : */
603 : int
604 537 : tdbio_set_dbname (const char *new_dbname, int create, int *r_nofile)
605 : {
606 : char *fname;
607 : struct stat statbuf;
608 : static int initialized = 0;
609 :
610 537 : if (!initialized)
611 : {
612 537 : atexit (cleanup);
613 537 : initialized = 1;
614 : }
615 :
616 537 : *r_nofile = 0;
617 :
618 537 : if (!new_dbname)
619 : {
620 537 : fname = make_filename (opt.homedir, "trustdb" EXTSEP_S GPGEXT_GPG, NULL);
621 : }
622 0 : else if (*new_dbname != DIRSEP_C )
623 : {
624 0 : if (strchr (new_dbname, DIRSEP_C))
625 0 : fname = make_filename (new_dbname, NULL);
626 : else
627 0 : fname = make_filename (opt.homedir, new_dbname, NULL);
628 : }
629 : else
630 : {
631 0 : fname = xstrdup (new_dbname);
632 : }
633 :
634 537 : xfree (db_name);
635 537 : db_name = fname;
636 :
637 : /* Quick check for (likely) case where there already is a
638 : * trustdb.gpg. This check is not required in theory, but it helps
639 : * in practice avoiding costly operations of preparing and taking
640 : * the lock. */
641 537 : if (!stat (fname, &statbuf) && statbuf.st_size > 0)
642 : {
643 : /* OK, we have the valid trustdb.gpg already. */
644 536 : return 0;
645 : }
646 :
647 1 : take_write_lock ();
648 :
649 1 : if (access (fname, R_OK))
650 : {
651 : #ifdef HAVE_W32CE_SYSTEM
652 : /* We know how the cegcc implementation of access works ;-). */
653 : if (GetLastError () == ERROR_FILE_NOT_FOUND)
654 : gpg_err_set_errno (ENOENT);
655 : else
656 : gpg_err_set_errno (EIO);
657 : #endif /*HAVE_W32CE_SYSTEM*/
658 1 : if (errno != ENOENT)
659 0 : log_fatal ( _("can't access '%s': %s\n"), fname, strerror (errno));
660 :
661 1 : if (!create)
662 0 : *r_nofile = 1;
663 : else
664 : {
665 : FILE *fp;
666 : TRUSTREC rec;
667 : int rc;
668 1 : char *p = strrchr (fname, DIRSEP_C);
669 : mode_t oldmask;
670 : int save_slash;
671 :
672 : #if HAVE_W32_SYSTEM
673 : {
674 : /* Windows may either have a slash or a backslash. Take
675 : care of it. */
676 : char *pp = strrchr (fname, '/');
677 : if (!p || pp > p)
678 : p = pp;
679 : }
680 : #endif /*HAVE_W32_SYSTEM*/
681 1 : assert (p);
682 1 : save_slash = *p;
683 1 : *p = 0;
684 1 : if (access (fname, F_OK))
685 : {
686 0 : try_make_homedir (fname);
687 0 : if (access (fname, F_OK))
688 0 : log_fatal (_("%s: directory does not exist!\n"), fname);
689 : }
690 1 : *p = save_slash;
691 :
692 1 : oldmask = umask (077);
693 1 : if (is_secured_filename (fname))
694 : {
695 0 : fp = NULL;
696 0 : gpg_err_set_errno (EPERM);
697 : }
698 : else
699 1 : fp = fopen (fname, "wb");
700 1 : umask(oldmask);
701 1 : if (!fp)
702 0 : log_fatal (_("can't create '%s': %s\n"), fname, strerror (errno));
703 1 : fclose (fp);
704 :
705 1 : db_fd = open (db_name, O_RDWR | MY_O_BINARY);
706 1 : if (db_fd == -1)
707 0 : log_fatal (_("can't open '%s': %s\n"), db_name, strerror (errno));
708 :
709 1 : rc = create_version_record ();
710 1 : if (rc)
711 0 : log_fatal (_("%s: failed to create version record: %s"),
712 : fname, gpg_strerror (rc));
713 :
714 : /* Read again to check that we are okay. */
715 1 : if (tdbio_read_record (0, &rec, RECTYPE_VER))
716 0 : log_fatal (_("%s: invalid trustdb created\n"), db_name);
717 :
718 1 : if (!opt.quiet)
719 1 : log_info (_("%s: trustdb created\n"), db_name);
720 : }
721 : }
722 :
723 1 : release_write_lock ();
724 1 : return 0;
725 : }
726 :
727 :
728 : /*
729 : * Return the full name of the trustdb.
730 : */
731 : const char *
732 0 : tdbio_get_dbname ()
733 : {
734 0 : return db_name;
735 : }
736 :
737 :
738 : /*
739 : * Open the trustdb. This may only be called if it has not yet been
740 : * opened and after a successful call to tdbio_set_dbname. On return
741 : * the trustdb handle (DB_FD) is guaranteed to be open.
742 : */
743 : static void
744 422 : open_db ()
745 : {
746 : TRUSTREC rec;
747 :
748 422 : assert( db_fd == -1 );
749 :
750 : #ifdef HAVE_W32CE_SYSTEM
751 : {
752 : DWORD prevrc = 0;
753 : wchar_t *wname = utf8_to_wchar (db_name);
754 : if (wname)
755 : {
756 : db_fd = (int)CreateFile (wname, GENERIC_READ|GENERIC_WRITE,
757 : FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
758 : OPEN_EXISTING, 0, NULL);
759 : xfree (wname);
760 : }
761 : if (db_fd == -1)
762 : log_fatal ("can't open '%s': %d, %d\n", db_name,
763 : (int)prevrc, (int)GetLastError ());
764 : }
765 : #else /*!HAVE_W32CE_SYSTEM*/
766 422 : db_fd = open (db_name, O_RDWR | MY_O_BINARY );
767 422 : if (db_fd == -1 && (errno == EACCES
768 : #ifdef EROFS
769 0 : || errno == EROFS
770 : #endif
771 : )
772 : ) {
773 : /* Take care of read-only trustdbs. */
774 0 : db_fd = open (db_name, O_RDONLY | MY_O_BINARY );
775 0 : if (db_fd != -1 && !opt.quiet)
776 0 : log_info (_("Note: trustdb not writable\n"));
777 : }
778 422 : if ( db_fd == -1 )
779 0 : log_fatal( _("can't open '%s': %s\n"), db_name, strerror(errno) );
780 : #endif /*!HAVE_W32CE_SYSTEM*/
781 422 : register_secured_file (db_name);
782 :
783 : /* Read the version record. */
784 422 : if (tdbio_read_record (0, &rec, RECTYPE_VER ) )
785 0 : log_fatal( _("%s: invalid trustdb\n"), db_name );
786 422 : }
787 :
788 :
789 : /*
790 : * Append a new empty hashtable to the trustdb. TYPE gives the type
791 : * of the hash table. The only defined type is 0 for a trust hash.
792 : * On return the hashtable has been created, written, the version
793 : * record update, and the data flushed to the disk. On a fatal error
794 : * the function terminates the process.
795 : */
796 : static void
797 1 : create_hashtable( TRUSTREC *vr, int type )
798 : {
799 : TRUSTREC rec;
800 : off_t offset;
801 : ulong recnum;
802 : int i, n, rc;
803 :
804 1 : offset = lseek (db_fd, 0, SEEK_END);
805 1 : if (offset == -1)
806 0 : log_fatal ("trustdb: lseek to end failed: %s\n", strerror(errno));
807 1 : recnum = offset / TRUST_RECORD_LEN;
808 1 : assert (recnum); /* This is will never be the first record. */
809 :
810 1 : if (!type)
811 1 : vr->r.ver.trusthashtbl = recnum;
812 :
813 : /* Now write the records making up the hash table. */
814 1 : n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD;
815 30 : for (i=0; i < n; i++, recnum++)
816 : {
817 29 : memset (&rec, 0, sizeof rec);
818 29 : rec.rectype = RECTYPE_HTBL;
819 29 : rec.recnum = recnum;
820 29 : rc = tdbio_write_record (&rec);
821 29 : if (rc)
822 0 : log_fatal (_("%s: failed to create hashtable: %s\n"),
823 : db_name, gpg_strerror (rc));
824 : }
825 : /* Update the version record and flush. */
826 1 : rc = tdbio_write_record (vr);
827 1 : if (!rc)
828 1 : rc = tdbio_sync ();
829 1 : if (rc)
830 0 : log_fatal (_("%s: error updating version record: %s\n"),
831 : db_name, gpg_strerror (rc));
832 1 : }
833 :
834 :
835 : /*
836 : * Check whether open trustdb matches the global trust options given
837 : * for this process. On a read problem the process is terminated.
838 : *
839 : * Return: 1 for yes, 0 for no.
840 : */
841 : int
842 301 : tdbio_db_matches_options()
843 : {
844 : static int yes_no = -1;
845 :
846 301 : if (yes_no == -1)
847 : {
848 : TRUSTREC vr;
849 : int rc;
850 :
851 301 : rc = tdbio_read_record (0, &vr, RECTYPE_VER);
852 301 : if( rc )
853 0 : log_fatal( _("%s: error reading version record: %s\n"),
854 : db_name, gpg_strerror (rc) );
855 :
856 602 : yes_no = vr.r.ver.marginals == opt.marginals_needed
857 301 : && vr.r.ver.completes == opt.completes_needed
858 301 : && vr.r.ver.cert_depth == opt.max_cert_depth
859 301 : && vr.r.ver.trust_model == opt.trust_model
860 514 : && vr.r.ver.min_cert_level == opt.min_cert_level;
861 : }
862 :
863 301 : return yes_no;
864 : }
865 :
866 :
867 : /*
868 : * Read and return the trust model identifier from the trustdb. On a
869 : * read problem the process is terminated.
870 : */
871 : byte
872 213 : tdbio_read_model (void)
873 : {
874 : TRUSTREC vr;
875 : int rc;
876 :
877 213 : rc = tdbio_read_record (0, &vr, RECTYPE_VER );
878 213 : if (rc)
879 0 : log_fatal (_("%s: error reading version record: %s\n"),
880 : db_name, gpg_strerror (rc) );
881 213 : return vr.r.ver.trust_model;
882 : }
883 :
884 :
885 : /*
886 : * Read and return the nextstamp value from the trustdb. On a read
887 : * problem the process is terminated.
888 : */
889 : ulong
890 229 : tdbio_read_nextcheck ()
891 : {
892 : TRUSTREC vr;
893 : int rc;
894 :
895 229 : rc = tdbio_read_record (0, &vr, RECTYPE_VER);
896 229 : if (rc)
897 0 : log_fatal (_("%s: error reading version record: %s\n"),
898 : db_name, gpg_strerror (rc));
899 229 : return vr.r.ver.nextcheck;
900 : }
901 :
902 :
903 : /*
904 : * Write the STAMP nextstamp timestamp to the trustdb. On a read or
905 : * write problem the process is terminated.
906 : *
907 : * Return: True if the stamp actually changed.
908 : */
909 : int
910 5 : tdbio_write_nextcheck (ulong stamp)
911 : {
912 : TRUSTREC vr;
913 : int rc;
914 :
915 5 : rc = tdbio_read_record (0, &vr, RECTYPE_VER);
916 5 : if (rc)
917 0 : log_fatal (_("%s: error reading version record: %s\n"),
918 : db_name, gpg_strerror (rc));
919 :
920 5 : if (vr.r.ver.nextcheck == stamp)
921 4 : return 0;
922 :
923 1 : vr.r.ver.nextcheck = stamp;
924 1 : rc = tdbio_write_record( &vr );
925 1 : if (rc)
926 0 : log_fatal (_("%s: error writing version record: %s\n"),
927 : db_name, gpg_strerror (rc));
928 1 : return 1;
929 : }
930 :
931 :
932 :
933 : /*
934 : * Return the record number of the trusthash table or create one if it
935 : * does not yet exist. On a read or write problem the process is
936 : * terminated.
937 : *
938 : * Return: record number
939 : */
940 : static ulong
941 969 : get_trusthashrec(void)
942 : {
943 : static ulong trusthashtbl; /* Record number of the trust hashtable. */
944 :
945 969 : if (!trusthashtbl)
946 : {
947 : TRUSTREC vr;
948 : int rc;
949 :
950 417 : rc = tdbio_read_record (0, &vr, RECTYPE_VER );
951 417 : if (rc)
952 0 : log_fatal (_("%s: error reading version record: %s\n"),
953 : db_name, gpg_strerror (rc) );
954 417 : if (!vr.r.ver.trusthashtbl)
955 1 : create_hashtable (&vr, 0);
956 :
957 417 : trusthashtbl = vr.r.ver.trusthashtbl;
958 : }
959 :
960 969 : return trusthashtbl;
961 : }
962 :
963 :
964 :
965 : /*
966 : * Update a hashtable in the trustdb. TABLE gives the start of the
967 : * table, KEY and KEYLEN are the key, NEWRECNUM is the record number
968 : * to insert into the table.
969 : *
970 : * Return: 0 on success or an error code.
971 : */
972 : static int
973 2 : upd_hashtable (ulong table, byte *key, int keylen, ulong newrecnum)
974 : {
975 : TRUSTREC lastrec, rec;
976 : ulong hashrec, item;
977 : int msb;
978 2 : int level = 0;
979 : int rc, i;
980 :
981 2 : hashrec = table;
982 : next_level:
983 2 : msb = key[level];
984 2 : hashrec += msb / ITEMS_PER_HTBL_RECORD;
985 2 : rc = tdbio_read_record (hashrec, &rec, RECTYPE_HTBL);
986 2 : if (rc)
987 : {
988 0 : log_error ("upd_hashtable: read failed: %s\n", gpg_strerror (rc));
989 0 : return rc;
990 : }
991 :
992 2 : item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
993 2 : if (!item) /* Insert a new item into the hash table. */
994 : {
995 2 : rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = newrecnum;
996 2 : rc = tdbio_write_record (&rec);
997 2 : if (rc)
998 : {
999 0 : log_error ("upd_hashtable: write htbl failed: %s\n",
1000 : gpg_strerror (rc));
1001 0 : return rc;
1002 : }
1003 : }
1004 0 : else if (item != newrecnum) /* Must do an update. */
1005 : {
1006 0 : lastrec = rec;
1007 0 : rc = tdbio_read_record (item, &rec, 0);
1008 0 : if (rc)
1009 : {
1010 0 : log_error ("upd_hashtable: read item failed: %s\n",
1011 : gpg_strerror (rc));
1012 0 : return rc;
1013 : }
1014 :
1015 0 : if (rec.rectype == RECTYPE_HTBL)
1016 : {
1017 0 : hashrec = item;
1018 0 : level++;
1019 0 : if (level >= keylen)
1020 : {
1021 0 : log_error ("hashtable has invalid indirections.\n");
1022 0 : return GPG_ERR_TRUSTDB;
1023 : }
1024 0 : goto next_level;
1025 : }
1026 0 : else if (rec.rectype == RECTYPE_HLST) /* Extend the list. */
1027 : {
1028 : /* Check whether the key is already in this list. */
1029 : for (;;)
1030 : {
1031 0 : for (i=0; i < ITEMS_PER_HLST_RECORD; i++)
1032 : {
1033 0 : if (rec.r.hlst.rnum[i] == newrecnum)
1034 : {
1035 0 : return 0; /* Okay, already in the list. */
1036 : }
1037 : }
1038 0 : if (rec.r.hlst.next)
1039 : {
1040 0 : rc = tdbio_read_record (rec.r.hlst.next, &rec, RECTYPE_HLST);
1041 0 : if (rc)
1042 : {
1043 0 : log_error ("upd_hashtable: read hlst failed: %s\n",
1044 : gpg_strerror (rc) );
1045 0 : return rc;
1046 : }
1047 : }
1048 : else
1049 0 : break; /* key is not in the list */
1050 0 : }
1051 :
1052 : /* Find the next free entry and put it in. */
1053 : for (;;)
1054 : {
1055 0 : for (i=0; i < ITEMS_PER_HLST_RECORD; i++)
1056 : {
1057 0 : if (!rec.r.hlst.rnum[i])
1058 : {
1059 : /* Empty slot found. */
1060 0 : rec.r.hlst.rnum[i] = newrecnum;
1061 0 : rc = tdbio_write_record (&rec);
1062 0 : if (rc)
1063 0 : log_error ("upd_hashtable: write hlst failed: %s\n",
1064 : gpg_strerror (rc));
1065 0 : return rc; /* Done. */
1066 : }
1067 : }
1068 :
1069 0 : if (rec.r.hlst.next)
1070 : {
1071 : /* read the next reord of the list. */
1072 0 : rc = tdbio_read_record (rec.r.hlst.next, &rec, RECTYPE_HLST);
1073 0 : if (rc)
1074 : {
1075 0 : log_error ("upd_hashtable: read hlst failed: %s\n",
1076 : gpg_strerror (rc));
1077 0 : return rc;
1078 : }
1079 : }
1080 : else
1081 : {
1082 : /* Append a new record to the list. */
1083 0 : rec.r.hlst.next = item = tdbio_new_recnum ();
1084 0 : rc = tdbio_write_record (&rec);
1085 0 : if (rc)
1086 : {
1087 0 : log_error ("upd_hashtable: write hlst failed: %s\n",
1088 : gpg_strerror (rc));
1089 0 : return rc;
1090 : }
1091 0 : memset (&rec, 0, sizeof rec);
1092 0 : rec.rectype = RECTYPE_HLST;
1093 0 : rec.recnum = item;
1094 0 : rec.r.hlst.rnum[0] = newrecnum;
1095 0 : rc = tdbio_write_record (&rec);
1096 0 : if (rc)
1097 0 : log_error ("upd_hashtable: write ext hlst failed: %s\n",
1098 : gpg_strerror (rc));
1099 0 : return rc; /* Done. */
1100 : }
1101 0 : } /* end loop over list slots */
1102 :
1103 : }
1104 0 : else if (rec.rectype == RECTYPE_TRUST) /* Insert a list record. */
1105 : {
1106 0 : if (rec.recnum == newrecnum)
1107 : {
1108 0 : return 0;
1109 : }
1110 0 : item = rec.recnum; /* Save number of key record. */
1111 0 : memset (&rec, 0, sizeof rec);
1112 0 : rec.rectype = RECTYPE_HLST;
1113 0 : rec.recnum = tdbio_new_recnum ();
1114 0 : rec.r.hlst.rnum[0] = item; /* Old key record */
1115 0 : rec.r.hlst.rnum[1] = newrecnum; /* and new key record */
1116 0 : rc = tdbio_write_record (&rec);
1117 0 : if (rc)
1118 : {
1119 0 : log_error( "upd_hashtable: write new hlst failed: %s\n",
1120 : gpg_strerror (rc) );
1121 0 : return rc;
1122 : }
1123 : /* Update the hashtable record. */
1124 0 : lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum;
1125 0 : rc = tdbio_write_record (&lastrec);
1126 0 : if (rc)
1127 0 : log_error ("upd_hashtable: update htbl failed: %s\n",
1128 : gpg_strerror (rc));
1129 0 : return rc; /* Ready. */
1130 : }
1131 : else
1132 : {
1133 0 : log_error ("hashtbl %lu: %lu/%d points to an invalid record %lu\n",
1134 : table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item);
1135 0 : if (opt.verbose > 1)
1136 0 : list_trustdb (es_stderr, NULL);
1137 0 : return GPG_ERR_TRUSTDB;
1138 : }
1139 : }
1140 :
1141 2 : return 0;
1142 : }
1143 :
1144 :
1145 : /*
1146 : * Drop an entry from a hashtable. TABLE gives the start of the
1147 : * table, KEY and KEYLEN are the key.
1148 : *
1149 : * Return: 0 on success or an error code.
1150 : */
1151 : static int
1152 0 : drop_from_hashtable (ulong table, byte *key, int keylen, ulong recnum)
1153 : {
1154 : TRUSTREC rec;
1155 : ulong hashrec, item;
1156 : int msb;
1157 0 : int level = 0;
1158 : int rc, i;
1159 :
1160 0 : hashrec = table;
1161 : next_level:
1162 0 : msb = key[level];
1163 0 : hashrec += msb / ITEMS_PER_HTBL_RECORD;
1164 0 : rc = tdbio_read_record (hashrec, &rec, RECTYPE_HTBL );
1165 0 : if (rc)
1166 : {
1167 0 : log_error ("drop_from_hashtable: read failed: %s\n", gpg_strerror (rc));
1168 0 : return rc;
1169 : }
1170 :
1171 0 : item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
1172 0 : if (!item)
1173 0 : return 0; /* Not found - forget about it. */
1174 :
1175 0 : if (item == recnum) /* Table points direct to the record. */
1176 : {
1177 0 : rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = 0;
1178 0 : rc = tdbio_write_record( &rec );
1179 0 : if (rc)
1180 0 : log_error ("drop_from_hashtable: write htbl failed: %s\n",
1181 : gpg_strerror (rc));
1182 0 : return rc;
1183 : }
1184 :
1185 0 : rc = tdbio_read_record (item, &rec, 0);
1186 0 : if (rc)
1187 : {
1188 0 : log_error ("drop_from_hashtable: read item failed: %s\n",
1189 : gpg_strerror (rc));
1190 0 : return rc;
1191 : }
1192 :
1193 0 : if (rec.rectype == RECTYPE_HTBL)
1194 : {
1195 0 : hashrec = item;
1196 0 : level++;
1197 0 : if (level >= keylen)
1198 : {
1199 0 : log_error ("hashtable has invalid indirections.\n");
1200 0 : return GPG_ERR_TRUSTDB;
1201 : }
1202 0 : goto next_level;
1203 : }
1204 :
1205 0 : if (rec.rectype == RECTYPE_HLST)
1206 : {
1207 : for (;;)
1208 : {
1209 0 : for (i=0; i < ITEMS_PER_HLST_RECORD; i++)
1210 : {
1211 0 : if (rec.r.hlst.rnum[i] == recnum)
1212 : {
1213 0 : rec.r.hlst.rnum[i] = 0; /* Mark as free. */
1214 0 : rc = tdbio_write_record (&rec);
1215 0 : if (rc)
1216 0 : log_error("drop_from_hashtable: write htbl failed: %s\n",
1217 : gpg_strerror (rc));
1218 0 : return rc;
1219 : }
1220 : }
1221 0 : if (rec.r.hlst.next)
1222 : {
1223 0 : rc = tdbio_read_record (rec.r.hlst.next, &rec, RECTYPE_HLST);
1224 0 : if (rc)
1225 : {
1226 0 : log_error ("drop_from_hashtable: read hlst failed: %s\n",
1227 : gpg_strerror (rc));
1228 0 : return rc;
1229 : }
1230 : }
1231 : else
1232 0 : return 0; /* Key not in table. */
1233 0 : }
1234 : }
1235 :
1236 0 : log_error ("hashtbl %lu: %lu/%d points to wrong record %lu\n",
1237 : table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item);
1238 0 : return GPG_ERR_TRUSTDB;
1239 : }
1240 :
1241 :
1242 :
1243 : /*
1244 : * Lookup a record via the hashtable TABLE by (KEY,KEYLEN) and return
1245 : * the result in REC. The return value of CMP() should be True if the
1246 : * record is the desired one.
1247 : *
1248 : * Return: 0 if found, GPG_ERR_NOT_FOUND, or another error code.
1249 : */
1250 : static gpg_error_t
1251 967 : lookup_hashtable (ulong table, const byte *key, size_t keylen,
1252 : int (*cmpfnc)(const void*, const TRUSTREC *),
1253 : const void *cmpdata, TRUSTREC *rec )
1254 : {
1255 : int rc;
1256 : ulong hashrec, item;
1257 : int msb;
1258 967 : int level = 0;
1259 :
1260 967 : hashrec = table;
1261 : next_level:
1262 967 : msb = key[level];
1263 967 : hashrec += msb / ITEMS_PER_HTBL_RECORD;
1264 967 : rc = tdbio_read_record (hashrec, rec, RECTYPE_HTBL);
1265 967 : if (rc)
1266 : {
1267 0 : log_error("lookup_hashtable failed: %s\n", gpg_strerror (rc) );
1268 0 : return rc;
1269 : }
1270 :
1271 967 : item = rec->r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
1272 967 : if (!item)
1273 963 : return gpg_error (GPG_ERR_NOT_FOUND);
1274 :
1275 4 : rc = tdbio_read_record (item, rec, 0);
1276 4 : if (rc)
1277 : {
1278 0 : log_error( "hashtable read failed: %s\n", gpg_strerror (rc) );
1279 0 : return rc;
1280 : }
1281 4 : if (rec->rectype == RECTYPE_HTBL)
1282 : {
1283 0 : hashrec = item;
1284 0 : level++;
1285 0 : if (level >= keylen)
1286 : {
1287 0 : log_error ("hashtable has invalid indirections\n");
1288 0 : return GPG_ERR_TRUSTDB;
1289 : }
1290 0 : goto next_level;
1291 : }
1292 4 : else if (rec->rectype == RECTYPE_HLST)
1293 : {
1294 : for (;;)
1295 : {
1296 : int i;
1297 :
1298 0 : for (i=0; i < ITEMS_PER_HLST_RECORD; i++)
1299 : {
1300 0 : if (rec->r.hlst.rnum[i])
1301 : {
1302 : TRUSTREC tmp;
1303 :
1304 0 : rc = tdbio_read_record (rec->r.hlst.rnum[i], &tmp, 0);
1305 0 : if (rc)
1306 : {
1307 0 : log_error ("lookup_hashtable: read item failed: %s\n",
1308 : gpg_strerror (rc));
1309 0 : return rc;
1310 : }
1311 0 : if ((*cmpfnc)(cmpdata, &tmp))
1312 : {
1313 0 : *rec = tmp;
1314 0 : return 0;
1315 : }
1316 : }
1317 : }
1318 0 : if (rec->r.hlst.next)
1319 : {
1320 0 : rc = tdbio_read_record (rec->r.hlst.next, rec, RECTYPE_HLST);
1321 0 : if (rc)
1322 : {
1323 0 : log_error ("lookup_hashtable: read hlst failed: %s\n",
1324 : gpg_strerror (rc) );
1325 0 : return rc;
1326 : }
1327 : }
1328 : else
1329 0 : return gpg_error (GPG_ERR_NOT_FOUND);
1330 0 : }
1331 : }
1332 :
1333 4 : if ((*cmpfnc)(cmpdata, rec))
1334 4 : return 0; /* really found */
1335 :
1336 0 : return gpg_error (GPG_ERR_NOT_FOUND); /* no: not found */
1337 : }
1338 :
1339 :
1340 : /*
1341 : * Update the trust hash table TR or create the table if it does not
1342 : * exist.
1343 : *
1344 : * Return: 0 on success or an error code.
1345 : */
1346 : static int
1347 2 : update_trusthashtbl( TRUSTREC *tr )
1348 : {
1349 4 : return upd_hashtable (get_trusthashrec(),
1350 2 : tr->r.trust.fingerprint, 20, tr->recnum);
1351 : }
1352 :
1353 :
1354 : /*
1355 : * Dump the trustdb record REC to stream FP.
1356 : */
1357 : void
1358 0 : tdbio_dump_record (TRUSTREC *rec, estream_t fp)
1359 : {
1360 : int i;
1361 0 : ulong rnum = rec->recnum;
1362 :
1363 0 : es_fprintf (fp, "rec %5lu, ", rnum);
1364 :
1365 0 : switch (rec->rectype)
1366 : {
1367 : case 0:
1368 0 : es_fprintf (fp, "blank\n");
1369 0 : break;
1370 :
1371 : case RECTYPE_VER:
1372 0 : es_fprintf (fp,
1373 : "version, td=%lu, f=%lu, m/c/d=%d/%d/%d tm=%d mcl=%d nc=%lu (%s)\n",
1374 : rec->r.ver.trusthashtbl,
1375 : rec->r.ver.firstfree,
1376 0 : rec->r.ver.marginals,
1377 0 : rec->r.ver.completes,
1378 0 : rec->r.ver.cert_depth,
1379 0 : rec->r.ver.trust_model,
1380 0 : rec->r.ver.min_cert_level,
1381 : rec->r.ver.nextcheck,
1382 0 : strtimestamp(rec->r.ver.nextcheck)
1383 : );
1384 0 : break;
1385 :
1386 : case RECTYPE_FREE:
1387 0 : es_fprintf (fp, "free, next=%lu\n", rec->r.free.next);
1388 0 : break;
1389 :
1390 : case RECTYPE_HTBL:
1391 0 : es_fprintf (fp, "htbl,");
1392 0 : for (i=0; i < ITEMS_PER_HTBL_RECORD; i++)
1393 0 : es_fprintf (fp, " %lu", rec->r.htbl.item[i]);
1394 0 : es_putc ('\n', fp);
1395 0 : break;
1396 :
1397 : case RECTYPE_HLST:
1398 0 : es_fprintf (fp, "hlst, next=%lu,", rec->r.hlst.next);
1399 0 : for (i=0; i < ITEMS_PER_HLST_RECORD; i++)
1400 0 : es_fprintf (fp, " %lu", rec->r.hlst.rnum[i]);
1401 0 : es_putc ('\n', fp);
1402 0 : break;
1403 :
1404 : case RECTYPE_TRUST:
1405 0 : es_fprintf (fp, "trust ");
1406 0 : for (i=0; i < 20; i++)
1407 0 : es_fprintf (fp, "%02X", rec->r.trust.fingerprint[i]);
1408 0 : es_fprintf (fp, ", ot=%d, d=%d, vl=%lu\n", rec->r.trust.ownertrust,
1409 0 : rec->r.trust.depth, rec->r.trust.validlist);
1410 0 : break;
1411 :
1412 : case RECTYPE_VALID:
1413 0 : es_fprintf (fp, "valid ");
1414 0 : for (i=0; i < 20; i++)
1415 0 : es_fprintf(fp, "%02X", rec->r.valid.namehash[i]);
1416 0 : es_fprintf (fp, ", v=%d, next=%lu\n", rec->r.valid.validity,
1417 : rec->r.valid.next);
1418 0 : break;
1419 :
1420 : default:
1421 0 : es_fprintf (fp, "unknown type %d\n", rec->rectype );
1422 0 : break;
1423 : }
1424 0 : }
1425 :
1426 :
1427 : /*
1428 : * Read the record with number RECNUM into the structure REC. If
1429 : * EXPECTED is not 0 reading any other record type will return an
1430 : * error.
1431 : *
1432 : * Return: 0 on success, -1 on EOF, or an error code.
1433 : */
1434 : int
1435 11975 : tdbio_read_record (ulong recnum, TRUSTREC *rec, int expected)
1436 : {
1437 : byte readbuf[TRUST_RECORD_LEN];
1438 : const byte *buf, *p;
1439 11975 : gpg_error_t err = 0;
1440 : int n, i;
1441 :
1442 11975 : if (db_fd == -1)
1443 422 : open_db ();
1444 :
1445 11975 : buf = get_record_from_cache( recnum );
1446 11975 : if (!buf)
1447 : {
1448 11921 : if (lseek (db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET) == -1)
1449 : {
1450 0 : err = gpg_error_from_syserror ();
1451 0 : log_error (_("trustdb: lseek failed: %s\n"), strerror (errno));
1452 0 : return err;
1453 : }
1454 11921 : n = read (db_fd, readbuf, TRUST_RECORD_LEN);
1455 11921 : if (!n)
1456 : {
1457 301 : return -1; /* eof */
1458 : }
1459 11620 : else if (n != TRUST_RECORD_LEN)
1460 : {
1461 0 : err = gpg_error_from_syserror ();
1462 0 : log_error (_("trustdb: read failed (n=%d): %s\n"),
1463 0 : n, strerror(errno));
1464 0 : return err;
1465 : }
1466 11620 : buf = readbuf;
1467 : }
1468 11674 : rec->recnum = recnum;
1469 11674 : rec->dirty = 0;
1470 11674 : p = buf;
1471 11674 : rec->rectype = *p++;
1472 11674 : if (expected && rec->rectype != expected)
1473 : {
1474 0 : log_error ("%lu: read expected rec type %d, got %d\n",
1475 : recnum, expected, rec->rectype);
1476 0 : return gpg_error (GPG_ERR_TRUSTDB);
1477 : }
1478 11674 : p++; /* Skip reserved byte. */
1479 11674 : switch (rec->rectype)
1480 : {
1481 : case 0: /* unused (free) record */
1482 0 : break;
1483 :
1484 : case RECTYPE_VER: /* version record */
1485 1674 : if (memcmp(buf+1, GPGEXT_GPG, 3))
1486 : {
1487 0 : log_error (_("%s: not a trustdb file\n"), db_name );
1488 0 : err = gpg_error (GPG_ERR_TRUSTDB);
1489 : }
1490 : else
1491 : {
1492 1674 : p += 2; /* skip "gpg" */
1493 1674 : rec->r.ver.version = *p++;
1494 1674 : rec->r.ver.marginals = *p++;
1495 1674 : rec->r.ver.completes = *p++;
1496 1674 : rec->r.ver.cert_depth = *p++;
1497 1674 : rec->r.ver.trust_model = *p++;
1498 1674 : rec->r.ver.min_cert_level = *p++;
1499 1674 : p += 2;
1500 1674 : rec->r.ver.created = buf32_to_ulong(p); p += 4;
1501 1674 : rec->r.ver.nextcheck = buf32_to_ulong(p); p += 4;
1502 1674 : p += 4;
1503 1674 : p += 4;
1504 1674 : rec->r.ver.firstfree =buf32_to_ulong(p); p += 4;
1505 1674 : p += 4;
1506 1674 : rec->r.ver.trusthashtbl =buf32_to_ulong(p); p += 4;
1507 1674 : if (recnum)
1508 : {
1509 0 : log_error( _("%s: version record with recnum %lu\n"), db_name,
1510 : (ulong)recnum );
1511 0 : err = gpg_error (GPG_ERR_TRUSTDB);
1512 : }
1513 1674 : else if (rec->r.ver.version != 3)
1514 : {
1515 0 : log_error( _("%s: invalid file version %d\n"), db_name,
1516 0 : rec->r.ver.version );
1517 0 : err = gpg_error (GPG_ERR_TRUSTDB);
1518 : }
1519 : }
1520 1674 : break;
1521 :
1522 : case RECTYPE_FREE:
1523 0 : rec->r.free.next = buf32_to_ulong(p); p += 4;
1524 0 : break;
1525 :
1526 : case RECTYPE_HTBL:
1527 96690 : for (i=0; i < ITEMS_PER_HTBL_RECORD; i++)
1528 : {
1529 87021 : rec->r.htbl.item[i] = buf32_to_ulong(p); p += 4;
1530 : }
1531 9669 : break;
1532 :
1533 : case RECTYPE_HLST:
1534 0 : rec->r.hlst.next = buf32_to_ulong(p); p += 4;
1535 0 : for (i=0; i < ITEMS_PER_HLST_RECORD; i++)
1536 : {
1537 0 : rec->r.hlst.rnum[i] = buf32_to_ulong(p); p += 4;
1538 : }
1539 0 : break;
1540 :
1541 : case RECTYPE_TRUST:
1542 331 : memcpy (rec->r.trust.fingerprint, p, 20); p+=20;
1543 331 : rec->r.trust.ownertrust = *p++;
1544 331 : rec->r.trust.depth = *p++;
1545 331 : rec->r.trust.min_ownertrust = *p++;
1546 331 : p++;
1547 331 : rec->r.trust.validlist = buf32_to_ulong(p); p += 4;
1548 331 : break;
1549 :
1550 : case RECTYPE_VALID:
1551 0 : memcpy (rec->r.valid.namehash, p, 20); p+=20;
1552 0 : rec->r.valid.validity = *p++;
1553 0 : rec->r.valid.next = buf32_to_ulong(p); p += 4;
1554 0 : rec->r.valid.full_count = *p++;
1555 0 : rec->r.valid.marginal_count = *p++;
1556 0 : break;
1557 :
1558 : default:
1559 0 : log_error ("%s: invalid record type %d at recnum %lu\n",
1560 : db_name, rec->rectype, (ulong)recnum);
1561 0 : err = gpg_error (GPG_ERR_TRUSTDB);
1562 0 : break;
1563 : }
1564 :
1565 11674 : return err;
1566 : }
1567 :
1568 :
1569 : /*
1570 : * Write the record from the struct REC.
1571 : *
1572 : * Return: 0 on success or an error code.
1573 : */
1574 : int
1575 36 : tdbio_write_record( TRUSTREC *rec )
1576 : {
1577 : byte buf[TRUST_RECORD_LEN];
1578 : byte *p;
1579 36 : int rc = 0;
1580 : int i;
1581 36 : ulong recnum = rec->recnum;
1582 :
1583 36 : if (db_fd == -1)
1584 0 : open_db ();
1585 :
1586 36 : memset (buf, 0, TRUST_RECORD_LEN);
1587 36 : p = buf;
1588 36 : *p++ = rec->rectype; p++;
1589 :
1590 36 : switch (rec->rectype)
1591 : {
1592 : case 0: /* unused record */
1593 0 : break;
1594 :
1595 : case RECTYPE_VER: /* version record */
1596 3 : if (recnum)
1597 0 : BUG ();
1598 3 : memcpy(p-1, GPGEXT_GPG, 3 ); p += 2;
1599 3 : *p++ = rec->r.ver.version;
1600 3 : *p++ = rec->r.ver.marginals;
1601 3 : *p++ = rec->r.ver.completes;
1602 3 : *p++ = rec->r.ver.cert_depth;
1603 3 : *p++ = rec->r.ver.trust_model;
1604 3 : *p++ = rec->r.ver.min_cert_level;
1605 3 : p += 2;
1606 3 : ulongtobuf(p, rec->r.ver.created); p += 4;
1607 3 : ulongtobuf(p, rec->r.ver.nextcheck); p += 4;
1608 3 : p += 4;
1609 3 : p += 4;
1610 3 : ulongtobuf(p, rec->r.ver.firstfree ); p += 4;
1611 3 : p += 4;
1612 3 : ulongtobuf(p, rec->r.ver.trusthashtbl ); p += 4;
1613 3 : break;
1614 :
1615 : case RECTYPE_FREE:
1616 0 : ulongtobuf(p, rec->r.free.next); p += 4;
1617 0 : break;
1618 :
1619 : case RECTYPE_HTBL:
1620 310 : for (i=0; i < ITEMS_PER_HTBL_RECORD; i++)
1621 : {
1622 279 : ulongtobuf( p, rec->r.htbl.item[i]); p += 4;
1623 : }
1624 31 : break;
1625 :
1626 : case RECTYPE_HLST:
1627 0 : ulongtobuf( p, rec->r.hlst.next); p += 4;
1628 0 : for (i=0; i < ITEMS_PER_HLST_RECORD; i++ )
1629 : {
1630 0 : ulongtobuf( p, rec->r.hlst.rnum[i]); p += 4;
1631 : }
1632 0 : break;
1633 :
1634 : case RECTYPE_TRUST:
1635 2 : memcpy (p, rec->r.trust.fingerprint, 20); p += 20;
1636 2 : *p++ = rec->r.trust.ownertrust;
1637 2 : *p++ = rec->r.trust.depth;
1638 2 : *p++ = rec->r.trust.min_ownertrust;
1639 2 : p++;
1640 2 : ulongtobuf( p, rec->r.trust.validlist); p += 4;
1641 2 : break;
1642 :
1643 : case RECTYPE_VALID:
1644 0 : memcpy (p, rec->r.valid.namehash, 20); p += 20;
1645 0 : *p++ = rec->r.valid.validity;
1646 0 : ulongtobuf( p, rec->r.valid.next); p += 4;
1647 0 : *p++ = rec->r.valid.full_count;
1648 0 : *p++ = rec->r.valid.marginal_count;
1649 0 : break;
1650 :
1651 : default:
1652 0 : BUG();
1653 : }
1654 :
1655 36 : rc = put_record_into_cache (recnum, buf);
1656 36 : if (rc)
1657 : ;
1658 36 : else if (rec->rectype == RECTYPE_TRUST)
1659 2 : rc = update_trusthashtbl (rec);
1660 :
1661 36 : return rc;
1662 : }
1663 :
1664 :
1665 : /*
1666 : * Delete the record at record number RECNUm from the trustdb.
1667 : *
1668 : * Return: 0 on success or an error code.
1669 : */
1670 : int
1671 0 : tdbio_delete_record (ulong recnum)
1672 : {
1673 : TRUSTREC vr, rec;
1674 : int rc;
1675 :
1676 : /* Must read the record fist, so we can drop it from the hash tables */
1677 0 : rc = tdbio_read_record (recnum, &rec, 0);
1678 0 : if (rc)
1679 : ;
1680 0 : else if (rec.rectype == RECTYPE_TRUST)
1681 : {
1682 0 : rc = drop_from_hashtable (get_trusthashrec(),
1683 : rec.r.trust.fingerprint, 20, rec.recnum);
1684 : }
1685 :
1686 0 : if (rc)
1687 0 : return rc;
1688 :
1689 : /* Now we can chnage it to a free record. */
1690 0 : rc = tdbio_read_record (0, &vr, RECTYPE_VER);
1691 0 : if (rc)
1692 0 : log_fatal (_("%s: error reading version record: %s\n"),
1693 : db_name, gpg_strerror (rc));
1694 :
1695 0 : rec.recnum = recnum;
1696 0 : rec.rectype = RECTYPE_FREE;
1697 0 : rec.r.free.next = vr.r.ver.firstfree;
1698 0 : vr.r.ver.firstfree = recnum;
1699 0 : rc = tdbio_write_record (&rec);
1700 0 : if (!rc)
1701 0 : rc = tdbio_write_record (&vr);
1702 :
1703 0 : return rc;
1704 : }
1705 :
1706 :
1707 : /*
1708 : * Create a new record and return its record number.
1709 : */
1710 : ulong
1711 2 : tdbio_new_recnum ()
1712 : {
1713 : off_t offset;
1714 : ulong recnum;
1715 : TRUSTREC vr, rec;
1716 : int rc;
1717 :
1718 : /* Look for unused records. */
1719 2 : rc = tdbio_read_record (0, &vr, RECTYPE_VER);
1720 2 : if (rc)
1721 0 : log_fatal( _("%s: error reading version record: %s\n"),
1722 : db_name, gpg_strerror (rc));
1723 2 : if (vr.r.ver.firstfree)
1724 : {
1725 0 : recnum = vr.r.ver.firstfree;
1726 0 : rc = tdbio_read_record (recnum, &rec, RECTYPE_FREE);
1727 0 : if (rc)
1728 : {
1729 0 : log_error (_("%s: error reading free record: %s\n"),
1730 : db_name, gpg_strerror (rc));
1731 0 : return rc;
1732 : }
1733 : /* Update dir record. */
1734 0 : vr.r.ver.firstfree = rec.r.free.next;
1735 0 : rc = tdbio_write_record (&vr);
1736 0 : if (rc)
1737 : {
1738 0 : log_error (_("%s: error writing dir record: %s\n"),
1739 : db_name, gpg_strerror (rc));
1740 0 : return rc;
1741 : }
1742 : /* Zero out the new record. */
1743 0 : memset (&rec, 0, sizeof rec);
1744 0 : rec.rectype = 0; /* Mark as unused record (actually already done
1745 : my the memset). */
1746 0 : rec.recnum = recnum;
1747 0 : rc = tdbio_write_record (&rec);
1748 0 : if (rc)
1749 0 : log_fatal (_("%s: failed to zero a record: %s\n"),
1750 : db_name, gpg_strerror (rc));
1751 : }
1752 : else /* Not found - append a new record. */
1753 : {
1754 2 : offset = lseek (db_fd, 0, SEEK_END);
1755 2 : if (offset == (off_t)(-1))
1756 0 : log_fatal ("trustdb: lseek to end failed: %s\n", strerror (errno));
1757 2 : recnum = offset / TRUST_RECORD_LEN;
1758 2 : assert (recnum); /* this is will never be the first record */
1759 : /* We must write a record, so that the next call to this
1760 : * function returns another recnum. */
1761 2 : memset (&rec, 0, sizeof rec);
1762 2 : rec.rectype = 0; /* unused record */
1763 2 : rec.recnum = recnum;
1764 2 : rc = 0;
1765 2 : if (lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET) == -1)
1766 : {
1767 0 : rc = gpg_error_from_syserror ();
1768 0 : log_error (_("trustdb rec %lu: lseek failed: %s\n"),
1769 0 : recnum, strerror (errno));
1770 : }
1771 : else
1772 : {
1773 : int n;
1774 :
1775 2 : n = write (db_fd, &rec, TRUST_RECORD_LEN);
1776 2 : if (n != TRUST_RECORD_LEN)
1777 : {
1778 0 : rc = gpg_error_from_syserror ();
1779 0 : log_error (_("trustdb rec %lu: write failed (n=%d): %s\n"),
1780 0 : recnum, n, strerror (errno));
1781 : }
1782 : }
1783 :
1784 2 : if (rc)
1785 0 : log_fatal (_("%s: failed to append a record: %s\n"),
1786 : db_name, gpg_strerror (rc));
1787 : }
1788 :
1789 2 : return recnum ;
1790 : }
1791 :
1792 :
1793 :
1794 : /* Helper function for tdbio_search_trust_byfpr. */
1795 : static int
1796 4 : cmp_trec_fpr ( const void *fpr, const TRUSTREC *rec )
1797 : {
1798 8 : return (rec->rectype == RECTYPE_TRUST
1799 4 : && !memcmp (rec->r.trust.fingerprint, fpr, 20));
1800 : }
1801 :
1802 :
1803 : /*
1804 : * Given a 20 byte FINGERPRINT search its trust record and return
1805 : * that at REC.
1806 : *
1807 : * Return: 0 if found, GPG_ERR_NOT_FOUND, or another error code.
1808 : */
1809 : gpg_error_t
1810 967 : tdbio_search_trust_byfpr (const byte *fingerprint, TRUSTREC *rec)
1811 : {
1812 : int rc;
1813 :
1814 : /* Locate the trust record using the hash table */
1815 967 : rc = lookup_hashtable (get_trusthashrec(), fingerprint, 20,
1816 : cmp_trec_fpr, fingerprint, rec );
1817 967 : return rc;
1818 : }
1819 :
1820 :
1821 : /*
1822 : * Given a primary public key object PK search its trust record and
1823 : * return that at REC.
1824 : *
1825 : * Return: 0 if found, GPG_ERR_NOT_FOUND, or another error code.
1826 : */
1827 : gpg_error_t
1828 967 : tdbio_search_trust_bypk (PKT_public_key *pk, TRUSTREC *rec)
1829 : {
1830 : byte fingerprint[MAX_FINGERPRINT_LEN];
1831 : size_t fingerlen;
1832 :
1833 967 : fingerprint_from_pk( pk, fingerprint, &fingerlen );
1834 967 : for (; fingerlen < 20; fingerlen++)
1835 0 : fingerprint[fingerlen] = 0;
1836 967 : return tdbio_search_trust_byfpr (fingerprint, rec);
1837 : }
1838 :
1839 :
1840 : /*
1841 : * Terminate the process with a message about a corrupted trustdb.
1842 : */
1843 : void
1844 0 : tdbio_invalid (void)
1845 : {
1846 0 : log_error (_("Error: The trustdb is corrupted.\n"));
1847 0 : how_to_fix_the_trustdb ();
1848 0 : g10_exit (2);
1849 : }
|