summaryrefslogtreecommitdiffstats
path: root/g10/tdbdump.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>1999-03-11 16:42:06 +0100
committerWerner Koch <wk@gnupg.org>1999-03-11 16:42:06 +0100
commite95a22a6d214edbb604ffe3292ad11ee096bf9a0 (patch)
treedb513c500ee4997d2645cbe71dbda7701e9f213a /g10/tdbdump.c
parentSee ChangeLog: Wed Mar 10 11:26:18 CET 1999 Werner Koch (diff)
downloadgnupg2-e95a22a6d214edbb604ffe3292ad11ee096bf9a0.tar.xz
gnupg2-e95a22a6d214edbb604ffe3292ad11ee096bf9a0.zip
See ChangeLog: Thu Mar 11 16:39:46 CET 1999 Werner Koch
Diffstat (limited to 'g10/tdbdump.c')
-rw-r--r--g10/tdbdump.c522
1 files changed, 522 insertions, 0 deletions
diff --git a/g10/tdbdump.c b/g10/tdbdump.c
new file mode 100644
index 000000000..f2b4ca9f8
--- /dev/null
+++ b/g10/tdbdump.c
@@ -0,0 +1,522 @@
+/* tdbdump.c
+ * Copyright (C) 1999 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "errors.h"
+#include "iobuf.h"
+#include "keydb.h"
+#include "memory.h"
+#include "util.h"
+#include "trustdb.h"
+#include "options.h"
+#include "packet.h"
+#include "main.h"
+#include "i18n.h"
+#include "tdbio.h"
+
+
+#define HEXTOBIN(a) ( (a) >= '0' && (a) <= '9' ? ((a)-'0') : \
+ (a) >= 'A' && (a) <= 'F' ? ((a)-'A'+10) : ((a)-'a'+10))
+
+/****************
+ * Read a record but die if it does not exist
+ * fixme: duplicate: remove it
+ */
+static void
+read_record( ulong recno, TRUSTREC *rec, int rectype )
+{
+ int rc = tdbio_read_record( recno, rec, rectype );
+ if( !rc )
+ return;
+ log_error(_("trust record %lu, req type %d: read failed: %s\n"),
+ recno, rectype, g10_errstr(rc) );
+ tdbio_invalid();
+}
+
+/****************
+ * Wirte a record but die on error
+ */
+static void
+write_record( TRUSTREC *rec )
+{
+ int rc = tdbio_write_record( rec );
+ if( !rc )
+ return;
+ log_error(_("trust record %lu, type %d: write failed: %s\n"),
+ rec->recnum, rec->rectype, g10_errstr(rc) );
+ tdbio_invalid();
+}
+
+
+/****************
+ * sync the db
+ */
+static void
+do_sync(void)
+{
+ int rc = tdbio_sync();
+ if( !rc )
+ return;
+ log_error(_("trustdb: sync failed: %s\n"), g10_errstr(rc) );
+ g10_exit(2);
+}
+
+
+static int
+print_sigflags( FILE *fp, unsigned flags )
+{
+ if( flags & SIGF_CHECKED ) {
+ fprintf(fp,"%c%c%c",
+ (flags & SIGF_VALID) ? 'V':'-',
+ (flags & SIGF_EXPIRED) ? 'E':'-',
+ (flags & SIGF_REVOKED) ? 'R':'-');
+ }
+ else if( flags & SIGF_NOPUBKEY)
+ fputs("?--", fp);
+ else
+ fputs("---", fp);
+ return 3;
+}
+
+
+
+/****************
+ * Walk through the signatures of a public key.
+ * The caller must provide a context structure, with all fields set
+ * to zero, but the local_id field set to the requested key;
+ * This function does not change this field. On return the context
+ * is filled with the local-id of the signature and the signature flag.
+ * No fields should be changed (clearing all fields and setting
+ * pubkeyid is okay to continue with an other pubkey)
+ * Returns: 0 - okay, -1 for eof (no more sigs) or any other errorcode
+ * FIXME: Do we really need this large and complicated function?
+ */
+static int
+walk_sigrecs( SIGREC_CONTEXT *c )
+{
+ TRUSTREC *r;
+ ulong rnum;
+
+ if( c->ctl.eof )
+ return -1;
+ r = &c->ctl.rec;
+ if( !c->ctl.init_done ) {
+ c->ctl.init_done = 1;
+ read_record( c->lid, r, 0 );
+ if( r->rectype != RECTYPE_DIR ) {
+ c->ctl.eof = 1;
+ return -1; /* return eof */
+ }
+ c->ctl.nextuid = r->r.dir.uidlist;
+ /* force a read */
+ c->ctl.index = SIGS_PER_RECORD;
+ r->r.sig.next = 0;
+ }
+
+ /* need a loop to skip over deleted sigs */
+ do {
+ if( c->ctl.index >= SIGS_PER_RECORD ) { /* read the record */
+ rnum = r->r.sig.next;
+ if( !rnum && c->ctl.nextuid ) { /* read next uid record */
+ read_record( c->ctl.nextuid, r, RECTYPE_UID );
+ c->ctl.nextuid = r->r.uid.next;
+ rnum = r->r.uid.siglist;
+ }
+ if( !rnum ) {
+ c->ctl.eof = 1;
+ return -1; /* return eof */
+ }
+ read_record( rnum, r, RECTYPE_SIG );
+ if( r->r.sig.lid != c->lid ) {
+ log_error(_("chained sigrec %lu has a wrong owner\n"), rnum );
+ c->ctl.eof = 1;
+ tdbio_invalid();
+ }
+ c->ctl.index = 0;
+ }
+ } while( !r->r.sig.sig[c->ctl.index++].lid );
+
+ c->sig_lid = r->r.sig.sig[c->ctl.index-1].lid;
+ c->sig_flag = r->r.sig.sig[c->ctl.index-1].flag;
+ return 0;
+}
+
+
+#if 0
+static int
+do_list_sigs( ulong root, ulong pk_lid, int depth,
+ LOCAL_ID_TABLE lids, unsigned *lineno )
+{
+ SIGREC_CONTEXT sx;
+ int rc;
+ u32 keyid[2];
+
+ memset( &sx, 0, sizeof sx );
+ sx.lid = pk_lid;
+ for(;;) {
+ rc = walk_sigrecs( &sx ); /* should we replace it and use */
+ if( rc )
+ break;
+ rc = keyid_from_lid( sx.sig_lid, keyid );
+ if( rc ) {
+ printf("%6u: %*s????????.%lu:", *lineno, depth*4, "", sx.sig_lid );
+ print_sigflags( stdout, sx.sig_flag );
+ putchar('\n');
+ ++*lineno;
+ }
+ else {
+ printf("%6u: %*s%08lX.%lu:", *lineno, depth*4, "",
+ (ulong)keyid[1], sx.sig_lid );
+ print_sigflags( stdout, sx.sig_flag );
+ putchar(' ');
+ /* check whether we already checked this pk_lid */
+ if( !qry_lid_table_flag( ultikey_table, sx.sig_lid, NULL ) ) {
+ print_user_id("[ultimately trusted]", keyid);
+ ++*lineno;
+ }
+ else if( sx.sig_lid == pk_lid ) {
+ printf("[self-signature]\n");
+ ++*lineno;
+ }
+ else if( sx.sig_lid == root ) {
+ printf("[closed]\n");
+ ++*lineno;
+ }
+ else if( ins_lid_table_item( lids, sx.sig_lid, *lineno ) ) {
+ unsigned refline;
+ qry_lid_table_flag( lids, sx.sig_lid, &refline );
+ printf("[see line %u]\n", refline);
+ ++*lineno;
+ }
+ else if( depth+1 >= MAX_LIST_SIGS_DEPTH ) {
+ print_user_id( "[too deeply nested]", keyid );
+ ++*lineno;
+ }
+ else {
+ print_user_id( "", keyid );
+ ++*lineno;
+ rc = do_list_sigs( root, sx.sig_lid, depth+1, lids, lineno );
+ if( rc )
+ break;
+ }
+ }
+ }
+ return rc==-1? 0 : rc;
+}
+#endif
+/****************
+ * List all signatures of a public key
+ */
+static int
+list_sigs( ulong pubkey_id )
+{
+ int rc=0;
+ #if 0
+ u32 keyid[2];
+ LOCAL_ID_TABLE lids;
+ unsigned lineno = 1;
+
+ rc = keyid_from_lid( pubkey_id, keyid );
+ if( rc )
+ return rc;
+ printf("Signatures of %08lX.%lu ", (ulong)keyid[1], pubkey_id );
+ print_user_id("", keyid);
+ printf("----------------------\n");
+
+ lids = new_lid_table();
+ rc = do_list_sigs( pubkey_id, pubkey_id, 0, lids, &lineno );
+ putchar('\n');
+ release_lid_table(lids);
+ #endif
+ return rc;
+}
+
+/****************
+ * List all records of a public key
+ */
+static int
+list_records( ulong lid )
+{
+ int rc;
+ TRUSTREC dr, ur, rec;
+ ulong recno;
+
+ rc = tdbio_read_record( lid, &dr, RECTYPE_DIR );
+ if( rc ) {
+ log_error(_("lid %lu: read dir record failed: %s\n"),
+ lid, g10_errstr(rc));
+ return rc;
+ }
+ tdbio_dump_record( &dr, stdout );
+
+ for( recno=dr.r.dir.keylist; recno; recno = rec.r.key.next ) {
+ rc = tdbio_read_record( recno, &rec, 0 );
+ if( rc ) {
+ log_error(_("lid %lu: read key record failed: %s\n"),
+ lid, g10_errstr(rc));
+ return rc;
+ }
+ tdbio_dump_record( &rec, stdout );
+ }
+
+ for( recno=dr.r.dir.uidlist; recno; recno = ur.r.uid.next ) {
+ rc = tdbio_read_record( recno, &ur, RECTYPE_UID );
+ if( rc ) {
+ log_error(_("lid %lu: read uid record failed: %s\n"),
+ lid, g10_errstr(rc));
+ return rc;
+ }
+ tdbio_dump_record( &ur, stdout );
+ /* preference records */
+ for(recno=ur.r.uid.prefrec; recno; recno = rec.r.pref.next ) {
+ rc = tdbio_read_record( recno, &rec, RECTYPE_PREF );
+ if( rc ) {
+ log_error(_("lid %lu: read pref record failed: %s\n"),
+ lid, g10_errstr(rc));
+ return rc;
+ }
+ tdbio_dump_record( &rec, stdout );
+ }
+ /* sig records */
+ for(recno=ur.r.uid.siglist; recno; recno = rec.r.sig.next ) {
+ rc = tdbio_read_record( recno, &rec, RECTYPE_SIG );
+ if( rc ) {
+ log_error(_("lid %lu: read sig record failed: %s\n"),
+ lid, g10_errstr(rc));
+ return rc;
+ }
+ tdbio_dump_record( &rec, stdout );
+ }
+ }
+
+ /* add cache record dump here */
+
+
+
+ return rc;
+}
+
+
+/****************
+ * Dump the complte trustdb or only the entries of one key.
+ */
+void
+list_trustdb( const char *username )
+{
+ TRUSTREC rec;
+
+ init_trustdb();
+
+ if( username && *username == '#' ) {
+ int rc;
+ ulong lid = atoi(username+1);
+
+ if( (rc = list_records( lid)) )
+ log_error(_("user '%s' read problem: %s\n"),
+ username, g10_errstr(rc));
+ else if( (rc = list_sigs( lid )) )
+ log_error(_("user '%s' list problem: %s\n"),
+ username, g10_errstr(rc));
+ }
+ else if( username ) {
+ PKT_public_key *pk = m_alloc_clear( sizeof *pk );
+ int rc;
+
+ if( (rc = get_pubkey_byname( NULL, pk, username, NULL )) )
+ log_error(_("user '%s' not found: %s\n"), username, g10_errstr(rc) );
+ else if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 )
+ log_error(_("problem finding '%s' in trustdb: %s\n"),
+ username, g10_errstr(rc));
+ else if( rc == -1 )
+ log_error(_("user '%s' not in trustdb\n"), username);
+ else if( (rc = list_records( pk->local_id)) )
+ log_error(_("user '%s' read problem: %s\n"),
+ username, g10_errstr(rc));
+ else if( (rc = list_sigs( pk->local_id )) )
+ log_error(_("user '%s' list problem: %s\n"),
+ username, g10_errstr(rc));
+ free_public_key( pk );
+ }
+ else {
+ ulong recnum;
+ int i;
+
+ printf("TrustDB: %s\n", tdbio_get_dbname() );
+ for(i=9+strlen(tdbio_get_dbname()); i > 0; i-- )
+ putchar('-');
+ putchar('\n');
+ for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ )
+ tdbio_dump_record( &rec, stdout );
+ }
+}
+
+
+
+
+
+/****************
+ * Print a list of all defined owner trust value.
+ */
+void
+export_ownertrust()
+{
+ TRUSTREC rec;
+ TRUSTREC rec2;
+ ulong recnum;
+ int i;
+ byte *p;
+ int rc;
+
+ init_trustdb();
+ printf(_("# List of assigned trustvalues, created %s\n"
+ "# (Use \"gpgm --import-ownertrust\" to restore them)\n"),
+ asctimestamp( make_timestamp() ) );
+ for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
+ if( rec.rectype == RECTYPE_DIR ) {
+ if( !rec.r.dir.keylist ) {
+ log_error(_("directory record w/o primary key\n"));
+ continue;
+ }
+ if( !rec.r.dir.ownertrust )
+ continue;
+ rc = tdbio_read_record( rec.r.dir.keylist, &rec2, RECTYPE_KEY);
+ if( rc ) {
+ log_error(_("error reading key record: %s\n"), g10_errstr(rc));
+ continue;
+ }
+ p = rec2.r.key.fingerprint;
+ for(i=0; i < rec2.r.key.fingerprint_len; i++, p++ )
+ printf("%02X", *p );
+ printf(":%u:\n", (unsigned)rec.r.dir.ownertrust );
+ }
+ }
+}
+
+
+void
+import_ownertrust( const char *fname )
+{
+ FILE *fp;
+ int is_stdin=0;
+ char line[256];
+ char *p;
+ size_t n, fprlen;
+ unsigned otrust;
+
+ init_trustdb();
+ if( !fname || (*fname == '-' && !fname[1]) ) {
+ fp = stdin;
+ fname = "[stdin]";
+ is_stdin = 1;
+ }
+ else if( !(fp = fopen( fname, "r" )) ) {
+ log_error_f(fname, _("can't open file: %s\n"), strerror(errno) );
+ return;
+ }
+
+ while( fgets( line, DIM(line)-1, fp ) ) {
+ TRUSTREC rec;
+ int rc;
+
+ if( !*line || *line == '#' )
+ continue;
+ n = strlen(line);
+ if( line[n-1] != '\n' ) {
+ log_error_f(fname, _("line too long\n") );
+ /* ... or last line does not have a LF */
+ break; /* can't continue */
+ }
+ for(p = line; *p && *p != ':' ; p++ )
+ if( !isxdigit(*p) )
+ break;
+ if( *p != ':' ) {
+ log_error_f(fname, _("error: missing colon\n") );
+ continue;
+ }
+ fprlen = p - line;
+ if( fprlen != 32 && fprlen != 40 ) {
+ log_error_f(fname, _("error: invalid fingerprint\n") );
+ continue;
+ }
+ if( sscanf(p, ":%u:", &otrust ) != 1 ) {
+ log_error_f(fname, _("error: no ownertrust value\n") );
+ continue;
+ }
+ if( !otrust )
+ continue; /* no otrust defined - no need to update or insert */
+ /* convert the ascii fingerprint to binary */
+ for(p=line, fprlen=0; *p != ':'; p += 2 )
+ line[fprlen++] = HEXTOBIN(p[0]) * 16 + HEXTOBIN(p[1]);
+ line[fprlen] = 0;
+
+ repeat:
+ rc = tdbio_search_dir_byfpr( line, fprlen, 0, &rec );
+ if( !rc ) { /* found: update */
+ if( rec.r.dir.ownertrust )
+ log_info("LID %lu: changing trust from %u to %u\n",
+ rec.r.dir.lid, rec.r.dir.ownertrust, otrust );
+ else
+ log_info("LID %lu: setting trust to %u\n",
+ rec.r.dir.lid, otrust );
+ rec.r.dir.ownertrust = otrust;
+ write_record( &rec );
+ }
+ else if( rc == -1 ) { /* not found; get the key from the ring */
+ PKT_public_key *pk = m_alloc_clear( sizeof *pk );
+
+ log_info_f(fname, _("key not in trustdb, searching ring.\n"));
+ rc = get_pubkey_byfprint( pk, line, fprlen );
+ if( rc )
+ log_info_f(fname, _("key not in ring: %s\n"), g10_errstr(rc));
+ else {
+ rc = query_trust_record( pk ); /* only as assertion */
+ if( rc != -1 )
+ log_error_f(fname, _("Oops: key is now in trustdb???\n"));
+ else {
+ rc = insert_trust_record( pk );
+ if( !rc )
+ goto repeat; /* update the ownertrust */
+ log_error_f(fname, _("insert trust record failed: %s\n"),
+ g10_errstr(rc) );
+ }
+ }
+ }
+ else /* error */
+ log_error_f(fname, _("error finding dir record: %s\n"),
+ g10_errstr(rc));
+ }
+ if( ferror(fp) )
+ log_error_f(fname, _("read error: %s\n"), strerror(errno) );
+ if( !is_stdin )
+ fclose(fp);
+ do_sync();
+}
+