2003-06-05 09:14:21 +02:00
|
|
|
|
/* trustlist.c - Maintain the list of trusted keys
|
2012-04-30 14:37:36 +02:00
|
|
|
|
* Copyright (C) 2002, 2004, 2006, 2007, 2009,
|
|
|
|
|
* 2012 Free Software Foundation, Inc.
|
2003-06-05 09:14:21 +02:00
|
|
|
|
*
|
|
|
|
|
* 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
|
2007-07-04 21:49:40 +02:00
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2003-06-05 09:14:21 +02:00
|
|
|
|
* (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
|
2016-11-05 12:02:19 +01:00
|
|
|
|
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
2003-06-05 09:14:21 +02:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <sys/stat.h>
|
Port to npth.
* configure.ac: Don't check for PTH but for NPTH.
(AH_BOTTOM): Remove PTH_SYSCALL_SOFT.
(have_pth): Rename to ...
(have_npth): ... this.
(USE_GNU_NPTH): Rename to ...
(USE_GNU_PTH): ... this.
* m4/npth.m4: New file.
* agent/Makefile.am, agent/cache.c, agent/call-pinentry.c,
agent/call-scd.c, agent/findkey.c, agent/gpg-agent.c,
agent/trustlist.c, common/Makefile.am, common/estream.c,
common/exechelp-posix.c, common/exechelp-w32.c,
common/exechelp-w32ce.c, common/http.c, common/init.c,
common/sysutils.c, dirmngr/Makefile.am, dirmngr/crlfetch.c,
dirmngr/dirmngr.c, dirmngr/dirmngr_ldap.c, dirmngr/ldap-wrapper-ce.c,
dirmngr/ldap-wrapper.c, dirmngr/ldap.c, g13/Makefile.am,
g13/call-gpg.c, g13/g13.c, g13/runner.c, scd/Makefile.am,
scd/apdu.c, scd/app.c, scd/ccid-driver.c, scd/command.c,
scd/scdaemon.c, tools/Makefile.am: Port to npth.
2012-01-03 22:12:37 +01:00
|
|
|
|
#include <npth.h>
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
|
|
#include "agent.h"
|
|
|
|
|
#include <assuan.h> /* fixme: need a way to avoid assuan calls here */
|
agent: Resolve conflict of util.h.
* agent/Makefile.am (AM_CPPFLAGS): Remove -I$(top_srcdir)/common.
* agent/call-pinentry.c, agent/call-scd.c: Follow the change.
* agent/command-ssh.c, agent/command.c, agent/cvt-openpgp.c: Ditto.
* agent/divert-scd.c, agent/findkey.c, agent/genkey.c: Ditto.
* agent/gpg-agent.c, agent/pksign.c, agent/preset-passphrase.c: Ditto.
* agent/protect-tool.c, agent/protect.c, agent/trustlist.c: Ditto.
* agent/w32main.c: Ditto.
--
For openpty function, we need to include util.h on some OS.
We also have util.h in common/, so this change is needed.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-03-07 11:22:48 +01:00
|
|
|
|
#include "../common/i18n.h"
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
/* A structure to store the information from the trust file. */
|
|
|
|
|
struct trustitem_s
|
|
|
|
|
{
|
2006-09-25 20:29:20 +02:00
|
|
|
|
struct
|
|
|
|
|
{
|
2009-03-19 11:21:51 +01:00
|
|
|
|
int disabled:1; /* This entry is disabled. */
|
2006-09-25 20:29:20 +02:00
|
|
|
|
int for_pgp:1; /* Set by '*' or 'P' as first flag. */
|
|
|
|
|
int for_smime:1; /* Set by '*' or 'S' as first flag. */
|
|
|
|
|
int relax:1; /* Relax checking of root certificate
|
|
|
|
|
constraints. */
|
2007-08-10 18:52:05 +02:00
|
|
|
|
int cm:1; /* Use chain model for validation. */
|
2006-09-25 20:29:20 +02:00
|
|
|
|
} flags;
|
2006-09-15 20:53:37 +02:00
|
|
|
|
unsigned char fpr[20]; /* The binary fingerprint. */
|
|
|
|
|
};
|
|
|
|
|
typedef struct trustitem_s trustitem_t;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
/* Malloced table and its allocated size with all trust items. */
|
2011-02-04 12:57:53 +01:00
|
|
|
|
static trustitem_t *trusttable;
|
|
|
|
|
static size_t trusttablesize;
|
2006-09-15 20:53:37 +02:00
|
|
|
|
/* A mutex used to protect the table. */
|
Port to npth.
* configure.ac: Don't check for PTH but for NPTH.
(AH_BOTTOM): Remove PTH_SYSCALL_SOFT.
(have_pth): Rename to ...
(have_npth): ... this.
(USE_GNU_NPTH): Rename to ...
(USE_GNU_PTH): ... this.
* m4/npth.m4: New file.
* agent/Makefile.am, agent/cache.c, agent/call-pinentry.c,
agent/call-scd.c, agent/findkey.c, agent/gpg-agent.c,
agent/trustlist.c, common/Makefile.am, common/estream.c,
common/exechelp-posix.c, common/exechelp-w32.c,
common/exechelp-w32ce.c, common/http.c, common/init.c,
common/sysutils.c, dirmngr/Makefile.am, dirmngr/crlfetch.c,
dirmngr/dirmngr.c, dirmngr/dirmngr_ldap.c, dirmngr/ldap-wrapper-ce.c,
dirmngr/ldap-wrapper.c, dirmngr/ldap.c, g13/Makefile.am,
g13/call-gpg.c, g13/g13.c, g13/runner.c, scd/Makefile.am,
scd/apdu.c, scd/app.c, scd/ccid-driver.c, scd/command.c,
scd/scdaemon.c, tools/Makefile.am: Port to npth.
2012-01-03 22:12:37 +01:00
|
|
|
|
static npth_mutex_t trusttable_lock;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
static const char headerblurb[] =
|
|
|
|
|
"# This is the list of trusted keys. Comment lines, like this one, as\n"
|
|
|
|
|
"# well as empty lines are ignored. Lines have a length limit but this\n"
|
2009-03-19 11:21:51 +01:00
|
|
|
|
"# is not a serious limitation as the format of the entries is fixed and\n"
|
2006-09-15 20:53:37 +02:00
|
|
|
|
"# checked by gpg-agent. A non-comment line starts with optional white\n"
|
2009-03-19 11:21:51 +01:00
|
|
|
|
"# space, followed by the SHA-1 fingerpint in hex, followed by a flag\n"
|
|
|
|
|
"# which may be one of 'P', 'S' or '*' and optionally followed by a list of\n"
|
|
|
|
|
"# other flags. The fingerprint may be prefixed with a '!' to mark the\n"
|
|
|
|
|
"# key as not trusted. You should give the gpg-agent a HUP or run the\n"
|
|
|
|
|
"# command \"gpgconf --reload gpg-agent\" after changing this file.\n"
|
2006-09-15 20:53:37 +02:00
|
|
|
|
"\n\n"
|
|
|
|
|
"# Include the default trust list\n"
|
|
|
|
|
"include-default\n"
|
|
|
|
|
"\n";
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
|
|
|
2007-06-14 19:05:07 +02:00
|
|
|
|
/* This function must be called once to initialize this module. This
|
|
|
|
|
has to be done before a second thread is spawned. We can't do the
|
|
|
|
|
static initialization because Pth emulation code might not be able
|
|
|
|
|
to do a static init; in particular, it is not possible for W32. */
|
|
|
|
|
void
|
|
|
|
|
initialize_module_trustlist (void)
|
|
|
|
|
{
|
|
|
|
|
static int initialized;
|
Port to npth.
* configure.ac: Don't check for PTH but for NPTH.
(AH_BOTTOM): Remove PTH_SYSCALL_SOFT.
(have_pth): Rename to ...
(have_npth): ... this.
(USE_GNU_NPTH): Rename to ...
(USE_GNU_PTH): ... this.
* m4/npth.m4: New file.
* agent/Makefile.am, agent/cache.c, agent/call-pinentry.c,
agent/call-scd.c, agent/findkey.c, agent/gpg-agent.c,
agent/trustlist.c, common/Makefile.am, common/estream.c,
common/exechelp-posix.c, common/exechelp-w32.c,
common/exechelp-w32ce.c, common/http.c, common/init.c,
common/sysutils.c, dirmngr/Makefile.am, dirmngr/crlfetch.c,
dirmngr/dirmngr.c, dirmngr/dirmngr_ldap.c, dirmngr/ldap-wrapper-ce.c,
dirmngr/ldap-wrapper.c, dirmngr/ldap.c, g13/Makefile.am,
g13/call-gpg.c, g13/g13.c, g13/runner.c, scd/Makefile.am,
scd/apdu.c, scd/app.c, scd/ccid-driver.c, scd/command.c,
scd/scdaemon.c, tools/Makefile.am: Port to npth.
2012-01-03 22:12:37 +01:00
|
|
|
|
int err;
|
2007-06-14 19:05:07 +02:00
|
|
|
|
|
|
|
|
|
if (!initialized)
|
|
|
|
|
{
|
Port to npth.
* configure.ac: Don't check for PTH but for NPTH.
(AH_BOTTOM): Remove PTH_SYSCALL_SOFT.
(have_pth): Rename to ...
(have_npth): ... this.
(USE_GNU_NPTH): Rename to ...
(USE_GNU_PTH): ... this.
* m4/npth.m4: New file.
* agent/Makefile.am, agent/cache.c, agent/call-pinentry.c,
agent/call-scd.c, agent/findkey.c, agent/gpg-agent.c,
agent/trustlist.c, common/Makefile.am, common/estream.c,
common/exechelp-posix.c, common/exechelp-w32.c,
common/exechelp-w32ce.c, common/http.c, common/init.c,
common/sysutils.c, dirmngr/Makefile.am, dirmngr/crlfetch.c,
dirmngr/dirmngr.c, dirmngr/dirmngr_ldap.c, dirmngr/ldap-wrapper-ce.c,
dirmngr/ldap-wrapper.c, dirmngr/ldap.c, g13/Makefile.am,
g13/call-gpg.c, g13/g13.c, g13/runner.c, scd/Makefile.am,
scd/apdu.c, scd/app.c, scd/ccid-driver.c, scd/command.c,
scd/scdaemon.c, tools/Makefile.am: Port to npth.
2012-01-03 22:12:37 +01:00
|
|
|
|
err = npth_mutex_init (&trusttable_lock, NULL);
|
|
|
|
|
if (err)
|
2012-04-30 14:37:36 +02:00
|
|
|
|
log_fatal ("failed to init mutex in %s: %s\n", __FILE__,strerror (err));
|
2007-06-14 19:05:07 +02:00
|
|
|
|
initialized = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
lock_trusttable (void)
|
|
|
|
|
{
|
Port to npth.
* configure.ac: Don't check for PTH but for NPTH.
(AH_BOTTOM): Remove PTH_SYSCALL_SOFT.
(have_pth): Rename to ...
(have_npth): ... this.
(USE_GNU_NPTH): Rename to ...
(USE_GNU_PTH): ... this.
* m4/npth.m4: New file.
* agent/Makefile.am, agent/cache.c, agent/call-pinentry.c,
agent/call-scd.c, agent/findkey.c, agent/gpg-agent.c,
agent/trustlist.c, common/Makefile.am, common/estream.c,
common/exechelp-posix.c, common/exechelp-w32.c,
common/exechelp-w32ce.c, common/http.c, common/init.c,
common/sysutils.c, dirmngr/Makefile.am, dirmngr/crlfetch.c,
dirmngr/dirmngr.c, dirmngr/dirmngr_ldap.c, dirmngr/ldap-wrapper-ce.c,
dirmngr/ldap-wrapper.c, dirmngr/ldap.c, g13/Makefile.am,
g13/call-gpg.c, g13/g13.c, g13/runner.c, scd/Makefile.am,
scd/apdu.c, scd/app.c, scd/ccid-driver.c, scd/command.c,
scd/scdaemon.c, tools/Makefile.am: Port to npth.
2012-01-03 22:12:37 +01:00
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
err = npth_mutex_lock (&trusttable_lock);
|
|
|
|
|
if (err)
|
|
|
|
|
log_fatal ("failed to acquire mutex in %s: %s\n", __FILE__, strerror (err));
|
2003-06-05 09:14:21 +02:00
|
|
|
|
}
|
|
|
|
|
|
2012-04-30 14:37:36 +02:00
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
static void
|
|
|
|
|
unlock_trusttable (void)
|
|
|
|
|
{
|
Port to npth.
* configure.ac: Don't check for PTH but for NPTH.
(AH_BOTTOM): Remove PTH_SYSCALL_SOFT.
(have_pth): Rename to ...
(have_npth): ... this.
(USE_GNU_NPTH): Rename to ...
(USE_GNU_PTH): ... this.
* m4/npth.m4: New file.
* agent/Makefile.am, agent/cache.c, agent/call-pinentry.c,
agent/call-scd.c, agent/findkey.c, agent/gpg-agent.c,
agent/trustlist.c, common/Makefile.am, common/estream.c,
common/exechelp-posix.c, common/exechelp-w32.c,
common/exechelp-w32ce.c, common/http.c, common/init.c,
common/sysutils.c, dirmngr/Makefile.am, dirmngr/crlfetch.c,
dirmngr/dirmngr.c, dirmngr/dirmngr_ldap.c, dirmngr/ldap-wrapper-ce.c,
dirmngr/ldap-wrapper.c, dirmngr/ldap.c, g13/Makefile.am,
g13/call-gpg.c, g13/g13.c, g13/runner.c, scd/Makefile.am,
scd/apdu.c, scd/app.c, scd/ccid-driver.c, scd/command.c,
scd/scdaemon.c, tools/Makefile.am: Port to npth.
2012-01-03 22:12:37 +01:00
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
err = npth_mutex_unlock (&trusttable_lock);
|
|
|
|
|
if (err)
|
|
|
|
|
log_fatal ("failed to release mutex in %s: %s\n", __FILE__, strerror (err));
|
2006-09-15 20:53:37 +02:00
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
|
|
|
2012-04-30 14:37:36 +02:00
|
|
|
|
/* Clear the trusttable. The caller needs to make sure that the
|
|
|
|
|
trusttable is locked. */
|
|
|
|
|
static inline void
|
|
|
|
|
clear_trusttable (void)
|
|
|
|
|
{
|
|
|
|
|
xfree (trusttable);
|
|
|
|
|
trusttable = NULL;
|
|
|
|
|
trusttablesize = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
static gpg_error_t
|
|
|
|
|
read_one_trustfile (const char *fname, int allow_include,
|
2011-02-04 12:57:53 +01:00
|
|
|
|
trustitem_t **addr_of_table,
|
2006-09-15 20:53:37 +02:00
|
|
|
|
size_t *addr_of_tablesize,
|
|
|
|
|
int *addr_of_tableidx)
|
2003-06-05 09:14:21 +02:00
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
gpg_error_t err = 0;
|
2010-04-14 13:24:02 +02:00
|
|
|
|
estream_t fp;
|
2006-09-15 20:53:37 +02:00
|
|
|
|
int n, c;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
char *p, line[256];
|
2006-09-15 20:53:37 +02:00
|
|
|
|
trustitem_t *table, *ti;
|
|
|
|
|
int tableidx;
|
|
|
|
|
size_t tablesize;
|
|
|
|
|
int lnr = 0;
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
table = *addr_of_table;
|
|
|
|
|
tablesize = *addr_of_tablesize;
|
|
|
|
|
tableidx = *addr_of_tableidx;
|
|
|
|
|
|
2010-04-14 13:24:02 +02:00
|
|
|
|
fp = es_fopen (fname, "r");
|
2006-09-15 20:53:37 +02:00
|
|
|
|
if (!fp)
|
2003-06-05 09:14:21 +02:00
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
err = gpg_error_from_syserror ();
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error (_("error opening '%s': %s\n"), fname, gpg_strerror (err));
|
2006-09-15 20:53:37 +02:00
|
|
|
|
goto leave;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-04-14 13:24:02 +02:00
|
|
|
|
while (es_fgets (line, DIM(line)-1, fp))
|
2003-06-05 09:14:21 +02:00
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
lnr++;
|
2011-01-19 18:05:15 +01:00
|
|
|
|
|
|
|
|
|
n = strlen (line);
|
|
|
|
|
if (!n || line[n-1] != '\n')
|
2003-06-05 09:14:21 +02:00
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
/* Eat until end of line. */
|
2010-04-14 13:24:02 +02:00
|
|
|
|
while ( (c=es_getc (fp)) != EOF && c != '\n')
|
2003-06-05 09:14:21 +02:00
|
|
|
|
;
|
2006-09-15 20:53:37 +02:00
|
|
|
|
err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
|
|
|
|
|
: GPG_ERR_INCOMPLETE_LINE);
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error (_("file '%s', line %d: %s\n"),
|
2006-09-15 20:53:37 +02:00
|
|
|
|
fname, lnr, gpg_strerror (err));
|
|
|
|
|
continue;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
}
|
2011-01-19 18:05:15 +01:00
|
|
|
|
line[--n] = 0; /* Chop the LF. */
|
|
|
|
|
if (n && line[n-1] == '\r')
|
|
|
|
|
line[--n] = 0; /* Chop an optional CR. */
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2004-07-22 11:37:36 +02:00
|
|
|
|
/* Allow for empty lines and spaces */
|
2003-06-05 09:14:21 +02:00
|
|
|
|
for (p=line; spacep (p); p++)
|
|
|
|
|
;
|
2006-09-15 20:53:37 +02:00
|
|
|
|
if (!*p || *p == '#')
|
|
|
|
|
continue;
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
if (!strncmp (p, "include-default", 15)
|
|
|
|
|
&& (!p[15] || spacep (p+15)))
|
|
|
|
|
{
|
|
|
|
|
char *etcname;
|
|
|
|
|
gpg_error_t err2;
|
|
|
|
|
|
|
|
|
|
if (!allow_include)
|
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error (_("statement \"%s\" ignored in '%s', line %d\n"),
|
2006-09-15 20:53:37 +02:00
|
|
|
|
"include-default", fname, lnr);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
/* fixme: Should check for trailing garbage. */
|
|
|
|
|
|
2007-06-14 19:05:07 +02:00
|
|
|
|
etcname = make_filename (gnupg_sysconfdir (), "trustlist.txt", NULL);
|
2006-09-15 20:53:37 +02:00
|
|
|
|
if ( !strcmp (etcname, fname) ) /* Same file. */
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_info (_("statement \"%s\" ignored in '%s', line %d\n"),
|
2006-09-15 20:53:37 +02:00
|
|
|
|
"include-default", fname, lnr);
|
|
|
|
|
else if ( access (etcname, F_OK) && errno == ENOENT )
|
|
|
|
|
{
|
|
|
|
|
/* A non existent system trustlist is not an error.
|
|
|
|
|
Just print a note. */
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_info (_("system trustlist '%s' not available\n"), etcname);
|
2006-09-15 20:53:37 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
err2 = read_one_trustfile (etcname, 0,
|
|
|
|
|
&table, &tablesize, &tableidx);
|
|
|
|
|
if (err2)
|
|
|
|
|
err = err2;
|
|
|
|
|
}
|
|
|
|
|
xfree (etcname);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tableidx == tablesize) /* Need more space. */
|
|
|
|
|
{
|
|
|
|
|
trustitem_t *tmp;
|
|
|
|
|
size_t tmplen;
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
tmplen = tablesize + 20;
|
|
|
|
|
tmp = xtryrealloc (table, tmplen * sizeof *table);
|
|
|
|
|
if (!tmp)
|
|
|
|
|
{
|
|
|
|
|
err = gpg_error_from_syserror ();
|
|
|
|
|
goto leave;
|
|
|
|
|
}
|
|
|
|
|
table = tmp;
|
|
|
|
|
tablesize = tmplen;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ti = table + tableidx;
|
|
|
|
|
|
2009-03-19 11:21:51 +01:00
|
|
|
|
memset (&ti->flags, 0, sizeof ti->flags);
|
|
|
|
|
if (*p == '!')
|
|
|
|
|
{
|
|
|
|
|
ti->flags.disabled = 1;
|
|
|
|
|
p++;
|
|
|
|
|
while (spacep (p))
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
n = hexcolon2bin (p, ti->fpr, 20);
|
|
|
|
|
if (n < 0)
|
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error (_("bad fingerprint in '%s', line %d\n"), fname, lnr);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
err = gpg_error (GPG_ERR_BAD_DATA);
|
2006-09-15 20:53:37 +02:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
p += n;
|
|
|
|
|
for (; spacep (p); p++)
|
|
|
|
|
;
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2006-09-25 20:29:20 +02:00
|
|
|
|
/* Process the first flag which needs to be the first for
|
|
|
|
|
backward compatibility. */
|
|
|
|
|
if (!*p || *p == '*' )
|
|
|
|
|
{
|
|
|
|
|
ti->flags.for_smime = 1;
|
|
|
|
|
ti->flags.for_pgp = 1;
|
|
|
|
|
}
|
2006-09-15 20:53:37 +02:00
|
|
|
|
else if ( *p == 'P' || *p == 'p')
|
2006-09-25 20:29:20 +02:00
|
|
|
|
{
|
|
|
|
|
ti->flags.for_pgp = 1;
|
|
|
|
|
}
|
2006-09-15 20:53:37 +02:00
|
|
|
|
else if ( *p == 'S' || *p == 's')
|
2006-09-25 20:29:20 +02:00
|
|
|
|
{
|
|
|
|
|
ti->flags.for_smime = 1;
|
|
|
|
|
}
|
2006-09-15 20:53:37 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error (_("invalid keyflag in '%s', line %d\n"), fname, lnr);
|
2006-09-15 20:53:37 +02:00
|
|
|
|
err = gpg_error (GPG_ERR_BAD_DATA);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
p++;
|
|
|
|
|
if ( *p && !spacep (p) )
|
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error (_("invalid keyflag in '%s', line %d\n"), fname, lnr);
|
2006-09-15 20:53:37 +02:00
|
|
|
|
err = gpg_error (GPG_ERR_BAD_DATA);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2006-09-25 20:29:20 +02:00
|
|
|
|
|
|
|
|
|
/* Now check for more key-value pairs of the form NAME[=VALUE]. */
|
|
|
|
|
while (*p)
|
|
|
|
|
{
|
|
|
|
|
for (; spacep (p); p++)
|
|
|
|
|
;
|
|
|
|
|
if (!*p)
|
|
|
|
|
break;
|
|
|
|
|
n = strcspn (p, "= \t");
|
|
|
|
|
if (p[n] == '=')
|
|
|
|
|
{
|
|
|
|
|
log_error ("assigning a value to a flag is not yet supported; "
|
2012-06-05 19:29:22 +02:00
|
|
|
|
"in '%s', line %d\n", fname, lnr);
|
2006-09-25 20:29:20 +02:00
|
|
|
|
err = gpg_error (GPG_ERR_BAD_DATA);
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
else if (n == 5 && !memcmp (p, "relax", 5))
|
|
|
|
|
ti->flags.relax = 1;
|
2007-08-10 18:52:05 +02:00
|
|
|
|
else if (n == 2 && !memcmp (p, "cm", 2))
|
|
|
|
|
ti->flags.cm = 1;
|
2006-09-25 20:29:20 +02:00
|
|
|
|
else
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("flag '%.*s' in '%s', line %d ignored\n",
|
2006-09-25 20:29:20 +02:00
|
|
|
|
n, p, fname, lnr);
|
|
|
|
|
p += n;
|
|
|
|
|
}
|
2006-09-15 20:53:37 +02:00
|
|
|
|
tableidx++;
|
|
|
|
|
}
|
2010-04-14 13:24:02 +02:00
|
|
|
|
if ( !err && !es_feof (fp) )
|
2003-06-05 09:14:21 +02:00
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
err = gpg_error_from_syserror ();
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error (_("error reading '%s', line %d: %s\n"),
|
2006-09-15 20:53:37 +02:00
|
|
|
|
fname, lnr, gpg_strerror (err));
|
2003-06-05 09:14:21 +02:00
|
|
|
|
}
|
2006-09-15 20:53:37 +02:00
|
|
|
|
|
|
|
|
|
leave:
|
2010-04-14 13:24:02 +02:00
|
|
|
|
es_fclose (fp);
|
2006-09-15 20:53:37 +02:00
|
|
|
|
*addr_of_table = table;
|
|
|
|
|
*addr_of_tablesize = tablesize;
|
|
|
|
|
*addr_of_tableidx = tableidx;
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-04-30 14:37:36 +02:00
|
|
|
|
/* Read the trust files and update the global table on success. The
|
|
|
|
|
trusttable is assumed to be locked. */
|
2006-09-15 20:53:37 +02:00
|
|
|
|
static gpg_error_t
|
|
|
|
|
read_trustfiles (void)
|
|
|
|
|
{
|
|
|
|
|
gpg_error_t err;
|
|
|
|
|
trustitem_t *table, *ti;
|
|
|
|
|
int tableidx;
|
|
|
|
|
size_t tablesize;
|
|
|
|
|
char *fname;
|
|
|
|
|
int allow_include = 1;
|
|
|
|
|
|
2006-09-25 20:29:20 +02:00
|
|
|
|
tablesize = 20;
|
2006-09-15 20:53:37 +02:00
|
|
|
|
table = xtrycalloc (tablesize, sizeof *table);
|
|
|
|
|
if (!table)
|
|
|
|
|
return gpg_error_from_syserror ();
|
|
|
|
|
tableidx = 0;
|
|
|
|
|
|
2016-06-07 10:59:46 +02:00
|
|
|
|
fname = make_filename_try (gnupg_homedir (), "trustlist.txt", NULL);
|
|
|
|
|
if (!fname)
|
|
|
|
|
{
|
|
|
|
|
err = gpg_error_from_syserror ();
|
|
|
|
|
xfree (table);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
if ( access (fname, F_OK) )
|
2003-06-05 09:14:21 +02:00
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
if ( errno == ENOENT )
|
|
|
|
|
; /* Silently ignore a non-existing trustfile. */
|
2003-06-05 09:14:21 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
err = gpg_error_from_syserror ();
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error (_("error opening '%s': %s\n"), fname, gpg_strerror (err));
|
2003-06-05 09:14:21 +02:00
|
|
|
|
}
|
2006-09-15 20:53:37 +02:00
|
|
|
|
xfree (fname);
|
2007-06-14 19:05:07 +02:00
|
|
|
|
fname = make_filename (gnupg_sysconfdir (), "trustlist.txt", NULL);
|
2006-09-15 20:53:37 +02:00
|
|
|
|
allow_include = 0;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
}
|
2006-09-15 20:53:37 +02:00
|
|
|
|
err = read_one_trustfile (fname, allow_include,
|
|
|
|
|
&table, &tablesize, &tableidx);
|
|
|
|
|
xfree (fname);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
if (err)
|
|
|
|
|
{
|
|
|
|
|
xfree (table);
|
2007-04-03 20:43:00 +02:00
|
|
|
|
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
|
|
|
|
{
|
|
|
|
|
/* Take a missing trustlist as an empty one. */
|
2012-04-30 14:37:36 +02:00
|
|
|
|
clear_trusttable ();
|
2007-04-03 20:43:00 +02:00
|
|
|
|
err = 0;
|
|
|
|
|
}
|
2006-09-15 20:53:37 +02:00
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Fixme: we should drop duplicates and sort the table. */
|
2006-11-09 17:09:46 +01:00
|
|
|
|
ti = xtryrealloc (table, (tableidx?tableidx:1) * sizeof *table);
|
2006-09-15 20:53:37 +02:00
|
|
|
|
if (!ti)
|
|
|
|
|
{
|
2009-12-02 20:00:10 +01:00
|
|
|
|
err = gpg_error_from_syserror ();
|
2006-09-15 20:53:37 +02:00
|
|
|
|
xfree (table);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-30 14:37:36 +02:00
|
|
|
|
/* Replace the trusttable. */
|
2006-09-15 20:53:37 +02:00
|
|
|
|
xfree (trusttable);
|
2009-12-02 20:00:10 +01:00
|
|
|
|
trusttable = ti;
|
2006-09-15 20:53:37 +02:00
|
|
|
|
trusttablesize = tableidx;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
|
2004-05-11 21:11:53 +02:00
|
|
|
|
/* Check whether the given fpr is in our trustdb. We expect FPR to be
|
2012-04-30 14:37:36 +02:00
|
|
|
|
an all uppercase hexstring of 40 characters. If ALREADY_LOCKED is
|
|
|
|
|
true the function assumes that the trusttable is already locked. */
|
|
|
|
|
static gpg_error_t
|
|
|
|
|
istrusted_internal (ctrl_t ctrl, const char *fpr, int *r_disabled,
|
|
|
|
|
int already_locked)
|
2003-06-05 09:14:21 +02:00
|
|
|
|
{
|
2015-11-19 16:18:20 +01:00
|
|
|
|
gpg_error_t err = 0;
|
2012-04-30 14:37:36 +02:00
|
|
|
|
int locked = already_locked;
|
2006-09-15 20:53:37 +02:00
|
|
|
|
trustitem_t *ti;
|
|
|
|
|
size_t len;
|
|
|
|
|
unsigned char fprbin[20];
|
|
|
|
|
|
2009-03-19 11:21:51 +01:00
|
|
|
|
if (r_disabled)
|
|
|
|
|
*r_disabled = 0;
|
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
if ( hexcolon2bin (fpr, fprbin, 20) < 0 )
|
2012-04-30 14:37:36 +02:00
|
|
|
|
{
|
|
|
|
|
err = gpg_error (GPG_ERR_INV_VALUE);
|
|
|
|
|
goto leave;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!already_locked)
|
|
|
|
|
{
|
|
|
|
|
lock_trusttable ();
|
|
|
|
|
locked = 1;
|
|
|
|
|
}
|
2006-09-15 20:53:37 +02:00
|
|
|
|
|
|
|
|
|
if (!trusttable)
|
2003-06-05 09:14:21 +02:00
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
err = read_trustfiles ();
|
|
|
|
|
if (err)
|
2004-05-11 21:11:53 +02:00
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
log_error (_("error reading list of trusted root certificates\n"));
|
2012-04-30 14:37:36 +02:00
|
|
|
|
goto leave;
|
2004-05-11 21:11:53 +02:00
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
}
|
2006-09-15 20:53:37 +02:00
|
|
|
|
|
|
|
|
|
if (trusttable)
|
2003-06-05 09:14:21 +02:00
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
for (ti=trusttable, len = trusttablesize; len; ti++, len--)
|
|
|
|
|
if (!memcmp (ti->fpr, fprbin, 20))
|
2006-09-25 20:29:20 +02:00
|
|
|
|
{
|
2009-03-26 12:33:53 +01:00
|
|
|
|
if (ti->flags.disabled && r_disabled)
|
|
|
|
|
*r_disabled = 1;
|
|
|
|
|
|
2012-04-30 14:37:36 +02:00
|
|
|
|
/* Print status messages only if we have not been called
|
|
|
|
|
in a locked state. */
|
|
|
|
|
if (already_locked)
|
|
|
|
|
;
|
|
|
|
|
else if (ti->flags.relax)
|
2006-09-25 20:29:20 +02:00
|
|
|
|
{
|
2012-04-30 14:37:36 +02:00
|
|
|
|
unlock_trusttable ();
|
|
|
|
|
locked = 0;
|
|
|
|
|
err = agent_write_status (ctrl, "TRUSTLISTFLAG", "relax", NULL);
|
2006-09-25 20:29:20 +02:00
|
|
|
|
}
|
2007-08-10 18:52:05 +02:00
|
|
|
|
else if (ti->flags.cm)
|
|
|
|
|
{
|
2012-04-30 14:37:36 +02:00
|
|
|
|
unlock_trusttable ();
|
|
|
|
|
locked = 0;
|
|
|
|
|
err = agent_write_status (ctrl, "TRUSTLISTFLAG", "cm", NULL);
|
2007-08-10 18:52:05 +02:00
|
|
|
|
}
|
2012-04-30 14:37:36 +02:00
|
|
|
|
|
|
|
|
|
if (!err)
|
|
|
|
|
err = ti->flags.disabled? gpg_error (GPG_ERR_NOT_TRUSTED) : 0;
|
|
|
|
|
goto leave;
|
2006-09-25 20:29:20 +02:00
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
}
|
2012-04-30 14:37:36 +02:00
|
|
|
|
err = gpg_error (GPG_ERR_NOT_TRUSTED);
|
|
|
|
|
|
|
|
|
|
leave:
|
|
|
|
|
if (locked && !already_locked)
|
|
|
|
|
unlock_trusttable ();
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Check whether the given fpr is in our trustdb. We expect FPR to be
|
|
|
|
|
an all uppercase hexstring of 40 characters. */
|
|
|
|
|
gpg_error_t
|
|
|
|
|
agent_istrusted (ctrl_t ctrl, const char *fpr, int *r_disabled)
|
|
|
|
|
{
|
|
|
|
|
return istrusted_internal (ctrl, fpr, r_disabled, 0);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-05-11 21:11:53 +02:00
|
|
|
|
/* Write all trust entries to FP. */
|
2011-02-04 12:57:53 +01:00
|
|
|
|
gpg_error_t
|
2003-06-05 09:14:21 +02:00
|
|
|
|
agent_listtrusted (void *assuan_context)
|
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
trustitem_t *ti;
|
|
|
|
|
char key[51];
|
|
|
|
|
gpg_error_t err;
|
|
|
|
|
size_t len;
|
|
|
|
|
|
2012-04-30 14:37:36 +02:00
|
|
|
|
lock_trusttable ();
|
2006-09-15 20:53:37 +02:00
|
|
|
|
if (!trusttable)
|
2003-06-05 09:14:21 +02:00
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
err = read_trustfiles ();
|
|
|
|
|
if (err)
|
|
|
|
|
{
|
2012-04-30 14:37:36 +02:00
|
|
|
|
unlock_trusttable ();
|
2006-09-15 20:53:37 +02:00
|
|
|
|
log_error (_("error reading list of trusted root certificates\n"));
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (trusttable)
|
2003-06-05 09:14:21 +02:00
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
for (ti=trusttable, len = trusttablesize; len; ti++, len--)
|
|
|
|
|
{
|
2009-03-19 11:21:51 +01:00
|
|
|
|
if (ti->flags.disabled)
|
|
|
|
|
continue;
|
2006-09-15 20:53:37 +02:00
|
|
|
|
bin2hex (ti->fpr, 20, key);
|
|
|
|
|
key[40] = ' ';
|
2006-09-25 20:29:20 +02:00
|
|
|
|
key[41] = ((ti->flags.for_smime && ti->flags.for_pgp)? '*'
|
|
|
|
|
: ti->flags.for_smime? 'S': ti->flags.for_pgp? 'P':' ');
|
2006-09-15 20:53:37 +02:00
|
|
|
|
key[42] = '\n';
|
|
|
|
|
assuan_send_data (assuan_context, key, 43);
|
|
|
|
|
assuan_send_data (assuan_context, NULL, 0); /* flush */
|
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
}
|
2006-09-15 20:53:37 +02:00
|
|
|
|
|
2012-04-30 14:37:36 +02:00
|
|
|
|
unlock_trusttable ();
|
2006-09-15 20:53:37 +02:00
|
|
|
|
return 0;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-08-27 20:10:27 +02:00
|
|
|
|
/* Create a copy of string with colons inserted after each two bytes.
|
|
|
|
|
Caller needs to release the string. In case of a memory failure,
|
|
|
|
|
NULL is returned. */
|
|
|
|
|
static char *
|
|
|
|
|
insert_colons (const char *string)
|
|
|
|
|
{
|
|
|
|
|
char *buffer, *p;
|
|
|
|
|
size_t n = strlen (string);
|
2008-05-27 14:03:50 +02:00
|
|
|
|
size_t nnew = n + (n+1)/2;
|
2007-08-27 20:10:27 +02:00
|
|
|
|
|
2008-05-27 14:03:50 +02:00
|
|
|
|
p = buffer = xtrymalloc ( nnew + 1 );
|
2007-08-27 20:10:27 +02:00
|
|
|
|
if (!buffer)
|
|
|
|
|
return NULL;
|
|
|
|
|
while (*string)
|
|
|
|
|
{
|
|
|
|
|
*p++ = *string++;
|
|
|
|
|
if (*string)
|
|
|
|
|
{
|
|
|
|
|
*p++ = *string++;
|
|
|
|
|
if (*string)
|
|
|
|
|
*p++ = ':';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*p = 0;
|
2019-05-14 10:31:46 +02:00
|
|
|
|
log_assert (strlen (buffer) <= nnew);
|
2007-08-27 20:10:27 +02:00
|
|
|
|
|
|
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-03-26 12:33:53 +01:00
|
|
|
|
/* To pretty print DNs in the Pinentry, we replace slashes by
|
|
|
|
|
REPLSTRING. The caller needs to free the returned string. NULL is
|
|
|
|
|
returned on error with ERRNO set. */
|
|
|
|
|
static char *
|
|
|
|
|
reformat_name (const char *name, const char *replstring)
|
|
|
|
|
{
|
|
|
|
|
const char *s;
|
|
|
|
|
char *newname;
|
|
|
|
|
char *d;
|
|
|
|
|
size_t count;
|
|
|
|
|
size_t replstringlen = strlen (replstring);
|
|
|
|
|
|
|
|
|
|
/* If the name does not start with a slash it is not a preformatted
|
|
|
|
|
DN and thus we don't bother to reformat it. */
|
|
|
|
|
if (*name != '/')
|
|
|
|
|
return xtrystrdup (name);
|
|
|
|
|
|
|
|
|
|
/* Count the names. Note that a slash contained in a DN part is
|
|
|
|
|
expected to be C style escaped and thus the slashes we see here
|
|
|
|
|
are the actual part delimiters. */
|
|
|
|
|
for (s=name+1, count=0; *s; s++)
|
|
|
|
|
if (*s == '/')
|
|
|
|
|
count++;
|
|
|
|
|
newname = xtrymalloc (strlen (name) + count*replstringlen + 1);
|
|
|
|
|
if (!newname)
|
2011-02-04 12:57:53 +01:00
|
|
|
|
return NULL;
|
2009-03-26 12:33:53 +01:00
|
|
|
|
for (s=name+1, d=newname; *s; s++)
|
|
|
|
|
if (*s == '/')
|
|
|
|
|
d = stpcpy (d, replstring);
|
|
|
|
|
else
|
|
|
|
|
*d++ = *s;
|
|
|
|
|
*d = 0;
|
|
|
|
|
return newname;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
|
/* Insert the given fpr into our trustdb. We expect FPR to be an all
|
|
|
|
|
uppercase hexstring of 40 characters. FLAG is either 'P' or 'C'.
|
2012-04-30 14:37:36 +02:00
|
|
|
|
This function does first check whether that key has already been
|
|
|
|
|
put into the trustdb and returns success in this case. Before a
|
|
|
|
|
FPR actually gets inserted, the user is asked by means of the
|
|
|
|
|
Pinentry whether this is actual what he wants to do. */
|
2006-09-15 20:53:37 +02:00
|
|
|
|
gpg_error_t
|
2006-09-06 18:35:52 +02:00
|
|
|
|
agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag)
|
2003-06-05 09:14:21 +02:00
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
gpg_error_t err = 0;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
char *desc;
|
2004-01-28 17:19:46 +01:00
|
|
|
|
char *fname;
|
2009-06-03 19:24:24 +02:00
|
|
|
|
estream_t fp;
|
2007-08-27 20:10:27 +02:00
|
|
|
|
char *fprformatted;
|
2009-03-26 12:33:53 +01:00
|
|
|
|
char *nameformatted;
|
2009-03-19 11:21:51 +01:00
|
|
|
|
int is_disabled;
|
|
|
|
|
int yes_i_trust;
|
2004-01-28 17:19:46 +01:00
|
|
|
|
|
|
|
|
|
/* Check whether we are at all allowed to modify the trustlist.
|
|
|
|
|
This is useful so that the trustlist may be a symlink to a global
|
2017-04-28 03:06:33 +02:00
|
|
|
|
trustlist with only admin privileges to modify it. Of course
|
2004-01-28 17:19:46 +01:00
|
|
|
|
this is not a secure way of denying access, but it avoids the
|
2006-09-15 20:53:37 +02:00
|
|
|
|
usual clicking on an Okay button most users are used to. */
|
2016-06-07 10:59:46 +02:00
|
|
|
|
fname = make_filename_try (gnupg_homedir (), "trustlist.txt", NULL);
|
|
|
|
|
if (!fname)
|
|
|
|
|
return gpg_error_from_syserror ();
|
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
if ( access (fname, W_OK) && errno != ENOENT)
|
2004-01-28 17:19:46 +01:00
|
|
|
|
{
|
|
|
|
|
xfree (fname);
|
|
|
|
|
return gpg_error (GPG_ERR_EPERM);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
}
|
2004-01-28 17:19:46 +01:00
|
|
|
|
xfree (fname);
|
|
|
|
|
|
2009-03-19 11:21:51 +01:00
|
|
|
|
if (!agent_istrusted (ctrl, fpr, &is_disabled))
|
2003-06-05 09:14:21 +02:00
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
return 0; /* We already got this fingerprint. Silently return
|
|
|
|
|
success. */
|
2004-05-11 21:11:53 +02:00
|
|
|
|
}
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2004-05-03 15:37:38 +02:00
|
|
|
|
/* This feature must explicitly been enabled. */
|
|
|
|
|
if (!opt.allow_mark_trusted)
|
2006-09-15 20:53:37 +02:00
|
|
|
|
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
2004-05-03 15:37:38 +02:00
|
|
|
|
|
2009-03-19 11:21:51 +01:00
|
|
|
|
if (is_disabled)
|
2007-08-27 20:10:27 +02:00
|
|
|
|
{
|
2009-03-19 11:21:51 +01:00
|
|
|
|
/* There is an disabled entry in the trustlist. Return an error
|
|
|
|
|
so that the user won't be asked again for that one. Changing
|
|
|
|
|
this flag with the integrated marktrusted feature is and will
|
|
|
|
|
not be made possible. */
|
|
|
|
|
return gpg_error (GPG_ERR_NOT_TRUSTED);
|
2007-08-27 20:10:27 +02:00
|
|
|
|
}
|
2006-10-16 19:36:44 +02:00
|
|
|
|
|
|
|
|
|
|
2009-03-19 11:21:51 +01:00
|
|
|
|
/* Insert a new one. */
|
2009-03-26 12:33:53 +01:00
|
|
|
|
nameformatted = reformat_name (name, "%0A ");
|
|
|
|
|
if (!nameformatted)
|
|
|
|
|
return gpg_error_from_syserror ();
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
2009-03-19 11:21:51 +01:00
|
|
|
|
/* First a general question whether this is trusted. */
|
2008-05-27 14:03:50 +02:00
|
|
|
|
desc = xtryasprintf (
|
2005-01-13 19:00:46 +01:00
|
|
|
|
/* TRANSLATORS: This prompt is shown by the Pinentry
|
|
|
|
|
and has one special property: A "%%0A" is used by
|
|
|
|
|
Pinentry to insert a line break. The double
|
|
|
|
|
percent sign is actually needed because it is also
|
|
|
|
|
a printf format string. If you need to insert a
|
|
|
|
|
plain % sign, you need to encode it as "%%25". The
|
2009-03-26 12:33:53 +01:00
|
|
|
|
"%s" gets replaced by the name as stored in the
|
2005-01-13 19:00:46 +01:00
|
|
|
|
certificate. */
|
2015-06-30 21:58:02 +02:00
|
|
|
|
L_("Do you ultimately trust%%0A"
|
|
|
|
|
" \"%s\"%%0A"
|
|
|
|
|
"to correctly certify user certificates?"),
|
2009-03-26 12:33:53 +01:00
|
|
|
|
nameformatted);
|
2008-05-27 14:03:50 +02:00
|
|
|
|
if (!desc)
|
2009-03-26 12:33:53 +01:00
|
|
|
|
{
|
|
|
|
|
xfree (nameformatted);
|
|
|
|
|
return out_of_core ();
|
|
|
|
|
}
|
2015-06-30 21:58:02 +02:00
|
|
|
|
err = agent_get_confirmation (ctrl, desc, L_("Yes"), L_("No"), 1);
|
2008-05-27 14:03:50 +02:00
|
|
|
|
xfree (desc);
|
2009-03-19 11:21:51 +01:00
|
|
|
|
if (!err)
|
|
|
|
|
yes_i_trust = 1;
|
|
|
|
|
else if (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED)
|
|
|
|
|
yes_i_trust = 0;
|
|
|
|
|
else
|
2009-03-26 12:33:53 +01:00
|
|
|
|
{
|
|
|
|
|
xfree (nameformatted);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2009-03-19 11:21:51 +01:00
|
|
|
|
|
|
|
|
|
fprformatted = insert_colons (fpr);
|
|
|
|
|
if (!fprformatted)
|
2009-03-26 12:33:53 +01:00
|
|
|
|
{
|
|
|
|
|
xfree (nameformatted);
|
|
|
|
|
return out_of_core ();
|
|
|
|
|
}
|
2009-03-19 11:21:51 +01:00
|
|
|
|
|
|
|
|
|
/* If the user trusts this certificate he has to verify the
|
|
|
|
|
fingerprint of course. */
|
|
|
|
|
if (yes_i_trust)
|
2007-08-27 20:10:27 +02:00
|
|
|
|
{
|
2011-02-04 12:57:53 +01:00
|
|
|
|
desc = xtryasprintf
|
2009-03-19 11:21:51 +01:00
|
|
|
|
(
|
|
|
|
|
/* TRANSLATORS: This prompt is shown by the Pinentry and has
|
|
|
|
|
one special property: A "%%0A" is used by Pinentry to
|
|
|
|
|
insert a line break. The double percent sign is actually
|
|
|
|
|
needed because it is also a printf format string. If you
|
|
|
|
|
need to insert a plain % sign, you need to encode it as
|
|
|
|
|
"%%25". The second "%s" gets replaced by a hexdecimal
|
|
|
|
|
fingerprint string whereas the first one receives the name
|
|
|
|
|
as stored in the certificate. */
|
2015-06-30 21:58:02 +02:00
|
|
|
|
L_("Please verify that the certificate identified as:%%0A"
|
|
|
|
|
" \"%s\"%%0A"
|
|
|
|
|
"has the fingerprint:%%0A"
|
|
|
|
|
" %s"), nameformatted, fprformatted);
|
2009-03-19 11:21:51 +01:00
|
|
|
|
if (!desc)
|
|
|
|
|
{
|
|
|
|
|
xfree (fprformatted);
|
2009-03-26 12:33:53 +01:00
|
|
|
|
xfree (nameformatted);
|
2009-03-19 11:21:51 +01:00
|
|
|
|
return out_of_core ();
|
|
|
|
|
}
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2009-03-19 11:21:51 +01:00
|
|
|
|
/* TRANSLATORS: "Correct" is the label of a button and intended
|
|
|
|
|
to be hit if the fingerprint matches the one of the CA. The
|
|
|
|
|
other button is "the default "Cancel" of the Pinentry. */
|
2015-06-30 21:58:02 +02:00
|
|
|
|
err = agent_get_confirmation (ctrl, desc, L_("Correct"), L_("Wrong"), 1);
|
2009-03-19 11:21:51 +01:00
|
|
|
|
xfree (desc);
|
|
|
|
|
if (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED)
|
|
|
|
|
yes_i_trust = 0;
|
|
|
|
|
else if (err)
|
|
|
|
|
{
|
|
|
|
|
xfree (fprformatted);
|
2009-03-26 12:33:53 +01:00
|
|
|
|
xfree (nameformatted);
|
2009-03-19 11:21:51 +01:00
|
|
|
|
return err;
|
|
|
|
|
}
|
2007-08-27 20:10:27 +02:00
|
|
|
|
}
|
2006-09-15 20:53:37 +02:00
|
|
|
|
|
2009-03-19 11:21:51 +01:00
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
/* Now check again to avoid duplicates. We take the lock to make
|
2009-03-26 12:33:53 +01:00
|
|
|
|
sure that nobody else plays with our file and force a reread. */
|
2006-09-15 20:53:37 +02:00
|
|
|
|
lock_trusttable ();
|
2012-04-30 14:37:36 +02:00
|
|
|
|
clear_trusttable ();
|
|
|
|
|
if (!istrusted_internal (ctrl, fpr, &is_disabled, 1) || is_disabled)
|
2009-03-26 12:33:53 +01:00
|
|
|
|
{
|
|
|
|
|
unlock_trusttable ();
|
|
|
|
|
xfree (fprformatted);
|
|
|
|
|
xfree (nameformatted);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
return is_disabled? gpg_error (GPG_ERR_NOT_TRUSTED) : 0;
|
2009-03-26 12:33:53 +01:00
|
|
|
|
}
|
2006-09-15 20:53:37 +02:00
|
|
|
|
|
2016-06-07 10:59:46 +02:00
|
|
|
|
fname = make_filename_try (gnupg_homedir (), "trustlist.txt", NULL);
|
|
|
|
|
if (!fname)
|
|
|
|
|
{
|
|
|
|
|
err = gpg_error_from_syserror ();
|
|
|
|
|
unlock_trusttable ();
|
|
|
|
|
xfree (fprformatted);
|
|
|
|
|
xfree (nameformatted);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
2006-09-15 20:53:37 +02:00
|
|
|
|
if ( access (fname, F_OK) && errno == ENOENT)
|
2003-06-05 09:14:21 +02:00
|
|
|
|
{
|
2010-08-26 10:47:42 +02:00
|
|
|
|
fp = es_fopen (fname, "wx,mode=-rw-r");
|
2006-09-15 20:53:37 +02:00
|
|
|
|
if (!fp)
|
2004-05-11 21:11:53 +02:00
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
err = gpg_error_from_syserror ();
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("can't create '%s': %s\n", fname, gpg_strerror (err));
|
2006-09-15 20:53:37 +02:00
|
|
|
|
xfree (fname);
|
|
|
|
|
unlock_trusttable ();
|
2007-08-27 20:10:27 +02:00
|
|
|
|
xfree (fprformatted);
|
2009-03-26 12:33:53 +01:00
|
|
|
|
xfree (nameformatted);
|
2006-09-15 20:53:37 +02:00
|
|
|
|
return err;
|
2004-05-11 21:11:53 +02:00
|
|
|
|
}
|
2009-06-03 19:24:24 +02:00
|
|
|
|
es_fputs (headerblurb, fp);
|
|
|
|
|
es_fclose (fp);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
}
|
2010-08-26 10:47:42 +02:00
|
|
|
|
fp = es_fopen (fname, "a+,mode=-rw-r");
|
2006-09-15 20:53:37 +02:00
|
|
|
|
if (!fp)
|
2003-06-05 09:14:21 +02:00
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
err = gpg_error_from_syserror ();
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("can't open '%s': %s\n", fname, gpg_strerror (err));
|
2006-09-15 20:53:37 +02:00
|
|
|
|
xfree (fname);
|
|
|
|
|
unlock_trusttable ();
|
2007-08-27 20:10:27 +02:00
|
|
|
|
xfree (fprformatted);
|
2009-03-26 12:33:53 +01:00
|
|
|
|
xfree (nameformatted);
|
2006-09-15 20:53:37 +02:00
|
|
|
|
return err;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
}
|
|
|
|
|
|
2004-05-11 21:11:53 +02:00
|
|
|
|
/* Append the key. */
|
2009-06-03 19:24:24 +02:00
|
|
|
|
es_fputs ("\n# ", fp);
|
2009-03-26 12:33:53 +01:00
|
|
|
|
xfree (nameformatted);
|
|
|
|
|
nameformatted = reformat_name (name, "\n# ");
|
|
|
|
|
if (!nameformatted || strchr (name, '\n'))
|
|
|
|
|
{
|
|
|
|
|
/* Note that there should never be a LF in NAME but we better
|
|
|
|
|
play safe and print a sanitized version in this case. */
|
2009-06-03 19:24:24 +02:00
|
|
|
|
es_write_sanitized (fp, name, strlen (name), NULL, NULL);
|
2009-03-26 12:33:53 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
2009-06-03 19:24:24 +02:00
|
|
|
|
es_fputs (nameformatted, fp);
|
2013-07-03 15:20:25 +02:00
|
|
|
|
es_fprintf (fp, "\n%s%s %c%s\n", yes_i_trust?"":"!", fprformatted, flag,
|
|
|
|
|
flag == 'S'? " relax":"");
|
2009-06-03 19:24:24 +02:00
|
|
|
|
if (es_ferror (fp))
|
2006-09-15 20:53:37 +02:00
|
|
|
|
err = gpg_error_from_syserror ();
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2009-06-03 19:24:24 +02:00
|
|
|
|
if (es_fclose (fp))
|
2006-09-15 20:53:37 +02:00
|
|
|
|
err = gpg_error_from_syserror ();
|
2004-05-11 21:11:53 +02:00
|
|
|
|
|
2012-04-30 14:37:36 +02:00
|
|
|
|
clear_trusttable ();
|
2006-09-15 20:53:37 +02:00
|
|
|
|
xfree (fname);
|
|
|
|
|
unlock_trusttable ();
|
2007-08-27 20:10:27 +02:00
|
|
|
|
xfree (fprformatted);
|
2009-03-26 12:33:53 +01:00
|
|
|
|
xfree (nameformatted);
|
2012-04-30 14:37:36 +02:00
|
|
|
|
if (!err)
|
|
|
|
|
bump_key_eventcounter ();
|
2006-09-15 20:53:37 +02:00
|
|
|
|
return err;
|
2004-05-11 21:11:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-09-15 20:53:37 +02:00
|
|
|
|
/* This function may be called to force reloading of the
|
|
|
|
|
trustlist. */
|
2004-05-11 21:11:53 +02:00
|
|
|
|
void
|
|
|
|
|
agent_reload_trustlist (void)
|
|
|
|
|
{
|
2006-09-15 20:53:37 +02:00
|
|
|
|
/* All we need to do is to delete the trusttable. At the next
|
|
|
|
|
access it will get re-read. */
|
|
|
|
|
lock_trusttable ();
|
2012-04-30 14:37:36 +02:00
|
|
|
|
clear_trusttable ();
|
2006-09-15 20:53:37 +02:00
|
|
|
|
unlock_trusttable ();
|
2006-11-14 15:53:42 +01:00
|
|
|
|
bump_key_eventcounter ();
|
2004-05-11 21:11:53 +02:00
|
|
|
|
}
|