[svn] GnuPG - r5167 - in trunk: common g10 g13 sm

svn author wk cvs at cvs.gnupg.org
Wed Sep 30 17:28:40 CEST 2009


Author: wk
Date: 2009-09-30 17:28:38 +0200 (Wed, 30 Sep 2009)
New Revision: 5167

Added:
   trunk/g13/backend.c
   trunk/g13/backend.h
   trunk/g13/be-encfs.c
   trunk/g13/be-encfs.h
   trunk/g13/be-truecrypt.c
   trunk/g13/be-truecrypt.h
   trunk/g13/call-gpg.c
   trunk/g13/call-gpg.h
   trunk/g13/create.c
   trunk/g13/keyblob.h
   trunk/g13/utils.c
   trunk/g13/utils.h
Modified:
   trunk/common/ChangeLog
   trunk/common/audit.h
   trunk/common/exechelp.c
   trunk/common/exechelp.h
   trunk/common/iobuf.c
   trunk/common/iobuf.h
   trunk/g10/ChangeLog
   trunk/g10/compress.c
   trunk/g10/dearmor.c
   trunk/g10/encrypt.c
   trunk/g10/export.c
   trunk/g10/gpg.c
   trunk/g10/keydb.h
   trunk/g10/main.h
   trunk/g10/openfile.c
   trunk/g10/parse-packet.c
   trunk/g10/pkclist.c
   trunk/g10/revoke.c
   trunk/g10/server.c
   trunk/g10/sign.c
   trunk/g13/Makefile.am
   trunk/g13/g13.c
   trunk/g13/g13.h
   trunk/sm/ChangeLog
   trunk/sm/gpgsm.c
Log:
Some changes to suport g13.


[The diff below has been truncated]

Modified: trunk/common/ChangeLog
===================================================================
--- trunk/common/ChangeLog	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/common/ChangeLog	2009-09-30 15:28:38 UTC (rev 5167)
@@ -1,3 +1,15 @@
+2009-09-29  Werner Koch  <wk at g10code.com>
+
+	* exechelp.c (create_inheritable_pipe): Rename to
+	create_inheritable_pipe_w.
+	(create_inheritable_pipe_r): New.
+	(gnupg_create_outbound_pipe): New.
+
+	* iobuf.h: Include "sysutils.h"
+
+	* iobuf.c (iobuf_open_fd_or_name): New.
+	(iobuf_get_fname_nonnull): New.
+
 2009-09-23  Marcus Brinkmann  <marcus at g10code.de>
 
 	* asshelp.c (start_new_gpg_agent): Allocate assuan context before

Modified: trunk/g10/ChangeLog
===================================================================
--- trunk/g10/ChangeLog	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/g10/ChangeLog	2009-09-30 15:28:38 UTC (rev 5167)
@@ -1,5 +1,33 @@
+2009-09-30  Werner Koch  <wk at g10code.com>
+
+	* parse-packet.c (skip_packet, parse_gpg_control) <ist_mode>: Take
+	care of premature EOFs.
+
+	* gpg.c (main): Remove obsolete GCRYCTL_DISABLE_INTERNAL_LOCKING.
+
+2009-09-29  Werner Koch  <wk at g10code.com>
+
+	* openfile.c (open_outfile): Re-indent.  Use xstrconcat.
+	(NAME_OF_DEV_NULL): New.
+	(open_outfile): Use it.
+	(overwrite_filep): Use it.  Also use case insensitive compare
+	when needed.  Re-indent.
+	(open_outfile): Add arg INP_FD.  Change all callers.
+
+	* encrypt.c (encrypt_crypt): Add new args FILEFD, OUTPUTFD and
+	PROVIDED_KEYS.  Change all callers.
+
 2009-09-28  Werner Koch  <wk at g10code.com>
 
+	* server.c (skip_options, has_option): New.
+	(cmd_recipient): Implement.
+
+	* keydb.h (pk_list_t): New.
+
+	* pkclist.c (send_status_inv_recp): New.  Replace direct calls.
+	(build_pk_list): Factor some code out to ...
+	(find_and_check_key): ... new.
+
 	* encode.c: Rename to encrypt.c.  Re-indent all.
 	* encrypt.c (encode_symmetric, encode_store, encode_seskey)
 	(encode_simple, encode_crypt, encode_filter)

Modified: trunk/sm/ChangeLog
===================================================================
--- trunk/sm/ChangeLog	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/sm/ChangeLog	2009-09-30 15:28:38 UTC (rev 5167)
@@ -1,3 +1,7 @@
+2009-09-30  Werner Koch  <wk at g10code.com>
+
+	* gpgsm.c (main): Remove obsolete GCRYCTL_DISABLE_INTERNAL_LOCKING.
+
 2009-09-23  Marcus Brinkmann  <marcus at g10code.de>
 
 	* gpgsm.c (main): Update to new assuan API.

Modified: trunk/common/audit.h
===================================================================
--- trunk/common/audit.h	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/common/audit.h	2009-09-30 15:28:38 UTC (rev 5167)
@@ -62,6 +62,15 @@
        operations the Dirmngr is not required and thus no such event
        will be logged.  */
 
+    AUDIT_GPG_READY,   /* err */
+    /* Indicates whether the Gpg engine is available. */
+
+    AUDIT_GPGSM_READY, /* err */
+    /* Indicates whether the Gpgsm engine is available. */
+
+    AUDIT_G13_READY, /* err */
+    /* Indicates whether the G13 engine is available. */
+
     AUDIT_GOT_DATA,
     /* Data to be processed has been seen.  */
 

Modified: trunk/common/exechelp.c
===================================================================
--- trunk/common/exechelp.c	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/common/exechelp.c	2009-09-30 15:28:38 UTC (rev 5167)
@@ -304,7 +304,7 @@
 #ifdef HAVE_W32_SYSTEM
 /* Create  pipe where the write end is inheritable.  */
 static int
-create_inheritable_pipe (int filedes[2])
+create_inheritable_pipe_w (int filedes[2])
 {
   HANDLE r, w, h;
   SECURITY_ATTRIBUTES sec_attr;
@@ -332,6 +332,37 @@
   filedes[1] = handle_to_fd (w);
   return 0;
 }
+
+/* Create  pipe where the read end is inheritable.  */
+static int
+create_inheritable_pipe_r (int filedes[2])
+{
+  HANDLE r, w, h;
+  SECURITY_ATTRIBUTES sec_attr;
+
+  memset (&sec_attr, 0, sizeof sec_attr );
+  sec_attr.nLength = sizeof sec_attr;
+  sec_attr.bInheritHandle = FALSE;
+    
+  if (!CreatePipe (&r, &w, &sec_attr, 0))
+    return -1;
+
+  if (!DuplicateHandle (GetCurrentProcess(), r,
+                        GetCurrentProcess(), &h, 0,
+                        TRUE, DUPLICATE_SAME_ACCESS ))
+    {
+      log_error ("DuplicateHandle failed: %s\n", w32_strerror (-1));
+      CloseHandle (r);
+      CloseHandle (w);
+      return -1;
+    }
+  CloseHandle (r);
+  r = h;
+
+  filedes[0] = handle_to_fd (r);
+  filedes[1] = handle_to_fd (w);
+  return 0;
+}
 #endif /*HAVE_W32_SYSTEM*/
 
 
