dsig.c: Allow precomputed hashes to be read from a file.
authorMark Wooding <mdw@distorted.org.uk>
Sun, 22 Jan 2012 13:12:15 +0000 (13:12 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 22 Jan 2012 13:12:15 +0000 (13:12 +0000)
This lets you convert a hashsum(1) file or similar into a dsig(1)
signature file.

dsig.1
dsig.c
hashsum.c

diff --git a/dsig.1 b/dsig.1
index 58cea8f..ad5b6fe 100644 (file)
--- a/dsig.1
+++ b/dsig.1
@@ -55,6 +55,8 @@ is one of:
 \h'8n'
 .RB [ \-f
 .IR file ]
+.RB [ \-h
+.IR file ]
 .RB [ \-o
 .IR output ]
 .br
@@ -309,6 +311,12 @@ Read filenames from
 .I name
 instead of from standard input.
 .TP
+.BI "\-h, \-\-hashes " name
+Rather than hashing files, read precomputed hashes from the file
+.IR name ,
+which should be in the format produced by
+.BR hashsum (1).
+.TP
 .BI "\-o, \-\-output " name
 Write output to
 .I name
diff --git a/dsig.c b/dsig.c
index 2707f45..5006423 100644 (file)
--- a/dsig.c
+++ b/dsig.c
@@ -469,14 +469,15 @@ static int sign(int argc, char *argv[])
   sig *s;
   time_t exp = KEXP_EXPIRE;
   unsigned verb = 0;
-  const char *ifile = 0;
+  const char *ifile = 0, *hfile = 0;
   const char *ofile = 0;
   const char *c = 0;
   const char *err;
   FILE *ifp, *ofp;
   dstr d = DSTR_INIT;
+  hfpctx hfp;
   block b;
-  int e;
+  int e, hf, n;
 
   for (;;) {
     static struct option opts[] = {
@@ -487,13 +488,15 @@ static int sign(int argc, char *argv[])
       { "quiet",       0,              0,      'q' },
       { "comment",     OPTF_ARGREQ,    0,      'c' },
       { "file",                OPTF_ARGREQ,    0,      'f' },
+      { "hashes",      OPTF_ARGREQ,    0,      'h' },
       { "output",      OPTF_ARGREQ,    0,      'o' },
       { "key",         OPTF_ARGREQ,    0,      'k' },
       { "expire",      OPTF_ARGREQ,    0,      'e' },
       { "nocheck",     OPTF_ARGREQ,    0,      'C' },
       { 0,             0,              0,      0 }
     };
-    int i = mdwopt(argc, argv, "+0vpqbC" "c:" "f:o:" "k:e:", opts, 0, 0, 0);
+    int i = mdwopt(argc, argv, "+0vpqbC" "c:" "f:h:o:" "k:e:",
+                  opts, 0, 0, 0);
     if (i < 0)
       break;
     switch (i) {
@@ -522,6 +525,9 @@ static int sign(int argc, char *argv[])
       case 'f':
        ifile = optarg;
        break;
+      case 'h':
+       hfile = optarg;
+       break;
       case 'o':
        ofile = optarg;
        break;
@@ -541,6 +547,8 @@ static int sign(int argc, char *argv[])
   }
   if (optind != argc || (f & f_bogus))
     die(EXIT_FAILURE, "Usage: sign [-OPTIONS]");
+  if (hfile && ifile)
+    die(EXIT_FAILURE, "Inconsistent options `-h' and `-f'");
 
   /* --- Locate the signing key --- */
 
@@ -562,6 +570,7 @@ static int sign(int argc, char *argv[])
 
   /* --- Open files --- */
 
+  if (hfile) ifile = hfile;
   if (!ifile || strcmp(ifile, "-") == 0)
     ifp = stdin;
   else if ((ifp = fopen(ifile, (f & f_bin) ? "rb" : "r")) == 0) {
@@ -605,32 +614,70 @@ static int sign(int argc, char *argv[])
 
   /* --- Now hash the various files --- */
 
-  for (;;) {
+  if (hfile) {
+    hfp.f = f;
+    hfp.fp = ifp;
+    hfp.ee = &encodingtab[ENC_HEX];
+    hfp.gch = GH_CLASS(s->h);
+    hfp.dline = &d;
+    hfp.dfile = &b.d;
+
+    n = 0;
+    for (;;) {
+      breset(&b);
+      DENSURE(&b.b, hfp.gch->hashsz);
+      hfp.hbuf = (octet *)b.b.buf;
+      if (ferror(ofp)) { f |= f_bogus; break; }
+      if ((hf = hfparse(&hfp)) == HF_EOF) break;
+      n++;
+
+      switch (hf) {
+       case HF_HASH:
+         if (hfp.gch != GH_CLASS(s->h)) {
+           moan("%s:%d: incorrect hash function `%s' (should be `%s')",
+                hfile, n, hfp.gch->name, GH_CLASS(s->h)->name);
+           f |= f_bogus;
+         }
+         break;
+       case HF_BAD:
+         moan("%s:%d: invalid hash-file line", hfile, n);
+         f |= f_bogus;
+         break;
+       case HF_FILE:
+         b.tag = T_FILE;
+         b.b.len += hfp.gch->hashsz;
+         bemit(&b, ofp, s->h, f & f_bin);
+         break;
+      }
+    }
+  } else {
+    for (;;) {
 
-    /* --- Stop on an output error --- */
+      /* --- Stop on an output error --- */
 
-    if (ferror(ofp)) {
-      f |= f_bogus;
-      break;
-    }
+      if (ferror(ofp)) {
+       f |= f_bogus;
+       break;
+      }
 
-    /* --- Read the next filename to hash --- */
+      /* --- Read the next filename to hash --- */
 
-    breset(&b);
-    if (getstring(ifp, &b.d, GSF_FILE | f))
-      break;
-    b.tag = T_FILE;
-    DENSURE(&b.b, GH_CLASS(s->h)->hashsz);
-    if (fhash(GH_CLASS(s->h), f | FHF_BINARY, b.d.buf, b.b.buf)) {
-      moan("Error reading `%s': %s", b.d.buf, strerror(errno));
-      f |= f_bogus;
-    } else {
-      b.b.len += GH_CLASS(s->h)->hashsz;
-      if (verb) {
-       fhex(stderr, b.b.buf, b.b.len);
-       fprintf(stderr, " %s\n", b.d.buf);
+      breset(&b);
+      if (getstring(ifp, &b.d, GSF_FILE | f))
+       break;
+      b.tag = T_FILE;
+      DENSURE(&b.b, GH_CLASS(s->h)->hashsz);
+      if (fhash(GH_CLASS(s->h), f | FHF_BINARY, b.d.buf, b.b.buf)) {
+       moan("error reading `%s': %s", b.d.buf, strerror(errno));
+       f |= f_bogus;
+      } else {
+       b.b.len += GH_CLASS(s->h)->hashsz;
+       if (verb) {
+         fhex(stderr, b.b.buf, b.b.len);
+         fprintf(stderr, " %s\n", b.d.buf);
+       }
+       bemit(&b, ofp, s->h, f & f_bin);
       }
-      bemit(&b, ofp, s->h, f & f_bin);
     }
   }
 
@@ -923,7 +970,7 @@ static cmd cmdtab[] = {
   { "show", cmd_show, "show [ITEM...]" },
   { "sign", sign,
     "sign [-0bpqvC] [-c COMMENT] [-k TAG] [-e EXPIRE]\n\t\
-[-f FILE] [-o OUTPUT]",
+[-f FILE] [-h FILE] [-o OUTPUT]",
     "\
 Options:\n\
 \n\
@@ -935,6 +982,7 @@ Options:\n\
 -C, --nocheck          Don't check the private key.\n\
 -c, --comment=COMMENT  Include COMMENT in the output file.\n\
 -f, --file=FILE                Read filenames to hash from FILE.\n\
+-h, --hashes=FILE      Read precomputed hashes from FILE.\n\
 -o, --output=FILE      Write the signed result to FILE.\n\
 -k, --key=TAG          Use a key named by TAG.\n\
 -e, --expire=TIME      The signature should expire after TIME.\n\
index 23b5d56..d12c506 100644 (file)
--- a/hashsum.c
+++ b/hashsum.c
@@ -113,6 +113,11 @@ static int checkhash(const gchash *gch, unsigned f,
     }
   }
 
+  if (ferror(hfp.fp)) {
+    moan("error reading input `%s': %s",
+        file ? file : "<stdin>", strerror(errno));
+    rc = EXIT_FAILURE;
+  }
   dstr_destroy(&dl);
   dstr_destroy(&df);
   xfree(hfp.hbuf);
@@ -236,7 +241,7 @@ int main(int argc, char *argv[])
 {
   unsigned f = 0;
   const gchash *gch = 0;
-  const encodeops *e = &encodingtab[0];
+  const encodeops *e = &encodingtab[ENC_HEX];
   int rc;
 
   /* --- Initialization --- */