commit 2e349bb6173789e0e9e42c32873d89c7bc36cea4
Author: Werner Koch <wk@gnupg.org>
Date:   Mon Jul 1 15:14:59 2019 +0200

    gpg: New import and keyserver option "self-sigs-only"
    
    * g10/options.h (IMPORT_SELF_SIGS_ONLY): New.
    * g10/import.c (parse_import_options): Add option "self-sigs-only".
    (read_block): Handle that option.
    --
    
    This option is intended to help against importing keys with many bogus
    key-signatures.  It has obvious drawbacks and is not a bullet-proof
    solution because a self-signature can also be faked and would be
    detected only later.
    
    GnuPG-bug-id: 4591
    Signed-off-by: Werner Koch <wk@gnupg.org>

Index: gnupg-2.2.5/doc/gpg.texi
===================================================================
--- gnupg-2.2.5.orig/doc/gpg.texi
+++ gnupg-2.2.5/doc/gpg.texi
@@ -2350,6 +2350,14 @@ opposite meaning. The options are:
   on the keyring. This option is the same as running the @option{--edit-key}
   command "clean" after import. Defaults to no.
 
+  @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
   signatures.  Defaults to yes.
Index: gnupg-2.2.5/g10/import.c
===================================================================
--- gnupg-2.2.5.orig/g10/import.c
+++ gnupg-2.2.5/g10/import.c
@@ -180,6 +180,9 @@ parse_import_options(char *str,unsigned
       {"import-minimal",IMPORT_MINIMAL|IMPORT_CLEAN,NULL,
        N_("remove as much as possible from key after import")},
 
+      {"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")},
 
@@ -779,6 +782,8 @@ read_block( IOBUF a, int with_meta,
   PACKET *pkt;
   kbnode_t root = NULL;
   int in_cert, in_v3key;
+  u32 keyid[2];
+  unsigned int dropped_nonselfsigs = 0;
 
   *r_v3keys = 0;
 
@@ -870,15 +875,43 @@ read_block( IOBUF a, int with_meta,
 	    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 */
+	    in_cert = 1;
+	    keyid_from_pk (pkt->pkt.public_key, keyid);
+	    goto x_default;
+
 	  default:
           x_default:
 	    if (in_cert && valid_keyblock_packet (pkt->pkttype))
@@ -905,6 +938,10 @@ read_block( IOBUF a, int with_meta,
   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;
 }
 
Index: gnupg-2.2.5/g10/options.h
===================================================================
--- gnupg-2.2.5.orig/g10/options.h
+++ gnupg-2.2.5/g10/options.h
@@ -355,6 +355,7 @@ EXTERN_UNLESS_MAIN_MODULE int memory_sta
 #define IMPORT_RESTORE                   (1<<10)
 #define IMPORT_REPAIR_KEYS               (1<<11)
 #define IMPORT_DRY_RUN                   (1<<12)
+#define IMPORT_SELF_SIGS_ONLY            (1<<14)
 
 #define EXPORT_LOCAL_SIGS                (1<<0)
 #define EXPORT_ATTRIBUTES                (1<<1)