@@ -425,7 +456,7 @@
 
   filedes[0] = filedes[1] = -1;
   err = gpg_error (GPG_ERR_GENERAL);
-  if (!create_inheritable_pipe (fds))
+  if (!create_inheritable_pipe_w (fds))
     {
       filedes[0] = _open_osfhandle (fds[0], 0);
       if (filedes[0] == -1)
@@ -458,6 +489,50 @@
 }
 
 
+/* Portable function to create a pipe.  Under Windows the read end is
+   inheritable.  */
+gpg_error_t
+gnupg_create_outbound_pipe (int filedes[2])
+{
+  gpg_error_t err = 0;
+#if HAVE_W32_SYSTEM
+  int fds[2];
+
+  filedes[0] = filedes[1] = -1;
+  err = gpg_error (GPG_ERR_GENERAL);
+  if (!create_inheritable_pipe_r (fds))
+    {
+      filedes[0] = _open_osfhandle (fds[0], 0);
+      if (filedes[0] == -1)
+        {
+          log_error ("failed to translate osfhandle %p\n", (void*)fds[0]);
+          CloseHandle (fd_to_handle (fds[1]));
+        }
+      else 
+        {
+          filedes[1] = _open_osfhandle (fds[1], 1);
+          if (filedes[1] == -1)
+            {
+              log_error ("failed to translate osfhandle %p\n", (void*)fds[1]);
+              close (filedes[0]);
+              filedes[0] = -1;
+              CloseHandle (fd_to_handle (fds[1]));
+            }
+          else
+            err = 0;
+        }
+    }
+#else
+  if (pipe (filedes) == -1)
+    {
+      err = gpg_error_from_syserror ();
+      filedes[0] = filedes[1] = -1;
+    }
+#endif
+  return err;
+}
+
+
 /* Fork and exec the PGMNAME, connect the file descriptor of INFILE to
    stdin, write the output to OUTFILE, return a new stream in
    STATUSFILE for stderr and the pid of the process in PID. The
@@ -522,7 +597,7 @@
     return err; 
 
   /* Create a pipe.  */
-  if (create_inheritable_pipe (rp))
+  if (create_inheritable_pipe_w (rp))
     {
       err = gpg_error (GPG_ERR_GENERAL);
       log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));

Modified: trunk/common/exechelp.h
===================================================================
--- trunk/common/exechelp.h	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/common/exechelp.h	2009-09-30 15:28:38 UTC (rev 5167)
@@ -44,7 +44,11 @@
    inheritable.  */
 gpg_error_t gnupg_create_inbound_pipe (int filedes[2]);
 
+/* Portable function to create a pipe.  Under Windows the read end is
+   inheritable.  */
+gpg_error_t gnupg_create_outbound_pipe (int filedes[2]);
 
+
 /* Fork and exec the PGMNAME, connect the file descriptor of INFILE to
    stdin, write the output to OUTFILE, return a new stream in
    STATUSFILE for stderr and the pid of the process in PID. The

Modified: trunk/common/iobuf.c
===================================================================
--- trunk/common/iobuf.c	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/common/iobuf.c	2009-09-30 15:28:38 UTC (rev 5167)
@@ -1260,6 +1260,32 @@
   return check_special_filename (fname) != -1;
 }
 
+
+/* Either open the file specified by the file descriptor FD or - if FD
+   is GNUPG_INVALID_FD - the file with name FNAME.  As of now MODE is
+   assumed to be "rb" if FNAME is used.  In contrast to iobuf_fdopen
+   the fiel descriptor FD will not be closed during an iobuf_close. */
+iobuf_t
+iobuf_open_fd_or_name (gnupg_fd_t fd, const char *fname, const char *mode)
+{
+  iobuf_t a;
+
+  if (fd == GNUPG_INVALID_FD)
+    a = iobuf_open (fname);
+  else
+    {
+      gnupg_fd_t fd2;
+
+      fd2 = dup (fd);
+      if (fd2 == GNUPG_INVALID_FD)
+        a = NULL;
+      else
+        a = iobuf_fdopen (fd2, mode);
+    }
+  return a;
+}
+
+
 /****************
  * Create a head iobuf for reading from a file
  * returns: NULL if an error occures and sets errno
@@ -1306,8 +1332,8 @@
 }
 
 /****************
- * Create a head iobuf for reading from a file
- * returns: NULL if an error occures and sets errno
+ * Create a head iobuf for reading or writing from/to a file
+ * Returns: NULL if an error occures and sets ERRNO.
  */
 iobuf_t
 iobuf_fdopen (int fd, const char *mode)
@@ -2355,7 +2381,9 @@
 
 
 /****************
- * Retrieve the real filename
+ * Retrieve the real filename.  This is the filename actually used on
+ * disk and not a made up one.  Returns NULL if no real filename is
+ * available.
  */
 const char *
 iobuf_get_real_fname (iobuf_t a)
@@ -2376,7 +2404,7 @@
 
 
 /****************
- * Retrieve the filename
+ * Retrieve the filename.  This name should only be used in diagnostics.
  */
 const char *
 iobuf_get_fname (iobuf_t a)
@@ -2390,7 +2418,17 @@
   return NULL;
 }
 
+/* Same as iobuf_get_fname but never returns NULL.  */
+const char *
+iobuf_get_fname_nonnull (iobuf_t a)
+{
+  const char *fname;
 
+  fname = iobuf_get_fname (a);
+  return fname? fname : "[?]";
+}
+
+
 /****************
  * enable partial block mode as described in the OpenPGP draft.
  * LEN is the first length byte on read, but ignored on writes.

Modified: trunk/common/iobuf.h
===================================================================
--- trunk/common/iobuf.h	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/common/iobuf.h	2009-09-30 15:28:38 UTC (rev 5167)
@@ -21,8 +21,8 @@
 #define GNUPG_COMMON_IOBUF_H
 
 #include "../include/types.h" /* fixme: should be moved elsewhere. */
+#include "../common/sysutils.h"
 
-
 #define DBG_IOBUF   iobuf_debug_mode
 
 
@@ -85,6 +85,8 @@
 iobuf_t iobuf_alloc (int use, size_t bufsize);
 iobuf_t iobuf_temp (void);
 iobuf_t iobuf_temp_with_content (const char *buffer, size_t length);
+iobuf_t iobuf_open_fd_or_name (gnupg_fd_t fd, const char *fname,
+                               const char *mode);
 iobuf_t iobuf_open (const char *fname);
 iobuf_t iobuf_fdopen (int fd, const char *mode);
 iobuf_t iobuf_sockopen (int fd, const char *mode);
