[git] GnuPG - branch, master, updated. gnupg-2.1.13-120-ga479804

by Werner Koch cvs at cvs.gnupg.org
Wed Jul 6 15:39:41 CEST 2016


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  a479804c86bc24bfab101f39464db3ecfbaedf6d (commit)
       via  073be51a866cb5600479c504a44ae5ac94a449a2 (commit)
      from  fdfde91595109e51a5b8fafd292244ad41dfb83d (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a479804c86bc24bfab101f39464db3ecfbaedf6d
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Jul 6 14:03:50 2016 +0200

    gpg: New options --recipient-file and --hidden-recipient-file.
    
    * g10/gpg.c (oRecipientFile, oHiddenRecipientFile): New.
    (opts): Add options --recipient-file and --hidden-recipient-file.
    (main): Implement them.  Also remove duplicate code from similar
    options.
    * g10/keydb.h (PK_LIST_FROM_FILE): New.
    (PK_LIST_SHIFT): Bump up.
    * g10/pkclist.c (expand_group): Take care of PK_LIST_FROM_FILE.
    (find_and_check_key): Add and implement arg FROM_FILE.
    (build_pk_list): Pass new value for new arg.
    * g10/getkey.c (get_pubkey_fromfile): New.
    * g10/gpgv.c (read_key_from_file): New stub.
    * g10/test-stubs.c (read_key_from_file): New stub.
    * g10/server.c (cmd_recipient): Add flag --file.
    * g10/import.c (read_key_from_file): New.
    
    * tests/openpgp/defs.scm (key-file1): New.
    (key-file2): New.
    * tests/openpgp/setup.scm: Add their private keys and import the
    key-file1.
    * tests/openpgp/encrypt.scm: Add new test.
    
    --
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/doc/gpg.texi b/doc/gpg.texi
index 9a60890..11d3a65 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -2037,6 +2037,22 @@ limited countermeasure against traffic analysis. If this option or
 @option{--recipient} is not specified, GnuPG asks for the user ID unless
 @option{--default-recipient} is given.
 
+ at item --recipient-file @var{file}
+ at itemx -f
+ at opindex recipient-file
+This option is similar to @option{--recipient} except that it
+encrypts to a key stored in the given file.  @var{file} must be the
+name of a file containing exactly one key.  @command{gpg} assumes that
+the key in this file is fully valid.
+
+ at item --hidden-recipient-file @var{file}
+ at itemx -F
+ at opindex hidden-recipient-file
+This option is similar to @option{--hidden-recipient} except that it
+encrypts to a key stored in the given file.  @var{file} must be the
+name of a file containing exactly one key.  @command{gpg} assumes that
+the key in this file is fully valid.
+
 @item --encrypt-to @code{name}
 @opindex encrypt-to
 Same as @option{--recipient} but this one is intended for use in the
@@ -2055,11 +2071,6 @@ recipients given either by use of @option{--recipient} or by the asked user id.
 No trust checking is performed for these user ids and even disabled
 keys can be used.
 
- at item --encrypt-to-default-key
- at opindex encrypt-to-default-key
-If the default secret key is taken from @option{--default-key}, then
-also encrypt to that key.
-
 @item --no-encrypt-to
 @opindex no-encrypt-to
 Disable the use of all @option{--encrypt-to} and
diff --git a/g10/getkey.c b/g10/getkey.c
index f34127d..90fd175 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -1,7 +1,7 @@
 /* getkey.c -  Get a key from the database
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
  *               2007, 2008, 2010  Free Software Foundation, Inc.
- * Copyright (C) 2015 g10 Code GmbH
+ * Copyright (C) 2015, 2016 g10 Code GmbH
  *
  * This file is part of GnuPG.
  *
@@ -143,6 +143,11 @@ static void merge_selfsigs (kbnode_t keyblock);
 static int lookup (getkey_ctx_t ctx,
 		   kbnode_t *ret_keyblock, kbnode_t *ret_found_key,
 		   int want_secret);
+static kbnode_t finish_lookup (kbnode_t keyblock,
+                               unsigned int req_usage, int want_exact,
+                               unsigned int *r_flags);
+static void print_status_key_considered (kbnode_t keyblock, unsigned int flags);
+
 
 #if 0
 static void
@@ -1454,6 +1459,53 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
 }
 
 
+/* Get a public key from a file.
+ *
+ * PK is the buffer to store the key.  The caller needs to make sure
+ * that PK->REQ_USAGE is valid.  PK->REQ_USAGE is passed through to
+ * the lookup function and is a mask of PUBKEY_USAGE_SIG,
+ * PUBKEY_USAGE_ENC and PUBKEY_USAGE_CERT.  If this is non-zero, only
+ * keys with the specified usage will be returned.
+ *
+ * FNAME is the file name.  That file should contain exactly one
+ * keyblock.
+ *
+ * This function returns 0 on success.  Otherwise, an error code is
+ * returned.  In particular, GPG_ERR_NO_PUBKEY is returned if the key
+ * is not found.
+ *
+ * The self-signed data has already been merged into the public key
+ * using merge_selfsigs.  The caller must release the content of PK by
+ * calling release_public_key_parts (or, if PK was malloced, using
+ * free_public_key).
+ */
+gpg_error_t
+get_pubkey_fromfile (ctrl_t ctrl, PKT_public_key *pk, const char *fname)
+{
+  gpg_error_t err;
+  kbnode_t keyblock;
+  kbnode_t found_key;
+  unsigned int infoflags;
+
+  err = read_key_from_file (ctrl, fname, &keyblock);
+  if (!err)
+    {
+      /* Warning: node flag bits 0 and 1 should be preserved by
+       * merge_selfsigs.  FIXME: Check whether this still holds. */
+      merge_selfsigs (keyblock);
+      found_key = finish_lookup (keyblock, pk->req_usage, 0, &infoflags);
+      print_status_key_considered (keyblock, infoflags);
+      if (found_key)
+        pk_from_block (pk, keyblock, found_key);
+      else
+        err = gpg_error (GPG_ERR_UNUSABLE_PUBKEY);
+    }
+
+  release_kbnode (keyblock);
+  return err;
+}
+
+
 /* Lookup a key with the specified fingerprint.
  *
  * If PK is not NULL, the public key of the first result is returned
diff --git a/g10/gpg.c b/g10/gpg.c
index cf0e645..34009bb 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -81,6 +81,8 @@ enum cmd_and_opt_values
     aSym	  = 'c',
     aDecrypt	  = 'd',
     aEncr	  = 'e',
+    oRecipientFile       = 'f',
+    oHiddenRecipientFile = 'F',
     oInteractive  = 'i',
     aListKeys	  = 'k',
     oDryRun	  = 'n',
@@ -506,6 +508,8 @@ static ARGPARSE_OPTS opts[] = {
 
   ARGPARSE_s_s (oRecipient, "recipient", N_("|USER-ID|encrypt for USER-ID")),
   ARGPARSE_s_s (oHiddenRecipient, "hidden-recipient", "@"),
+  ARGPARSE_s_s (oRecipientFile, "recipient-file", "@"),
+  ARGPARSE_s_s (oHiddenRecipientFile, "hidden-recipient-file", "@"),
   ARGPARSE_s_s (oRecipient, "remote-user", "@"),  /* (old option name) */
   ARGPARSE_s_s (oDefRecipient, "default-recipient", "@"),
   ARGPARSE_s_n (oDefRecipientSelf,  "default-recipient-self", "@"),
@@ -2838,37 +2842,45 @@ main (int argc, char **argv)
             else
               opt.s2k_count = 0;  /* Auto-calibrate when needed.  */
 	    break;
-	  case oNoEncryptTo: opt.no_encrypt_to = 1; break;
-	  case oEncryptTo: /* store the recipient in the second list */
+
+	  case oRecipient:
+	  case oHiddenRecipient:
+	  case oRecipientFile:
+	  case oHiddenRecipientFile:
+            /* Store the recipient.  Note that we also store the
+             * option as private data in the flags.  This is achieved
+             * by shifting the option value to the left so to keep
+             * enough space for the flags.  */
 	    sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
-	    sl->flags = ((pargs.r_opt << PK_LIST_SHIFT) | PK_LIST_ENCRYPT_TO);
+	    sl->flags = (pargs.r_opt << PK_LIST_SHIFT);
             if (configfp)
               sl->flags |= PK_LIST_CONFIG;
+            if (pargs.r_opt == oHiddenRecipient
+                || pargs.r_opt == oHiddenRecipientFile)
+              sl->flags |= PK_LIST_HIDDEN;
+            if (pargs.r_opt == oRecipientFile
+                || pargs.r_opt == oHiddenRecipientFile)
+              sl->flags |= PK_LIST_FROM_FILE;
+            any_explicit_recipient = 1;
 	    break;
-	  case oHiddenEncryptTo: /* store the recipient in the second list */
+
+	  case oEncryptTo:
+	  case oHiddenEncryptTo:
+            /* Store an additional recipient.  */
 	    sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
-	    sl->flags = ((pargs.r_opt << PK_LIST_SHIFT)
-                         | PK_LIST_ENCRYPT_TO|PK_LIST_HIDDEN);
+	    sl->flags = ((pargs.r_opt << PK_LIST_SHIFT) | PK_LIST_ENCRYPT_TO);
             if (configfp)
               sl->flags |= PK_LIST_CONFIG;
+            if (pargs.r_opt == oHiddenEncryptTo)
+              sl->flags |= PK_LIST_HIDDEN;
 	    break;
+
+	  case oNoEncryptTo:
+            opt.no_encrypt_to = 1;
+            break;
           case oEncryptToDefaultKey:
             opt.encrypt_to_default_key = configfp ? 2 : 1;
             break;
-	  case oRecipient: /* store the recipient */
-	    sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
-	    sl->flags = (pargs.r_opt << PK_LIST_SHIFT);
-            if (configfp)
-              sl->flags |= PK_LIST_CONFIG;
-            any_explicit_recipient = 1;
-	    break;
-	  case oHiddenRecipient: /* store the recipient with a flag */
-	    sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
-	    sl->flags = ((pargs.r_opt << PK_LIST_SHIFT) | PK_LIST_HIDDEN);
-            if (configfp)
-              sl->flags |= PK_LIST_CONFIG;
-            any_explicit_recipient = 1;
-	    break;
 
 	  case oTrySecretKey:
 	    add_to_strlist2 (&opt.secret_keys_to_try,
diff --git a/g10/gpgv.c b/g10/gpgv.c
index 9ccc0da..d238ee0 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -416,6 +416,17 @@ keyserver_import_ldap (const char *name)
   return -1;
 }
 
+
+gpg_error_t
+read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
+{
+  (void)ctrl;
+  (void)fname;
+  (void)r_keyblock;
+  return -1;
+}
+
+
 /* Stub:
  * No encryption here but mainproc links to these functions.
  */
diff --git a/g10/import.c b/g10/import.c
index 8cfd6ea..e035328 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -220,6 +220,113 @@ import_release_stats_handle (import_stats_t p)
 }
 
 
