mirror of
git://git.gnupg.org/gnupg.git
synced 2024-06-14 00:19:50 +02:00
gpg: New option --assert-signer.
* g10/gpg.c (enum cmd_and_opt_values): Add oAssertSigner. (opts): Add "assert-signer". (main): Set option. (assert_signer_true): New var. (g10_exit): Evaluate new var. * g10/main.h (assert_signer_true): Declare new var. * common/status.h (STATUS_ASSERT_SIGNER): New. * g10/options.h (opt): Add field assert_signer_list. * g10/verify.c (is_fingerprint): New. (check_assert_signer_list): New. * g10/mainproc.c (check_sig_and_print): Call that function. Clear assert_signer_true on a warning. * g10/gpgv.c: Add dummy function and vars. * g10/t-keydb-get-keyblock.c: Ditto. * g10/t-keydb.c: Ditto. * g10/t-stutter.c: Ditto. --
This commit is contained in:
parent
42ccbd6c78
commit
c9e95b8dee
4
NEWS
4
NEWS
|
@ -1,11 +1,13 @@
|
||||||
Noteworthy changes in version 2.4.1 (unreleased)
|
Noteworthy changes in version 2.4.1 (unreleased)
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
* If the ~/.gnupg home directory does not exist, the keyboxd is now
|
* If the ~/.gnupg directory does not exist, the keyboxd is now
|
||||||
automagically enabled.
|
automagically enabled.
|
||||||
|
|
||||||
* gpg: New option --add-desig-revoker. [rG3d094e2bcf]
|
* gpg: New option --add-desig-revoker. [rG3d094e2bcf]
|
||||||
|
|
||||||
|
* gpg: New option --assert-signer.
|
||||||
|
|
||||||
* gpg: New list-option "show-unusable-sigs". Also show
|
* gpg: New list-option "show-unusable-sigs". Also show
|
||||||
"[self-signature]" instead of the user-id in key signature
|
"[self-signature]" instead of the user-id in key signature
|
||||||
listings. [rG103acfe9ca]
|
listings. [rG103acfe9ca]
|
||||||
|
|
|
@ -53,6 +53,7 @@ enum
|
||||||
|
|
||||||
STATUS_NEED_PASSPHRASE,
|
STATUS_NEED_PASSPHRASE,
|
||||||
STATUS_VALIDSIG,
|
STATUS_VALIDSIG,
|
||||||
|
STATUS_ASSERT_SIGNER,
|
||||||
STATUS_SIG_ID,
|
STATUS_SIG_ID,
|
||||||
STATUS_ENC_TO,
|
STATUS_ENC_TO,
|
||||||
STATUS_NODATA,
|
STATUS_NODATA,
|
||||||
|
|
|
@ -522,6 +522,11 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
|
||||||
Epoch or an ISO 8601 string which can be detected by the presence
|
Epoch or an ISO 8601 string which can be detected by the presence
|
||||||
of the letter 'T'.
|
of the letter 'T'.
|
||||||
|
|
||||||
|
*** ASSERT_SIGNER <fingerprint>
|
||||||
|
This is emitted for the matching <fingerprint> when option
|
||||||
|
--assert-signer is used. The fingerprint is printed with
|
||||||
|
uppercase hex digits.
|
||||||
|
|
||||||
*** SIG_ID <radix64_string> <sig_creation_date> <sig-timestamp>
|
*** SIG_ID <radix64_string> <sig_creation_date> <sig-timestamp>
|
||||||
This is emitted only for signatures of class 0 or 1 which have
|
This is emitted only for signatures of class 0 or 1 which have
|
||||||
been verified okay. The string is a signature id and may be used
|
been verified okay. The string is a signature id and may be used
|
||||||
|
|
32
doc/gpg.texi
32
doc/gpg.texi
|
@ -264,11 +264,11 @@ out the actual signed data, but there are other pitfalls with this
|
||||||
format as well. It is suggested to avoid cleartext signatures in
|
format as well. It is suggested to avoid cleartext signatures in
|
||||||
favor of detached signatures.
|
favor of detached signatures.
|
||||||
|
|
||||||
Note: Sometimes the use of the @command{gpgv} tool is easier than
|
Note: To check whether a file was signed by a certain key the option
|
||||||
using the full-fledged @command{gpg} with this option. @command{gpgv}
|
@option{--assert-signer} can be used. As an alternative the
|
||||||
is designed to compare signed data against a list of trusted keys and
|
@command{gpgv} tool can be used. @command{gpgv} is designed to
|
||||||
returns with success only for a good signature. It has its own manual
|
compare signed data against a list of trusted keys and returns with
|
||||||
page.
|
success only for a good signature. It has its own manual page.
|
||||||
|
|
||||||
|
|
||||||
@item --multifile
|
@item --multifile
|
||||||
|
@ -1889,6 +1889,24 @@ Set what trust model GnuPG should follow. The models are:
|
||||||
must be enabled explicitly.
|
must be enabled explicitly.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
@item --always-trust
|
||||||
|
@opindex always-trust
|
||||||
|
Identical to @option{--trust-model always}.
|
||||||
|
|
||||||
|
@item --assert-signer @var{fpr_or_file}
|
||||||
|
@opindex assert-signer
|
||||||
|
This option checks whether at least one valid signature on a file has
|
||||||
|
been made with the specified key. The key is either specified as a
|
||||||
|
fingerprint or a file listing fingerprints. The fingerprint must be
|
||||||
|
given or listed in compact format (no colons or spaces in between).
|
||||||
|
This option can be given multiple times and each fingerprint is
|
||||||
|
checked against the signing key as well as the corresponding primary
|
||||||
|
key. If @var{fpr_or_file} specifies a file, empty lines are ignored
|
||||||
|
as well as all lines starting with a hash sign. With this option gpg
|
||||||
|
is guaranteed to return with an exit code of 0 if and only if a
|
||||||
|
signature has been encountered, is valid, and the key matches one of
|
||||||
|
the fingerprints given by this option.
|
||||||
|
|
||||||
|
|
||||||
@item --auto-key-locate @var{mechanisms}
|
@item --auto-key-locate @var{mechanisms}
|
||||||
@itemx --no-auto-key-locate
|
@itemx --no-auto-key-locate
|
||||||
|
@ -3856,10 +3874,6 @@ Display the keyring name at the head of key listings to show which
|
||||||
keyring a given key resides on. This option is deprecated: use
|
keyring a given key resides on. This option is deprecated: use
|
||||||
@option{--list-options [no-]show-keyring} instead.
|
@option{--list-options [no-]show-keyring} instead.
|
||||||
|
|
||||||
@item --always-trust
|
|
||||||
@opindex always-trust
|
|
||||||
Identical to @option{--trust-model always}. This option is deprecated.
|
|
||||||
|
|
||||||
@item --show-notation
|
@item --show-notation
|
||||||
@itemx --no-show-notation
|
@itemx --no-show-notation
|
||||||
@opindex show-notation
|
@opindex show-notation
|
||||||
|
|
24
g10/gpg.c
24
g10/gpg.c
|
@ -446,6 +446,7 @@ enum cmd_and_opt_values
|
||||||
oRequireCompliance,
|
oRequireCompliance,
|
||||||
oCompatibilityFlags,
|
oCompatibilityFlags,
|
||||||
oAddDesigRevoker,
|
oAddDesigRevoker,
|
||||||
|
oAssertSigner,
|
||||||
|
|
||||||
oNoop
|
oNoop
|
||||||
};
|
};
|
||||||
|
@ -708,7 +709,7 @@ static gpgrt_opt_t opts[] = {
|
||||||
ARGPARSE_s_n (oNoAutoTrustNewKey, "no-auto-trust-new-key", "@"),
|
ARGPARSE_s_n (oNoAutoTrustNewKey, "no-auto-trust-new-key", "@"),
|
||||||
#endif
|
#endif
|
||||||
ARGPARSE_s_s (oAddDesigRevoker, "add-desig-revoker", "@"),
|
ARGPARSE_s_s (oAddDesigRevoker, "add-desig-revoker", "@"),
|
||||||
|
ARGPARSE_s_s (oAssertSigner, "assert-signer", "@"),
|
||||||
|
|
||||||
ARGPARSE_header ("Input", N_("Options controlling the input")),
|
ARGPARSE_header ("Input", N_("Options controlling the input")),
|
||||||
|
|
||||||
|
@ -1032,8 +1033,12 @@ static struct compatibility_flags_s compatibility_flags [] =
|
||||||
/* The list of the default AKL methods. */
|
/* The list of the default AKL methods. */
|
||||||
#define DEFAULT_AKL_LIST "local,wkd"
|
#define DEFAULT_AKL_LIST "local,wkd"
|
||||||
|
|
||||||
|
/* Can be set to true to force gpg to return with EXIT_FAILURE. */
|
||||||
int g10_errors_seen = 0;
|
int g10_errors_seen = 0;
|
||||||
|
/* If opt.assert_signer_list is used and this variabale is not true
|
||||||
|
* gpg will be forced to return EXIT_FAILURE. */
|
||||||
|
int assert_signer_true = 0;
|
||||||
|
|
||||||
|
|
||||||
static int utf8_strings =
|
static int utf8_strings =
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
|
@ -3734,6 +3739,11 @@ main (int argc, char **argv)
|
||||||
append_to_strlist (&opt.desig_revokers, pargs.r.ret_str);
|
append_to_strlist (&opt.desig_revokers, pargs.r.ret_str);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case oAssertSigner:
|
||||||
|
add_to_strlist (&opt.assert_signer_list, pargs.r.ret_str);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
case oNoop: break;
|
case oNoop: break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -5448,7 +5458,15 @@ g10_exit( int rc )
|
||||||
gnupg_block_all_signals ();
|
gnupg_block_all_signals ();
|
||||||
emergency_cleanup ();
|
emergency_cleanup ();
|
||||||
|
|
||||||
rc = rc? rc : log_get_errorcount(0)? 2 : g10_errors_seen? 1 : 0;
|
if (rc)
|
||||||
|
;
|
||||||
|
else if (log_get_errorcount(0))
|
||||||
|
rc = 2;
|
||||||
|
else if (g10_errors_seen)
|
||||||
|
rc = 1;
|
||||||
|
else if (opt.assert_signer_list && !assert_signer_true)
|
||||||
|
rc = 1;
|
||||||
|
|
||||||
exit (rc);
|
exit (rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ static struct debug_flags_s debug_flags [] =
|
||||||
|
|
||||||
|
|
||||||
int g10_errors_seen = 0;
|
int g10_errors_seen = 0;
|
||||||
|
int assert_signer_true = 0;
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
make_libversion (const char *libname, const char *(*getfnc)(const char*))
|
make_libversion (const char *libname, const char *(*getfnc)(const char*))
|
||||||
|
|
|
@ -83,6 +83,7 @@ struct weakhash
|
||||||
|
|
||||||
/*-- gpg.c --*/
|
/*-- gpg.c --*/
|
||||||
extern int g10_errors_seen;
|
extern int g10_errors_seen;
|
||||||
|
extern int assert_signer_true;
|
||||||
|
|
||||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
|
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
|
||||||
void g10_exit(int rc) __attribute__ ((__noreturn__));
|
void g10_exit(int rc) __attribute__ ((__noreturn__));
|
||||||
|
@ -492,6 +493,7 @@ void print_file_status( int status, const char *name, int what );
|
||||||
int verify_signatures (ctrl_t ctrl, int nfiles, char **files );
|
int verify_signatures (ctrl_t ctrl, int nfiles, char **files );
|
||||||
int verify_files (ctrl_t ctrl, int nfiles, char **files );
|
int verify_files (ctrl_t ctrl, int nfiles, char **files );
|
||||||
int gpg_verify (ctrl_t ctrl, int sig_fd, int data_fd, estream_t out_fp);
|
int gpg_verify (ctrl_t ctrl, int sig_fd, int data_fd, estream_t out_fp);
|
||||||
|
void check_assert_signer_list (const char *mainpkhex, const char *pkhex);
|
||||||
|
|
||||||
/*-- decrypt.c --*/
|
/*-- decrypt.c --*/
|
||||||
int decrypt_message (ctrl_t ctrl, const char *filename );
|
int decrypt_message (ctrl_t ctrl, const char *filename );
|
||||||
|
|
|
@ -2410,7 +2410,7 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For good signatures print the VALIDSIG status line. */
|
/* For good signatures print the VALIDSIG status line. */
|
||||||
if (!rc && is_status_enabled () && pk)
|
if (!rc && (is_status_enabled () || opt.assert_signer_list) && pk)
|
||||||
{
|
{
|
||||||
char pkhex[MAX_FINGERPRINT_LEN*2+1];
|
char pkhex[MAX_FINGERPRINT_LEN*2+1];
|
||||||
char mainpkhex[MAX_FINGERPRINT_LEN*2+1];
|
char mainpkhex[MAX_FINGERPRINT_LEN*2+1];
|
||||||
|
@ -2430,6 +2430,8 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||||
sig->digest_algo,
|
sig->digest_algo,
|
||||||
sig->sig_class,
|
sig->sig_class,
|
||||||
mainpkhex);
|
mainpkhex);
|
||||||
|
/* Handle the --assert-signer option. */
|
||||||
|
check_assert_signer_list (mainpkhex, pkhex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print compliance warning for Good signatures. */
|
/* Print compliance warning for Good signatures. */
|
||||||
|
@ -2510,6 +2512,7 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||||
is not a detached signature. */
|
is not a detached signature. */
|
||||||
log_info (_("WARNING: not a detached signature; "
|
log_info (_("WARNING: not a detached signature; "
|
||||||
"file '%s' was NOT verified!\n"), dfile);
|
"file '%s' was NOT verified!\n"), dfile);
|
||||||
|
assert_signer_true = 0;
|
||||||
}
|
}
|
||||||
xfree (dfile);
|
xfree (dfile);
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,6 +235,10 @@ struct
|
||||||
value. */
|
value. */
|
||||||
int limit_card_insert_tries;
|
int limit_card_insert_tries;
|
||||||
|
|
||||||
|
/* The list of --assert-signer option values. Note: The values are
|
||||||
|
* modify to be uppercase if they represent a fingerrint */
|
||||||
|
strlist_t assert_signer_list;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
/* If set, require an 0x19 backsig to be present on signatures
|
/* If set, require an 0x19 backsig to be present on signatures
|
||||||
|
|
|
@ -67,3 +67,12 @@ do_test (int argc, char *argv[])
|
||||||
release_kbnode (kb1);
|
release_kbnode (kb1);
|
||||||
xfree (ctrl);
|
xfree (ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int assert_signer_true = 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
check_assert_signer_list (const char *mainpkhex, const char *pkhex)
|
||||||
|
{
|
||||||
|
(void)mainpkhex;
|
||||||
|
(void)pkhex;
|
||||||
|
}
|
||||||
|
|
|
@ -105,3 +105,13 @@ do_test (int argc, char *argv[])
|
||||||
keydb_release (hd2);
|
keydb_release (hd2);
|
||||||
xfree (ctrl);
|
xfree (ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int assert_signer_true = 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
check_assert_signer_list (const char *mainpkhex, const char *pkhex)
|
||||||
|
{
|
||||||
|
(void)mainpkhex;
|
||||||
|
(void)pkhex;
|
||||||
|
}
|
||||||
|
|
|
@ -611,3 +611,12 @@ do_test (int argc, char *argv[])
|
||||||
|
|
||||||
xfree (filename);
|
xfree (filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int assert_signer_true = 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
check_assert_signer_list (const char *mainpkhex, const char *pkhex)
|
||||||
|
{
|
||||||
|
(void)mainpkhex;
|
||||||
|
(void)pkhex;
|
||||||
|
}
|
||||||
|
|
124
g10/verify.c
124
g10/verify.c
|
@ -1,6 +1,8 @@
|
||||||
/* verify.c - Verify signed data
|
/* verify.c - Verify signed data
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006,
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006,
|
||||||
* 2007, 2010 Free Software Foundation, Inc.
|
* 2007, 2010 Free Software Foundation, Inc.
|
||||||
|
* Copyright (C) 2003, 2006-2008, 2010-2011, 2015-2017,
|
||||||
|
* 2020, 2023 g10 Code GmbH
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
|
@ -16,6 +18,7 @@
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
@ -281,3 +284,124 @@ gpg_verify (ctrl_t ctrl, int sig_fd, int data_fd, estream_t out_fp)
|
||||||
release_armor_context (afx);
|
release_armor_context (afx);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
is_fingerprint (const char *string)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (!string || !*string)
|
||||||
|
return 0;
|
||||||
|
for (n=0; hexdigitp (string); string++)
|
||||||
|
n++;
|
||||||
|
if (!*string && (n == 40 || n == 64))
|
||||||
|
return 1; /* v4 or v5 fingerprint. */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This function shall be called with the main and subkey fingerprint
|
||||||
|
* iff a signature is fully valid. If the option --assert-signer is
|
||||||
|
* active it check whether the signing key matches one of the keys
|
||||||
|
* given by this option and if so, sets a global flag. */
|
||||||
|
void
|
||||||
|
check_assert_signer_list (const char *mainpkhex, const char *pkhex)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
strlist_t item;
|
||||||
|
const char *fname;
|
||||||
|
estream_t fp = NULL;
|
||||||
|
int lnr;
|
||||||
|
int n, c;
|
||||||
|
char *p, *pend;
|
||||||
|
char line[256];
|
||||||
|
|
||||||
|
if (!opt.assert_signer_list)
|
||||||
|
return; /* Nothing to do. */
|
||||||
|
if (assert_signer_true)
|
||||||
|
return; /* Already one valid signature seen. */
|
||||||
|
|
||||||
|
for (item = opt.assert_signer_list; item; item = item->next)
|
||||||
|
{
|
||||||
|
if (is_fingerprint (item->d))
|
||||||
|
{
|
||||||
|
ascii_strupr (item->d);
|
||||||
|
if (!strcmp (item->d, mainpkhex) || !strcmp (item->d, pkhex))
|
||||||
|
{
|
||||||
|
assert_signer_true = 1;
|
||||||
|
write_status_text (STATUS_ASSERT_SIGNER, item->d);
|
||||||
|
if (!opt.quiet)
|
||||||
|
log_info ("signer '%s' matched\n", item->d);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* Assume this is a file - read and compare. */
|
||||||
|
{
|
||||||
|
fname = item->d;
|
||||||
|
es_fclose (fp);
|
||||||
|
fp = es_fopen (fname, "r");
|
||||||
|
if (!fp)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
log_error (_("error opening '%s': %s\n"),
|
||||||
|
fname, gpg_strerror (err));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
lnr = 0;
|
||||||
|
err = 0;
|
||||||
|
while (es_fgets (line, DIM(line)-1, fp))
|
||||||
|
{
|
||||||
|
lnr++;
|
||||||
|
|
||||||
|
n = strlen (line);
|
||||||
|
if (!n || line[n-1] != '\n')
|
||||||
|
{
|
||||||
|
/* Eat until end of line. */
|
||||||
|
while ( (c=es_getc (fp)) != EOF && c != '\n')
|
||||||
|
;
|
||||||
|
err = gpg_error (GPG_ERR_INCOMPLETE_LINE);
|
||||||
|
log_error (_("file '%s', line %d: %s\n"),
|
||||||
|
fname, lnr, gpg_strerror (err));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
line[--n] = 0; /* Chop the LF. */
|
||||||
|
if (n && line[n-1] == '\r')
|
||||||
|
line[--n] = 0; /* Chop an optional CR. */
|
||||||
|
|
||||||
|
/* Allow for empty lines and spaces */
|
||||||
|
for (p=line; spacep (p); p++)
|
||||||
|
;
|
||||||
|
if (!*p || *p == '#')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Get the first token and ignore trailing stuff. */
|
||||||
|
for (pend = p; *pend && !spacep (pend); pend++)
|
||||||
|
;
|
||||||
|
*pend = 0;
|
||||||
|
ascii_strupr (p);
|
||||||
|
|
||||||
|
if (!strcmp (p, mainpkhex) || !strcmp (p, pkhex))
|
||||||
|
{
|
||||||
|
assert_signer_true = 1;
|
||||||
|
write_status_text (STATUS_ASSERT_SIGNER, p);
|
||||||
|
if (!opt.quiet)
|
||||||
|
log_info ("signer '%s' matched '%s', line %d\n",
|
||||||
|
p, fname, lnr);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!err && !es_feof (fp))
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
log_error (_("error reading '%s', line %d: %s\n"),
|
||||||
|
fname, lnr, gpg_strerror (err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
es_fclose (fp);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user