@@ -131,6 +133,7 @@
 int  iobuf_get_fd (iobuf_t a);
 const char *iobuf_get_real_fname (iobuf_t a);
 const char *iobuf_get_fname (iobuf_t a);
+const char *iobuf_get_fname_nonnull (iobuf_t a);
 
 void iobuf_set_partial_block_mode (iobuf_t a, size_t len);
 

Modified: trunk/g10/compress.c
===================================================================
--- trunk/g10/compress.c	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/g10/compress.c	2009-09-30 15:28:38 UTC (rev 5167)
@@ -245,6 +245,9 @@
 	    memset( &cd, 0, sizeof cd );
 	    cd.len = 0;
 	    cd.algorithm = zfx->algo;
+            /* Fixme: We should force a new CTB here:
+               cd.new_ctb = zfx->new_ctb;
+            */
 	    init_packet( &pkt );
 	    pkt.pkttype = PKT_COMPRESSED;
 	    pkt.pkt.compressed = &cd;

Modified: trunk/g10/dearmor.c
===================================================================
--- trunk/g10/dearmor.c	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/g10/dearmor.c	2009-09-30 15:28:38 UTC (rev 5167)
@@ -64,7 +64,7 @@
 
     push_armor_filter ( afx, inp );
 
-    if( (rc = open_outfile( fname, 0, &out )) )
+    if( (rc = open_outfile (GNUPG_INVALID_FD, fname, 0, &out )) )
 	goto leave;
 
     while( (c = iobuf_get(inp)) != -1 )
@@ -110,7 +110,7 @@
     }
 
 
-    if( (rc = open_outfile( fname, 1, &out )) )
+    if( (rc = open_outfile (GNUPG_INVALID_FD, fname, 1, &out )) )
 	goto leave;
 
     afx->what = 4;

Modified: trunk/g10/encrypt.c
===================================================================
--- trunk/g10/encrypt.c	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/g10/encrypt.c	2009-09-30 15:28:38 UTC (rev 5167)
@@ -264,7 +264,8 @@
       do_compress = 0;        
     }
   
-  if ( rc || (rc = open_outfile( filename, opt.armor? 1:0, &out )))
+  if ( rc || (rc = open_outfile (GNUPG_INVALID_FD, filename,
+                                 opt.armor? 1:0, &out )))
     {
       iobuf_cancel (inp);
       xfree (cfx.dek);
@@ -455,11 +456,15 @@
 
 
 /*
- * Encrypt the file with the given userids (or ask if none
- * is supplied).
+ * Encrypt the file with the given userids (or ask if none is
+ * supplied).  Either FILENAME or FILEFD must be given, but not both.
+ * The caller may provide a checked list of public keys in
+ * PROVIDED_PKS; if not the function builds a list of keys on its own.
  */
 int
-encrypt_crypt (const char *filename, strlist_t remusr, int use_symkey)
+encrypt_crypt (gnupg_fd_t filefd, const char *filename,
+               strlist_t remusr, int use_symkey, pk_list_t provided_keys,
+               gnupg_fd_t outputfd)
 {
   iobuf_t inp = NULL;
   iobuf_t out = NULL;
@@ -477,6 +482,9 @@
   PK_LIST pk_list, work_list;
   int do_compress;
 
+  if (filefd != GNUPG_INVALID_FD && filename)
+    return gpg_error (GPG_ERR_INV_ARG);
+
   do_compress = opt.compress_algo && !RFC1991;
 
   pfx = new_progress_context ();
@@ -492,10 +500,15 @@
       return rc;
     }
 
-  if ((rc = build_pk_list (remusr, &pk_list, PUBKEY_USAGE_ENC)))
+  if (provided_keys)
+    pk_list = provided_keys;
+  else
     {
-      release_progress_context (pfx);
-      return rc;
+      if ((rc = build_pk_list (remusr, &pk_list, PUBKEY_USAGE_ENC)))
+        {
+          release_progress_context (pfx);
+          return rc;
+        }
     }
   
   if(PGP2)
@@ -512,7 +525,7 @@
     }
 
   /* Prepare iobufs. */
-  inp = iobuf_open(filename);
+  inp = iobuf_open_fd_or_name (filefd, filename, "rb");
   if (inp)
     iobuf_ioctl (inp, 3, 1, NULL); /* Disable fd caching. */
   if (inp && is_secured_file (iobuf_get_fd (inp)))
@@ -523,20 +536,30 @@
     }
   if (!inp)
     {
+      char xname[64];
+
       rc = gpg_error_from_syserror ();
+      if (filefd != GNUPG_INVALID_FD)
+        snprintf (xname, sizeof xname, "[fd %d]", filefd);
+      else if (!filename)
+        strcpy (xname, "[stdin]");
+      else
+        *xname = 0;
       log_error (_("can't open `%s': %s\n"),
-                 filename? filename: "[stdin]", gpg_strerror (rc) );
+                 *xname? xname : filename, gpg_strerror (rc) );
       goto leave;
     }
-  else if (opt.verbose)
-    log_info (_("reading from `%s'\n"), filename? filename: "[stdin]");
 
+  if (opt.verbose)
+    log_info (_("reading from `%s'\n"), iobuf_get_fname_nonnull (inp));
+
   handle_progress (pfx, inp, filename);
 
   if (opt.textmode)
     iobuf_push_filter (inp, text_filter, &tfx);
 
-  if ((rc = open_outfile( filename, opt.armor? 1:0, &out )))
+  rc = open_outfile (outputfd, filename, opt.armor? 1:0, &out);
+  if (rc)
     goto leave;
   
   if (opt.armor)
@@ -629,7 +652,8 @@
   if (!opt.no_literal)
     pt = setup_plaintext_name (filename, inp);
   
-  if (!iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
+  if (filefd != GNUPG_INVALID_FD 
+      && !iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
     {
       off_t tmpsize;
       int overflow;
@@ -709,13 +733,16 @@
          plain data. */
       byte copy_buffer[4096];
       int  bytes_copied;
-      while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
-        if ((rc=iobuf_write(out, copy_buffer, bytes_copied)))
-          {
-            log_error ("copying input to output failed: %s\n",
-                       gpg_strerror (rc));
-            break;
-          }
+      while ((bytes_copied = iobuf_read (inp, copy_buffer, 4096)) != -1)
+        {
+          rc = iobuf_write (out, copy_buffer, bytes_copied);
+          if (rc)
+            {
+              log_error ("copying input to output failed: %s\n",
+                         gpg_strerror (rc));
+              break;
+            }
+        }
       wipememory (copy_buffer, 4096); /* Burn the buffer. */
     }
 
@@ -735,7 +762,8 @@
   xfree (cfx.dek);
   xfree (symkey_dek);
   xfree (symkey_s2k);
-  release_pk_list (pk_list);
+  if (!provided_keys)
+    release_pk_list (pk_list);
   release_armor_context (afx);
   release_progress_context (pfx);
   return rc;
@@ -936,9 +964,11 @@
             }
           line[strlen(line)-1] = '\0';
           print_file_status(STATUS_FILE_START, line, 2);
-          if ( (rc = encrypt_crypt(line, remusr, 0)) )
-            log_error("encryption of `%s' failed: %s\n",
-                      print_fname_stdin(line), g10_errstr(rc) );
+          rc = encrypt_crypt (GNUPG_INVALID_FD, line, remusr, 0,
+                              NULL, GNUPG_INVALID_FD);
+          if (rc)
+            log_error ("encryption of `%s' failed: %s\n",
+                       print_fname_stdin(line), g10_errstr(rc) );
           write_status( STATUS_FILE_DONE );
         }
     }