+/* Read a key from a file.  Only the first key in the file is
+ * considered and stored at R_KEYBLOCK.  FNAME is the name of the
+ * file.
+ */
+gpg_error_t
+read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
+{
+  gpg_error_t err;
+  iobuf_t inp;
+  PACKET *pending_pkt = NULL;
+  kbnode_t keyblock = NULL;
+  u32 keyid[2];
+  int v3keys;   /* Dummy */
+  int non_self; /* Dummy */
+
+  (void)ctrl;
+
+  *r_keyblock = NULL;
+
+  inp = iobuf_open (fname);
+  if (!inp)
+    err = gpg_error_from_syserror ();
+  else if (is_secured_file (iobuf_get_fd (inp)))
+    {
+      iobuf_close (inp);
+      inp = NULL;
+      err = gpg_error (GPG_ERR_EPERM);
+    }
+  else
+    err = 0;
+  if (err)
+    {
+      log_error (_("can't open '%s': %s\n"),
+                 iobuf_is_pipe_filename (fname)? "[stdin]": fname,
+                 gpg_strerror (err));
+      if (gpg_err_code (err) == GPG_ERR_ENOENT)
+        err = gpg_error (GPG_ERR_NO_PUBKEY);
+      goto leave;
+    }
+
+  /* Push the armor filter.  */
+  {
+    armor_filter_context_t *afx;
+    afx = new_armor_context ();
+    afx->only_keyblocks = 1;
+    push_armor_filter (afx, inp);
+    release_armor_context (afx);
+  }
+
+  /* Read the first non-v3 keyblock.  */
+  while (!(err = read_block (inp, &pending_pkt, &keyblock, &v3keys)))
+    {
+      if (keyblock->pkt->pkttype == PKT_PUBLIC_KEY)
+        break;
+      log_info (_("skipping block of type %d\n"), keyblock->pkt->pkttype);
+      release_kbnode (keyblock);
+      keyblock = NULL;
+    }
+  if (err)
+    {
+      if (gpg_err_code (err) != GPG_ERR_INV_KEYRING)
+        log_error (_("error reading '%s': %s\n"),
+                   iobuf_is_pipe_filename (fname)? "[stdin]": fname,
+                   gpg_strerror (err));
+      goto leave;
+    }
+
+  keyid_from_pk (keyblock->pkt->pkt.public_key, keyid);
+
+  if (!find_next_kbnode (keyblock, PKT_USER_ID))
+    {
+      err = gpg_error (GPG_ERR_NO_USER_ID);
+      goto leave;
+    }
+
+  collapse_uids (&keyblock);
+
+  clear_kbnode_flags (keyblock);
+  if (chk_self_sigs (keyblock, keyid, &non_self))
+    {
+      err = gpg_error (GPG_ERR_INV_KEYRING);
+      goto leave;
+    }
+
+  if (!delete_inv_parts (keyblock, keyid, 0) )
+    {
+      err = gpg_error (GPG_ERR_NO_USER_ID);
+      goto leave;
+    }
+
+  *r_keyblock = keyblock;
+  keyblock = NULL;
+
+ leave:
+  if (inp)
+    {
+      iobuf_close (inp);
+      /* Must invalidate that ugly cache to actually close the file. */
+      iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname);
+    }
+  release_kbnode (keyblock);
+  /* FIXME: Do we need to free PENDING_PKT ? */
+  return err;
+}
+
+
+
 /*
  * Import the public keys from the given filename. Input may be armored.
  * This function rejects all keys which are not validly self signed on at
diff --git a/g10/keydb.h b/g10/keydb.h
index a30cf7a..4e8f3f2 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -70,15 +70,16 @@ enum resource_type {
 /* Bit flags used with build_pk_list.  */
 enum
   {
-    PK_LIST_ENCRYPT_TO=1,   /* This is an encrypt-to recipient.  */
-    PK_LIST_HIDDEN=2,       /* This is a hidden recipient.       */
-    PK_LIST_CONFIG=4        /* Specified via config file.        */
+    PK_LIST_ENCRYPT_TO = 1, /* This is an encrypt-to recipient.    */
+    PK_LIST_HIDDEN     = 2, /* This is a hidden recipient.         */
+    PK_LIST_CONFIG     = 4, /* Specified via config file.          */
+    PK_LIST_FROM_FILE  = 8  /* Take key from file with that name.  */
   };
