catcrypt.c, catsign.c: Shorten chunk sizes.
[u/mdw/catacomb] / catsign.c
index dc96e55..8171404 100644 (file)
--- a/catsign.c
+++ b/catsign.c
@@ -7,7 +7,7 @@
  * (c) 2005 Straylight/Edgeware
  */
 
-/*----- Licensing notice --------------------------------------------------* 
+/*----- Licensing notice --------------------------------------------------*
  *
  * This file is part of Catacomb.
  *
  * it under the terms of the GNU Library General Public License as
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
- * 
+ *
  * Catacomb 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 Library General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Library General Public
  * License along with Catacomb; if not, write to the Free
  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 #include "noise.h"
 #include "mprand.h"
 #include "key.h"
+#include "getdate.h"
 #include "cc.h"
 
 #include "ectab.h"
 #include "ptab.h"
 
-/*----- Utilities ---------------------------------------------------------*/
-
-/* --- @keyreport@ --- *
- *
- * Arguments:   @const char *file@ = filename containing the error
- *              @int line@ = line number in file
- *              @const char *err@ = error text message
- *              @void *p@ = unimportant pointer
- *
- * Returns:     ---
- *
- * Use:         Reports errors during the opening of a key file.
- */
-
-static void keyreport(const char *file, int line, const char *err, void *p)
-{
-  moan("error in keyring `%s' at line `%s': %s", file, line, err);
-}
-
 /*----- Static variables --------------------------------------------------*/
 
 static const char *keyring = "keyring";
@@ -109,6 +91,7 @@ typedef struct sigmsg {
 #define F_BOGUS 128u
 #define F_BUFFER 256u
 #define F_UTC 512u
+#define F_NOCHECK 1024u
 
 /*----- Chunk I/O ---------------------------------------------------------*/
 
@@ -216,7 +199,7 @@ static void textwrite(msgcanon *m, const void *bp, size_t n)
 static size_t binreadembed(msgcanon *m, void *bp)
   { return (chunk_read(m->e, bp)); }
 static size_t binreaddetach(msgcanon *m, void *bp)
-  { return (fread(bp, 1, MSGBUFSZ, m->fp)); }
+  { return (fread(bp, 1, MSGBUFSZ - 1, m->fp)); }
 
 static void binwriteembed(msgcanon *m, const void *bp, size_t n)
   { chunk_write(m->e, bp, n); }
@@ -309,7 +292,7 @@ static void mc_endread(msgcanon *m, const encops *eops, enc **ee)
   if (m->fp && !(m->f & F_NOCLOSE)) {
     if (ferror(m->fp) || fclose(m->fp))
       die(EXIT_FAILURE, "error closing message file: %s", strerror(errno));
-  }    
+  }
 }
 
 static void mc_endwrite(msgcanon *m, const encops *eops, enc **ee)
@@ -327,7 +310,7 @@ static void mc_endwrite(msgcanon *m, const encops *eops, enc **ee)
   if (m->fp && !(m->f & F_NOCLOSE)) {
     if (fflush(m->fp) || ferror(m->fp) || fclose(m->fp))
       die(EXIT_FAILURE, "error closing message file: %s", strerror(errno));
-  }    
+  }
 }
 
 /*----- Signature reading and writing -------------------------------------*/
@@ -384,7 +367,7 @@ static void keyhash(key *k, sig *s, dstr *d)
   ghash *h;
   key_filter kf;
 
-  h = GH_INIT(GH_CLASS(s->h));
+  h = GH_INIT(s->ch);
   kf.f = KCAT_PUB;
   kf.m = KF_CATMASK;
   key_fingerprint(k, h, &kf);
@@ -456,7 +439,7 @@ static int sign(int argc, char *argv[])
   int i;
   char bb[MSGBUFSZ];
   size_t n;
-  dstr d = DSTR_INIT;  
+  dstr d = DSTR_INIT;
   const encops *eo;
   msgcanon mc_in = MC_INIT, mc_out = MC_INIT;
   enc *e;
@@ -471,9 +454,10 @@ static int sign(int argc, char *argv[])
       { "format",      OPTF_ARGREQ,    0,      'f' },
       { "output",      OPTF_ARGREQ,    0,      'o' },
       { "text",                0,              0,      't' },
+      { "nocheck",     0,              0,      'C' },
       { 0,             0,              0,      0 }
     };
