diff options
author | Werner Koch <wk@gnupg.org> | 2013-10-04 08:20:49 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2013-10-04 14:05:59 +0200 |
commit | e6175055fbca958b7fa43aaf84359574ca7f3ebb (patch) | |
tree | 332a905606ed1aadfd080cb9f42c9fcf1438b68f /g10/mainproc.c | |
parent | gpg: Fix bug with deeply nested compressed packets. (diff) | |
download | gnupg2-e6175055fbca958b7fa43aaf84359574ca7f3ebb.tar.xz gnupg2-e6175055fbca958b7fa43aaf84359574ca7f3ebb.zip |
gpg: Limit the nesting level of I/O filters.
* common/iobuf.c (MAX_NESTING_FILTER): New.
(iobuf_push_filter2): Limit the nesting level.
* g10/mainproc.c (mainproc_context): New field ANY. Change HAVE_DATA
and ANY_SIG_SIGN to bit fields of ANY. Add bit field
UNCOMPRESS_FAILED.
(proc_compressed): Avoid printing multiple Bad Data messages.
(check_nesting): Return GPG_ERR_BAD_DATA instead of UNEXPECTED_DATA.
--
This is a more general fix for the nested compression packet bug. In
particular this helps g10/import.c:read_block to stop pushing
compression filters onto an iobuf stream. This patch also reduces the
number of error messages for the non-import case.
Signed-off-by: Werner Koch <wk@gnupg.org>
(cherry picked from commit 35e40e2d514223c950c2f6d1214e02e92d87e997)
Resolved conflicts:
common/iobuf.c
g10/mainproc.c
Diffstat (limited to '')
-rw-r--r-- | g10/mainproc.c | 78 |
1 files changed, 48 insertions, 30 deletions
diff --git a/g10/mainproc.c b/g10/mainproc.c index 4dec7487b..bd5cac5bc 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -92,12 +92,16 @@ struct mainproc_context DEK *dek; int last_was_session_key; KBNODE list; /* The current list of packets. */ - int have_data; IOBUF iobuf; /* Used to get the filename etc. */ int trustletter; /* Temporary usage in list_node. */ ulong symkeys; struct kidlist_item *pkenc_list; /* List of encryption packets. */ - int any_sig_seen; /* Set to true if a signature packet has been seen. */ + struct { + unsigned int sig_seen:1; /* Set to true if a signature packet + has been seen. */ + unsigned int data:1; /* Any data packet seen */ + unsigned int uncompress_failed:1; + } any; }; @@ -126,7 +130,8 @@ release_list( CTX c ) } c->pkenc_list = NULL; c->list = NULL; - c->have_data = 0; + c->any.data = 0; + c->any.uncompress_failed = 0; c->last_was_session_key = 0; xfree(c->dek); c->dek = NULL; } @@ -204,7 +209,7 @@ add_signature( CTX c, PACKET *pkt ) { KBNODE node; - c->any_sig_seen = 1; + c->any.sig_seen = 1; if( pkt->pkttype == PKT_SIGNATURE && !c->list ) { /* This is the first signature for the following datafile. * GPG does not write such packets; instead it always uses @@ -777,21 +782,34 @@ proc_encrypt_cb (IOBUF a, void *info ) static int proc_compressed( CTX c, PACKET *pkt ) { - PKT_compressed *zd = pkt->pkt.compressed; - int rc; + PKT_compressed *zd = pkt->pkt.compressed; + int rc; - /*printf("zip: compressed data packet\n");*/ - if (c->sigs_only) - rc = handle_compressed (c->ctrl, c, zd, proc_compressed_cb, c ); - else if( c->encrypt_only ) - rc = handle_compressed (c->ctrl, c, zd, proc_encrypt_cb, c ); - else - rc = handle_compressed (c->ctrl, c, zd, NULL, NULL ); - if( rc ) - log_error("uncompressing failed: %s\n", g10_errstr(rc)); - free_packet(pkt); - c->last_was_session_key = 0; - return rc; + /*printf("zip: compressed data packet\n");*/ + if (c->sigs_only) + rc = handle_compressed (c->ctrl, c, zd, proc_compressed_cb, c); + else if( c->encrypt_only ) + rc = handle_compressed (c->ctrl, c, zd, proc_encrypt_cb, c); + else + rc = handle_compressed (c->ctrl, c, zd, NULL, NULL); + + if (gpg_err_code (rc) == GPG_ERR_BAD_DATA) + { + if (!c->any.uncompress_failed) + { + CTX cc; + + for (cc=c; cc; cc = cc->anchor) + cc->any.uncompress_failed = 1; + log_error ("uncompressing failed: %s\n", gpg_strerror (rc)); + } + } + else if (rc) + log_error ("uncompressing failed: %s\n", gpg_strerror (rc)); + + free_packet(pkt); + c->last_was_session_key = 0; + return rc; } /**************** @@ -1213,7 +1231,7 @@ proc_signature_packets (ctrl_t ctrl, void *anchor, IOBUF a, Using log_error is required because verify_files does not check error codes for each file but we want to terminate the process with an error. */ - if (!rc && !c->any_sig_seen) + if (!rc && !c->any.sig_seen) { write_status_text (STATUS_NODATA, "4"); log_error (_("no signature found\n")); @@ -1223,8 +1241,8 @@ proc_signature_packets (ctrl_t ctrl, void *anchor, IOBUF a, /* Propagate the signature seen flag upward. Do this only on success so that we won't issue the nodata status several times. */ - if (!rc && c->anchor && c->any_sig_seen) - c->anchor->any_sig_seen = 1; + if (!rc && c->anchor && c->any.sig_seen) + c->anchor->any.sig_seen = 1; xfree( c ); return rc; @@ -1257,7 +1275,7 @@ proc_signature_packets_by_fd (ctrl_t ctrl, Using log_error is required because verify_files does not check error codes for each file but we want to terminate the process with an error. */ - if (!rc && !c->any_sig_seen) + if (!rc && !c->any.sig_seen) { write_status_text (STATUS_NODATA, "4"); log_error (_("no signature found\n")); @@ -1266,8 +1284,8 @@ proc_signature_packets_by_fd (ctrl_t ctrl, /* Propagate the signature seen flag upward. Do this only on success so that we won't issue the nodata status several times. */ - if (!rc && c->anchor && c->any_sig_seen) - c->anchor->any_sig_seen = 1; + if (!rc && c->anchor && c->any.sig_seen) + c->anchor->any.sig_seen = 1; xfree ( c ); return rc; @@ -1294,14 +1312,14 @@ check_nesting (CTX c) { int level; - for (level = 0; c; c = c->anchor) + for (level=0; c; c = c->anchor) level++; if (level > MAX_NESTING_DEPTH) { log_error ("input data with too deeply nested packets\n"); write_status_text (STATUS_UNEXPECTED, "1"); - return G10ERR_UNEXPECTED; + return GPG_ERR_BAD_DATA; } return 0; } @@ -1423,7 +1441,7 @@ do_proc_packets( CTX c, IOBUF a ) * Hmmm: Rewrite this whole module here?? */ if( pkt->pkttype != PKT_SIGNATURE && pkt->pkttype != PKT_MDC ) - c->have_data = pkt->pkttype == PKT_PLAINTEXT; + c->any.data = (pkt->pkttype == PKT_PLAINTEXT); if( newpkt == -1 ) ; @@ -2061,7 +2079,7 @@ proc_tree( CTX c, KBNODE node ) } else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) { /* check all signatures */ - if( !c->have_data ) { + if( !c->any.data ) { int use_textmode = 0; free_md_filter_context( &c->mfx ); @@ -2114,7 +2132,7 @@ proc_tree( CTX c, KBNODE node ) && node->pkt->pkt.gpg_control->control == CTRLPKT_CLEARSIGN_START ) { /* clear text signed message */ - if( !c->have_data ) { + if( !c->any.data ) { log_error("cleartext signature without data\n" ); return; } @@ -2156,7 +2174,7 @@ proc_tree( CTX c, KBNODE node ) if( sig->sig_class != 0x00 && sig->sig_class != 0x01 ) log_info(_("standalone signature of class 0x%02x\n"), sig->sig_class); - else if( !c->have_data ) { + else if( !c->any.data ) { /* detached signature */ free_md_filter_context( &c->mfx ); if (gcry_md_open (&c->mfx.md, sig->digest_algo, 0)) |