-/* To store private data in the flags they must be left shifted by
-   this value.  */
+/* To store private data in the flags the private data must be left
+   shifted by this value.  */
 enum
   {
-    PK_LIST_SHIFT=3
+    PK_LIST_SHIFT = 4
   };
 
 /****************
@@ -104,7 +105,7 @@ struct pk_list
 {
   PK_LIST next;
   PKT_public_key *pk;
-  int flags; /* flag bit 1==throw_keyid */
+  int flags;           /* See PK_LIST_ constants. */
 };
 
 /* Structure to hold a list of secret key certificates.  */
@@ -228,7 +229,8 @@ void release_pk_list (PK_LIST pk_list);
 int  build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list);
 gpg_error_t find_and_check_key (ctrl_t ctrl,
                                 const char *name, unsigned int use,
-                                int mark_hidden, pk_list_t *pk_list_addr);
+                                int mark_hidden, int from_file,
+                                pk_list_t *pk_list_addr);
 
 int  algo_available( preftype_t preftype, int algo,
 		     const union pref_hint *hint );
@@ -322,6 +324,10 @@ int get_pubkey_byname (ctrl_t ctrl,
                        KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd,
 		       int include_unusable, int no_akl );
 
+/* Get a public key directly from file FNAME.  */
+gpg_error_t get_pubkey_fromfile (ctrl_t ctrl,
+                                 PKT_public_key *pk, const char *fname);
+
 /* Return the public key with the key id KEYID iff the secret key is
  * available and store it at PK.  */
 gpg_error_t get_seckey (PKT_public_key *pk, u32 *keyid);
