diff --git a/common/openpgpdefs.h b/common/openpgpdefs.h --- a/common/openpgpdefs.h +++ b/common/openpgpdefs.h @@ -53,7 +53,7 @@ PKT_MDC = 19, /* Manipulation detection code packet. */ PKT_ENCRYPTED_AEAD= 20, /* AEAD encrypted data packet. */ PKT_COMMENT = 61, /* new comment packet (GnuPG specific). */ - PKT_GPG_CONTROL = 63 /* internal control packet (GnuPG specific). */ + PKT_GPG_CONTROL = 63, /* internal control packet (GnuPG specific). */ } pkttype_t; diff --git a/g10/import.c b/g10/import.c --- a/g10/import.c +++ b/g10/import.c @@ -1042,22 +1042,8 @@ switch (pkt->pkttype) { case PKT_COMPRESSED: - if (check_compress_algo (pkt->pkt.compressed->algorithm)) - { - rc = GPG_ERR_COMPR_ALGO; - goto ready; - } - else - { - compress_filter_context_t *cfx = xmalloc_clear( sizeof *cfx ); - pkt->pkt.compressed->buf = NULL; - if (push_compress_filter2 (a, cfx, - pkt->pkt.compressed->algorithm, 1)) - xfree (cfx); /* e.g. in case of compression_algo NONE. */ - } - free_packet (pkt, &parsectx); - init_packet(pkt); - break; + rc = GPG_ERR_UNEXPECTED; + goto ready; case PKT_RING_TRUST: /* Skip those packets unless we are in restore mode. */ diff --git a/g10/mainproc.c b/g10/mainproc.c --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -152,6 +152,7 @@ { kbnode_t node; + log_assert(!(c->sigs_only && c->signed_data.used)); if (c->list) /* Add another packet. */ add_kbnode (c->list, new_kbnode (pkt)); else /* Insert the first one. */ @@ -553,6 +554,7 @@ int early_plaintext = literals_seen; unsigned int compliance_de_vs = 0; + log_assert(!c->sigs_only || opt.list_packets); if (pkt->pkttype == PKT_ENCRYPTED_AEAD) c->seen_pkt_encrypted_aead = 1; if (pkt->pkttype == PKT_ENCRYPTED_MDC) @@ -898,6 +900,7 @@ /* This is a literal data packet. Bump a counter for later checks. */ literals_seen++; + log_assert(!(c->sigs_only && c->signed_data.used)); if (pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8)) log_info (_("Note: sender requested \"for-your-eyes-only\"\n")); else if (opt.verbose) @@ -1077,7 +1080,10 @@ /*printf("zip: compressed data packet\n");*/ if (c->sigs_only) - rc = handle_compressed (c->ctrl, c, zd, proc_compressed_cb, c); + { + log_assert(!c->signed_data.used); + 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 @@ -1596,6 +1602,7 @@ c->iobuf = a; init_packet(pkt); init_parse_packet (&parsectx, a); + parsectx.sigs_only = c->sigs_only && c->signed_data.used; while ((rc=parse_packet (&parsectx, pkt)) != -1) { any_data = 1; @@ -1607,6 +1614,12 @@ if (gpg_err_code (rc) == GPG_ERR_INV_PACKET && opt.list_packets == 0) break; + + if (gpg_err_code (rc) == GPG_ERR_UNEXPECTED) + { + write_status_text( STATUS_UNEXPECTED, "0" ); + goto leave; + } continue; } newpkt = -1; @@ -1635,6 +1648,7 @@ case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: case PKT_ENCRYPTED_AEAD: + log_assert(!c->signed_data.used); write_status_text( STATUS_UNEXPECTED, "0" ); rc = GPG_ERR_UNEXPECTED; goto leave; @@ -1644,7 +1658,9 @@ 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; + default: + log_assert(!c->signed_data.used); + newpkt = 0; break; } } else if (c->encrypt_only) diff --git a/g10/packet.h b/g10/packet.h --- a/g10/packet.h +++ b/g10/packet.h @@ -657,6 +657,7 @@ int free_last_pkt; /* Indicates that LAST_PKT must be freed. */ int skip_meta; /* Skip ring trust packets. */ unsigned int n_parsed_packets; /* Number of parsed packets. */ + int sigs_only; /* Only accept detached signature packets */ }; typedef struct parse_packet_ctx_s *parse_packet_ctx_t; @@ -667,6 +668,7 @@ (a)->free_last_pkt = 0; \ (a)->skip_meta = 0; \ (a)->n_parsed_packets = 0; \ + (a)->sigs_only = 0; \ } while (0) #define deinit_parse_packet(a) do { \ diff --git a/g10/parse-packet.c b/g10/parse-packet.c --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -738,6 +738,18 @@ case PKT_ENCRYPTED_MDC: case PKT_ENCRYPTED_AEAD: case PKT_COMPRESSED: + if (ctx->sigs_only) + { + log_error (_("not a detached signature\n")); + rc = gpg_error (GPG_ERR_UNEXPECTED); + goto leave; + } + if (onlykeypkts) + { + log_error (_("partial length packet in keyring\n")); + rc = gpg_error (GPG_ERR_UNEXPECTED); + goto leave; + } iobuf_set_partial_body_length_mode (inp, c & 0xff); pktlen = 0; /* To indicate partial length. */ partial = 1; @@ -775,6 +787,18 @@ rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } + else if (ctx->sigs_only) + { + log_error (_("not a detached signature\n")); + rc = gpg_error (GPG_ERR_UNEXPECTED); + goto leave; + } + else if (onlykeypkts) + { + log_error (_("indeterminate length packet in keyring\n")); + rc = gpg_error (GPG_ERR_UNEXPECTED); + goto leave; + } } else { @@ -828,7 +852,19 @@ goto leave; } - if (with_uid && pkttype == PKT_USER_ID) + if (ctx->sigs_only) + switch (pkttype) + { + case PKT_SIGNATURE: + case PKT_MARKER: + break; + default: + iobuf_skip_rest (inp, pktlen, partial); + *skip = 1; + rc = GPG_ERR_UNEXPECTED; + goto leave; + } + else if (with_uid && pkttype == PKT_USER_ID) /* If ONLYKEYPKTS is set to 2, then we never skip user id packets, even if DO_SKIP is set. */ ;