@@ -947,7 +977,8 @@
       while (nfiles--)
         {
           print_file_status(STATUS_FILE_START, *files, 2);
-          if ( (rc = encrypt_crypt(*files, remusr, 0)) )
+          if ( (rc = encrypt_crypt (GNUPG_INVALID_FD, *files, remusr, 0,
+                                    NULL, GNUPG_INVALID_FD)) )
             log_error("encryption of `%s' failed: %s\n",
                       print_fname_stdin(*files), g10_errstr(rc) );
           write_status( STATUS_FILE_DONE );

Modified: trunk/g10/export.c
===================================================================
--- trunk/g10/export.c	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/g10/export.c	2009-09-30 15:28:38 UTC (rev 5167)
@@ -140,7 +140,7 @@
   
   memset( &zfx, 0, sizeof zfx);
   
-  rc = open_outfile( NULL, 0, &out );
+  rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out );
   if (rc)
     return rc;
 

Modified: trunk/g10/gpg.c
===================================================================
--- trunk/g10/gpg.c	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/g10/gpg.c	2009-09-30 15:28:38 UTC (rev 5167)
@@ -1920,9 +1920,6 @@
     gnupg_rl_initialize ();
     set_strusage (my_strusage);
     gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
-    /* We don't need any locking in libgcrypt unless we use any kind of
-       threading. */
-    gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING);
     log_set_prefix ("gpg", 1);
 
     /* Make sure that our subsystems are ready.  */
@@ -3437,7 +3434,8 @@
 	  {
 	    if( argc > 1 )
 	      wrong_args(_("--encrypt [filename]"));
-	    if( (rc = encrypt_crypt(fname,remusr,0)) )
+	    if( (rc = encrypt_crypt (GNUPG_INVALID_FD, fname,
+                                     remusr, 0, NULL, GNUPG_INVALID_FD)) )
 	      log_error("%s: encryption failed: %s\n",
 			print_fname_stdin(fname), g10_errstr(rc) );
 	  }
@@ -3458,7 +3456,8 @@
 		      " while in %s mode\n"),compliance_option_string());
 	else
 	  {
-	    if( (rc = encrypt_crypt(fname,remusr,1)) )
+	    if( (rc = encrypt_crypt (GNUPG_INVALID_FD, fname, 
+                                     remusr, 1, NULL, GNUPG_INVALID_FD)) )
 	      log_error("%s: encryption failed: %s\n",
 			print_fname_stdin(fname), g10_errstr(rc) );
 	  }

Modified: trunk/g10/keydb.h
===================================================================
--- trunk/g10/keydb.h	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/g10/keydb.h	2009-09-30 15:28:38 UTC (rev 5167)
@@ -83,12 +83,14 @@
 };
 typedef struct keyblock_pos_struct KBPOS;
 
-/* structure to hold a couple of public key certificates */
-typedef struct pk_list *PK_LIST;
-struct pk_list {
-    PK_LIST next;
-    PKT_public_key *pk;
-    int flags; /* flag bit 1==throw_keyid */
+/* Structure to hold a couple of public key certificates. */
+typedef struct pk_list *PK_LIST;  /* Deprecated. */
+typedef struct pk_list *pk_list_t;
+struct pk_list 
+{
+  PK_LIST next;
+  PKT_public_key *pk;
+  int flags; /* flag bit 1==throw_keyid */
 };
 
 /* structure to hold a couple of secret key certificates */
@@ -179,8 +181,12 @@
 /*-- pkclist.c --*/
 void show_revocation_reason( PKT_public_key *pk, int mode );
 int  check_signatures_trust( PKT_signature *sig );
-void release_pk_list( PK_LIST pk_list );
-int  build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned use );
+
+void release_pk_list (PK_LIST pk_list);
+int  build_pk_list (strlist_t rcpts, PK_LIST *ret_pk_list, unsigned use);
+gpg_error_t find_and_check_key (const char *name, unsigned int use, 
+                                int mark_hidden, pk_list_t *pk_list_addr);
+
 int  algo_available( preftype_t preftype, int algo,
 		     const union pref_hint *hint );
 int  select_algo_from_prefs( PK_LIST pk_list, int preftype,

Modified: trunk/g10/main.h
===================================================================
--- trunk/g10/main.h	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/g10/main.h	2009-09-30 15:28:38 UTC (rev 5167)
@@ -185,7 +185,9 @@
 int setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek);
 int encrypt_symmetric (const char *filename );
 int encrypt_store (const char *filename );
-int encrypt_crypt (const char *filename, strlist_t remusr, int use_symkey );
+int encrypt_crypt (gnupg_fd_t filefd, const char *filename,
+                   strlist_t remusr, int use_symkey, pk_list_t provided_keys,
+                   gnupg_fd_t outputfd);
 void encrypt_crypt_files (int nfiles, char **files, strlist_t remusr);
 int encrypt_filter (void *opaque, int control,
 		    iobuf_t a, byte *buf, size_t *ret_len);
@@ -243,7 +245,7 @@
 int overwrite_filep( const char *fname );
 char *make_outfile_name( const char *iname );
 char *ask_outfile_name( const char *name, size_t namelen );
-int   open_outfile( const char *iname, int mode, iobuf_t *a );
+int open_outfile (gnupg_fd_t inp_fd, const char *iname, int mode, iobuf_t *a);
 iobuf_t open_sigfile( const char *iname, progress_filter_context_t *pfx );
 void try_make_homedir( const char *fname );
 