-    i = mdwopt(argc, argv, "k:f:o:abdt", opt, 0, 0, 0);
+    i = mdwopt(argc, argv, "k:f:o:abdtC", opt, 0, 0, 0);
     if (i < 0) break;
     switch (i) {
       case 'k': kn = optarg; break;
@@ -483,13 +467,14 @@ static int sign(int argc, char *argv[])
       case 't': f &= ~F_BINARY; break;
       case 'b': f |= F_BINARY; break;
       case 'd': f |= F_DETACH; break;
+      case 'C': f |= F_NOCHECK; break;
       default: f |= F_BOGUS; break;
     }
   }
   if (argc - optind > 1 || (f & F_BOGUS))
     die(EXIT_FAILURE, "Usage: sign [-OPTIONS] [FILE]");
 
-  if (key_open(&kf, keyring, KOPEN_READ, keyreport, 0))
+  if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0))
     die(EXIT_FAILURE, "can't open keyring `%s'", keyring);
   if ((k = key_bytag(&kf, kn)) == 0)
     die(EXIT_FAILURE, "key `%s' not found", kn);
@@ -512,7 +497,7 @@ static int sign(int argc, char *argv[])
   dstr_reset(&d);
   key_fulltag(k, &d);
   s.s = getsig(k, "ccsig", 1);
-  if ((err = s.s->ops->check(s.s)) != 0)
+  if (!(f & F_NOCHECK) && (err = s.s->ops->check(s.s)) != 0)
     moan("key %s fails check: %s", d.buf, err);
   keyhash(k, s.s, &s.kh);
   e = initenc(eo, ofp,
@@ -599,6 +584,7 @@ static int verify(int argc, char *argv[])
   int i;
   char bb[MSGBUFSZ];
   size_t n;
+  time_t t_fresh = 0;
   dstr d = DSTR_INIT, dd = DSTR_INIT;
   const encops *eo;
   msgcanon mc_in = MC_INIT;
@@ -614,11 +600,13 @@ static int verify(int argc, char *argv[])
       { "output",      OPTF_ARGREQ,    0,      'o' },
       { "quiet",       0,              0,      'q' },
       { "utc",         0,              0,      'u' },
+      { "fresh-time",  0,              0,      't' },
       { "gmt",         0,              0,      'u' },
       { "verbose",     0,              0,      'v' },
+      { "nocheck",     0,              0,      'C' },
       { 0,             0,              0,      0 }
     };
-    i = mdwopt(argc, argv, "k:f:o:abquv", opt, 0, 0, 0);
+    i = mdwopt(argc, argv, "k:f:o:abqt:uvC", opt, 0, 0, 0);
     if (i < 0) break;
     switch (i) {
       case 'a': ef = "pem"; break;
@@ -627,6 +615,12 @@ static int verify(int argc, char *argv[])
       case 'f': ef = optarg; break;
       case 'o': of = optarg; break;
       case 'u': v.f |= F_UTC; break;
+      case 'C': v.f |= F_NOCHECK; break;
+      case 't':
+       if (strcmp(optarg, "always") == 0) t_fresh = 0;
+       else if ((t_fresh = get_date(optarg, 0)) < 0)
+         die(EXIT_FAILURE, "bad freshness time");
+       break;
       case 'q': if (v.verb > 0) v.verb--; break;
       case 'v': if (v.verb < 10) v.verb++; break;
       default: v.f |= F_BOGUS; break;
@@ -649,7 +643,7 @@ static int verify(int argc, char *argv[])
   } else
     optind++;
 
-  if (key_open(&kf, keyring, KOPEN_READ, keyreport, 0))
+  if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0))
     die(EXIT_FAILURE, "can't open keyring `%s'", keyring);
   if (kn && (kk = key_bytag(&kf, kn)) == 0)
     die(EXIT_FAILURE, "key `%s' not found", kn);
@@ -683,14 +677,14 @@ static int verify(int argc, char *argv[])
 
   s.s = getsig(k, "ccsig", 0);
   dstr_reset(&d); key_fulltag(k, &d);
-  if (v.verb && (err = s.s->ops->check(s.s)) != 0)
+  if (!(v.f & F_NOCHECK) && v.verb && (err = s.s->ops->check(s.s)) != 0)
     printf("WARN verification key %s fails check: %s\n", d.buf, err);
 
   dstr_reset(&dd); keyhash(k, s.s, &dd);
   if (dd.len != s.kh.len || memcmp(dd.buf, s.kh.buf, dd.len) != 0) {
     if (v.verb) printf("FAIL key hash mismatch\n");
     exit(EXIT_FAILURE);
-  }    
+  }
 
   /* --- Now a merry dance --- */
 
