/**************** * Simple transactions system: * Everything between begin_transaction and end/cancel_transaction * is not immediatly written but at the time of end_transaction. * */ int tdbio_begin_transaction() { int rc; if( in_transaction ) log_bug("tdbio: nested transactions\n"); /* flush everything out */ rc = tdbio_sync(); if( rc ) return rc; in_transaction = 1; return 0; }
int tdbio_end_transaction() { int rc; if( !in_transaction ) log_bug("tdbio: no active transaction\n"); take_write_lock (); block_all_signals(); in_transaction = 0; rc = tdbio_sync(); unblock_all_signals(); release_write_lock (); return rc; }
static int create_version_record (void) { TRUSTREC rec; int rc; memset( &rec, 0, sizeof rec ); rec.r.ver.version = 3; rec.r.ver.created = make_timestamp(); rec.r.ver.marginals = opt.marginals_needed; rec.r.ver.completes = opt.completes_needed; rec.r.ver.cert_depth = opt.max_cert_depth; if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC) rec.r.ver.trust_model = opt.trust_model; else rec.r.ver.trust_model = TM_PGP; rec.rectype = RECTYPE_VER; rec.recnum = 0; rc = tdbio_write_record( &rec ); if( !rc ) tdbio_sync(); return rc; }
int tdbio_end_transaction() { int rc; if( !in_transaction ) log_bug("tdbio: no active transaction\n"); if( !is_locked ) { if( make_dotlock( lockhandle, -1 ) ) log_fatal("can't acquire lock - giving up\n"); else is_locked = 1; } block_all_signals(); in_transaction = 0; rc = tdbio_sync(); unblock_all_signals(); if( !opt.lock_once ) { if( !release_dotlock( lockhandle ) ) is_locked = 0; } return rc; }
/* * Append a new empty hashtable to the trustdb. TYPE gives the type * of the hash table. The only defined type is 0 for a trust hash. * On return the hashtable has been created, written, the version * record update, and the data flushed to the disk. On a fatal error * the function terminates the process. */ static void create_hashtable( TRUSTREC *vr, int type ) { TRUSTREC rec; off_t offset; ulong recnum; int i, n, rc; offset = lseek (db_fd, 0, SEEK_END); if (offset == -1) log_fatal ("trustdb: lseek to end failed: %s\n", strerror(errno)); recnum = offset / TRUST_RECORD_LEN; assert (recnum); /* This is will never be the first record. */ if (!type) vr->r.ver.trusthashtbl = recnum; /* Now write the records making up the hash table. */ n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD; for (i=0; i < n; i++, recnum++) { memset (&rec, 0, sizeof rec); rec.rectype = RECTYPE_HTBL; rec.recnum = recnum; rc = tdbio_write_record (&rec); if (rc) log_fatal (_("%s: failed to create hashtable: %s\n"), db_name, gpg_strerror (rc)); } /* Update the version record and flush. */ rc = tdbio_write_record (vr); if (!rc) rc = tdbio_sync (); if (rc) log_fatal (_("%s: error updating version record: %s\n"), db_name, gpg_strerror (rc)); }
/* * Migrate the trustdb as just up to gpg 1.0.6 (trustdb version 2) * to the 2.1 version as used with 1.0.6b - This is pretty trivial as needs * only to scan the tdb and insert new the new trust records. The old ones are * obsolte from now on */ static void migrate_from_v2 () { TRUSTREC rec; int i, n; struct { ulong keyrecno; byte ot; byte okay; byte fpr[20]; } *ottable; int ottable_size, ottable_used; byte oldbuf[40]; ulong recno; int rc, count; ottable_size = 5; ottable = xmalloc (ottable_size * sizeof *ottable); ottable_used = 0; /* We have some restrictions here. We can't use the version record * and we can't use any of the old hashtables because we dropped the * code. So we first collect all ownertrusts and then use a second * pass fo find the associated keys. We have to do this all without using * the regular record read functions. */ /* get all the ownertrusts */ if (lseek (db_fd, 0, SEEK_SET ) == -1 ) log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno)); for (recno=0;;recno++) { do n = read (db_fd, oldbuf, 40); while (n==-1 && errno == EINTR); if (!n) break; /* eof */ if (n != 40) log_fatal ("migrate_vfrom_v2: read error or short read\n"); if (*oldbuf != 2) continue; /* v2 dir record */ if (ottable_used == ottable_size) { ottable_size += 1000; ottable = xrealloc (ottable, ottable_size * sizeof *ottable); } ottable[ottable_used].keyrecno = buftoulong (oldbuf+6); ottable[ottable_used].ot = oldbuf[18]; ottable[ottable_used].okay = 0; memset (ottable[ottable_used].fpr,0, 20); if (ottable[ottable_used].keyrecno && ottable[ottable_used].ot) ottable_used++; } log_info ("found %d ownertrust records\n", ottable_used); /* Read again and find the fingerprints */ if (lseek (db_fd, 0, SEEK_SET ) == -1 ) log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno)); for (recno=0;;recno++) { do n = read (db_fd, oldbuf, 40); while (n==-1 && errno == EINTR); if (!n) break; /* eof */ if (n != 40) log_fatal ("migrate_from_v2: read error or short read\n"); if (*oldbuf != 3) continue; /* v2 key record */ for (i=0; i < ottable_used; i++) { if (ottable[i].keyrecno == recno) { memcpy (ottable[i].fpr, oldbuf+20, 20); ottable[i].okay = 1; break; } } } /* got everything - create the v3 trustdb */ if (ftruncate (db_fd, 0)) log_fatal ("can't truncate `%s': %s\n", db_name, strerror (errno) ); if (create_version_record ()) log_fatal ("failed to recreate version record of `%s'\n", db_name); /* access the hash table, so it is store just after the version record, * this is not needed put a dump is more pretty */ get_trusthashrec (); /* And insert the old ownertrust values */ count = 0; for (i=0; i < ottable_used; i++) { if (!ottable[i].okay) continue; memset (&rec, 0, sizeof rec); rec.recnum = tdbio_new_recnum (); rec.rectype = RECTYPE_TRUST; memcpy(rec.r.trust.fingerprint, ottable[i].fpr, 20); rec.r.trust.ownertrust = ottable[i].ot; if (tdbio_write_record (&rec)) log_fatal ("failed to write trust record of `%s'\n", db_name); count++; } revalidation_mark (); rc = tdbio_sync (); if (rc) log_fatal ("failed to sync `%s'\n", db_name); log_info ("migrated %d version 2 ownertrusts\n", count); xfree (ottable); }
void import_ownertrust (ctrl_t ctrl, const char *fname ) { estream_t fp; int is_stdin=0; char line[256]; char *p; size_t n, fprlen; unsigned int otrust; byte fpr[MAX_FINGERPRINT_LEN]; int any = 0; int rc; init_trustdb (ctrl, 0); if( iobuf_is_pipe_filename (fname) ) { fp = es_stdin; fname = "[stdin]"; is_stdin = 1; } else if( !(fp = es_fopen( fname, "r" )) ) { log_error ( _("can't open '%s': %s\n"), fname, strerror(errno) ); return; } if (is_secured_file (es_fileno (fp))) { es_fclose (fp); gpg_err_set_errno (EPERM); log_error (_("can't open '%s': %s\n"), fname, strerror(errno) ); return; } while (es_fgets (line, DIM(line)-1, fp)) { TRUSTREC rec; if( !*line || *line == '#' ) continue; n = strlen(line); if( line[n-1] != '\n' ) { log_error (_("error in '%s': %s\n"), fname, _("line too long") ); /* ... or last line does not have a LF */ break; /* can't continue */ } for(p = line; *p && *p != ':' ; p++ ) if( !hexdigitp(p) ) break; if( *p != ':' ) { log_error (_("error in '%s': %s\n"), fname, _("colon missing") ); continue; } fprlen = p - line; if( fprlen != 32 && fprlen != 40 && fprlen != 64) { log_error (_("error in '%s': %s\n"), fname, _("invalid fingerprint") ); continue; } if( sscanf(p, ":%u:", &otrust ) != 1 ) { log_error (_("error in '%s': %s\n"), fname, _("ownertrust value missing")); continue; } if( !otrust ) continue; /* no otrust defined - no need to update or insert */ /* Convert the ascii fingerprint to binary */ for(p=line, fprlen=0; fprlen < MAX_FINGERPRINT_LEN && *p != ':'; p += 2 ) fpr[fprlen++] = HEXTOBIN(p[0]) * 16 + HEXTOBIN(p[1]); while (fprlen < MAX_FINGERPRINT_LEN) fpr[fprlen++] = 0; rc = tdbio_search_trust_byfpr (fpr, &rec); if( !rc ) { /* found: update */ if (rec.r.trust.ownertrust != otrust) { if (!opt.quiet) { if( rec.r.trust.ownertrust ) log_info("changing ownertrust from %u to %u\n", rec.r.trust.ownertrust, otrust ); else log_info("setting ownertrust to %u\n", otrust ); } rec.r.trust.ownertrust = otrust; write_record (ctrl, &rec); any = 1; } } else if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND) { /* insert */ if (!opt.quiet) log_info("inserting ownertrust of %u\n", otrust ); memset (&rec, 0, sizeof rec); rec.recnum = tdbio_new_recnum (ctrl); rec.rectype = RECTYPE_TRUST; memcpy (rec.r.trust.fingerprint, fpr, 20); rec.r.trust.ownertrust = otrust; write_record (ctrl, &rec); any = 1; } else /* error */ log_error (_("error finding trust record in '%s': %s\n"), fname, gpg_strerror (rc)); } if (es_ferror (fp)) log_error ( _("read error in '%s': %s\n"), fname, strerror(errno) ); if (!is_stdin) es_fclose (fp); if (any) { revalidation_mark (ctrl); rc = tdbio_sync (); if (rc) log_error (_("trustdb: sync failed: %s\n"), gpg_strerror (rc) ); } }