Modified: trunk/g10/openfile.c
===================================================================
--- trunk/g10/openfile.c	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/g10/openfile.c	2009-09-30 15:28:38 UTC (rev 5167)
@@ -1,6 +1,6 @@
 /* openfile.c
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- *               2005 Free Software Foundation, Inc.
+ *               2005, 2009 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -43,6 +43,13 @@
 #define SKELEXT EXTSEP_S "skel"
 #endif
 
+#ifdef HAVE_W32_SYSTEM
+#define NAME_OF_DEV_NULL "nul"
+#else
+#define NAME_OF_DEV_NULL "/dev/null"
+#endif
+
+
 #if defined (HAVE_DRIVE_LETTERS) || defined (__riscos__)
 #define CMP_FILENAME(a,b) ascii_strcasecmp( (a), (b) )
 #else
@@ -65,34 +72,27 @@
 int
 overwrite_filep( const char *fname )
 {
-    if( iobuf_is_pipe_filename (fname) )
-	return 1; /* Writing to stdout is always okay */
+  if ( iobuf_is_pipe_filename (fname) )
+    return 1; /* Writing to stdout is always okay.  */
+  
+  if ( access( fname, F_OK ) )
+    return 1; /* Does not exist.  */
+  
+  if ( !compare_filenames (fname, NAME_OF_DEV_NULL) )
+    return 1; /* Does not do any harm.  */
 
-    if( access( fname, F_OK ) )
-	return 1; /* does not exist */
+  if (opt.answer_yes)
+    return 1;
+  if (opt.answer_no || opt.batch)
+    return 0;  /* Do not overwrite.  */
 
-#ifndef HAVE_DOSISH_SYSTEM
-    if ( !strcmp ( fname, "/dev/null" ) )
-        return 1; /* does not do any harm */
-#endif
-#ifdef HAVE_W32_SYSTEM
-    if ( !strcmp ( fname, "nul" ) )
-        return 1;
-#endif
-
-    /* fixme: add some backup stuff in case of overwrite */
-    if( opt.answer_yes )
-	return 1;
-    if( opt.answer_no || opt.batch )
-	return 0;  /* do not overwrite */
-
-    tty_printf(_("File `%s' exists. "), fname);
-    if( cpr_enabled () )
-        tty_printf ("\n");
-    if( cpr_get_answer_is_yes("openfile.overwrite.okay",
-			       _("Overwrite? (y/N) ")) )
-	return 1;
-    return 0;
+  tty_printf (_("File `%s' exists. "), fname);
+  if (cpr_enabled ())
+    tty_printf ("\n");
+  if (cpr_get_answer_is_yes ("openfile.overwrite.okay",
+                             _("Overwrite? (y/N) ")) )
+    return 1;
+  return 0;
 }
 
 
@@ -178,110 +178,134 @@
  * Mode 0 = use ".gpg"
  *	1 = use ".asc"
  *	2 = use ".sig"
+
+ * If INP_FD is not GNUPG_INVALID_FD the function will simply create
+ * an IOBUF for that file descriptor and ignore a INAME and MODE.
+ * Note that INP_FD won't be closed if the returned IOBUF is closed.
  */
 int
