* AUTHORS: Copied from 1.4 and edited to refelct the changes in
authorWerner Koch <wk@gnupg.org>
Thu, 3 Feb 2005 17:40:02 +0000 (17:40 +0000)
committerWerner Koch <wk@gnupg.org>
Thu, 3 Feb 2005 17:40:02 +0000 (17:40 +0000)
1.9.

* agent.h (agent_exit): Add JNLIB_GCC_A_NR to indicate that this
function won't return.

* gpg-agent.c (check_for_running_agent): Initialize pid to a
default value if not needed.

* command-ssh.c: Removed stdint.h.  s/byte_t/unsigned char/,
s/uint32/u32/ becuase that is what we have always used in GnuPG.
(ssh_request_specs): Moved to top of file.
(ssh_key_types): Ditto.
(make_cstring): Ditto.
(data_sign): Don't use a variable for the passphrase prompt, make
it translatable.
(ssh_request_process):

* findkey.c (modify_description): Renamed arguments for clarity,
polished documentation.  Make comment a C-string.  Fixed case of
DESCRIPTION being just "%".
(agent_key_from_file): Make sure comment string to a C-string.

* gpg-agent.c (create_socket_name): Cleanup the implemntation, use
DIMof, agent_exit, removed superflous args and return the
allocated string as value.  Documented.  Changed callers.
(create_server_socket): Cleanups similar to above.  Changed callers.
(cleanup_do): Renamed to ..
(remove_socket): .. this.  Changed caller.
(handle_connections): The signals are to be handled in the select
and not in the accept.  Test all FDs after returning from a
select.  Remove the event tests from the accept calls.  The select
already assured that the accept won't block.

AUTHORS
ChangeLog
agent/ChangeLog
agent/agent.h
agent/command-ssh.c
agent/findkey.c
agent/gpg-agent.c
common/estream.h

diff --git a/AUTHORS b/AUTHORS
index e69de29..0de6a86 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -0,0 +1,140 @@
+Program: GnuPG
+Maintainer:  Werner Koch <wk@gnupg.org>
+Bug reports: <bug-gnupg@gnu.org>
+Security related bug reports: <security@gnupg.org>
+
+Please note that this file is for the 1.9 branch of GnuPG.
+
+
+Authors
+=======
+
+Ales Nyakhaychyk <nyakhaychyk@i1fn.linux.by> Translations [be]
+
+Birger Langkjer <birger.langkjer@image.dk> Translations [da]
+
+Maxim Britov <maxbritov@tut.by> Translations [ru]
+
+Daniel Resare  <daniel@resare.com> Translations [sv]
+Per Tunedal    <per@clipanish.com> Translations [sv]
+
+David Shaw <dshaw@jabberwocky.com> Assigns past and future changes.
+    (all in keyserver/,
+     a lot of changes in g10/ see the ChangeLog,
+     bug fixes here and there)           
+
+Dokianakis Theofanis <madf@hellug.gr> Translations [el]
+
+Edmund GRIMLEY EVANS <edmundo@rano.org> Translations [eo]
+
+Florian Weimer <fw@deneb.enyo.de>  Assigns past and future changes
+    (changed:g10/parse-packet.c, include/iobuf.h, util/iobuf.c)
+
+g10 Code GmbH   <info@g10code.com>  Assigns past and future changes
+    (all work since 2001 as indicated by mail addresses in ChangeLogs)
+
+Gaël Quéri  <gael@lautre.net>  Translations [fr]
+    (fixed a lot of typos)
+
+Gregory Steuck <steuck@iname.com> Translations [ru]
+
+Nagy Ferenc László <nfl@nfllab.com> Translations [hu]
+
+Ivo Timmermans <itimmermans@bigfoot.com> Translations [nl]
+
+Jacobo Tarri'o Barreiro <jtarrio@iname.com> Translations [gl]
+
+Janusz Aleksander Urbanowicz <alex@bofh.torun.pl> Translations [po]
+
+Jedi Lin <Jedi@idej.org> Translations [zh-tw]
+
+Jouni Hiltunen <jouni.hiltunen@kolumbus.fi> Translations [fi]
+Tommi Vainikainen <Tommi.Vainikainen@iki.fi> Translations [fi]
+
+Laurentiu Buzdugan <lbgnupg@rolix.org> Translations [ro]
+
+Magda Procha'zkova'  <magda@math.muni.cz> Translations [cs]
+
+Michael Roth  <mroth@nessie.de>  Assigns changes.
+    (wrote cipher/des.c., changes and bug fixes all over the place)
+
+Michal Majer <mmajer@econ.umb.sk> Translations [sk]
+
+Marco d'Itri <md@linux.it> Translations [it]
+
+Marcus Brinkmann  <marcus@g10code.de>
+    (gpgconf and fixes all over the place)
+
+Matthew Skala <mskala@ansuz.sooke.bc.ca>  Disclaimer
+    (wrote cipher/twofish.c)
+
+Moritz Schulte  <moritz@g10code.com>  
+   (ssh support gpg-agent)
+
+Niklas Hernaeus <nh@df.lth.se> Disclaimer
+    (weak key patches)
+
+Nilgun Belma Buguner <nilgun@technologist.com> Translations [tr]
+
+Nils Ellmenreich  <nils 'at' infosun.fmi.uni-passau.de> 
+                                      Assigns past and future changes
+    (configure.in, cipher/rndlinux.c, FAQ)
+
+Paul Eggert <eggert@twinsun.com> 
+    (configuration macros for LFS)
+
+Pavel I. Shajdo <zwon@severodvinsk.ru> Translations [ru]
+    (man pages)
+
+Pedro Morais <morais@poli.org> Translations [pt_PT]
+
+Rémi Guyomarch        <rguyom@mail.dotcom.fr> Assigns past and future changes.
+    (g10/compress.c, g10/encr-data.c,
+     g10/free-packet.c, g10/mdfilter.c, g10/plaintext.c, util/iobuf.c)
+
+Stefan Bellon   <sbellon@sbellon.de> Assigns past and future changes.
+   (All patches to support RISC OS)
+
+Timo Schulz     <twoaday@freakmail.de> Assigns past and future changes.
+   (util/w32reg.c, g10/passphrase.c, g10/hkp.c)
+
+Tedi Heriyanto <tedi_h@gmx.net> Translations [id]
+
+Thiago Jung Bauermann <jungmann@cwb.matrix.com.br> Translations [pt_BR]
+Rafael Caetano dos Santos <rcaetano@linux.ime.usp.br> Translations [pt_BR]
+
+Toomas Soome <tsoome@ut.ee> Translations [et]
+
+Urko Lusa <ulusa@euskalnet.net> Translations [es_ES]
+
+Walter Koch <koch@u32.de>  Translations [de]
+
+Werner Koch  <wk@gnupg.org>  Assigns GNU Privacy Guard and future changes.
+    (started the whole thing, wrote the S/MIME extensions, the
+     smartcard daemon and the gpg-agent)
+
+Yosiaki IIDA <iida@ring.gr.jp> Translations [ja]
+
+
+
+Other authors
+=============
+
+The files common/libestream.[ch] are maintained as a separate project
+by g10 Code GmbH.  These files, as used here, are considered part of
+GnuPG.
+
+The RPM specs file scripts/gnupg.spec has been contributed by
+several people.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2004,
+           2005 Free Software Foundation, Inc.
+
+ This file is free software; as a special exception the author gives
+ unlimited permission to copy and/or distribute it, with or without
+ modifications, as long as this notice is preserved.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
index f878f60..2c86f42 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2005-02-03  Werner Koch  <wk@g10code.com>
+
+       * AUTHORS: Copied from 1.4 and edited to refelct the changes in
+       1.9.
+
 2005-01-17  Werner Koch  <wk@g10code.com>
 
        * configure.ac: Make --without-included-regex work as expected.
