mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
Merge branch 'STABLE-BRANCH-2-4'
-- Resolved conflicts: NEWS common/exechelp-w32.c configure.ac
This commit is contained in:
commit
4485930f9f
103 changed files with 1485 additions and 1135 deletions
|
@ -183,7 +183,7 @@ gpgv_LDFLAGS =
|
|||
|
||||
|
||||
t_common_ldadd =
|
||||
module_tests = t-rmd160 t-keydb t-keydb-get-keyblock t-stutter
|
||||
module_tests = t-rmd160 t-keydb t-keydb-get-keyblock t-stutter t-keyid
|
||||
t_rmd160_SOURCES = t-rmd160.c rmd160.c
|
||||
t_rmd160_LDADD = $(t_common_ldadd)
|
||||
t_keydb_SOURCES = t-keydb.c test-stubs.c $(common_source)
|
||||
|
@ -200,6 +200,10 @@ t_stutter_SOURCES = t-stutter.c test-stubs.c \
|
|||
t_stutter_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
|
||||
$(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
|
||||
$(LIBICONV) $(t_common_ldadd)
|
||||
t_keyid_SOURCES = t-keyid.c test-stubs.c $(common_source)
|
||||
t_keyid_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
|
||||
$(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
|
||||
$(LIBICONV) $(t_common_ldadd)
|
||||
|
||||
|
||||
$(PROGRAMS): $(needed_libs) ../common/libgpgrl.a
|
||||
|
|
|
@ -306,7 +306,9 @@ gpg_mpi_write (iobuf_t out, gcry_mpi_t a, unsigned int *r_nwritten)
|
|||
p = gcry_mpi_get_opaque (a, &nbits);
|
||||
if (p)
|
||||
{
|
||||
/* Strip leading zero bits. */
|
||||
/* First get nbits back to full bytes. */
|
||||
nbits = ((nbits + 7) / 8) * 8;
|
||||
/* Then strip leading zero bits. */
|
||||
for (; nbits >= 8 && !*p; p++, nbits -= 8)
|
||||
;
|
||||
if (nbits >= 8 && !(*p & 0x80))
|
||||
|
|
|
@ -53,7 +53,11 @@ init_compress( compress_filter_context_t *zfx, bz_stream *bzs )
|
|||
}
|
||||
|
||||
if((rc=BZ2_bzCompressInit(bzs,level,0,0))!=BZ_OK)
|
||||
log_fatal("bz2lib problem: %d\n",rc);
|
||||
{
|
||||
log_error ("bz2lib problem: %d\n",rc);
|
||||
write_status_error ("bzip2.init", gpg_error (GPG_ERR_INTERNAL));
|
||||
g10_exit (2);
|
||||
}
|
||||
|
||||
zfx->outbufsize = 8192;
|
||||
zfx->outbuf = xmalloc( zfx->outbufsize );
|
||||
|
@ -80,7 +84,11 @@ do_compress(compress_filter_context_t *zfx, bz_stream *bzs, int flush, IOBUF a)
|
|||
if( zrc == BZ_STREAM_END && flush == BZ_FINISH )
|
||||
;
|
||||
else if( zrc != BZ_RUN_OK && zrc != BZ_FINISH_OK )
|
||||
log_fatal("bz2lib deflate problem: rc=%d\n", zrc );
|
||||
{
|
||||
log_error ("bz2lib deflate problem: rc=%d\n", zrc );
|
||||
write_status_error ("bzip2.deflate", gpg_error (GPG_ERR_INTERNAL));
|
||||
g10_exit (2);
|
||||
}
|
||||
|
||||
n = zfx->outbufsize - bzs->avail_out;
|
||||
if( DBG_FILTER )
|
||||
|
@ -91,7 +99,7 @@ do_compress(compress_filter_context_t *zfx, bz_stream *bzs, int flush, IOBUF a)
|
|||
|
||||
if( (rc=iobuf_write( a, zfx->outbuf, n )) )
|
||||
{
|
||||
log_debug("bzCompress: iobuf_write failed\n");
|
||||
log_error ("bzCompress: iobuf_write failed\n");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +114,11 @@ init_uncompress( compress_filter_context_t *zfx, bz_stream *bzs )
|
|||
int rc;
|
||||
|
||||
if((rc=BZ2_bzDecompressInit(bzs,0,opt.bz2_decompress_lowmem))!=BZ_OK)
|
||||
log_fatal("bz2lib problem: %d\n",rc);
|
||||
{
|
||||
log_error ("bz2lib problem: %d\n",rc);
|
||||
write_status_error ("bzip2.init.un", gpg_error (GPG_ERR_INTERNAL));
|
||||
g10_exit (2);
|
||||
}
|
||||
|
||||
zfx->inbufsize = 2048;
|
||||
zfx->inbuf = xmalloc( zfx->inbufsize );
|
||||
|
@ -159,7 +171,11 @@ do_uncompress( compress_filter_context_t *zfx, bz_stream *bzs,
|
|||
if( zrc == BZ_STREAM_END )
|
||||
rc = -1; /* eof */
|
||||
else if( zrc != BZ_OK && zrc != BZ_PARAM_ERROR )
|
||||
log_fatal("bz2lib inflate problem: rc=%d\n", zrc );
|
||||
{
|
||||
log_error ("bz2lib inflate problem: rc=%d\n", zrc );
|
||||
write_status_error ("bzip2.inflate", gpg_error (GPG_ERR_BAD_DATA));
|
||||
g10_exit (2);
|
||||
}
|
||||
else if (zrc == BZ_OK && eofseen
|
||||
&& !bzs->avail_in && bzs->avail_out > 0)
|
||||
{
|
||||
|
|
|
@ -73,10 +73,12 @@ init_compress( compress_filter_context_t *zfx, z_stream *zs )
|
|||
-13, 8, Z_DEFAULT_STRATEGY)
|
||||
: deflateInit( zs, level )
|
||||
) != Z_OK ) {
|
||||
log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
|
||||
log_error ("zlib problem: %s\n", zs->msg? zs->msg :
|
||||
rc == Z_MEM_ERROR ? "out of core" :
|
||||
rc == Z_VERSION_ERROR ? "invalid lib version" :
|
||||
"unknown error" );
|
||||
write_status_error ("zlib.init", gpg_error (GPG_ERR_INTERNAL));
|
||||
g10_exit (2);
|
||||
}
|
||||
|
||||
zfx->outbufsize = 8192;
|
||||
|
@ -104,9 +106,11 @@ do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a )
|
|||
;
|
||||
else if( zrc != Z_OK ) {
|
||||
if( zs->msg )
|
||||
log_fatal("zlib deflate problem: %s\n", zs->msg );
|
||||
log_error ("zlib deflate problem: %s\n", zs->msg );
|
||||
else
|
||||
log_fatal("zlib deflate problem: rc=%d\n", zrc );
|
||||
log_error ("zlib deflate problem: rc=%d\n", zrc );
|
||||
write_status_error ("zlib.deflate", gpg_error (GPG_ERR_INTERNAL));
|
||||
g10_exit (2);
|
||||
}
|
||||
n = zfx->outbufsize - zs->avail_out;
|
||||
if( DBG_FILTER )
|
||||
|
@ -116,7 +120,7 @@ do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a )
|
|||
(unsigned)n, zrc );
|
||||
|
||||
if( (rc=iobuf_write( a, zfx->outbuf, n )) ) {
|
||||
log_debug("deflate: iobuf_write failed\n");
|
||||
log_error ("deflate: iobuf_write failed\n");
|
||||
return rc;
|
||||
}
|
||||
} while( zs->avail_in || (flush == Z_FINISH && zrc != Z_STREAM_END) );
|
||||
|
@ -140,10 +144,12 @@ init_uncompress( compress_filter_context_t *zfx, z_stream *zs )
|
|||
*/
|
||||
if( (rc = zfx->algo == 1? inflateInit2( zs, -15)
|
||||
: inflateInit( zs )) != Z_OK ) {
|
||||
log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
|
||||
rc == Z_MEM_ERROR ? "out of core" :
|
||||
rc == Z_VERSION_ERROR ? "invalid lib version" :
|
||||
"unknown error" );
|
||||
log_error ("zlib problem: %s\n", zs->msg? zs->msg :
|
||||
rc == Z_MEM_ERROR ? "out of core" :
|
||||
rc == Z_VERSION_ERROR ? "invalid lib version" :
|
||||
"unknown error" );
|
||||
write_status_error ("zlib.init.un", gpg_error (GPG_ERR_INTERNAL));
|
||||
g10_exit (2);
|
||||
}
|
||||
|
||||
zfx->inbufsize = 2048;
|
||||
|
@ -198,9 +204,11 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs,
|
|||
rc = -1; /* eof */
|
||||
else if( zrc != Z_OK && zrc != Z_BUF_ERROR ) {
|
||||
if( zs->msg )
|
||||
log_fatal("zlib inflate problem: %s\n", zs->msg );
|
||||
log_error ("zlib inflate problem: %s\n", zs->msg );
|
||||
else
|
||||
log_fatal("zlib inflate problem: rc=%d\n", zrc );
|
||||
log_error ("zlib inflate problem: rc=%d\n", zrc );
|
||||
write_status_error ("zlib.inflate", gpg_error (GPG_ERR_BAD_DATA));
|
||||
g10_exit (2);
|
||||
}
|
||||
} while (zs->avail_out && zrc != Z_STREAM_END && zrc != Z_BUF_ERROR
|
||||
&& !leave);
|
||||
|
|
|
@ -129,6 +129,8 @@ parse_export_options(char *str,unsigned int *options,int noisy)
|
|||
N_("export revocation keys marked as \"sensitive\"")},
|
||||
{"export-clean",EXPORT_CLEAN,NULL,
|
||||
N_("remove unusable parts from key during export")},
|
||||
{"export-realclean",EXPORT_MINIMAL|EXPORT_REALCLEAN|EXPORT_CLEAN,NULL,
|
||||
NULL},
|
||||
{"export-minimal",EXPORT_MINIMAL|EXPORT_CLEAN,NULL,
|
||||
N_("remove as much as possible from key during export")},
|
||||
|
||||
|
@ -166,7 +168,7 @@ parse_export_options(char *str,unsigned int *options,int noisy)
|
|||
{
|
||||
*options |= (EXPORT_LOCAL_SIGS | EXPORT_ATTRIBUTES
|
||||
| EXPORT_SENSITIVE_REVKEYS);
|
||||
*options &= ~(EXPORT_CLEAN | EXPORT_MINIMAL
|
||||
*options &= ~(EXPORT_CLEAN | EXPORT_MINIMAL | EXPORT_REALCLEAN
|
||||
| EXPORT_DANE_FORMAT);
|
||||
}
|
||||
|
||||
|
@ -643,7 +645,7 @@ canon_pk_algo (enum gcry_pk_algos algo)
|
|||
}
|
||||
|
||||
|
||||
/* Take an s-expression wit the public and private key and change the
|
||||
/* Take an s-expression with the public and private key and change the
|
||||
* parameter array in PK to include the secret parameters. */
|
||||
static gpg_error_t
|
||||
secret_key_to_mode1003 (gcry_sexp_t s_key, PKT_public_key *pk)
|
||||
|
@ -2366,8 +2368,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
|
|||
if ((options & EXPORT_CLEAN))
|
||||
{
|
||||
merge_keys_and_selfsig (ctrl, keyblock);
|
||||
clean_all_uids (ctrl, keyblock, opt.verbose,
|
||||
(options&EXPORT_MINIMAL), NULL, NULL);
|
||||
clean_all_uids (ctrl, keyblock, opt.verbose, options, NULL, NULL);
|
||||
clean_all_subkeys (ctrl, keyblock, opt.verbose,
|
||||
(options&EXPORT_MINIMAL)? KEY_CLEAN_ALL
|
||||
/**/ : KEY_CLEAN_AUTHENCR,
|
||||
|
|
|
@ -1921,7 +1921,7 @@ get_pubkey_byfprint_fast (ctrl_t ctrl, PKT_public_key * pk,
|
|||
* R_HD may be NULL. If LOCK is set the handle has been opend in
|
||||
* locked mode and keydb_disable_caching () has been called. On error
|
||||
* R_KEYBLOCK is set to NULL but R_HD must be released by the caller;
|
||||
* it may have a value of NULL, though. This allows to do an insert
|
||||
* it may have a value of NULL, though. This allows one to do an insert
|
||||
* operation on a locked keydb handle. */
|
||||
gpg_error_t
|
||||
get_keyblock_byfprint_fast (ctrl_t ctrl,
|
||||
|
|
56
g10/gpg.c
56
g10/gpg.c
|
@ -451,6 +451,7 @@ enum cmd_and_opt_values
|
|||
oCompatibilityFlags,
|
||||
oAddDesigRevoker,
|
||||
oAssertSigner,
|
||||
oAssertPubkeyAlgo,
|
||||
oKbxBufferSize,
|
||||
|
||||
oNoop
|
||||
|
@ -715,6 +716,7 @@ static gpgrt_opt_t opts[] = {
|
|||
#endif
|
||||
ARGPARSE_s_s (oAddDesigRevoker, "add-desig-revoker", "@"),
|
||||
ARGPARSE_s_s (oAssertSigner, "assert-signer", "@"),
|
||||
ARGPARSE_s_s (oAssertPubkeyAlgo,"assert-pubkey-algo", "@"),
|
||||
|
||||
ARGPARSE_header ("Input", N_("Options controlling the input")),
|
||||
|
||||
|
@ -753,7 +755,7 @@ static gpgrt_opt_t opts[] = {
|
|||
ARGPARSE_s_n (oNoEscapeFrom, "no-escape-from-lines", "@"),
|
||||
ARGPARSE_s_n (oMimemode, "mimemode", "@"),
|
||||
ARGPARSE_s_n (oTextmodeShort, NULL, "@"),
|
||||
ARGPARSE_s_n (oTextmode, "textmode", N_("use canonical text mode")),
|
||||
ARGPARSE_s_n (oTextmode, "textmode", "@"),
|
||||
ARGPARSE_s_n (oNoTextmode, "no-textmode", "@"),
|
||||
ARGPARSE_s_s (oSetFilename, "set-filename", "@"),
|
||||
ARGPARSE_s_n (oForYourEyesOnly, "for-your-eyes-only", "@"),
|
||||
|
@ -1045,9 +1047,12 @@ static struct compatibility_flags_s compatibility_flags [] =
|
|||
|
||||
/* 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
|
||||
/* If opt.assert_signer_list is used and this variable is not true
|
||||
* gpg will be forced to return EXIT_FAILURE. */
|
||||
int assert_signer_true = 0;
|
||||
/* If opt.assert_pubkey_algo is used and this variable is not true
|
||||
* gpg will be forced to return EXIT_FAILURE. */
|
||||
int assert_pubkey_algo_false = 0;
|
||||
|
||||
|
||||
static int utf8_strings =
|
||||
|
@ -3584,9 +3589,18 @@ main (int argc, char **argv)
|
|||
case oPersonalCompressPreferences:
|
||||
pers_compress_list=pargs.r.ret_str;
|
||||
break;
|
||||
case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
|
||||
case oKeyboxdProgram: opt.keyboxd_program = pargs.r.ret_str; break;
|
||||
case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break;
|
||||
case oAgentProgram:
|
||||
xfree (opt.agent_program);
|
||||
opt.agent_program = make_filename (pargs.r.ret_str, NULL);
|
||||
break;
|
||||
case oKeyboxdProgram:
|
||||
xfree (opt.keyboxd_program);
|
||||
opt.keyboxd_program = make_filename (pargs.r.ret_str, NULL);
|
||||
break;
|
||||
case oDirmngrProgram:
|
||||
xfree (opt.dirmngr_program);
|
||||
opt.dirmngr_program = make_filename (pargs.r.ret_str, NULL);
|
||||
break;
|
||||
case oDisableDirmngr: opt.disable_dirmngr = 1; break;
|
||||
case oWeakDigest:
|
||||
additional_weak_digest(pargs.r.ret_str);
|
||||
|
@ -3767,6 +3781,18 @@ main (int argc, char **argv)
|
|||
add_to_strlist (&opt.assert_signer_list, pargs.r.ret_str);
|
||||
break;
|
||||
|
||||
case oAssertPubkeyAlgo:
|
||||
if (!opt.assert_pubkey_algos)
|
||||
opt.assert_pubkey_algos = xstrdup (pargs.r.ret_str);
|
||||
else
|
||||
{
|
||||
char *tmp = opt.assert_pubkey_algos;
|
||||
opt.assert_pubkey_algos = xstrconcat (tmp, ",",
|
||||
pargs.r.ret_str, NULL);
|
||||
xfree (tmp);
|
||||
}
|
||||
break;
|
||||
|
||||
case oKbxBufferSize:
|
||||
keybox_set_buffersize (pargs.r.ret_ulong, 0);
|
||||
break;
|
||||
|
@ -5471,6 +5497,17 @@ emergency_cleanup (void)
|
|||
void
|
||||
g10_exit( int rc )
|
||||
{
|
||||
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;
|
||||
else if (opt.assert_pubkey_algos && assert_pubkey_algo_false)
|
||||
rc = 1;
|
||||
|
||||
/* If we had an error but not printed an error message, do it now.
|
||||
* Note that write_status_failure will never print a second failure
|
||||
* status line. */
|
||||
|
@ -5495,15 +5532,6 @@ g10_exit( int rc )
|
|||
gnupg_block_all_signals ();
|
||||
emergency_cleanup ();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
30
g10/gpgv.c
30
g10/gpgv.c
|
@ -68,6 +68,7 @@ enum cmd_and_opt_values {
|
|||
oWeakDigest,
|
||||
oEnableSpecialFilenames,
|
||||
oDebug,
|
||||
oAssertPubkeyAlgo,
|
||||
aTest
|
||||
};
|
||||
|
||||
|
@ -91,6 +92,7 @@ static gpgrt_opt_t opts[] = {
|
|||
N_("|ALGO|reject signatures made with ALGO")),
|
||||
ARGPARSE_s_n (oEnableSpecialFilenames, "enable-special-filenames", "@"),
|
||||
ARGPARSE_s_s (oDebug, "debug", "@"),
|
||||
ARGPARSE_s_s (oAssertPubkeyAlgo,"assert-pubkey-algo", "@"),
|
||||
|
||||
ARGPARSE_end ()
|
||||
};
|
||||
|
@ -119,6 +121,7 @@ static struct debug_flags_s debug_flags [] =
|
|||
|
||||
int g10_errors_seen = 0;
|
||||
int assert_signer_true = 0;
|
||||
int assert_pubkey_algo_false = 0;
|
||||
|
||||
static char *
|
||||
make_libversion (const char *libname, const char *(*getfnc)(const char*))
|
||||
|
@ -251,6 +254,19 @@ main( int argc, char **argv )
|
|||
case oEnableSpecialFilenames:
|
||||
enable_special_filenames ();
|
||||
break;
|
||||
|
||||
case oAssertPubkeyAlgo:
|
||||
if (!opt.assert_pubkey_algos)
|
||||
opt.assert_pubkey_algos = xstrdup (pargs.r.ret_str);
|
||||
else
|
||||
{
|
||||
char *tmp = opt.assert_pubkey_algos;
|
||||
opt.assert_pubkey_algos = xstrconcat (tmp, ",",
|
||||
pargs.r.ret_str, NULL);
|
||||
xfree (tmp);
|
||||
}
|
||||
break;
|
||||
|
||||
default : pargs.err = ARGPARSE_PRINT_ERROR; break;
|
||||
}
|
||||
}
|
||||
|
@ -288,10 +304,18 @@ main( int argc, char **argv )
|
|||
|
||||
|
||||
void
|
||||
g10_exit( int rc )
|
||||
g10_exit (int rc)
|
||||
{
|
||||
rc = rc? rc : log_get_errorcount(0)? 2 : g10_errors_seen? 1 : 0;
|
||||
exit(rc );
|
||||
if (rc)
|
||||
;
|
||||
else if (log_get_errorcount(0))
|
||||
rc = 2;
|
||||
else if (g10_errors_seen)
|
||||
rc = 1;
|
||||
else if (opt.assert_pubkey_algos && assert_pubkey_algo_false)
|
||||
rc = 1;
|
||||
|
||||
exit (rc);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2081,7 +2081,9 @@ import_one_real (ctrl_t ctrl,
|
|||
{
|
||||
merge_keys_and_selfsig (ctrl, keyblock);
|
||||
clean_all_uids (ctrl, keyblock,
|
||||
opt.verbose, (options&IMPORT_MINIMAL), NULL, NULL);
|
||||
opt.verbose,
|
||||
(options&IMPORT_MINIMAL)? EXPORT_MINIMAL : 0,
|
||||
NULL, NULL);
|
||||
clean_all_subkeys (ctrl, keyblock, opt.verbose, KEY_CLEAN_NONE,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
@ -2233,7 +2235,8 @@ import_one_real (ctrl_t ctrl,
|
|||
if ((options & IMPORT_CLEAN))
|
||||
{
|
||||
merge_keys_and_selfsig (ctrl, keyblock);
|
||||
clean_all_uids (ctrl, keyblock, opt.verbose, (options&IMPORT_MINIMAL),
|
||||
clean_all_uids (ctrl, keyblock, opt.verbose,
|
||||
(options&IMPORT_MINIMAL)? EXPORT_MINIMAL : 0,
|
||||
&n_uids_cleaned,&n_sigs_cleaned);
|
||||
clean_all_subkeys (ctrl, keyblock, opt.verbose, KEY_CLEAN_NONE,
|
||||
NULL, NULL);
|
||||
|
@ -2331,7 +2334,7 @@ import_one_real (ctrl_t ctrl,
|
|||
{
|
||||
merge_keys_and_selfsig (ctrl, keyblock_orig);
|
||||
clean_all_uids (ctrl, keyblock_orig, opt.verbose,
|
||||
(options&IMPORT_MINIMAL),
|
||||
(options&IMPORT_MINIMAL)? EXPORT_MINIMAL : 0,
|
||||
&n_uids_cleaned,&n_sigs_cleaned);
|
||||
clean_all_subkeys (ctrl, keyblock_orig, opt.verbose, KEY_CLEAN_NONE,
|
||||
NULL, NULL);
|
||||
|
|
|
@ -91,6 +91,7 @@ mark_usable_uid_certs (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
|
|||
continue;
|
||||
}
|
||||
node->flag |= 1<<NF_CONSIDER;
|
||||
|
||||
}
|
||||
/* Reset the remaining flags. */
|
||||
for (; node; node = node->next)
|
||||
|
@ -215,9 +216,22 @@ mark_usable_uid_certs (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
|
|||
}
|
||||
|
||||
|
||||
/* Return true if the signature at NODE has is from a key specified by
|
||||
* the --trusted-key option and is exportable. */
|
||||
static int
|
||||
is_trusted_key_sig (kbnode_t node)
|
||||
{
|
||||
if (!node->pkt->pkt.signature->flags.exportable)
|
||||
return 0;
|
||||
/* Not yet implemented. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Note: OPTIONS are from the EXPORT_* set. */
|
||||
static int
|
||||
clean_sigs_from_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
|
||||
int noisy, int self_only)
|
||||
int noisy, unsigned int options)
|
||||
{
|
||||
int deleted = 0;
|
||||
kbnode_t node;
|
||||
|
@ -256,8 +270,15 @@ clean_sigs_from_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
|
|||
{
|
||||
int keep;
|
||||
|
||||
keep = self_only? (node->pkt->pkt.signature->keyid[0] == keyid[0]
|
||||
&& node->pkt->pkt.signature->keyid[1] == keyid[1]) : 1;
|
||||
if ((options & EXPORT_REALCLEAN))
|
||||
keep = ((node->pkt->pkt.signature->keyid[0] == keyid[0]
|
||||
&& node->pkt->pkt.signature->keyid[1] == keyid[1])
|
||||
|| is_trusted_key_sig (node));
|
||||
else if ((options & EXPORT_MINIMAL))
|
||||
keep = (node->pkt->pkt.signature->keyid[0] == keyid[0]
|
||||
&& node->pkt->pkt.signature->keyid[1] == keyid[1]);
|
||||
else
|
||||
keep = 1;
|
||||
|
||||
/* Keep usable uid sigs ... */
|
||||
if ((node->flag & (1<<NF_USABLE)) && keep)
|
||||
|
@ -364,10 +385,12 @@ clean_uid_from_key (kbnode_t keyblock, kbnode_t uidnode, int noisy)
|
|||
}
|
||||
|
||||
|
||||
/* Needs to be called after a merge_keys_and_selfsig() */
|
||||
/* Needs to be called after a merge_keys_and_selfsig().
|
||||
* Note: OPTIONS are from the EXPORT_* set. */
|
||||
void
|
||||
clean_one_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
|
||||
int noisy, int self_only, int *uids_cleaned, int *sigs_cleaned)
|
||||
int noisy, unsigned int options,
|
||||
int *uids_cleaned, int *sigs_cleaned)
|
||||
{
|
||||
int dummy = 0;
|
||||
|
||||
|
@ -386,15 +409,15 @@ clean_one_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
|
|||
*uids_cleaned += clean_uid_from_key (keyblock, uidnode, noisy);
|
||||
if (!uidnode->pkt->pkt.user_id->flags.compacted)
|
||||
*sigs_cleaned += clean_sigs_from_uid (ctrl, keyblock, uidnode,
|
||||
noisy, self_only);
|
||||
noisy, options);
|
||||
}
|
||||
|
||||
|
||||
/* NB: This function marks the deleted nodes only and the caller is
|
||||
* responsible to skip or remove them. Needs to be called after a
|
||||
* merge_keys_and_selfsig(). */
|
||||
* merge_keys_and_selfsig. Note: OPTIONS are from the EXPORT_* set. */
|
||||
void
|
||||
clean_all_uids (ctrl_t ctrl, kbnode_t keyblock, int noisy, int self_only,
|
||||
clean_all_uids (ctrl_t ctrl, kbnode_t keyblock, int noisy, unsigned int options,
|
||||
int *uids_cleaned, int *sigs_cleaned)
|
||||
{
|
||||
kbnode_t node;
|
||||
|
@ -405,7 +428,7 @@ clean_all_uids (ctrl_t ctrl, kbnode_t keyblock, int noisy, int self_only,
|
|||
node = node->next)
|
||||
{
|
||||
if (node->pkt->pkttype == PKT_USER_ID)
|
||||
clean_one_uid (ctrl, keyblock, node, noisy, self_only,
|
||||
clean_one_uid (ctrl, keyblock, node, noisy, options,
|
||||
uids_cleaned, sigs_cleaned);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,9 +40,10 @@ void mark_usable_uid_certs (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
|
|||
u32 curtime, u32 *next_expire);
|
||||
|
||||
void clean_one_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
|
||||
int noisy, int self_only,
|
||||
int noisy, unsigned int options,
|
||||
int *uids_cleaned, int *sigs_cleaned);
|
||||
void clean_all_uids (ctrl_t ctrl, kbnode_t keyblock, int noisy, int self_only,
|
||||
void clean_all_uids (ctrl_t ctrl, kbnode_t keyblock,
|
||||
int noisy, unsigned int options,
|
||||
int *uids_cleaned,int *sigs_cleaned);
|
||||
void clean_all_subkeys (ctrl_t ctrl, kbnode_t keyblock,
|
||||
int noisy, int clean_level,
|
||||
|
|
|
@ -487,6 +487,7 @@ const char *key_origin_string (int origin);
|
|||
/*-- keyid.c --*/
|
||||
int pubkey_letter( int algo );
|
||||
char *pubkey_string (PKT_public_key *pk, char *buffer, size_t bufsize);
|
||||
int compare_pubkey_string (const char *astr, const char *bstr);
|
||||
#define PUBKEY_STRING_SIZE 32
|
||||
u32 v3_keyid (gcry_mpi_t a, u32 *ki);
|
||||
void hash_public_key( gcry_md_hd_t md, PKT_public_key *pk );
|
||||
|
@ -572,6 +573,7 @@ const char *colon_expirestr_from_sig (PKT_signature *sig);
|
|||
byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
|
||||
byte *v5_fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len);
|
||||
void fpr20_from_pk (PKT_public_key *pk, byte array[20]);
|
||||
void fpr20_from_fpr (const byte *fpr, unsigned int fprlen, byte array[20]);
|
||||
char *hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen);
|
||||
char *v5hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen);
|
||||
char *format_hexfingerprint (const char *fingerprint,
|
||||
|
|
|
@ -70,7 +70,7 @@ static int menu_adduid (ctrl_t ctrl, kbnode_t keyblock,
|
|||
int photo, const char *photo_name, const char *uidstr);
|
||||
static void menu_deluid (KBNODE pub_keyblock);
|
||||
static int menu_delsig (ctrl_t ctrl, kbnode_t pub_keyblock);
|
||||
static int menu_clean (ctrl_t ctrl, kbnode_t keyblock, int self_only);
|
||||
static int menu_clean (ctrl_t ctrl, kbnode_t keyblock, unsigned int options);
|
||||
static void menu_delkey (KBNODE pub_keyblock);
|
||||
static int menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive);
|
||||
static int menu_addadsk (ctrl_t ctrl, kbnode_t pub_keyblock,
|
||||
|
@ -2258,7 +2258,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
|
|||
break;
|
||||
|
||||
case cmdMINIMIZE:
|
||||
if (menu_clean (ctrl, keyblock, 1))
|
||||
if (menu_clean (ctrl, keyblock, EXPORT_MINIMAL))
|
||||
redisplay = modified = 1;
|
||||
break;
|
||||
|
||||
|
@ -4543,11 +4543,13 @@ menu_delsig (ctrl_t ctrl, kbnode_t pub_keyblock)
|
|||
}
|
||||
|
||||
|
||||
/* Note: OPTIONS are from the EXPORT_* set. */
|
||||
static int
|
||||
menu_clean (ctrl_t ctrl, kbnode_t keyblock, int self_only)
|
||||
menu_clean (ctrl_t ctrl, kbnode_t keyblock, unsigned int options)
|
||||
{
|
||||
KBNODE uidnode;
|
||||
int modified = 0, select_all = !count_selected_uids (keyblock);
|
||||
int modified = 0;
|
||||
int select_all = !count_selected_uids (keyblock);
|
||||
|
||||
for (uidnode = keyblock->next;
|
||||
uidnode && uidnode->pkt->pkttype != PKT_PUBLIC_SUBKEY;
|
||||
|
@ -4561,8 +4563,8 @@ menu_clean (ctrl_t ctrl, kbnode_t keyblock, int self_only)
|
|||
uidnode->pkt->pkt.user_id->len,
|
||||
0);
|
||||
|
||||
clean_one_uid (ctrl, keyblock, uidnode, opt.verbose, self_only, &uids,
|
||||
&sigs);
|
||||
clean_one_uid (ctrl, keyblock, uidnode, opt.verbose, options,
|
||||
&uids, &sigs);
|
||||
if (uids)
|
||||
{
|
||||
const char *reason;
|
||||
|
@ -4587,7 +4589,7 @@ menu_clean (ctrl_t ctrl, kbnode_t keyblock, int self_only)
|
|||
}
|
||||
else
|
||||
{
|
||||
tty_printf (self_only == 1 ?
|
||||
tty_printf ((options & EXPORT_MINIMAL)?
|
||||
_("User ID \"%s\": already minimized\n") :
|
||||
_("User ID \"%s\": already clean\n"), user);
|
||||
}
|
||||
|
|
178
g10/keyid.c
178
g10/keyid.c
|
@ -145,6 +145,130 @@ pubkey_string (PKT_public_key *pk, char *buffer, size_t bufsize)
|
|||
}
|
||||
|
||||
|
||||
/* Helper for compare_pubkey_string. This skips leading spaces,
|
||||
* commas and optional condition operators and returns a pointer to
|
||||
* the first non-space character or NULL in case of an error. The
|
||||
* length of a prefix consisting of letters is then returned ar PFXLEN
|
||||
* and the value of the number (e.g. 384 for "brainpoolP384r1") at
|
||||
* NUMBER. R_LENGTH receives the entire length of the algorithm name
|
||||
* which is terminated by a space, nul, or a comma. If R_CONDITION is
|
||||
* not NULL, 0 is stored for a leading "=", 1 for a ">", 2 for a ">=",
|
||||
* -1 for a "<", and -2 for a "<=". If R_CONDITION is NULL no
|
||||
* condition prefix is allowed. */
|
||||
static const char *
|
||||
parse_one_algo_string (const char *str, size_t *pfxlen, unsigned int *number,
|
||||
size_t *r_length, int *r_condition)
|
||||
{
|
||||
int condition = 0;
|
||||
const char *result;
|
||||
|
||||
while (spacep (str) || *str ==',')
|
||||
str++;
|
||||
if (!r_condition)
|
||||
;
|
||||
else if (*str == '>' && str[1] == '=')
|
||||
condition = 2, str += 2;
|
||||
else if (*str == '>' )
|
||||
condition = 1, str += 1;
|
||||
else if (*str == '<' && str[1] == '=')
|
||||
condition = -2, str += 2;
|
||||
else if (*str == '<')
|
||||
condition = -1, str += 1;
|
||||
else if (*str == '=') /* Default. */
|
||||
str += 1;
|
||||
|
||||
if (!alphap (str))
|
||||
return NULL; /* Error. */
|
||||
|
||||
*pfxlen = 1;
|
||||
for (result = str++; alphap (str); str++)
|
||||
++*pfxlen;
|
||||
while (*str == '-' || *str == '+')
|
||||
str++;
|
||||
*number = atoi (str);
|
||||
while (*str && !spacep (str) && *str != ',')
|
||||
str++;
|
||||
|
||||
*r_length = str - result;
|
||||
if (r_condition)
|
||||
*r_condition = condition;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Helper for compare_pubkey_string. If BPARSED is set to 0 on
|
||||
* return, an error in ASTR or BSTR was found and further checks are
|
||||
* not possible. */
|
||||
static int
|
||||
compare_pubkey_string_part (const char *astr, const char *bstr_arg,
|
||||
size_t *bparsed)
|
||||
{
|
||||
const char *bstr = bstr_arg;
|
||||
size_t alen, apfxlen, blen, bpfxlen;
|
||||
unsigned int anumber, bnumber;
|
||||
int condition;
|
||||
|
||||
*bparsed = 0;
|
||||
astr = parse_one_algo_string (astr, &apfxlen, &anumber, &alen, &condition);
|
||||
if (!astr)
|
||||
return 0; /* Invalid algorithm name. */
|
||||
bstr = parse_one_algo_string (bstr, &bpfxlen, &bnumber, &blen, &condition);
|
||||
if (!bstr)
|
||||
return 0; /* Invalid algorithm name. */
|
||||
*bparsed = blen + (bstr - bstr_arg);
|
||||
if (apfxlen != bpfxlen || ascii_strncasecmp (astr, bstr, apfxlen))
|
||||
return 0; /* false. */
|
||||
switch (condition)
|
||||
{
|
||||
case 2: return anumber >= bnumber;
|
||||
case 1: return anumber > bnumber;
|
||||
case -1: return anumber < bnumber;
|
||||
case -2: return anumber <= bnumber;
|
||||
}
|
||||
|
||||
return alen == blen && !ascii_strncasecmp (astr, bstr, alen);
|
||||
}
|
||||
|
||||
|
||||
/* Check whether ASTR matches the constraints given by BSTR. ASTR may
|
||||
* be any algo string like "rsa2048", "ed25519" and BSTR may be a
|
||||
* constraint which is in the simplest case just another algo string.
|
||||
* BSTR may have more that one string in which case they are comma
|
||||
* separated and any match will return true. It is possible to prefix
|
||||
* BSTR with ">", ">=", "<=", or "<". That prefix operator is applied
|
||||
* to the number part of the algorithm, i.e. the first sequence of
|
||||
* digits found before end-of-string or a comma. Examples:
|
||||
*
|
||||
* | ASTR | BSTR | result |
|
||||
* |----------+----------------------+--------|
|
||||
* | rsa2048 | rsa2048 | true |
|
||||
* | rsa2048 | >=rsa2048 | true |
|
||||
* | rsa2048 | >rsa2048 | false |
|
||||
* | ed25519 | >rsa1024 | false |
|
||||
* | ed25519 | ed25519 | true |
|
||||
* | nistp384 | >nistp256 | true |
|
||||
* | nistp521 | >=rsa3072, >nistp384 | true |
|
||||
*/
|
||||
int
|
||||
compare_pubkey_string (const char *astr, const char *bstr)
|
||||
{
|
||||
size_t bparsed;
|
||||
int result;
|
||||
|
||||
while (*bstr)
|
||||
{
|
||||
result = compare_pubkey_string_part (astr, bstr, &bparsed);
|
||||
if (result)
|
||||
return 1;
|
||||
if (!bparsed)
|
||||
return 0; /* Syntax error in ASTR or BSTR. */
|
||||
bstr += bparsed;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Hash a public key and allow to specify the to be used format.
|
||||
* Note that if the v5 format is requested for a v4 key, a 0x04 as
|
||||
* version is hashed instead of the 0x05. */
|
||||
|
@ -239,20 +363,16 @@ do_hash_public_key (gcry_md_hd_t md, PKT_public_key *pk, int use_v5)
|
|||
if (use_v5)
|
||||
{
|
||||
gcry_md_putc ( md, 0x9a ); /* ctb */
|
||||
gcry_md_putc ( md, n >> 24 ); /* 4 byte length header */
|
||||
gcry_md_putc ( md, n >> 24 ); /* 4 byte length header (upper bits) */
|
||||
gcry_md_putc ( md, n >> 16 );
|
||||
gcry_md_putc ( md, n >> 8 );
|
||||
gcry_md_putc ( md, n );
|
||||
/* Note that the next byte may either be 4 or 5. */
|
||||
gcry_md_putc ( md, pk->version );
|
||||
}
|
||||
else
|
||||
{
|
||||
gcry_md_putc ( md, 0x99 ); /* ctb */
|
||||
gcry_md_putc ( md, n >> 8 ); /* 2 byte length header */
|
||||
gcry_md_putc ( md, n );
|
||||
gcry_md_putc ( md, pk->version );
|
||||
}
|
||||
gcry_md_putc ( md, n >> 8 ); /* lower bits of the length header. */
|
||||
gcry_md_putc ( md, n );
|
||||
gcry_md_putc ( md, pk->version );
|
||||
gcry_md_putc ( md, pk->timestamp >> 24 );
|
||||
gcry_md_putc ( md, pk->timestamp >> 16 );
|
||||
gcry_md_putc ( md, pk->timestamp >> 8 );
|
||||
|
@ -260,7 +380,7 @@ do_hash_public_key (gcry_md_hd_t md, PKT_public_key *pk, int use_v5)
|
|||
|
||||
gcry_md_putc ( md, pk->pubkey_algo );
|
||||
|
||||
if (use_v5)
|
||||
if (use_v5) /* Hash the 32 bit length */
|
||||
{
|
||||
n -= 10;
|
||||
gcry_md_putc ( md, n >> 24 );
|
||||
|
@ -935,6 +1055,32 @@ v5_fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is the core of fpr20_from_pk which directly takes a
|
||||
* fingerprint and its length instead of the public key. See below
|
||||
* for details.
|
||||
*/
|
||||
void
|
||||
fpr20_from_fpr (const byte *fpr, unsigned int fprlen, byte array[20])
|
||||
{
|
||||
if (fprlen >= 32) /* v5 fingerprint (or larger) */
|
||||
{
|
||||
memcpy (array + 0, fpr + 20, 4);
|
||||
memcpy (array + 4, fpr + 24, 4);
|
||||
memcpy (array + 8, fpr + 28, 4);
|
||||
memcpy (array + 12, fpr + 0, 4); /* kid[0] */
|
||||
memcpy (array + 16, fpr + 4, 4); /* kid[1] */
|
||||
}
|
||||
else if (fprlen == 20) /* v4 fingerprint */
|
||||
memcpy (array, fpr, 20);
|
||||
else /* v3 or too short: fill up with zeroes. */
|
||||
{
|
||||
memset (array, 0, 20);
|
||||
memcpy (array, fpr, fprlen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get FPR20 for the given PK/SK into ARRAY.
|
||||
*
|
||||
|
@ -951,19 +1097,7 @@ fpr20_from_pk (PKT_public_key *pk, byte array[20])
|
|||
if (!pk->fprlen)
|
||||
compute_fingerprint (pk);
|
||||
|
||||
if (!array)
|
||||
array = xmalloc (pk->fprlen);
|
||||
|
||||
if (pk->fprlen == 32) /* v5 fingerprint */
|
||||
{
|
||||
memcpy (array + 0, pk->fpr + 20, 4);
|
||||
memcpy (array + 4, pk->fpr + 24, 4);
|
||||
memcpy (array + 8, pk->fpr + 28, 4);
|
||||
memcpy (array + 12, pk->fpr + 0, 4); /* kid[0] */
|
||||
memcpy (array + 16, pk->fpr + 4, 4); /* kid[1] */
|
||||
}
|
||||
else /* v4 fingerprint */
|
||||
memcpy (array, pk->fpr, 20);
|
||||
fpr20_from_fpr (pk->fpr, pk->fprlen, array);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ struct weakhash
|
|||
/*-- gpg.c --*/
|
||||
extern int g10_errors_seen;
|
||||
extern int assert_signer_true;
|
||||
extern int assert_pubkey_algo_false;
|
||||
|
||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
|
||||
void g10_exit(int rc) __attribute__ ((__noreturn__));
|
||||
|
@ -495,6 +496,7 @@ int verify_files (ctrl_t ctrl, int nfiles, char **files );
|
|||
int gpg_verify (ctrl_t ctrl, gnupg_fd_t sig_fd, gnupg_fd_t data_fd,
|
||||
estream_t out_fp);
|
||||
void check_assert_signer_list (const char *mainpkhex, const char *pkhex);
|
||||
void check_assert_pubkey_algo (const char *algostr, const char *pkhex);
|
||||
|
||||
/*-- decrypt.c --*/
|
||||
int decrypt_message (ctrl_t ctrl, const char *filename );
|
||||
|
|
|
@ -898,7 +898,7 @@ proc_encrypted (CTX c, PACKET *pkt)
|
|||
* encrypted packet. */
|
||||
literals_seen++;
|
||||
|
||||
/* The --require-compliance option allows to simplify decryption in
|
||||
/* The --require-compliance option allows one to simplify decryption in
|
||||
* de-vs compliance mode by just looking at the exit status. */
|
||||
if (opt.flags.require_compliance
|
||||
&& opt.compliance == CO_DE_VS
|
||||
|
@ -1876,6 +1876,8 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||
const void *extrahash = NULL;
|
||||
size_t extrahashlen = 0;
|
||||
kbnode_t included_keyblock = NULL;
|
||||
char pkstrbuf[PUBKEY_STRING_SIZE] = { 0 };
|
||||
|
||||
|
||||
if (opt.skip_verify)
|
||||
{
|
||||
|
@ -2409,8 +2411,14 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||
show_notation (sig, 0, 2, 0);
|
||||
}
|
||||
|
||||
/* Fill PKSTRBUF with the algostring in case we later need it. */
|
||||
if (pk)
|
||||
pubkey_string (pk, pkstrbuf, sizeof pkstrbuf);
|
||||
|
||||
/* For good signatures print the VALIDSIG status line. */
|
||||
if (!rc && (is_status_enabled () || opt.assert_signer_list) && pk)
|
||||
if (!rc && (is_status_enabled ()
|
||||
|| opt.assert_signer_list
|
||||
|| opt.assert_pubkey_algos) && pk)
|
||||
{
|
||||
char pkhex[MAX_FINGERPRINT_LEN*2+1];
|
||||
char mainpkhex[MAX_FINGERPRINT_LEN*2+1];
|
||||
|
@ -2432,6 +2440,8 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||
mainpkhex);
|
||||
/* Handle the --assert-signer option. */
|
||||
check_assert_signer_list (mainpkhex, pkhex);
|
||||
/* Handle the --assert-pubkey-algo option. */
|
||||
check_assert_pubkey_algo (pkstrbuf, pkhex);
|
||||
}
|
||||
|
||||
/* Print compliance warning for Good signatures. */
|
||||
|
@ -2464,13 +2474,6 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||
|
||||
if (opt.verbose)
|
||||
{
|
||||
char pkstrbuf[PUBKEY_STRING_SIZE];
|
||||
|
||||
if (pk)
|
||||
pubkey_string (pk, pkstrbuf, sizeof pkstrbuf);
|
||||
else
|
||||
*pkstrbuf = 0;
|
||||
|
||||
log_info (_("%s signature, digest algorithm %s%s%s\n"),
|
||||
sig->sig_class==0x00?_("binary"):
|
||||
sig->sig_class==0x01?_("textmode"):_("unknown"),
|
||||
|
|
|
@ -126,9 +126,9 @@ struct
|
|||
int marginals_needed;
|
||||
int completes_needed;
|
||||
int max_cert_depth;
|
||||
const char *agent_program;
|
||||
const char *keyboxd_program;
|
||||
const char *dirmngr_program;
|
||||
char *agent_program;
|
||||
char *keyboxd_program;
|
||||
char *dirmngr_program;
|
||||
int disable_dirmngr;
|
||||
|
||||
const char *def_new_key_algo;
|
||||
|
@ -241,6 +241,10 @@ struct
|
|||
* modify to be uppercase if they represent a fingerrint */
|
||||
strlist_t assert_signer_list;
|
||||
|
||||
/* A single string with the comma delimited args from
|
||||
* --assert-pubkey_algo. */
|
||||
char *assert_pubkey_algos;
|
||||
|
||||
struct
|
||||
{
|
||||
/* If set, require an 0x19 backsig to be present on signatures
|
||||
|
@ -414,12 +418,13 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
|
|||
#define EXPORT_ATTRIBUTES (1<<1)
|
||||
#define EXPORT_SENSITIVE_REVKEYS (1<<2)
|
||||
#define EXPORT_RESET_SUBKEY_PASSWD (1<<3)
|
||||
#define EXPORT_MINIMAL (1<<4)
|
||||
#define EXPORT_CLEAN (1<<5)
|
||||
#define EXPORT_MINIMAL (1<<5)
|
||||
#define EXPORT_CLEAN (1<<6)
|
||||
#define EXPORT_DANE_FORMAT (1<<7)
|
||||
#define EXPORT_BACKUP (1<<10)
|
||||
#define EXPORT_REVOCS (1<<11)
|
||||
#define EXPORT_MODE1003 (1<<12)
|
||||
#define EXPORT_REALCLEAN (1<<13)
|
||||
|
||||
#define LIST_SHOW_PHOTOS (1<<0)
|
||||
#define LIST_SHOW_POLICY_URLS (1<<1)
|
||||
|
|
|
@ -67,12 +67,3 @@ 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;
|
||||
}
|
||||
|
|
|
@ -105,13 +105,3 @@ 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;
|
||||
}
|
||||
|
|
129
g10/t-keyid.c
Normal file
129
g10/t-keyid.c
Normal file
|
@ -0,0 +1,129 @@
|
|||
/* t-keyid.c - Tests for keyid.c.
|
||||
* Copyright (C) 2024 g10 Code GmbH
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (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
|
||||
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define LEAN_T_SUPPORT 1
|
||||
|
||||
#define PGM "t-keyid"
|
||||
|
||||
#include "gpg.h"
|
||||
#include "keydb.h"
|
||||
#include "../common/t-support.h"
|
||||
|
||||
|
||||
|
||||
static int verbose;
|
||||
|
||||
|
||||
static void
|
||||
test_compare_pubkey_string (void)
|
||||
{
|
||||
static struct { const char *astr; const char *bstr; int expected; } t[] =
|
||||
{
|
||||
{ "rsa2048" , "rsa2048" , 1 },
|
||||
{ "rsa2048" , ">=rsa2048" , 1 },
|
||||
{ "rsa2048" , ">rsa2048" , 0 },
|
||||
{ "ed25519" , ">rsa1024" , 0 },
|
||||
{ "ed25519" , "ed25519" , 1 },
|
||||
{ "ed25519" , ",,,=ed25519" , 1 },
|
||||
{ "nistp384" , ">nistp256" , 1 },
|
||||
{ "nistp521" , ">=rsa3072, >nistp384", 1 },
|
||||
{ " nistp521" , ">=rsa3072, >nistp384 ", 1 },
|
||||
{ " nistp521 " , " >=rsa3072, >nistp384 ", 1 },
|
||||
{ " =nistp521 " , " >=rsa3072, >nistp384,,", 1 },
|
||||
{ "nistp384" , ">nistp384" , 0 },
|
||||
{ "nistp384" , ">=nistp384" , 1 },
|
||||
{ "brainpoolP384" , ">=brainpoolp256", 1 },
|
||||
{ "brainpoolP384" , ">brainpoolp384" , 0 },
|
||||
{ "brainpoolP384" , ">=brainpoolp384", 1 },
|
||||
{ "brainpoolP256r1", ">brainpoolp256r1", 0 },
|
||||
{ "brainpoolP384r1", ">brainpoolp384r1" , 0 },
|
||||
{ "brainpoolP384r1", ">=brainpoolp384r1", 1 },
|
||||
{ "brainpoolP384r1", ">=brainpoolp384" , 1 },
|
||||
{ "", "", 0}
|
||||
};
|
||||
int idx;
|
||||
int result;
|
||||
|
||||
for (idx=0; idx < DIM(t); idx++)
|
||||
{
|
||||
result = compare_pubkey_string (t[idx].astr, t[idx].bstr);
|
||||
if (result != t[idx].expected)
|
||||
{
|
||||
fail (idx);
|
||||
if (verbose)
|
||||
log_debug ("\"%s\", \"%s\" want %d got %d\n",
|
||||
t[idx].astr, t[idx].bstr, t[idx].expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int last_argc = -1;
|
||||
|
||||
no_exit_on_fail = 1;
|
||||
|
||||
if (argc)
|
||||
{ argc--; argv++; }
|
||||
while (argc && last_argc != argc )
|
||||
{
|
||||
last_argc = argc;
|
||||
if (!strcmp (*argv, "--"))
|
||||
{
|
||||
argc--; argv++;
|
||||
break;
|
||||
}
|
||||
else if (!strcmp (*argv, "--help"))
|
||||
{
|
||||
fputs ("usage: " PGM " [FILE]\n"
|
||||
"Options:\n"
|
||||
" --verbose Print timings etc.\n"
|
||||
" --debug Flyswatter\n"
|
||||
, stdout);
|
||||
exit (0);
|
||||
}
|
||||
else if (!strcmp (*argv, "--verbose"))
|
||||
{
|
||||
verbose++;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--debug"))
|
||||
{
|
||||
verbose += 2;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strncmp (*argv, "--", 2))
|
||||
{
|
||||
fprintf (stderr, PGM ": unknown option '%s'\n", *argv);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
test_compare_pubkey_string ();
|
||||
|
||||
return !!errcount;
|
||||
}
|
|
@ -611,12 +611,3 @@ 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;
|
||||
}
|
||||
|
|
|
@ -190,7 +190,11 @@ import_ownertrust (ctrl_t ctrl, const char *fname )
|
|||
while (fprlen < MAX_FINGERPRINT_LEN)
|
||||
fpr[fprlen++] = 0;
|
||||
|
||||
rc = tdbio_search_trust_byfpr (ctrl, fpr, &rec);
|
||||
/* FIXME: The intention is to save the special fpr20 as used
|
||||
* in the trustdb here. However, the above conversions seems
|
||||
* not to be aware of this. Or why does it allow up to
|
||||
* MAX_FINGERPRINT_LEN ? */
|
||||
rc = tdbio_search_trust_byfpr (ctrl, fpr, 20, &rec);
|
||||
if( !rc ) { /* found: update */
|
||||
if (rec.r.trust.ownertrust != otrust)
|
||||
{
|
||||
|
|
16
g10/tdbio.c
16
g10/tdbio.c
|
@ -1864,13 +1864,21 @@ cmp_trec_fpr ( const void *fpr, const TRUSTREC *rec )
|
|||
* Return: 0 if found, GPG_ERR_NOT_FOUND, or another error code.
|
||||
*/
|
||||
gpg_error_t
|
||||
tdbio_search_trust_byfpr (ctrl_t ctrl, const byte *fingerprint, TRUSTREC *rec)
|
||||
tdbio_search_trust_byfpr (ctrl_t ctrl, const byte *fpr, unsigned int fprlen,
|
||||
TRUSTREC *rec)
|
||||
{
|
||||
int rc;
|
||||
byte fingerprint[20];
|
||||
|
||||
if (fprlen != 20)
|
||||
{
|
||||
fpr20_from_fpr (fpr, fprlen, fingerprint);
|
||||
fpr = fingerprint;
|
||||
}
|
||||
|
||||
/* Locate the trust record using the hash table */
|
||||
rc = lookup_hashtable (get_trusthashrec (ctrl), fingerprint, 20,
|
||||
cmp_trec_fpr, fingerprint, rec );
|
||||
rc = lookup_hashtable (get_trusthashrec (ctrl), fpr, 20,
|
||||
cmp_trec_fpr, fpr, rec);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1887,7 +1895,7 @@ tdbio_search_trust_bypk (ctrl_t ctrl, PKT_public_key *pk, TRUSTREC *rec)
|
|||
byte fingerprint[20];
|
||||
|
||||
fpr20_from_pk (pk, fingerprint);
|
||||
return tdbio_search_trust_byfpr (ctrl, fingerprint, rec);
|
||||
return tdbio_search_trust_byfpr (ctrl, fingerprint, 20, rec);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -111,7 +111,8 @@ int tdbio_end_transaction(void);
|
|||
int tdbio_cancel_transaction(void);
|
||||
int tdbio_delete_record (ctrl_t ctrl, ulong recnum);
|
||||
ulong tdbio_new_recnum (ctrl_t ctrl);
|
||||
gpg_error_t tdbio_search_trust_byfpr (ctrl_t ctrl, const byte *fingerprint,
|
||||
gpg_error_t tdbio_search_trust_byfpr (ctrl_t ctrl,
|
||||
const byte *fpr, unsigned int fprlen,
|
||||
TRUSTREC *rec);
|
||||
gpg_error_t tdbio_search_trust_bypk (ctrl_t ctrl, PKT_public_key *pk,
|
||||
TRUSTREC *rec);
|
||||
|
|
|
@ -43,6 +43,9 @@
|
|||
#include "call-agent.h"
|
||||
|
||||
int g10_errors_seen;
|
||||
int assert_signer_true = 0;
|
||||
int assert_pubkey_algo_false = 0;
|
||||
|
||||
|
||||
|
||||
void
|
||||
|
@ -580,3 +583,18 @@ impex_filter_getval (void *cookie, const char *propname)
|
|||
(void)propname;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
check_assert_signer_list (const char *mainpkhex, const char *pkhex)
|
||||
{
|
||||
(void)mainpkhex;
|
||||
(void)pkhex;
|
||||
}
|
||||
|
||||
void
|
||||
check_assert_pubkey_algo (const char *algostr, const char *pkhex)
|
||||
{
|
||||
(void)algostr;
|
||||
(void)pkhex;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,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>
|
||||
|
|
110
g10/trustdb.c
110
g10/trustdb.c
|
@ -39,8 +39,52 @@
|
|||
#include "tofu.h"
|
||||
#include "key-clean.h"
|
||||
|
||||
|
||||
|
||||
typedef struct key_item **KeyHashTable; /* see new_key_hash_table() */
|
||||
|
||||
/*
|
||||
* Structure to keep track of keys, this is used as an array where the
|
||||
* item right after the last one has a keyblock set to NULL. Maybe we
|
||||
* can drop this thing and replace it by key_item
|
||||
*/
|
||||
struct key_array
|
||||
{
|
||||
KBNODE keyblock;
|
||||
};
|
||||
|
||||
|
||||
/* Control information for the trust DB. */
|
||||
static struct
|
||||
{
|
||||
int init;
|
||||
int level;
|
||||
char *dbname;
|
||||
int no_trustdb;
|
||||
} trustdb_args;
|
||||
|
||||
|
||||
/* Some globals. */
|
||||
static struct key_item *utk_list; /* all ultimately trusted keys */
|
||||
|
||||
/* A list used to temporary store trusted keys and a flag indicated
|
||||
* whether any --trusted-key option has been seen. */
|
||||
static struct key_item *trusted_key_list;
|
||||
static int any_trusted_key_seen;
|
||||
|
||||
/* Flag whether a trustdb check is pending. */
|
||||
static int pending_check_trustdb;
|
||||
|
||||
|
||||
|
||||
static void write_record (ctrl_t ctrl, TRUSTREC *rec);
|
||||
static void do_sync(void);
|
||||
static void do_sync (void);
|
||||
static int validate_keys (ctrl_t ctrl, int interactive);
|
||||
|
||||
|
||||
/**********************************************
|
||||
************* some helpers *******************
|
||||
**********************************************/
|
||||
|
||||
|
||||
|
||||
|
@ -54,7 +98,7 @@ keyid_from_fpr20 (ctrl_t ctrl, const byte *fpr, u32 *keyid)
|
|||
keyid = dummy_keyid;
|
||||
|
||||
/* Problem: We do only use fingerprints in the trustdb but
|
||||
* we need the keyID here to indetify the key; we can only
|
||||
* we need the keyID here to identify the key; we can only
|
||||
* use that ugly hack to distinguish between 16 and 20
|
||||
* bytes fpr - it does not work always so we better change
|
||||
* the whole validation code to only work with
|
||||
|
@ -88,40 +132,6 @@ keyid_from_fpr20 (ctrl_t ctrl, const byte *fpr, u32 *keyid)
|
|||
return keyid[1];
|
||||
}
|
||||
|
||||
typedef struct key_item **KeyHashTable; /* see new_key_hash_table() */
|
||||
|
||||
/*
|
||||
* Structure to keep track of keys, this is used as an array wherre
|
||||
* the item right after the last one has a keyblock set to NULL.
|
||||
* Maybe we can drop this thing and replace it by key_item
|
||||
*/
|
||||
struct key_array
|
||||
{
|
||||
KBNODE keyblock;
|
||||
};
|
||||
|
||||
|
||||
/* Control information for the trust DB. */
|
||||
static struct
|
||||
{
|
||||
int init;
|
||||
int level;
|
||||
char *dbname;
|
||||
int no_trustdb;
|
||||
} trustdb_args;
|
||||
|
||||
/* Some globals. */
|
||||
static struct key_item *user_utk_list; /* temp. used to store --trusted-keys */
|
||||
static struct key_item *utk_list; /* all ultimately trusted keys */
|
||||
|
||||
static int pending_check_trustdb;
|
||||
|
||||
static int validate_keys (ctrl_t ctrl, int interactive);
|
||||
|
||||
|
||||
/**********************************************
|
||||
************* some helpers *******************
|
||||
**********************************************/
|
||||
|
||||
static struct key_item *
|
||||
new_key_item (void)
|
||||
|
@ -245,11 +255,19 @@ tdb_register_trusted_keyid (u32 *keyid)
|
|||
k = new_key_item ();
|
||||
k->kid[0] = keyid[0];
|
||||
k->kid[1] = keyid[1];
|
||||
k->next = user_utk_list;
|
||||
user_utk_list = k;
|
||||
k->next = trusted_key_list;
|
||||
trusted_key_list = k;
|
||||
}
|
||||
|
||||
|
||||
/* This is called for the option --trusted-key to register these keys
|
||||
* for later syncing them into the trustdb. The special value "none"
|
||||
* may be used to indicate that there is a trusted-key option but no
|
||||
* key shall be inserted for it. This "none" value is helpful to
|
||||
* distinguish between changing the gpg.conf from a trusted-key to no
|
||||
* trusted-key options at all. Simply not specify the option would
|
||||
* not allow to distinguish this case from the --no-options case as
|
||||
* used for certain calls of gpg for example by gpg-wks-client. */
|
||||
void
|
||||
tdb_register_trusted_key (const char *string)
|
||||
{
|
||||
|
@ -257,6 +275,9 @@ tdb_register_trusted_key (const char *string)
|
|||
KEYDB_SEARCH_DESC desc;
|
||||
u32 kid[2];
|
||||
|
||||
any_trusted_key_seen = 1;
|
||||
if (!strcmp (string, "none"))
|
||||
return;
|
||||
err = classify_user_id (string, &desc, 1);
|
||||
if (!err)
|
||||
{
|
||||
|
@ -378,11 +399,12 @@ verify_own_keys (ctrl_t ctrl)
|
|||
if (!add_utk (kid))
|
||||
log_info (_("key %s occurs more than once in the trustdb\n"),
|
||||
keystr(kid));
|
||||
else if ((rec.r.trust.flags & 1))
|
||||
else if ((rec.r.trust.flags & 1)
|
||||
&& any_trusted_key_seen)
|
||||
{
|
||||
/* Record marked as inserted via --trusted-key. Is this
|
||||
* still the case? */
|
||||
for (k2 = user_utk_list; k2; k2 = k2->next)
|
||||
for (k2 = trusted_key_list; k2; k2 = k2->next)
|
||||
if (k2->kid[0] == kid[0] && k2->kid[1] == kid[1])
|
||||
break;
|
||||
if (!k2) /* No - clear the flag. */
|
||||
|
@ -406,7 +428,7 @@ verify_own_keys (ctrl_t ctrl)
|
|||
}
|
||||
|
||||
/* Put any --trusted-key keys into the trustdb */
|
||||
for (k = user_utk_list; k; k = k->next)
|
||||
for (k = trusted_key_list; k; k = k->next)
|
||||
{
|
||||
if ( add_utk (k->kid) )
|
||||
{ /* not yet in trustDB as ultimately trusted */
|
||||
|
@ -431,9 +453,9 @@ verify_own_keys (ctrl_t ctrl)
|
|||
}
|
||||
}
|
||||
|
||||
/* release the helper table table */
|
||||
release_key_items (user_utk_list);
|
||||
user_utk_list = NULL;
|
||||
/* Release the helper table. */
|
||||
release_key_items (trusted_key_list);
|
||||
trusted_key_list = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
33
g10/verify.c
33
g10/verify.c
|
@ -335,7 +335,7 @@ check_assert_signer_list (const char *mainpkhex, const char *pkhex)
|
|||
assert_signer_true = 1;
|
||||
write_status_text (STATUS_ASSERT_SIGNER, item->d);
|
||||
if (!opt.quiet)
|
||||
log_info ("signer '%s' matched\n", item->d);
|
||||
log_info ("asserted signer '%s'\n", item->d);
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
@ -390,7 +390,7 @@ check_assert_signer_list (const char *mainpkhex, const char *pkhex)
|
|||
assert_signer_true = 1;
|
||||
write_status_text (STATUS_ASSERT_SIGNER, p);
|
||||
if (!opt.quiet)
|
||||
log_info ("signer '%s' matched '%s', line %d\n",
|
||||
log_info ("asserted signer '%s' (%s:%d)\n",
|
||||
p, fname, lnr);
|
||||
goto leave;
|
||||
}
|
||||
|
@ -407,3 +407,32 @@ check_assert_signer_list (const char *mainpkhex, const char *pkhex)
|
|||
leave:
|
||||
es_fclose (fp);
|
||||
}
|
||||
|
||||
|
||||
/* This function shall be called with the signer's public key
|
||||
* algorithm ALGOSTR iff a signature is fully valid. If the option
|
||||
* --assert-pubkey-algo is active the functions checks whether the
|
||||
* signing key's algo is valid according to that list; in this case a
|
||||
* global flag is set. */
|
||||
void
|
||||
check_assert_pubkey_algo (const char *algostr, const char *pkhex)
|
||||
{
|
||||
if (!opt.assert_pubkey_algos)
|
||||
return; /* Nothing to do. */
|
||||
|
||||
if (compare_pubkey_string (algostr, opt.assert_pubkey_algos))
|
||||
{
|
||||
write_status_strings (STATUS_ASSERT_PUBKEY_ALGO,
|
||||
pkhex, " 1 ", algostr, NULL);
|
||||
if (!opt.quiet)
|
||||
log_info ("asserted signer '%s' with algo %s\n", pkhex, algostr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!opt.quiet)
|
||||
log_info ("denied signer '%s' with algo %s\n", pkhex, algostr);
|
||||
assert_pubkey_algo_false = 1;
|
||||
write_status_strings (STATUS_ASSERT_PUBKEY_ALGO,
|
||||
pkhex, " 0 ", algostr, NULL);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue