Sicherung
authorWerner Koch <wk@gnupg.org>
Tue, 2 Dec 1997 19:36:53 +0000 (19:36 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 2 Dec 1997 19:36:53 +0000 (19:36 +0000)
TODO
g10/build-packet.c
g10/g10.c
g10/mainproc.c
g10/packet.h
g10/parse-packet.c
util/iobuf.c

diff --git a/TODO b/TODO
index 2076d25..03f4faa 100644 (file)
--- a/TODO
+++ b/TODO
@@ -6,7 +6,6 @@
       function of iobuf.
     * filter all output read from the input when displaying it to the user.
     * keyring editing
-    * remove some debugging stuff (e.g. the listing mode in mainproc)
     * add trust stuff
     * make ttyio.c work (hide passwords etc..)
     * add detached signatures
     * add signal handling
     * enable a SIGSEGV handler while using zlib functions
 
+    * PGP writes the signature and then the file, this is not
+      a good idea, we can't write such files if we take input rom stdin.
+      So the solution will: accept such packet, but write
+      signature the corret way: first the data and then the signature[s]
+      this is much easier to check, also we must read the entire data
+      before we can check wether we have the pubkey or not.  The one-pass
+      signature packets should be implemented to avoid this.
+
index 9109296..6d9957f 100644 (file)
@@ -44,6 +44,7 @@ static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt );
 static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed );
 static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd );
 static int do_signature( IOBUF out, int ctb, PKT_signature *sig );
+static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops );
 
 static int calc_header_length( u32 len );
 static int write_16(IOBUF inp, u16 a);
@@ -95,6 +96,9 @@ build_packet( IOBUF out, PACKET *pkt )
       case PKT_SIGNATURE:
        rc = do_signature( out, ctb, pkt->pkt.signature );
        break;
+      case PKT_ONEPASS_SIG:
+       rc = do_onepass_sig( out, ctb, pkt->pkt.onepass_sig );
+       break;
       case PKT_RING_TRUST:
       default:
        log_bug("invalid packet type in build_packet()");
@@ -124,6 +128,7 @@ calc_packet_length( PACKET *pkt )
       case PKT_PUBKEY_ENC:
       case PKT_ENCRYPTED:
       case PKT_SIGNATURE:
+      case PKT_ONEPASS_SIG:
       case PKT_RING_TRUST:
       case PKT_COMPRESSED:
       default:
@@ -399,6 +404,30 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
 
 
 static int
+do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops )
+{
+    int rc = 0;
+    IOBUF a = iobuf_temp();
+
+    write_version( a, ctb );
+    iobuf_put(a, ops->sig_class );
+    iobuf_put(a, ops->digest_algo );
+    iobuf_put(a, ops->pubkey_algo );
+    write_32(a, ops->keyid[0] );
+    write_32(a, ops->keyid[1] );
+    iobuf_put(a, ops->last );
+
+    write_header(out, ctb, iobuf_get_temp_length(a) );
+    if( iobuf_write_temp( out, a ) )
+       rc = G10ERR_WRITE_FILE;
+
+  leave:
+    iobuf_close(a);
+    return rc;
+}
+
+
+static int
 write_16(IOBUF out, u16 a)
 {
     iobuf_put(out, a>>8);
index a27bd19..345ccd5 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -230,7 +230,7 @@ main( int argc, char **argv )
       case aSign: /* sign the given file */
        if( argc > 1 )
            usage(1);
-       if( (rc = sign_file(fname, 0, locusr)) )
+       if( (rc = sign_file(fname, opt.detached_sig, locusr)) )
            log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) );
        break;
 
