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. */ @@ -1077,7 +1078,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 +1600,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 +1612,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; @@ -1644,7 +1655,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,20 @@ case PKT_ENCRYPTED_MDC: case PKT_ENCRYPTED_AEAD: case PKT_COMPRESSED: + if (ctx->sigs_only) + { + log_error (_("partial length packet of type %d in detached" + " signature\n"), pkttype); + rc = gpg_error (GPG_ERR_UNEXPECTED); + goto leave; + } + if (onlykeypkts) + { + log_error (_("partial length packet of type %d in keyring\n"), + pkttype); + 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 +789,20 @@ rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } + else if (ctx->sigs_only) + { + log_error (_("indeterminate length packet of type %d in detached" + " signature\n"), pkttype); + rc = gpg_error (GPG_ERR_UNEXPECTED); + goto leave; + } + else if (onlykeypkts) + { + log_error (_("indeterminate length packet of type %d in" + " keyring\n"), pkttype); + rc = gpg_error (GPG_ERR_UNEXPECTED); + goto leave; + } } else { @@ -828,7 +856,21 @@ goto leave; } - if (with_uid && pkttype == PKT_USER_ID) + if (ctx->sigs_only) + switch (pkttype) + { + case PKT_SIGNATURE: + case PKT_MARKER: + break; + default: + log_error(_("Packet type %d not allowed in detached signature\n"), + pkttype); + 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. */ ;