Prefer GnuPG-2 engines over GnuPG-1.

* src/util.h: Move some prototypes to ...
* src/sys-util.h: New.
* src/Makefile.am (main_sources): Add sys-util.h.
* configure.ac (AH_VERBATIM): Add DIRSEP_C and DIRSEP_S.
* src/dirinfo.c: Include sys-util.h.
(WANT_GPG_NAME, WANT_GPGSM_NAME, WANT_G13_NAME)
(WANT_UISRV_SOCKET): New.
(dirinfo): Add corresponding fields.
(parse_output): Add arg COMPONENTS and set new fields.
(read_gpgconf_dirs): Add arg components and act upon it.
(get_gpgconf_item): Call read_gpgconf_dirs two times.  Add debug
output.
(_gpgme_get_default_gpg_name): New.
(_gpgme_get_default_gpgsm_name): New.
(_gpgme_get_default_g13_name): New.
(_gpgme_get_default_gpgconf_name): New.
(_gpgme_get_default_uisrv_socket): New.
* src/engine-gpg.c, src/engine-g13.c, src/engine-gpgconf.c
* src/engine-gpgsm.c, src/engine-uiserver.c: Change to use
_gpgme_get_default_ instead of those from sys-util.h.
* src/posix-util.c (_gpgme_get_gpg_path): Include sys-util.h.
(_gpgme_get_uiserver_socket_path): Remove.
* src/w32-util.c (_gpgme_get_gpg_path): Include sys-util.h.
(_gpgme_get_uiserver_socket_path): Remove.
--

The default engines names are now taken from the output of gpgconf.
If gpgconf is not installed gpg 1 is assumed and locate the same was
as gpgconf.
This commit is contained in:
Werner Koch 2013-08-02 15:25:23 +02:00
parent 3881ea4e83
commit a4c80126ae
13 changed files with 212 additions and 92 deletions

6
NEWS
View File

@ -1,6 +1,12 @@
Noteworthy changes in version 1.4.3 (unreleased)
------------------------------------------------
* The default engine names are now taken from the output of gpgconf.
If gpgconf is not found the use of gpg 1 is assumed.
* Under Windows the default engines names are first searched in the
installation directory of the gpgme DLL.
* Interface changes relative to the 1.4.2 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_signers_count NEW.

View File

@ -920,11 +920,15 @@ AM_CONDITIONAL(HAVE_UISERVER, test "$uiserver" != "no")
# Add a few constants to help porting to W32
AH_VERBATIM([SEPCONSTANTS],
[
/* Separators as used in $PATH. */
/* Separators as used in $PATH and file name. */
#ifdef HAVE_DOSISH_SYSTEM
#define PATHSEP_C ';'
#define DIRSEP_C '\\'
#define DIRSEP_S "\\"
#else
#define PATHSEP_C ':'
#define DIRSEP_C '/'
#define DIRSEP_S "/"
#endif
])

View File

@ -118,7 +118,7 @@ main_sources = \
$(uiserver_components) \
$(g13_components) vfs-mount.c vfs-create.c \
gpgconf.c \
sema.h priv-io.h $(system_components) dirinfo.c \
sema.h priv-io.h $(system_components) sys-util.h dirinfo.c \
debug.c debug.h gpgme.c version.c error.c
libgpgme_la_SOURCES = $(main_sources) \

View File

