mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
2005-01-26 Moritz Schulte <moritz@g10code.com>
* command-ssh.c: New file. * Makefile.am (gpg_agent_SOURCES): New source file: command-ssh.c. * findkey.c (modify_description): New function. (agent_key_from_file): Support comment field in key s-expressions. * gpg-agent.c (enum cmd_and_opt_values): New item: oSSHSupport. (opts) New entry for oSSHSupport. New variable: socket_name_ssh. (cleanup_do): New function based on cleanup(). (cleanup): Use cleanup_do() for socket_name and socket_name_ssh. (main): New switch case for oSSHSupport. (main): Move socket name creation code to ... (create_socket_name): ... this new function. (main): Use create_socket_name() for creating socket names for socket_name and for socket_name_ssh in case ssh support is enabled. Move socket creation code to ... (create_server_socket): ... this new function. (main): Use create_server_socket() for creating sockets. In case standard_socket is set, do not only store a socket name in socket_name, but also in socket_name_ssh. Generate additional environment info strings for ssh support. Pass additional ssh socket argument to handle_connections. (start_connection_thread_ssh): New function. (handle_connections): Use select to multiplex between gpg-agent and ssh-agent protocol. * agent.h (struct opt): New member: ssh_support. Declare function: start_command_handler_ssh.
This commit is contained in:
parent
6cb495ca5c
commit
a5d3f8a6e7
@ -1,3 +1,36 @@
|
|||||||
|
2005-01-26 Moritz Schulte <moritz@g10code.com>
|
||||||
|
|
||||||
|
* command-ssh.c: New file.
|
||||||
|
* Makefile.am (gpg_agent_SOURCES): New source file: command-ssh.c.
|
||||||
|
|
||||||
|
* findkey.c (modify_description): New function.
|
||||||
|
(agent_key_from_file): Support comment field in key s-expressions.
|
||||||
|
|
||||||
|
* gpg-agent.c (enum cmd_and_opt_values): New item: oSSHSupport.
|
||||||
|
(opts) New entry for oSSHSupport.
|
||||||
|
New variable: socket_name_ssh.
|
||||||
|
(cleanup_do): New function based on cleanup().
|
||||||
|
(cleanup): Use cleanup_do() for socket_name and socket_name_ssh.
|
||||||
|
(main): New switch case for oSSHSupport.
|
||||||
|
(main): Move socket name creation code to ...
|
||||||
|
(create_socket_name): ... this new function.
|
||||||
|
(main): Use create_socket_name() for creating socket names for
|
||||||
|
socket_name and for socket_name_ssh in case ssh support is
|
||||||
|
enabled.
|
||||||
|
Move socket creation code to ...
|
||||||
|
(create_server_socket): ... this new function.
|
||||||
|
(main): Use create_server_socket() for creating sockets.
|
||||||
|
In case standard_socket is set, do not only store a socket name in
|
||||||
|
socket_name, but also in socket_name_ssh.
|
||||||
|
Generate additional environment info strings for ssh support.
|
||||||
|
Pass additional ssh socket argument to handle_connections.
|
||||||
|
(start_connection_thread_ssh): New function.
|
||||||
|
(handle_connections): Use select to multiplex between gpg-agent
|
||||||
|
and ssh-agent protocol.
|
||||||
|
|
||||||
|
* agent.h (struct opt): New member: ssh_support.
|
||||||
|
Declare function: start_command_handler_ssh.
|
||||||
|
|
||||||
2005-01-04 Werner Koch <wk@g10code.com>
|
2005-01-04 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* trustlist.c (agent_marktrusted): Use "Cancel" for the first
|
* trustlist.c (agent_marktrusted): Use "Cancel" for the first
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
|
# Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||||
#
|
#
|
||||||
# This file is part of GnuPG.
|
# This file is part of GnuPG.
|
||||||
#
|
#
|
||||||
@ -29,7 +29,7 @@ AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(PTH_CFLAGS)
|
|||||||
|
|
||||||
gpg_agent_SOURCES = \
|
gpg_agent_SOURCES = \
|
||||||
gpg-agent.c agent.h \
|
gpg-agent.c agent.h \
|
||||||
command.c \
|
command.c command-ssh.c \
|
||||||
query.c \
|
query.c \
|
||||||
cache.c \
|
cache.c \
|
||||||
trans.c \
|
trans.c \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* agent.h - Global definitions for the agent
|
/* agent.h - Global definitions for the agent
|
||||||
* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
|
* Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -66,6 +66,7 @@ struct {
|
|||||||
int allow_preset_passphrase;
|
int allow_preset_passphrase;
|
||||||
int keep_tty; /* don't switch the TTY (for pinentry) on request */
|
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 keep_display; /* don't switch the DISPLAY (for pinentry) on request */
|
||||||
|
int ssh_support; /* Enable ssh-agent emulation. */
|
||||||
} opt;
|
} opt;
|
||||||
|
|
||||||
|
|
||||||
@ -136,6 +137,9 @@ void agent_init_default_ctrl (struct server_control_s *ctrl);
|
|||||||
/*-- command.c --*/
|
/*-- command.c --*/
|
||||||
void start_command_handler (int, int);
|
void start_command_handler (int, int);
|
||||||
|
|
||||||
|
/*-- command-ssh.c --*/
|
||||||
|
void start_command_handler_ssh (int);
|
||||||
|
|
||||||
/*-- findkey.c --*/
|
/*-- findkey.c --*/
|
||||||
int agent_write_private_key (const unsigned char *grip,
|
int agent_write_private_key (const unsigned char *grip,
|
||||||
const void *buffer, size_t length, int force);
|
const void *buffer, size_t length, int force);
|
||||||
|
144
agent/findkey.c
144
agent/findkey.c
@ -1,5 +1,5 @@
|
|||||||
/* findkey.c - locate the secret key
|
/* findkey.c - locate the secret key
|
||||||
* Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -140,6 +140,108 @@ try_unprotect_cb (struct pin_entry_info_s *pi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Modify a Key description, replacing certain special format
|
||||||
|
characters. List of currently supported replacements:
|
||||||
|
|
||||||
|
%% -> %
|
||||||
|
%c -> <COMMENT>. */
|
||||||
|
static int
|
||||||
|
modify_description (const char *description,
|
||||||
|
const char *comment, size_t comment_length,
|
||||||
|
char **description_modified)
|
||||||
|
{
|
||||||
|
size_t description_length;
|
||||||
|
size_t description_new_length;
|
||||||
|
gpg_error_t err;
|
||||||
|
char *description_new;
|
||||||
|
unsigned int i, j;
|
||||||
|
unsigned int special;
|
||||||
|
|
||||||
|
description_length = strlen (description);
|
||||||
|
description_new_length = description_length;
|
||||||
|
description_new = NULL;
|
||||||
|
|
||||||
|
/* Calculate length. */
|
||||||
|
special = 0;
|
||||||
|
for (i = 0; i < description_length; i++)
|
||||||
|
{
|
||||||
|
if (description[i] == '%')
|
||||||
|
special = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (special)
|
||||||
|
{
|
||||||
|
description_new_length -= 2;
|
||||||
|
switch (description[i])
|
||||||
|
{
|
||||||
|
case 'c':
|
||||||
|
/* Comment. */
|
||||||
|
description_new_length += comment_length;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '%':
|
||||||
|
description_new_length += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
special = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate. */
|
||||||
|
description_new = xtrymalloc (description_new_length + 1);
|
||||||
|
if (! description_new)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_errno (errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
|
/* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
|
||||||
should be the hex encoded keygrip of that key to be used with the
|
should be the hex encoded keygrip of that key to be used with the
|
||||||
caching mechanism. DESC_TEXT may be set to override the default
|
caching mechanism. DESC_TEXT may be set to override the default
|
||||||
@ -292,10 +394,42 @@ agent_key_from_file (CTRL ctrl, const char *desc_text,
|
|||||||
case PRIVATE_KEY_CLEAR:
|
case PRIVATE_KEY_CLEAR:
|
||||||
break; /* no unprotection needed */
|
break; /* no unprotection needed */
|
||||||
case PRIVATE_KEY_PROTECTED:
|
case PRIVATE_KEY_PROTECTED:
|
||||||
rc = unprotect (ctrl, desc_text, &buf, grip, ignore_cache);
|
{
|
||||||
if (rc)
|
gcry_sexp_t comment_sexp;
|
||||||
log_error ("failed to unprotect the secret key: %s\n",
|
size_t comment_length;
|
||||||
gpg_strerror (rc));
|
char *desc_text_final;
|
||||||
|
const char *comment;
|
||||||
|
|
||||||
|
comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
|
||||||
|
if (comment_sexp)
|
||||||
|
comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
comment = NULL;
|
||||||
|
comment_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
desc_text_final = NULL;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PRIVATE_KEY_SHADOWED:
|
case PRIVATE_KEY_SHADOWED:
|
||||||
if (shadow_info)
|
if (shadow_info)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* gpg-agent.c - The GnuPG Agent
|
/* gpg-agent.c - The GnuPG Agent
|
||||||
* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
* Copyright (C) 2000, 2001, 2002, 2003,
|
||||||
|
* 2005 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -91,7 +92,8 @@ enum cmd_and_opt_values
|
|||||||
oAllowMarkTrusted,
|
oAllowMarkTrusted,
|
||||||
oAllowPresetPassphrase,
|
oAllowPresetPassphrase,
|
||||||
oKeepTTY,
|
oKeepTTY,
|
||||||
oKeepDISPLAY
|
oKeepDISPLAY,
|
||||||
|
oSSHSupport
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -144,6 +146,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
N_("allow clients to mark keys as \"trusted\"")},
|
N_("allow clients to mark keys as \"trusted\"")},
|
||||||
{ oAllowPresetPassphrase, "allow-preset-passphrase", 0,
|
{ oAllowPresetPassphrase, "allow-preset-passphrase", 0,
|
||||||
N_("allow presetting passphrase")},
|
N_("allow presetting passphrase")},
|
||||||
|
{ oSSHSupport, "ssh-support", 0, "Enable SSH-Agent emulation" },
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -163,6 +166,9 @@ static int maybe_setuid = 1;
|
|||||||
/* Name of the communication socket */
|
/* Name of the communication socket */
|
||||||
static char *socket_name;
|
static char *socket_name;
|
||||||
|
|
||||||
|
/* Name of the communication socket used for ssh-agent-emulation. */
|
||||||
|
static char *socket_name_ssh;
|
||||||
|
|
||||||
/* Default values for options passed to the pinentry. */
|
/* Default values for options passed to the pinentry. */
|
||||||
static char *default_display;
|
static char *default_display;
|
||||||
static char *default_ttyname;
|
static char *default_ttyname;
|
||||||
@ -183,7 +189,7 @@ static char *current_logfile;
|
|||||||
/* Local prototypes. */
|
/* Local prototypes. */
|
||||||
static void create_directories (void);
|
static void create_directories (void);
|
||||||
#ifdef USE_GNU_PTH
|
#ifdef USE_GNU_PTH
|
||||||
static void handle_connections (int listen_fd);
|
static void handle_connections (int listen_fd, int listen_fd_ssh);
|
||||||
/* Pth wrapper function definitions. */
|
/* Pth wrapper function definitions. */
|
||||||
GCRY_THREAD_OPTION_PTH_IMPL;
|
GCRY_THREAD_OPTION_PTH_IMPL;
|
||||||
#endif /*USE_GNU_PTH*/
|
#endif /*USE_GNU_PTH*/
|
||||||
@ -297,22 +303,29 @@ set_debug (void)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cleanup (void)
|
cleanup_do (char *name)
|
||||||
{
|
{
|
||||||
if (socket_name && *socket_name)
|
if (name && *name)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
remove (socket_name);
|
remove (name);
|
||||||
p = strrchr (socket_name, '/');
|
p = strrchr (name, '/');
|
||||||
if (p)
|
if (p)
|
||||||
{
|
{
|
||||||
*p = 0;
|
*p = 0;
|
||||||
rmdir (socket_name);
|
rmdir (name);
|
||||||
*p = '/';
|
*p = '/';
|
||||||
}
|
}
|
||||||
*socket_name = 0;
|
*name = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cleanup (void)
|
||||||
|
{
|
||||||
|
cleanup_do (socket_name);
|
||||||
|
cleanup_do (socket_name_ssh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -404,6 +417,105 @@ 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
|
int
|
||||||
main (int argc, char **argv )
|
main (int argc, char **argv )
|
||||||
{
|
{
|
||||||
@ -596,6 +708,12 @@ main (int argc, char **argv )
|
|||||||
case oKeepTTY: opt.keep_tty = 1; break;
|
case oKeepTTY: opt.keep_tty = 1; break;
|
||||||
case oKeepDISPLAY: opt.keep_display = 1; break;
|
case oKeepDISPLAY: opt.keep_display = 1; break;
|
||||||
|
|
||||||
|
case oSSHSupport:
|
||||||
|
opt.ssh_support = 1;
|
||||||
|
opt.keep_tty = 1;
|
||||||
|
opt.keep_display = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
default : pargs.err = configfp? 1:2; break;
|
default : pargs.err = configfp? 1:2; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -745,11 +863,10 @@ main (int argc, char **argv )
|
|||||||
else
|
else
|
||||||
{ /* Regular server mode */
|
{ /* Regular server mode */
|
||||||
int fd;
|
int fd;
|
||||||
int rc;
|
int fd_ssh;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int len;
|
|
||||||
struct sockaddr_un serv_addr;
|
struct sockaddr_un serv_addr;
|
||||||
char *p;
|
struct sockaddr_un serv_addr_ssh;
|
||||||
|
|
||||||
/* Remove the DISPLAY variable so that a pinentry does not
|
/* Remove the DISPLAY variable so that a pinentry does not
|
||||||
default to a specific display. There is still a default
|
default to a specific display. There is still a default
|
||||||
@ -761,90 +878,26 @@ main (int argc, char **argv )
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Create the socket name . */
|
/* Create the socket name . */
|
||||||
if (standard_socket)
|
create_socket_name (&socket_name, standard_socket, &serv_addr,
|
||||||
socket_name = make_filename (opt.homedir, "S.gpg-agent", NULL);
|
"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);
|
||||||
|
if (opt.ssh_support)
|
||||||
|
fd_ssh = create_server_socket (&serv_addr_ssh,
|
||||||
|
standard_socket, socket_name_ssh);
|
||||||
else
|
else
|
||||||
{
|
/* Make the compiler happy. */
|
||||||
socket_name = xstrdup ("/tmp/gpg-XXXXXX/S.gpg-agent");
|
fd_ssh = -1;
|
||||||
p = strrchr (socket_name, '/');
|
|
||||||
if (!p)
|
|
||||||
BUG ();
|
|
||||||
*p = 0;;
|
|
||||||
if (!mkdtemp(socket_name))
|
|
||||||
{
|
|
||||||
log_error (_("can't create directory `%s': %s\n"),
|
|
||||||
socket_name, strerror(errno) );
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
*p = '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strchr (socket_name, PATHSEP_C) )
|
|
||||||
{
|
|
||||||
log_error ("`%s' are not allowed in the socket name\n", PATHSEP_S);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path )
|
|
||||||
{
|
|
||||||
log_error ("name of socket too long\n");
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#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, socket_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 (socket_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 (socket_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 );
|
|
||||||
|
|
||||||
|
|
||||||
fflush (NULL);
|
fflush (NULL);
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
pid = getpid ();
|
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);
|
||||||
|
printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid);
|
||||||
#else /*!HAVE_W32_SYSTEM*/
|
#else /*!HAVE_W32_SYSTEM*/
|
||||||
pid = fork ();
|
pid = fork ();
|
||||||
if (pid == (pid_t)-1)
|
if (pid == (pid_t)-1)
|
||||||
@ -854,7 +907,7 @@ main (int argc, char **argv )
|
|||||||
}
|
}
|
||||||
else if (pid)
|
else if (pid)
|
||||||
{ /* We are the parent */
|
{ /* We are the parent */
|
||||||
char *infostr;
|
char *infostr, *infostr_ssh_sock, *infostr_ssh_pid;
|
||||||
|
|
||||||
close (fd);
|
close (fd);
|
||||||
|
|
||||||
@ -866,8 +919,29 @@ main (int argc, char **argv )
|
|||||||
kill (pid, SIGTERM);
|
kill (pid, SIGTERM);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
if (opt.ssh_support)
|
||||||
|
{
|
||||||
|
if (asprintf (&infostr_ssh_sock, "SSH_AUTH_SOCK=%s",
|
||||||
|
socket_name_ssh) < 0)
|
||||||
|
{
|
||||||
|
log_error ("out of core\n");
|
||||||
|
kill (pid, SIGTERM);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
if (asprintf (&infostr_ssh_pid, "SSH_AGENT_PID=%u",
|
||||||
|
pid) < 0)
|
||||||
|
{
|
||||||
|
log_error ("out of core\n");
|
||||||
|
kill (pid, SIGTERM);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*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 */
|
the child should do this from now on */
|
||||||
|
if (opt.ssh_support)
|
||||||
|
*socket_name_ssh = 0;
|
||||||
|
|
||||||
if (argc)
|
if (argc)
|
||||||
{ /* run the program given on the commandline */
|
{ /* run the program given on the commandline */
|
||||||
if (putenv (infostr))
|
if (putenv (infostr))
|
||||||
@ -877,6 +951,20 @@ main (int argc, char **argv )
|
|||||||
kill (pid, SIGTERM );
|
kill (pid, SIGTERM );
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
if (putenv (infostr_ssh_sock))
|
||||||
|
{
|
||||||
|
log_error ("failed to set environment: %s\n",
|
||||||
|
strerror (errno) );
|
||||||
|
kill (pid, SIGTERM );
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
if (putenv (infostr_ssh_pid))
|
||||||
|
{
|
||||||
|
log_error ("failed to set environment: %s\n",
|
||||||
|
strerror (errno) );
|
||||||
|
kill (pid, SIGTERM );
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
execvp (argv[0], argv);
|
execvp (argv[0], argv);
|
||||||
log_error ("failed to run the command: %s\n", strerror (errno));
|
log_error ("failed to run the command: %s\n", strerror (errno));
|
||||||
kill (pid, SIGTERM);
|
kill (pid, SIGTERM);
|
||||||
@ -890,12 +978,29 @@ main (int argc, char **argv )
|
|||||||
{
|
{
|
||||||
*strchr (infostr, '=') = ' ';
|
*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);
|
||||||
|
*strchr (infostr_ssh_pid, '=') = ' ';
|
||||||
|
printf ( "setenv %s\n", infostr_ssh_pid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf ( "%s; export GPG_AGENT_INFO;\n", infostr);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free (infostr);
|
free (infostr);
|
||||||
|
if (opt.ssh_support)
|
||||||
|
{
|
||||||
|
free (infostr_ssh_sock);
|
||||||
|
free (infostr_ssh_pid);
|
||||||
|
}
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
/*NEVER REACHED*/
|
/*NEVER REACHED*/
|
||||||
@ -949,7 +1054,7 @@ main (int argc, char **argv )
|
|||||||
sa.sa_flags = 0;
|
sa.sa_flags = 0;
|
||||||
sigaction (SIGPIPE, &sa, NULL);
|
sigaction (SIGPIPE, &sa, NULL);
|
||||||
#endif
|
#endif
|
||||||
handle_connections (fd);
|
handle_connections (fd, opt.ssh_support ? fd_ssh : -1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif /*!USE_GNU_PTH*/
|
#endif /*!USE_GNU_PTH*/
|
||||||
@ -1230,16 +1335,37 @@ start_connection_thread (void *arg)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_connections (int listen_fd)
|
handle_connections (int listen_fd, int listen_fd_ssh)
|
||||||
{
|
{
|
||||||
pth_attr_t tattr;
|
pth_attr_t tattr;
|
||||||
pth_event_t ev;
|
pth_event_t ev;
|
||||||
sigset_t sigs;
|
sigset_t sigs;
|
||||||
int signo;
|
int signo;
|
||||||
struct sockaddr_un paddr;
|
struct sockaddr_un paddr;
|
||||||
socklen_t plen = sizeof( paddr );
|
socklen_t plen = sizeof ( paddr );
|
||||||
|
fd_set fdset, read_fdset;
|
||||||
|
int ret;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
tattr = pth_attr_new();
|
tattr = pth_attr_new();
|
||||||
@ -1259,6 +1385,11 @@ handle_connections (int listen_fd)
|
|||||||
ev = NULL;
|
ev = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
FD_ZERO (&fdset);
|
||||||
|
FD_SET (listen_fd, &fdset);
|
||||||
|
if (listen_fd_ssh != -1)
|
||||||
|
FD_SET (listen_fd_ssh, &fdset);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (shutdown_pending)
|
if (shutdown_pending)
|
||||||
@ -1275,28 +1406,68 @@ handle_connections (int listen_fd)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev);
|
read_fdset = fdset;
|
||||||
if (fd == -1)
|
ret = pth_select (FD_SETSIZE, &read_fdset, NULL, NULL, NULL);
|
||||||
{
|
if (ret == -1)
|
||||||
#ifdef PTH_STATUS_OCCURRED /* This is Pth 2 */
|
{
|
||||||
if (pth_event_status (ev) == PTH_STATUS_OCCURRED)
|
log_error ("pth_select failed: %s - waiting 1s\n",
|
||||||
#else
|
strerror (errno));
|
||||||
if (pth_event_occurred (ev))
|
pth_sleep (1);
|
||||||
#endif
|
continue;
|
||||||
{
|
|
||||||
handle_signal (signo);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
log_error ("accept failed: %s - waiting 1s\n", strerror (errno));
|
|
||||||
pth_sleep(1);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!pth_spawn (tattr, start_connection_thread, (void*)fd))
|
if (FD_ISSET (listen_fd, &read_fdset))
|
||||||
{
|
{
|
||||||
log_error ("error spawning connection handler: %s\n",
|
fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev);
|
||||||
strerror (errno) );
|
if (fd == -1)
|
||||||
close (fd);
|
{
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pth_spawn (tattr, start_connection_thread, (void*)fd))
|
||||||
|
{
|
||||||
|
log_error ("error spawning connection handler: %s\n",
|
||||||
|
strerror (errno) );
|
||||||
|
close (fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((listen_fd_ssh != -1) && FD_ISSET (listen_fd_ssh, &read_fdset))
|
||||||
|
{
|
||||||
|
fd = pth_accept_ev (listen_fd_ssh, (struct sockaddr *)&paddr, &plen, ev);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pth_spawn (tattr, start_connection_thread_ssh, (void*)fd))
|
||||||
|
{
|
||||||
|
log_error ("error spawning connection handler: %s\n",
|
||||||
|
strerror (errno) );
|
||||||
|
close (fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user