* 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.
This commit is contained in:
Werner Koch 2005-02-03 17:40:02 +00:00
parent 625bafa4da
commit b326996b78
8 changed files with 728 additions and 418 deletions

140
AUTHORS
View File

@ -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.

View File

@ -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.

View 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)
@ -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 <wk@g10code.com>

View 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 --*/

View 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"
@ -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;

View 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)
%% - Replaced by a single %
%c - Replaced by the content of COMMENT.
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 description_length;
size_t description_new_length;
gpg_error_t err;
char *description_new;
unsigned int i, j;
unsigned int special;
size_t comment_length;
size_t in_len;
size_t out_len;
char *out;
size_t i;
int special, pass;
description_length = strlen (description);
description_new_length = description_length;
description_new = NULL;
comment_length = strlen (comment);
in_len = strlen (in);
/* Calculate length. */
special = 0;
for (i = 0; i < description_length; i++)
/* 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)
{
description_new_length -= 2;
switch (description[i])
{
case 'c':
/* Comment. */
description_new_length += comment_length;
break;
case '%':
description_new_length += 1;
break;
}
special = 0;
}
}
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);
}
}
/* Allocate. */
description_new = xtrymalloc (description_new_length + 1);
if (! description_new)
{
err = gpg_error_from_errno (errno);
goto out;
}
/* Fill. */
for (i = j = 0; i < description_length; i++)
{
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++;
}
}
}
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);
}

View 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");
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");
fd = create_server_socket (&serv_addr,
standard_socket, socket_name);
/* Create the sockets. */
socket_name = create_socket_name (standard_socket,
"S.gpg-agent",
"/tmp/gpg-XXXXXX/S.gpg-agent");
if (opt.ssh_support)
fd_ssh = create_server_socket (&serv_addr_ssh,
standard_socket, socket_name_ssh);
socket_name_ssh = create_socket_name (standard_socket,
"S.gpg-agent.ssh",
"/tmp/gpg-XXXXXX/S.gpg-agent.ssh");
fd = create_server_socket (standard_socket, socket_name);
if (opt.ssh_support)
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);
}

View 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*/