diff --git a/AUTHORS b/AUTHORS index e69de29bb..0de6a8662 100644 --- a/AUTHORS +++ b/AUTHORS @@ -0,0 +1,140 @@ +Program: GnuPG +Maintainer: Werner Koch +Bug reports: +Security related bug reports: + +Please note that this file is for the 1.9 branch of GnuPG. + + +Authors +======= + +Ales Nyakhaychyk Translations [be] + +Birger Langkjer Translations [da] + +Maxim Britov Translations [ru] + +Daniel Resare Translations [sv] +Per Tunedal Translations [sv] + +David Shaw Assigns past and future changes. + (all in keyserver/, + a lot of changes in g10/ see the ChangeLog, + bug fixes here and there) + +Dokianakis Theofanis Translations [el] + +Edmund GRIMLEY EVANS Translations [eo] + +Florian Weimer Assigns past and future changes + (changed:g10/parse-packet.c, include/iobuf.h, util/iobuf.c) + +g10 Code GmbH Assigns past and future changes + (all work since 2001 as indicated by mail addresses in ChangeLogs) + +Gaël Quéri Translations [fr] + (fixed a lot of typos) + +Gregory Steuck Translations [ru] + +Nagy Ferenc László Translations [hu] + +Ivo Timmermans Translations [nl] + +Jacobo Tarri'o Barreiro Translations [gl] + +Janusz Aleksander Urbanowicz Translations [po] + +Jedi Lin Translations [zh-tw] + +Jouni Hiltunen Translations [fi] +Tommi Vainikainen Translations [fi] + +Laurentiu Buzdugan Translations [ro] + +Magda Procha'zkova' Translations [cs] + +Michael Roth Assigns changes. + (wrote cipher/des.c., changes and bug fixes all over the place) + +Michal Majer Translations [sk] + +Marco d'Itri Translations [it] + +Marcus Brinkmann + (gpgconf and fixes all over the place) + +Matthew Skala Disclaimer + (wrote cipher/twofish.c) + +Moritz Schulte + (ssh support gpg-agent) + +Niklas Hernaeus Disclaimer + (weak key patches) + +Nilgun Belma Buguner Translations [tr] + +Nils Ellmenreich + Assigns past and future changes + (configure.in, cipher/rndlinux.c, FAQ) + +Paul Eggert + (configuration macros for LFS) + +Pavel I. Shajdo Translations [ru] + (man pages) + +Pedro Morais Translations [pt_PT] + +Rémi Guyomarch 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 Assigns past and future changes. + (All patches to support RISC OS) + +Timo Schulz Assigns past and future changes. + (util/w32reg.c, g10/passphrase.c, g10/hkp.c) + +Tedi Heriyanto Translations [id] + +Thiago Jung Bauermann Translations [pt_BR] +Rafael Caetano dos Santos Translations [pt_BR] + +Toomas Soome Translations [et] + +Urko Lusa Translations [es_ES] + +Walter Koch Translations [de] + +Werner Koch 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 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 + + * AUTHORS: Copied from 1.4 and edited to refelct the changes in + 1.9. + 2005-01-17 Werner Koch * 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 + + * 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 * 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 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 -#include + #include #include #include @@ -33,9 +33,8 @@ #include "agent.h" -#include - #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 -> . */ -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); } 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"); - 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: :: */ + /* Create the info string: :: */ 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*/ +