index bf3ffe8..3bd7792 100644 (file)
@@ -1,3 +1,37 @@
+2005-02-03  Werner Koch  <wk@g10code.com>
+
+       * agent.h (agent_exit): Add JNLIB_GCC_A_NR to indicate that this
+       function won't return.
+
+       * gpg-agent.c (check_for_running_agent): Initialize pid to a
+       default value if not needed.
+
+       * command-ssh.c: Removed stdint.h.  s/byte_t/unsigned char/,
+       s/uint32/u32/ becuase that is what we have always used in GnuPG.
+       (ssh_request_specs): Moved to top of file.
+       (ssh_key_types): Ditto.
+       (make_cstring): Ditto.
+       (data_sign): Don't use a variable for the passphrase prompt, make
+       it translatable.
+       (ssh_request_process): 
+       
+
+       * findkey.c (modify_description): Renamed arguments for clarity,
+       polished documentation.  Make comment a C-string.  Fixed case of
+       DESCRIPTION being just "%".
+       (agent_key_from_file): Make sure comment string to a C-string.
+
+       * gpg-agent.c (create_socket_name): Cleanup the implemntation, use
+       DIMof, agent_exit, removed superflous args and return the
+       allocated string as value.  Documented.  Changed callers.
+       (create_server_socket): Cleanups similar to above.  Changed callers.
+       (cleanup_do): Renamed to ..
+       (remove_socket): .. this.  Changed caller.
+       (handle_connections): The signals are to be handled in the select
+       and not in the accept.  Test all FDs after returning from a
+       select.  Remove the event tests from the accept calls.  The select
+       already assured that the accept won't block.
+
 2005-01-29  Moritz Schulte  <moritz@g10code.com>
 
        * command-ssh.c (ssh_handler_request_identities)
        and ssh-agent protocol.
 
        * agent.h (struct opt): New member: ssh_support.
-       Declare function: start_command_handler_ssh.
+       (start_command_handler_ssh): Add prototype.
 
 2005-01-04  Werner Koch  <wk@g10code.com>
 
index 8afda64..a1196bc 100644 (file)
@@ -47,26 +47,28 @@ out_of_core (void)
 
 /* A large struct name "opt" to keep global flags */
 struct {
-  unsigned int debug; /* debug flags (DBG_foo_VALUE) */
-  int verbose;      /* verbosity level */
-  int quiet;        /* be as quiet as possible */
-  int dry_run;      /* don't change any persistent data */
-  int batch;        /* batch mode */
-  const char *homedir; /* configuration directory name */
-  const char *pinentry_program; 
-  const char *scdaemon_program; 
-  int no_grab;      /* don't let the pinentry grab the keyboard */
+  unsigned int debug;  /* Debug flags (DBG_foo_VALUE) */
+  int verbose;         /* Verbosity level */
+  int quiet;           /* Be as quiet as possible */
+  int dry_run;         /* Don't change any persistent data */
+  int batch;           /* Batch mode */
+  const char *homedir; /* Configuration directory name */
+  const char *pinentry_program; /* Filename of the program to start as
+                                   pinentry.  */
+  const char *scdaemon_program; /* Filename of the program to handle
+                                   smartcard tasks.  */
+  int no_grab;         /* Don't let the pinentry grab the keyboard */
   unsigned long def_cache_ttl;
   unsigned long max_cache_ttl;
 
-  int running_detached; /* we are running detached from the tty. */
+  int running_detached; /* We are running detached from the tty. */
 
   int ignore_cache_for_signing;
   int allow_mark_trusted;
   int allow_preset_passphrase;
-  int keep_tty;  /* don't switch the TTY (for pinentry) on request */
-  int keep_display;  /* don't switch the DISPLAY (for pinentry) on request */
-  int ssh_support;             /* Enable ssh-agent emulation.  */
+  int keep_tty;      /* Don't switch the TTY (for pinentry) on request */
+  int keep_display;  /* Don't switch the DISPLAY (for pinentry) on request */
+  int ssh_support;   /* Enable ssh-agent emulation.  */
 } opt;
 
 
@@ -131,7 +133,7 @@ enum {
 };
 
 /*-- gpg-agent.c --*/
-void agent_exit (int rc); /* also implemented in other tools */
+void agent_exit (int rc) JNLIB_GCC_A_NR; /* Also implemented in other tools */
 void agent_init_default_ctrl (struct server_control_s *ctrl);
 
 /*-- command.c --*/
index db0e8da..390bfe9 100644 (file)
@@ -22,7 +22,7 @@
 /* Only v2 of the ssh-agent protocol is implemented.  */
 
 #include <config.h>
-#include <stdint.h>
+
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
@@ -33,9 +33,8 @@
 
 #include "agent.h"
 
-#include <gcrypt.h>
-
 #include "estream.h"
+#include "i18n.h"
 
 \f
 
 #define SSH_RESPONSE_IDENTITIES_ANSWER    12
 #define SSH_RESPONSE_SIGN_RESPONSE        14
 
+/* Other constants.  */
+#define SSH_DSA_SIGNATURE_PADDING 20
+#define SSH_DSA_SIGNATURE_ELEMS    2
+#define SPEC_FLAG_USE_PKCS1V2 (1 << 0)
+
+
+
 \f
 
 
 /* Basic types.  */
 
-/* A "byte".  */
-typedef unsigned char byte_t;
-
 typedef gpg_error_t (*ssh_request_handler_t) (ctrl_t ctrl,
                                              estream_t request,
                                              estream_t response);
 
 typedef struct ssh_request_spec
 {
-  byte_t type;
+  unsigned char type;
   ssh_request_handler_t handler;
   const char *identifier;
 } ssh_request_spec_t;
 
-typedef gpg_error_t (*ssh_key_modifier_t) (const char *elems, gcry_mpi_t *mpis);
+typedef gpg_error_t (*ssh_key_modifier_t) (const char *elems,
+                                           gcry_mpi_t *mpis);
 typedef gpg_error_t (*ssh_signature_encoder_t) (estream_t signature_blob,
                                                gcry_mpi_t *mpis);
 
@@ -96,10 +100,91 @@ typedef struct ssh_key_type_spec
   unsigned int flags;
 } ssh_key_type_spec_t;
 
