From cccf1efa4bcb97e2951a25ebd6250950d73d5169 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 2 Dec 1997 19:36:53 +0000 Subject: [PATCH] Sicherung --- TODO | 9 ++++- g10/build-packet.c | 29 ++++++++++++++ g10/g10.c | 2 +- g10/mainproc.c | 97 +++++++++++++++++++++++++++++++++++++++++++++- g10/packet.h | 16 +++++--- g10/parse-packet.c | 42 ++++++++++++++++++++ util/iobuf.c | 2 +- 7 files changed, 186 insertions(+), 11 deletions(-) diff --git a/TODO b/TODO index 2076d25f5..03f4faa4b 100644 --- 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 @@ -24,3 +23,11 @@ * 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. + diff --git a/g10/build-packet.c b/g10/build-packet.c index 910929658..6d9957f17 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -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: @@ -398,6 +403,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) { diff --git a/g10/g10.c b/g10/g10.c index a27bd19b6..345ccd5ae 100644 --- 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; diff --git a/g10/mainproc.c b/g10/mainproc.c index fd814cc80..8004c3803 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -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"); + +} + + + diff --git a/g10/packet.h b/g10/packet.h index bef97a41f..63626307e 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -63,6 +63,15 @@ typedef struct { } PKT_pubkey_enc; +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 */ @@ -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) diff --git a/g10/parse-packet.c b/g10/parse-packet.c index dd049406b..6aef1b4fe 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -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 diff --git a/util/iobuf.c b/util/iobuf.c index 466f07e31..61e1c5909 100644 --- a/util/iobuf.c +++ b/util/iobuf.c @@ -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*/