mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-05 12:31:50 +01:00
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
This commit is contained in:
parent
0899f6d4be
commit
e6175055fb
@ -60,6 +60,10 @@
|
|||||||
test "armored_key_8192" in armor.test! */
|
test "armored_key_8192" in armor.test! */
|
||||||
#define IOBUF_BUFFER_SIZE 8192
|
#define IOBUF_BUFFER_SIZE 8192
|
||||||
|
|
||||||
|
/* To avoid a potential DoS with compression packets we better limit
|
||||||
|
the number of filters in a chain. */
|
||||||
|
#define MAX_NESTING_FILTER 64
|
||||||
|
|
||||||
/*-- End configurable part. --*/
|
/*-- End configurable part. --*/
|
||||||
|
|
||||||
|
|
||||||
@ -1599,6 +1603,13 @@ iobuf_push_filter2 (iobuf_t a,
|
|||||||
|
|
||||||
if (a->use == 2 && (rc = iobuf_flush (a)))
|
if (a->use == 2 && (rc = iobuf_flush (a)))
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
if (a->subno >= MAX_NESTING_FILTER)
|
||||||
|
{
|
||||||
|
log_error ("i/o filter too deeply nested - corrupted data?\n");
|
||||||
|
return GPG_ERR_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
/* make a copy of the current stream, so that
|
/* make a copy of the current stream, so that
|
||||||
* A is the new stream and B the original one.
|
* A is the new stream and B the original one.
|
||||||
* The contents of the buffers are transferred to the
|
* The contents of the buffers are transferred to the
|
||||||
|
@ -92,12 +92,16 @@ struct mainproc_context
|
|||||||
DEK *dek;
|
DEK *dek;
|
||||||
int last_was_session_key;
|
int last_was_session_key;
|
||||||
KBNODE list; /* The current list of packets. */
|
KBNODE list; /* The current list of packets. */
|
||||||
int have_data;
|
|
||||||
IOBUF iobuf; /* Used to get the filename etc. */
|
IOBUF iobuf; /* Used to get the filename etc. */
|
||||||
int trustletter; /* Temporary usage in list_node. */
|
int trustletter; /* Temporary usage in list_node. */
|
||||||
ulong symkeys;
|
ulong symkeys;
|
||||||
struct kidlist_item *pkenc_list; /* List of encryption packets. */
|
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->pkenc_list = NULL;
|
||||||
c->list = NULL;
|
c->list = NULL;
|
||||||
c->have_data = 0;
|
c->any.data = 0;
|
||||||
|
c->any.uncompress_failed = 0;
|
||||||
c->last_was_session_key = 0;
|
c->last_was_session_key = 0;
|
||||||
xfree(c->dek); c->dek = NULL;
|
xfree(c->dek); c->dek = NULL;
|
||||||
}
|
}
|
||||||
@ -204,7 +209,7 @@ add_signature( CTX c, PACKET *pkt )
|
|||||||
{
|
{
|
||||||
KBNODE node;
|
KBNODE node;
|
||||||
|
|
||||||
c->any_sig_seen = 1;
|
c->any.sig_seen = 1;
|
||||||
if( pkt->pkttype == PKT_SIGNATURE && !c->list ) {
|
if( pkt->pkttype == PKT_SIGNATURE && !c->list ) {
|
||||||
/* This is the first signature for the following datafile.
|
/* This is the first signature for the following datafile.
|
||||||
* GPG does not write such packets; instead it always uses
|
* GPG does not write such packets; instead it always uses
|
||||||
@ -787,8 +792,21 @@ proc_compressed( CTX c, PACKET *pkt )
|
|||||||
rc = handle_compressed (c->ctrl, c, zd, proc_encrypt_cb, c);
|
rc = handle_compressed (c->ctrl, c, zd, proc_encrypt_cb, c);
|
||||||
else
|
else
|
||||||
rc = handle_compressed (c->ctrl, c, zd, NULL, NULL);
|
rc = handle_compressed (c->ctrl, c, zd, NULL, NULL);
|
||||||
if( rc )
|
|
||||||
log_error("uncompressing failed: %s\n", g10_errstr(rc));
|
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);
|
free_packet(pkt);
|
||||||
c->last_was_session_key = 0;
|
c->last_was_session_key = 0;
|
||||||
return rc;
|
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
|
Using log_error is required because verify_files does not check
|
||||||
error codes for each file but we want to terminate the process
|
error codes for each file but we want to terminate the process
|
||||||
with an error. */
|
with an error. */
|
||||||
if (!rc && !c->any_sig_seen)
|
if (!rc && !c->any.sig_seen)
|
||||||
{
|
{
|
||||||
write_status_text (STATUS_NODATA, "4");
|
write_status_text (STATUS_NODATA, "4");
|
||||||
log_error (_("no signature found\n"));
|
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
|
/* Propagate the signature seen flag upward. Do this only on
|
||||||
success so that we won't issue the nodata status several
|
success so that we won't issue the nodata status several
|
||||||
times. */
|
times. */
|
||||||
if (!rc && c->anchor && c->any_sig_seen)
|
if (!rc && c->anchor && c->any.sig_seen)
|
||||||
c->anchor->any_sig_seen = 1;
|
c->anchor->any.sig_seen = 1;
|
||||||
|
|
||||||
xfree( c );
|
xfree( c );
|
||||||
return rc;
|
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
|
Using log_error is required because verify_files does not check
|
||||||
error codes for each file but we want to terminate the process
|
error codes for each file but we want to terminate the process
|
||||||
with an error. */
|
with an error. */
|
||||||
if (!rc && !c->any_sig_seen)
|
if (!rc && !c->any.sig_seen)
|
||||||
{
|
{
|
||||||
write_status_text (STATUS_NODATA, "4");
|
write_status_text (STATUS_NODATA, "4");
|
||||||
log_error (_("no signature found\n"));
|
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
|
/* Propagate the signature seen flag upward. Do this only on success
|
||||||
so that we won't issue the nodata status several times. */
|
so that we won't issue the nodata status several times. */
|
||||||
if (!rc && c->anchor && c->any_sig_seen)
|
if (!rc && c->anchor && c->any.sig_seen)
|
||||||
c->anchor->any_sig_seen = 1;
|
c->anchor->any.sig_seen = 1;
|
||||||
|
|
||||||
xfree ( c );
|
xfree ( c );
|
||||||
return rc;
|
return rc;
|
||||||
@ -1301,7 +1319,7 @@ check_nesting (CTX c)
|
|||||||
{
|
{
|
||||||
log_error ("input data with too deeply nested packets\n");
|
log_error ("input data with too deeply nested packets\n");
|
||||||
write_status_text (STATUS_UNEXPECTED, "1");
|
write_status_text (STATUS_UNEXPECTED, "1");
|
||||||
return G10ERR_UNEXPECTED;
|
return GPG_ERR_BAD_DATA;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1423,7 +1441,7 @@ do_proc_packets( CTX c, IOBUF a )
|
|||||||
* Hmmm: Rewrite this whole module here??
|
* Hmmm: Rewrite this whole module here??
|
||||||
*/
|
*/
|
||||||
if( pkt->pkttype != PKT_SIGNATURE && pkt->pkttype != PKT_MDC )
|
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 )
|
if( newpkt == -1 )
|
||||||
;
|
;
|
||||||
@ -2061,7 +2079,7 @@ proc_tree( CTX c, KBNODE node )
|
|||||||
}
|
}
|
||||||
else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) {
|
else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) {
|
||||||
/* check all signatures */
|
/* check all signatures */
|
||||||
if( !c->have_data ) {
|
if( !c->any.data ) {
|
||||||
int use_textmode = 0;
|
int use_textmode = 0;
|
||||||
|
|
||||||
free_md_filter_context( &c->mfx );
|
free_md_filter_context( &c->mfx );
|
||||||
@ -2114,7 +2132,7 @@ proc_tree( CTX c, KBNODE node )
|
|||||||
&& node->pkt->pkt.gpg_control->control
|
&& node->pkt->pkt.gpg_control->control
|
||||||
== CTRLPKT_CLEARSIGN_START ) {
|
== CTRLPKT_CLEARSIGN_START ) {
|
||||||
/* clear text signed message */
|
/* clear text signed message */
|
||||||
if( !c->have_data ) {
|
if( !c->any.data ) {
|
||||||
log_error("cleartext signature without data\n" );
|
log_error("cleartext signature without data\n" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2156,7 +2174,7 @@ proc_tree( CTX c, KBNODE node )
|
|||||||
if( sig->sig_class != 0x00 && sig->sig_class != 0x01 )
|
if( sig->sig_class != 0x00 && sig->sig_class != 0x01 )
|
||||||
log_info(_("standalone signature of class 0x%02x\n"),
|
log_info(_("standalone signature of class 0x%02x\n"),
|
||||||
sig->sig_class);
|
sig->sig_class);
|
||||||
else if( !c->have_data ) {
|
else if( !c->any.data ) {
|
||||||
/* detached signature */
|
/* detached signature */
|
||||||
free_md_filter_context( &c->mfx );
|
free_md_filter_context( &c->mfx );
|
||||||
if (gcry_md_open (&c->mfx.md, sig->digest_algo, 0))
|
if (gcry_md_open (&c->mfx.md, sig->digest_algo, 0))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user