gpg: New options --recipient-file and --hidden-recipient-file.
authorWerner Koch <wk@gnupg.org>
Wed, 6 Jul 2016 12:03:50 +0000 (14:03 +0200)
committerWerner Koch <wk@gnupg.org>
Wed, 6 Jul 2016 13:35:19 +0000 (15:35 +0200)
* 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@gnupg.org>
13 files changed:
doc/gpg.texi
g10/getkey.c
g10/gpg.c
g10/gpgv.c
g10/import.c
g10/keydb.h
g10/main.h
g10/pkclist.c
g10/server.c
g10/test-stubs.c
tests/openpgp/defs.scm
tests/openpgp/encrypt.scm
tests/openpgp/setup.scm

index 9a60890..11d3a65 100644 (file)
@@ -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.
 
+@item --recipient-file @var{file}
+@itemx -f
+@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.
+
+@item --hidden-recipient-file @var{file}
+@itemx -F
+@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.
 
-@item --encrypt-to-default-key
-@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
index f34127d..90fd175 100644 (file)
@@ -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
index cf0e645..34009bb 100644 (file)
--- 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,
index 9ccc0da..d238ee0 100644 (file)
@@ -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.
  */
index 8cfd6ea..e035328 100644 (file)
@@ -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
index a30cf7a..4e8f3f2 100644 (file)
@@ -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);
index 3ee2762..ec20b28 100644 (file)
@@ -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,
index 8efa954..6315a6d 100644 (file)
@@ -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;
index 771a8a7..258f08a 100644 (file)
@@ -177,6 +177,7 @@ output_notify (assuan_context_t ctx, char *line)
 
 \f
 /*  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)
index f4d9526..6f50759 100644 (file)
@@ -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.
  */
index 4257b28..8ceffc8 100644 (file)
@@ -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 '())
index 5a3e178..7452fc5 100755 (executable)
        (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)
index ce2e42c..9ad19c2 100755 (executable)
     "1DF48228FEFF3EC2481B106E0ACA8C465C662CC5"
     "A2832820DC9F40751BDCD375BB0945BA33EC6B4C"
     "ADE710D74409777B7729A7653373D820F67892E0"
-    "CEFC51AF91F68A2904FBFF62C4F075A4785B803F"))
+    "CEFC51AF91F68A2904FBFF62C4F075A4785B803F"
+    "1E28F20E41B54C2D1234D896096495FF57E08D18"
+    "EB33B687EB8581AB64D04852A54453E85F3DF62D"
+    "C6A6390E9388CDBAD71EAEA698233FE5E04F001E"
+    "D69102E0F5AC6B6DB8E4D16DA8E18CF46D88CAE3"))
 
 (info "Importing public demo and test keys")
 (call-check `(,@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))