diff --git a/g10/main.h b/g10/main.h
index 3ee2762..ec20b28 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -350,6 +350,8 @@ typedef gpg_error_t (*import_screener_t)(kbnode_t keyblock, void *arg);
 
 int parse_import_options(char *str,unsigned int *options,int noisy);
 gpg_error_t parse_and_set_import_filter (const char *string);
+gpg_error_t read_key_from_file (ctrl_t ctrl, const char *fname,
+                                kbnode_t *r_keyblock);
 void import_keys (ctrl_t ctrl, char **fnames, int nnames,
 		  import_stats_t stats_hd, unsigned int options);
 int import_keys_stream (ctrl_t ctrl, iobuf_t inp, import_stats_t stats_hd,
diff --git a/g10/pkclist.c b/g10/pkclist.c
index 8efa954..6315a6d 100644
--- a/g10/pkclist.c
+++ b/g10/pkclist.c
@@ -775,14 +775,16 @@ expand_id(const char *id,strlist_t *into,unsigned int flags)
 }
 
 /* For simplicity, and to avoid potential loops, we only expand once -
-   you can't make an alias that points to an alias. */
+ * you can't make an alias that points to an alias.  */
 static strlist_t
-expand_group(strlist_t input)
+expand_group (strlist_t input)
 {
-  strlist_t sl,output=NULL,rover;
+  strlist_t output = NULL;
+  strlist_t sl, rover;
 
-  for(rover=input;rover;rover=rover->next)
-    if(expand_id(rover->d,&output,rover->flags)==0)
+  for (rover = input; rover; rover = rover->next)
+    if (!(rover->flags & PK_LIST_FROM_FILE)
+        && !expand_id(rover->d,&output,rover->flags))
       {
 	/* Didn't find any groups, so use the existing string */
 	sl=add_to_strlist(&output,rover->d);
@@ -794,17 +796,18 @@ expand_group(strlist_t input)
 
 
 /* Helper for build_pk_list to find and check one key.  This helper is
-   also used directly in server mode by the RECIPIENTS command.  On
-   success the new key is added to PK_LIST_ADDR.  NAME is the user id
-   of the key. USE the requested usage and a set MARK_HIDDEN will mark
-   the key in the updated list as a hidden recipient. */
+ * also used directly in server mode by the RECIPIENTS command.  On
+ * success the new key is added to PK_LIST_ADDR.  NAME is the user id
+ * of the key.  USE the requested usage and a set MARK_HIDDEN will
+ * mark the key in the updated list as a hidden recipient.  If
+ * FROM_FILE is true, NAME is is not a user ID but the name of a file
+ * holding a key. */
 gpg_error_t
 find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
-                    int mark_hidden, pk_list_t *pk_list_addr)
+                    int mark_hidden, int from_file, pk_list_t *pk_list_addr)
 {
   int rc;
   PKT_public_key *pk;
-  int trustlevel;
 
   if (!name || !*name)
     return gpg_error (GPG_ERR_INV_USER_ID);
@@ -814,7 +817,10 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
     return gpg_error_from_syserror ();
   pk->req_usage = use;
 
-  rc = get_pubkey_byname (ctrl, NULL, pk, name, NULL, NULL, 0, 0);
+  if (from_file)
+    rc = get_pubkey_fromfile (ctrl, pk, name);
+  else
+    rc = get_pubkey_byname (ctrl, NULL, pk, name, NULL, NULL, 0, 0);
   if (rc)
     {
       int code;
@@ -844,24 +850,28 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
     }
 
   /* Key found and usable.  Check validity. */
-  trustlevel = get_validity (ctrl, pk, pk->user_id, NULL, 1);
-  if ( (trustlevel & TRUST_FLAG_DISABLED) )
+  if (!from_file)
     {
-      /* Key has been disabled. */
-      send_status_inv_recp (13, name);
-      log_info (_("%s: skipped: public key is disabled\n"), name);
-      free_public_key (pk);
-      return GPG_ERR_UNUSABLE_PUBKEY;
-    }
+      int trustlevel;
 
-  if ( !do_we_trust_pre (pk, trustlevel) )
-    {
-      /* We don't trust this key.  */
-      send_status_inv_recp (10, name);
-      free_public_key (pk);
-      return GPG_ERR_UNUSABLE_PUBKEY;
+      trustlevel = get_validity (ctrl, pk, pk->user_id, NULL, 1);
+      if ( (trustlevel & TRUST_FLAG_DISABLED) )
+        {
+          /* Key has been disabled. */
+          send_status_inv_recp (13, name);
+          log_info (_("%s: skipped: public key is disabled\n"), name);
+          free_public_key (pk);
+          return GPG_ERR_UNUSABLE_PUBKEY;
+        }
+
+      if ( !do_we_trust_pre (pk, trustlevel) )
+        {
+          /* We don't trust this key.  */
+          send_status_inv_recp (10, name);
+          free_public_key (pk);
+          return GPG_ERR_UNUSABLE_PUBKEY;
+        }
     }
-  /* Note: do_we_trust may have changed the trustlevel. */
 
   /* Skip the actual key if the key is already present in the
      list.  */
@@ -894,22 +904,24 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
 
 
 /* This is the central function to collect the keys for recipients.
-   It is thus used to prepare a public key encryption. encrypt-to
-   keys, default keys and the keys for the actual recipients are all
-   collected here.  When not in batch mode and no recipient has been
-   passed on the commandline, the function will also ask for
-   recipients.
-
-   RCPTS is a string list with the recipients; NULL is an allowed
-   value but not very useful.  Group expansion is done on these names;
-   they may be in any of the user Id formats we can handle.  The flags
-   bits for each string in the string list are used for:
-     Bit 0 (PK_LIST_ENCRYPT_TO): This is an encrypt-to recipient.
-     Bit 1 (PK_LIST_HIDDEN)    : This is a hidden recipient.
-
-   On success a list of keys is stored at the address RET_PK_LIST; the
-   caller must free this list.  On error the value at this address is
-   not changed.
+ * It is thus used to prepare a public key encryption. encrypt-to
+ * keys, default keys and the keys for the actual recipients are all
+ * collected here.  When not in batch mode and no recipient has been
+ * passed on the commandline, the function will also ask for
+ * recipients.
+ *
+ * RCPTS is a string list with the recipients; NULL is an allowed
+ * value but not very useful.  Group expansion is done on these names;
+ * they may be in any of the user Id formats we can handle.  The flags
+ * bits for each string in the string list are used for:
+ *
+ * - PK_LIST_ENCRYPT_TO :: This is an encrypt-to recipient.
+ * - PK_LIST_HIDDEN     :: This is a hidden recipient.
+ * - PK_LIST_FROM_FILE  :: The argument is a file with a key.
+ *
+ * On success a list of keys is stored at the address RET_PK_LIST; the
+ * caller must free this list.  On error the value at this address is
+ * not changed.
  */
 int
 build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list)