-open_outfile( const char *iname, int mode, IOBUF *a )
+open_outfile (gnupg_fd_t inp_fd, const char *iname, int mode, iobuf_t *a)
 {
   int rc = 0;
 
   *a = NULL;
-  if( iobuf_is_pipe_filename (iname) && !opt.outfile ) {
-    *a = iobuf_create(NULL);
-    if( !*a ) {
-      rc = gpg_error_from_syserror ();
-      log_error(_("can't open `%s': %s\n"), "[stdout]", strerror(errno) );
+  if (inp_fd != GNUPG_INVALID_FD)
+    {
+      char xname[64];
+      gnupg_fd_t fd2;
+      
+      fd2 = INT2FD (dup (FD2INT (inp_fd)));
+      if (fd2 == GNUPG_INVALID_FD)
+        *a = NULL;
+      else
+        *a = iobuf_fdopen (fd2, "wb");
+      if (!*a)
+        {
+          rc = gpg_error_from_syserror ();
+          snprintf (xname, sizeof xname, "[fd %d]", inp_fd);
+          log_error (_("can't open `%s': %s\n"), xname, gpg_strerror (rc));
+        }
+      else if (opt.verbose)
+        {
+          snprintf (xname, sizeof xname, "[fd %d]", inp_fd);
+          log_info (_("writing to `%s'\n"), xname);
+        }
     }
-    else if( opt.verbose )
-      log_info(_("writing to stdout\n"));
-  }
-  else {
-    char *buf = NULL;
-    const char *name;
+  else if (iobuf_is_pipe_filename (iname) && !opt.outfile) 
+    {
+      *a = iobuf_create(NULL);
+      if ( !*a )
+        {
+          rc = gpg_error_from_syserror ();
+          log_error (_("can't open `%s': %s\n"), "[stdout]", strerror(errno) );
+        }
+      else if ( opt.verbose )
+        log_info (_("writing to stdout\n"));
+    }
+  else
+    {
+      char *buf = NULL;
+      const char *name;
     
-    if ( opt.dry_run )
-      {
-#ifdef HAVE_W32_SYSTEM
-        name = "nul";
-#else
-        name = "/dev/null";
-#endif
-      }
-    else if( opt.outfile )
-      name = opt.outfile;
-    else {
+      if (opt.dry_run)
+        name = NAME_OF_DEV_NULL;
+      else if (opt.outfile)
+        name = opt.outfile;
+      else 
+        {
 #ifdef USE_ONLY_8DOT3
-      if (opt.mangle_dos_filenames)
-        {
-          /* It is quite common DOS system to have only one dot in a
-           * a filename So if we have something like this, we simple
-           * replace the suffix execpt in cases where the suffix is
-           * larger than 3 characters and not the same as.
-           * We should really map the filenames to 8.3 but this tends to
-           * be more complicated and is probaly a duty of the filesystem
-           */
-          char *dot;
-          const char *newsfx = mode==1 ? ".asc" :
-                               mode==2 ? ".sig" : ".gpg";
+          if (opt.mangle_dos_filenames)
+            {
+              /* It is quite common for DOS systems to have only one
+                 dot in a filename.  If we have something like this,
+                 we simple replace the suffix except in cases where
+                 the suffix is larger than 3 characters and not the
+                 same as the new one.  We don't map the filenames to
+                 8.3 because this is a duty of the file system.  */
+              char *dot;
+              const char *newsfx;
+
+              newsfx = (mode==1 ? ".asc" :
+                        mode==2 ? ".sig" : ".gpg");
           
-          buf = xmalloc(strlen(iname)+4+1);
-          strcpy(buf,iname);
-          dot = strchr(buf, '.' );
-          if ( dot && dot > buf && dot[1] && strlen(dot) <= 4
-				  && CMP_FILENAME(newsfx, dot) )
+              buf = xmalloc (strlen(iname)+4+1);
+              strcpy (buf, iname);
+              dot = strchr (buf, '.' );
+              if ( dot && dot > buf && dot[1] && strlen(dot) <= 4
+                   && CMP_FILENAME (newsfx, dot) )
+                strcpy (dot, newsfx);
+              else if (dot && !dot[1]) /* Do not duplicate a dot.  */
+                strcpy (dot, newsfx+1);
+              else
+                strcat (buf, newsfx);
+            }
+          if (!buf)
+#endif /* USE_ONLY_8DOT3 */
             {
-              strcpy(dot, newsfx );
+              buf = xstrconcat (iname, 
+                                (mode==1 ? EXTSEP_S "asc" :
+                                 mode==2 ? EXTSEP_S "sig" : EXTSEP_S "gpg"),
+                                NULL);
             }
-          else if ( dot && !dot[1] ) /* don't duplicate a dot */
-            strcpy( dot, newsfx+1 );
-          else
-            strcat ( buf, newsfx );
+          name = buf;
         }
-      if (!buf)
-#endif /* USE_ONLY_8DOT3 */
+      
+      rc = 0;
+      while ( !overwrite_filep (name) )
         {
-          buf = xmalloc(strlen(iname)+4+1);
-          strcpy(stpcpy(buf,iname), mode==1 ? EXTSEP_S "asc" :
-		                   mode==2 ? EXTSEP_S "sig" : EXTSEP_S "gpg");
+          char *tmp = ask_outfile_name (NULL, 0);
+          if ( !tmp || !*tmp )
+            {
+              xfree (tmp);
+              rc = gpg_error (GPG_ERR_EEXIST);
+              break;
+            }
+          xfree (buf);
+          name = buf = tmp;
         }
-      name = buf;
+    
+      if ( !rc )
+        {
+          if (is_secured_filename (name) )
+            {
+              *a = NULL;
+              errno = EPERM;
+            }
+          else
+            *a = iobuf_create (name);
+          if (!*a)
+            {
+              rc = gpg_error_from_syserror ();
+              log_error(_("can't create `%s': %s\n"), name, strerror(errno) );
+            }
+          else if( opt.verbose )
+            log_info (_("writing to `%s'\n"), name );
+        }
+      xfree(buf);
     }
-
-    rc = 0;
-    while( !overwrite_filep (name) )
-      {
-        char *tmp = ask_outfile_name (NULL, 0);
-        if ( !tmp || !*tmp )
-          {
-            xfree (tmp);
-            rc = gpg_error (GPG_ERR_EEXIST);
-            break;
-          }
-        xfree (buf);
-        name = buf = tmp;
-      }
-    
-    if( !rc )
-      {
-        if (is_secured_filename (name) )
-          {
-            *a = NULL;
-            errno = EPERM;
-          }
-        else
-          *a = iobuf_create( name );
-        if( !*a )
-          {
-            rc = gpg_error_from_syserror ();
-            log_error(_("can't create `%s': %s\n"), name, strerror(errno) );
-          }
-        else if( opt.verbose )
-          log_info(_("writing to `%s'\n"), name );
-      }
-    xfree(buf);
-  }
-
+  
   if (*a)
-    iobuf_ioctl (*a,3,1,NULL); /* disable fd caching */
+    iobuf_ioctl (*a, 3, 1, NULL); /* Disable fd caching.  */
 
   return rc;
 }

Modified: trunk/g10/parse-packet.c
===================================================================
--- trunk/g10/parse-packet.c	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/g10/parse-packet.c	2009-09-30 15:28:38 UTC (rev 5167)
@@ -682,7 +682,11 @@
 	  else
 	    {
 	      for( ; pktlen; pktlen-- )
-		dump_hex_line(iobuf_get(inp), &i);
+                {
+                  dump_hex_line( (c=iobuf_get(inp)), &i);
+                  if (c == -1)
+                    break;
+                }
 	    }
 	  putc ('\n', listfp);
 	  return;
@@ -2529,7 +2533,11 @@
         }
         else {
             for( ; pktlen; pktlen-- )
-                dump_hex_line(iobuf_get(inp), &i);
+              {
+                dump_hex_line ((c=iobuf_get (inp)), &i);
+                if (c == -1)
+                  break;
+              }
         }
         putc ('\n', listfp);
     }

Modified: trunk/g10/pkclist.c
===================================================================
--- trunk/g10/pkclist.c	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/g10/pkclist.c	2009-09-30 15:28:38 UTC (rev 5167)
@@ -1,6 +1,6 @@
 /* pkclist.c - create a list of public keys
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- *               2008 Free Software Foundation, Inc.
+ *               2008, 2009 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -40,6 +40,18 @@
 
 #define CONTROL_D ('D' - 'A' + 1)
 
+static void
+send_status_inv_recp (int reason, const char *name)
+{
+  char buf[40];
+
+  snprintf (buf, sizeof buf, "%d ", reason);
+  write_status_text_and_buffer (STATUS_INV_RECP, buf,
+                                name, strlen (name), 
+                                -1);
+}
+
+
 /****************
  * Show the revocation reason as it is stored with the given signature
  */
@@ -656,14 +668,15 @@
 
 
 void
-release_pk_list( PK_LIST pk_list )
+release_pk_list (pk_list_t pk_list)
 {
-    PK_LIST pk_rover;
-
-    for( ; pk_list; pk_list = pk_rover ) {
-	pk_rover = pk_list->next;
-	free_public_key( pk_list->pk );
-	xfree( pk_list );
+  PK_LIST pk_rover;
+  
+  for ( ; pk_list; pk_list = pk_rover)
+    {
+      pk_rover = pk_list->next;
+      free_public_key ( pk_list->pk );
+      xfree ( pk_list );
     }
 }
 
@@ -680,7 +693,7 @@
 
 
 /****************
- * Return a malloced string with a default reciepient if there is any
+ * Return a malloced string with a default recipient if there is any
  */
 static char *
 default_recipient(void)
@@ -760,6 +773,96 @@
 }
 
 
+/* 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. */
+gpg_error_t
+find_and_check_key (const char *name, unsigned int use, 
+                    int mark_hidden, pk_list_t *pk_list_addr)
+{
+  int rc;
+  PKT_public_key *pk;
+  int trustlevel;
+
+  if (!name || !*name)
+    return gpg_error (GPG_ERR_INV_NAME);
+
+  pk = xtrycalloc (1, sizeof *pk);
+  if (!pk)
+    return gpg_error_from_syserror ();
+  pk->req_usage = use;
+
+  rc = get_pubkey_byname (NULL, pk, name, NULL, NULL, 0, 0);
+  if (rc)
+    {
+      /* Key not found or other error. */
+      log_error (_("%s: skipped: %s\n"), name, g10_errstr(rc) );
+      send_status_inv_recp (0, name);
+      free_public_key (pk);
+      return rc;
+    }
+
+  rc = openpgp_pk_test_algo2 (pk->pubkey_algo, use);
+  if (rc)
+    {
+      /* Key found but not usable for us (e.g. sign-only key). */
+      send_status_inv_recp (0, name);
+      log_error (_("%s: skipped: %s\n"), name, g10_errstr(rc) );
+      free_public_key (pk);
+      return rc;
+    }
+
+  /* Key found and usable.  Check validity. */
+  trustlevel = get_validity (pk, pk->user_id);
+  if ( (trustlevel & TRUST_FLAG_DISABLED) ) 
+    {
+      /* Key has been disabled. */
+      send_status_inv_recp (0, name);
+      log_info (_("%s: skipped: public key is disabled\n"), name);
+      free_public_key (pk);
+      return G10ERR_UNU_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 G10ERR_UNU_PUBKEY;
+    }
+  /* Note: do_we_trust may have changed the trustlevel. */
+  
+  /* Skip the actual key if the key is already present in the
+     list.  */
+  if (!key_present_in_pk_list (*pk_list_addr, pk)) 
+    {
+      log_info (_("%s: skipped: public key already present\n"), name);
+      free_public_key (pk);
+    }
+  else
+    {
+      pk_list_t r;
+      
+      r = xtrymalloc (sizeof *r);
+      if (!r)
+        {
+          rc = gpg_error_from_syserror ();
+          free_public_key (pk);
+          return rc;
+        }
+      r->pk = pk;
+      r->next = *pk_list_addr;
+      r->flags = mark_hidden? 1:0;
+      *pk_list_addr = r;
+    }
+  
+  return 0;
+}
+
+
+
 /* 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
@@ -831,8 +934,7 @@
             {
               free_public_key ( pk ); pk = NULL;
               log_error (_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) );
-              write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
-                                            rov->d, strlen (rov->d), -1);
+              send_status_inv_recp (0, rov->d);
               goto fail;
             }
           else if ( !(rc=openpgp_pk_test_algo2 (pk->pubkey_algo, use)) ) 
@@ -873,8 +975,7 @@
                  available. */
               free_public_key( pk ); pk = NULL;
               log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) );
