1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +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:
Werner Koch 2023-04-05 21:32:23 +02:00
parent 42ccbd6c78
commit c9e95b8dee
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
13 changed files with 216 additions and 15 deletions

View file

@ -446,6 +446,7 @@ enum cmd_and_opt_values
oRequireCompliance,
oCompatibilityFlags,
oAddDesigRevoker,
oAssertSigner,
oNoop
};
@ -708,7 +709,7 @@ static gpgrt_opt_t opts[] = {
ARGPARSE_s_n (oNoAutoTrustNewKey, "no-auto-trust-new-key", "@"),
#endif
ARGPARSE_s_s (oAddDesigRevoker, "add-desig-revoker", "@"),
ARGPARSE_s_s (oAssertSigner, "assert-signer", "@"),
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. */
#define DEFAULT_AKL_LIST "local,wkd"
/* Can be set to true to force gpg to return with EXIT_FAILURE. */
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 =
#ifdef HAVE_W32_SYSTEM
@ -3734,6 +3739,11 @@ main (int argc, char **argv)
append_to_strlist (&opt.desig_revokers, pargs.r.ret_str);
break;
case oAssertSigner:
add_to_strlist (&opt.assert_signer_list, pargs.r.ret_str);
break;
case oNoop: break;
default:
@ -5448,7 +5458,15 @@ g10_exit( int rc )
gnupg_block_all_signals ();
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);
}

View file

@ -118,7 +118,7 @@ static struct debug_flags_s debug_flags [] =
int g10_errors_seen = 0;
int assert_signer_true = 0;
static char *
make_libversion (const char *libname, const char *(*getfnc)(const char*))

View file

@ -83,6 +83,7 @@ struct weakhash
/*-- gpg.c --*/
extern int g10_errors_seen;
extern int assert_signer_true;
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
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_files (ctrl_t ctrl, int nfiles, char **files );
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 --*/
int decrypt_message (ctrl_t ctrl, const char *filename );

View file

@ -2410,7 +2410,7 @@ check_sig_and_print (CTX c, kbnode_t node)
}
/* 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 mainpkhex[MAX_FINGERPRINT_LEN*2+1];
@ -2430,6 +2430,8 @@ check_sig_and_print (CTX c, kbnode_t node)
sig->digest_algo,
sig->sig_class,
mainpkhex);
/* Handle the --assert-signer option. */
check_assert_signer_list (mainpkhex, pkhex);
}
/* Print compliance warning for Good signatures. */
@ -2510,6 +2512,7 @@ check_sig_and_print (CTX c, kbnode_t node)
is not a detached signature. */
log_info (_("WARNING: not a detached signature; "
"file '%s' was NOT verified!\n"), dfile);
assert_signer_true = 0;
}
xfree (dfile);
}

View file

@ -235,6 +235,10 @@ struct
value. */
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
{
/* If set, require an 0x19 backsig to be present on signatures

View file

@ -67,3 +67,12 @@ do_test (int argc, char *argv[])
release_kbnode (kb1);
xfree (ctrl);
}
int assert_signer_true = 0;
void
check_assert_signer_list (const char *mainpkhex, const char *pkhex)
{
(void)mainpkhex;
(void)pkhex;
}

View file

@ -105,3 +105,13 @@ do_test (int argc, char *argv[])
keydb_release (hd2);
xfree (ctrl);
}
int assert_signer_true = 0;
void
check_assert_signer_list (const char *mainpkhex, const char *pkhex)
{
(void)mainpkhex;
(void)pkhex;
}

View file

@ -611,3 +611,12 @@ do_test (int argc, char *argv[])
xfree (filename);
}
int assert_signer_true = 0;
void
check_assert_signer_list (const char *mainpkhex, const char *pkhex)
{
(void)mainpkhex;
(void)pkhex;
}

View file

@ -1,6 +1,8 @@
/* verify.c - Verify signed data
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006,
* 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.
*
@ -16,6 +18,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#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);
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);
}