@@ -1269,6 +1281,7 @@ build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list)
 
           rc = find_and_check_key (ctrl, remusr->d, PUBKEY_USAGE_ENC,
                                    !!(remusr->flags&PK_LIST_HIDDEN),
+                                   !!(remusr->flags&PK_LIST_FROM_FILE),
                                    &pk_list);
           if (rc)
             goto fail;
diff --git a/g10/server.c b/g10/server.c
index 771a8a7..258f08a 100644
--- a/g10/server.c
+++ b/g10/server.c
@@ -177,6 +177,7 @@ output_notify (assuan_context_t ctx, char *line)
 
 

 /*  RECIPIENT [--hidden] <userID>
+    RECIPIENT [--hidden] --file <filename>
 
    Set the recipient for the encryption.  <userID> should be the
    internal representation of the key; the server may accept any other
@@ -192,9 +193,10 @@ cmd_recipient (assuan_context_t ctx, char *line)
 {
   ctrl_t ctrl = assuan_get_pointer (ctx);
   gpg_error_t err;
-  int hidden;
+  int hidden, file;
 
   hidden = has_option (line,"--hidden");
+  file = has_option (line,"--file");
   line = skip_options (line);
 
   /* FIXME: Expand groups
@@ -204,7 +206,7 @@ cmd_recipient (assuan_context_t ctx, char *line)
     remusr = rcpts;
   */
 