@@ -739,6 +733,14 @@ static int verify(int argc, char *argv[])
     if (v.verb) printf("FAIL signature verification failed\n");
     exit(EXIT_FAILURE);
   }
+  if (t_fresh && s.t < t_fresh) {
+    if (v.verb) printf("FAIL signature is stale\n");
+    exit(EXIT_FAILURE);
+  }
+  if (s.t > time(0)) {
+    if (v.verb) printf("FAIL signature timestamp in the future\n");
+    exit(EXIT_FAILURE);
+  }
   if (v.verb) {
     tm = (v.f & F_UTC) ? gmtime(&s.t) : localtime(&s.t);
     strftime(bb, sizeof(bb), "%Y-%m-%d %H:%M:%S %Z", tm);
@@ -765,7 +767,7 @@ static int verify(int argc, char *argv[])
       die(EXIT_FAILURE, "error unbuffering output: %s", strerror(errno));
   }
   if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp)))
-      die(EXIT_FAILURE, "error writing output: %s", strerror(errno));    
+      die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
 
   /* --- Tidy up --- */
 
@@ -777,7 +779,7 @@ static int verify(int argc, char *argv[])
   sig_destroy(&s);
   dstr_destroy(&d);
   dstr_destroy(&dd);
-  return (0);  
+  return (0);
 }
 
 /*----- Reformatting ------------------------------------------------------*/
@@ -807,8 +809,8 @@ static int format(int argc, char *argv[])
       { "embed",       0,              0,      'E' },
       { "format-in",   OPTF_ARGREQ,    0,      'f' },
       { "format-out",  OPTF_ARGREQ,    0,      'F' },
-      { "message",     OPTF_ARGREQ,    0,      'm' },
-      { "output",      OPTF_ARGREQ,    0,      'o' },
+      { "message",     OPTF_ARGREQ,    0,      'm' },
+      { "output",      OPTF_ARGREQ,    0,      'o' },
       { 0,             0,              0,      0 }
     };
     i = mdwopt(argc, argv, "f:F:m:o:aADE", opt, 0, 0, 0);
@@ -856,7 +858,7 @@ static int format(int argc, char *argv[])
 
   if (((s.f ^ v.f) & v.m) != 0)
     moan("boundary string inconsistent with contents (ignoring)");
-  
+
   mcsetup_read(&mc_in, s.f, &ie, dfn);
 
   /* --- Prepare the output stuff --- */
@@ -1056,7 +1058,7 @@ static cmd cmdtab[] = {
   CMD_ENCODE,
   CMD_DECODE,
   { "sign", sign,
-    "sign [-adt] [-k TAG] [-f FORMAT] [-o OUTPUT] [FILE]", "\
+    "sign [-adtC] [-k TAG] [-f FORMAT] [-o OUTPUT] [FILE]", "\
 Options:\n\
 \n\
 -a, --armour           Same as `-f pem'.\n\
@@ -1066,9 +1068,10 @@ Options:\n\
 -k, --key=TAG          Use public encryption key named by TAG.\n\
 -o, --output=FILE      Write output to FILE.\n\
 -t, --text             Canonify input message as a text file.\n\
+-C, --nocheck          Don't check the private key.\n\
 " },
   { "verify", verify,
-    "verify [-abquv] [-f FORMAT] [-k TAG] [-o OUTPUT]\n\t\
+    "verify [-abquvC] [-f FORMAT] [-k TAG] [-o OUTPUT]\n\t\
 [FILE [MESSAGE]]", "\
 Options:\n\
 \n\
@@ -1078,8 +1081,10 @@ Options:\n\
 -k, --key=TAG          Require that the message be signed by key TAG.\n\
 -o, --output=FILE      Write message to FILE.\n\
 -q, --quiet            Produce fewer messages.\n\
+-t, --freshtime=TIME   Only accept signatures made after this time.\n\
 -u, --utc              Show dates in UTC rather than local time.\n\
 -v, --verbose          Produce more verbose messages.\n\
+-C, --nocheck          Don't check the public key.\n\
 " },
   { "info", info,
     "info [-au] [-f FORMAT] [FILE]", "\