-              write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
-                                            rov->d, strlen (rov->d), -1);
+              send_status_inv_recp (0, rov->d);
               goto fail;
             }
         }
@@ -1078,85 +1179,11 @@
           if ( (remusr->flags & 1) )
             continue; /* encrypt-to keys are already handled. */
 
-          pk = xmalloc_clear( sizeof *pk );
-          pk->req_usage = use;
-          if ((rc = get_pubkey_byname (NULL, pk, remusr->d, NULL, NULL, 0, 0)))
-            {
-              /* Key not found or other error. */
-              free_public_key( pk ); pk = NULL;
-              log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) );
-              write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
-                                            remusr->d, strlen (remusr->d),
-                                            -1);
-              goto fail;
-            }
-          else if ( !(rc=openpgp_pk_test_algo2(pk->pubkey_algo, use )) ) 
-            {
-              /* Key found and usable.  Check validity. */
-              int trustlevel;
-              
-              trustlevel = get_validity (pk, pk->user_id);
-              if ( (trustlevel & TRUST_FLAG_DISABLED) ) 
-                {
-                  /*Key has been disabled. */
-                  free_public_key(pk); pk = NULL;
-                  log_info(_("%s: skipped: public key is disabled\n"),
-                           remusr->d);
-                  write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
-                                                remusr->d,
-                                                strlen (remusr->d),
-                                                -1);
-                  rc=G10ERR_UNU_PUBKEY;
-                  goto fail;
-                }
-              else if ( do_we_trust_pre( pk, trustlevel ) ) 
-                {
-                  /* Note: do_we_trust may have changed the trustlevel */
-
-                  /* We have at least one valid recipient. It doesn't
-                   * matters if this recipient is already present. */
-                  any_recipients = 1;
-
-                  /* Skip the actual key if the key is already present
-                   * in the list */
-                  if (!key_present_in_pk_list(pk_list, pk)) 
-                    {
-                      free_public_key(pk); pk = NULL;
-                      log_info(_("%s: skipped: public key already present\n"),
-                               remusr->d);
-                    }
-                  else
-                    {
-                      PK_LIST r;
-                      r = xmalloc( sizeof *r );
-                      r->pk = pk; pk = NULL;
-                      r->next = pk_list;
-                      r->flags = (remusr->flags&2)?1:0;
-                      pk_list = r;
-                    }
-                }
-              else
-                { /* We don't trust this key. */
-                  free_public_key( pk ); pk = NULL;
-                  write_status_text_and_buffer (STATUS_INV_RECP, "10 ",
-                                                remusr->d,
-                                                strlen (remusr->d),
-                                                -1);
-                  rc=G10ERR_UNU_PUBKEY;
-                  goto fail;
-                }
-            }
-          else
-            {
-              /* Key found but not usable for us (e.g. sign-only key). */
-              free_public_key( pk ); pk = NULL;
-              write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
-                                            remusr->d,
-                                            strlen (remusr->d),
-                                            -1);
-              log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) );
-              goto fail;
-            }
+          rc = find_and_check_key (remusr->d, use, !!(remusr->flags&2),
+                                   &pk_list);
+          if (rc)
+            goto fail;
+          any_recipients = 1;
         }
     }
   

Modified: trunk/g10/revoke.c
===================================================================
--- trunk/g10/revoke.c	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/g10/revoke.c	2009-09-30 15:28:38 UTC (rev 5167)
@@ -326,7 +326,7 @@
 	    if( !opt.armor )
 	      tty_printf(_("ASCII armored output forced.\n"));
 
-	    if( (rc = open_outfile( NULL, 0, &out )) )
+	    if( (rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out )) )
 	      goto leave;
 
 	    afx->what = 1;
@@ -550,7 +550,7 @@
     if( !opt.armor )
 	tty_printf(_("ASCII armored output forced.\n"));
 
-    if( (rc = open_outfile( NULL, 0, &out )) )
+    if( (rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out )) )
 	goto leave;
 
     afx->what = 1;

Modified: trunk/g10/server.c
===================================================================
--- trunk/g10/server.c	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/g10/server.c	2009-09-30 15:28:38 UTC (rev 5167)
@@ -33,6 +33,7 @@
 #include "i18n.h"
 #include "options.h"
 #include "../common/sysutils.h"
+#include "status.h"
 
 
 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
@@ -45,6 +46,10 @@
   assuan_context_t assuan_ctx;  
   /* File descriptor as set by the MESSAGE command. */
   gnupg_fd_t message_fd;               
+
+  /* List of prepared recipients.  */
+  pk_list_t recplist;
+
 };
 
 
@@ -61,6 +66,39 @@
 }
 
 
+/* Skip over options.  Blanks after the options are also removed.  */
+static char *
+skip_options (const char *line)
+{
+  while (spacep (line))
+    line++;
+  while ( *line == '-' && line[1] == '-' )
+    {
+      while (*line && !spacep (line))
+        line++;
+      while (spacep (line))
+        line++;
+    }
+  return (char*)line;
+}
+
+
+/* Check whether the option NAME appears in LINE.  */
+static int
+has_option (const char *line, const char *name)
+{
+  const char *s;
+  int n = strlen (name);
+  
+  s = strstr (line, name);
+  if (s && s >= skip_options (line))
+    return 0;
+  return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
+}
+
+
+
+
 
 /* Called by libassuan for Assuan options.  See the Assuan manual for
    details. */