-  err = find_and_check_key (ctrl, line, PUBKEY_USAGE_ENC, hidden,
+  err = find_and_check_key (ctrl, line, PUBKEY_USAGE_ENC, hidden, file,
                             &ctrl->server_local->recplist);
 
   if (err)
diff --git a/g10/test-stubs.c b/g10/test-stubs.c
index f4d9526..6f50759 100644
--- a/g10/test-stubs.c
+++ b/g10/test-stubs.c
@@ -228,6 +228,15 @@ keyserver_import_ldap (const char *name)
   return -1;
 }
 
+gpg_error_t
+read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
+{
+  (void)ctrl;
+  (void)fname;
+  (void)r_keyblock;
+  return -1;
+}
+
 /* Stub:
  * No encryption here but mainproc links to these functions.
  */
diff --git a/tests/openpgp/defs.scm b/tests/openpgp/defs.scm
index 4257b28..8ceffc8 100644
--- a/tests/openpgp/defs.scm
+++ b/tests/openpgp/defs.scm
@@ -35,6 +35,9 @@
 ;; first and then search for the encryption subkey.)
 (define dsa-usrname2 "0xCB879DE9")
 
+(define key-file1 "samplekeys/rsa-rsa-sample-1.asc")
+(define key-file2 "samplekeys/ed25519-cv25519-sample-1.asc")
+
 (define plain-files '("plain-1" "plain-2" "plain-3"))
 (define data-files '("data-500" "data-9000" "data-32000" "data-80000"))
 (define exp-files '())
diff --git a/tests/openpgp/encrypt.scm b/tests/openpgp/encrypt.scm
index 5a3e178..7452fc5 100755
--- a/tests/openpgp/encrypt.scm
+++ b/tests/openpgp/encrypt.scm
@@ -43,3 +43,18 @@
        (tr:assert-identity source)))
     (append plain-files data-files)))
  all-cipher-algos)