+
+/* Prototypes.  */
+static gpg_error_t ssh_handler_request_identities (ctrl_t ctrl,
+                                                   estream_t request,
+                                                   estream_t response);
+static gpg_error_t ssh_handler_sign_request (ctrl_t ctrl,
+                                             estream_t request,
+                                             estream_t response);
+static gpg_error_t ssh_handler_add_identity (ctrl_t ctrl,
+                                             estream_t request,
+                                             estream_t response);
+static gpg_error_t ssh_handler_remove_identity (ctrl_t ctrl,
+                                                estream_t request,
+                                                estream_t response);
+static gpg_error_t ssh_handler_remove_all_identities (ctrl_t ctrl,
+                                                      estream_t request,
+                                                      estream_t response);
+static gpg_error_t ssh_handler_lock (ctrl_t ctrl,
+                                     estream_t request,
+                                     estream_t response);
+static gpg_error_t ssh_handler_unlock (ctrl_t ctrl,
+                                     estream_t request,
+                                     estream_t response);
+
+static gpg_error_t ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis);
+static gpg_error_t ssh_signature_encoder_rsa (estream_t signature_blob,
+                                              gcry_mpi_t *mpis);
+static gpg_error_t ssh_signature_encoder_dsa (estream_t signature_blob,
+                                              gcry_mpi_t *mpis);
+
+
+
+/* Global variables.  */
+   
+
+/* Associating request types with the corresponding request
+   handlers.  */
+
+#define REQUEST_SPEC_DEFINE(id, name) \
+  { SSH_REQUEST_##id, ssh_handler_##name, #name }
+
+static ssh_request_spec_t request_specs[] =
+  {
+    REQUEST_SPEC_DEFINE (REQUEST_IDENTITIES,    request_identities),
+    REQUEST_SPEC_DEFINE (SIGN_REQUEST,          sign_request),
+    REQUEST_SPEC_DEFINE (ADD_IDENTITY,          add_identity),
+    REQUEST_SPEC_DEFINE (ADD_ID_CONSTRAINED,    add_identity),
+    REQUEST_SPEC_DEFINE (REMOVE_IDENTITY,       remove_identity),
+    REQUEST_SPEC_DEFINE (REMOVE_ALL_IDENTITIES, remove_all_identities),
+    REQUEST_SPEC_DEFINE (LOCK,                  lock),
+    REQUEST_SPEC_DEFINE (UNLOCK,                unlock)
+  };
+#undef REQUEST_SPEC_DEFINE
+
+
+/* Table holding key type specifications.  */
+static ssh_key_type_spec_t ssh_key_types[] =
+  {
+    {
+      "ssh-rsa", "rsa", "nedupq", "en",   "dupq", "s",  "nedpqu",
+      ssh_key_modifier_rsa, ssh_signature_encoder_rsa,
+      SPEC_FLAG_USE_PKCS1V2
+    },
+    {
+      "ssh-dss", "dsa", "pqgyx",  "pqgy", "x",    "rs", "pqgyx",
+      NULL,                 ssh_signature_encoder_dsa,
+      0
+    },
+  };
+
+\f
+
+
+
+
 \f
 
-/* General utility functions.  */
+/*
+   General utility functions. 
+ */
 
+/* A secure realloc, i.e. it amkese sure to allocate secure memory if
+   A is NULL.  This is required becuase the standard gcry_realloc does
+   not know whether to allocate secure or normal if NULL is passed as
+   existing buffer.  */
 static void *
 realloc_secure (void *a, size_t n)
 {
@@ -113,10 +198,39 @@ realloc_secure (void *a, size_t n)
   return p;
 }
 
-/* Primitive I/O functions.  */
+
+
+static char *
+make_cstring (const char *data, size_t data_n)
+{
+  char *s;
+
+  s = xtrymalloc (data_n + 1);
+  if (s)
+    {
+      strncpy (s, data, data_n);
+      s[data_n] = 0;
+    }
+
+  return s;
+}
+
+
+
+
+/* 
+   Primitive I/O functions.  
+
+   FIXME: Needs documentation.
+
+   Why are all these functions prefixed with es_ ? They are not part
+   of libestream, thus they should not use this prefix.
+
+ */
+
 
 static gpg_error_t
-es_read_byte (estream_t stream, byte_t *b)
+es_read_byte (estream_t stream, unsigned char *b)
 {
   gpg_error_t err;
   int ret;
@@ -138,8 +252,9 @@ es_read_byte (estream_t stream, byte_t *b)
   return err;
 }
 
+
 static gpg_error_t
-es_write_byte (estream_t stream, byte_t b)
+es_write_byte (estream_t stream, unsigned char b)
 {
   gpg_error_t err;
   int ret;
@@ -153,8 +268,9 @@ es_write_byte (estream_t stream, byte_t b)
   return err;
 }
 
+
 static gpg_error_t
-es_read_uint32 (estream_t stream, uint32_t *uint32)
+es_read_uint32 (estream_t stream, u32 *uint32)
 {
   unsigned char buffer[4];
   size_t bytes_read;
@@ -170,13 +286,20 @@ es_read_uint32 (estream_t stream, uint32_t *uint32)
        err = gpg_error (GPG_ERR_EOF);
       else
        {
-         uint32_t n;
+         u32 n;
+
+          /* FIXME: For what is the cast good for? The proper way of
+             wrinting it - assuming an unsigned buffer - is:
 
+             n = (buffer[0]<< 24)|(buffer[0]<< 16)|(buffer[0]<<8)|(buffer[0]);
+            
+             -wk
+          */
          n = (0
-              | ((uint32_t) (buffer[0] << 24))
-              | ((uint32_t) (buffer[1] << 16))
-              | ((uint32_t) (buffer[2] <<  8))
-              | ((uint32_t) (buffer[3] <<  0)));
+              | ((u32) (buffer[0] << 24))
+              | ((u32) (buffer[1] << 16))
+              | ((u32) (buffer[2] <<  8))
+              | ((u32) (buffer[3] <<  0)));
          *uint32 = n;
          err = 0;
        }
@@ -185,13 +308,15 @@ es_read_uint32 (estream_t stream, uint32_t *uint32)
   return err;
 }
 
+
 static gpg_error_t
-es_write_uint32 (estream_t stream, uint32_t uint32)
+es_write_uint32 (estream_t stream, u32 uint32)
 {
   unsigned char buffer[4];
   gpg_error_t err;
   int ret;
 
+  /* Fixme:  The 0xFF mask is superfluous.  */
   buffer[0] = (uint32 >> 24) & 0xFF;
   buffer[1] = (uint32 >> 16) & 0xFF;
   buffer[2] = (uint32 >>  8) & 0xFF;
@@ -206,6 +331,7 @@ es_write_uint32 (estream_t stream, uint32_t uint32)
   return err;
 }
 
+
 static gpg_error_t
 es_read_data (estream_t stream, unsigned char *buffer, size_t size)
 {
@@ -227,6 +353,7 @@ es_read_data (estream_t stream, unsigned char *buffer, size_t size)
   return err;
 }
 
+
 static gpg_error_t
 es_write_data (estream_t stream, const unsigned char *buffer, size_t size)
 {
@@ -242,13 +369,14 @@ es_write_data (estream_t stream, const unsigned char *buffer, size_t size)
   return err;
 }
 
+
 static gpg_error_t
 es_read_string (estream_t stream, unsigned int secure,
-               unsigned char **string, uint32_t *string_size)
+               unsigned char **string, u32 *string_size)
 {
   gpg_error_t err;
   unsigned char *buffer;
-  uint32_t length;
+  u32 length;
 
   buffer = NULL;
 
@@ -289,6 +417,7 @@ es_read_string (estream_t stream, unsigned int secure,
   return err;
 }
 
+
 static gpg_error_t
 es_read_cstring (estream_t stream, char **string)
 {
@@ -306,9 +435,11 @@ es_read_cstring (estream_t stream, char **string)
   return err;
 }
 
+
+/* FIXME: Needs documentation.  */
 static gpg_error_t
 es_write_string (estream_t stream,
-                const unsigned char *string, uint32_t string_n)
+                const unsigned char *string, u32 string_n)
 {
   gpg_error_t err;
 
@@ -323,6 +454,7 @@ es_write_string (estream_t stream,
   return err;
 }
 
+
 static gpg_error_t
 es_write_cstring (estream_t stream, const char *string)
 {
@@ -334,11 +466,12 @@ es_write_cstring (estream_t stream, const char *string)
   return err;
 }                        
 
+
 static gpg_error_t
 es_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint)
 {
   unsigned char *mpi_data;
-  uint32_t mpi_data_size;
+  u32 mpi_data_size;
   gpg_error_t err;
   gcry_mpi_t mpi;
 
@@ -361,6 +494,7 @@ es_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint)
   return err;
 }
 
+
 static gpg_error_t
 es_write_mpi (estream_t stream, gcry_mpi_t mpint)
 {
@@ -383,6 +517,7 @@ es_write_mpi (estream_t stream, gcry_mpi_t mpint)
   return err;
 }
 
+
 static gpg_error_t
 es_read_file (const char *filename, unsigned char **buffer, size_t *buffer_n)
 {
@@ -434,6 +569,7 @@ es_read_file (const char *filename, unsigned char **buffer, size_t *buffer_n)
   return err;
 }
 
+
 static gpg_error_t
 es_copy (estream_t dst, estream_t src)
 {
@@ -463,9 +599,14 @@ es_copy (estream_t dst, estream_t src)
   return err;
 }
 
+
 \f
 
-/* MPI lists.  */
+/*
+
+  MPI lists. 
+
+ */
 
 static void
 mpint_list_free (gcry_mpi_t *mpi_list)
@@ -480,6 +621,7 @@ mpint_list_free (gcry_mpi_t *mpi_list)
     }
 }
 
+
 static gpg_error_t
 ssh_receive_mpint_list (estream_t stream, int secret,
                        ssh_key_type_spec_t key_spec, gcry_mpi_t **mpi_list)
