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