From cc71376bcef00c2e2710eefe6bc4517daea1b8d5 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 5 Oct 2010 19:05:43 +0000 Subject: [PATCH] Don't set SSH_AGENTPID_INFO. Doc fixes. Allow TCP and local sockets in watchgnupg. --- agent/ChangeLog | 5 + agent/gpg-agent.c | 23 +--- doc/gpg-agent.texi | 13 +-- sm/certchain.c | 2 +- tools/ChangeLog | 8 ++ tools/watchgnupg.c | 254 +++++++++++++++++++++++++++++---------------- 6 files changed, 189 insertions(+), 116 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 16871b20f..5abcc67f2 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2010-10-05 Werner Koch + + * gpg-agent.c (main): Don't set SSH_AGENT_PID so that ssh-agent -k + won't kill out gpg-agent. + 2010-09-30 Werner Koch * gpg-agent.c (agent_exit): Run cleanup. diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index a0e018ea3..477185c49 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1054,7 +1054,7 @@ main (int argc, char **argv ) } else if (pid) { /* We are the parent */ - char *infostr, *infostr_ssh_sock, *infostr_ssh_pid; + char *infostr, *infostr_ssh_sock; /* Close the socket FD. */ close (fd); @@ -1100,13 +1100,6 @@ main (int argc, char **argv ) 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 - @@ -1130,8 +1123,6 @@ main (int argc, char **argv ) { es_fputs (infostr_ssh_sock, fp); es_putc ('\n', fp); - es_fputs (infostr_ssh_pid, fp); - es_putc ('\n', fp); } es_fclose (fp); } @@ -1154,13 +1145,6 @@ main (int argc, char **argv ) kill (pid, SIGTERM ); exit (1); } - if (opt.ssh_support && putenv (infostr_ssh_pid)) - { - log_error ("failed to set environment: %s\n", - strerror (errno) ); - kill (pid, SIGTERM ); - exit (1); - } /* Close all the file descriptors except the standard ones and those open at startup. We explicitly don't @@ -1186,8 +1170,6 @@ main (int argc, char **argv ) { *strchr (infostr_ssh_sock, '=') = ' '; es_printf ("setenv %s\n", infostr_ssh_sock); - *strchr (infostr_ssh_pid, '=') = ' '; - es_printf ("setenv %s\n", infostr_ssh_pid); } } else @@ -1197,15 +1179,12 @@ main (int argc, char **argv ) { es_printf ("%s; export SSH_AUTH_SOCK;\n", infostr_ssh_sock); - es_printf ("%s; export SSH_AGENT_PID;\n", - infostr_ssh_pid); } } xfree (infostr); if (opt.ssh_support) { xfree (infostr_ssh_sock); - xfree (infostr_ssh_pid); } exit (0); } diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 41f2efc8b..2d7f85e47 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -83,7 +83,6 @@ if [ -f "$@{HOME@}/.gpg-agent-info" ]; then . "$@{HOME@}/.gpg-agent-info" export GPG_AGENT_INFO export SSH_AUTH_SOCK - export SSH_AGENT_PID fi @end smallexample @@ -576,10 +575,13 @@ It is possible to add further flags after the @code{S} for use by the caller: @table @code + @item relax -Relax checking of some root certificate requirements. This is for -example required if the certificate is missing the basicConstraints -attribute (despite that it is a MUST for CA certificates). +@cindex relax +Relax checking of some root certificate requirements. As of now this +flag allows the use of root certificates with a missing basicConstraints +attribute (despite that it is a MUST for CA certificates) and disables +CRL checking for the root certificate. @item cm If validation of a certificate finally issued by a CA with this flag set @@ -589,7 +591,7 @@ fails, try again using the chain validation model. @item sshcontrol - +@cindex sshcontrol This file is used when support for the secure shell agent protocol has been enabled (@pxref{option --enable-ssh-support}). Only keys present in this file are used in the SSH protocol. You should backup this file. @@ -712,7 +714,6 @@ and add something like (for Bourne shells) . "$@{HOME@}/.gpg-agent-info" export GPG_AGENT_INFO export SSH_AUTH_SOCK - export SSH_AGENT_PID fi @end example @end cartouche diff --git a/sm/certchain.c b/sm/certchain.c index 40ab6a4b5..3d856fee1 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -274,7 +274,7 @@ unknown_criticals (ksba_cert_t cert, int listmode, estream_t fp) /* Check whether CERT is an allowed certificate. This requires that CERT matches all requirements for such a CA, i.e. the BasicConstraints extension. The function returns 0 on success and - the awlloed length of the chain at CHAINLEN. */ + the allowed length of the chain at CHAINLEN. */ static int allowed_ca (ctrl_t ctrl, ksba_cert_t cert, int *chainlen, int listmode, estream_t fp) diff --git a/tools/ChangeLog b/tools/ChangeLog index 93e5e1074..aad09355e 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,11 @@ +2010-10-05 Werner Koch + + * watchgnupg.c (main): Support TCP and local socket listening. + (main): Factor some code out to .. + (setup_client): this. + (err): New. + (client_list): New. + 2010-08-25 Werner Koch * gpgtar-extract.c (create_directory): Add .p7m as known diff --git a/tools/watchgnupg.c b/tools/watchgnupg.c index fe9e3d634..95726dae9 100644 --- a/tools/watchgnupg.c +++ b/tools/watchgnupg.c @@ -71,19 +71,19 @@ die (const char *format, ...) } -/* static void */ -/* err (const char *format, ...) */ -/* { */ -/* va_list arg_ptr; */ +static void +err (const char *format, ...) +{ + va_list arg_ptr; -/* fflush (stdout); */ -/* fprintf (stderr, "%s: ", PGM); */ + fflush (stdout); + fprintf (stderr, "%s: ", PGM); -/* va_start (arg_ptr, format); */ -/* vfprintf (stderr, format, arg_ptr); */ -/* va_end (arg_ptr); */ -/* putc ('\n', stderr); */ -/* } */ + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + putc ('\n', stderr); +} static void * xmalloc (size_t n) @@ -123,6 +123,10 @@ struct client_s { }; typedef struct client_s *client_t; +/* The list of all connected peers. */ +static client_t client_list; + + static void @@ -186,6 +190,57 @@ print_line (client_t c, const char *line) } +static void +setup_client (int server_fd, int is_un) +{ + struct sockaddr_un addr_un; + struct sockaddr_in addr_in; + struct sockaddr *addr; + socklen_t addrlen; + int fd; + client_t client; + + if (is_un) + { + addr = (struct sockaddr *)&addr_un; + addrlen = sizeof addr_un; + } + else + { + addr = (struct sockaddr *)&addr_in; + addrlen = sizeof addr_in; + } + + fd = accept (server_fd, addr, &addrlen); + if (fd == -1) + { + printf ("[accepting %s connection failed: %s]\n", + is_un? "local":"tcp", strerror (errno)); + } + else if (fd >= FD_SETSIZE) + { + close (fd); + printf ("[connection request denied: too many connections]\n"); + } + else + { + for (client = client_list; client && client->fd != -1; + client = client->next) + ; + if (!client) + { + client = xcalloc (1, sizeof *client); + client->next = client_list; + client_list = client; + } + client->fd = fd; + printf ("[client at fd %d connected (%s)]\n", + client->fd, is_un? "local":"tcp"); + } +} + + + static void print_version (int with_help) { @@ -197,17 +252,19 @@ print_version (int with_help) "There is NO WARRANTY, to the extent permitted by law.\n", stdout); if (with_help) - fputs ("\n" - "Usage: " PGM " [OPTIONS] SOCKETNAME|PORT\n" - "Open the local socket SOCKETNAME (or the TCP port PORT)\n" - "and display log messages\n" - "\n" - " --force delete an already existing socket file\n" - " --tcp listen on a TCP port instead of a local socket\n" - " --verbose enable extra informational output\n" - " --version print version of the program and exit\n" - " --help display this help and exit\n" - BUGREPORT_LINE, stdout ); + fputs + ("\n" + "Usage: " PGM " [OPTIONS] SOCKETNAME\n" + " " PGM " [OPTIONS] PORT [SOCKETNAME]\n" + "Open the local socket SOCKETNAME (or the TCP port PORT)\n" + "and display log messages\n" + "\n" + " --tcp listen on a TCP port and optionally on a local socket\n" + " --force delete an already existing socket file\n" + " --verbose enable extra informational output\n" + " --version print version of the program and exit\n" + " --help display this help and exit\n" + BUGREPORT_LINE, stdout ); exit (0); } @@ -221,12 +278,12 @@ main (int argc, char **argv) struct sockaddr_un srvr_addr_un; struct sockaddr_in srvr_addr_in; - struct sockaddr *srvr_addr = NULL; - socklen_t addrlen; + struct sockaddr *addr_in = NULL; + struct sockaddr *addr_un = NULL; + socklen_t addrlen_in, addrlen_un; unsigned short port; - int server; + int server_un, server_in; int flags; - client_t client_list = NULL; if (argc) { @@ -261,36 +318,70 @@ main (int argc, char **argv) } } - if (argc != 1) + if (!((!tcp && argc == 1) || (tcp && (argc == 1 || argc == 2)))) { - fprintf (stderr, "usage: " PGM " socketname\n"); + fprintf (stderr, "usage: " PGM " socketname\n" + " " PGM " --tcp port [socketname]\n"); exit (1); } - - port = tcp? atoi (*argv) : 0; - - if (verbose) + + if (tcp) { - if (tcp) - fprintf (stderr, "listening on port %hu\n", port); - else - fprintf (stderr, "opening socket `%s'\n", *argv); + port = atoi (*argv); + argc--; argv++; + } + else + { + port = 0; } setvbuf (stdout, NULL, _IOLBF, 0); - server = socket (tcp? PF_INET : PF_LOCAL, SOCK_STREAM, 0); - if (server == -1) - die ("socket() failed: %s\n", strerror (errno)); + if (tcp) + { + int i = 1; + server_in = socket (PF_INET, SOCK_STREAM, 0); + if (server_in == -1) + die ("socket(PF_INET) failed: %s\n", strerror (errno)); + if (setsockopt (server_in, SOL_SOCKET, SO_REUSEADDR, + (unsigned char *)&i, sizeof (i))) + err ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno)); + if (verbose) + fprintf (stderr, "listening on port %hu\n", port); + } + else + server_in = -1; + + if (argc) + { + server_un = socket (PF_LOCAL, SOCK_STREAM, 0); + if (server_un == -1) + die ("socket(PF_LOCAL) failed: %s\n", strerror (errno)); + if (verbose) + fprintf (stderr, "listening on socket `%s'\n", *argv); + } + else + server_un = -1; /* We better set the listening socket to non-blocking so that we don't get bitten by race conditions in accept. The should not happen for Unix Domain sockets but well, shit happens. */ - flags = fcntl (server, F_GETFL, 0); - if (flags == -1) - die ("fcntl (F_GETFL) failed: %s\n", strerror (errno)); - if ( fcntl (server, F_SETFL, (flags | O_NONBLOCK)) == -1) - die ("fcntl (F_SETFL) failed: %s\n", strerror (errno)); + if (server_in != -1) + { + flags = fcntl (server_in, F_GETFL, 0); + if (flags == -1) + die ("fcntl (F_GETFL) failed: %s\n", strerror (errno)); + if ( fcntl (server_in, F_SETFL, (flags | O_NONBLOCK)) == -1) + die ("fcntl (F_SETFL) failed: %s\n", strerror (errno)); + } + if (server_un != -1) + { + flags = fcntl (server_un, F_GETFL, 0); + if (flags == -1) + die ("fcntl (F_GETFL) failed: %s\n", strerror (errno)); + if ( fcntl (server_un, F_SETFL, (flags | O_NONBLOCK)) == -1) + die ("fcntl (F_SETFL) failed: %s\n", strerror (errno)); + } if (tcp) { @@ -298,36 +389,41 @@ main (int argc, char **argv) srvr_addr_in.sin_family = AF_INET; srvr_addr_in.sin_port = htons (port); srvr_addr_in.sin_addr.s_addr = htonl (INADDR_ANY); - srvr_addr = (struct sockaddr *)&srvr_addr_in; - addrlen = sizeof srvr_addr_in; + addr_in = (struct sockaddr *)&srvr_addr_in; + addrlen_in = sizeof srvr_addr_in; } - else + if (argc) { memset (&srvr_addr_un, 0, sizeof srvr_addr_un); srvr_addr_un.sun_family = AF_LOCAL; strncpy (srvr_addr_un.sun_path, *argv, sizeof (srvr_addr_un.sun_path)-1); srvr_addr_un.sun_path[sizeof (srvr_addr_un.sun_path) - 1] = 0; - srvr_addr = (struct sockaddr *)&srvr_addr_un; - addrlen = SUN_LEN (&srvr_addr_un); + addr_un = (struct sockaddr *)&srvr_addr_un; + addrlen_un = SUN_LEN (&srvr_addr_un); } + else + addrlen_un = 0; /* Silent gcc. */ + if (server_in != -1 && bind (server_in, addr_in, addrlen_in)) + die ("bind to port %hu failed: %s\n", port, strerror (errno)); + again: - if (bind (server, srvr_addr, addrlen)) + if (server_un != -1 && bind (server_un, addr_un, addrlen_un)) { - if (!tcp && errno == EADDRINUSE && force) + if (errno == EADDRINUSE && force) { force = 0; remove (srvr_addr_un.sun_path); goto again; } - if (tcp) - die ("bind to port %hu failed: %s\n", port, strerror (errno)); else die ("bind to `%s' failed: %s\n", *argv, strerror (errno)); } - if (listen (server, 5)) - die ("listen failed: %s\n", strerror (errno)); + if (server_in != -1 && listen (server_in, 5)) + die ("listen on inet failed: %s\n", strerror (errno)); + if (server_un != -1 && listen (server_un, 5)) + die ("listen on local failed: %s\n", strerror (errno)); for (;;) { @@ -339,8 +435,18 @@ main (int argc, char **argv) to set them allways from scratch and don't maintain an active fd_set. */ FD_ZERO (&rfds); - FD_SET (server, &rfds); - max_fd = server; + max_fd = -1; + if (server_in != -1) + { + FD_SET (server_in, &rfds); + max_fd = server_in; + } + if (server_un != -1) + { + FD_SET (server_un, &rfds); + if (server_un > max_fd) + max_fd = server_un; + } for (client = client_list; client; client = client->next) if (client->fd != -1) { @@ -352,37 +458,11 @@ main (int argc, char **argv) if (select (max_fd + 1, &rfds, NULL, NULL, NULL) <= 0) continue; /* Ignore any errors. */ - if (FD_ISSET (server, &rfds)) /* New connection. */ - { - struct sockaddr_un clnt_addr; - int fd; + if (server_in != -1 && FD_ISSET (server_in, &rfds)) + setup_client (server_in, 0); + if (server_un != -1 && FD_ISSET (server_un, &rfds)) + setup_client (server_un, 1); - addrlen = sizeof clnt_addr; - fd = accept (server, (struct sockaddr *) &clnt_addr, &addrlen); - if (fd == -1) - { - printf ("[accepting connection failed: %s]\n", strerror (errno)); - } - else if (fd >= FD_SETSIZE) - { - close (fd); - printf ("[connection request denied: too many connections]\n"); - } - else - { - for (client = client_list; client && client->fd != -1; - client = client->next) - ; - if (!client) - { - client = xcalloc (1, sizeof *client); - client->next = client_list; - client_list = client; - } - client->fd = fd; - printf ("[client at fd %d connected]\n", client->fd); - } - } for (client = client_list; client; client = client->next) if (client->fd != -1 && FD_ISSET (client->fd, &rfds)) {