+
+
+;; We encrypt to two keys and we have also put the first key into our
+;; pubring, so that decryption will work.
+(for-each-p
+ "Checking encryption using a key from file"
+ (lambda (source)
+   (tr:do
+    (tr:open source)
+    (tr:gpg "" `(--yes -v --no-keyring --encrypt
+                 --recipient-file ,(in-srcdir key-file1)
+                 --hidden-recipient-file ,(in-srcdir key-file2)))
+    (tr:gpg "" '(--yes))
+    (tr:assert-identity source)))
+ plain-files)
diff --git a/tests/openpgp/setup.scm b/tests/openpgp/setup.scm
index ce2e42c..9ad19c2 100755
--- a/tests/openpgp/setup.scm
+++ b/tests/openpgp/setup.scm
@@ -91,12 +91,17 @@
     "1DF48228FEFF3EC2481B106E0ACA8C465C662CC5"
     "A2832820DC9F40751BDCD375BB0945BA33EC6B4C"
     "ADE710D74409777B7729A7653373D820F67892E0"
-    "CEFC51AF91F68A2904FBFF62C4F075A4785B803F"))
+    "CEFC51AF91F68A2904FBFF62C4F075A4785B803F"
+    "1E28F20E41B54C2D1234D896096495FF57E08D18"
+    "EB33B687EB8581AB64D04852A54453E85F3DF62D"
+    "C6A6390E9388CDBAD71EAEA698233FE5E04F001E"
+    "D69102E0F5AC6B6DB8E4D16DA8E18CF46D88CAE3"))
 
 (info "Importing public demo and test keys")
 (call-check `(, at GPG --yes --import
 		    ,(in-srcdir "pubdemo.asc")
-		    ,(in-srcdir "pubring.asc")))
+		    ,(in-srcdir "pubring.asc")
+                    ,(in-srcdir key-file1)))
 ;; (letfd ((source (open (in-srcdir "pubring.pkr.asc") O_RDONLY)))
 ;;        ((gpg-pipe '(--dearmor) '(--yes --import) STDERR_FILENO)
 ;; 	source CLOSED_FD))

commit 073be51a866cb5600479c504a44ae5ac94a449a2
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Jul 6 15:33:40 2016 +0200

    gpg: New option --no-keyring.
    
    * g10/gpg.c (oNoKeyring): New.
    (opts): Add "--no-keyring".
    (main): Do not register any keyring if the option is used.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/doc/gpg.texi b/doc/gpg.texi
index 7dff333..9a60890 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -1371,6 +1371,10 @@ Note that this adds a keyring to the current list. If the intent is to
 use the specified keyring alone, use @option{--keyring} along with
 @option{--no-default-keyring}.
 
+If the the option @option{--no-keyring} has been used no keyrings will
+be used at all.
+
+
 @item --secret-keyring @code{file}
 @opindex secret-keyring
 This is an obsolete option and ignored.  All secret keys are stored in
@@ -3008,6 +3012,10 @@ and do not provide alternate keyrings via @option{--keyring} or
 @option{--secret-keyring}, then GnuPG will still use the default public or
 secret keyrings.
 
+ at item --no-keyring
+ at opindex no-keyring
+Do not add use any keyrings even if specified as options.
+
 @item --skip-verify
 @opindex skip-verify
 Skip the signature verification step. This may be
diff --git a/g10/gpg.c b/g10/gpg.c
index 154d39a..cf0e645 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -248,6 +248,7 @@ enum cmd_and_opt_values
     oNoMDCWarn,
     oNoArmor,
     oNoDefKeyring,
+    oNoKeyring,
     oNoGreeting,
     oNoTTY,
     oNoOptions,
@@ -681,6 +682,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oNoArmor, "no-armor", "@"),
   ARGPARSE_s_n (oNoArmor, "no-armour", "@"),
   ARGPARSE_s_n (oNoDefKeyring, "no-default-keyring", "@"),