index fd814cc..8004c38 100644 (file)
@@ -75,6 +75,7 @@ typedef struct {
 
 
 static void list_node( CTX c, NODE node );
+static void proc_tree( CTX c, NODE node );
 
 static int
 pubkey_letter( int algo )
@@ -142,12 +143,31 @@ release_cert( CTX c )
 {
     if( !c->cert )
        return;
-  list_node(c, c->cert );
+    proc_tree(c, c->cert );
     release_node( c->cert );
     c->cert = NULL;
 }
 
 
+static int
+add_onepass_sig( CTX c, PACKET *pkt )
+{
+    if( c->cert ) { /* add another packet */
+       NODE node;
+
+       if( c->cert->pkt->pkttype != PKT_ONEPASS_SIG ) {
+          log_error("add_onepass_sig: another packet is in the way\n");
+          release_cert( c );
+       }
+       node = new_node( pkt );
+       node->next = c->cert;
+       c->cert = node;
+    }
+    else /* insert the first one */
+       c->cert = new_node( pkt );
+    return 1;
+}
+
 
 static int
 add_public_cert( CTX c, PACKET *pkt )
@@ -205,10 +225,24 @@ add_signature( CTX c, PACKET *pkt )
     NODE node, n1, n2;
 
     if( !c->cert ) {
-       log_error("orphaned signature (no certificate)\n" );
+       /* orphaned signature (no certificate)
+        * this is the first signature for a following datafile
+        */
        return 0;
     }
     assert( c->cert->pkt );
+    if( c->cert->pkt->pkttype == PKT_ONEPASS_SIG ) {
+       /* The root is a onepass signature, so we are signing data
+        * The childs direct under the root are the signatures
+        * (there is no need to keep the correct sequence of packets)
+        */
+       node = new_node( pkt );
+       node->next = c->cert->child;
+       c->cert->child = node;
+       return 1;
+    }
+
+
     if( !c->cert->child ) {
        log_error("orphaned signature (no userid)\n" );
        return 0;
@@ -531,6 +565,7 @@ proc_packets( IOBUF a )
          case PKT_ENCRYPTED:   proc_encrypted( c, pkt ); break;
          case PKT_PLAINTEXT:   proc_plaintext( c, pkt ); break;
          case PKT_COMPRESSED:  proc_compressed( c, pkt ); break;
+         case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
          default: newpkt = 0; break;
        }
        if( newpkt == -1 )
@@ -553,3 +588,61 @@ proc_packets( IOBUF a )
 }
 
 
+static void
+print_keyid( FILE *fp, u32 *keyid )
+{
+    size_t n;
+    char *p = get_user_id( keyid, &n );
+    print_string( fp, p, n );
+    m_free(p);
+}
+
+/****************
+ * Preocess the tree which starts at node
+ */
+static void
+proc_tree( CTX c, NODE node )
+{
+    NODE n1;
+    int rc;
+
+    if( node->pkt->pkttype == PKT_PUBLIC_CERT )
+       list_node( c, node );
+    else if( node->pkt->pkttype == PKT_SECRET_CERT )
+       list_node( c, node );
+    else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) {
+       if( !node->child )
+           log_error("proc_tree: onepass_sig without followin data\n");
+       else if( node->child->pkt->pkttype != PKT_SIGNATURE )
+           log_error("proc_tree: onepass_sig not followed by signature\n");
+       else {  /* check all signature */
+           for(n1=node->child; n1; n1 = n1->next ) {
+               PKT_signature *sig = n1->pkt->pkt.signature;
+
+               rc = do_check_sig(c, n1 );
+               if( !rc ) {
+                   log_info("Good signature from ");
+                   print_keyid( stderr, sig->keyid );
+                   putc('\n', stderr);
+               }
+               else if( rc == G10ERR_BAD_SIGN ) {
+                   log_error("BAD signature from ");
+                   print_keyid( stderr, sig->keyid );
+                   putc('\n', stderr);
+               }
+               else
+                   log_error("Can't check signature made by %08lX: %s\n",
+                              sig->keyid[1], g10_errstr(rc) );
+           }
+       }
+    }
+    else if( node->pkt->pkttype == PKT_SIGNATURE ) {
+       log_info("proc_tree: old style signature\n");
+    }
+    else
+       log_error("proc_tree: invalid root packet\n");
+
+}
+
+
+
index bef97a4..6362630 100644 (file)
@@ -65,6 +65,15 @@ typedef struct {
 
 typedef struct {
     u32     keyid[2];      /* 64 bit keyid */
+    byte    sig_class;     /* sig classification */
+    byte    digest_algo;    /* algorithm used for digest */
+    byte    pubkey_algo;    /* algorithm used for public key scheme */
+    byte    last;          /* a stupid flag */
+} PKT_onepass_sig;
+
+
+typedef struct {
+    u32     keyid[2];      /* 64 bit keyid */
     u32     timestamp;     /* signature made */
     byte    sig_class;     /* sig classification, append for MD calculation*/
     byte    pubkey_algo;    /* algorithm used for public key scheme */
@@ -182,12 +191,10 @@ typedef struct {
 /* combine all packets into a union */
 struct packet_struct {
     pkttype_t pkttype;
-    PKT_public_cert *pkc_parent;     /* the pubkey to which it belongs */
-    PKT_secret_cert *skc_parent;      /* the seckey to which it belongs */
-    PKT_user_id     *user_parent;     /* the user_id to which it belongs */
     union {
        void *generic;
        PKT_pubkey_enc  *pubkey_enc;    /* PKT_PUBKEY_ENC */
+       PKT_onepass_sig *onepass_sig;   /* PKT_ONEPASS_SIG */
        PKT_signature   *signature;     /* PKT_SIGNATURE */
        PKT_public_cert *public_cert;   /* PKT_PUBLIC_CERT */
        PKT_secret_cert *secret_cert;   /* PKT_SECRET_CERT */
@@ -200,9 +207,6 @@ struct packet_struct {
 };
 
 #define init_packet(a) do { (a)->pkttype = 0;          \
-                           (a)->pkc_parent = NULL;     \
-                           (a)->skc_parent = NULL;     \
-                           (a)->user_parent = NULL;    \
                            (a)->pkt.generic = NULL;    \
                       } while(0)
 
index dd04940..6aef1b4 100644 (file)
@@ -42,6 +42,8 @@ static int  parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen,
                                                             PACKET *packet );
 static int  parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
                                                         PKT_signature *sig );
+static int  parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
+                                                       PKT_onepass_sig *ops );
 static int  parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
                                      byte *hdr, int hdrlen, PACKET *packet );
 static int  parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