@ -1,5 +1,5 @@
/* dirinfo.c - Get directory information
* Copyright (C) 2009 g10 Code GmbH
* Copyright (C) 2009, 2013 g10 Code GmbH
*
* This file is part of GPGME.
*
@ -29,6 +29,7 @@
#include "priv-io.h"
#include "debug.h"
#include "sema.h"
#include "sys-util.h"
DEFINE_STATIC_LOCK (dirinfo_lock);
@ -36,7 +37,11 @@ DEFINE_STATIC_LOCK (dirinfo_lock);
enum
{
WANT_HOMEDIR,
WANT_AGENT_SOCKET
WANT_AGENT_SOCKET,
WANT_GPG_NAME,
WANT_GPGSM_NAME,
WANT_G13_NAME,
WANT_UISRV_SOCKET
};
/* Values retrieved via gpgconf and cached here. */
@ -44,13 +49,18 @@ static struct {
int valid; /* Cached information is valid. */
char *homedir;
char *agent_socket;
char *gpg_name;
char *gpgsm_name;
char *g13_name;
char *uisrv_socket;
} dirinfo;
/* Parse the output of "gpgconf --list-dirs". This function expects
that DIRINFO_LOCK is held by the caller. */
that DIRINFO_LOCK is held by the caller. If COMPONENTS is set, the
output of --list-components is expected. */
static void
parse_output (char *line)
parse_output (char *line, int components)
{
char *value, *p;
@ -58,6 +68,14 @@ parse_output (char *line)
if (!value)
return;
*value++ = 0;
if (components)
{
/* Skip the second field. */
value = strchr (value, ':');
if (!value)
return;
*value++ = 0;
}
p = strchr (value, ':');
if (p)
*p = 0;
@ -66,19 +84,45 @@ parse_output (char *line)
if (!*value)
return;
if (components)
{
if (!strcmp (line, "gpg") && !dirinfo.gpg_name)
dirinfo.gpg_name = strdup (value);
else if (!strcmp (line, "gpgsm") && !dirinfo.gpgsm_name)
dirinfo.gpgsm_name = strdup (value);
else if (!strcmp (line, "g13") && !dirinfo.g13_name)
dirinfo.g13_name = strdup (value);
}
else
{
if (!strcmp (line, "homedir") && !dirinfo.homedir)
{
const char name[] = "S.uiserver";
dirinfo.homedir = strdup (value);
if (dirinfo.homedir)
{
dirinfo.uisrv_socket = malloc (strlen (dirinfo
.homedir)
+ 1 + strlen (name) + 1);
if (dirinfo.uisrv_socket)
strcpy (stpcpy (stpcpy (dirinfo.uisrv_socket, dirinfo.homedir),
DIRSEP_S), name);
}
}
else if (!strcmp (line, "agent-socket") && !dirinfo.agent_socket)
dirinfo.agent_socket = strdup (value);
}
}
/* Read the directory information from gpgconf. This function expects
that DIRINFO_LOCK is held by the caller. */
that DIRINFO_LOCK is held by the caller. PGNAME is the name of the
gpgconf binary. If COMPONENTS is set, not the directories bit the
name of the componeNts are read. */
static void
read_gpgconf_dirs (void)
read_gpgconf_dirs (const char *pgmname, int components)
{
const char *pgmname;
char linebuf[1024] = {0};
int linelen = 0;
char * argv[3];
@ -89,12 +133,8 @@ read_gpgconf_dirs (void)
int nread;
char *mark = NULL;
pgmname = _gpgme_get_gpgconf_path ();
if (!pgmname)
return; /* No way. */
argv[0] = (char *)pgmname;
argv[1] = "--list-dirs";
argv[1] = components? "--list-components" : "--list-dirs";
argv[2] = NULL;
if (_gpgme_io_pipe (rp, 1) < 0)
@ -132,7 +172,7 @@ read_gpgconf_dirs (void)
else
mark[0] = '\0';
parse_output (line);
parse_output (line, components);
}
nused = lastmark? (lastmark + 1 - linebuf) : 0;
@ -147,14 +187,38 @@ read_gpgconf_dirs (void)
static const char *
get_gpgconf_dir (int what)
get_gpgconf_item (int what)
{
const char *result = NULL;
LOCK (dirinfo_lock);
if (!dirinfo.valid)
{
read_gpgconf_dirs ();
const char *pgmname;
pgmname = _gpgme_get_gpgconf_path ();
if (pgmname && access (pgmname, F_OK))
{
_gpgme_debug (DEBUG_INIT,
"gpgme_dinfo: gpgconf='%s' [not installed]\n", pgmname);
pgmname = NULL; /* Not available. */
}
else
_gpgme_debug (DEBUG_INIT, "gpgme_dinfo: gpgconf='%s'\n",
pgmname? pgmname : "[null]");
if (!pgmname)
{
/* Probably gpgconf is not installed. Assume we are using
GnuPG-1. */
pgmname = _gpgme_get_gpg_path ();
if (pgmname)
dirinfo.gpg_name = strdup (pgmname);
}
else
{
read_gpgconf_dirs (pgmname, 0);
read_gpgconf_dirs (pgmname, 1);
}
/* Even if the reading of the directories failed (e.g. due to an
too old version gpgconf or no gpgconf at all), we need to
mark the entries as valid so that we won't try over and over
@ -162,11 +226,33 @@ get_gpgconf_dir (int what)
the read values later because they are practically statically
allocated. */
dirinfo.valid = 1;
if (dirinfo.gpg_name)
_gpgme_debug (DEBUG_INIT, "gpgme_dinfo: gpg='%s'\n",
dirinfo.gpg_name);
if (dirinfo.g13_name)
_gpgme_debug (DEBUG_INIT, "gpgme_dinfo: g13='%s'\n",
dirinfo.g13_name);
if (dirinfo.gpgsm_name)
_gpgme_debug (DEBUG_INIT, "gpgme_dinfo: gpgsm='%s'\n",
dirinfo.gpgsm_name);
if (dirinfo.homedir)
_gpgme_debug (DEBUG_INIT, "gpgme_dinfo: homedir='%s'\n",
dirinfo.homedir);
if (dirinfo.agent_socket)
_gpgme_debug (DEBUG_INIT, "gpgme_dinfo: agent='%s'\n",
dirinfo.agent_socket);
if (dirinfo.uisrv_socket)
_gpgme_debug (DEBUG_INIT, "gpgme_dinfo: uisrv='%s'\n",
dirinfo.uisrv_socket);
}
switch (what)
{
case WANT_HOMEDIR: result = dirinfo.homedir; break;
case WANT_AGENT_SOCKET: result = dirinfo.agent_socket; break;
case WANT_GPG_NAME: result = dirinfo.gpg_name; break;
case WANT_GPGSM_NAME: result = dirinfo.gpgsm_name; break;
case WANT_G13_NAME: result = dirinfo.g13_name; break;
case WANT_UISRV_SOCKET: result = dirinfo.uisrv_socket; break;
}
UNLOCK (dirinfo_lock);
return result;
@ -177,13 +263,51 @@ get_gpgconf_dir (int what)
const char *
_gpgme_get_default_homedir (void)
{
return get_gpgconf_dir (WANT_HOMEDIR);
return get_gpgconf_item (WANT_HOMEDIR);
}
/* Return the default gpg-agent socket name. Returns NULL if not known. */
const char *
_gpgme_get_default_agent_socket (void)
{
return get_gpgconf_dir (WANT_AGENT_SOCKET);
return get_gpgconf_item (WANT_AGENT_SOCKET);
}
/* Return the default gpg file name. Returns NULL if not known. */
const char *
_gpgme_get_default_gpg_name (void)
{
return get_gpgconf_item (WANT_GPG_NAME);
}
/* Return the default gpgsm file name. Returns NULL if not known. */
const char *
_gpgme_get_default_gpgsm_name (void)
{
return get_gpgconf_item (WANT_GPGSM_NAME);
}
/* Return the default g13 file name. Returns NULL if not known. */
const char *
_gpgme_get_default_g13_name (void)
{
return get_gpgconf_item (WANT_G13_NAME);
}
/* Return the default gpgconf file name. Returns NULL if not known.
Because gpgconf is the binary used to retrieved all these default
names, this function is merely a simple wrapper around the function
used to locate this binary. */
const char *
_gpgme_get_default_gpgconf_name (void)
{
return _gpgme_get_gpgconf_path ();
}
/* Return the default UI-server socket name. Returns NULL if not
known. */
const char *
_gpgme_get_default_uisrv_socket (void)
{
return get_gpgconf_item (WANT_UISRV_SOCKET);
}

View File

@ -100,7 +100,7 @@ static char *
g13_get_version (const char *file_name)
{
return _gpgme_get_program_version (file_name ? file_name
: _gpgme_get_g13_path ());
: _gpgme_get_default_g13_name ());
}
@ -251,11 +251,11 @@ g13_new (void **engine, const char *file_name, const char *home_dir)
#if USE_DESCRIPTOR_PASSING
err = assuan_pipe_connect
(g13->assuan_ctx, file_name ? file_name : _gpgme_get_g13_path (),
(g13->assuan_ctx, file_name ? file_name : _gpgme_get_default_g13_name (),
argv, NULL, NULL, NULL, ASSUAN_PIPE_CONNECT_FDPASSING);
#else
err = assuan_pipe_connect
(g13->assuan_ctx, file_name ? file_name : _gpgme_get_g13_path (),
(g13->assuan_ctx, file_name ? file_name : _gpgme_get_default_g13_name (),
argv, NULL, NULL, NULL, 0);
#endif
if (err)
@ -757,7 +757,7 @@ g13_io_event (void *engine, gpgme_event_io_t type, void *type_data)
struct engine_ops _gpgme_engine_ops_g13 =
{
/* Static functions. */
_gpgme_get_g13_path,
_gpgme_get_default_g13_name,
NULL,
g13_get_version,
g13_get_req_version,

View File

@ -296,7 +296,7 @@ static char *
gpg_get_version (const char *file_name)
{
return _gpgme_get_program_version (file_name ? file_name
: _gpgme_get_gpg_path ());
: _gpgme_get_default_gpg_name ());
}
@ -1296,7 +1296,7 @@ start (engine_gpg_t gpg)
if (!gpg)
return gpg_error (GPG_ERR_INV_VALUE);
if (!gpg->file_name && !_gpgme_get_gpg_path ())
if (!gpg->file_name && !_gpgme_get_default_gpg_name ())
return trace_gpg_error (GPG_ERR_INV_ENGINE);
if (gpg->lc_ctype)
@ -1352,7 +1352,7 @@ start (engine_gpg_t gpg)
fd_list[n].dup_to = -1;
status = _gpgme_io_spawn (gpg->file_name ? gpg->file_name :
_gpgme_get_gpg_path (), gpg->argv,
_gpgme_get_default_gpg_name (), gpg->argv,
IOSPAWN_FLAG_ALLOW_SET_FG,
fd_list, NULL, NULL, &pid);
{
@ -2401,7 +2401,7 @@ gpg_set_pinentry_mode (void *engine, gpgme_pinentry_mode_t mode)
struct engine_ops _gpgme_engine_ops_gpg =
{
/* Static functions. */
_gpgme_get_gpg_path,
_gpgme_get_default_gpg_name,
NULL,
gpg_get_version,
gpg_get_req_version,

View File

@ -61,7 +61,7 @@ static char *
gpgconf_get_version (const char *file_name)
{
return _gpgme_get_program_version (file_name ? file_name
: _gpgme_get_gpgconf_path ());
: _gpgme_get_default_gpgconf_name ());
}
@ -100,7 +100,7 @@ gpgconf_new (void **engine, const char *file_name, const char *home_dir)
return gpg_error_from_syserror ();
gpgconf->file_name = strdup (file_name ? file_name
: _gpgme_get_gpgconf_path ());
: _gpgme_get_default_gpgconf_name ());
if (!gpgconf->file_name)
err = gpg_error_from_syserror ();
@ -923,7 +923,7 @@ _gpgme_conf_release (gpgme_conf_comp_t conf)
struct engine_ops _gpgme_engine_ops_gpgconf =
{
/* Static functions. */
_gpgme_get_gpgconf_path,
_gpgme_get_default_gpgconf_name,
NULL,
gpgconf_get_version,
gpgconf_get_req_version,

View File

@ -120,7 +120,7 @@ static char *
gpgsm_get_version (const char *file_name)
{
return _gpgme_get_program_version (file_name ? file_name
: _gpgme_get_gpgsm_path ());
: _gpgme_get_default_gpgsm_name ());
}
@ -340,7 +340,8 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
#if USE_DESCRIPTOR_PASSING
err = assuan_pipe_connect
(gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (),
(gpgsm->assuan_ctx,
file_name ? file_name : _gpgme_get_default_gpgsm_name (),
argv, NULL, NULL, NULL, ASSUAN_PIPE_CONNECT_FDPASSING);
#else
{
@ -352,7 +353,8 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
achild_fds[i] = (assuan_fd_t) child_fds[i];
err = assuan_pipe_connect
(gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (),
(gpgsm->assuan_ctx,
file_name ? file_name : _gpgme_get_default_gpgsm_name (),
argv, achild_fds, NULL, NULL, 0);
/* For now... */
@ -1945,7 +1947,7 @@ gpgsm_passwd (void *engine, gpgme_key_t key, unsigned int flags)
struct engine_ops _gpgme_engine_ops_gpgsm =
{
/* Static functions. */
_gpgme_get_gpgsm_path,
_gpgme_get_default_gpgsm_name,
NULL,
gpgsm_get_version,
gpgsm_get_req_version,

View File

@ -296,7 +296,7 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir)
err = assuan_socket_connect (uiserver->assuan_ctx,
file_name ?
file_name : _gpgme_get_uiserver_socket_path (),
file_name : _gpgme_get_default_uisrv_socket (),
0, ASSUAN_SOCKET_SERVER_FDPASSING);
if (err)
goto leave;
@ -1302,7 +1302,7 @@ uiserver_io_event (void *engine, gpgme_event_io_t type, void *type_data)
struct engine_ops _gpgme_engine_ops_uiserver =
{
/* Static functions. */
_gpgme_get_uiserver_socket_path,
_gpgme_get_default_uisrv_socket,
NULL,
uiserver_get_version,
uiserver_get_req_version,

View File

@ -28,6 +28,7 @@
#include <assert.h>
#include "util.h"
#include "sys-util.h"
const char *
_gpgme_get_gpg_path (void)
@ -70,29 +71,6 @@ _gpgme_get_g13_path (void)
}
const char *
_gpgme_get_uiserver_socket_path (void)
{
static char *socket_path;
const char *homedir;
const char name[] = "S.uiserver";
if (socket_path)
return socket_path;
homedir = _gpgme_get_default_homedir ();
if (! homedir)
return NULL;
socket_path = malloc (strlen (homedir) + 1 + strlen (name) + 1);
if (! socket_path)
return NULL;
strcpy (stpcpy (stpcpy (socket_path, homedir), "/"), name);
return socket_path;
}
/* See w32-util.c */
int
_gpgme_get_conf_int (const char *key, int *value)

29
src/sys-util.h Normal file
View File

@ -0,0 +1,29 @@
/* sys-util.h - System utilities not generally used.
* Copyright (C) 2013 g10 Code GmbH
*
* This file is part of GPGME.
*
* GPGME is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* GPGME 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SYS_UTIL_H
#define SYS_UTIL_H
/*-- {posix,w32}-util.c --*/
const char *_gpgme_get_gpg_path (void);
const char *_gpgme_get_gpgsm_path (void);
const char *_gpgme_get_gpgconf_path (void);
const char *_gpgme_get_g13_path (void);
#endif /* SYS_UTIL_H */

View File

@ -47,18 +47,17 @@
/*-- {posix,w32}-util.c --*/
const char *_gpgme_get_gpg_path (void);
const char *_gpgme_get_gpgsm_path (void);
const char *_gpgme_get_gpgconf_path (void);
const char *_gpgme_get_g13_path (void);
const char *_gpgme_get_uiserver_socket_path (void);
int _gpgme_get_conf_int (const char *key, int *value);
void _gpgme_allow_set_foreground_window (pid_t pid);
/*-- dirinfo.c --*/
const char *_gpgme_get_default_homedir (void);
const char *_gpgme_get_default_agent_socket (void);
const char *_gpgme_get_default_gpg_name (void);
const char *_gpgme_get_default_gpgsm_name (void);
const char *_gpgme_get_default_g13_name (void);
const char *_gpgme_get_default_gpgconf_name (void);
const char *_gpgme_get_default_uisrv_socket (void);

View File

@ -62,6 +62,7 @@
#include "ath.h"
#include "sema.h"
#include "debug.h"
#include "sys-util.h"
#ifndef HAVE_W32CE_SYSTEM
@ -492,29 +493,6 @@ _gpgme_get_g13_path (void)
}
const char *
_gpgme_get_uiserver_socket_path (void)
{
static char *socket_path;
const char *homedir;
const char name[] = "S.uiserver";
if (socket_path)
return socket_path;
homedir = _gpgme_get_default_homedir ();
if (! homedir)
return NULL;
socket_path = malloc (strlen (homedir) + 1 + strlen (name) + 1);
if (! socket_path)
return NULL;
strcpy (stpcpy (stpcpy (socket_path, homedir), "\\"), name);
return socket_path;
}
const char *
_gpgme_get_w32spawn_path (void)
{