+  ARGPARSE_s_n (oNoKeyring, "no-keyring", "@"),
   ARGPARSE_s_n (oNoGreeting, "no-greeting", "@"),
   ARGPARSE_s_n (oNoOptions, "no-options", "@"),
   ARGPARSE_s_s (oHomedir, "homedir", "@"),
@@ -2609,7 +2611,15 @@ main (int argc, char **argv)
 	    }
 	    break;
 	  case oNoArmor: opt.no_armor=1; opt.armor=0; break;
-	  case oNoDefKeyring: default_keyring = 0; break;
+
+	  case oNoDefKeyring:
+            if (default_keyring > 0)
+              default_keyring = 0;
+            break;
+	  case oNoKeyring:
+            default_keyring = -1;
+            break;
+
 	  case oNoGreeting: nogreeting = 1; break;
 	  case oNoVerbose:
             opt.verbose = 0;
@@ -3703,14 +3713,15 @@ main (int argc, char **argv)
     if( opt.verbose > 1 )
 	set_packet_list_mode(1);
 
-    /* Add the keyrings, but not for some special commands.
-       We always need to add the keyrings if we are running under
-       SELinux, this is so that the rings are added to the list of
-       secured files. */
-    if( ALWAYS_ADD_KEYRINGS
-        || (cmd != aDeArmor && cmd != aEnArmor && cmd != aGPGConfTest) )
+    /* Add the keyrings, but not for some special commands.  We always
+     * need to add the keyrings if we are running under SELinux, this
+     * is so that the rings are added to the list of secured files.
+     * We do not add any keyring if --no-keyring has been used.  */
+    if (default_keyring >= 0
+        && (ALWAYS_ADD_KEYRINGS
+            || (cmd != aDeArmor && cmd != aEnArmor && cmd != aGPGConfTest)))
       {
-	if (!nrings || default_keyring)  /* Add default ring. */
+	if (!nrings || default_keyring > 0)  /* Add default ring. */
 	    keydb_add_resource ("pubring" EXTSEP_S GPGEXT_GPG,
                                 KEYDB_RESOURCE_FLAG_DEFAULT);
 	for (sl = nrings; sl; sl = sl->next )

-----------------------------------------------------------------------

Summary of changes:
 doc/gpg.texi              |  29 ++++++++++---
 g10/getkey.c              |  54 ++++++++++++++++++++++-
 g10/gpg.c                 |  79 ++++++++++++++++++++++------------
 g10/gpgv.c                |  11 +++++
 g10/import.c              | 107 ++++++++++++++++++++++++++++++++++++++++++++++
 g10/keydb.h               |  22 ++++++----
 g10/main.h                |   2 +
 g10/pkclist.c             |  99 +++++++++++++++++++++++-------------------
 g10/server.c              |   6 ++-
 g10/test-stubs.c          |   9 ++++
 tests/openpgp/defs.scm    |   3 ++
 tests/openpgp/encrypt.scm |  15 +++++++
 tests/openpgp/setup.scm   |   9 +++-
 13 files changed, 356 insertions(+), 89 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list