mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
* 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:
parent
625bafa4da
commit
b326996b78
8 changed files with 728 additions and 418 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue