diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/ChangeLog | 33 | ||||
-rw-r--r-- | common/Makefile.am | 4 | ||||
-rw-r--r-- | common/estream.c | 29 | ||||
-rw-r--r-- | common/homedir.c | 149 | ||||
-rw-r--r-- | common/http.c | 12 | ||||
-rw-r--r-- | common/init.c | 73 | ||||
-rw-r--r-- | common/simple-pwquery.c | 49 | ||||
-rw-r--r-- | common/simple-pwquery.h | 41 | ||||
-rw-r--r-- | common/util.h | 16 |
9 files changed, 381 insertions, 25 deletions
diff --git a/common/ChangeLog b/common/ChangeLog index 3f4675de1..f0381229e 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,36 @@ +2007-06-14 Werner Koch <[email protected]> + + * simple-pwquery.h (MAP_SPWQ_ERROR_IMPL): New. + (SPWQ_NO_PIN_ENTRY): New. + * simple-pwquery.c (simple_pw_set_socket): New. + (agent_open): Use it if GPG_AGENT_INFO is not set. + (simple_pwquery): Extended to allow returning of otehyr error codes. + + * util.h (GNUPG_MODULE_NAME_AGENT, GNUPG_MODULE_NAME_PINENTRY) + (GNUPG_MODULE_NAME_SCDAEMON, GNUPG_MODULE_NAME_DIRMNGR) + (GNUPG_MODULE_NAME_PROTECT_TOOL): New. + * homedir.c (gnupg_module_name): New. + (gnupg_bindir): New. + +2007-06-12 Werner Koch <[email protected]> + + * homedir.c (gnupg_sysconfdir): New. + (gnupg_libexecdir): New. Taken from g10/misc.c:get_libexecdir. + (gnupg_datadir): New. + (gnupg_libdir): New. + + * http.c (connect_server) [W32]: Do not call init_sockets if + HTTP_NO_WSASTARTUP is defined. + + * init.c: New. + + * estream.c (es_init_do): Init stream lock here because we can't + use a static initialization with W32pth. + +2007-06-11 Werner Koch <[email protected]> + + * Makefile.am (t_common_ldadd): Use libcommonstd macro. + 2007-06-06 Werner Koch <[email protected]> * Makefile.am: Include am/cmacros.am. diff --git a/common/Makefile.am b/common/Makefile.am index 8f70cdc28..51682306d 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -37,6 +37,7 @@ common_sources = \ openpgpdefs.h \ keyserver.h \ sexp-parse.h \ + init.c \ sexputil.c \ sysutils.c sysutils.h \ homedir.c \ @@ -59,6 +60,7 @@ common_sources = \ pka.c pka.h \ http.c http.h + libcommon_a_SOURCES = $(common_sources) if USE_DNS_SRV libcommon_a_SOURCES += srv.c @@ -83,7 +85,7 @@ libgpgrl_a_SOURCES = \ # module_tests = t-convert -t_common_ldadd = ../jnlib/libjnlib.a ../common/libcommon.a ../gl/libgnu.a \ +t_common_ldadd = ../jnlib/libjnlib.a $(libcommon) ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV) t_convert_DEPENDENCIES = convert.c libcommon.a diff --git a/common/estream.c b/common/estream.c index 05b1230ad..131ddc232 100644 --- a/common/estream.c +++ b/common/estream.c @@ -109,8 +109,6 @@ typedef pth_mutex_t estream_mutex_t; ((pth_mutex_acquire (&(mutex), 1, NULL) == TRUE) ? 0 : -1) # define ESTREAM_MUTEX_INITIALIZE(mutex) \ pth_mutex_init (&(mutex)) -# define ESTREAM_THREADING_INIT() ((pth_init () == TRUE) ? 0 : -1) - #else typedef void *estream_mutex_t; @@ -119,8 +117,6 @@ typedef void *estream_mutex_t; # define ESTREAM_MUTEX_UNLOCK(mutex) (void) 0 # define ESTREAM_MUTEX_TRYLOCK(mutex) 0 # define ESTREAM_MUTEX_INITIALIZE(mutex) (void) 0 -# define ESTREAM_THREADING_INIT() 0 - #endif /* Memory allocator functions. */ @@ -194,13 +190,9 @@ struct estream_list static estream_list_t estream_list; #ifdef HAVE_PTH -/* Note that we can't use a static initialization with W32Pth; however - W32Pth does an implicit initialization anyway. */ -static estream_mutex_t estream_list_lock -# ifndef _W32_PTH_H - = ESTREAM_MUTEX_INITIALIZER -# endif - ; +/* Note that we can't use a static initialization with W32Pth, thus we + do it in es_init. */ +static estream_mutex_t estream_list_lock; #endif #define ESTREAM_LIST_LOCK ESTREAM_MUTEX_LOCK (estream_list_lock) @@ -308,11 +300,18 @@ es_list_iterate (estream_iterator_t iterator) static int es_init_do (void) { - int err; - - err = ESTREAM_THREADING_INIT (); +#ifdef HAVE_PTH + static int initialized; - return err; + if (!initialized) + { + if (!pth_init ()) + return -1; + if (pth_mutex_init (&estream_list_lock)) + initialized = 1; + } +#endif + return 0; } diff --git a/common/homedir.c b/common/homedir.c index 39d6dce20..654c96bec 100644 --- a/common/homedir.c +++ b/common/homedir.c @@ -124,3 +124,152 @@ default_homedir (void) return dir; } + + +/* Return the name of the sysconfdir. This is a static string. This + function is required because under Windows we can't simply compile + it in. */ +const char * +gnupg_sysconfdir (void) +{ +#ifdef HAVE_W32_SYSTEM +#warning get the sysconfdir from somewhere else + return GNUPG_SYSCONFDIR; +#else /*!HAVE_W32_SYSTEM*/ + return GNUPG_SYSCONFDIR; +#endif /*!HAVE_W32_SYSTEM*/ +} + + +const char * +gnupg_bindir (void) +{ +#ifdef HAVE_W32_SYSTEM + return gnupg_libexecdir (); +#else /*!HAVE_W32_SYSTEM*/ + return GNUPG_BINDIR; +#endif /*!HAVE_W32_SYSTEM*/ +} + + +/* Return the name of the libexec directory. The name is allocated in + a static area on the first use. This function won't fail. */ +const char * +gnupg_libexecdir (void) +{ +#ifdef HAVE_W32_SYSTEM + static int got_dir; + static char dir[MAX_PATH+5]; + + if (!got_dir) + { + char *p; + + if ( !GetModuleFileName ( NULL, dir, MAX_PATH) ) + { + log_debug ("GetModuleFileName failed: %s\n", w32_strerror (0)); + *dir = 0; + } + got_dir = 1; + p = strrchr (dir, DIRSEP_C); + if (p) + *p = 0; + else + { + log_debug ("bad filename `%s' returned for this process\n", dir); + *dir = 0; + } + } + + if (*dir) + return dir; + /* Fallback to the hardwired value. */ +#endif /*HAVE_W32_SYSTEM*/ + + return GNUPG_LIBEXECDIR; +} + +const char * +gnupg_libdir (void) +{ +#ifdef HAVE_W32_SYSTEM +#warning get the libdir from somewhere else + return GNUPG_LIBDIR; +#else /*!HAVE_W32_SYSTEM*/ + return GNUPG_LIBDIR; +#endif /*!HAVE_W32_SYSTEM*/ +} + +const char * +gnupg_datadir (void) +{ +#ifdef HAVE_W32_SYSTEM +#warning get the datadir from somewhere else + return GNUPG_DATADIR; +#else /*!HAVE_W32_SYSTEM*/ + return GNUPG_DATADIR; +#endif /*!HAVE_W32_SYSTEM*/ +} + + +/* Return the file name of a helper tool. WHICH is one of the + GNUPG_MODULE_NAME_foo constants. */ +const char * +gnupg_module_name (int which) +{ + const char *s, *s2; + +#define X(a,b) do { \ + static char *name; \ + if (!name) \ + { \ + s = gnupg_ ## a (); \ + s2 = DIRSEP_S b EXEEXT_S; \ + name = xmalloc (strlen (s) + strlen (s2) + 1); \ + strcpy (stpcpy (name, s), s2); \ + } \ + return name; \ + } while (0) + + switch (which) + { + case GNUPG_MODULE_NAME_AGENT: +#ifdef GNUPG_DEFAULT_AGENT + return GNUPG_DEFAULT_AGENT; +#else + X(bindir, "gpg-agent"); +#endif + + case GNUPG_MODULE_NAME_PINENTRY: +#ifdef GNUPG_DEFAULT_PINENTRY + return GNUPG_DEFAULT_PINENTRY; +#else + X(bindir, "pinentry"); +#endif + + case GNUPG_MODULE_NAME_SCDAEMON: +#ifdef GNUPG_DEFAULT_SCDAEMON + return GNUPG_DEFAULT_SCDAEMON; +#else + X(bindir, "scdaemon"); +#endif + + case GNUPG_MODULE_NAME_DIRMNGR: +#ifdef GNUPG_DEFAULT_DIRMNGR + return GNUPG_DEFAULT_DIRMNGR; +#else + X(bindir, "dirmngr"); +#endif + + case GNUPG_MODULE_NAME_PROTECT_TOOL: +#ifdef GNUPG_DEFAULT_PROTECT_TOOL + return GNUPG_DEFAULT_PROTECT_TOOL; +#else + X(libexecdir, "gpg-protect-tool"); +#endif + + default: + BUG (); + } +#undef X +} diff --git a/common/http.c b/common/http.c index 4693c33e2..293a96a2b 100644 --- a/common/http.c +++ b/common/http.c @@ -30,6 +30,10 @@ - With HTTP_USE_ESTREAM defined, all I/O is done through estream. - With HTTP_USE_GNUTLS support for https is provided (this also requires estream). + - With HTTP_NO_WSASTARTUP the socket initialization is not done + under Windows. This is useful if the socket layer has already + been initialized elsewhere. This also avoids the installation of + an exit handler to cleanup the socket layer. */ #ifdef HAVE_CONFIG_H @@ -200,7 +204,7 @@ struct http_context_s -#ifdef HAVE_W32_SYSTEM +#if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP) #if GNUPG_MAJOR_VERSION == 1 #define REQ_WINSOCK_MAJOR 1 @@ -244,7 +248,7 @@ init_sockets (void) atexit ( deinit_sockets ); initialized = 1; } -#endif /*HAVE_W32_SYSTEM*/ +#endif /*HAVE_W32_SYSTEM && !HTTP_NO_WSASTARTUP*/ @@ -1504,7 +1508,9 @@ connect_server (const char *server, unsigned short port, #ifdef HAVE_W32_SYSTEM unsigned long inaddr; - init_sockets(); +#ifndef HTTP_NO_WSASTARTUP + init_sockets (); +#endif /* Win32 gethostbyname doesn't handle IP addresses internally, so we try inet_addr first on that platform only. */ inaddr = inet_addr(server); diff --git a/common/init.c b/common/init.c new file mode 100644 index 000000000..9ac6006c2 --- /dev/null +++ b/common/init.c @@ -0,0 +1,73 @@ +/* init.c - Various initializations + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include <config.h> + +#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */ +#undef HAVE_PTH +#undef USE_GNU_PTH +#endif + +#ifdef HAVE_W32_SYSTEM +#include <windows.h> +#endif +#ifdef HAVE_PTH +#include <pth.h> +#endif + +#include "estream.h" +#include "util.h" + + +/* This function is to be used early at program startup to make sure + that some subsystems are initialized. This is in particualr + important for W32 to initialize the sockets so that our socket + emulation code used directly as well as in libassuan may be used. + It should best be called before any I/O is done so that setup + required for logging is ready. CAUTION: This might be called while + running suid(root). */ +void +init_common_subsystems (void) +{ + /* Try to auto set the character set. */ + set_native_charset (NULL); + +#ifdef HAVE_W32_SYSTEM + /* For W32 we need to initialize the socket layer. This is becuase + we use recv and send in libassuan as well as at some other + places. If we are building with PTH we let pth_init do it. We + can't do much on error so we ignore them. An error would anyway + later pop up if one of the socket functions is used. */ +# ifdef HAVE_PTH + pth_init (); +# else + { + WSADATA wsadat; + + WSAStartup (0x202, &wsadat); + } +# endif /*!HAVE_PTH*/ +#endif + + /* Initialize the Estream library. */ + es_init (); +} + diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c index f0c1cdc00..217ca69cd 100644 --- a/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -1,5 +1,5 @@ /* simple-pwquery.c - A simple password query client for gpg-agent - * Copyright (C) 2002, 2004 Free Software Foundation, Inc. + * Copyright (C) 2002, 2004, 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -68,6 +68,11 @@ #endif +/* Name of the socket to be used if GPG_AGENT_INFO has not been + set. No default socket is used if this is NULL. */ +static char *default_gpg_agent_info; + + @@ -154,9 +159,9 @@ readline (int fd, char *buf, size_t buflen) ; if (n) { - break; /* at least one full line available - that's enough. + break; /* At least one full line available - that's enough. This function is just a simple implementation, so - it is okay to forget about pending bytes */ + it is okay to forget about pending bytes. */ } } @@ -305,6 +310,8 @@ agent_open (int *rfd) *rfd = -1; infostr = getenv ( "GPG_AGENT_INFO" ); if ( !infostr || !*infostr ) + infostr = default_gpg_agent_info; + if ( !infostr || !*infostr ) { #ifdef SPWQ_USE_LOGGING log_error (_("gpg-agent is not available in this session\n")); @@ -322,6 +329,9 @@ agent_open (int *rfd) { #ifdef SPWQ_USE_LOGGING log_error ( _("malformed GPG_AGENT_INFO environment variable\n")); + log_debug ( "a='%s'\n", infostr); + log_debug ( "a='%s'\n", strchr ( infostr, PATHSEP_C)); + log_debug ( "a=%td\n", (p-infostr)); #endif return SPWQ_NO_AGENT; } @@ -425,13 +435,34 @@ copy_and_escape (char *buffer, const char *text) } +/* Set the name of the default socket to NAME. */ +int +simple_pw_set_socket (const char *name) +{ + spwq_free (default_gpg_agent_info); + if (name) + { + default_gpg_agent_info = spwq_malloc (strlen (name) + 4 + 1); + if (!default_gpg_agent_info) + return SPWQ_OUT_OF_CORE; + /* We don't know the PID thus we use 0. */ + strcpy (stpcpy (default_gpg_agent_info, name), + PATHSEP_S "0" PATHSEP_S "1"); + } + else + default_gpg_agent_info = NULL; + + return 0; +} + + /* Ask the gpg-agent for a passphrase and present the user with a DESCRIPTION, a PROMPT and optionally with a TRYAGAIN extra text. If a CACHEID is not NULL it is used to locate the passphrase in in the cache and store it under this ID. If OPT_CHECK is true gpg-agent is asked to apply some checks on the passphrase security. If ERRORCODE is not NULL it should point a variable receiving an - errorcode; this errocode might be 0 if the user canceled the + errorcode; this error code might be 0 if the user canceled the operation. The function returns NULL to indicate an error. */ char * simple_pwquery (const char *cacheid, @@ -530,7 +561,15 @@ simple_pwquery (const char *cacheid, #ifdef SPWQ_USE_LOGGING log_info (_("canceled by user\n") ); #endif - *errorcode = 0; /* canceled */ + *errorcode = 0; /* Special error code to indicate Cancel. */ + } + else if (nread > 4 && !memcmp (pw, "ERR ", 4)) + { + switch ( (strtoul (pw+4, NULL, 0) & 0xffff) ) + { + case 85: rc = SPWQ_NO_PIN_ENTRY; break; + default: rc = SPWQ_GENERAL_ERROR; break; + } } else { diff --git a/common/simple-pwquery.h b/common/simple-pwquery.h index ab2724ffa..cb5d9354b 100644 --- a/common/simple-pwquery.h +++ b/common/simple-pwquery.h @@ -41,7 +41,6 @@ #define spwq_secure_malloc(a) gcry_malloc_secure (a) #define spwq_secure_free(a) gcry_free (a) - #endif /*SIMPLE_PWQUERY_IMPLEMENTATION*/ /* End configuration stuff. */ @@ -67,6 +66,11 @@ int simple_pwclear (const char *cacheid); terminated) and return the error code. */ int simple_query (const char *query); +/* Set the name of the standard socket to be used if GPG_AGENT_INFO is + not defined. The use of this function is optional but if it needs + to be called before any other function. Returns 0 on success. */ +int simple_pw_set_socket (const char *name); + #define SPWQ_OUT_OF_CORE 1 #define SPWQ_IO_ERROR 2 #define SPWQ_PROTOCOL_ERROR 3 @@ -74,5 +78,40 @@ int simple_query (const char *query); #define SPWQ_NO_AGENT 5 #define SPWQ_SYS_ERROR 6 #define SPWQ_GENERAL_ERROR 7 +#define SPWQ_NO_PIN_ENTRY 8 + + +/* We often need to map error codes to gpg-error style error codes. + To have a consistent mapping this macro may be used to implemt the + mapping function. */ +#define MAP_SPWQ_ERROR_IMPL \ + static gpg_error_t \ + map_spwq_error (int err) \ + { \ + switch (err) \ + { \ + case 0: \ + return 0; \ + case SPWQ_OUT_OF_CORE: \ + return gpg_error_from_errno (ENOMEM); \ + case SPWQ_IO_ERROR: \ + return gpg_error_from_errno (EIO); \ + case SPWQ_PROTOCOL_ERROR: \ + return gpg_error (GPG_ERR_PROTOCOL_VIOLATION); \ + case SPWQ_ERR_RESPONSE: \ + return gpg_error (GPG_ERR_INV_RESPONSE); \ + case SPWQ_NO_AGENT: \ + return gpg_error (GPG_ERR_NO_AGENT); \ + case SPWQ_SYS_ERROR: \ + return gpg_error_from_syserror (); \ + case SPWQ_NO_PIN_ENTRY: \ + return gpg_error (GPG_ERR_NO_PIN_ENTRY); \ + case SPWQ_GENERAL_ERROR: \ + default: \ + return gpg_error (GPG_ERR_GENERAL); \ + } \ + } +/* End of MAP_SPWQ_ERROR_IMPL. */ + #endif /*SIMPLE_PWQUERY_H*/ diff --git a/common/util.h b/common/util.h index 3b7050132..42df1274f 100644 --- a/common/util.h +++ b/common/util.h @@ -120,6 +120,8 @@ gnupg_copy_time (gnupg_isotime_t d, const gnupg_isotime_t s) strcpy (d, s); } +/*-- init.c --*/ +void init_common_subsystems (void); /*-- signal.c --*/ void gnupg_init_signals (int mode, void (*fast_cleanup)(void)); @@ -170,6 +172,20 @@ char *bin2hexcolon (const void *buffer, size_t length, char *stringbuf); /*-- homedir.c --*/ const char *default_homedir (void); +const char *gnupg_sysconfdir (void); +const char *gnupg_bindir (void); +const char *gnupg_libexecdir (void); +const char *gnupg_libdir (void); +const char *gnupg_datadir (void); + +#define GNUPG_MODULE_NAME_AGENT 1 +#define GNUPG_MODULE_NAME_PINENTRY 2 +#define GNUPG_MODULE_NAME_SCDAEMON 3 +#define GNUPG_MODULE_NAME_DIRMNGR 4 +#define GNUPG_MODULE_NAME_PROTECT_TOOL 5 +const char *gnupg_module_name (int which); + + /*-- gpgrlhelp.c --*/ void gnupg_rl_initialize (void); |