diff --git a/doc/gpg.texi b/doc/gpg.texi index c9262c66a..4c383f495 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -2341,6 +2341,14 @@ opposite meaning. The options are: can be used to update only the subkeys or other non-user id related information. + @item self-sigs-only + Accept only self-signatures while importing a key. All other + key-signatures are skipped at an early import stage. This option + can be used with @code{keyserver-options} to mitigate attempts to + flood a key with bogus signatures from a keyserver. The drawback is + that all other valid key-signatures, as required by the Web of Trust + are also not imported. + @item repair-keys After import, fix various problems with the keys. For example, this reorders signatures, and strips duplicate diff --git a/g10/import.c b/g10/import.c index de45755a4..583c8e66f 100644 --- a/g10/import.c +++ b/g10/import.c @@ -190,7 +190,10 @@ parse_import_options(char *str,unsigned int *options,int noisy) N_("remove as much as possible from key after import")}, {"import-drop-uids", IMPORT_DROP_UIDS, NULL, - N_("Do not import user id or attribute packets")}, + N_("do not import user id or attribute packets")}, + + {"self-sigs-only", IMPORT_SELF_SIGS_ONLY, NULL, + N_("ignore key-signatures which are not self-signatures")}, {"import-export", IMPORT_EXPORT, NULL, N_("run import filters and export key immediately")}, @@ -861,6 +864,8 @@ read_block( IOBUF a, unsigned int options, PACKET *pkt; kbnode_t root = NULL; int in_cert, in_v3key, skip_sigs; + u32 keyid[2]; + unsigned int dropped_nonselfsigs = 0; *r_v3keys = 0; @@ -983,16 +988,43 @@ read_block( IOBUF a, unsigned int options, init_packet(pkt); break; + case PKT_SIGNATURE: + if (!in_cert) + goto x_default; + if (!(options & IMPORT_SELF_SIGS_ONLY)) + goto x_default; + if (pkt->pkt.signature->keyid[0] == keyid[0] + && pkt->pkt.signature->keyid[1] == keyid[1]) + { /* This is likely a self-signature. We import this one. + * Eventually we should use the ISSUER_FPR to compare + * self-signatures, but that will work only for v5 keys + * which are currently not even deployed. + * Note that we do not do any crypto verify here because + * that would defeat this very mitigation of DoS by + * importing a key with a huge amount of faked + * key-signatures. A verification will be done later in + * the processing anyway. Here we want a cheap an early + * way to drop non-self-signatures. */ + goto x_default; + } + /* Skip this signature. */ + dropped_nonselfsigs++; + free_packet (pkt, &parsectx); + init_packet(pkt); + break; + case PKT_PUBLIC_KEY: case PKT_SECRET_KEY: - if (in_cert ) /* Store this packet. */ + if (in_cert) /* Store this packet. */ { *pending_pkt = pkt; pkt = NULL; goto ready; } in_cert = 1; - /* fall through */ + keyid_from_pk (pkt->pkt.public_key, keyid); + goto x_default; + default: x_default: if (in_cert && valid_keyblock_packet (pkt->pkttype)) @@ -1021,6 +1053,10 @@ read_block( IOBUF a, unsigned int options, free_packet (pkt, &parsectx); deinit_parse_packet (&parsectx); xfree( pkt ); + if (!rc && dropped_nonselfsigs && opt.verbose) + log_info ("key %s: number of dropped non-self-signatures: %u\n", + keystr (keyid), dropped_nonselfsigs); + return rc; } diff --git a/g10/options.h b/g10/options.h index b26cea0db..234929b15 100644 --- a/g10/options.h +++ b/g10/options.h @@ -363,6 +363,7 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode; #define IMPORT_REPAIR_KEYS (1<<11) #define IMPORT_DRY_RUN (1<<12) #define IMPORT_DROP_UIDS (1<<13) +#define IMPORT_SELF_SIGS_ONLY (1<<14) #define EXPORT_LOCAL_SIGS (1<<0) #define EXPORT_ATTRIBUTES (1<<1)