summaryrefslogtreecommitdiff
path: root/g10/mainproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/mainproc.c')
-rw-r--r--g10/mainproc.c280
1 files changed, 144 insertions, 136 deletions
diff --git a/g10/mainproc.c b/g10/mainproc.c
index c7df113..551ab58 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -1,6 +1,7 @@
/* mainproc.c - handle packets
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
* 2008, 2009 Free Software Foundation, Inc.
+ * Copyright (C) 2013 Werner Koch
*
* This file is part of GnuPG.
*
@@ -42,6 +43,11 @@
#include "pka.h"
+/* Put an upper limit on nested packets. The 32 is an arbitrary
+ value, a much lower should actually be sufficient. */
+#define MAX_NESTING_DEPTH 32
+
+
struct kidlist_item {
struct kidlist_item *next;
u32 kid[2];
@@ -86,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;
};
@@ -120,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;
}
@@ -198,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
@@ -444,7 +455,7 @@ print_pkenc_list( struct kidlist_item *list, int failed )
if ( !failed && list->reason )
continue;
- algstr = gcry_pk_algo_name ( list->pubkey_algo );
+ algstr = openpgp_pk_algo_name ( list->pubkey_algo );
pk = xmalloc_clear( sizeof *pk );
if( !algstr )
@@ -558,6 +569,7 @@ proc_encrypted( CTX c, PACKET *pkt )
}
else if( !c->dek )
result = G10ERR_NO_SECKEY;
+
if( !result )
result = decrypt_data( c, pkt->pkt.encrypted, c->dek );
@@ -572,16 +584,6 @@ proc_encrypted( CTX c, PACKET *pkt )
write_status( STATUS_GOODMDC );
else if(!opt.no_mdc_warn)
log_info (_("WARNING: message was not integrity protected\n"));
- if(opt.show_session_key)
- {
- int i;
- char *buf = xmalloc ( c->dek->keylen*2 + 20 );
- sprintf ( buf, "%d:", c->dek->algo );
- for(i=0; i < c->dek->keylen; i++ )
- sprintf(buf+strlen(buf), "%02X", c->dek->key[i] );
- log_info( "session key: `%s'\n", buf );
- write_status_text ( STATUS_SESSION_KEY, buf );
- }
}
else if( result == G10ERR_BAD_SIGN ) {
log_error(_("WARNING: encrypted message has been manipulated!\n"));
@@ -699,9 +701,9 @@ proc_plaintext( CTX c, PACKET *pkt )
BUG ();
}
if ( DBG_HASHING ) {
- gcry_md_start_debug ( c->mfx.md, "verify" );
+ gcry_md_debug ( c->mfx.md, "verify" );
if ( c->mfx.md2 )
- gcry_md_start_debug ( c->mfx.md2, "verify2" );
+ gcry_md_debug ( c->mfx.md2, "verify2" );
}
rc=0;
@@ -764,23 +766,37 @@ proc_encrypt_cb( IOBUF a, void *info )
return proc_encryption_packets( info, a );
}
-static void
+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, zd, proc_compressed_cb, c );
- else if( c->encrypt_only )
- rc = handle_compressed( c, zd, proc_encrypt_cb, c );
- else
- rc = handle_compressed( c, zd, NULL, NULL );
- if( rc )
- log_error("uncompressing failed: %s\n", g10_errstr(rc));
- free_packet(pkt);
- c->last_was_session_key = 0;
+ /*printf("zip: compressed data packet\n");*/
+ if (c->sigs_only)
+ rc = handle_compressed (c, zd, proc_compressed_cb, c);
+ else if (c->encrypt_only)
+ rc = handle_compressed (c, zd, proc_encrypt_cb, c);
+ else
+ rc = handle_compressed (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", g10_errstr(rc));
+ }
+ }
+ else if (rc)
+ log_error("uncompressing failed: %s\n", g10_errstr(rc));
+
+ free_packet (pkt);
+ c->last_was_session_key = 0;
+ return rc;
}
/****************
@@ -901,7 +917,6 @@ print_userid( PACKET *pkt )
static void
list_node( CTX c, KBNODE node )
{
- int any=0;
int mainkey;
if( !node )
@@ -929,47 +944,55 @@ list_node( CTX c, KBNODE node )
if( mainkey && !opt.fast_list_mode )
putchar( get_ownertrust_info (pk) );
putchar(':');
- if( node->next && node->next->pkt->pkttype == PKT_RING_TRUST) {
- putchar('\n'); any=1;
- if( opt.fingerprint )
- print_fingerprint( pk, NULL, 0 );
- printf("rtv:1:%u:\n",
- node->next->pkt->pkt.ring_trust->trustval );
- }
- }
+ }
else
- printf("%s %4u%c/%s %s%s",
- mainkey? "pub":"sub", nbits_from_pk( pk ),
- pubkey_letter( pk->pubkey_algo ), keystr_from_pk( pk ),
- datestr_from_pk( pk ), mainkey?" ":"");
+ {
+ printf("%s %4u%c/%s %s",
+ mainkey? "pub":"sub", nbits_from_pk( pk ),
+ pubkey_letter( pk->pubkey_algo ), keystr_from_pk( pk ),
+ datestr_from_pk (pk));
+ }
+
+ if (pk->is_revoked)
+ {
+ printf(" [");
+ printf(_("revoked: %s"),revokestr_from_pk(pk));
+ printf("]\n");
+ }
+ else if (pk->expiredate && !opt.with_colons)
+ {
+ printf(" [");
+ printf(_("expires: %s"),expirestr_from_pk(pk));
+ printf("]\n");
+ }
+ else
+ putchar ('\n');
+
+ if ((mainkey && opt.fingerprint) || opt.fingerprint > 1)
+ print_fingerprint (pk, NULL, 0);
+
+ if (opt.with_colons)
+ {
+ if (node->next && node->next->pkt->pkttype == PKT_RING_TRUST)
+ printf("rtv:1:%u:\n", node->next->pkt->pkt.ring_trust->trustval);
+ }
if( mainkey ) {
/* and now list all userids with their signatures */
for( node = node->next; node; node = node->next ) {
if( node->pkt->pkttype == PKT_SIGNATURE ) {
- if( !any ) {
- if( node->pkt->pkt.signature->sig_class == 0x20 )
- puts("[revoked]");
- else
- putchar('\n');
- any = 1;
- }
list_node(c, node );
}
else if( node->pkt->pkttype == PKT_USER_ID ) {
- if( any ) {
- if( opt.with_colons )
- printf("%s:::::::::",
- node->pkt->pkt.user_id->attrib_data?"uat":"uid");
- else
- printf( "uid%*s", 28, "" );
- }
+ if( opt.with_colons )
+ printf("%s:::::::::",
+ node->pkt->pkt.user_id->attrib_data?"uat":"uid");
+ else
+ printf( "uid%*s", 28, "" );
print_userid( node->pkt );
if( opt.with_colons )
putchar(':');
putchar('\n');
- if( opt.fingerprint && !any )
- print_fingerprint( pk, NULL, 0 );
if( opt.with_colons
&& node->next
&& node->next->pkt->pkttype == PKT_RING_TRUST ) {
@@ -977,38 +1000,12 @@ list_node( CTX c, KBNODE node )
node->next->pkt->pkt.ring_trust?
node->next->pkt->pkt.ring_trust->trustval : 0);
}
- any=1;
}
else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
- if( !any ) {
- putchar('\n');
- any = 1;
- }
- list_node(c, node );
+ list_node(c, node );
}
}
}
- else
- {
- /* of subkey */
- if( pk->is_revoked )
- {
- printf(" [");
- printf(_("revoked: %s"),revokestr_from_pk(pk));
- printf("]");
- }
- else if( pk->expiredate )
- {
- printf(" [");
- printf(_("expires: %s"),expirestr_from_pk(pk));
- printf("]");
- }
- }
-
- if( !any )
- putchar('\n');
- if( !mainkey && opt.fingerprint > 1 )
- print_fingerprint( pk, NULL, 0 );
}
else if( (mainkey = (node->pkt->pkttype == PKT_SECRET_KEY) )
|| node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
@@ -1024,55 +1021,39 @@ list_node( CTX c, KBNODE node )
sk->pubkey_algo,
(ulong)keyid[0],(ulong)keyid[1],
colon_datestr_from_sk( sk ),
- colon_strtime (sk->expiredate)
- /* fixme: add LID */ );
+ colon_strtime (sk->expiredate));
}
else
printf("%s %4u%c/%s %s ", mainkey? "sec":"ssb",
nbits_from_sk( sk ), pubkey_letter( sk->pubkey_algo ),
keystr_from_sk( sk ), datestr_from_sk( sk ));
+
+ putchar ('\n');
+ if ((mainkey && opt.fingerprint) || opt.fingerprint > 1)
+ print_fingerprint (NULL, sk,0);
+
if( mainkey ) {
/* and now list all userids with their signatures */
for( node = node->next; node; node = node->next ) {
if( node->pkt->pkttype == PKT_SIGNATURE ) {
- if( !any ) {
- if( node->pkt->pkt.signature->sig_class == 0x20 )
- puts("[revoked]");
- else
- putchar('\n');
- any = 1;
- }
list_node(c, node );
}
else if( node->pkt->pkttype == PKT_USER_ID ) {
- if( any ) {
- if( opt.with_colons )
- printf("%s:::::::::",
- node->pkt->pkt.user_id->attrib_data?"uat":"uid");
- else
- printf( "uid%*s", 28, "" );
- }
+ if( opt.with_colons )
+ printf("%s:::::::::",
+ node->pkt->pkt.user_id->attrib_data?"uat":"uid");
+ else
+ printf( "uid%*s", 28, "" );
print_userid( node->pkt );
if( opt.with_colons )
putchar(':');
putchar('\n');
- if( opt.fingerprint && !any )
- print_fingerprint( NULL, sk, 0 );
- any=1;
}
else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
- if( !any ) {
- putchar('\n');
- any = 1;
- }
- list_node(c, node );
+ list_node(c, node );
}
}
}
- if( !any )
- putchar('\n');
- if( !mainkey && opt.fingerprint > 1 )
- print_fingerprint( NULL, sk, 0 );
}
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;
@@ -1197,7 +1178,7 @@ proc_signature_packets( 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"));
@@ -1207,8 +1188,8 @@ proc_signature_packets( 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;
@@ -1234,7 +1215,7 @@ proc_signature_packets_by_fd (void *anchor, IOBUF a, int signed_data_fd )
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"));
@@ -1243,8 +1224,8 @@ proc_signature_packets_by_fd (void *anchor, IOBUF a, int signed_data_fd )
/* 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;
@@ -1265,14 +1246,37 @@ proc_encryption_packets( void *anchor, IOBUF a )
}
-int
+static int
+check_nesting (CTX c)
+{
+ int level;
+
+ 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 GPG_ERR_BAD_DATA;
+ }
+ return 0;
+}
+
+
+static int
do_proc_packets( CTX c, IOBUF a )
{
- PACKET *pkt = xmalloc( sizeof *pkt );
- int rc=0;
- int any_data=0;
+ PACKET *pkt;
+ int rc = 0;
+ int any_data = 0;
int newpkt;
+ rc = check_nesting (c);
+ if (rc)
+ return rc;
+
+ pkt = xmalloc( sizeof *pkt );
c->iobuf = a;
init_packet(pkt);
while( (rc=parse_packet(a, pkt)) != -1 ) {
@@ -1293,7 +1297,7 @@ do_proc_packets( CTX c, IOBUF a )
case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break;
case PKT_ENCRYPTED:
case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break;
- case PKT_COMPRESSED: proc_compressed( c, pkt ); break;
+ case PKT_COMPRESSED: rc = proc_compressed( c, pkt ); break;
default: newpkt = 0; break;
}
}
@@ -1311,7 +1315,7 @@ do_proc_packets( CTX c, IOBUF a )
goto leave;
case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break;
case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break;
- case PKT_COMPRESSED: proc_compressed( c, pkt ); break;
+ case PKT_COMPRESSED: rc = proc_compressed( c, pkt ); break;
case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
case PKT_GPG_CONTROL: newpkt = add_gpg_control(c, pkt); break;
default: newpkt = 0; break;
@@ -1331,7 +1335,7 @@ do_proc_packets( CTX c, IOBUF a )
case PKT_ENCRYPTED:
case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break;
case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break;
- case PKT_COMPRESSED: proc_compressed( c, pkt ); break;
+ case PKT_COMPRESSED: rc = proc_compressed( c, pkt ); break;
case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
case PKT_GPG_CONTROL: newpkt = add_gpg_control(c, pkt); break;
default: newpkt = 0; break;
@@ -1356,13 +1360,17 @@ do_proc_packets( CTX c, IOBUF a )
case PKT_ENCRYPTED:
case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break;
case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break;
- case PKT_COMPRESSED: proc_compressed( c, pkt ); break;
+ case PKT_COMPRESSED: rc = proc_compressed( c, pkt ); break;
case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
case PKT_GPG_CONTROL: newpkt = add_gpg_control(c, pkt); break;
case PKT_RING_TRUST: newpkt = add_ring_trust( c, pkt ); break;
default: newpkt = 0; break;
}
}
+
+ if (rc)
+ goto leave;
+
/* This is a very ugly construct and frankly, I don't remember why
* I used it. Adding the MDC check here is a hack.
* The right solution is to initiate another context for encrypted
@@ -1372,7 +1380,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 )
;
@@ -1592,7 +1600,7 @@ check_sig_and_print( CTX c, KBNODE node )
/* (Indendation below not yet changed to GNU style.) */
- astr = gcry_pk_algo_name ( sig->pubkey_algo );
+ astr = openpgp_pk_algo_name ( sig->pubkey_algo );
if(keystrlen()>8)
{
log_info(_("Signature made %s\n"),asctimestamp(sig->timestamp));
@@ -2010,7 +2018,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 );
@@ -2063,7 +2071,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;
}
@@ -2105,7 +2113,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))
@@ -2138,9 +2146,9 @@ proc_tree( CTX c, KBNODE node )
/* c->mfx.md2? 0 :(sig->sig_class == 0x01) */
#endif
if ( DBG_HASHING ) {
- gcry_md_start_debug( c->mfx.md, "verify" );
+ gcry_md_debug( c->mfx.md, "verify" );
if ( c->mfx.md2 )
- gcry_md_start_debug( c->mfx.md2, "verify2" );
+ gcry_md_debug( c->mfx.md2, "verify2" );
}
if( c->sigs_only ) {
if (c->signed_data.used && c->signed_data.data_fd != -1)