@@ -159,6 +161,10 @@ parse_packet( IOBUF inp, PACKET *pkt )
        pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature );
        rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
        break;
+      case PKT_ONEPASS_SIG:
+       pkt->pkt.onepass_sig = m_alloc_clear(sizeof *pkt->pkt.onepass_sig );
+       rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig );
+       break;
       case PKT_USER_ID:
        rc = parse_user_id(inp, pkttype, pktlen, pkt );
        break;
@@ -340,6 +346,42 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
 }
 
 
+static int
+parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
+                                            PKT_onepass_sig *ops )
+{
+    int version;
+    unsigned n;
+
+    if( pktlen < 13 ) {
+       log_error("packet(%d) too short\n", pkttype);
+       goto leave;
+    }
+    version = iobuf_get_noeof(inp); pktlen--;
+    if( version != 3 ) {
+       log_error("onepass_sig with unknown version %d\n", version);
+       goto leave;
+    }
+    ops->sig_class = iobuf_get_noeof(inp); pktlen--;
+    ops->digest_algo = iobuf_get_noeof(inp); pktlen--;
+    ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
+    ops->keyid[0] = read_32(inp); pktlen -= 4;
+    ops->keyid[1] = read_32(inp); pktlen -= 4;
+    ops->last = iobuf_get_noeof(inp); pktlen--;
+    if( list_mode )
+       printf(":onepass_sig packet: keyid %08lX%08lX\n"
+              "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
+               ops->keyid[0], ops->keyid[1],
+               version, ops->sig_class,
+               ops->digest_algo, ops->pubkey_algo, ops->last );
+
+
+  leave:
+    skip_rest(inp, pktlen);
+    return 0;
+}
+
+
 
 
 static int
index 466f07e..61e1c59 100644 (file)
@@ -283,7 +283,7 @@ iobuf_cancel( IOBUF a )
 {
     const char *s;
 
-    if( a->usage == 2 ) {
+    if( a && a->usage == 2 ) {
        s = iobuf_get_fname(a);
        if( s && *s )
            remove(s);  /* remove the file. Fixme: this will fail for MSDOZE*/