mirror of
git://git.gnupg.org/gnupg.git
synced 2025-02-01 16:33:02 +01:00
scd: Implement socket redirection.
* scd/scdaemon.c (ENAMETOOLONG): New. (redir_socket_name): New. (cleanup): Take care of a redirected socket. (main): Pass redir_socket_name to create_server_socket. (create_socket_name): Remove superfluous length check. (create_server_socket): Add arg r_redir_name and implement redirection. Replace assert for older Assuan by an error message. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
eede0e59bf
commit
2f90b7c21b
@ -1525,8 +1525,8 @@ create_socket_name (char *standard_name, int with_homedir)
|
|||||||
/* Create a Unix domain socket with NAME. Returns the file descriptor
|
/* Create a Unix domain socket with NAME. Returns the file descriptor
|
||||||
or terminates the process in case of an error. Note that this
|
or terminates the process in case of an error. Note that this
|
||||||
function needs to be used for the regular socket first (indicated
|
function needs to be used for the regular socket first (indicated
|
||||||
by PRIMARY) and only then for the extra and the ssh sockets. if
|
by PRIMARY) and only then for the extra and the ssh sockets. If
|
||||||
the soecket has been redirected the name of the real socket is
|
the socket has been redirected the name of the real socket is
|
||||||
stored as a malloced string at R_REDIR_NAME. */
|
stored as a malloced string at R_REDIR_NAME. */
|
||||||
static gnupg_fd_t
|
static gnupg_fd_t
|
||||||
create_server_socket (char *name, int primary,
|
create_server_socket (char *name, int primary,
|
||||||
|
@ -55,6 +55,9 @@
|
|||||||
#include "asshelp.h"
|
#include "asshelp.h"
|
||||||
#include "../common/init.h"
|
#include "../common/init.h"
|
||||||
|
|
||||||
|
#ifndef ENAMETOOLONG
|
||||||
|
# define ENAMETOOLONG EINVAL
|
||||||
|
#endif
|
||||||
|
|
||||||
enum cmd_and_opt_values
|
enum cmd_and_opt_values
|
||||||
{ aNull = 0,
|
{ aNull = 0,
|
||||||
@ -194,6 +197,8 @@ static int pipe_server;
|
|||||||
|
|
||||||
/* Name of the communication socket */
|
/* Name of the communication socket */
|
||||||
static char *socket_name;
|
static char *socket_name;
|
||||||
|
/* Name of the redirected socket or NULL. */
|
||||||
|
static char *redir_socket_name;
|
||||||
|
|
||||||
/* We need to keep track of the server's nonces (these are dummies for
|
/* We need to keep track of the server's nonces (these are dummies for
|
||||||
POSIX systems). */
|
POSIX systems). */
|
||||||
@ -207,6 +212,7 @@ static int ticker_disabled;
|
|||||||
|
|
||||||
static char *create_socket_name (char *standard_name);
|
static char *create_socket_name (char *standard_name);
|
||||||
static gnupg_fd_t create_server_socket (const char *name,
|
static gnupg_fd_t create_server_socket (const char *name,
|
||||||
|
char **r_redir_name,
|
||||||
assuan_sock_nonce_t *nonce);
|
assuan_sock_nonce_t *nonce);
|
||||||
|
|
||||||
static void *start_connection_thread (void *arg);
|
static void *start_connection_thread (void *arg);
|
||||||
@ -357,14 +363,17 @@ cleanup (void)
|
|||||||
{
|
{
|
||||||
if (socket_name && *socket_name)
|
if (socket_name && *socket_name)
|
||||||
{
|
{
|
||||||
|
char *name;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
remove (socket_name);
|
name = redir_socket_name? redir_socket_name : socket_name;
|
||||||
p = strrchr (socket_name, '/');
|
|
||||||
|
gnupg_remove (name);
|
||||||
|
p = strrchr (name, '/');
|
||||||
if (p)
|
if (p)
|
||||||
{
|
{
|
||||||
*p = 0;
|
*p = 0;
|
||||||
rmdir (socket_name);
|
rmdir (name);
|
||||||
*p = '/';
|
*p = '/';
|
||||||
}
|
}
|
||||||
*socket_name = 0;
|
*socket_name = 0;
|
||||||
@ -736,7 +745,8 @@ main (int argc, char **argv )
|
|||||||
if (multi_server)
|
if (multi_server)
|
||||||
{
|
{
|
||||||
socket_name = create_socket_name (SCDAEMON_SOCK_NAME);
|
socket_name = create_socket_name (SCDAEMON_SOCK_NAME);
|
||||||
fd = FD2INT(create_server_socket (socket_name, &socket_nonce));
|
fd = FD2INT(create_server_socket (socket_name,
|
||||||
|
&redir_socket_name, &socket_nonce));
|
||||||
}
|
}
|
||||||
|
|
||||||
res = npth_attr_init (&tattr);
|
res = npth_attr_init (&tattr);
|
||||||
@ -788,7 +798,8 @@ main (int argc, char **argv )
|
|||||||
|
|
||||||
/* Create the socket. */
|
/* Create the socket. */
|
||||||
socket_name = create_socket_name (SCDAEMON_SOCK_NAME);
|
socket_name = create_socket_name (SCDAEMON_SOCK_NAME);
|
||||||
fd = FD2INT (create_server_socket (socket_name, &socket_nonce));
|
fd = FD2INT (create_server_socket (socket_name,
|
||||||
|
&redir_socket_name, &socket_nonce));
|
||||||
|
|
||||||
|
|
||||||
fflush (NULL);
|
fflush (NULL);
|
||||||
@ -1025,26 +1036,28 @@ create_socket_name (char *standard_name)
|
|||||||
log_error (("'%s' are not allowed in the socket name\n"), PATHSEP_S);
|
log_error (("'%s' are not allowed in the socket name\n"), PATHSEP_S);
|
||||||
scd_exit (2);
|
scd_exit (2);
|
||||||
}
|
}
|
||||||
if (strlen (name) + 1 >= DIMof (struct sockaddr_un, sun_path) )
|
|
||||||
{
|
|
||||||
log_error (_("name of socket too long\n"));
|
|
||||||
scd_exit (2);
|
|
||||||
}
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Create a Unix domain socket with NAME. Returns the file descriptor
|
/* Create a Unix domain socket with NAME. Returns the file descriptor
|
||||||
or terminates the process in case of an error. */
|
or terminates the process in case of an error. If the socket has
|
||||||
|
been redirected the name of the real socket is stored as a malloced
|
||||||
|
string at R_REDIR_NAME. */
|
||||||
static gnupg_fd_t
|
static gnupg_fd_t
|
||||||
create_server_socket (const char *name, assuan_sock_nonce_t *nonce)
|
create_server_socket (const char *name, char **r_redir_name,
|
||||||
|
assuan_sock_nonce_t *nonce)
|
||||||
{
|
{
|
||||||
struct sockaddr_un *serv_addr;
|
struct sockaddr *addr;
|
||||||
|
struct sockaddr_un *unaddr;
|
||||||
socklen_t len;
|
socklen_t len;
|
||||||
gnupg_fd_t fd;
|
gnupg_fd_t fd;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
xfree (*r_redir_name);
|
||||||
|
*r_redir_name = NULL;
|
||||||
|
|
||||||
fd = assuan_sock_new (AF_UNIX, SOCK_STREAM, 0);
|
fd = assuan_sock_new (AF_UNIX, SOCK_STREAM, 0);
|
||||||
if (fd == GNUPG_INVALID_FD)
|
if (fd == GNUPG_INVALID_FD)
|
||||||
{
|
{
|
||||||
@ -1052,26 +1065,55 @@ create_server_socket (const char *name, assuan_sock_nonce_t *nonce)
|
|||||||
scd_exit (2);
|
scd_exit (2);
|
||||||
}
|
}
|
||||||
|
|
||||||
serv_addr = xmalloc (sizeof (*serv_addr));
|
unaddr = xmalloc (sizeof (*unaddr));
|
||||||
memset (serv_addr, 0, sizeof *serv_addr);
|
addr = (struct sockaddr*)unaddr;
|
||||||
serv_addr->sun_family = AF_UNIX;
|
|
||||||
assert (strlen (name) + 1 < sizeof (serv_addr->sun_path));
|
|
||||||
strcpy (serv_addr->sun_path, name);
|
|
||||||
len = SUN_LEN (serv_addr);
|
|
||||||
|
|
||||||
rc = assuan_sock_bind (fd, (struct sockaddr*) serv_addr, len);
|
#if ASSUAN_VERSION_NUMBER >= 0x020104 /* >= 2.1.4 */
|
||||||
|
{
|
||||||
|
int redirected;
|
||||||
|
|
||||||
|
if (assuan_sock_set_sockaddr_un (name, addr, &redirected))
|
||||||
|
{
|
||||||
|
if (errno == ENAMETOOLONG)
|
||||||
|
log_error (_("socket name '%s' is too long\n"), name);
|
||||||
|
else
|
||||||
|
log_error ("error preparing socket '%s': %s\n",
|
||||||
|
name, gpg_strerror (gpg_error_from_syserror ()));
|
||||||
|
scd_exit (2);
|
||||||
|
}
|
||||||
|
if (redirected)
|
||||||
|
{
|
||||||
|
*r_redir_name = xstrdup (unaddr->sun_path);
|
||||||
|
if (opt.verbose)
|
||||||
|
log_info ("redirecting socket '%s' to '%s'\n", name, *r_redir_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else /* Assuan < 2.1.4 */
|
||||||
|
memset (unaddr, 0, sizeof *unaddr);
|
||||||
|
unaddr->sun_family = AF_UNIX;
|
||||||
|
if (strlen (name) + 1 >= sizeof (unaddr->sun_path))
|
||||||
|
{
|
||||||
|
log_error (_("socket name '%s' is too long\n"), name);
|
||||||
|
scd_exit (2);
|
||||||
|
}
|
||||||
|
strcpy (unaddr->sun_path, name);
|
||||||
|
#endif /* Assuan < 2.1.4 */
|
||||||
|
|
||||||
|
len = SUN_LEN (unaddr);
|
||||||
|
|
||||||
|
rc = assuan_sock_bind (fd, addr, len);
|
||||||
if (rc == -1 && errno == EADDRINUSE)
|
if (rc == -1 && errno == EADDRINUSE)
|
||||||
{
|
{
|
||||||
remove (name);
|
gnupg_remove (unaddr->sun_path);
|
||||||
rc = assuan_sock_bind (fd, (struct sockaddr*) serv_addr, len);
|
rc = assuan_sock_bind (fd, addr, len);
|
||||||
}
|
}
|
||||||
if (rc != -1
|
if (rc != -1
|
||||||
&& (rc=assuan_sock_get_nonce ((struct sockaddr*)serv_addr, len, nonce)))
|
&& (rc=assuan_sock_get_nonce (addr, len, nonce)))
|
||||||
log_error (_("error getting nonce for the socket\n"));
|
log_error (_("error getting nonce for the socket\n"));
|
||||||
if (rc == -1)
|
if (rc == -1)
|
||||||
{
|
{
|
||||||
log_error (_("error binding socket to '%s': %s\n"),
|
log_error (_("error binding socket to '%s': %s\n"),
|
||||||
serv_addr->sun_path,
|
unaddr->sun_path,
|
||||||
gpg_strerror (gpg_error_from_syserror ()));
|
gpg_strerror (gpg_error_from_syserror ()));
|
||||||
assuan_sock_close (fd);
|
assuan_sock_close (fd);
|
||||||
scd_exit (2);
|
scd_exit (2);
|
||||||
@ -1086,7 +1128,7 @@ create_server_socket (const char *name, assuan_sock_nonce_t *nonce)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
log_info (_("listening on socket '%s'\n"), serv_addr->sun_path);
|
log_info (_("listening on socket '%s'\n"), unaddr->sun_path);
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user