@@ -593,8 +735,7 @@ ssh_signature_encoder_rsa (estream_t signature_blob, gcry_mpi_t *mpis)
   return err;
 }
 
-#define SSH_DSA_SIGNATURE_PADDING 20
-#define SSH_DSA_SIGNATURE_ELEMS    2
+
 
 static gpg_error_t
 ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis)
@@ -639,27 +780,9 @@ ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis)
   return err;
 }
 
-#define SPEC_FLAG_USE_PKCS1V2 (1 << 0)
-
-
-/* Table holding key type specifications.  */
-static ssh_key_type_spec_t ssh_key_types[] =
-  {
-    {
-      "ssh-rsa", "rsa", "nedupq", "en",   "dupq", "s",  "nedpqu",
-      ssh_key_modifier_rsa, ssh_signature_encoder_rsa,
-      SPEC_FLAG_USE_PKCS1V2
-    },
-    {
-      "ssh-dss", "dsa", "pqgyx",  "pqgy", "x",    "rs", "pqgyx",
-      NULL,                 ssh_signature_encoder_dsa,
-      0
-    },
-  };
-
-\f
-
-/* S-Expressions.  */
+/* 
+   S-Expressions. 
+ */
 
 static gpg_error_t
 ssh_sexp_construct (gcry_sexp_t *sexp,
@@ -685,7 +808,9 @@ ssh_sexp_construct (gcry_sexp_t *sexp,
     elems = key_spec.elems_key_public;
   elems_n = strlen (elems);
 
-  sexp_template_n = 33 + strlen (key_spec.identifier) + (elems_n * 6) - (! secret);
+  /* FIXME: Why 33? -wk */
+  sexp_template_n = (33 + strlen (key_spec.identifier)
+                     + (elems_n * 6) - (!secret));
   sexp_template = xtrymalloc (sexp_template_n);
   if (! sexp_template)
     {
@@ -765,13 +890,13 @@ ssh_sexp_extract (gcry_sexp_t sexp,
       goto out;
     }
 
-  if ((data_n == 10) && (! strncmp (data, "public-key", 10)))
+  if (data_n == 10 && !strncmp (data, "public-key", 10))
     {
       is_secret = 0;
       elems = key_spec.elems_key_public;
     }
-  else if (((data_n == 11) && (! strncmp (data, "private-key", 11)))
-          || ((data_n == 21) && (! strncmp (data, "protected-private-key", 21))))
+  else if ((data_n == 11 && !strncmp (data, "private-key", 11))
+          || (data_n == 21 && !strncmp (data, "protected-private-key", 21)))
     {
       is_secret = 1;
       elems = key_spec.elems_key_secret;
@@ -934,8 +1059,8 @@ ssh_key_type_lookup (const char *ssh_name, const char *name,
 }
 
 static gpg_error_t
-ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret, int read_comment,
-                ssh_key_type_spec_t *key_spec)
+ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret,
+                 int read_comment, ssh_key_type_spec_t *key_spec)
 {
   gpg_error_t err;
   char *key_type;
@@ -1093,7 +1218,8 @@ ssh_send_key_public (estream_t stream, gcry_sexp_t key_public)
   if (err)
     goto out;
 
-  err = ssh_convert_key_to_blob (&blob, &blob_n, spec.ssh_identifier, mpi_list);
+  err = ssh_convert_key_to_blob (&blob, &blob_n,
+                                 spec.ssh_identifier, mpi_list);
   if (err)
     goto out;
   
@@ -1268,27 +1394,13 @@ key_secret_to_public (gcry_sexp_t *key_public,
 
 \f
 
-static char *
-make_cstring (const char *data, size_t data_n)
-{
-  char *s;
-
-  s = xtrymalloc (data_n + 1);
-  if (s)
-    {
-      strncpy (s, data, data_n);
-      s[data_n] = 0;
-    }
-
-  return s;
-}
-
-\f
-
-/* Request handler.  */
+/*
+  Request handler.  
+ */
 
 static gpg_error_t
-ssh_handler_request_identities (ctrl_t ctrl, estream_t request, estream_t response)
+ssh_handler_request_identities (ctrl_t ctrl,
+                                estream_t request, estream_t response)
 {
   const char *key_type;
   ssh_key_type_spec_t spec;
@@ -1298,7 +1410,7 @@ ssh_handler_request_identities (ctrl_t ctrl, estream_t request, estream_t respon
   char *key_path;
   unsigned char *buffer;
   size_t buffer_n;
-  uint32_t key_counter;
+  u32 key_counter;
   estream_t key_blobs;
   gcry_sexp_t key_secret;
   gcry_sexp_t key_public;
@@ -1468,11 +1580,11 @@ data_hash (unsigned char *data, size_t data_n,
   return 0;
 }
 
+
 static gpg_error_t
-data_sign (CTRL ctrl, ssh_signature_encoder_t sig_encoder,
+data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder,
           unsigned char **sig, size_t *sig_n)
 {
-  char description[] = "Please provide the passphrase for key `%c':";
   gpg_error_t err;
   gcry_sexp_t signature_sexp;
   estream_t stream;
@@ -1501,7 +1613,9 @@ data_sign (CTRL ctrl, ssh_signature_encoder_t sig_encoder,
   sig_value = NULL;
   mpis = NULL;
 
-  err = agent_pksign_do (ctrl, description, &signature_sexp, 0);
+  err = agent_pksign_do (ctrl,
+                         _("Please provide the passphrase "
+                           "for the ssh key `%c':"), &signature_sexp, 0);
   if (err)
     goto out;
 
@@ -1632,12 +1746,12 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response)
   unsigned int hash_n;
   unsigned char key_grip[20];
   unsigned char *key_blob;
-  uint32_t key_blob_size;
+  u32 key_blob_size;
   unsigned char *data;
   unsigned char *sig;
   size_t sig_n;
-  uint32_t data_size;
-  uint32_t flags;
+  u32 data_size;
+  u32 flags;
   const void *p;
   gpg_error_t err;
   gpg_error_t ret_err;
@@ -1886,6 +2000,11 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
   if (err)
     goto out;
 
+
+  /* FIXME: What the hell is that: Never have use sprintf in that way.
+     When marking a string translatbale you might get a buffer
+     overflow.  We have never done this elsewhere.  Using [x]asprintf
+     is the right way!! */
   description_length = 95 + (comment ? strlen (comment) : 0);
   description = malloc (description_length);
   if (! description)
@@ -1896,7 +2015,7 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
   else
     sprintf (description,
             "Please provide the passphrase, which should be used "
-            "for protecting the received secret key `%s':",
+               "for protecting the received secret key `%s':",
             comment ? comment : "");
 
   err = get_passphrase (ctrl, description, sizeof (passphrase), passphrase);
@@ -1954,7 +2073,7 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response)
   gpg_error_t ret_err;
   gpg_error_t err;
   gcry_sexp_t key;
-  byte_t b;
+  unsigned char b;
   int confirm;
   int ttl;
   
@@ -1980,7 +2099,7 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response)
        {
        case SSH_OPT_CONSTRAIN_LIFETIME:
          {
-           uint32_t n = 0;
+           u32 n = 0;
 
            err = es_read_uint32 (request, &n);
            if (! err)
@@ -2017,10 +2136,11 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response)
 }
 
 static gpg_error_t
-ssh_handler_remove_identity (ctrl_t ctrl, estream_t request, estream_t response)
+ssh_handler_remove_identity (ctrl_t ctrl, estream_t request,
+                             estream_t response)
 {
   unsigned char *key_blob;
-  uint32_t key_blob_size;
+  u32 key_blob_size;
   gcry_sexp_t key;
   gpg_error_t ret_err;
   gpg_error_t err;
@@ -2065,7 +2185,8 @@ ssh_identities_remove_all (void)
 }
 
 static gpg_error_t
-ssh_handler_remove_all_identities (ctrl_t ctrl, estream_t request, estream_t response)
+ssh_handler_remove_all_identities (ctrl_t ctrl, estream_t request,
+                                   estream_t response)
 {
   gpg_error_t ret_err;
   gpg_error_t err;
@@ -2083,7 +2204,7 @@ ssh_lock (void)
   gpg_error_t err;
 
   /* FIXME */
-  log_error ("[gpg-agent/ssh] lock command is not implemented\n");
+  log_error (_("lock command is not implemented\n"));
   err = 0;
 
   return err;
@@ -2094,7 +2215,7 @@ ssh_unlock (void)
 {
   gpg_error_t err;
 
-  log_error ("[gpg-agent/ssh] unlock command is not implemented\n");
+  log_error (_("unlock command is not implemented\n"));
   err = 0;
 
   return err;
@@ -2128,39 +2249,19 @@ ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response)
 
 \f
 
-/* Associating request types with the corresponding request
-   handlers.  */
-
-#define REQUEST_SPEC_DEFINE(id, name) \
-  { SSH_REQUEST_##id, ssh_handler_##name, #name }
-
-static ssh_request_spec_t request_specs[] =
-  {
-    REQUEST_SPEC_DEFINE (REQUEST_IDENTITIES,    request_identities),
-    REQUEST_SPEC_DEFINE (SIGN_REQUEST,          sign_request),
-    REQUEST_SPEC_DEFINE (ADD_IDENTITY,          add_identity),
-    REQUEST_SPEC_DEFINE (ADD_ID_CONSTRAINED,    add_identity),
-    REQUEST_SPEC_DEFINE (REMOVE_IDENTITY,       remove_identity),
-    REQUEST_SPEC_DEFINE (REMOVE_ALL_IDENTITIES, remove_all_identities),
-    REQUEST_SPEC_DEFINE (LOCK,                  lock),
-    REQUEST_SPEC_DEFINE (UNLOCK,                unlock)
-  };
-
-\f
-
 static int
 ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
 {
   estream_t response;
   estream_t request;
-  byte_t request_type;
+  unsigned char request_type;
   gpg_error_t err;
   unsigned int i;
   int send_err;
   int ret;
   unsigned char *request_data;
-  uint32_t request_data_size;
-  uint32_t response_size;
+  u32 request_data_size;
+  u32 response_size;
 
   request_data = NULL;
   response = NULL;
@@ -2170,15 +2271,22 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
   /* Create memory streams for request/response data.  The entire
      request will be stored in secure memory, since it might contain
      secret key material.  The response does not have to be stored in
-     secure memory, since we never give out secret keys.  */
+     secure memory, since we never give out secret keys. 
+
+     FIXME: This is a pretty good DoS.  We only have a limited amount
+     of secure memory, we can't trhow hin everything we get from a
+     client -wk */
       
   /* Retrieve request.  */
   err = es_read_string (stream_sock, 1, &request_data, &request_data_size);
   if (err)
     goto out;
 
-  if (opt.verbose)
-    log_debug ("[gpg-agent/ssh] Received request of length: %u\n",
+  if (opt.verbose) /* FIXME: using log_debug is not good with
+                      verbose. log_debug should only be used in
+                      debugging mode or in sitattions which are
+                      unexpected. */
+    log_debug ("received request of length: %u\n",
               request_data_size);
 
   request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+");
@@ -2217,14 +2325,14 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
       break;
   if (i == DIM (request_specs))
     {
-      log_debug ("[gpg-agent/ssh] request %u is not supported\n",
+      log_debug ("request %u is not supported\n",
                 request_type);
       send_err = 1;
       goto out;
     }
 
   if (opt.verbose)
-    log_debug ("[gpg-agent/ssh] Executing request handler: %s (%u)\n",
+    log_debug ("executing request handler: %s (%u)\n",
               request_specs[i].identifier, request_specs[i].type);
 
   err = (*request_specs[i].handler) (ctrl, request, response);
@@ -2260,7 +2368,7 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
  out:
 
   if (err && es_feof (stream_sock))
-    log_error ("[gpg-agent/ssh] Error occured while processing request: %s\n",
+    log_error ("error occured while processing request: %s\n",
               gpg_strerror (err));
 
   if (send_err)
@@ -2301,10 +2409,10 @@ start_command_handler_ssh (int sock_client)
 
   /* Create stream from socket.  */
   stream_sock = es_fdopen (sock_client, "r+");
-  if (! stream_sock)
+  if (!stream_sock)
     {
       err = gpg_error_from_errno (errno);
-      log_error ("[gpg-agent/ssh] Failed to create stream from socket: %s\n",
+      log_error (_("failed to create stream from socket: %s\n"),
                 gpg_strerror (err));
       goto out;
     }
@@ -2314,14 +2422,13 @@ start_command_handler_ssh (int sock_client)
   if (ret)
     {
       err = gpg_error_from_errno (errno);
-      log_error ("[gpg-agent/ssh] Failed to disable buffering "
-                "on socket stream: %s\n", gpg_strerror (err));
+      log_error (_("failed to disable buffering "
+                   "on socket stream: %s\n"), gpg_strerror (err));
       goto out;
     }
 
   while (1)
     {
-      /* Process request.  */
       bad = ssh_request_process (&ctrl, stream_sock);
       if (bad)
        break;
index d39d3aa..896cb88 100644 (file)
@@ -143,101 +143,79 @@ try_unprotect_cb (struct pin_entry_info_s *pi)
 /* Modify a Key description, replacing certain special format
    characters.  List of currently supported replacements:
 
-   %% -> %
-   %c -> <COMMENT>. */
-static int
-modify_description (const char *description,
-                   const char *comment, size_t comment_length,
-                   char **description_modified)
-{
-  size_t description_length;
-  size_t description_new_length;
-  gpg_error_t err;
-  char *description_new;
-  unsigned int i, j;
-  unsigned int special;
-
-  description_length  = strlen (description);
-  description_new_length = description_length;
-  description_new = NULL;
-
-  /* Calculate length.  */
-  special = 0;
-  for (i = 0; i < description_length; i++)
-    {
-      if (description[i] == '%')
-       special = 1;
-      else
-       {
-         if (special)
-           {
-             description_new_length -= 2;
-             switch (description[i])
-               {
-               case 'c':
-                 /* Comment.  */
-                 description_new_length += comment_length;
-                 break;
-                 
-               case '%':
-                 description_new_length += 1;
-                 break;
-               }
-             special = 0;
-           }
-       }
-    }
-
-  /* Allocate.  */
-  description_new = xtrymalloc (description_new_length + 1);
-  if (! description_new)
-    {
-      err = gpg_error_from_errno (errno);
-      goto out;
-    }
+   %% - Replaced by a single %
+   %c - Replaced by the content of COMMENT.
 
-  /* Fill.  */
-  for (i = j = 0; i < description_length; i++)
+   The functions returns 0 on success or an error code.  On success a
+   newly allocated string is stored at the address of RESULT.
+ */
+static gpg_error_t
+modify_description (const char *in, const char *comment, char **result)
+{
+  size_t comment_length;
+  size_t in_len;
+  size_t out_len;
+  char *out;
+  size_t i;
+  int special, pass;
+
+  comment_length = strlen (comment);
+  in_len  = strlen (in);
+
+  /* First pass calculates the length, second pass does the actual
+     copying.  */
+  out = NULL;
+  out_len = 0;
+  for (pass=0; pass < 2; pass++)
     {
-      if (description[i] == '%')
-       special = 1;
-      else
-       {
-         if (special)
-           {
-             switch (description[i])
-               {
-               case 'c':
-                 /* Comment.  */
-                 if (comment)
-                   {
-                     strncpy (description_new + j, comment, comment_length);
-                     j += comment_length;
-                   }
-                 break;
-                 
-               case '%':
-                 description_new[j] = '%';
-                 j++;
-                 break;
-               }
-             special = 0;
-           }
-         else
-           {
-             description_new[j] = description[i];
-             j++;
-           }
-       }
+      special = 0;
+      for (i = 0; i < in_len; i++)
+        {
+          if (in[i] == '%')
+            special = 1;
+          else if (special)
+            {
+              special = 0;
+              switch (in[i])
+                {
+                case '%':
+                  out_len++;
+                  if (out)
+                    *out++ = '%';
+                  break;
+
+                case 'c': /* Comment.  */
+                  out_len += comment_length;
+                  if (out && comment_length)
+                    {
+                      memcpy (out, comment, comment_length);
+                      out += comment_length;
+                    }
+                  break;
+
+                default: /* Invalid special sequences are ignored.  */
+                  break;
+                }
+            }
+          else
+            {
+              out_len++;
+              if (out)
+                *out++ = in[i];
+            }
+        }
+      
+      if (!pass)
+        {
+          *result = out = xtrymalloc (out_len + 1);
+          if (!out)
+            return gpg_error_from_errno (errno);
+        }
     }
 
-  description_new[j] = 0;
-  *description_modified = description_new;
-  err = 0;
-
- out:
-
-  return err;
+  *out = 0;
+  assert (*result + out_len == out);
+  return 0;
 }
 
   
@@ -398,35 +376,51 @@ agent_key_from_file (CTRL ctrl, const char *desc_text,
        gcry_sexp_t comment_sexp;
        size_t comment_length;
        char *desc_text_final;
-       const char *comment;
-       
+       const char *comment = NULL;
+
+        /* Note, that we will take the comment as a C styring for
+           display purposes; i.e. all stuff beyond a Nul character is
+           ignored.  */
        comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
        if (comment_sexp)
          comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
-       else
+       if (!comment)
          {
-           comment = NULL;
+           comment = "";
            comment_length = 0;
          }
 
+        desc_text_final = NULL;
        if (desc_text)
          {
-           rc = modify_description (desc_text,
-                                    comment, comment_length, &desc_text_final);
-           if (rc)
-             log_error ("failed to modify description: %s\n", gpg_strerror (rc));
+            if (comment[comment_length])
+              {
+                /* Not a C-string; create one.  We might here allocate
+                   more than actually displayed but well, that
+                   shouldn't be a problem.  */
+                char *tmp = xtrymalloc (comment_length+1);
+                if (!tmp)
+                  rc = gpg_error_from_errno (errno);
+                else
+                  {
+                    memcpy (tmp, comment, comment_length);
+                    tmp[comment_length] = 0;
+                    rc = modify_description (desc_text, tmp, &desc_text_final);
+                    xfree (tmp);
+                  }
+              }
+            else
+              rc = modify_description (desc_text, comment, &desc_text_final);
          }
-       else
-         desc_text_final = NULL;
 
-       if (! rc)
+       if (!rc)
          {
            rc = unprotect (ctrl, desc_text_final, &buf, grip, ignore_cache);
            if (rc)
              log_error ("failed to unprotect the secret key: %s\n",
                         gpg_strerror (rc));
          }
-
+        
        gcry_sexp_release (comment_sexp);
        xfree (desc_text_final);
       }
index 9f97fb6..d8b891e 100644 (file)
@@ -51,6 +51,7 @@
 #include "../jnlib/w32-afunix.h"
 #endif
 
+
 enum cmd_and_opt_values 
 { aNull = 0,
   oCsh           = 'c',
@@ -146,7 +147,7 @@ static ARGPARSE_OPTS opts[] = {
                              N_("allow clients to mark keys as \"trusted\"")},
   { oAllowPresetPassphrase, "allow-preset-passphrase", 0,
                              N_("allow presetting passphrase")},
-  { oSSHSupport, "ssh-support", 0, "Enable SSH-Agent emulation" },
+  { oSSHSupport, "ssh-support", 0, N_("enable secure ssh-agent emulation") },
   {0}
 };
 
@@ -163,7 +164,7 @@ static int shutdown_pending;
 /* It is possible that we are currently running under setuid permissions */
 static int maybe_setuid = 1;
 
-/* Name of the communication socket */
+/* Name of the communication socket used for native gpg-agent requests.  */
 static char *socket_name;
 
 /* Name of the communication socket used for ssh-agent-emulation.  */
@@ -186,8 +187,15 @@ static const char *debug_level;
    the log file after a SIGHUP if it didn't changed. Malloced. */
 static char *current_logfile;
 
-/* Local prototypes. */
+/*
+   Local prototypes. 
+ */
+
+static char *create_socket_name (int use_standard_socket,
+                                 char *standard_name, char *template);
+static int create_server_socket (int is_standard_name, const char *name);
 static void create_directories (void);
+
 #ifdef USE_GNU_PTH
 static void handle_connections (int listen_fd, int listen_fd_ssh);
 /* Pth wrapper function definitions. */
@@ -198,6 +206,12 @@ static int check_for_running_agent (int);
 
 
 
+
+/*
+   Functions. 
+ */
+
+
 static const char *
 my_strusage (int level)
 {
@@ -302,8 +316,9 @@ set_debug (void)
 }
  
 
+/* Helper for cleanup to remove one socket with NAME.  */
 static void
-cleanup_do (char *name)
+remove_socket (char *name)
 {
   if (name && *name)
     {
@@ -324,8 +339,8 @@ cleanup_do (char *name)
 static void
 cleanup (void)
 {
-  cleanup_do (socket_name);
-  cleanup_do (socket_name_ssh);
+  remove_socket (socket_name);
+  remove_socket (socket_name_ssh);
 }
 
 
@@ -417,105 +432,6 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
 }
 
 
-static void
-create_socket_name (char **name, int standard_socket,
-                   struct sockaddr_un *serv_addr,
-                   char *standard_identifier, char *identifier)
-{
-  char *p;
-
-  if (standard_socket)
-    *name = make_filename (opt.homedir, standard_identifier, NULL);
-  else
-    {
-      *name = xstrdup (identifier);
-      p = strrchr (*name, '/');
-      if (! p)
-       BUG ();
-      *p = 0;
-      if (!mkdtemp (*name))
-       {
-         log_error (_("can't create directory `%s': %s\n"),
-                    *name, strerror (errno));
-         exit (1);
-       }
-      *p = '/';
-    }
-
-  if (strchr (*name, PATHSEP_C))
-    {
-      log_error ("`%s' are not allowed in the socket name\n", PATHSEP_S);
-      exit (1);
-    }
-  if (strlen (*name) + 1 >= sizeof serv_addr->sun_path)
-    {
-      log_error ("name of socket too long\n");
-      exit (1);
-    }
-}
-
-static int
-create_server_socket (struct sockaddr_un *serv_addr,
-                     int standard_socket, const char *name)
-{
-  socklen_t len;
-  int fd;
-  int rc;
-
-#ifdef HAVE_W32_SYSTEM
-  fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0);
-#else
-  fd = socket (AF_UNIX, SOCK_STREAM, 0);
-#endif
-  if (fd == -1)
-    {
-      log_error ("can't create socket: %s\n", strerror (errno));
-      exit (1);
-    }
-
-  memset (serv_addr, 0, sizeof *serv_addr);
-  serv_addr->sun_family = AF_UNIX;
-  strcpy (serv_addr->sun_path, name);
-  len = (offsetof (struct sockaddr_un, sun_path)
-        + strlen (serv_addr->sun_path) + 1);
-
-#ifdef HAVE_W32_SYSTEM
-  rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len);
-  if ((rc == -1) && standard_socket)
-    {
-      remove (name);
-      rc = bind (fd, (struct sockaddr*) serv_addr, len);
-    }
-#else
-  rc = bind (fd, (struct sockaddr*) serv_addr, len);
-  if ((rc == -1) && standard_socket && (errno == EADDRINUSE))
-    {
-      remove (name);
-      rc = bind (fd, (struct sockaddr*) serv_addr, len);
-    }
-#endif
-  if (rc == -1)
-    {
-      log_error ("error binding socket to `%s': %s\n",
-                serv_addr->sun_path, strerror (errno));
-      close (fd);
-      exit (1);
-    }
-
-  if (listen (fd, 5 ) == -1)
-    {
-      log_error ("listen() failed: %s\n", strerror (errno));
-      close (fd);
-      exit (1);
-    }
-
-  if (opt.verbose)
-    log_info ("listening on socket `%s'\n", socket_name);
-
-  return fd;
-}
-
-
 int
 main (int argc, char **argv )
 {
@@ -865,8 +781,6 @@ main (int argc, char **argv )
       int fd;
       int fd_ssh;
       pid_t pid;
-      struct sockaddr_un serv_addr;
-      struct sockaddr_un serv_addr_ssh;
 
       /* Remove the DISPLAY variable so that a pinentry does not
          default to a specific display.  There is still a default
@@ -877,27 +791,27 @@ main (int argc, char **argv )
         unsetenv ("DISPLAY");
 #endif
 
-      /* Create the socket name . */
-      create_socket_name (&socket_name, standard_socket, &serv_addr,
-                         "S.gpg-agent", "/tmp/gpg-XXXXXX/S.gpg-agent");
+
+      /* Create the sockets.  */
+      socket_name = create_socket_name (standard_socket,
+                                        "S.gpg-agent",
+                                        "/tmp/gpg-XXXXXX/S.gpg-agent");
       if (opt.ssh_support)
-       create_socket_name (&socket_name_ssh, standard_socket, &serv_addr_ssh,
-                           "S.gpg-agent.ssh", "/tmp/gpg-XXXXXX/S.gpg-agent.ssh");
+       socket_name_ssh = create_socket_name (standard_socket, 
+                                            "S.gpg-agent.ssh",
+                                            "/tmp/gpg-XXXXXX/S.gpg-agent.ssh");
 
-      fd = create_server_socket (&serv_addr,
-                                standard_socket, socket_name);
+      fd = create_server_socket (standard_socket, socket_name);
       if (opt.ssh_support)
-       fd_ssh = create_server_socket (&serv_addr_ssh,
-                                      standard_socket, socket_name_ssh);
+       fd_ssh = create_server_socket (standard_socket, socket_name_ssh);
       else
-       /* Make the compiler happy.  */
        fd_ssh = -1;
 
+
       fflush (NULL);
 #ifdef HAVE_W32_SYSTEM
       pid = getpid ();
       printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid);
-      printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid);
 #else /*!HAVE_W32_SYSTEM*/
       pid = fork ();
       if (pid == (pid_t)-1) 
@@ -911,7 +825,7 @@ main (int argc, char **argv )
           
           close (fd);
           
-          /* create the info string: <name>:<pid>:<protocol_version> */
+          /* Create the info string: <name>:<pid>:<protocol_version> */
           if (asprintf (&infostr, "GPG_AGENT_INFO=%s:%lu:1",
                         socket_name, (ulong)pid ) < 0)
             {
@@ -937,13 +851,14 @@ main (int argc, char **argv )
                }
            }
 
-          *socket_name = 0; /* don't let cleanup() remove the socket -
+          *socket_name = 0; /* Don't let cleanup() remove the socket -
                                the child should do this from now on */
          if (opt.ssh_support)
            *socket_name_ssh = 0;
 
+
           if (argc) 
-            { /* run the program given on the commandline */
+            { /* Run the program given on the commandline.  */
               if (putenv (infostr))
                 {
                   log_error ("failed to set environment: %s\n",
@@ -972,18 +887,18 @@ main (int argc, char **argv )
             }
           else
             {
-              /* print the environment string, so that the caller can use
+              /* Print the environment string, so that the caller can use
                  shell's eval to set it */
               if (csh_style)
                 {
                   *strchr (infostr, '=') = ' ';
-                  printf ( "setenv %s\n", infostr);
+                  printf ("setenv %s\n", infostr);
                  if (opt.ssh_support)
                    {
                      *strchr (infostr_ssh_sock, '=') = ' ';
-                     printf ( "setenv %s\n", infostr_ssh_sock);
+                     printf ("setenv %s\n", infostr_ssh_sock);
                      *strchr (infostr_ssh_pid, '=') = ' ';
-                     printf ( "setenv %s\n", infostr_ssh_pid);
+                     printf ("setenv %s\n", infostr_ssh_pid);
                    }
                 }
               else
@@ -991,10 +906,11 @@ main (int argc, char **argv )
                   printf ( "%s; export GPG_AGENT_INFO;\n", infostr);
                  if (opt.ssh_support)
                    {
-                     printf ( "%s; export SSH_AUTH_SOCK;\n", infostr_ssh_sock);
-                     printf ( "%s; export SSH_AGENT_PID;\n", infostr_ssh_pid);
+                     printf ("%s; export SSH_AUTH_SOCK;\n", infostr_ssh_sock);
+                     printf ("%s; export SSH_AGENT_PID;\n", infostr_ssh_pid);
                    }
                 }
+              /* Note: teh standard free is here correct.  */
               free (infostr);
              if (opt.ssh_support)
                {
@@ -1003,8 +919,8 @@ main (int argc, char **argv )
                }
               exit (0); 
             }
-          /*NEVER REACHED*/
-        } /* end parent */
+          /*NOTREACHED*/
+        } /* End parent */
 
       /* 
          This is the child
@@ -1181,6 +1097,125 @@ reread_configuration (void)
 }
 
 
+
+
+/* Create a name for the socket.  With USE_STANDARD_SOCKET given as
+   true ising STANDARD_NAME in the home directory or if given has
+   false from the mkdir type name TEMPLATE.  In the latter case a
+   unique name in a unique new directory will be created.  In both
+   cases check for valid characters as well as against a maximum
+   allowed length for a unix domain socket is done.  The function
+   terminates the process in case of an error.  Retunrs: Pointer to an
+   allcoated string with the absolute name of the socket used.  */
+static char *
+create_socket_name (int use_standard_socket,
+                   char *standard_name, char *template)
+{
+  char *name, *p;
+
+  if (use_standard_socket)
+    name = make_filename (opt.homedir, standard_name, NULL);
+  else
+    {
+      name = xstrdup (template);
+      p = strrchr (name, '/');
+      if (!p)
+       BUG ();
+      *p = 0;
+      if (!mkdtemp (name))
+       {
+         log_error (_("can't create directory `%s': %s\n"),
+                    name, strerror (errno));
+         agent_exit (2);
+       }
+      *p = '/';
+    }
+
+  if (strchr (name, PATHSEP_C))
+    {
+      log_error (("`%s' are not allowed in the socket name\n"), PATHSEP_S);
+      agent_exit (2);
+    }
+  if (strlen (name) + 1 >= DIMof (struct sockaddr_un, sun_path) )
+    {
+      log_error (_("name of socket too long\n"));
+      agent_exit (2);
+    }
+  return name;
+}
+
+
+
+/* Create a Unix domain socket with NAME.  IS_STANDARD_NAME indicates
+   whether a non-random socket is used.  Returns the filedescriptor or
+   terminates the process in case of an error. */
+static int
+create_server_socket (int is_standard_name, const char *name)
+{
+  struct sockaddr_un *serv_addr;
+  socklen_t len;
+  int fd;
+  int rc;
+
+#ifdef HAVE_W32_SYSTEM
+  fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0);
+#else
+  fd = socket (AF_UNIX, SOCK_STREAM, 0);
+#endif
+  if (fd == -1)
+    {
+      log_error (_("can't create socket: %s\n"), strerror (errno));
+      agent_exit (2);
+    }
+
+
+  memset (serv_addr, 0, sizeof *serv_addr);
+  serv_addr->sun_family = AF_UNIX;
+  assert (strlen (name) + 1 < sizeof (serv_addr->sun_path));
+  strcpy (serv_addr->sun_path, name);
+  len = (offsetof (struct sockaddr_un, sun_path)
+        + strlen (serv_addr->sun_path) + 1);
+
+#ifdef HAVE_W32_SYSTEM
+  rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len);
+  if (is_standard_name && rc == -1 )
+    {
+      remove (name);
+      rc = bind (fd, (struct sockaddr*) serv_addr, len);
+    }
+#else
+  rc = bind (fd, (struct sockaddr*) serv_addr, len);
+  if (is_standard_name && rc == -1 && errno == EADDRINUSE)
+    {
+      remove (name);
+      rc = bind (fd, (struct sockaddr*) serv_addr, len);
+    }
+#endif
+  if (rc == -1)
+    {
+      log_error (_("error binding socket to `%s': %s\n"),
+                serv_addr->sun_path, strerror (errno));
+      close (fd);
+      agent_exit (2);
+    }
+
+  if (listen (fd, 5 ) == -1)
+    {
+      log_error (_("listen() failed: %s\n"), strerror (errno));
+      close (fd);
+      agent_exit (2);
+    }
+          
+  if (opt.verbose)
+    log_info (_("listening on socket `%s'\n"), serv_addr->sun_path);
+
+  return fd;
+}
+
+
+/* Check that the directory for storing the private keys exists and
+   create it if not.  This function won't fail as it is only a
+   convenience function and not strictly necessary.  */
 static void
 create_private_keys_directory (const char *home)
 {
@@ -1218,7 +1253,7 @@ create_directories (void)
   const char *defhome = GNUPG_DEFAULT_HOMEDIR;
   char *home;
 
-  home  = make_filename (opt.homedir, NULL);
+  home = make_filename (opt.homedir, NULL);
   if ( stat (home, &statbuf) )
     {
       if (errno == ENOENT)
@@ -1248,11 +1283,11 @@ create_directories (void)
             }
         }
       else
-        log_error ("error stat-ing `%s': %s\n", home, strerror (errno));
+        log_error (_("stat() failed for `%s': %s\n"), home, strerror (errno));
     }
   else if ( !S_ISDIR(statbuf.st_mode))
     {
-      log_error ("can't use `%s' as home directory\n", home);
+      log_error (_("can't use `%s' as home directory\n"), home);
     }
   else /* exists and is a directory. */
     {
@@ -1315,13 +1350,14 @@ handle_signal (int signo)
 }
 
 
+/* This is the standard connection thread's main function.  */
 static void *
 start_connection_thread (void *arg)
 {
   int fd = (int)arg;
 
   if (opt.verbose)
-    log_info ("handler for fd %d started\n", fd);
+    log_info (_("handler for fd %d started\n"), fd);
 
   /* FIXME: Move this housekeeping into a ticker function.  Calling it
      for each connection should work but won't work anymore if our
@@ -1330,31 +1366,33 @@ start_connection_thread (void *arg)
 
   start_command_handler (-1, fd);
   if (opt.verbose)
-    log_info ("handler for fd %d terminated\n", fd);
+    log_info (_("handler for fd %d terminated\n"), fd);
   
   return NULL;
 }
 
+
+/* This is the ssh connection thread's main function.  */
 static void *
 start_connection_thread_ssh (void *arg)
 {
   int fd = (int)arg;
 
   if (opt.verbose)
-    log_info ("ssh handler for fd %d started\n", fd);
+    log_info (_("ssh handler for fd %d started\n"), fd);
 
-  /* FIXME: Move this housekeeping into a ticker function.  Calling it
-     for each connection should work but won't work anymore if our
-     cleints start to keep connections. */
   agent_trustlist_housekeeping ();
 
   start_command_handler_ssh (fd);
   if (opt.verbose)
-    log_info ("ssh handler for fd %d terminated\n", fd);
+    log_info (_("ssh handler for fd %d terminated\n"), fd);
   
   return NULL;
 }
 
+
+/* Connection handler loop.  Wait for coecntion requests and spawn a
+   thread after accepting a connection.  */
 static void
 handle_connections (int listen_fd, int listen_fd_ssh)
 {
@@ -1363,7 +1401,7 @@ handle_connections (int listen_fd, int listen_fd_ssh)
   sigset_t sigs;
   int signo;
   struct sockaddr_un paddr;
-  socklen_t plen = sizeof ( paddr );
+  socklen_t plen;
   fd_set fdset, read_fdset;
   int ret;
   int fd;
@@ -1406,74 +1444,62 @@ handle_connections (int listen_fd, int listen_fd_ssh)
           continue;
        }
 
+      /* POSIX says that fd_set should be implemented as a structure,
+         thus a simple assignment is fine to copy the entire set.  */
       read_fdset = fdset;
-      ret = pth_select (FD_SETSIZE, &read_fdset, NULL, NULL, NULL);
+
+      ret = pth_select_ev (FD_SETSIZE, &read_fdset, NULL, NULL, NULL, ev);
       if (ret == -1)
        {
-         log_error ("pth_select failed: %s - waiting 1s\n",
-                    strerror (errno));
-         pth_sleep (1);
+          log_error (_("pth_select failed: %s - waiting 1s\n"),
+                     strerror (errno));
+          pth_sleep (1);
          continue;
        }
-      
+
+      if (pth_event_occurred (ev))
+        {
+          handle_signal (signo);
+        }
 
       if (FD_ISSET (listen_fd, &read_fdset))
        {
-         fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev);
+          plen = sizeof paddr;
+         fd = pth_accept (listen_fd, (struct sockaddr *)&paddr, &plen);
          if (fd == -1)
            {
-#ifdef PTH_STATUS_OCCURRED     /* This is Pth 2 */
-             if (pth_event_status (ev) == PTH_STATUS_OCCURRED)
-#else
-               if (pth_event_occurred (ev))
-#endif
-                 {
-                   handle_signal (signo);
-                   continue;
-                 }
-             log_error ("accept failed: %s - waiting 1s\n", strerror (errno));
-             pth_sleep(1);
-             continue;
+             log_error ("accept failed: %s\n", strerror (errno));
            }
-
-         if (!pth_spawn (tattr, start_connection_thread, (void*)fd))
+          else if (!pth_spawn (tattr, start_connection_thread, (void*)fd))
            {
              log_error ("error spawning connection handler: %s\n",
                         strerror (errno) );
              close (fd);
            }
+          fd = -1;
        }
-      else if ((listen_fd_ssh != -1) && FD_ISSET (listen_fd_ssh, &read_fdset))
+
+      if (listen_fd_ssh != -1 && FD_ISSET (listen_fd_ssh, &read_fdset))
        {
-         fd = pth_accept_ev (listen_fd_ssh, (struct sockaddr *)&paddr, &plen, ev);
+          plen = sizeof paddr;
+         fd = pth_accept (listen_fd_ssh, (struct sockaddr *)&paddr, &plen);
          if (fd == -1)
            {
-#ifdef PTH_STATUS_OCCURRED     /* This is Pth 2 */
-             if (pth_event_status (ev) == PTH_STATUS_OCCURRED)
-#else
-               if (pth_event_occurred (ev))
-#endif
-                 {
-                   handle_signal (signo);
-                   continue;
-                 }
-             log_error ("accept failed: %s - waiting 1s\n", strerror (errno));
-             pth_sleep(1);
-             continue;
+             log_error ("accept failed for ssh: %s\n", strerror (errno));
            }
-
-         if (!pth_spawn (tattr, start_connection_thread_ssh, (void*)fd))
+          else if (!pth_spawn (tattr, start_connection_thread_ssh, (void*)fd))
            {
-             log_error ("error spawning connection handler: %s\n",
+             log_error ("error spawning ssh connection handler: %s\n",
                         strerror (errno) );
              close (fd);
            }
+          fd = -1;
        }
     }
 
   pth_event_free (ev, PTH_FREE_ALL);
   cleanup ();
-  log_info ("%s %s stopped\n", strusage(11), strusage(13));
+  log_info (_("%s %s stopped\n"), strusage(11), strusage(13));
 }
 #endif /*USE_GNU_PTH*/
 
@@ -1527,6 +1553,7 @@ check_for_running_agent (int mode)
   else /* MODE != 0 */
     {
       infostr = make_filename (opt.homedir, "S.gpg-agent", NULL);
+      pid = (pid_t)(-1);
     }
 
 
index 382b6da..c201b66 100644 (file)
@@ -198,4 +198,5 @@ estream_t es_tmpfile (void);
 void es_opaque_set (estream_t ES__RESTRICT stream, void *ES__RESTRICT opaque);
 void *es_opaque_get (estream_t stream);
 
-#endif
+#endif /*ESTREAM_H*/
+