mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Changed order of the confirmation questions for root certificates
and stores negative answers in trustlist.txt.
This commit is contained in:
parent
588a7c34bb
commit
c2c3cf4be1
7
NEWS
7
NEWS
@ -7,8 +7,11 @@ Noteworthy changes in version 2.0.12
|
|||||||
* New command "KEYINFO" for GPG_AGENT. GPGSM now also returns
|
* New command "KEYINFO" for GPG_AGENT. GPGSM now also returns
|
||||||
information about smartcards.
|
information about smartcards.
|
||||||
|
|
||||||
* Make sure not to leak file descriptors if running gpg-agent with a
|
* Made sure not to leak file descriptors if running gpg-agent with a
|
||||||
command. Restore the signal mask to solve a problem in Mono.
|
command. Restores the signal mask to solve a problem in Mono.
|
||||||
|
|
||||||
|
* Changed order of the confirmation questions for root certificates
|
||||||
|
and stores negative answers in trustlist.txt.
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 2.0.11 (2009-03-03)
|
Noteworthy changes in version 2.0.11 (2009-03-03)
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
2009-03-19 Werner Koch <wk@g10code.com>
|
2009-03-19 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* trustlist.c (struct trustitem_s): Add field DISABLED.
|
||||||
|
(read_one_trustfile): Parse the '!' flag.
|
||||||
|
(agent_istrusted, agent_listtrusted): Check flag.
|
||||||
|
(agent_istrusted): Add arg R_DISABLED. Change all callers.
|
||||||
|
(agent_marktrusted): Do not ask if flagged as disabled. Reverse
|
||||||
|
the order of the questions. Store the disabled flag.
|
||||||
|
|
||||||
* gpg-agent.c (main): Save signal mask and open fds. Restore mask
|
* gpg-agent.c (main): Save signal mask and open fds. Restore mask
|
||||||
and close all fds prior to the exec. Fixes bug#1013.
|
and close all fds prior to the exec. Fixes bug#1013.
|
||||||
|
|
||||||
|
@ -303,7 +303,7 @@ gpg_error_t parse_shadow_info (const unsigned char *shadow_info,
|
|||||||
|
|
||||||
/*-- trustlist.c --*/
|
/*-- trustlist.c --*/
|
||||||
void initialize_module_trustlist (void);
|
void initialize_module_trustlist (void);
|
||||||
gpg_error_t agent_istrusted (ctrl_t ctrl, const char *fpr);
|
gpg_error_t agent_istrusted (ctrl_t ctrl, const char *fpr, int *r_disabled);
|
||||||
gpg_error_t agent_listtrusted (void *assuan_context);
|
gpg_error_t agent_listtrusted (void *assuan_context);
|
||||||
gpg_error_t agent_marktrusted (ctrl_t ctrl, const char *name,
|
gpg_error_t agent_marktrusted (ctrl_t ctrl, const char *name,
|
||||||
const char *fpr, int flag);
|
const char *fpr, int flag);
|
||||||
|
@ -461,7 +461,7 @@ cmd_istrusted (assuan_context_t ctx, char *line)
|
|||||||
for (p=line; i < 40; p++, i++)
|
for (p=line; i < 40; p++, i++)
|
||||||
fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
|
fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
|
||||||
fpr[i] = 0;
|
fpr[i] = 0;
|
||||||
rc = agent_istrusted (ctrl, fpr);
|
rc = agent_istrusted (ctrl, fpr, NULL);
|
||||||
if (!rc || gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
|
if (!rc || gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
|
||||||
return rc;
|
return rc;
|
||||||
else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF )
|
else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF )
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* trustlist.c - Maintain the list of trusted keys
|
/* trustlist.c - Maintain the list of trusted keys
|
||||||
* Copyright (C) 2002, 2004, 2006, 2007 Free Software Foundation, Inc.
|
* Copyright (C) 2002, 2004, 2006, 2007, 2009 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -38,6 +38,7 @@ struct trustitem_s
|
|||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
int disabled:1; /* This entry is disabled. */
|
||||||
int for_pgp:1; /* Set by '*' or 'P' as first flag. */
|
int for_pgp:1; /* Set by '*' or 'P' as first flag. */
|
||||||
int for_smime:1; /* Set by '*' or 'S' as first flag. */
|
int for_smime:1; /* Set by '*' or 'S' as first flag. */
|
||||||
int relax:1; /* Relax checking of root certificate
|
int relax:1; /* Relax checking of root certificate
|
||||||
@ -59,11 +60,13 @@ static pth_mutex_t trusttable_lock;
|
|||||||
static const char headerblurb[] =
|
static const char headerblurb[] =
|
||||||
"# This is the list of trusted keys. Comment lines, like this one, as\n"
|
"# 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"
|
"# well as empty lines are ignored. Lines have a length limit but this\n"
|
||||||
"# is not serious limitation as the format of the entries is fixed and\n"
|
"# is not a serious limitation as the format of the entries is fixed and\n"
|
||||||
"# checked by gpg-agent. A non-comment line starts with optional white\n"
|
"# checked by gpg-agent. A non-comment line starts with optional white\n"
|
||||||
"# space, followed by the SHA-1 fingerpint in hex, optionally followed\n"
|
"# space, followed by the SHA-1 fingerpint in hex, followed by a flag\n"
|
||||||
"# by a flag character which my either be 'P', 'S' or '*'. You should\n"
|
"# which may be one of 'P', 'S' or '*' and optionally followed by a list of\n"
|
||||||
"# give the gpg-agent a HUP after editing this file.\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"
|
||||||
"\n\n"
|
"\n\n"
|
||||||
"# Include the default trust list\n"
|
"# Include the default trust list\n"
|
||||||
"include-default\n"
|
"include-default\n"
|
||||||
@ -120,7 +123,7 @@ read_one_trustfile (const char *fname, int allow_include,
|
|||||||
int tableidx;
|
int tableidx;
|
||||||
size_t tablesize;
|
size_t tablesize;
|
||||||
int lnr = 0;
|
int lnr = 0;
|
||||||
|
|
||||||
table = *addr_of_table;
|
table = *addr_of_table;
|
||||||
tablesize = *addr_of_tablesize;
|
tablesize = *addr_of_tablesize;
|
||||||
tableidx = *addr_of_tableidx;
|
tableidx = *addr_of_tableidx;
|
||||||
@ -210,6 +213,15 @@ read_one_trustfile (const char *fname, int allow_include,
|
|||||||
|
|
||||||
ti = table + tableidx;
|
ti = table + tableidx;
|
||||||
|
|
||||||
|
memset (&ti->flags, 0, sizeof ti->flags);
|
||||||
|
if (*p == '!')
|
||||||
|
{
|
||||||
|
ti->flags.disabled = 1;
|
||||||
|
p++;
|
||||||
|
while (spacep (p))
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
n = hexcolon2bin (p, ti->fpr, 20);
|
n = hexcolon2bin (p, ti->fpr, 20);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
{
|
{
|
||||||
@ -221,7 +233,6 @@ read_one_trustfile (const char *fname, int allow_include,
|
|||||||
for (; spacep (p); p++)
|
for (; spacep (p); p++)
|
||||||
;
|
;
|
||||||
|
|
||||||
memset (&ti->flags, 0, sizeof ti->flags);
|
|
||||||
/* Process the first flag which needs to be the first for
|
/* Process the first flag which needs to be the first for
|
||||||
backward compatibility. */
|
backward compatibility. */
|
||||||
if (!*p || *p == '*' )
|
if (!*p || *p == '*' )
|
||||||
@ -366,13 +377,16 @@ read_trustfiles (void)
|
|||||||
/* Check whether the given fpr is in our trustdb. We expect FPR to be
|
/* Check whether the given fpr is in our trustdb. We expect FPR to be
|
||||||
an all uppercase hexstring of 40 characters. */
|
an all uppercase hexstring of 40 characters. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
agent_istrusted (ctrl_t ctrl, const char *fpr)
|
agent_istrusted (ctrl_t ctrl, const char *fpr, int *r_disabled)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
trustitem_t *ti;
|
trustitem_t *ti;
|
||||||
size_t len;
|
size_t len;
|
||||||
unsigned char fprbin[20];
|
unsigned char fprbin[20];
|
||||||
|
|
||||||
|
if (r_disabled)
|
||||||
|
*r_disabled = 0;
|
||||||
|
|
||||||
if ( hexcolon2bin (fpr, fprbin, 20) < 0 )
|
if ( hexcolon2bin (fpr, fprbin, 20) < 0 )
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
@ -407,7 +421,13 @@ agent_istrusted (ctrl_t ctrl, const char *fpr)
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
return 0; /* Trusted. */
|
if (ti->flags.disabled)
|
||||||
|
{
|
||||||
|
if (r_disabled)
|
||||||
|
*r_disabled = 1;
|
||||||
|
return gpg_error (GPG_ERR_NOT_TRUSTED);
|
||||||
|
}
|
||||||
|
return 0; /* Trusted. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return gpg_error (GPG_ERR_NOT_TRUSTED);
|
return gpg_error (GPG_ERR_NOT_TRUSTED);
|
||||||
@ -440,6 +460,8 @@ agent_listtrusted (void *assuan_context)
|
|||||||
lock_trusttable ();
|
lock_trusttable ();
|
||||||
for (ti=trusttable, len = trusttablesize; len; ti++, len--)
|
for (ti=trusttable, len = trusttablesize; len; ti++, len--)
|
||||||
{
|
{
|
||||||
|
if (ti->flags.disabled)
|
||||||
|
continue;
|
||||||
bin2hex (ti->fpr, 20, key);
|
bin2hex (ti->fpr, 20, key);
|
||||||
key[40] = ' ';
|
key[40] = ' ';
|
||||||
key[41] = ((ti->flags.for_smime && ti->flags.for_pgp)? '*'
|
key[41] = ((ti->flags.for_smime && ti->flags.for_pgp)? '*'
|
||||||
@ -490,7 +512,7 @@ insert_colons (const char *string)
|
|||||||
This function does first check whether that key has already been put
|
This function does first check whether that key has already been put
|
||||||
into the trustdb and returns success in this case. Before a FPR
|
into the trustdb and returns success in this case. Before a FPR
|
||||||
actually gets inserted, the user is asked by means of the Pinentry
|
actually gets inserted, the user is asked by means of the Pinentry
|
||||||
whether this is actual wants he want to do. */
|
whether this is actual want he wants to do. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag)
|
agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag)
|
||||||
{
|
{
|
||||||
@ -499,7 +521,8 @@ agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag)
|
|||||||
char *fname;
|
char *fname;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *fprformatted;
|
char *fprformatted;
|
||||||
|
int is_disabled;
|
||||||
|
int yes_i_trust;
|
||||||
|
|
||||||
/* Check whether we are at all allowed to modify the trustlist.
|
/* 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
|
This is useful so that the trustlist may be a symlink to a global
|
||||||
@ -514,57 +537,29 @@ agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag)
|
|||||||
}
|
}
|
||||||
xfree (fname);
|
xfree (fname);
|
||||||
|
|
||||||
if (!agent_istrusted (ctrl, fpr))
|
if (!agent_istrusted (ctrl, fpr, &is_disabled))
|
||||||
{
|
{
|
||||||
return 0; /* We already got this fingerprint. Silently return
|
return 0; /* We already got this fingerprint. Silently return
|
||||||
success. */
|
success. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This feature must explicitly been enabled. */
|
/* This feature must explicitly been enabled. */
|
||||||
if (!opt.allow_mark_trusted)
|
if (!opt.allow_mark_trusted)
|
||||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||||
|
|
||||||
|
if (is_disabled)
|
||||||
|
{
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Insert a new one. */
|
/* Insert a new one. */
|
||||||
fprformatted = insert_colons (fpr);
|
|
||||||
if (!fprformatted)
|
|
||||||
return out_of_core ();
|
|
||||||
desc = xtryasprintf (
|
|
||||||
/* 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. */
|
|
||||||
_("Please verify that the certificate identified as:%%0A"
|
|
||||||
" \"%s\"%%0A"
|
|
||||||
"has the fingerprint:%%0A"
|
|
||||||
" %s"), name, fprformatted);
|
|
||||||
if (!desc)
|
|
||||||
{
|
|
||||||
xfree (fprformatted);
|
|
||||||
return out_of_core ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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. */
|
|
||||||
err = agent_get_confirmation (ctrl, desc, _("Correct"), NULL);
|
|
||||||
xfree (desc);
|
|
||||||
/* If the user did not confirmed this, we return cancel here so that
|
|
||||||
gpgsm may stop asking further questions. We won't do this for
|
|
||||||
the second question of course. */
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
xfree (fprformatted);
|
|
||||||
return (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED ?
|
|
||||||
gpg_err_make (gpg_err_source (err), GPG_ERR_CANCELED) : err);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* First a general question whether this is trusted. */
|
||||||
desc = xtryasprintf (
|
desc = xtryasprintf (
|
||||||
/* TRANSLATORS: This prompt is shown by the Pinentry
|
/* TRANSLATORS: This prompt is shown by the Pinentry
|
||||||
and has one special property: A "%%0A" is used by
|
and has one special property: A "%%0A" is used by
|
||||||
@ -579,30 +574,75 @@ agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag)
|
|||||||
"to correctly certify user certificates?"),
|
"to correctly certify user certificates?"),
|
||||||
name);
|
name);
|
||||||
if (!desc)
|
if (!desc)
|
||||||
{
|
return out_of_core ();
|
||||||
xfree (fprformatted);
|
|
||||||
return out_of_core ();
|
|
||||||
}
|
|
||||||
|
|
||||||
err = agent_get_confirmation (ctrl, desc, _("Yes"), _("No"));
|
err = agent_get_confirmation (ctrl, desc, _("Yes"), _("No"));
|
||||||
xfree (desc);
|
xfree (desc);
|
||||||
if (err)
|
if (!err)
|
||||||
|
yes_i_trust = 1;
|
||||||
|
else if (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED)
|
||||||
|
yes_i_trust = 0;
|
||||||
|
else
|
||||||
|
return err;
|
||||||
|
|
||||||
|
|
||||||
|
fprformatted = insert_colons (fpr);
|
||||||
|
if (!fprformatted)
|
||||||
|
return out_of_core ();
|
||||||
|
|
||||||
|
/* If the user trusts this certificate he has to verify the
|
||||||
|
fingerprint of course. */
|
||||||
|
if (yes_i_trust)
|
||||||
{
|
{
|
||||||
xfree (fprformatted);
|
desc = xtryasprintf
|
||||||
return err;
|
(
|
||||||
|
/* 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. */
|
||||||
|
_("Please verify that the certificate identified as:%%0A"
|
||||||
|
" \"%s\"%%0A"
|
||||||
|
"has the fingerprint:%%0A"
|
||||||
|
" %s"), name, fprformatted);
|
||||||
|
if (!desc)
|
||||||
|
{
|
||||||
|
xfree (fprformatted);
|
||||||
|
return out_of_core ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
err = agent_get_confirmation (ctrl, desc, _("Correct"), _("Wrong"));
|
||||||
|
xfree (desc);
|
||||||
|
if (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED)
|
||||||
|
yes_i_trust = 0;
|
||||||
|
else if (err)
|
||||||
|
{
|
||||||
|
xfree (fprformatted);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Now check again to avoid duplicates. We take the lock to make
|
/* Now check again to avoid duplicates. We take the lock to make
|
||||||
sure that nobody else plays with our file. Frankly we don't work
|
sure that nobody else plays with our file. Frankly we don't work
|
||||||
with the trusttable but using this lock is just fine for our
|
with the trusttable but using this lock is just fine for our
|
||||||
purpose. */
|
purpose. */
|
||||||
lock_trusttable ();
|
lock_trusttable ();
|
||||||
if (!agent_istrusted (ctrl, fpr))
|
{
|
||||||
{
|
int now_disabled;
|
||||||
unlock_trusttable ();
|
|
||||||
xfree (fprformatted);
|
if (!agent_istrusted (ctrl, fpr, &now_disabled) || now_disabled)
|
||||||
return 0;
|
{
|
||||||
}
|
unlock_trusttable ();
|
||||||
|
xfree (fprformatted);
|
||||||
|
return now_disabled? gpg_error (GPG_ERR_NOT_TRUSTED) : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fname = make_filename (opt.homedir, "trustlist.txt", NULL);
|
fname = make_filename (opt.homedir, "trustlist.txt", NULL);
|
||||||
@ -635,7 +675,7 @@ agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag)
|
|||||||
/* Append the key. */
|
/* Append the key. */
|
||||||
fputs ("\n# ", fp);
|
fputs ("\n# ", fp);
|
||||||
print_sanitized_string (fp, name, 0);
|
print_sanitized_string (fp, name, 0);
|
||||||
fprintf (fp, "\n%s %c\n", fprformatted, flag);
|
fprintf (fp, "\n%s%s %c\n", yes_i_trust?"":"!", fprformatted, flag);
|
||||||
if (ferror (fp))
|
if (ferror (fp))
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
@ -520,9 +520,11 @@ agent. By default they may all be found in the current home directory
|
|||||||
you need to enter its fingerprint followed by a space and a capital
|
you need to enter its fingerprint followed by a space and a capital
|
||||||
letter @code{S}. Colons may optionally be used to separate the bytes of
|
letter @code{S}. Colons may optionally be used to separate the bytes of
|
||||||
a fingerprint; this allows to cut and paste the fingerprint from a key
|
a fingerprint; this allows to cut and paste the fingerprint from a key
|
||||||
listing output.
|
listing output. If the line is prefixed with a @code{!} the key is
|
||||||
|
explicitly marked as not trusted.
|
||||||
|
|
||||||
Here is an example where two keys are marked as ultimately trusted:
|
Here is an example where two keys are marked as ultimately trusted
|
||||||
|
and one as not trusted:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
# CN=Wurzel ZS 3,O=Intevation GmbH,C=DE
|
# CN=Wurzel ZS 3,O=Intevation GmbH,C=DE
|
||||||
@ -530,6 +532,9 @@ agent. By default they may all be found in the current home directory
|
|||||||
|
|
||||||
# CN=PCA-1-Verwaltung-02/O=PKI-1-Verwaltung/C=DE
|
# CN=PCA-1-Verwaltung-02/O=PKI-1-Verwaltung/C=DE
|
||||||
DC:BD:69:25:48:BD:BB:7E:31:6E:BB:80:D3:00:80:35:D4:F8:A6:CD S
|
DC:BD:69:25:48:BD:BB:7E:31:6E:BB:80:D3:00:80:35:D4:F8:A6:CD S
|
||||||
|
|
||||||
|
# CN=Root-CA/O=Schlapphuete/L=Pullach/C=DE
|
||||||
|
!14:56:98:D3:FE:9C:CA:5A:31:6E:BC:81:D3:11:4E:00:90:A3:44:C2 S
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
Before entering a key into this file, you need to ensure its
|
Before entering a key into this file, you need to ensure its
|
||||||
|
Loading…
x
Reference in New Issue
Block a user