@@ -111,6 +149,9 @@
 {
   ctrl_t ctrl = assuan_get_pointer (ctx);
 
+  release_pk_list (ctrl->server_local->recplist);
+  ctrl->server_local->recplist = NULL;
+
   close_message_fd (ctrl);
   assuan_close_input_fd (ctx);
   assuan_close_output_fd (ctx);
@@ -157,7 +198,7 @@
 
 
 
-/*  RECIPIENT <userID>
+/*  RECIPIENT [--hidden] <userID>
 
    Set the recipient for the encryption.  <userID> should be the
    internal representation of the key; the server may accept any other
@@ -171,9 +212,26 @@
 static gpg_error_t
 cmd_recipient (assuan_context_t ctx, char *line)
 {
-  (void)ctx;
-  (void)line;
-  return gpg_error (GPG_ERR_NOT_SUPPORTED);
+  ctrl_t ctrl = assuan_get_pointer (ctx);
+  gpg_error_t err;
+  int hidden;
+
+  hidden = has_option (line,"--hidden");
+  line = skip_options (line);
+
+  /* FIXME: Expand groups
+  if (opt.grouplist)
+    remusr = expand_group (rcpts);
+  else
+    remusr = rcpts;
+  */
+
+  err = find_and_check_key (line, PUBKEY_USAGE_ENC, hidden, 
+                            &ctrl->server_local->recplist);
+  
+  if (err)
+    log_error ("command '%s' failed: %s\n", "RECIPIENT", gpg_strerror (err));
+  return err;
 }
 
 
@@ -206,22 +264,81 @@
 /*  ENCRYPT 
 
    Do the actual encryption process.  Takes the plaintext from the
-   INPUT command, writes to the ciphertext to the file descriptor set
-   with the OUTPUT command, take the recipients form all the
-   recipients set so far.  If this command fails the clients should
-   try to delete all output currently done or otherwise mark it as
-   invalid.  GPG does ensure that there won't be any security problem
-   with leftover data on the output in this case.
+   INPUT command, writes the ciphertext to the file descriptor set
+   with the OUTPUT command, take the recipients from all the
+   recipients set so far with RECIPIENTS.
 
-   This command should in general not fail, as all necessary checks
-   have been done while setting the recipients.  The input and output
-   pipes are closed.  */
+   If this command fails the clients should try to delete all output
+   currently done or otherwise mark it as invalid.  GPG does ensure
+   that there won't be any security problem with leftover data on the
+   output in this case.
+
+   In most cases this command won't fail because most necessary checks
+   have been done while setting the recipients.  However some checks
+   can only be done right here and thus error may occur anyway (for
+   example, no recipients at all).
+
+   The input, output and message pipes are closed after this
+   command.  */
 static gpg_error_t
 cmd_encrypt (assuan_context_t ctx, char *line)
 {
-  (void)ctx;
-  (void)line;
-  return gpg_error (GPG_ERR_NOT_SUPPORTED);
+  ctrl_t ctrl = assuan_get_pointer (ctx);
+  gpg_error_t err;
+  int inp_fd, out_fd;
+
+  (void)line; /* LINE is not used.  */
+
+  if ( !ctrl->server_local->recplist ) 
+    {
+      write_status_text (STATUS_NO_RECP, "0");
+      err = gpg_error (GPG_ERR_NO_USER_ID);
+      goto leave;
+    }
+
+  inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
+  if (inp_fd == -1)
+    {
+      err = set_error (GPG_ERR_ASS_NO_INPUT, NULL);
+      goto leave;
+    }
+  out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
+  if (out_fd == -1)
+    {
+      err = set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
+      goto leave;
+    }
+
+  /* Fixme: Check that we are using real files and not pipes if in
+     PGP-2 mode.  Do all the other checks we do in gpg.c for aEncr.
+     Maybe we should drop the PGP2 compatibility. */
+
+  
+  /* FIXME: GPGSM does this here: Add all encrypt-to marked recipients
+     from the default list. */
+
+  /* fixme: err = ctrl->audit? 0 : start_audit_session (ctrl);*/
+    
+  err = encrypt_crypt (inp_fd, NULL, NULL, 0,
+                       ctrl->server_local->recplist,
+                       out_fd);
+
+ leave:
+  /* Release the recipient list on success.  */
+  if (!err)
+    {
+      release_pk_list (ctrl->server_local->recplist);
+      ctrl->server_local->recplist = NULL;
+    }
+
+  /* Close and reset the fds. */
+  close_message_fd (ctrl);
+  assuan_close_input_fd (ctx);
+  assuan_close_output_fd (ctx);
+
+  if (err)
+    log_error ("command '%s' failed: %s\n", "ENCRYPT", gpg_strerror (err));
+  return err;
 }
 
 
@@ -258,6 +375,9 @@
   gnupg_fd_t out_fd = assuan_get_output_fd (ctx);
   FILE *out_fp = NULL;
 
+  /* FIXME: Revamp this code it is nearly to 3 years old and was only
+     intended as a quick test.  */
+  
   (void)line;
 
   if (fd == GNUPG_INVALID_FD)
@@ -270,8 +390,8 @@
         return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
     }
 
-  log_debug ("WARNING: The server mode work "
-             "in progress and not ready for use\n");
+  log_debug ("WARNING: The server mode is WORK "
+             "iN PROGRESS and not ready for use\n");
 
   /* Need to dup it because it might get closed and libassuan won't
      know about it then. */
@@ -596,8 +716,13 @@
     }
 
  leave:
-  xfree (ctrl->server_local);
-  ctrl->server_local = NULL;
+  if (ctrl->server_local)
+    {
+      release_pk_list (ctrl->server_local->recplist);
+
+      xfree (ctrl->server_local);
+      ctrl->server_local = NULL;
+    }
   assuan_release (ctx);
   return rc;
 }

Modified: trunk/g10/sign.c
===================================================================
--- trunk/g10/sign.c	2009-09-28 17:11:32 UTC (rev 5166)
+++ trunk/g10/sign.c	2009-09-30 15:28:38 UTC (rev 5167)
@@ -801,7 +801,8 @@
 	else if( opt.verbose )
 	    log_info(_("writing to `%s'\n"), outfile );
     }
-    else if( (rc = open_outfile( fname, opt.armor? 1: detached? 2:0, &out )))
+    else if( (rc = open_outfile (GNUPG_INVALID_FD, fname,
+                                 opt.armor? 1: detached? 2:0, &out )))
 	goto leave;
 
     /* prepare to calculate the MD over the input */
@@ -1110,7 +1111,7 @@
 	else if( opt.verbose )
 	    log_info(_("writing to `%s'\n"), outfile );
     }
-    else if( (rc = open_outfile( fname, 1, &out )) )
+    else if( (rc = open_outfile (GNUPG_INVALID_FD, fname, 1, &out )) )




More information about the Gnupg-commits mailing list