aboutsummaryrefslogtreecommitdiffstats
path: root/g10/mainproc.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--g10/mainproc.c209
1 files changed, 111 insertions, 98 deletions
diff --git a/g10/mainproc.c b/g10/mainproc.c
index a83fb9e45..8512a9336 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -114,27 +114,14 @@ release_list( CTX c )
static int
add_onepass_sig( CTX c, PACKET *pkt )
{
- KBNODE node;
+ KBNODE node;
- if( c->list ) { /* add another packet */
- /* We can only append another onepass packet if the list
- * does contain only onepass packets */
- for( node=c->list; node && node->pkt->pkttype == PKT_ONEPASS_SIG;
- node = node->next )
- ;
- if( node ) {
- /* this is not the case, so we flush the current thing and
- * allow this packet to start a new verification thing */
- release_list( c );
- c->list = new_kbnode( pkt );
- }
- else
- add_kbnode( c->list, new_kbnode( pkt ));
- }
- else /* insert the first one */
- c->list = node = new_kbnode( pkt );
+ if ( c->list ) /* add another packet */
+ add_kbnode( c->list, new_kbnode( pkt ));
+ else /* insert the first one */
+ c->list = node = new_kbnode( pkt );
- return 1;
+ return 1;
}
@@ -1416,92 +1403,117 @@ pka_uri_from_sig (PKT_signature *sig)
static int
check_sig_and_print( CTX c, KBNODE node )
{
- PKT_signature *sig = node->pkt->pkt.signature;
- const char *astr;
- int rc, is_expkey=0, is_revkey=0;
+ PKT_signature *sig = node->pkt->pkt.signature;
+ const char *astr;
+ int rc, is_expkey=0, is_revkey=0;
- if( opt.skip_verify ) {
- log_info(_("signature verification suppressed\n"));
- return 0;
+ if (opt.skip_verify)
+ {
+ log_info(_("signature verification suppressed\n"));
+ return 0;
}
- /* It is not in all cases possible to check multiple signatures:
- * PGP 2 (which is also allowed by OpenPGP), does use the packet
- * sequence: sig+data, OpenPGP does use onepas+data=sig and GnuPG
- * sometimes uses (because I did'nt read the specs right) data+sig.
- * Because it is possible to create multiple signatures with
- * different packet sequence (e.g. data+sig and sig+data) it might
- * not be possible to get it right: let's say we have:
- * data+sig, sig+data,sig+data and we have not yet encountered the last
- * data, we could also see this a one data with 2 signatures and then
- * data+sig.
- * To protect against this we check that all signatures follow
- * without any intermediate packets. Note, that we won't get this
- * error when we use onepass packets or cleartext signatures because
- * we reset the list every time
- *
- * FIXME: Now that we have these marker packets, we should create a
- * real grammar and check against this.
- */
- {
- KBNODE n;
- int n_sig = 0;
- int n_plaintext = 0;
- int sig_seen, onepass_seen;
+ /* Check that the message composition is valid.
+
+ Per RFC-2440bis (-15) allowed:
- for (n=c->list; n; n=n->next )
+ S{1,n} -- detached signature.
+ S{1,n} P -- old style PGP2 signature
+ O{1,n} P S{1,n} -- standard OpenPGP signature.
+ C P S{1,n} -- cleartext signature.
+
+
+ O = One-Pass Signature packet.
+ S = Signature packet.
+ P = OpenPGP Message packet (Encrypted | Compressed | Literal)
+ (Note that the current rfc2440bis draft also allows
+ for a signed message but that does not work as it
+ introduces ambiguities.)
+ We keep track of these packages using the marker packet
+ CTRLPKT_PLAINTEXT_MARK.
+ C = Marker packet for cleartext signatures.
+
+ We reject all other messages.
+
+ Actually we are calling this too often, i.e. for verification of
+ each message but better have some duplicate work than to silently
+ introduce a bug here.
+ */
+ {
+ KBNODE n;
+ int n_onepass, n_sig;
+
+ log_debug ("checking signature packet composition\n");
+ dump_kbnode (c->list);
+
+ n = c->list;
+ assert (n);
+ if ( n->pkt->pkttype == PKT_SIGNATURE )
+ {
+ /* This is either "S{1,n}" case (detached signature) or
+ "S{1,n} P" (old style PGP2 signature). */
+ for (n = n->next; n; n = n->next)
+ if (n->pkt->pkttype != PKT_SIGNATURE)
+ break;
+ if (!n)
+ ; /* Okay, this is a detached signature. */
+ else if (n->pkt->pkttype == PKT_GPG_CONTROL
+ && (n->pkt->pkt.gpg_control->control
+ == CTRLPKT_PLAINTEXT_MARK) )
{
- if ( n->pkt->pkttype == PKT_SIGNATURE )
- n_sig++;
- else if (n->pkt->pkttype == PKT_GPG_CONTROL
- && (n->pkt->pkt.gpg_control->control
- == CTRLPKT_PLAINTEXT_MARK) )
- n_plaintext++;
+ if (n->next)
+ goto ambiguous; /* We only allow one P packet. */
}
-
- for (sig_seen=onepass_seen=0,n=c->list; n; n=n->next )
+ else
+ goto ambiguous;
+ }
+ else if (n->pkt->pkttype == PKT_ONEPASS_SIG)
+ {
+ /* This is the "O{1,n} P S{1,n}" case (standard signature). */
+ for (n_onepass=1, n = n->next;
+ n && n->pkt->pkttype == PKT_ONEPASS_SIG; n = n->next)
+ n_onepass++;
+ if (!n || !(n->pkt->pkttype == PKT_GPG_CONTROL
+ && (n->pkt->pkt.gpg_control->control
+ == CTRLPKT_PLAINTEXT_MARK)))
+ goto ambiguous;
+ for (n_sig=0, n = n->next;
+ n && n->pkt->pkttype == PKT_SIGNATURE; n = n->next)
+ n_sig++;
+ if (n || !n_sig)
+ goto ambiguous;
+ if (n_onepass != n_sig)
{
- if (n->pkt->pkttype == PKT_ONEPASS_SIG)
- {
- onepass_seen++;
- }
- else if (n->pkt->pkttype == PKT_GPG_CONTROL
- && (n->pkt->pkt.gpg_control->control
- == CTRLPKT_CLEARSIGN_START) )
- {
- onepass_seen++; /* Handle the same way as a onepass. */
- }
- else if ( (sig_seen && n->pkt->pkttype != PKT_SIGNATURE) )
- {
- log_error(_("can't handle these multiple signatures\n"));
- return 0;
- }
- else if ( n->pkt->pkttype == PKT_SIGNATURE )
- {
- sig_seen = 1;
- }
- else if (n_sig > 1 && !sig_seen && !onepass_seen
- && n->pkt->pkttype == PKT_GPG_CONTROL
- && (n->pkt->pkt.gpg_control->control
- == CTRLPKT_PLAINTEXT_MARK) )
- {
- /* Plaintext before signatures but no onepass
- signature packets. */
- log_error(_("can't handle these multiple signatures\n"));
- return 0;
- }
- else if (n_plaintext > 1 && !sig_seen && !onepass_seen
- && n->pkt->pkttype == PKT_GPG_CONTROL
- && (n->pkt->pkt.gpg_control->control
- == CTRLPKT_PLAINTEXT_MARK) )
- {
- /* More than one plaintext before a signature but no
- onepass packets. */
- log_error(_("can't handle this ambiguous signed data\n"));
- return 0;
- }
+ log_info ("number of one-pass packets does not match "
+ "number of signature packets\n");
+ goto ambiguous;
}
- }
+ }
+ else if (n->pkt->pkttype == PKT_GPG_CONTROL
+ && n->pkt->pkt.gpg_control->control == CTRLPKT_CLEARSIGN_START )
+ {
+ /* This is the "C P S{1,n}" case (clear text signature). */
+ n = n->next;
+ if (!n || !(n->pkt->pkttype == PKT_GPG_CONTROL
+ && (n->pkt->pkt.gpg_control->control
+ == CTRLPKT_PLAINTEXT_MARK)))
+ goto ambiguous;
+ for (n_sig=0, n = n->next;
+ n && n->pkt->pkttype == PKT_SIGNATURE; n = n->next)
+ n_sig++;
+ if (n || !n_sig)
+ goto ambiguous;
+ }
+ else
+ {
+ ambiguous:
+ log_error(_("can't handle this ambiguous signature data\n"));
+ return 0;
+ }
+
+ }
+
+ /* (Indendation below not yet changed to GNU style.) */
astr = pubkey_algo_to_string( sig->pubkey_algo );
if(keystrlen()>8)
@@ -1926,7 +1938,8 @@ proc_tree( CTX c, KBNODE node )
/* prepare to create all requested message digests */
c->mfx.md = md_open(0, 0);
- /* fixme: why looking for the signature packet and not 1passpacket*/
+ /* fixme: why looking for the signature packet and not the
+ one-pass packet? */
for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) {
md_enable( c->mfx.md, n1->pkt->pkt.signature->digest_algo);
}