gpg: Protect against rogue keyservers sending secret keys.
authorWerner Koch <wk@gnupg.org>
Fri, 4 Oct 2013 11:44:39 +0000 (13:44 +0200)
committerWerner Koch <wk@gnupg.org>
Fri, 4 Oct 2013 11:44:39 +0000 (13:44 +0200)
* g10/options.h (IMPORT_NO_SECKEY): New.
* g10/keyserver.c (keyserver_spawn, keyserver_import_cert): Set new
flag.
* g10/import.c (import_secret_one): Deny import if flag is set.
--

By modifying a keyserver or a DNS record to send a secret key, an
attacker could trick a user into signing using a different key and
user id.  The trust model should protect against such rogue keys but
we better make sure that secret keys are never received from remote
sources.

Suggested-by: Stefan Tomanek
Signed-off-by: Werner Koch <wk@gnupg.org>
g10/import.c
g10/keyserver.c
g10/options.h

index ad112d6..540b24b 100644 (file)
@@ -1195,6 +1195,12 @@ import_secret_one( const char *fname, KBNODE keyblock,
       }
     stats->secret_read++;
 
+    if ((options & IMPORT_NO_SECKEY))
+      {
+        log_error (_("importing secret keys not allowed\n"));
+        return 0;
+      }
+
     if( !uidnode )
       {
        log_error( _("key %s: no user ID\n"), keystr_from_sk(sk));
index f90467c..291a79c 100644 (file)
@@ -1498,10 +1498,14 @@ keyserver_spawn(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
             It's harmless to ignore them, but ignoring them does make
             gpg complain about "no valid OpenPGP data found".  One
             way to do this could be to continue parsing this
-            line-by-line and make a temp iobuf for each key. */
+            line-by-line and make a temp iobuf for each key.  Note
+            that we don't allow the import of secret keys from a
+            keyserver.  Keyservers should never accept or send them
+            but we better protect against rogue keyservers. */
 
-         import_keys_stream(spawn->fromchild,stats_handle,fpr,fpr_len,
-                            opt.keyserver_options.import_options);
+         import_keys_stream (spawn->fromchild, stats_handle, fpr, fpr_len,
+                              (opt.keyserver_options.import_options
+                               | IMPORT_NO_SECKEY));
 
          import_print_stats(stats_handle);
          import_release_stats_handle(stats_handle);
@@ -2039,8 +2043,9 @@ keyserver_import_cert(const char *name,unsigned char **fpr,size_t *fpr_len)
       /* CERTs are always in binary format */
       opt.no_armor=1;
 
-      rc=import_keys_stream(key,NULL,fpr,fpr_len,
-                           opt.keyserver_options.import_options);
+      rc=import_keys_stream (key, NULL, fpr, fpr_len,
+                             (opt.keyserver_options.import_options
+                              | IMPORT_NO_SECKEY));
 
       opt.no_armor=armor_status;
 
index 46f746d..f2866f1 100644 (file)
@@ -31,7 +31,7 @@
 #if defined (__riscos__) && !defined (INCLUDED_BY_MAIN_MODULE)
 #define EXTERN_UNLESS_MAIN_MODULE extern
 #else
-#define EXTERN_UNLESS_MAIN_MODULE 
+#define EXTERN_UNLESS_MAIN_MODULE
 #endif
 #endif
 
@@ -85,7 +85,7 @@ struct
   int completes_needed;
   int max_cert_depth;
   const char *homedir;
-  const char *agent_program; 
+  const char *agent_program;
 
   /* Options to be passed to the gpg-agent */
   session_env_t session_env;
@@ -207,7 +207,7 @@ struct
 
   /* If > 0, limit the number of card insertion prompts to this
      value. */
-  int limit_card_insert_tries; 
+  int limit_card_insert_tries;
 
 #ifdef ENABLE_CARD_SUPPORT
   /* FIXME: We don't needs this here as it is done in scdaemon. */
@@ -236,8 +236,8 @@ struct
     enum {
       AKL_NODEFAULT,
       AKL_LOCAL,
-      AKL_CERT, 
-      AKL_PKA, 
+      AKL_CERT,
+      AKL_PKA,
       AKL_LDAP,
       AKL_KEYSERVER,
       AKL_SPEC
@@ -317,6 +317,7 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
 #define IMPORT_MERGE_ONLY                (1<<4)
 #define IMPORT_MINIMAL                   (1<<5)
 #define IMPORT_CLEAN                     (1<<6)
+#define IMPORT_NO_SECKEY                 (1<<7)
 
 #define EXPORT_LOCAL_SIGS                (1<<0)
 #define EXPORT_ATTRIBUTES                (1<<1)