aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2005-02-03 17:40:02 +0000
committerWerner Koch <[email protected]>2005-02-03 17:40:02 +0000
commitb326996b784b561ab56af5b41037f60ae8a79849 (patch)
tree01ced87c39b865a5cb754985217c6692f5fa3097
parentForgot to commit the recent fixed to scd and logging - doing it now (diff)
downloadgnupg-b326996b784b561ab56af5b41037f60ae8a79849.tar.gz
gnupg-b326996b784b561ab56af5b41037f60ae8a79849.zip
* AUTHORS: Copied from 1.4 and edited to refelct the changes in
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.
Diffstat (limited to '')
-rw-r--r--AUTHORS140
-rw-r--r--ChangeLog5
-rw-r--r--agent/ChangeLog36
-rw-r--r--agent/agent.h30
-rw-r--r--agent/command-ssh.c351
-rw-r--r--agent/findkey.c200
-rw-r--r--agent/gpg-agent.c383
-rw-r--r--common/estream.h3
8 files changed, 729 insertions, 419 deletions
diff --git a/AUTHORS b/AUTHORS
index e69de29bb..0de6a8662 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -0,0 +1,140 @@
+Program: GnuPG
+Maintainer: Werner Koch <[email protected]>
+Bug reports: <[email protected]>
+Security related bug reports: <[email protected]>
+
+Please note that this file is for the 1.9 branch of GnuPG.
+
+
+Authors
+=======
+
+Ales Nyakhaychyk <[email protected]> Translations [be]
+
+Birger Langkjer <[email protected]> Translations [da]
+
+Maxim Britov <[email protected]> Translations [ru]
+
+Daniel Resare <[email protected]> Translations [sv]
+Per Tunedal <[email protected]> Translations [sv]
+
+David Shaw <[email protected]> Assigns past and future changes.
+ (all in keyserver/,
+ a lot of changes in g10/ see the ChangeLog,
+ bug fixes here and there)
+
+Dokianakis Theofanis <[email protected]> Translations [el]
+
+Edmund GRIMLEY EVANS <[email protected]> Translations [eo]
+
+Florian Weimer <[email protected]> Assigns past and future changes
+ (changed:g10/parse-packet.c, include/iobuf.h, util/iobuf.c)
+
+g10 Code GmbH <[email protected]> Assigns past and future changes
+ (all work since 2001 as indicated by mail addresses in ChangeLogs)
+
+Gaël Quéri <[email protected]> Translations [fr]
+ (fixed a lot of typos)
+
+Gregory Steuck <[email protected]> Translations [ru]
+
+Nagy Ferenc László <[email protected]> Translations [hu]
+
+Ivo Timmermans <[email protected]> Translations [nl]
+
+Jacobo Tarri'o Barreiro <[email protected]> Translations [gl]
+
+Janusz Aleksander Urbanowicz <[email protected]> Translations [po]
+
+Jedi Lin <[email protected]> Translations [zh-tw]
+
+Jouni Hiltunen <[email protected]> Translations [fi]
+Tommi Vainikainen <[email protected]> Translations [fi]
+
+Laurentiu Buzdugan <[email protected]> Translations [ro]
+
+Magda Procha'zkova' <[email protected]> Translations [cs]
+
+Michael Roth <[email protected]> Assigns changes.
+ (wrote cipher/des.c., changes and bug fixes all over the place)
+
+Michal Majer <[email protected]> Translations [sk]
+
+Marco d'Itri <[email protected]> Translations [it]
+
+Marcus Brinkmann <[email protected]>
+ (gpgconf and fixes all over the place)
+
+Matthew Skala <[email protected]> Disclaimer
+ (wrote cipher/twofish.c)
+
+Moritz Schulte <[email protected]>
+ (ssh support gpg-agent)
+
+Niklas Hernaeus <[email protected]> Disclaimer
+ (weak key patches)
+
+Nilgun Belma Buguner <[email protected]> Translations [tr]
+
+Nils Ellmenreich <nils 'at' infosun.fmi.uni-passau.de>
+ Assigns past and future changes
+ (configure.in, cipher/rndlinux.c, FAQ)
+
+Paul Eggert <[email protected]>
+ (configuration macros for LFS)
+
+Pavel I. Shajdo <[email protected]> Translations [ru]
+ (man pages)
+
+Pedro Morais <[email protected]> Translations [pt_PT]
+
+Rémi Guyomarch <[email protected]> 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 <[email protected]> Assigns past and future changes.
+ (All patches to support RISC OS)
+
+Timo Schulz <[email protected]> Assigns past and future changes.
+ (util/w32reg.c, g10/passphrase.c, g10/hkp.c)
+
+Tedi Heriyanto <[email protected]> Translations [id]
+
+Thiago Jung Bauermann <[email protected]> Translations [pt_BR]
+Rafael Caetano dos Santos <[email protected]> Translations [pt_BR]
+
+Toomas Soome <[email protected]> Translations [et]
+
+Urko Lusa <[email protected]> Translations [es_ES]
+
+Walter Koch <[email protected]> Translations [de]
+
+Werner Koch <[email protected]> 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 <[email protected]> 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.
+
diff --git a/ChangeLog b/ChangeLog
index f878f60d8..2c86f42a8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2005-02-03 Werner Koch <[email protected]>
+
+ * AUTHORS: Copied from 1.4 and edited to refelct the changes in
+ 1.9.
+
2005-01-17 Werner Koch <[email protected]>
* configure.ac: Make --without-included-regex work as expected.
diff --git a/agent/ChangeLog b/agent/ChangeLog
index bf3ffe824..3bd779256 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,3 +1,37 @@
+2005-02-03 Werner Koch <[email protected]>
+
+ * 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 <[email protected]>
* command-ssh.c (ssh_handler_request_identities)
@@ -67,7 +101,7 @@
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 <[email protected]>
diff --git a/agent/agent.h b/agent/agent.h
index 8afda6463..a1196bc0b 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -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 --*/
diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index db0e8daa9..390bfe92a 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -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"
@@ -59,26 +58,31 @@
#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)
+
+
+
/* 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
+ },
+ };
+
+
+
+
+
+
-/* 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;
}
+
-/* 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
- },
- };
-
-
-
-/* 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,
-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;
-}
-
-
-
-/* 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)
-/* 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)
- };
-
-
-
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;
diff --git a/agent/findkey.c b/agent/findkey.c
index d39d3aae3..896cb880e 100644
--- a/agent/findkey.c
+++ b/agent/findkey.c
@@ -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);
}
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 9f97fb6d7..d8b891e5f 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -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);
}
diff --git a/common/estream.h b/common/estream.h
index 382b6da84..c201b666a 100644
--- a/common/estream.h
+++ b/common/estream.h
@@ -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*/
+