diff --git a/ChangeLog b/ChangeLog index 433b50de1..c0cf51f0e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-08-09 Werner Koch + + * configure.ac (inet_pton): Check for it. + 2010-08-05 Werner Koch * configure.ac (AH_BOTTOM): Remove HTTP_USE_ESTREAM. diff --git a/agent/ChangeLog b/agent/ChangeLog index c4aa1c299..a9b67a80a 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2010-08-09 Werner Koch + + * Makefile.am (t_common_ldadd): Add NETLIBS for sake of the TCP + logging. + 2010-06-24 Werner Koch * genkey.c (check_passphrase_pattern): Use HANG option for diff --git a/agent/Makefile.am b/agent/Makefile.am index e22153681..abd39bed8 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -105,8 +105,8 @@ $(PROGRAMS): $(common_libs) $(commonpth_libs) $(pwquery_libs) # TESTS = t-protect -t_common_ldadd = $(common_libs) \ - $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV) +t_common_ldadd = $(common_libs) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \ + $(LIBINTL) $(LIBICONV) $(NETLIBS) t_protect_SOURCES = t-protect.c protect.c t_protect_LDADD = $(t_common_ldadd) diff --git a/autogen.sh b/autogen.sh index ab4c7dad8..30c2b1adc 100755 --- a/autogen.sh +++ b/autogen.sh @@ -267,5 +267,5 @@ echo "Running autoconf${FORCE} ..." $AUTOCONF${FORCE} echo "You may now run: - ./configure --sysconfdir=/etc --enable-maintainer-mode --enable-symcryptrun --enable-mailto && make + ./configure --sysconfdir=/etc --enable-maintainer-mode --enable-symcryptrun --enable-mailto --enable-gpgtar && make " diff --git a/common/ChangeLog b/common/ChangeLog index d69053429..9e6956370 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,10 @@ +2010-08-09 Werner Koch + + * logging.c (WITH_IPV6): New macro. + (parse_portno): New. From libassuan. + (fun_writer): Support TCP logging on all platforms. + (sock_close): New. + 2010-08-06 Werner Koch * homedir.c (dirmngr_socket_name) [W32CE]: Base on default homedir. diff --git a/common/logging.c b/common/logging.c index dbf9de4d9..87e335b07 100644 --- a/common/logging.c +++ b/common/logging.c @@ -29,16 +29,19 @@ #include #include #include -#ifndef HAVE_W32_SYSTEM +#ifdef HAVE_W32_SYSTEM +# include +#else /*!HAVE_W32_SYSTEM*/ # include # include -#endif /*HAVE_W32_SYSTEM*/ +# include +# include +#endif /*!HAVE_W32_SYSTEM*/ #include #include #include - #define JNLIB_NEED_LOG_LOGV 1 #define JNLIB_NEED_AFLOCAL 1 #include "libjnlib-config.h" @@ -56,6 +59,22 @@ # define isatty(a) (0) #endif +#undef WITH_IPV6 +#if defined (AF_INET6) && defined(PF_INET) \ + && defined (INET6_ADDRSTRLEN) && defined(HAVE_INET_PTON) +# define WITH_IPV6 1 +#endif + +#ifndef EAFNOSUPPORT +# define EAFNOSUPPORT EINVAL +#endif + +#ifdef HAVE_W32_SYSTEM +#define sock_close(a) closesocket(a) +#else +#define sock_close(a) close(a) +#endif + static estream_t logstream; static int log_socket = -1; @@ -109,7 +128,11 @@ writen (int fd, const void *buffer, size_t nbytes) while (nleft > 0) { +#ifdef HAVE_W32_SYSTEM + nwritten = send (fd, buf, nleft, 0); +#else nwritten = write (fd, buf, nleft); +#endif if (nwritten < 0 && errno == EINTR) continue; if (nwritten < 0) @@ -122,6 +145,27 @@ writen (int fd, const void *buffer, size_t nbytes) } +/* Returns true if STR represents a valid port number in decimal + notation and no garbage is following. */ +static int +parse_portno (const char *str, unsigned short *r_port) +{ + unsigned int value; + + for (value=0; *str && (*str >= '0' && *str <= '9'); str++) + { + value = value * 10 + (*str - '0'); + if (value > 65535) + return 0; + } + if (*str || !value) + return 0; + + *r_port = value; + return 1; +} + + static ssize_t fun_writer (void *cookie_arg, const void *buffer, size_t size) { @@ -134,12 +178,129 @@ fun_writer (void *cookie_arg, const void *buffer, size_t size) processes often close stderr and by writing to file descriptor 2 we might send the log message to a file not intended for logging (e.g. a pipe or network connection). */ -#ifndef HAVE_W32_SYSTEM if (cookie->want_socket && cookie->fd == -1) { +#ifdef WITH_IPV6 + struct sockaddr_in6 srvr_addr_in6; +#endif + struct sockaddr_in srvr_addr_in; +#ifndef HAVE_W32_SYSTEM + struct sockaddr_un srvr_addr_un; +#endif + size_t addrlen; + struct sockaddr *srvr_addr = NULL; + unsigned short port = 0; + int af = AF_LOCAL; + int pf = PF_LOCAL; + const char *name = cookie->name; + /* Not yet open or meanwhile closed due to an error. */ cookie->is_socket = 0; - cookie->fd = socket (PF_LOCAL, SOCK_STREAM, 0); + + /* Check whether this is a TCP socket or a local socket. */ + if (!strncmp (name, "tcp://", 6) && name[6]) + { + name += 6; + af = AF_INET; + pf = PF_INET; + } +#ifndef HAVE_W32_SYSTEM + else if (!strncmp (name, "socket://", 9) && name[9]) + name += 9; +#endif + + if (af == AF_LOCAL) + { +#ifdef HAVE_W32_SYSTEM + addrlen = 0; +#else + memset (&srvr_addr, 0, sizeof srvr_addr); + srvr_addr_un.sun_family = af; + strncpy (srvr_addr_un.sun_path, + name, 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); +#endif + } + else + { + char *addrstr, *p; + void *addrbuf = NULL; + + addrstr = jnlib_malloc (strlen (name) + 1); + if (!addrstr) + addrlen = 0; /* This indicates an error. */ + else if (*name == '[') + { + /* Check for IPv6 literal address. */ + strcpy (addrstr, name+1); + p = strchr (addrstr, ']'); + if (!p || p[1] != ':' || !parse_portno (p+2, &port)) + { + jnlib_set_errno (EINVAL); + addrlen = 0; + } + else + { + *p = 0; +#ifdef WITH_IPV6 + af = AF_INET6; + pf = PF_INET6; + memset (&srvr_addr_in6, 0, sizeof srvr_addr_in6); + srvr_addr_in6.sin6_family = af; + srvr_addr_in6.sin6_port = htons (port); + addrbuf = &srvr_addr_in6.sin6_addr; + srvr_addr = (struct sockaddr *)&srvr_addr_in6; + addrlen = sizeof srvr_addr_in6; +#else + jnlib_set_errno (EAFNOSUPPORT); + addrlen = 0; +#endif + } + } + else + { + /* Check for IPv4 literal address. */ + strcpy (addrstr, name); + p = strchr (addrstr, ':'); + if (!p || !parse_portno (p+1, &port)) + { + jnlib_set_errno (EINVAL); + addrlen = 0; + } + else + { + *p = 0; + memset (&srvr_addr_in, 0, sizeof srvr_addr_in); + srvr_addr_in.sin_family = af; + srvr_addr_in.sin_port = htons (port); + addrbuf = &srvr_addr_in.sin_addr; + srvr_addr = (struct sockaddr *)&srvr_addr_in; + addrlen = sizeof srvr_addr_in; + } + } + + if (addrlen) + { +#ifdef HAVE_INET_PTON + if (inet_pton (af, addrstr, addrbuf) != 1) + addrlen = 0; +#else /*!HAVE_INET_PTON*/ + /* We need to use the old function. If we are here v6 + support isn't enabled anyway and thus we can do fine + without. Note that Windows has a compatible inet_pton + function named inetPton, but only since Vista. */ + srvr_addr_in.sin_addr.s_addr = inet_addr (addrstr); + if (srvr_addr_in.sin_addr.s_addr == INADDR_NONE) + addrlen = 0; +#endif /*!HAVE_INET_PTON*/ + } + + jnlib_free (addrstr); + } + + cookie->fd = addrlen? socket (pf, SOCK_STREAM, 0) : -1; if (cookie->fd == -1) { if (!cookie->quiet && !running_detached @@ -149,22 +310,13 @@ fun_writer (void *cookie_arg, const void *buffer, size_t size) } else { - struct sockaddr_un addr; - size_t addrlen; - - memset (&addr, 0, sizeof addr); - addr.sun_family = PF_LOCAL; - strncpy (addr.sun_path, cookie->name, sizeof (addr.sun_path)-1); - addr.sun_path[sizeof (addr.sun_path)-1] = 0; - addrlen = SUN_LEN (&addr); - - if (connect (cookie->fd, (struct sockaddr *) &addr, addrlen) == -1) + if (connect (cookie->fd, srvr_addr, addrlen) == -1) { if (!cookie->quiet && !running_detached && isatty (es_fileno (es_stderr))) es_fprintf (es_stderr, "can't connect to `%s': %s\n", cookie->name, strerror(errno)); - close (cookie->fd); + sock_close (cookie->fd); cookie->fd = -1; } } @@ -174,9 +326,9 @@ fun_writer (void *cookie_arg, const void *buffer, size_t size) if (!running_detached) { /* Due to all the problems with apps not running - detached but being called with stderr closed or - used for a different purposes, it does not make - sense to switch to stderr. We therefore disable it. */ + detached but being called with stderr closed or used + for a different purposes, it does not make sense to + switch to stderr. We therefore disable it. */ if (!cookie->quiet) { /* fputs ("switching logging to stderr\n", stderr);*/ @@ -191,12 +343,11 @@ fun_writer (void *cookie_arg, const void *buffer, size_t size) cookie->is_socket = 1; } } -#endif /*HAVE_W32_SYSTEM*/ - + log_socket = cookie->fd; if (cookie->fd != -1 && !writen (cookie->fd, buffer, size)) return (ssize_t)size; /* Okay. */ - + if (!running_detached && cookie->fd != -1 && isatty (es_fileno (es_stderr))) { @@ -209,11 +360,11 @@ fun_writer (void *cookie_arg, const void *buffer, size_t size) } if (cookie->is_socket && cookie->fd != -1) { - close (cookie->fd); + sock_close (cookie->fd); cookie->fd = -1; log_socket = -1; } - + return (ssize_t)size; } @@ -224,7 +375,7 @@ fun_closer (void *cookie_arg) struct fun_cookie_s *cookie = cookie_arg; if (cookie->fd != -1 && cookie->fd != 2) - close (cookie->fd); + sock_close (cookie->fd); jnlib_free (cookie); log_socket = -1; return 0; @@ -254,18 +405,13 @@ set_file_fd (const char *name, int fd) fd = es_fileno (es_stderr); } + want_socket = 0; + if (name && !strncmp (name, "tcp://", 6) && name[6]) + want_socket = 1; #ifndef HAVE_W32_SYSTEM - if (name) - { - want_socket = (!strncmp (name, "socket://", 9) && name[9]); - if (want_socket) - name += 9; - } - else + else if (name && !strncmp (name, "socket://", 9) && name[9]) + want_socket = 2; #endif /*HAVE_W32_SYSTEM*/ - { - want_socket = 0; - } /* Setup a new stream. */ diff --git a/configure.ac b/configure.ac index ff48ee7c1..362dd0afb 100644 --- a/configure.ac +++ b/configure.ac @@ -1203,7 +1203,7 @@ AC_CHECK_HEADERS([signal.h]) AC_CHECK_FUNCS([memicmp stpcpy strsep strlwr strtoul memmove stricmp strtol \ memrchr isascii timegm getrusage setrlimit stat setlocale \ flockfile funlockfile fopencookie funopen getpwnam getpwuid \ - getenv ]) + getenv inet_pton]) # end jnlib checks. diff --git a/tools/ChangeLog b/tools/ChangeLog index 65bb6f6e2..252e7f972 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,8 @@ 2010-08-09 Werner Koch + * watchgnupg.c: Inlcude in.h and inet.h. + (main): Support tcp connections. + * gpgtar.c (main): Add options -T and --null. * gpgtar-create.c (gpgtar_create): Implement option --null. diff --git a/tools/watchgnupg.c b/tools/watchgnupg.c index 145a76b5e..fe9e3d634 100644 --- a/tools/watchgnupg.c +++ b/tools/watchgnupg.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include @@ -40,7 +42,7 @@ #define MYVERSION_LINE PGM " (GnuPG) " VERSION #define BUGREPORT_LINE "\nReport bugs to .\n" #else -#define MYVERSION_LINE PGM +#define MYVERSION_LINE PGM " (standalone build) " __DATE__ #define BUGREPORT_LINE "" #endif #if !defined(SUN_LEN) || !defined(PF_LOCAL) || !defined(AF_LOCAL) @@ -189,17 +191,19 @@ print_version (int with_help) { fputs (MYVERSION_LINE "\n" "Copyright (C) 2004 Free Software Foundation, Inc.\n" - "This program comes with ABSOLUTELY NO WARRANTY.\n" - "This is free software, and you are welcome to redistribute it\n" - "under certain conditions. See the file COPYING for details.\n", + "License GPLv3+: " + "GNU GPL version 3 or later \n" + "This is free software: you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n", stdout); - if (with_help) fputs ("\n" - "Usage: " PGM " [OPTIONS] SOCKETNAME\n" - "Open the local socket SOCKETNAME and display log messages\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" @@ -213,9 +217,13 @@ main (int argc, char **argv) { int last_argc = -1; int force = 0; + int tcp = 0; - struct sockaddr_un srvr_addr; + struct sockaddr_un srvr_addr_un; + struct sockaddr_in srvr_addr_in; + struct sockaddr *srvr_addr = NULL; socklen_t addrlen; + unsigned short port; int server; int flags; client_t client_list = NULL; @@ -246,6 +254,11 @@ main (int argc, char **argv) force = 1; argc--; argv++; } + else if (!strcmp (*argv, "--tcp")) + { + tcp = 1; + argc--; argv++; + } } if (argc != 1) @@ -254,13 +267,19 @@ main (int argc, char **argv) exit (1); } + port = tcp? atoi (*argv) : 0; if (verbose) - fprintf (stderr, "opening socket `%s'\n", *argv); + { + if (tcp) + fprintf (stderr, "listening on port %hu\n", port); + else + fprintf (stderr, "opening socket `%s'\n", *argv); + } setvbuf (stdout, NULL, _IOLBF, 0); - server = socket (PF_LOCAL, SOCK_STREAM, 0); + server = socket (tcp? PF_INET : PF_LOCAL, SOCK_STREAM, 0); if (server == -1) die ("socket() failed: %s\n", strerror (errno)); @@ -273,24 +292,38 @@ main (int argc, char **argv) if ( fcntl (server, F_SETFL, (flags | O_NONBLOCK)) == -1) die ("fcntl (F_SETFL) failed: %s\n", strerror (errno)); - - memset (&srvr_addr, 0, sizeof srvr_addr); - srvr_addr.sun_family = AF_LOCAL; - strncpy (srvr_addr.sun_path, *argv, sizeof (srvr_addr.sun_path) - 1); - srvr_addr.sun_path[sizeof (srvr_addr.sun_path) - 1] = 0; - addrlen = SUN_LEN (&srvr_addr); - + if (tcp) + { + memset (&srvr_addr_in, 0, sizeof srvr_addr_in); + 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; + } + else + { + 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); + } again: - if (bind (server, (struct sockaddr *) &srvr_addr, addrlen)) + if (bind (server, srvr_addr, addrlen)) { - if (errno == EADDRINUSE && force) + if (!tcp && errno == EADDRINUSE && force) { force = 0; - remove (srvr_addr.sun_path); + remove (srvr_addr_un.sun_path); goto again; } - die ("bind to `%s' failed: %s\n", *argv, strerror (errno)); + 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))