2010-01-09 20:00:46 +01:00
|
|
|
/* keylist.c - Print information about OpenPGP keys
|
2008-10-03 22:00:46 +02:00
|
|
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
|
2012-01-20 04:33:51 +01:00
|
|
|
* 2008, 2010, 2012 Free Software Foundation, Inc.
|
2014-05-07 13:39:28 +02:00
|
|
|
* Copyright (C) 2013, 2014 Werner Koch
|
2003-06-05 09:14:21 +02:00
|
|
|
*
|
|
|
|
* This file is part of GnuPG.
|
|
|
|
*
|
|
|
|
* GnuPG is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
2007-07-04 21:49:40 +02:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2003-06-05 09:14:21 +02:00
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* GnuPG is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2007-07-04 21:49:40 +02:00
|
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
2003-06-05 09:14:21 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <assert.h>
|
2008-12-09 09:58:02 +01:00
|
|
|
#ifdef HAVE_DOSISH_SYSTEM
|
2010-01-09 20:00:46 +01:00
|
|
|
#include <fcntl.h> /* for setmode() */
|
2008-12-09 09:58:02 +01:00
|
|
|
#endif
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
#include "gpg.h"
|
2003-06-05 09:14:21 +02:00
|
|
|
#include "options.h"
|
|
|
|
#include "packet.h"
|
2007-11-19 17:03:50 +01:00
|
|
|
#include "status.h"
|
2003-06-05 09:14:21 +02:00
|
|
|
#include "keydb.h"
|
|
|
|
#include "photoid.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "ttyio.h"
|
|
|
|
#include "trustdb.h"
|
|
|
|
#include "main.h"
|
|
|
|
#include "i18n.h"
|
|
|
|
#include "status.h"
|
2010-10-13 17:57:08 +02:00
|
|
|
#include "call-agent.h"
|
2015-02-25 11:43:50 +01:00
|
|
|
#include "mbox-util.h"
|
2015-10-30 12:33:40 +01:00
|
|
|
#include "zb32.h"
|
g10: Add TOFU support.
* configure.ac: Check for sqlite3.
(SQLITE3_CFLAGS): AC_SUBST it.
(SQLITE3_LIBS): Likewise.
* g10/Makefile.am (AM_CFLAGS): Add $(SQLITE3_CFLAGS).
(gpg2_SOURCES): Add tofu.h and tofu.c.
(gpg2_LDADD): Add $(SQLITE3_LIBS).
* g10/tofu.c: New file.
* g10/tofu.h: New file.
* g10/options.h (trust_model): Define TM_TOFU and TM_TOFU_PGP.
(tofu_db_format): Define.
* g10/packet.h (PKT_signature): Add fields digest and digest_len.
* g10/gpg.c: Include "tofu.h".
(cmd_and_opt_values): Declare aTOFUPolicy, oTOFUDefaultPolicy,
oTOFUDBFormat.
(opts): Add them.
(parse_trust_model): Recognize the tofu and tofu+pgp trust models.
(parse_tofu_policy): New function.
(parse_tofu_db_format): New function.
(main): Initialize opt.tofu_default_policy and opt.tofu_db_format.
Handle aTOFUPolicy, oTOFUDefaultPolicy and oTOFUDBFormat.
* g10/mainproc.c (do_check_sig): If the signature is good, copy the
hash to SIG->DIGEST and set SIG->DIGEST_LEN appropriately.
* g10/trustdb.h (get_validity): Add arguments sig and may_ask. Update
callers.
(tdb_get_validity_core): Add arguments sig and may_ask. Update
callers.
* g10/trust.c (get_validity) Add arguments sig and may_ask. Pass them
to tdb_get_validity_core.
* g10/trustdb.c: Include "tofu.h".
(trust_model_string): Handle TM_TOFU and TM_TOFU_PGP.
(tdb_get_validity_core): Add arguments sig and may_ask. If
OPT.TRUST_MODEL is TM_TOFU or TM_TOFU_PGP, compute the TOFU trust
level. Combine it with the computed PGP trust level, if appropriate.
* g10/keyedit.c: Include "tofu.h".
(show_key_with_all_names_colon): If the trust mode is tofu or
tofu+pgp, then show the trust policy.
* g10/keylist.c: Include "tofu.h".
(public_key_list): Also show the PGP stats if the trust model is
TM_TOFU_PGP.
(list_keyblock_colon): If the trust mode is tofu or
tofu+pgp, then show the trust policy.
* g10/pkclist.c: Include "tofu.h".
* g10/gpgv.c (get_validity): Add arguments sig and may_ask.
(enum tofu_policy): Define.
(tofu_get_policy): New stub.
(tofu_policy_str): Likewise.
* g10/test-stubs.c (get_validity): Add arguments sig and may_ask.
(enum tofu_policy): Define.
(tofu_get_policy): New stub.
(tofu_policy_str): Likewise.
* doc/DETAILS: Describe the TOFU Policy field.
* doc/gpg.texi: Document --tofu-set-policy, --trust-model=tofu,
--trust-model=tofu+pgp, --tofu-default-policy and --tofu-db-format.
* tests/openpgp/Makefile.am (TESTS): Add tofu.test.
(TEST_FILES): Add tofu-keys.asc, tofu-keys-secret.asc,
tofu-2183839A-1.txt, tofu-BC15C85A-1.txt and tofu-EE37CF96-1.txt.
(CLEANFILES): Add tofu.db.
(clean-local): Add tofu.d.
* tests/openpgp/tofu.test: New file.
* tests/openpgp/tofu-2183839A-1.txt: New file.
* tests/openpgp/tofu-BC15C85A-1.txt: New file.
* tests/openpgp/tofu-EE37CF96-1.txt: New file.
* tests/openpgp/tofu-keys.asc: New file.
* tests/openpgp/tofu-keys-secret.asc: New file.
--
Signed-off-by: Neal H. Walfield <neal@g10code.com>.
2015-10-18 18:44:05 +02:00
|
|
|
#include "tofu.h"
|
2015-02-25 11:43:50 +01:00
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2015-10-08 14:55:07 +02:00
|
|
|
static void list_all (ctrl_t, int, int);
|
|
|
|
static void list_one (ctrl_t ctrl,
|
|
|
|
strlist_t names, int secret, int mark_secret);
|
2010-10-01 22:33:53 +02:00
|
|
|
static void locate_one (ctrl_t ctrl, strlist_t names);
|
2010-10-13 17:57:08 +02:00
|
|
|
static void print_card_serialno (const char *serialno);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2015-04-06 19:46:25 +02:00
|
|
|
struct keylist_context
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2015-04-06 19:46:25 +02:00
|
|
|
int check_sigs; /* If set signatures shall be verified. */
|
2015-06-20 15:05:32 +02:00
|
|
|
int good_sigs; /* Counter used if CHECK_SIGS is set. */
|
2015-04-06 19:46:25 +02:00
|
|
|
int inv_sigs; /* Counter used if CHECK_SIGS is set. */
|
|
|
|
int no_key; /* Counter used if CHECK_SIGS is set. */
|
|
|
|
int oth_err; /* Counter used if CHECK_SIGS is set. */
|
2003-06-05 09:14:21 +02:00
|
|
|
};
|
|
|
|
|
2015-04-06 19:46:25 +02:00
|
|
|
|
2015-10-08 14:55:07 +02:00
|
|
|
static void list_keyblock (ctrl_t ctrl,
|
|
|
|
kbnode_t keyblock, int secret, int has_secret,
|
2015-04-06 19:46:25 +02:00
|
|
|
int fpr, struct keylist_context *listctx);
|
|
|
|
|
|
|
|
|
2008-12-09 09:58:02 +01:00
|
|
|
/* The stream used to write attribute packets to. */
|
2010-03-15 12:15:45 +01:00
|
|
|
static estream_t attrib_fp;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
|
2015-04-06 19:46:25 +02:00
|
|
|
/* Release resources from a keylist context. */
|
|
|
|
static void
|
|
|
|
keylist_context_release (struct keylist_context *listctx)
|
|
|
|
{
|
|
|
|
(void)listctx; /* Nothing to release. */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
/* List the keys. If list is NULL, all available keys are listed.
|
|
|
|
With LOCATE_MODE set the locate algorithm is used to find a
|
|
|
|
key. */
|
2003-06-05 09:14:21 +02:00
|
|
|
void
|
2010-10-01 22:33:53 +02:00
|
|
|
public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
gpg: Allow building without any trust model support.
* configure.ac: Add option --disable-trust-models
(NO_TRUST_MODELS): New ac_define and am_conditional.
* g10/Makefile.am (trust_source): New.
(gpg2_SOURCES): Factor some files out to above. Add trust.c.
* g10/gpg.c [NO_TRUST_MODELS]: Disable options --export-ownertrust,
--import-ownertrust, --update-trustdb, --check-trustdb, --fix-trustdb,
--list-trustdb, --trustdb-name, --auto-check-trustdb,
--no-auto-check-trustdb, and --force-ownertrust.
(parse_trust_model) [NO_TRUST_MODELS]: Do not build.
(main) [NO_TRUST_MODELS]: Set trust_model to always and exclude all
trustdb related option code.
* g10/keyedit.c (cmds) [NO_TRUST_MODELS]: Remove menu items "trust",
"enable", and "disable".
* g10/keylist.c (public_key_list) [NO_TRUST_MODELS]: Do not print
"tru" record.
* g10/trust.c: New.
* g10/trustdb.c (struct key_item): Move to trustdb.h.
(register_trusted_keyid): Rename to tdb_register_trusted_keyid.
(register_trusted_key): Rename to tdb_register_trusted_key.
(trust_letter, uid_trust_string_fixed, trust_value_to_string)
(string_to_trust_value, get_ownertrust_with_min, get_ownertrust_info)
(get_ownertrust_string, get_validity_info, get_validity_string)
(clean_sigs_from_uid, clean_uid_from_key, clean_key): Move to trust.c.
(mark_usable_uid_certs): Move to trust.c and make global.
(is_in_klist): Move as inline to trustdb.h.
(trustdb_check_or_update): Rename to tdb_check_or_update
(revalidation_mark): Rename to tdb_revalidation_mark.
(get_ownertrust): Rename to tdb_get_ownertrust.
(get_min_ownertrust): Rename to tdb_get_min_ownertrust.
(update_ownertrust): Rename to tdb_update_ownertrust.
(clear_ownertrusts): Rename to tdb_clear_ownertrusts.
(cache_disabled_value): Rename to tdb_cache_disabled_value.
(check_trustdb_stale): Rename to tdb_check_trustdb_stale.
(get_validity): Rename to tdb_get_validity_core, add arg MAIN_PK and
factor some code out to ...
* trust.c (get_validity): ...new.
(check_or_update_trustdb): New wrapper.
(revalidation_mark): New wrapper.
(get_ownertrust): New wrapper.
(get_ownertrust_with_min): New wrapper.
(update_ownertrust): New wrapper.
(clear_ownertrusts): New wrapper.
(cache_disabled_value): New wrapper.
(check_trustdb_stale): New wrapper.
* tests/openpgp/defs.inc (opt_always): New. Use in all tests instead
of --always-trust.
2014-02-10 17:05:54 +01:00
|
|
|
#ifndef NO_TRUST_MODELS
|
2008-05-07 17:40:36 +02:00
|
|
|
if (opt.with_colons)
|
2003-09-23 19:48:33 +02:00
|
|
|
{
|
2012-05-24 10:11:49 +02:00
|
|
|
byte trust_model, marginals, completes, cert_depth, min_cert_level;
|
|
|
|
ulong created, nextcheck;
|
2003-09-23 19:48:33 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
read_trust_options (&trust_model, &created, &nextcheck,
|
2012-01-20 04:33:51 +01:00
|
|
|
&marginals, &completes, &cert_depth, &min_cert_level);
|
2003-09-23 19:48:33 +02:00
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "tru:");
|
2003-09-23 19:48:33 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (nextcheck && nextcheck <= make_timestamp ())
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "o");
|
2010-01-09 20:00:46 +01:00
|
|
|
if (trust_model != opt.trust_model)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "t");
|
g10: Add TOFU support.
* configure.ac: Check for sqlite3.
(SQLITE3_CFLAGS): AC_SUBST it.
(SQLITE3_LIBS): Likewise.
* g10/Makefile.am (AM_CFLAGS): Add $(SQLITE3_CFLAGS).
(gpg2_SOURCES): Add tofu.h and tofu.c.
(gpg2_LDADD): Add $(SQLITE3_LIBS).
* g10/tofu.c: New file.
* g10/tofu.h: New file.
* g10/options.h (trust_model): Define TM_TOFU and TM_TOFU_PGP.
(tofu_db_format): Define.
* g10/packet.h (PKT_signature): Add fields digest and digest_len.
* g10/gpg.c: Include "tofu.h".
(cmd_and_opt_values): Declare aTOFUPolicy, oTOFUDefaultPolicy,
oTOFUDBFormat.
(opts): Add them.
(parse_trust_model): Recognize the tofu and tofu+pgp trust models.
(parse_tofu_policy): New function.
(parse_tofu_db_format): New function.
(main): Initialize opt.tofu_default_policy and opt.tofu_db_format.
Handle aTOFUPolicy, oTOFUDefaultPolicy and oTOFUDBFormat.
* g10/mainproc.c (do_check_sig): If the signature is good, copy the
hash to SIG->DIGEST and set SIG->DIGEST_LEN appropriately.
* g10/trustdb.h (get_validity): Add arguments sig and may_ask. Update
callers.
(tdb_get_validity_core): Add arguments sig and may_ask. Update
callers.
* g10/trust.c (get_validity) Add arguments sig and may_ask. Pass them
to tdb_get_validity_core.
* g10/trustdb.c: Include "tofu.h".
(trust_model_string): Handle TM_TOFU and TM_TOFU_PGP.
(tdb_get_validity_core): Add arguments sig and may_ask. If
OPT.TRUST_MODEL is TM_TOFU or TM_TOFU_PGP, compute the TOFU trust
level. Combine it with the computed PGP trust level, if appropriate.
* g10/keyedit.c: Include "tofu.h".
(show_key_with_all_names_colon): If the trust mode is tofu or
tofu+pgp, then show the trust policy.
* g10/keylist.c: Include "tofu.h".
(public_key_list): Also show the PGP stats if the trust model is
TM_TOFU_PGP.
(list_keyblock_colon): If the trust mode is tofu or
tofu+pgp, then show the trust policy.
* g10/pkclist.c: Include "tofu.h".
* g10/gpgv.c (get_validity): Add arguments sig and may_ask.
(enum tofu_policy): Define.
(tofu_get_policy): New stub.
(tofu_policy_str): Likewise.
* g10/test-stubs.c (get_validity): Add arguments sig and may_ask.
(enum tofu_policy): Define.
(tofu_get_policy): New stub.
(tofu_policy_str): Likewise.
* doc/DETAILS: Describe the TOFU Policy field.
* doc/gpg.texi: Document --tofu-set-policy, --trust-model=tofu,
--trust-model=tofu+pgp, --tofu-default-policy and --tofu-db-format.
* tests/openpgp/Makefile.am (TESTS): Add tofu.test.
(TEST_FILES): Add tofu-keys.asc, tofu-keys-secret.asc,
tofu-2183839A-1.txt, tofu-BC15C85A-1.txt and tofu-EE37CF96-1.txt.
(CLEANFILES): Add tofu.db.
(clean-local): Add tofu.d.
* tests/openpgp/tofu.test: New file.
* tests/openpgp/tofu-2183839A-1.txt: New file.
* tests/openpgp/tofu-BC15C85A-1.txt: New file.
* tests/openpgp/tofu-EE37CF96-1.txt: New file.
* tests/openpgp/tofu-keys.asc: New file.
* tests/openpgp/tofu-keys-secret.asc: New file.
--
Signed-off-by: Neal H. Walfield <neal@g10code.com>.
2015-10-18 18:44:05 +02:00
|
|
|
if (opt.trust_model == TM_PGP || opt.trust_model == TM_CLASSIC
|
|
|
|
|| opt.trust_model == TM_TOFU_PGP)
|
2003-09-23 19:48:33 +02:00
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
if (marginals != opt.marginals_needed)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "m");
|
2010-01-09 20:00:46 +01:00
|
|
|
if (completes != opt.completes_needed)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "c");
|
2010-01-09 20:00:46 +01:00
|
|
|
if (cert_depth != opt.max_cert_depth)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "d");
|
2012-01-20 04:33:51 +01:00
|
|
|
if (min_cert_level != opt.min_cert_level)
|
|
|
|
es_fprintf (es_stdout, "l");
|
2003-09-23 19:48:33 +02:00
|
|
|
}
|
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, ":%d:%lu:%lu", trust_model, created, nextcheck);
|
2003-09-23 19:48:33 +02:00
|
|
|
|
|
|
|
/* Only show marginals, completes, and cert_depth in the classic
|
2010-01-09 20:00:46 +01:00
|
|
|
or PGP trust models since they are not meaningful
|
|
|
|
otherwise. */
|
2003-09-23 19:48:33 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (trust_model == TM_PGP || trust_model == TM_CLASSIC)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, ":%d:%d:%d", marginals, completes, cert_depth);
|
|
|
|
es_fprintf (es_stdout, "\n");
|
2003-09-23 19:48:33 +02:00
|
|
|
}
|
gpg: Allow building without any trust model support.
* configure.ac: Add option --disable-trust-models
(NO_TRUST_MODELS): New ac_define and am_conditional.
* g10/Makefile.am (trust_source): New.
(gpg2_SOURCES): Factor some files out to above. Add trust.c.
* g10/gpg.c [NO_TRUST_MODELS]: Disable options --export-ownertrust,
--import-ownertrust, --update-trustdb, --check-trustdb, --fix-trustdb,
--list-trustdb, --trustdb-name, --auto-check-trustdb,
--no-auto-check-trustdb, and --force-ownertrust.
(parse_trust_model) [NO_TRUST_MODELS]: Do not build.
(main) [NO_TRUST_MODELS]: Set trust_model to always and exclude all
trustdb related option code.
* g10/keyedit.c (cmds) [NO_TRUST_MODELS]: Remove menu items "trust",
"enable", and "disable".
* g10/keylist.c (public_key_list) [NO_TRUST_MODELS]: Do not print
"tru" record.
* g10/trust.c: New.
* g10/trustdb.c (struct key_item): Move to trustdb.h.
(register_trusted_keyid): Rename to tdb_register_trusted_keyid.
(register_trusted_key): Rename to tdb_register_trusted_key.
(trust_letter, uid_trust_string_fixed, trust_value_to_string)
(string_to_trust_value, get_ownertrust_with_min, get_ownertrust_info)
(get_ownertrust_string, get_validity_info, get_validity_string)
(clean_sigs_from_uid, clean_uid_from_key, clean_key): Move to trust.c.
(mark_usable_uid_certs): Move to trust.c and make global.
(is_in_klist): Move as inline to trustdb.h.
(trustdb_check_or_update): Rename to tdb_check_or_update
(revalidation_mark): Rename to tdb_revalidation_mark.
(get_ownertrust): Rename to tdb_get_ownertrust.
(get_min_ownertrust): Rename to tdb_get_min_ownertrust.
(update_ownertrust): Rename to tdb_update_ownertrust.
(clear_ownertrusts): Rename to tdb_clear_ownertrusts.
(cache_disabled_value): Rename to tdb_cache_disabled_value.
(check_trustdb_stale): Rename to tdb_check_trustdb_stale.
(get_validity): Rename to tdb_get_validity_core, add arg MAIN_PK and
factor some code out to ...
* trust.c (get_validity): ...new.
(check_or_update_trustdb): New wrapper.
(revalidation_mark): New wrapper.
(get_ownertrust): New wrapper.
(get_ownertrust_with_min): New wrapper.
(update_ownertrust): New wrapper.
(clear_ownertrusts): New wrapper.
(cache_disabled_value): New wrapper.
(check_trustdb_stale): New wrapper.
* tests/openpgp/defs.inc (opt_always): New. Use in all tests instead
of --always-trust.
2014-02-10 17:05:54 +01:00
|
|
|
#endif /*!NO_TRUST_MODELS*/
|
2003-09-23 19:48:33 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
/* We need to do the stale check right here because it might need to
|
|
|
|
update the keyring while we already have the keyring open. This
|
|
|
|
is very bad for W32 because of a sharing violation. For real OSes
|
|
|
|
it might lead to false results if we are later listing a keyring
|
|
|
|
which is associated with the inode of a deleted file. */
|
|
|
|
check_trustdb_stale ();
|
|
|
|
|
2015-10-26 16:38:41 +01:00
|
|
|
#ifdef USE_TOFU
|
2015-10-23 17:23:17 +02:00
|
|
|
tofu_begin_batch_update ();
|
2015-10-26 16:38:41 +01:00
|
|
|
#endif
|
2015-10-23 17:23:17 +02:00
|
|
|
|
2008-05-07 17:40:36 +02:00
|
|
|
if (locate_mode)
|
2010-10-01 22:33:53 +02:00
|
|
|
locate_one (ctrl, list);
|
2008-05-07 17:40:36 +02:00
|
|
|
else if (!list)
|
2015-10-08 14:55:07 +02:00
|
|
|
list_all (ctrl, 0, opt.with_secret);
|
2003-09-23 19:48:33 +02:00
|
|
|
else
|
2015-10-08 14:55:07 +02:00
|
|
|
list_one (ctrl, list, 0, opt.with_secret);
|
2015-10-23 17:23:17 +02:00
|
|
|
|
2015-10-26 16:38:41 +01:00
|
|
|
#ifdef USE_TOFU
|
2015-10-23 17:23:17 +02:00
|
|
|
tofu_end_batch_update ();
|
2015-10-26 16:38:41 +01:00
|
|
|
#endif
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2008-05-07 17:40:36 +02:00
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
void
|
2010-10-01 22:33:53 +02:00
|
|
|
secret_key_list (ctrl_t ctrl, strlist_t list)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-10-01 22:33:53 +02:00
|
|
|
(void)ctrl;
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
check_trustdb_stale ();
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (!list)
|
2015-10-08 14:55:07 +02:00
|
|
|
list_all (ctrl, 1, 0);
|
2010-01-09 20:00:46 +01:00
|
|
|
else /* List by user id */
|
2015-10-08 14:55:07 +02:00
|
|
|
list_one (ctrl, list, 1, 0);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2015-11-20 12:52:04 +01:00
|
|
|
char *
|
|
|
|
format_seckey_info (PKT_public_key *pk)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
u32 keyid[2];
|
|
|
|
char *p;
|
2014-02-05 10:37:59 +01:00
|
|
|
char pkstrbuf[PUBKEY_STRING_SIZE];
|
2015-11-20 12:52:04 +01:00
|
|
|
char *info;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
keyid_from_pk (pk, keyid);
|
2010-01-09 20:00:46 +01:00
|
|
|
p = get_user_id_native (keyid);
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2015-11-20 12:52:04 +01:00
|
|
|
info = xtryasprintf ("sec %s/%s %s %s",
|
|
|
|
pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
|
|
|
|
keystr (keyid), datestr_from_pk (pk), p);
|
2010-01-09 20:00:46 +01:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree (p);
|
2015-11-20 12:52:04 +01:00
|
|
|
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
print_seckey_info (PKT_public_key *pk)
|
|
|
|
{
|
|
|
|
char *p = format_seckey_info (pk);
|
|
|
|
tty_printf ("\n%s\n", p);
|
|
|
|
xfree (p);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2003-07-24 11:06:43 +02:00
|
|
|
/* Print information about the public key. With FP passed as NULL,
|
|
|
|
the tty output interface is used, otherwise output is directted to
|
2010-01-09 20:00:46 +01:00
|
|
|
the given stream. */
|
2003-06-05 09:14:21 +02:00
|
|
|
void
|
2015-05-07 12:01:12 +02:00
|
|
|
print_pubkey_info (estream_t fp, PKT_public_key *pk)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
u32 keyid[2];
|
2003-06-05 09:14:21 +02:00
|
|
|
char *p;
|
2014-02-05 10:37:59 +01:00
|
|
|
char pkstrbuf[PUBKEY_STRING_SIZE];
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
keyid_from_pk (pk, keyid);
|
|
|
|
|
|
|
|
/* If the pk was chosen by a particular user ID, that is the one to
|
2010-01-09 20:00:46 +01:00
|
|
|
print. */
|
|
|
|
if (pk->user_id)
|
|
|
|
p = utf8_to_native (pk->user_id->name, pk->user_id->len, 0);
|
2006-04-19 13:26:11 +02:00
|
|
|
else
|
2010-01-09 20:00:46 +01:00
|
|
|
p = get_user_id_native (keyid);
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2003-07-24 11:06:43 +02:00
|
|
|
if (fp)
|
2010-03-15 12:15:45 +01:00
|
|
|
tty_printf ("\n");
|
2015-05-07 12:01:12 +02:00
|
|
|
tty_fprintf (fp, "%s %s/%s %s %s\n",
|
|
|
|
pk->flags.primary? "pub":"sub",
|
2014-02-05 10:37:59 +01:00
|
|
|
pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
|
2010-03-15 12:15:45 +01:00
|
|
|
keystr (keyid), datestr_from_pk (pk), p);
|
2003-06-18 21:56:13 +02:00
|
|
|
xfree (p);
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Print basic information of a secret key including the card serial
|
2010-01-09 20:00:46 +01:00
|
|
|
number information. */
|
2010-10-13 17:57:08 +02:00
|
|
|
#ifdef ENABLE_CARD_SUPPORT
|
2006-04-19 13:26:11 +02:00
|
|
|
void
|
2010-09-06 21:57:42 +02:00
|
|
|
print_card_key_info (estream_t fp, kbnode_t keyblock)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2011-03-03 16:16:24 +01:00
|
|
|
kbnode_t node;
|
|
|
|
char *hexgrip;
|
|
|
|
char *serialno;
|
|
|
|
int s2k_char;
|
2014-02-05 10:37:59 +01:00
|
|
|
char pkstrbuf[PUBKEY_STRING_SIZE];
|
2015-05-07 12:01:12 +02:00
|
|
|
int indent;
|
2011-03-03 16:16:24 +01:00
|
|
|
|
|
|
|
for (node = keyblock; node; node = node->next)
|
|
|
|
{
|
|
|
|
if (node->pkt->pkttype == PKT_PUBLIC_KEY
|
|
|
|
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
PKT_public_key *pk = node->pkt->pkt.public_key;
|
|
|
|
|
|
|
|
serialno = NULL;
|
|
|
|
rc = hexkeygrip_from_pk (pk, &hexgrip);
|
|
|
|
if (rc)
|
|
|
|
{
|
|
|
|
log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
|
|
|
|
s2k_char = '?';
|
|
|
|
}
|
|
|
|
else if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
|
|
|
|
s2k_char = serialno? '>':' ';
|
|
|
|
else
|
|
|
|
s2k_char = '#'; /* Key not found. */
|
|
|
|
|
2015-05-07 12:01:12 +02:00
|
|
|
tty_fprintf (fp, "%s%c %s/%s %n",
|
2011-03-03 16:16:24 +01:00
|
|
|
node->pkt->pkttype == PKT_PUBLIC_KEY ? "sec" : "ssb",
|
2014-02-05 10:37:59 +01:00
|
|
|
s2k_char,
|
|
|
|
pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
|
2015-05-07 12:01:12 +02:00
|
|
|
keystr_from_pk (pk),
|
|
|
|
&indent);
|
2011-03-03 16:16:24 +01:00
|
|
|
tty_fprintf (fp, _("created: %s"), datestr_from_pk (pk));
|
|
|
|
tty_fprintf (fp, " ");
|
|
|
|
tty_fprintf (fp, _("expires: %s"), expirestr_from_pk (pk));
|
|
|
|
if (serialno)
|
|
|
|
{
|
2015-05-07 12:01:12 +02:00
|
|
|
tty_fprintf (fp, "\n%*s%s", indent, "", _("card-no: "));
|
2011-03-03 16:16:24 +01:00
|
|
|
if (strlen (serialno) == 32
|
|
|
|
&& !strncmp (serialno, "D27600012401", 12))
|
|
|
|
{
|
|
|
|
/* This is an OpenPGP card. Print the relevant part. */
|
|
|
|
/* Example: D2760001240101010001000003470000 */
|
|
|
|
/* xxxxyyyyyyyy */
|
|
|
|
tty_fprintf (fp, "%.*s %.*s", 4, serialno+16, 8, serialno+20);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
tty_fprintf (fp, "%s", serialno);
|
|
|
|
}
|
|
|
|
tty_fprintf (fp, "\n");
|
|
|
|
xfree (hexgrip);
|
|
|
|
xfree (serialno);
|
|
|
|
}
|
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2010-10-13 17:57:08 +02:00
|
|
|
#endif /*ENABLE_CARD_SUPPORT*/
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
/* Flags = 0x01 hashed 0x02 critical. */
|
2006-04-19 13:26:11 +02:00
|
|
|
static void
|
2010-01-09 20:00:46 +01:00
|
|
|
status_one_subpacket (sigsubpkttype_t type, size_t len, int flags,
|
|
|
|
const byte * buf)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
char status[40];
|
|
|
|
|
|
|
|
/* Don't print these. */
|
2010-01-09 20:00:46 +01:00
|
|
|
if (len > 256)
|
2006-04-19 13:26:11 +02:00
|
|
|
return;
|
|
|
|
|
2011-02-04 12:57:53 +01:00
|
|
|
snprintf (status, sizeof status,
|
2010-03-15 12:15:45 +01:00
|
|
|
"%d %u %u ", type, flags, (unsigned int) len);
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
write_status_text_and_buffer (STATUS_SIG_SUBPACKET, status, buf, len, 0);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
/* Print a policy URL. Allowed values for MODE are:
|
|
|
|
* 0 - print to stdout.
|
|
|
|
* 1 - use log_info and emit status messages.
|
|
|
|
* 2 - emit only status messages.
|
|
|
|
*/
|
2003-06-05 09:14:21 +02:00
|
|
|
void
|
2010-01-09 20:00:46 +01:00
|
|
|
show_policy_url (PKT_signature * sig, int indent, int mode)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
|
|
|
const byte *p;
|
|
|
|
size_t len;
|
2010-01-09 20:00:46 +01:00
|
|
|
int seq = 0, crit;
|
2010-03-15 12:15:45 +01:00
|
|
|
estream_t fp = mode ? log_get_stream () : es_stdout;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
while ((p =
|
|
|
|
enum_sig_subpkt (sig->hashed, SIGSUBPKT_POLICY, &len, &seq, &crit)))
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
if (mode != 2)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
|
|
|
int i;
|
2006-04-19 13:26:11 +02:00
|
|
|
const char *str;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
for (i = 0; i < indent; i++)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc (' ', fp);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (crit)
|
|
|
|
str = _("Critical signature policy: ");
|
2003-06-05 09:14:21 +02:00
|
|
|
else
|
2010-01-09 20:00:46 +01:00
|
|
|
str = _("Signature policy: ");
|
|
|
|
if (mode)
|
|
|
|
log_info ("%s", str);
|
2003-06-05 09:14:21 +02:00
|
|
|
else
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (fp, "%s", str);
|
|
|
|
print_utf8_buffer (fp, p, len);
|
|
|
|
es_fprintf (fp, "\n");
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (mode)
|
|
|
|
write_status_buffer (STATUS_POLICY_URL, p, len, 0);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
|
2003-09-23 19:48:33 +02:00
|
|
|
/*
|
|
|
|
mode=0 for stdout.
|
|
|
|
mode=1 for log_info + status messages
|
|
|
|
mode=2 for status messages only
|
|
|
|
*/
|
|
|
|
/* TODO: use this */
|
|
|
|
void
|
2010-01-09 20:00:46 +01:00
|
|
|
show_keyserver_url (PKT_signature * sig, int indent, int mode)
|
2003-09-23 19:48:33 +02:00
|
|
|
{
|
|
|
|
const byte *p;
|
|
|
|
size_t len;
|
2010-01-09 20:00:46 +01:00
|
|
|
int seq = 0, crit;
|
2010-03-15 12:15:45 +01:00
|
|
|
estream_t fp = mode ? log_get_stream () : es_stdout;
|
2003-09-23 19:48:33 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
while ((p =
|
|
|
|
enum_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_KS, &len, &seq,
|
|
|
|
&crit)))
|
2003-09-23 19:48:33 +02:00
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
if (mode != 2)
|
2003-09-23 19:48:33 +02:00
|
|
|
{
|
|
|
|
int i;
|
2006-04-19 13:26:11 +02:00
|
|
|
const char *str;
|
2003-09-23 19:48:33 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
for (i = 0; i < indent; i++)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc (' ', es_stdout);
|
2003-09-23 19:48:33 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (crit)
|
|
|
|
str = _("Critical preferred keyserver: ");
|
2003-09-23 19:48:33 +02:00
|
|
|
else
|
2010-01-09 20:00:46 +01:00
|
|
|
str = _("Preferred keyserver: ");
|
|
|
|
if (mode)
|
|
|
|
log_info ("%s", str);
|
2003-09-23 19:48:33 +02:00
|
|
|
else
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%s", str);
|
|
|
|
print_utf8_buffer (fp, p, len);
|
|
|
|
es_fprintf (fp, "\n");
|
2003-09-23 19:48:33 +02:00
|
|
|
}
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (mode)
|
|
|
|
status_one_subpacket (SIGSUBPKT_PREF_KS, len,
|
|
|
|
(crit ? 0x02 : 0) | 0x01, p);
|
2003-09-23 19:48:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
/*
|
|
|
|
mode=0 for stdout.
|
|
|
|
mode=1 for log_info + status messages
|
|
|
|
mode=2 for status messages only
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
Defined bits in WHICH:
|
|
|
|
1 == standard notations
|
|
|
|
2 == user notations
|
2003-06-05 09:14:21 +02:00
|
|
|
*/
|
|
|
|
void
|
2010-01-09 20:00:46 +01:00
|
|
|
show_notation (PKT_signature * sig, int indent, int mode, int which)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-03-15 12:15:45 +01:00
|
|
|
estream_t fp = mode ? log_get_stream () : es_stdout;
|
2010-01-09 20:00:46 +01:00
|
|
|
struct notation *nd, *notations;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (which == 0)
|
|
|
|
which = 3;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
notations = sig_to_notation (sig);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
/* There may be multiple notations in the same sig. */
|
2010-01-09 20:00:46 +01:00
|
|
|
for (nd = notations; nd; nd = nd->next)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
if (mode != 2)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
int has_at = !!strchr (nd->name, '@');
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if ((which & 1 && !has_at) || (which & 2 && has_at))
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
const char *str;
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
for (i = 0; i < indent; i++)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc (' ', es_stdout);
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (nd->flags.critical)
|
|
|
|
str = _("Critical signature notation: ");
|
2006-04-19 13:26:11 +02:00
|
|
|
else
|
2010-01-09 20:00:46 +01:00
|
|
|
str = _("Signature notation: ");
|
|
|
|
if (mode)
|
|
|
|
log_info ("%s", str);
|
2006-04-19 13:26:11 +02:00
|
|
|
else
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%s", str);
|
2006-04-19 13:26:11 +02:00
|
|
|
/* This is all UTF8 */
|
2010-03-15 12:15:45 +01:00
|
|
|
print_utf8_buffer (fp, nd->name, strlen (nd->name));
|
|
|
|
es_fprintf (fp, "=");
|
|
|
|
print_utf8_buffer (fp, nd->value, strlen (nd->value));
|
2014-12-15 09:47:21 +01:00
|
|
|
/* (We need to use log_printf so that the next call to a
|
|
|
|
log function does not insert an extra LF.) */
|
|
|
|
if (mode)
|
|
|
|
log_printf ("\n");
|
|
|
|
else
|
|
|
|
es_putc ('\n', fp);
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (mode)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
write_status_buffer (STATUS_NOTATION_NAME,
|
|
|
|
nd->name, strlen (nd->name), 0);
|
|
|
|
write_status_buffer (STATUS_NOTATION_DATA,
|
|
|
|
nd->value, strlen (nd->value), 50);
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
free_notation (notations);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2015-04-06 19:46:25 +02:00
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
static void
|
2015-04-06 19:46:25 +02:00
|
|
|
print_signature_stats (struct keylist_context *s)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2015-04-06 19:46:25 +02:00
|
|
|
if (!s->check_sigs)
|
|
|
|
return; /* Signature checking was not requested. */
|
|
|
|
|
2015-06-20 15:05:32 +02:00
|
|
|
if (s->good_sigs == 1)
|
|
|
|
log_info (_("1 good signature\n"));
|
|
|
|
else if (s->good_sigs)
|
|
|
|
log_info (_("%d good signatures\n"), s->good_sigs);
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (s->inv_sigs == 1)
|
2015-06-20 15:05:32 +02:00
|
|
|
log_info (_("1 bad signature\n"));
|
2010-01-09 20:00:46 +01:00
|
|
|
else if (s->inv_sigs)
|
2015-06-20 15:05:32 +02:00
|
|
|
log_info (_("%d bad signatures\n"), s->inv_sigs);
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (s->no_key == 1)
|
2015-06-20 15:05:32 +02:00
|
|
|
log_info (_("1 signature not checked due to a missing key\n"));
|
2010-01-09 20:00:46 +01:00
|
|
|
else if (s->no_key)
|
2015-06-20 15:05:32 +02:00
|
|
|
log_info (_("%d signatures not checked due to missing keys\n"), s->no_key);
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (s->oth_err == 1)
|
2015-06-20 15:05:32 +02:00
|
|
|
log_info (_("1 signature not checked due to an error\n"));
|
2010-01-09 20:00:46 +01:00
|
|
|
else if (s->oth_err)
|
2015-06-20 15:05:32 +02:00
|
|
|
log_info (_("%d signatures not checked due to errors\n"), s->oth_err);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2014-06-03 21:35:59 +02:00
|
|
|
|
|
|
|
/* List all keys. If SECRET is true only secret keys are listed. If
|
|
|
|
MARK_SECRET is true secret keys are indicated in a public key
|
|
|
|
listing. */
|
2003-06-05 09:14:21 +02:00
|
|
|
static void
|
2015-10-08 14:55:07 +02:00
|
|
|
list_all (ctrl_t ctrl, int secret, int mark_secret)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
KEYDB_HANDLE hd;
|
|
|
|
KBNODE keyblock = NULL;
|
|
|
|
int rc = 0;
|
2014-06-03 21:35:59 +02:00
|
|
|
int any_secret;
|
2010-01-09 20:00:46 +01:00
|
|
|
const char *lastresname, *resname;
|
2015-04-06 19:46:25 +02:00
|
|
|
struct keylist_context listctx;
|
2010-01-09 20:00:46 +01:00
|
|
|
|
2015-04-06 19:46:25 +02:00
|
|
|
memset (&listctx, 0, sizeof (listctx));
|
|
|
|
if (opt.check_sigs)
|
|
|
|
listctx.check_sigs = 1;
|
2010-01-09 20:00:46 +01:00
|
|
|
|
2010-04-21 18:26:17 +02:00
|
|
|
hd = keydb_new ();
|
2010-01-09 20:00:46 +01:00
|
|
|
if (!hd)
|
2011-04-29 15:07:11 +02:00
|
|
|
rc = gpg_error (GPG_ERR_GENERAL);
|
2010-01-09 20:00:46 +01:00
|
|
|
else
|
|
|
|
rc = keydb_search_first (hd);
|
|
|
|
if (rc)
|
|
|
|
{
|
2011-04-29 15:07:11 +02:00
|
|
|
if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
|
2015-01-22 12:06:11 +01:00
|
|
|
log_error ("keydb_search_first failed: %s\n", gpg_strerror (rc));
|
2010-01-09 20:00:46 +01:00
|
|
|
goto leave;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
lastresname = NULL;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
rc = keydb_get_keyblock (hd, &keyblock);
|
|
|
|
if (rc)
|
|
|
|
{
|
2015-01-22 16:36:28 +01:00
|
|
|
if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
|
|
|
|
continue; /* Skip legacy keys. */
|
2015-01-22 12:06:11 +01:00
|
|
|
log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc));
|
2010-01-09 20:00:46 +01:00
|
|
|
goto leave;
|
|
|
|
}
|
2014-06-03 21:35:59 +02:00
|
|
|
|
|
|
|
if (secret || mark_secret)
|
|
|
|
any_secret = !agent_probe_any_secret_key (NULL, keyblock);
|
|
|
|
else
|
|
|
|
any_secret = 0;
|
|
|
|
|
|
|
|
if (secret && !any_secret)
|
2010-02-02 15:06:19 +01:00
|
|
|
; /* Secret key listing requested but this isn't one. */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!opt.with_colons)
|
|
|
|
{
|
|
|
|
resname = keydb_get_resource_name (hd);
|
|
|
|
if (lastresname != resname)
|
|
|
|
{
|
|
|
|
int i;
|
2011-02-04 12:57:53 +01:00
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%s\n", resname);
|
2010-02-02 15:06:19 +01:00
|
|
|
for (i = strlen (resname); i; i--)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('-', es_stdout);
|
|
|
|
es_putc ('\n', es_stdout);
|
2010-02-02 15:06:19 +01:00
|
|
|
lastresname = resname;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
merge_keys_and_selfsig (keyblock);
|
2015-10-08 14:55:07 +02:00
|
|
|
list_keyblock (ctrl, keyblock, secret, any_secret, opt.fingerprint,
|
2015-04-06 19:46:25 +02:00
|
|
|
&listctx);
|
2010-02-02 15:06:19 +01:00
|
|
|
}
|
2010-01-09 20:00:46 +01:00
|
|
|
release_kbnode (keyblock);
|
|
|
|
keyblock = NULL;
|
|
|
|
}
|
|
|
|
while (!(rc = keydb_search_next (hd)));
|
2014-10-09 20:57:02 +02:00
|
|
|
es_fflush (es_stdout);
|
2011-04-29 15:07:11 +02:00
|
|
|
if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
|
2015-01-22 12:06:11 +01:00
|
|
|
log_error ("keydb_search_next failed: %s\n", gpg_strerror (rc));
|
2014-10-09 21:01:49 +02:00
|
|
|
if (keydb_get_skipped_counter (hd))
|
|
|
|
log_info (_("Warning: %lu key(s) skipped due to their large size\n"),
|
|
|
|
keydb_get_skipped_counter (hd));
|
2010-01-09 20:00:46 +01:00
|
|
|
|
|
|
|
if (opt.check_sigs && !opt.with_colons)
|
2015-04-06 19:46:25 +02:00
|
|
|
print_signature_stats (&listctx);
|
2010-01-09 20:00:46 +01:00
|
|
|
|
2015-04-06 19:46:25 +02:00
|
|
|
leave:
|
|
|
|
keylist_context_release (&listctx);
|
2010-01-09 20:00:46 +01:00
|
|
|
release_kbnode (keyblock);
|
|
|
|
keydb_release (hd);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2015-10-08 14:55:07 +02:00
|
|
|
list_one (ctrl_t ctrl, strlist_t names, int secret, int mark_secret)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
int rc = 0;
|
|
|
|
KBNODE keyblock = NULL;
|
|
|
|
GETKEY_CTX ctx;
|
|
|
|
const char *resname;
|
|
|
|
const char *keyring_str = _("Keyring");
|
|
|
|
int i;
|
2015-04-06 19:46:25 +02:00
|
|
|
struct keylist_context listctx;
|
2010-01-09 20:00:46 +01:00
|
|
|
|
2015-04-06 19:46:25 +02:00
|
|
|
memset (&listctx, 0, sizeof (listctx));
|
|
|
|
if (!secret && opt.check_sigs)
|
|
|
|
listctx.check_sigs = 1;
|
2010-01-09 20:00:46 +01:00
|
|
|
|
|
|
|
/* fixme: using the bynames function has the disadvantage that we
|
|
|
|
* don't know wether one of the names given was not found. OTOH,
|
|
|
|
* this function has the advantage to list the names in the
|
|
|
|
* sequence as defined by the keyDB and does not duplicate
|
|
|
|
* outputs. A solution could be do test whether all given have
|
|
|
|
* been listed (this needs a way to use the keyDB search
|
|
|
|
* functions) or to have the search function return indicators for
|
|
|
|
* found names. Yet another way is to use the keydb search
|
|
|
|
* facilities directly. */
|
2010-02-02 15:06:19 +01:00
|
|
|
rc = getkey_bynames (&ctx, NULL, names, secret, &keyblock);
|
|
|
|
if (rc)
|
2010-01-09 20:00:46 +01:00
|
|
|
{
|
2015-01-22 12:06:11 +01:00
|
|
|
log_error ("error reading key: %s\n", gpg_strerror (rc));
|
2015-09-14 15:31:25 +02:00
|
|
|
getkey_end (ctx);
|
2010-02-02 15:06:19 +01:00
|
|
|
return;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
do
|
|
|
|
{
|
|
|
|
if ((opt.list_options & LIST_SHOW_KEYRING) && !opt.with_colons)
|
|
|
|
{
|
|
|
|
resname = keydb_get_resource_name (get_ctx_handle (ctx));
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%s: %s\n", keyring_str, resname);
|
2010-02-02 15:06:19 +01:00
|
|
|
for (i = strlen (resname) + strlen (keyring_str) + 2; i; i--)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('-', es_stdout);
|
|
|
|
es_putc ('\n', es_stdout);
|
2010-02-02 15:06:19 +01:00
|
|
|
}
|
2015-10-08 14:55:07 +02:00
|
|
|
list_keyblock (ctrl,
|
|
|
|
keyblock, secret, mark_secret, opt.fingerprint, &listctx);
|
2010-02-02 15:06:19 +01:00
|
|
|
release_kbnode (keyblock);
|
|
|
|
}
|
|
|
|
while (!getkey_next (ctx, NULL, &keyblock));
|
|
|
|
getkey_end (ctx);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (opt.check_sigs && !opt.with_colons)
|
2015-04-06 19:46:25 +02:00
|
|
|
print_signature_stats (&listctx);
|
|
|
|
|
|
|
|
keylist_context_release (&listctx);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2008-05-07 17:40:36 +02:00
|
|
|
|
|
|
|
static void
|
2010-10-01 22:33:53 +02:00
|
|
|
locate_one (ctrl_t ctrl, strlist_t names)
|
2008-05-07 17:40:36 +02:00
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
strlist_t sl;
|
2008-05-07 20:19:41 +02:00
|
|
|
GETKEY_CTX ctx = NULL;
|
2008-05-07 17:40:36 +02:00
|
|
|
KBNODE keyblock = NULL;
|
2015-04-06 19:46:25 +02:00
|
|
|
struct keylist_context listctx;
|
2008-05-07 17:40:36 +02:00
|
|
|
|
2015-04-06 19:46:25 +02:00
|
|
|
memset (&listctx, 0, sizeof (listctx));
|
|
|
|
if (opt.check_sigs)
|
|
|
|
listctx.check_sigs = 1;
|
2010-01-09 20:00:46 +01:00
|
|
|
|
|
|
|
for (sl = names; sl; sl = sl->next)
|
2008-05-07 17:40:36 +02:00
|
|
|
{
|
2010-10-01 22:33:53 +02:00
|
|
|
rc = get_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, NULL, 1, 0);
|
2008-05-07 17:40:36 +02:00
|
|
|
if (rc)
|
2010-01-09 20:00:46 +01:00
|
|
|
{
|
|
|
|
if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)
|
2015-01-22 12:06:11 +01:00
|
|
|
log_error ("error reading key: %s\n", gpg_strerror (rc));
|
2015-08-23 11:56:17 +02:00
|
|
|
else if (opt.verbose)
|
|
|
|
log_info (_("key \"%s\" not found: %s\n"),
|
|
|
|
sl->d, gpg_strerror (rc));
|
2008-05-07 17:40:36 +02:00
|
|
|
}
|
|
|
|
else
|
2010-01-09 20:00:46 +01:00
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
2015-10-08 14:55:07 +02:00
|
|
|
list_keyblock (ctrl, keyblock, 0, 0, opt.fingerprint, &listctx);
|
2010-01-09 20:00:46 +01:00
|
|
|
release_kbnode (keyblock);
|
|
|
|
}
|
2015-09-14 15:22:25 +02:00
|
|
|
while (ctx && !getkey_next (ctx, NULL, &keyblock));
|
2015-09-14 15:31:25 +02:00
|
|
|
getkey_end (ctx);
|
2010-01-09 20:00:46 +01:00
|
|
|
ctx = NULL;
|
|
|
|
}
|
2008-05-07 17:40:36 +02:00
|
|
|
}
|
2010-01-09 20:00:46 +01:00
|
|
|
|
2008-05-07 17:40:36 +02:00
|
|
|
if (opt.check_sigs && !opt.with_colons)
|
2015-04-06 19:46:25 +02:00
|
|
|
print_signature_stats (&listctx);
|
|
|
|
|
|
|
|
keylist_context_release (&listctx);
|
2008-05-07 17:40:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
static void
|
2010-01-09 20:00:46 +01:00
|
|
|
print_key_data (PKT_public_key * pk)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
int n = pk ? pubkey_get_npkey (pk->pubkey_algo) : 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
{
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "pkd:%d:%u:", i, mpi_get_nbits (pk->pkey[i]));
|
|
|
|
mpi_print (es_stdout, pk->pkey[i], 1);
|
|
|
|
es_putc (':', es_stdout);
|
|
|
|
es_putc ('\n', es_stdout);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-02-02 15:06:19 +01:00
|
|
|
print_capabilities (PKT_public_key *pk, KBNODE keyblock)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-02-02 15:06:19 +01:00
|
|
|
unsigned int use = pk->pubkey_usage;
|
|
|
|
int c_printed = 0;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
if (use & PUBKEY_USAGE_ENC)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('e', es_stdout);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
if (use & PUBKEY_USAGE_SIG)
|
|
|
|
{
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('s', es_stdout);
|
2010-10-20 13:33:50 +02:00
|
|
|
if (pk->flags.primary)
|
2010-02-02 15:06:19 +01:00
|
|
|
{
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('c', es_stdout);
|
2010-02-02 15:06:19 +01:00
|
|
|
/* The PUBKEY_USAGE_CERT flag was introduced later and we
|
|
|
|
used to always print 'c' for a primary key. To avoid any
|
|
|
|
regression here we better track whether we printed 'c'
|
|
|
|
already. */
|
|
|
|
c_printed = 1;
|
|
|
|
}
|
|
|
|
}
|
2003-09-05 09:40:18 +02:00
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
if ((use & PUBKEY_USAGE_CERT) && !c_printed)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('c', es_stdout);
|
2009-02-09 12:09:57 +01:00
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
if ((use & PUBKEY_USAGE_AUTH))
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('a', es_stdout);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2013-03-19 17:23:56 +01:00
|
|
|
if ((use & PUBKEY_USAGE_UNKNOWN))
|
|
|
|
es_putc ('?', es_stdout);
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (keyblock)
|
2010-02-02 15:06:19 +01:00
|
|
|
{
|
|
|
|
/* Figure out the usable capabilities. */
|
2010-01-09 20:00:46 +01:00
|
|
|
KBNODE k;
|
|
|
|
int enc = 0, sign = 0, cert = 0, auth = 0, disabled = 0;
|
|
|
|
|
|
|
|
for (k = keyblock; k; k = k->next)
|
|
|
|
{
|
|
|
|
if (k->pkt->pkttype == PKT_PUBLIC_KEY
|
|
|
|
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
|
|
|
{
|
|
|
|
pk = k->pkt->pkt.public_key;
|
|
|
|
|
2010-10-20 13:33:50 +02:00
|
|
|
if (pk->flags.primary)
|
2010-01-09 20:00:46 +01:00
|
|
|
disabled = pk_is_disabled (pk);
|
|
|
|
|
2010-10-20 13:33:50 +02:00
|
|
|
if (pk->flags.valid && !pk->flags.revoked && !pk->has_expired)
|
2010-01-09 20:00:46 +01:00
|
|
|
{
|
|
|
|
if (pk->pubkey_usage & PUBKEY_USAGE_ENC)
|
|
|
|
enc = 1;
|
|
|
|
if (pk->pubkey_usage & PUBKEY_USAGE_SIG)
|
|
|
|
{
|
|
|
|
sign = 1;
|
2010-10-20 13:33:50 +02:00
|
|
|
if (pk->flags.primary)
|
2010-01-09 20:00:46 +01:00
|
|
|
cert = 1;
|
|
|
|
}
|
|
|
|
if (pk->pubkey_usage & PUBKEY_USAGE_CERT)
|
|
|
|
cert = 1;
|
|
|
|
if ((pk->pubkey_usage & PUBKEY_USAGE_AUTH))
|
|
|
|
auth = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (enc)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('E', es_stdout);
|
2010-01-09 20:00:46 +01:00
|
|
|
if (sign)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('S', es_stdout);
|
2010-01-09 20:00:46 +01:00
|
|
|
if (cert)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('C', es_stdout);
|
2010-01-09 20:00:46 +01:00
|
|
|
if (auth)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('A', es_stdout);
|
2010-01-09 20:00:46 +01:00
|
|
|
if (disabled)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('D', es_stdout);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2011-02-04 12:57:53 +01:00
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc (':', es_stdout);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
/* FLAGS: 0x01 hashed
|
|
|
|
0x02 critical */
|
2006-04-19 13:26:11 +02:00
|
|
|
static void
|
2010-01-09 20:00:46 +01:00
|
|
|
print_one_subpacket (sigsubpkttype_t type, size_t len, int flags,
|
|
|
|
const byte * buf)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "spk:%d:%u:%u:", type, flags, (unsigned int) len);
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
for (i = 0; i < len; i++)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
/* printable ascii other than : and % */
|
2010-01-09 20:00:46 +01:00
|
|
|
if (buf[i] >= 32 && buf[i] <= 126 && buf[i] != ':' && buf[i] != '%')
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%c", buf[i]);
|
2006-04-19 13:26:11 +02:00
|
|
|
else
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%%%02X", buf[i]);
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "\n");
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
void
|
2010-01-09 20:00:46 +01:00
|
|
|
print_subpackets_colon (PKT_signature * sig)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
byte *i;
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
assert (opt.show_subpackets);
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
for (i = opt.show_subpackets; *i; i++)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
const byte *p;
|
|
|
|
size_t len;
|
2010-01-09 20:00:46 +01:00
|
|
|
int seq, crit;
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
seq = 0;
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
while ((p = enum_sig_subpkt (sig->hashed, *i, &len, &seq, &crit)))
|
|
|
|
print_one_subpacket (*i, len, 0x01 | (crit ? 0x02 : 0), p);
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
seq = 0;
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
while ((p = enum_sig_subpkt (sig->unhashed, *i, &len, &seq, &crit)))
|
|
|
|
print_one_subpacket (*i, len, 0x00 | (crit ? 0x02 : 0), p);
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
void
|
2010-02-02 15:06:19 +01:00
|
|
|
dump_attribs (const PKT_user_id *uid, PKT_public_key *pk)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (!attrib_fp)
|
2003-06-05 09:14:21 +02:00
|
|
|
return;
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
for (i = 0; i < uid->numattribs; i++)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
if (is_status_enabled ())
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
|
|
|
byte array[MAX_FINGERPRINT_LEN], *p;
|
2010-01-09 20:00:46 +01:00
|
|
|
char buf[(MAX_FINGERPRINT_LEN * 2) + 90];
|
|
|
|
size_t j, n;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
if (!pk)
|
|
|
|
BUG ();
|
|
|
|
fingerprint_from_pk (pk, array, &n);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
p = array;
|
2010-01-09 20:00:46 +01:00
|
|
|
for (j = 0; j < n; j++, p++)
|
|
|
|
sprintf (buf + 2 * j, "%02X", *p);
|
|
|
|
|
|
|
|
sprintf (buf + strlen (buf), " %lu %u %u %u %lu %lu %u",
|
|
|
|
(ulong) uid->attribs[i].len, uid->attribs[i].type, i + 1,
|
|
|
|
uid->numattribs, (ulong) uid->created,
|
|
|
|
(ulong) uid->expiredate,
|
|
|
|
((uid->is_primary ? 0x01 : 0) | (uid->
|
|
|
|
is_revoked ? 0x02 : 0) |
|
|
|
|
(uid->is_expired ? 0x04 : 0)));
|
|
|
|
write_status_text (STATUS_ATTRIBUTE, buf);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fwrite (uid->attribs[i].data, uid->attribs[i].len, 1, attrib_fp);
|
|
|
|
es_fflush (attrib_fp);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
|
2015-02-24 19:31:59 +01:00
|
|
|
/* Print IPGP cert records instead of a standard key listing. */
|
|
|
|
static void
|
2015-10-08 14:55:07 +02:00
|
|
|
list_keyblock_pka (ctrl_t ctrl, kbnode_t keyblock)
|
2015-02-24 19:31:59 +01:00
|
|
|
{
|
|
|
|
kbnode_t kbctx;
|
|
|
|
kbnode_t node;
|
|
|
|
PKT_public_key *pk;
|
|
|
|
char pkstrbuf[PUBKEY_STRING_SIZE];
|
|
|
|
char *hexfpr;
|
2015-10-08 15:04:45 +02:00
|
|
|
char *hexkeyblock = NULL;
|
|
|
|
unsigned int hexkeyblocklen;
|
|
|
|
const char *s;
|
2015-02-24 19:31:59 +01:00
|
|
|
|
|
|
|
/* Get the keyid from the keyblock. */
|
|
|
|
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
|
|
|
|
if (!node)
|
|
|
|
{
|
|
|
|
log_error ("Oops; key lost!\n");
|
|
|
|
dump_kbnode (keyblock);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pk = node->pkt->pkt.public_key;
|
|
|
|
|
2015-10-08 15:04:45 +02:00
|
|
|
/* First print an overview of the key with all userids. */
|
|
|
|
es_fprintf (es_stdout, ";; pub %s/%s %s\n;;",
|
2015-02-24 19:31:59 +01:00
|
|
|
pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
|
|
|
|
keystr_from_pk (pk), datestr_from_pk (pk));
|
|
|
|
print_fingerprint (NULL, pk, 10);
|
2015-10-08 15:04:45 +02:00
|
|
|
for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
|
|
|
|
{
|
|
|
|
if (node->pkt->pkttype == PKT_USER_ID)
|
|
|
|
{
|
|
|
|
PKT_user_id *uid = node->pkt->pkt.user_id;
|
|
|
|
|
|
|
|
if (pk && (uid->is_expired || uid->is_revoked)
|
|
|
|
&& !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
es_fputs (";; uid ", es_stdout);
|
|
|
|
print_utf8_buffer (es_stdout, uid->name, uid->len);
|
|
|
|
es_putc ('\n', es_stdout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-14 09:13:02 +01:00
|
|
|
hexfpr = hexfingerprint (pk, NULL, 0);
|
2015-10-08 15:04:45 +02:00
|
|
|
if (opt.print_dane_records)
|
|
|
|
{
|
|
|
|
kbnode_t dummy_keyblock;
|
|
|
|
void *data;
|
|
|
|
size_t datalen;
|
|
|
|
gpg_error_t err;
|
|
|
|
|
2015-11-16 12:41:46 +01:00
|
|
|
/* We do not have an export function which allows to pass a
|
2015-10-08 15:04:45 +02:00
|
|
|
keyblock, thus we need to search the key again. */
|
|
|
|
err = export_pubkey_buffer (ctrl, hexfpr,
|
2015-11-12 16:02:35 +01:00
|
|
|
EXPORT_DANE_FORMAT, NULL,
|
2015-10-08 15:04:45 +02:00
|
|
|
&dummy_keyblock, &data, &datalen);
|
|
|
|
release_kbnode (dummy_keyblock);
|
|
|
|
if (!err)
|
|
|
|
{
|
|
|
|
hexkeyblocklen = datalen;
|
|
|
|
hexkeyblock = bin2hex (data, datalen, NULL);
|
|
|
|
if (!hexkeyblock)
|
|
|
|
err = gpg_error_from_syserror ();
|
|
|
|
xfree (data);
|
|
|
|
ascii_strlwr (hexkeyblock);
|
|
|
|
}
|
|
|
|
if (err)
|
|
|
|
log_error (_("skipped \"%s\": %s\n"), hexfpr, gpg_strerror (err));
|
|
|
|
|
|
|
|
}
|
2015-02-24 19:31:59 +01:00
|
|
|
|
|
|
|
for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
|
|
|
|
{
|
|
|
|
if (node->pkt->pkttype == PKT_USER_ID)
|
|
|
|
{
|
|
|
|
PKT_user_id *uid = node->pkt->pkt.user_id;
|
|
|
|
char *mbox;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
if (pk && (uid->is_expired || uid->is_revoked)
|
|
|
|
&& !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
mbox = mailbox_from_userid (uid->name);
|
|
|
|
if (mbox && (p = strchr (mbox, '@')))
|
|
|
|
{
|
2015-10-08 15:04:45 +02:00
|
|
|
char hashbuf[32];
|
2015-02-24 19:31:59 +01:00
|
|
|
char *hash;
|
|
|
|
unsigned int len;
|
|
|
|
|
|
|
|
*p++ = 0;
|
2015-10-08 15:04:45 +02:00
|
|
|
if (opt.print_pka_records)
|
2015-02-24 19:31:59 +01:00
|
|
|
{
|
2015-10-08 15:04:45 +02:00
|
|
|
es_fprintf (es_stdout, "$ORIGIN _pka.%s.\n; %s\n; ",
|
|
|
|
p, hexfpr);
|
|
|
|
print_utf8_buffer (es_stdout, uid->name, uid->len);
|
|
|
|
es_putc ('\n', es_stdout);
|
|
|
|
gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf,
|
|
|
|
mbox, strlen (mbox));
|
|
|
|
hash = zb32_encode (hashbuf, 8*20);
|
|
|
|
if (hash)
|
|
|
|
{
|
|
|
|
len = strlen (hexfpr)/2;
|
|
|
|
es_fprintf (es_stdout,
|
|
|
|
"%s TYPE37 \\# %u 0006 0000 00 %02X %s\n",
|
|
|
|
hash, 6 + len, len, hexfpr);
|
|
|
|
xfree (hash);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (opt.print_dane_records && hexkeyblock)
|
|
|
|
{
|
|
|
|
es_fprintf (es_stdout, "$ORIGIN _openpgpkey.%s.\n; %s\n; ",
|
|
|
|
p, hexfpr);
|
|
|
|
print_utf8_buffer (es_stdout, uid->name, uid->len);
|
|
|
|
es_putc ('\n', es_stdout);
|
|
|
|
gcry_md_hash_buffer (GCRY_MD_SHA256, hashbuf,
|
|
|
|
mbox, strlen (mbox));
|
|
|
|
hash = bin2hex (hashbuf, 28, NULL);
|
|
|
|
if (hash)
|
|
|
|
{
|
|
|
|
ascii_strlwr (hash);
|
|
|
|
es_fprintf (es_stdout, "%s TYPE61 \\# %u (\n",
|
|
|
|
hash, hexkeyblocklen);
|
|
|
|
xfree (hash);
|
|
|
|
s = hexkeyblock;
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
es_fprintf (es_stdout, "\t%.64s\n", s);
|
|
|
|
if (strlen (s) < 64)
|
|
|
|
break;
|
|
|
|
s += 64;
|
|
|
|
}
|
|
|
|
es_fputs ("\t)\n", es_stdout);
|
|
|
|
}
|
2015-02-24 19:31:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
xfree (mbox);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
es_putc ('\n', es_stdout);
|
|
|
|
|
2015-10-08 15:04:45 +02:00
|
|
|
xfree (hexkeyblock);
|
2015-02-24 19:31:59 +01:00
|
|
|
xfree (hexfpr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
static void
|
2015-04-06 19:46:25 +02:00
|
|
|
list_keyblock_print (KBNODE keyblock, int secret, int fpr,
|
|
|
|
struct keylist_context *listctx)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-10-13 17:57:08 +02:00
|
|
|
int rc;
|
2010-01-09 20:00:46 +01:00
|
|
|
KBNODE kbctx;
|
|
|
|
KBNODE node;
|
|
|
|
PKT_public_key *pk;
|
|
|
|
int skip_sigs = 0;
|
2010-02-02 15:06:19 +01:00
|
|
|
int s2k_char;
|
2010-10-13 17:57:08 +02:00
|
|
|
char *hexgrip = NULL;
|
|
|
|
char *serialno = NULL;
|
2014-02-05 10:37:59 +01:00
|
|
|
char pkstrbuf[PUBKEY_STRING_SIZE];
|
2010-01-09 20:00:46 +01:00
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
/* Get the keyid from the keyblock. */
|
|
|
|
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
|
2010-01-09 20:00:46 +01:00
|
|
|
if (!node)
|
|
|
|
{
|
|
|
|
log_error ("Oops; key lost!\n");
|
|
|
|
dump_kbnode (keyblock);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
pk = node->pkt->pkt.public_key;
|
2010-10-13 17:57:08 +02:00
|
|
|
|
|
|
|
if (secret || opt.with_keygrip)
|
|
|
|
{
|
|
|
|
rc = hexkeygrip_from_pk (pk, &hexgrip);
|
|
|
|
if (rc)
|
|
|
|
log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (secret)
|
|
|
|
{
|
|
|
|
if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
|
|
|
|
s2k_char = serialno? '>':' ';
|
|
|
|
else
|
|
|
|
s2k_char = '#'; /* Key not found. */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
s2k_char = ' ';
|
2011-02-04 12:57:53 +01:00
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
check_trustdb_stale ();
|
2010-01-09 20:00:46 +01:00
|
|
|
|
2014-02-05 10:37:59 +01:00
|
|
|
|
|
|
|
es_fprintf (es_stdout, "%s%c %s/%s %s",
|
|
|
|
secret? "sec":"pub",
|
|
|
|
s2k_char,
|
|
|
|
pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
|
|
|
|
keystr_from_pk (pk), datestr_from_pk (pk));
|
2010-01-09 20:00:46 +01:00
|
|
|
|
2014-08-12 10:36:30 +02:00
|
|
|
if ((opt.list_options & LIST_SHOW_USAGE))
|
|
|
|
{
|
|
|
|
es_fprintf (es_stdout, " [%s]", usagestr_from_pk (pk, 0));
|
|
|
|
}
|
2010-10-20 13:33:50 +02:00
|
|
|
if (pk->flags.revoked)
|
2010-02-02 15:06:19 +01:00
|
|
|
{
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, " [");
|
|
|
|
es_fprintf (es_stdout, _("revoked: %s"), revokestr_from_pk (pk));
|
|
|
|
es_fprintf (es_stdout, "]");
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2010-02-02 15:06:19 +01:00
|
|
|
else if (pk->has_expired)
|
2010-01-09 20:00:46 +01:00
|
|
|
{
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, " [");
|
|
|
|
es_fprintf (es_stdout, _("expired: %s"), expirestr_from_pk (pk));
|
|
|
|
es_fprintf (es_stdout, "]");
|
2010-02-02 15:06:19 +01:00
|
|
|
}
|
|
|
|
else if (pk->expiredate)
|
|
|
|
{
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, " [");
|
|
|
|
es_fprintf (es_stdout, _("expires: %s"), expirestr_from_pk (pk));
|
|
|
|
es_fprintf (es_stdout, "]");
|
2010-02-02 15:06:19 +01:00
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
#if 0
|
2010-02-02 15:06:19 +01:00
|
|
|
/* I need to think about this some more. It's easy enough to
|
|
|
|
include, but it looks sort of confusing in the listing... */
|
|
|
|
if (opt.list_options & LIST_SHOW_VALIDITY)
|
|
|
|
{
|
g10: Add TOFU support.
* configure.ac: Check for sqlite3.
(SQLITE3_CFLAGS): AC_SUBST it.
(SQLITE3_LIBS): Likewise.
* g10/Makefile.am (AM_CFLAGS): Add $(SQLITE3_CFLAGS).
(gpg2_SOURCES): Add tofu.h and tofu.c.
(gpg2_LDADD): Add $(SQLITE3_LIBS).
* g10/tofu.c: New file.
* g10/tofu.h: New file.
* g10/options.h (trust_model): Define TM_TOFU and TM_TOFU_PGP.
(tofu_db_format): Define.
* g10/packet.h (PKT_signature): Add fields digest and digest_len.
* g10/gpg.c: Include "tofu.h".
(cmd_and_opt_values): Declare aTOFUPolicy, oTOFUDefaultPolicy,
oTOFUDBFormat.
(opts): Add them.
(parse_trust_model): Recognize the tofu and tofu+pgp trust models.
(parse_tofu_policy): New function.
(parse_tofu_db_format): New function.
(main): Initialize opt.tofu_default_policy and opt.tofu_db_format.
Handle aTOFUPolicy, oTOFUDefaultPolicy and oTOFUDBFormat.
* g10/mainproc.c (do_check_sig): If the signature is good, copy the
hash to SIG->DIGEST and set SIG->DIGEST_LEN appropriately.
* g10/trustdb.h (get_validity): Add arguments sig and may_ask. Update
callers.
(tdb_get_validity_core): Add arguments sig and may_ask. Update
callers.
* g10/trust.c (get_validity) Add arguments sig and may_ask. Pass them
to tdb_get_validity_core.
* g10/trustdb.c: Include "tofu.h".
(trust_model_string): Handle TM_TOFU and TM_TOFU_PGP.
(tdb_get_validity_core): Add arguments sig and may_ask. If
OPT.TRUST_MODEL is TM_TOFU or TM_TOFU_PGP, compute the TOFU trust
level. Combine it with the computed PGP trust level, if appropriate.
* g10/keyedit.c: Include "tofu.h".
(show_key_with_all_names_colon): If the trust mode is tofu or
tofu+pgp, then show the trust policy.
* g10/keylist.c: Include "tofu.h".
(public_key_list): Also show the PGP stats if the trust model is
TM_TOFU_PGP.
(list_keyblock_colon): If the trust mode is tofu or
tofu+pgp, then show the trust policy.
* g10/pkclist.c: Include "tofu.h".
* g10/gpgv.c (get_validity): Add arguments sig and may_ask.
(enum tofu_policy): Define.
(tofu_get_policy): New stub.
(tofu_policy_str): Likewise.
* g10/test-stubs.c (get_validity): Add arguments sig and may_ask.
(enum tofu_policy): Define.
(tofu_get_policy): New stub.
(tofu_policy_str): Likewise.
* doc/DETAILS: Describe the TOFU Policy field.
* doc/gpg.texi: Document --tofu-set-policy, --trust-model=tofu,
--trust-model=tofu+pgp, --tofu-default-policy and --tofu-db-format.
* tests/openpgp/Makefile.am (TESTS): Add tofu.test.
(TEST_FILES): Add tofu-keys.asc, tofu-keys-secret.asc,
tofu-2183839A-1.txt, tofu-BC15C85A-1.txt and tofu-EE37CF96-1.txt.
(CLEANFILES): Add tofu.db.
(clean-local): Add tofu.d.
* tests/openpgp/tofu.test: New file.
* tests/openpgp/tofu-2183839A-1.txt: New file.
* tests/openpgp/tofu-BC15C85A-1.txt: New file.
* tests/openpgp/tofu-EE37CF96-1.txt: New file.
* tests/openpgp/tofu-keys.asc: New file.
* tests/openpgp/tofu-keys-secret.asc: New file.
--
Signed-off-by: Neal H. Walfield <neal@g10code.com>.
2015-10-18 18:44:05 +02:00
|
|
|
int validity = get_validity (pk, NULL, NULL, 0);
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, " [%s]", trust_value_to_string (validity));
|
2010-02-02 15:06:19 +01:00
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
#endif
|
|
|
|
|
2014-05-07 13:39:28 +02:00
|
|
|
if (pk->pubkey_algo >= 100)
|
|
|
|
es_fprintf (es_stdout, " [experimental algorithm %d]", pk->pubkey_algo);
|
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "\n");
|
2010-01-09 20:00:46 +01:00
|
|
|
|
|
|
|
if (fpr)
|
2014-03-27 12:59:55 +01:00
|
|
|
print_fingerprint (NULL, pk, 0);
|
2010-02-02 15:06:19 +01:00
|
|
|
|
2010-10-13 17:57:08 +02:00
|
|
|
if (opt.with_keygrip && hexgrip)
|
|
|
|
es_fprintf (es_stdout, " Keygrip = %s\n", hexgrip);
|
2010-10-08 13:11:08 +02:00
|
|
|
|
2010-10-13 17:57:08 +02:00
|
|
|
if (serialno)
|
|
|
|
print_card_serialno (serialno);
|
2010-02-02 15:06:19 +01:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (opt.with_key_data)
|
|
|
|
print_key_data (pk);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
|
|
|
|
{
|
2015-04-06 20:23:05 +02:00
|
|
|
if (node->pkt->pkttype == PKT_USER_ID)
|
2010-01-09 20:00:46 +01:00
|
|
|
{
|
|
|
|
PKT_user_id *uid = node->pkt->pkt.user_id;
|
|
|
|
|
2015-03-15 12:30:06 +01:00
|
|
|
if ((uid->is_expired || uid->is_revoked)
|
2010-01-09 20:00:46 +01:00
|
|
|
&& !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
|
|
|
|
{
|
|
|
|
skip_sigs = 1;
|
|
|
|
continue;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2010-01-09 20:00:46 +01:00
|
|
|
else
|
|
|
|
skip_sigs = 0;
|
|
|
|
|
|
|
|
if (attrib_fp && uid->attrib_data != NULL)
|
2010-02-02 15:06:19 +01:00
|
|
|
dump_attribs (uid, pk);
|
2010-01-09 20:00:46 +01:00
|
|
|
|
|
|
|
if ((uid->is_revoked || uid->is_expired)
|
2015-03-15 12:30:06 +01:00
|
|
|
|| (opt.list_options & LIST_SHOW_UID_VALIDITY))
|
2010-01-09 20:00:46 +01:00
|
|
|
{
|
|
|
|
const char *validity;
|
|
|
|
int indent;
|
|
|
|
|
|
|
|
validity = uid_trust_string_fixed (pk, uid);
|
|
|
|
indent =
|
2015-08-06 17:09:27 +02:00
|
|
|
(keystrlen () + (opt.legacy_list_mode? 9:11)) -
|
2010-01-09 20:00:46 +01:00
|
|
|
atoi (uid_trust_string_fixed (NULL, NULL));
|
|
|
|
|
|
|
|
if (indent < 0 || indent > 40)
|
|
|
|
indent = 0;
|
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "uid%*s%s ", indent, "", validity);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2010-01-09 20:00:46 +01:00
|
|
|
else
|
2015-08-06 17:09:27 +02:00
|
|
|
es_fprintf (es_stdout, "uid%*s",
|
|
|
|
(int) keystrlen () + (opt.legacy_list_mode? 10:12), "");
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
print_utf8_buffer (es_stdout, uid->name, uid->len);
|
|
|
|
es_putc ('\n', es_stdout);
|
2010-01-09 20:00:46 +01:00
|
|
|
|
|
|
|
if ((opt.list_options & LIST_SHOW_PHOTOS) && uid->attribs != NULL)
|
2010-04-23 13:36:59 +02:00
|
|
|
show_photos (uid->attribs, uid->numattribs, pk, uid);
|
2010-01-09 20:00:46 +01:00
|
|
|
}
|
|
|
|
else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
|
|
|
{
|
|
|
|
PKT_public_key *pk2 = node->pkt->pkt.public_key;
|
|
|
|
|
2010-10-20 13:33:50 +02:00
|
|
|
if ((pk2->flags.revoked || pk2->has_expired)
|
2010-01-09 20:00:46 +01:00
|
|
|
&& !(opt.list_options & LIST_SHOW_UNUSABLE_SUBKEYS))
|
|
|
|
{
|
|
|
|
skip_sigs = 1;
|
|
|
|
continue;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2010-01-09 20:00:46 +01:00
|
|
|
else
|
|
|
|
skip_sigs = 0;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-10-13 17:57:08 +02:00
|
|
|
xfree (serialno); serialno = NULL;
|
|
|
|
xfree (hexgrip); hexgrip = NULL;
|
|
|
|
if (secret || opt.with_keygrip)
|
|
|
|
{
|
|
|
|
rc = hexkeygrip_from_pk (pk2, &hexgrip);
|
|
|
|
if (rc)
|
|
|
|
log_error ("error computing a keygrip: %s\n",
|
|
|
|
gpg_strerror (rc));
|
|
|
|
}
|
|
|
|
if (secret)
|
|
|
|
{
|
|
|
|
if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
|
|
|
|
s2k_char = serialno? '>':' ';
|
|
|
|
else
|
|
|
|
s2k_char = '#'; /* Key not found. */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
s2k_char = ' ';
|
2011-02-04 12:57:53 +01:00
|
|
|
|
2014-02-05 10:37:59 +01:00
|
|
|
es_fprintf (es_stdout, "%s%c %s/%s %s",
|
2010-02-02 15:06:19 +01:00
|
|
|
secret? "ssb":"sub",
|
|
|
|
s2k_char,
|
2014-02-05 10:37:59 +01:00
|
|
|
pubkey_string (pk2, pkstrbuf, sizeof pkstrbuf),
|
2010-01-09 20:00:46 +01:00
|
|
|
keystr_from_pk (pk2), datestr_from_pk (pk2));
|
2013-11-15 08:59:45 +01:00
|
|
|
|
2014-08-12 10:36:30 +02:00
|
|
|
if ((opt.list_options & LIST_SHOW_USAGE))
|
|
|
|
{
|
|
|
|
es_fprintf (es_stdout, " [%s]", usagestr_from_pk (pk2, 0));
|
|
|
|
}
|
2010-10-20 13:33:50 +02:00
|
|
|
if (pk2->flags.revoked)
|
2010-01-09 20:00:46 +01:00
|
|
|
{
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, " [");
|
|
|
|
es_fprintf (es_stdout, _("revoked: %s"), revokestr_from_pk (pk2));
|
|
|
|
es_fprintf (es_stdout, "]");
|
2010-01-09 20:00:46 +01:00
|
|
|
}
|
|
|
|
else if (pk2->has_expired)
|
|
|
|
{
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, " [");
|
|
|
|
es_fprintf (es_stdout, _("expired: %s"), expirestr_from_pk (pk2));
|
|
|
|
es_fprintf (es_stdout, "]");
|
2010-01-09 20:00:46 +01:00
|
|
|
}
|
|
|
|
else if (pk2->expiredate)
|
|
|
|
{
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, " [");
|
|
|
|
es_fprintf (es_stdout, _("expires: %s"), expirestr_from_pk (pk2));
|
|
|
|
es_fprintf (es_stdout, "]");
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('\n', es_stdout);
|
2010-01-09 20:00:46 +01:00
|
|
|
if (fpr > 1)
|
2010-02-02 15:06:19 +01:00
|
|
|
{
|
2014-03-27 12:59:55 +01:00
|
|
|
print_fingerprint (NULL, pk2, 0);
|
2010-10-13 17:57:08 +02:00
|
|
|
if (serialno)
|
|
|
|
print_card_serialno (serialno);
|
2010-10-08 13:11:08 +02:00
|
|
|
}
|
2010-10-13 17:57:08 +02:00
|
|
|
if (opt.with_keygrip && hexgrip)
|
|
|
|
es_fprintf (es_stdout, " Keygrip = %s\n", hexgrip);
|
2010-01-09 20:00:46 +01:00
|
|
|
if (opt.with_key_data)
|
|
|
|
print_key_data (pk2);
|
|
|
|
}
|
|
|
|
else if (opt.list_sigs
|
|
|
|
&& node->pkt->pkttype == PKT_SIGNATURE && !skip_sigs)
|
|
|
|
{
|
|
|
|
PKT_signature *sig = node->pkt->pkt.signature;
|
|
|
|
int sigrc;
|
|
|
|
char *sigstr;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2015-04-06 19:46:25 +02:00
|
|
|
if (listctx->check_sigs)
|
2010-01-09 20:00:46 +01:00
|
|
|
{
|
|
|
|
rc = check_key_signature (keyblock, node, NULL);
|
|
|
|
switch (gpg_err_code (rc))
|
|
|
|
{
|
|
|
|
case 0:
|
2015-06-20 15:05:32 +02:00
|
|
|
listctx->good_sigs++;
|
2010-01-09 20:00:46 +01:00
|
|
|
sigrc = '!';
|
|
|
|
break;
|
|
|
|
case GPG_ERR_BAD_SIGNATURE:
|
2015-04-06 19:46:25 +02:00
|
|
|
listctx->inv_sigs++;
|
2010-01-09 20:00:46 +01:00
|
|
|
sigrc = '-';
|
|
|
|
break;
|
|
|
|
case GPG_ERR_NO_PUBKEY:
|
|
|
|
case GPG_ERR_UNUSABLE_PUBKEY:
|
2015-04-06 19:46:25 +02:00
|
|
|
listctx->no_key++;
|
2010-01-09 20:00:46 +01:00
|
|
|
continue;
|
|
|
|
default:
|
2015-04-06 19:46:25 +02:00
|
|
|
listctx->oth_err++;
|
2010-01-09 20:00:46 +01:00
|
|
|
sigrc = '%';
|
|
|
|
break;
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
/* TODO: Make sure a cached sig record here still has
|
|
|
|
the pk that issued it. See also
|
|
|
|
keyedit.c:print_and_check_one_sig */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rc = 0;
|
|
|
|
sigrc = ' ';
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (sig->sig_class == 0x20 || sig->sig_class == 0x28
|
|
|
|
|| sig->sig_class == 0x30)
|
|
|
|
sigstr = "rev";
|
|
|
|
else if ((sig->sig_class & ~3) == 0x10)
|
|
|
|
sigstr = "sig";
|
|
|
|
else if (sig->sig_class == 0x18)
|
|
|
|
sigstr = "sig";
|
|
|
|
else if (sig->sig_class == 0x1F)
|
|
|
|
sigstr = "sig";
|
|
|
|
else
|
|
|
|
{
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "sig "
|
2010-01-09 20:00:46 +01:00
|
|
|
"[unexpected signature class 0x%02x]\n",
|
|
|
|
sig->sig_class);
|
|
|
|
continue;
|
|
|
|
}
|
2003-09-23 19:48:33 +02:00
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fputs (sigstr, es_stdout);
|
|
|
|
es_fprintf (es_stdout, "%c%c %c%c%c%c%c%c %s %s",
|
2010-01-09 20:00:46 +01:00
|
|
|
sigrc, (sig->sig_class - 0x10 > 0 &&
|
|
|
|
sig->sig_class - 0x10 <
|
|
|
|
4) ? '0' + sig->sig_class - 0x10 : ' ',
|
|
|
|
sig->flags.exportable ? ' ' : 'L',
|
|
|
|
sig->flags.revocable ? ' ' : 'R',
|
|
|
|
sig->flags.policy_url ? 'P' : ' ',
|
|
|
|
sig->flags.notation ? 'N' : ' ',
|
|
|
|
sig->flags.expired ? 'X' : ' ',
|
|
|
|
(sig->trust_depth > 9) ? 'T' : (sig->trust_depth >
|
|
|
|
0) ? '0' +
|
|
|
|
sig->trust_depth : ' ', keystr (sig->keyid),
|
|
|
|
datestr_from_sig (sig));
|
|
|
|
if (opt.list_options & LIST_SHOW_SIG_EXPIRE)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, " %s", expirestr_from_sig (sig));
|
|
|
|
es_fprintf (es_stdout, " ");
|
2010-01-09 20:00:46 +01:00
|
|
|
if (sigrc == '%')
|
2015-01-22 12:06:11 +01:00
|
|
|
es_fprintf (es_stdout, "[%s] ", gpg_strerror (rc));
|
2010-01-09 20:00:46 +01:00
|
|
|
else if (sigrc == '?')
|
|
|
|
;
|
|
|
|
else if (!opt.fast_list_mode)
|
|
|
|
{
|
|
|
|
size_t n;
|
|
|
|
char *p = get_user_id (sig->keyid, &n);
|
2010-03-15 12:15:45 +01:00
|
|
|
print_utf8_buffer (es_stdout, p, n);
|
2010-01-09 20:00:46 +01:00
|
|
|
xfree (p);
|
|
|
|
}
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('\n', es_stdout);
|
2010-01-09 20:00:46 +01:00
|
|
|
|
|
|
|
if (sig->flags.policy_url
|
|
|
|
&& (opt.list_options & LIST_SHOW_POLICY_URLS))
|
|
|
|
show_policy_url (sig, 3, 0);
|
|
|
|
|
|
|
|
if (sig->flags.notation && (opt.list_options & LIST_SHOW_NOTATIONS))
|
|
|
|
show_notation (sig, 3, 0,
|
|
|
|
((opt.
|
|
|
|
list_options & LIST_SHOW_STD_NOTATIONS) ? 1 : 0)
|
|
|
|
+
|
|
|
|
((opt.
|
|
|
|
list_options & LIST_SHOW_USER_NOTATIONS) ? 2 :
|
|
|
|
0));
|
|
|
|
|
|
|
|
if (sig->flags.pref_ks
|
|
|
|
&& (opt.list_options & LIST_SHOW_KEYSERVER_URLS))
|
|
|
|
show_keyserver_url (sig, 3, 0);
|
|
|
|
|
|
|
|
/* fixme: check or list other sigs here */
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
}
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('\n', es_stdout);
|
2010-10-13 17:57:08 +02:00
|
|
|
xfree (serialno);
|
|
|
|
xfree (hexgrip);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
void
|
2014-03-27 12:59:55 +01:00
|
|
|
print_revokers (estream_t fp, PKT_public_key * pk)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
/* print the revoker record */
|
2010-01-09 20:00:46 +01:00
|
|
|
if (!pk->revkey && pk->numrevkeys)
|
|
|
|
BUG ();
|
2006-04-19 13:26:11 +02:00
|
|
|
else
|
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
int i, j;
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
for (i = 0; i < pk->numrevkeys; i++)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
byte *p;
|
|
|
|
|
2014-03-27 12:59:55 +01:00
|
|
|
es_fprintf (fp, "rvk:::%d::::::", pk->revkey[i].algid);
|
2006-04-19 13:26:11 +02:00
|
|
|
p = pk->revkey[i].fpr;
|
2010-01-09 20:00:46 +01:00
|
|
|
for (j = 0; j < 20; j++, p++)
|
2014-03-27 12:59:55 +01:00
|
|
|
es_fprintf (fp, "%02X", *p);
|
|
|
|
es_fprintf (fp, ":%02x%s:\n",
|
|
|
|
pk->revkey[i].class,
|
|
|
|
(pk->revkey[i].class & 0x40) ? "s" : "");
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2014-06-03 21:35:59 +02:00
|
|
|
|
|
|
|
/* List a key in colon mode. If SECRET is true this is a secret key
|
|
|
|
record (i.e. requested via --list-secret-key). If HAS_SECRET a
|
|
|
|
secret key is available even if SECRET is not set. */
|
2003-06-05 09:14:21 +02:00
|
|
|
static void
|
2014-06-03 21:35:59 +02:00
|
|
|
list_keyblock_colon (KBNODE keyblock, int secret, int has_secret, int fpr)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-10-13 17:57:08 +02:00
|
|
|
int rc;
|
2008-06-11 10:07:54 +02:00
|
|
|
KBNODE kbctx;
|
|
|
|
KBNODE node;
|
|
|
|
PKT_public_key *pk;
|
|
|
|
u32 keyid[2];
|
|
|
|
int trustletter = 0;
|
|
|
|
int ulti_hack = 0;
|
|
|
|
int i;
|
2010-04-20 19:57:50 +02:00
|
|
|
char *p;
|
2010-10-13 17:57:08 +02:00
|
|
|
char *hexgrip = NULL;
|
|
|
|
char *serialno = NULL;
|
|
|
|
int stubkey;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
/* Get the keyid from the keyblock. */
|
|
|
|
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
|
2010-01-09 20:00:46 +01:00
|
|
|
if (!node)
|
2008-06-11 10:07:54 +02:00
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
log_error ("Oops; key lost!\n");
|
|
|
|
dump_kbnode (keyblock);
|
2008-06-11 10:07:54 +02:00
|
|
|
return;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2010-02-02 15:06:19 +01:00
|
|
|
pk = node->pkt->pkt.public_key;
|
2014-06-03 21:35:59 +02:00
|
|
|
if (secret || has_secret || opt.with_keygrip || opt.with_key_data)
|
2010-10-13 17:57:08 +02:00
|
|
|
{
|
|
|
|
rc = hexkeygrip_from_pk (pk, &hexgrip);
|
|
|
|
if (rc)
|
|
|
|
log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
|
|
|
|
}
|
|
|
|
stubkey = 0;
|
2014-06-03 21:35:59 +02:00
|
|
|
if ((secret||has_secret) && agent_get_keyinfo (NULL, hexgrip, &serialno))
|
2010-10-13 17:57:08 +02:00
|
|
|
stubkey = 1; /* Key not found. */
|
2010-02-02 15:06:19 +01:00
|
|
|
|
|
|
|
keyid_from_pk (pk, keyid);
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fputs (secret? "sec:":"pub:", es_stdout);
|
2010-10-20 13:33:50 +02:00
|
|
|
if (!pk->flags.valid)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('i', es_stdout);
|
2010-10-20 13:33:50 +02:00
|
|
|
else if (pk->flags.revoked)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('r', es_stdout);
|
2010-02-02 15:06:19 +01:00
|
|
|
else if (pk->has_expired)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('e', es_stdout);
|
2010-02-02 15:06:19 +01:00
|
|
|
else if (opt.fast_list_mode || opt.no_expensive_trust_checks)
|
|
|
|
;
|
2008-06-11 10:07:54 +02:00
|
|
|
else
|
|
|
|
{
|
2010-02-02 15:06:19 +01:00
|
|
|
trustletter = get_validity_info (pk, NULL);
|
|
|
|
if (trustletter == 'u')
|
|
|
|
ulti_hack = 1;
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc (trustletter, es_stdout);
|
2008-06-11 10:07:54 +02:00
|
|
|
}
|
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s::",
|
2010-02-02 15:06:19 +01:00
|
|
|
nbits_from_pk (pk),
|
|
|
|
pk->pubkey_algo,
|
|
|
|
(ulong) keyid[0], (ulong) keyid[1],
|
|
|
|
colon_datestr_from_pk (pk), colon_strtime (pk->expiredate));
|
|
|
|
|
|
|
|
if (!opt.fast_list_mode && !opt.no_expensive_trust_checks)
|
2011-04-20 22:41:22 +02:00
|
|
|
es_putc (get_ownertrust_info (pk), es_stdout);
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc (':', es_stdout);
|
2010-02-02 15:06:19 +01:00
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc (':', es_stdout);
|
|
|
|
es_putc (':', es_stdout);
|
2010-02-02 15:06:19 +01:00
|
|
|
print_capabilities (pk, keyblock);
|
2013-11-15 08:59:45 +01:00
|
|
|
es_putc (':', es_stdout); /* End of field 13. */
|
|
|
|
es_putc (':', es_stdout); /* End of field 14. */
|
2014-06-03 21:35:59 +02:00
|
|
|
if (secret || has_secret)
|
2008-06-11 10:07:54 +02:00
|
|
|
{
|
2010-10-13 17:57:08 +02:00
|
|
|
if (stubkey)
|
|
|
|
es_putc ('#', es_stdout);
|
|
|
|
else if (serialno)
|
2013-11-15 08:59:45 +01:00
|
|
|
es_fputs (serialno, es_stdout);
|
2014-06-03 21:35:59 +02:00
|
|
|
else if (has_secret)
|
|
|
|
es_putc ('+', es_stdout);
|
2013-11-15 08:59:45 +01:00
|
|
|
}
|
|
|
|
es_putc (':', es_stdout); /* End of field 15. */
|
|
|
|
es_putc (':', es_stdout); /* End of field 16. */
|
|
|
|
if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
|| pk->pubkey_algo == PUBKEY_ALGO_EDDSA
|
2013-11-15 08:59:45 +01:00
|
|
|
|| pk->pubkey_algo == PUBKEY_ALGO_ECDH)
|
|
|
|
{
|
|
|
|
char *curve = openpgp_oid_to_str (pk->pkey[0]);
|
2015-08-06 09:44:03 +02:00
|
|
|
const char *name = openpgp_oid_to_curve (curve, 0);
|
2015-07-08 08:05:06 +02:00
|
|
|
if (!name)
|
2013-11-15 08:59:45 +01:00
|
|
|
name = curve;
|
|
|
|
es_fputs (name, es_stdout);
|
|
|
|
xfree (curve);
|
2008-06-11 10:07:54 +02:00
|
|
|
}
|
2013-11-15 08:59:45 +01:00
|
|
|
es_putc (':', es_stdout); /* End of field 17. */
|
g10: Add TOFU support.
* configure.ac: Check for sqlite3.
(SQLITE3_CFLAGS): AC_SUBST it.
(SQLITE3_LIBS): Likewise.
* g10/Makefile.am (AM_CFLAGS): Add $(SQLITE3_CFLAGS).
(gpg2_SOURCES): Add tofu.h and tofu.c.
(gpg2_LDADD): Add $(SQLITE3_LIBS).
* g10/tofu.c: New file.
* g10/tofu.h: New file.
* g10/options.h (trust_model): Define TM_TOFU and TM_TOFU_PGP.
(tofu_db_format): Define.
* g10/packet.h (PKT_signature): Add fields digest and digest_len.
* g10/gpg.c: Include "tofu.h".
(cmd_and_opt_values): Declare aTOFUPolicy, oTOFUDefaultPolicy,
oTOFUDBFormat.
(opts): Add them.
(parse_trust_model): Recognize the tofu and tofu+pgp trust models.
(parse_tofu_policy): New function.
(parse_tofu_db_format): New function.
(main): Initialize opt.tofu_default_policy and opt.tofu_db_format.
Handle aTOFUPolicy, oTOFUDefaultPolicy and oTOFUDBFormat.
* g10/mainproc.c (do_check_sig): If the signature is good, copy the
hash to SIG->DIGEST and set SIG->DIGEST_LEN appropriately.
* g10/trustdb.h (get_validity): Add arguments sig and may_ask. Update
callers.
(tdb_get_validity_core): Add arguments sig and may_ask. Update
callers.
* g10/trust.c (get_validity) Add arguments sig and may_ask. Pass them
to tdb_get_validity_core.
* g10/trustdb.c: Include "tofu.h".
(trust_model_string): Handle TM_TOFU and TM_TOFU_PGP.
(tdb_get_validity_core): Add arguments sig and may_ask. If
OPT.TRUST_MODEL is TM_TOFU or TM_TOFU_PGP, compute the TOFU trust
level. Combine it with the computed PGP trust level, if appropriate.
* g10/keyedit.c: Include "tofu.h".
(show_key_with_all_names_colon): If the trust mode is tofu or
tofu+pgp, then show the trust policy.
* g10/keylist.c: Include "tofu.h".
(public_key_list): Also show the PGP stats if the trust model is
TM_TOFU_PGP.
(list_keyblock_colon): If the trust mode is tofu or
tofu+pgp, then show the trust policy.
* g10/pkclist.c: Include "tofu.h".
* g10/gpgv.c (get_validity): Add arguments sig and may_ask.
(enum tofu_policy): Define.
(tofu_get_policy): New stub.
(tofu_policy_str): Likewise.
* g10/test-stubs.c (get_validity): Add arguments sig and may_ask.
(enum tofu_policy): Define.
(tofu_get_policy): New stub.
(tofu_policy_str): Likewise.
* doc/DETAILS: Describe the TOFU Policy field.
* doc/gpg.texi: Document --tofu-set-policy, --trust-model=tofu,
--trust-model=tofu+pgp, --tofu-default-policy and --tofu-db-format.
* tests/openpgp/Makefile.am (TESTS): Add tofu.test.
(TEST_FILES): Add tofu-keys.asc, tofu-keys-secret.asc,
tofu-2183839A-1.txt, tofu-BC15C85A-1.txt and tofu-EE37CF96-1.txt.
(CLEANFILES): Add tofu.db.
(clean-local): Add tofu.d.
* tests/openpgp/tofu.test: New file.
* tests/openpgp/tofu-2183839A-1.txt: New file.
* tests/openpgp/tofu-BC15C85A-1.txt: New file.
* tests/openpgp/tofu-EE37CF96-1.txt: New file.
* tests/openpgp/tofu-keys.asc: New file.
* tests/openpgp/tofu-keys-secret.asc: New file.
--
Signed-off-by: Neal H. Walfield <neal@g10code.com>.
2015-10-18 18:44:05 +02:00
|
|
|
es_putc (':', es_stdout); /* End of field 18. */
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('\n', es_stdout);
|
2010-02-02 15:06:19 +01:00
|
|
|
|
2014-03-27 12:59:55 +01:00
|
|
|
print_revokers (es_stdout, pk);
|
2008-06-11 10:07:54 +02:00
|
|
|
if (fpr)
|
2014-03-27 12:59:55 +01:00
|
|
|
print_fingerprint (NULL, pk, 0);
|
2010-10-08 13:11:08 +02:00
|
|
|
if (opt.with_key_data || opt.with_keygrip)
|
2010-04-20 19:57:50 +02:00
|
|
|
{
|
2010-10-13 17:57:08 +02:00
|
|
|
if (hexgrip)
|
|
|
|
es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
|
2010-10-08 13:11:08 +02:00
|
|
|
if (opt.with_key_data)
|
|
|
|
print_key_data (pk);
|
2010-04-20 19:57:50 +02:00
|
|
|
}
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
|
2008-06-11 10:07:54 +02:00
|
|
|
{
|
2015-04-06 20:23:05 +02:00
|
|
|
if (node->pkt->pkttype == PKT_USER_ID)
|
2010-01-09 20:00:46 +01:00
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
PKT_user_id *uid = node->pkt->pkt.user_id;
|
|
|
|
|
|
|
|
if (attrib_fp && node->pkt->pkt.user_id->attrib_data != NULL)
|
2010-02-02 15:06:19 +01:00
|
|
|
dump_attribs (node->pkt->pkt.user_id, pk);
|
2010-01-09 20:00:46 +01:00
|
|
|
/*
|
2011-02-04 12:57:53 +01:00
|
|
|
* Fixme: We need a valid flag here too
|
2010-01-09 20:00:46 +01:00
|
|
|
*/
|
|
|
|
str = uid->attrib_data ? "uat" : "uid";
|
2010-02-02 15:06:19 +01:00
|
|
|
if (uid->is_revoked)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%s:r::::", str);
|
2010-01-09 20:00:46 +01:00
|
|
|
else if (uid->is_expired)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%s:e::::", str);
|
2010-01-09 20:00:46 +01:00
|
|
|
else if (opt.no_expensive_trust_checks)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%s:::::", str);
|
2010-01-09 20:00:46 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
int uid_validity;
|
|
|
|
|
2015-03-15 12:30:06 +01:00
|
|
|
if (!ulti_hack)
|
2010-01-09 20:00:46 +01:00
|
|
|
uid_validity = get_validity_info (pk, uid);
|
|
|
|
else
|
|
|
|
uid_validity = 'u';
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%s:%c::::", str, uid_validity);
|
2010-01-09 20:00:46 +01:00
|
|
|
}
|
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%s:", colon_strtime (uid->created));
|
|
|
|
es_fprintf (es_stdout, "%s:", colon_strtime (uid->expiredate));
|
2010-01-09 20:00:46 +01:00
|
|
|
|
|
|
|
namehash_from_uid (uid);
|
|
|
|
|
|
|
|
for (i = 0; i < 20; i++)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%02X", uid->namehash[i]);
|
2010-01-09 20:00:46 +01:00
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "::");
|
2010-01-09 20:00:46 +01:00
|
|
|
|
|
|
|
if (uid->attrib_data)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%u %lu", uid->numattribs, uid->attrib_len);
|
2010-01-09 20:00:46 +01:00
|
|
|
else
|
2010-03-15 12:15:45 +01:00
|
|
|
es_write_sanitized (es_stdout, uid->name, uid->len, ":", NULL);
|
g10: Add TOFU support.
* configure.ac: Check for sqlite3.
(SQLITE3_CFLAGS): AC_SUBST it.
(SQLITE3_LIBS): Likewise.
* g10/Makefile.am (AM_CFLAGS): Add $(SQLITE3_CFLAGS).
(gpg2_SOURCES): Add tofu.h and tofu.c.
(gpg2_LDADD): Add $(SQLITE3_LIBS).
* g10/tofu.c: New file.
* g10/tofu.h: New file.
* g10/options.h (trust_model): Define TM_TOFU and TM_TOFU_PGP.
(tofu_db_format): Define.
* g10/packet.h (PKT_signature): Add fields digest and digest_len.
* g10/gpg.c: Include "tofu.h".
(cmd_and_opt_values): Declare aTOFUPolicy, oTOFUDefaultPolicy,
oTOFUDBFormat.
(opts): Add them.
(parse_trust_model): Recognize the tofu and tofu+pgp trust models.
(parse_tofu_policy): New function.
(parse_tofu_db_format): New function.
(main): Initialize opt.tofu_default_policy and opt.tofu_db_format.
Handle aTOFUPolicy, oTOFUDefaultPolicy and oTOFUDBFormat.
* g10/mainproc.c (do_check_sig): If the signature is good, copy the
hash to SIG->DIGEST and set SIG->DIGEST_LEN appropriately.
* g10/trustdb.h (get_validity): Add arguments sig and may_ask. Update
callers.
(tdb_get_validity_core): Add arguments sig and may_ask. Update
callers.
* g10/trust.c (get_validity) Add arguments sig and may_ask. Pass them
to tdb_get_validity_core.
* g10/trustdb.c: Include "tofu.h".
(trust_model_string): Handle TM_TOFU and TM_TOFU_PGP.
(tdb_get_validity_core): Add arguments sig and may_ask. If
OPT.TRUST_MODEL is TM_TOFU or TM_TOFU_PGP, compute the TOFU trust
level. Combine it with the computed PGP trust level, if appropriate.
* g10/keyedit.c: Include "tofu.h".
(show_key_with_all_names_colon): If the trust mode is tofu or
tofu+pgp, then show the trust policy.
* g10/keylist.c: Include "tofu.h".
(public_key_list): Also show the PGP stats if the trust model is
TM_TOFU_PGP.
(list_keyblock_colon): If the trust mode is tofu or
tofu+pgp, then show the trust policy.
* g10/pkclist.c: Include "tofu.h".
* g10/gpgv.c (get_validity): Add arguments sig and may_ask.
(enum tofu_policy): Define.
(tofu_get_policy): New stub.
(tofu_policy_str): Likewise.
* g10/test-stubs.c (get_validity): Add arguments sig and may_ask.
(enum tofu_policy): Define.
(tofu_get_policy): New stub.
(tofu_policy_str): Likewise.
* doc/DETAILS: Describe the TOFU Policy field.
* doc/gpg.texi: Document --tofu-set-policy, --trust-model=tofu,
--trust-model=tofu+pgp, --tofu-default-policy and --tofu-db-format.
* tests/openpgp/Makefile.am (TESTS): Add tofu.test.
(TEST_FILES): Add tofu-keys.asc, tofu-keys-secret.asc,
tofu-2183839A-1.txt, tofu-BC15C85A-1.txt and tofu-EE37CF96-1.txt.
(CLEANFILES): Add tofu.db.
(clean-local): Add tofu.d.
* tests/openpgp/tofu.test: New file.
* tests/openpgp/tofu-2183839A-1.txt: New file.
* tests/openpgp/tofu-BC15C85A-1.txt: New file.
* tests/openpgp/tofu-EE37CF96-1.txt: New file.
* tests/openpgp/tofu-keys.asc: New file.
* tests/openpgp/tofu-keys-secret.asc: New file.
--
Signed-off-by: Neal H. Walfield <neal@g10code.com>.
2015-10-18 18:44:05 +02:00
|
|
|
es_fprintf (es_stdout, "::::::::");
|
|
|
|
if (opt.trust_model == TM_TOFU || opt.trust_model == TM_TOFU_PGP)
|
|
|
|
{
|
2015-10-20 17:32:23 +02:00
|
|
|
#ifdef USE_TOFU
|
g10: Add TOFU support.
* configure.ac: Check for sqlite3.
(SQLITE3_CFLAGS): AC_SUBST it.
(SQLITE3_LIBS): Likewise.
* g10/Makefile.am (AM_CFLAGS): Add $(SQLITE3_CFLAGS).
(gpg2_SOURCES): Add tofu.h and tofu.c.
(gpg2_LDADD): Add $(SQLITE3_LIBS).
* g10/tofu.c: New file.
* g10/tofu.h: New file.
* g10/options.h (trust_model): Define TM_TOFU and TM_TOFU_PGP.
(tofu_db_format): Define.
* g10/packet.h (PKT_signature): Add fields digest and digest_len.
* g10/gpg.c: Include "tofu.h".
(cmd_and_opt_values): Declare aTOFUPolicy, oTOFUDefaultPolicy,
oTOFUDBFormat.
(opts): Add them.
(parse_trust_model): Recognize the tofu and tofu+pgp trust models.
(parse_tofu_policy): New function.
(parse_tofu_db_format): New function.
(main): Initialize opt.tofu_default_policy and opt.tofu_db_format.
Handle aTOFUPolicy, oTOFUDefaultPolicy and oTOFUDBFormat.
* g10/mainproc.c (do_check_sig): If the signature is good, copy the
hash to SIG->DIGEST and set SIG->DIGEST_LEN appropriately.
* g10/trustdb.h (get_validity): Add arguments sig and may_ask. Update
callers.
(tdb_get_validity_core): Add arguments sig and may_ask. Update
callers.
* g10/trust.c (get_validity) Add arguments sig and may_ask. Pass them
to tdb_get_validity_core.
* g10/trustdb.c: Include "tofu.h".
(trust_model_string): Handle TM_TOFU and TM_TOFU_PGP.
(tdb_get_validity_core): Add arguments sig and may_ask. If
OPT.TRUST_MODEL is TM_TOFU or TM_TOFU_PGP, compute the TOFU trust
level. Combine it with the computed PGP trust level, if appropriate.
* g10/keyedit.c: Include "tofu.h".
(show_key_with_all_names_colon): If the trust mode is tofu or
tofu+pgp, then show the trust policy.
* g10/keylist.c: Include "tofu.h".
(public_key_list): Also show the PGP stats if the trust model is
TM_TOFU_PGP.
(list_keyblock_colon): If the trust mode is tofu or
tofu+pgp, then show the trust policy.
* g10/pkclist.c: Include "tofu.h".
* g10/gpgv.c (get_validity): Add arguments sig and may_ask.
(enum tofu_policy): Define.
(tofu_get_policy): New stub.
(tofu_policy_str): Likewise.
* g10/test-stubs.c (get_validity): Add arguments sig and may_ask.
(enum tofu_policy): Define.
(tofu_get_policy): New stub.
(tofu_policy_str): Likewise.
* doc/DETAILS: Describe the TOFU Policy field.
* doc/gpg.texi: Document --tofu-set-policy, --trust-model=tofu,
--trust-model=tofu+pgp, --tofu-default-policy and --tofu-db-format.
* tests/openpgp/Makefile.am (TESTS): Add tofu.test.
(TEST_FILES): Add tofu-keys.asc, tofu-keys-secret.asc,
tofu-2183839A-1.txt, tofu-BC15C85A-1.txt and tofu-EE37CF96-1.txt.
(CLEANFILES): Add tofu.db.
(clean-local): Add tofu.d.
* tests/openpgp/tofu.test: New file.
* tests/openpgp/tofu-2183839A-1.txt: New file.
* tests/openpgp/tofu-BC15C85A-1.txt: New file.
* tests/openpgp/tofu-EE37CF96-1.txt: New file.
* tests/openpgp/tofu-keys.asc: New file.
* tests/openpgp/tofu-keys-secret.asc: New file.
--
Signed-off-by: Neal H. Walfield <neal@g10code.com>.
2015-10-18 18:44:05 +02:00
|
|
|
enum tofu_policy policy;
|
|
|
|
if (! tofu_get_policy (pk, uid, &policy)
|
|
|
|
&& policy != TOFU_POLICY_NONE)
|
|
|
|
es_fprintf (es_stdout, "%s", tofu_policy_str (policy));
|
2015-10-20 17:32:23 +02:00
|
|
|
#endif /*USE_TOFU*/
|
g10: Add TOFU support.
* configure.ac: Check for sqlite3.
(SQLITE3_CFLAGS): AC_SUBST it.
(SQLITE3_LIBS): Likewise.
* g10/Makefile.am (AM_CFLAGS): Add $(SQLITE3_CFLAGS).
(gpg2_SOURCES): Add tofu.h and tofu.c.
(gpg2_LDADD): Add $(SQLITE3_LIBS).
* g10/tofu.c: New file.
* g10/tofu.h: New file.
* g10/options.h (trust_model): Define TM_TOFU and TM_TOFU_PGP.
(tofu_db_format): Define.
* g10/packet.h (PKT_signature): Add fields digest and digest_len.
* g10/gpg.c: Include "tofu.h".
(cmd_and_opt_values): Declare aTOFUPolicy, oTOFUDefaultPolicy,
oTOFUDBFormat.
(opts): Add them.
(parse_trust_model): Recognize the tofu and tofu+pgp trust models.
(parse_tofu_policy): New function.
(parse_tofu_db_format): New function.
(main): Initialize opt.tofu_default_policy and opt.tofu_db_format.
Handle aTOFUPolicy, oTOFUDefaultPolicy and oTOFUDBFormat.
* g10/mainproc.c (do_check_sig): If the signature is good, copy the
hash to SIG->DIGEST and set SIG->DIGEST_LEN appropriately.
* g10/trustdb.h (get_validity): Add arguments sig and may_ask. Update
callers.
(tdb_get_validity_core): Add arguments sig and may_ask. Update
callers.
* g10/trust.c (get_validity) Add arguments sig and may_ask. Pass them
to tdb_get_validity_core.
* g10/trustdb.c: Include "tofu.h".
(trust_model_string): Handle TM_TOFU and TM_TOFU_PGP.
(tdb_get_validity_core): Add arguments sig and may_ask. If
OPT.TRUST_MODEL is TM_TOFU or TM_TOFU_PGP, compute the TOFU trust
level. Combine it with the computed PGP trust level, if appropriate.
* g10/keyedit.c: Include "tofu.h".
(show_key_with_all_names_colon): If the trust mode is tofu or
tofu+pgp, then show the trust policy.
* g10/keylist.c: Include "tofu.h".
(public_key_list): Also show the PGP stats if the trust model is
TM_TOFU_PGP.
(list_keyblock_colon): If the trust mode is tofu or
tofu+pgp, then show the trust policy.
* g10/pkclist.c: Include "tofu.h".
* g10/gpgv.c (get_validity): Add arguments sig and may_ask.
(enum tofu_policy): Define.
(tofu_get_policy): New stub.
(tofu_policy_str): Likewise.
* g10/test-stubs.c (get_validity): Add arguments sig and may_ask.
(enum tofu_policy): Define.
(tofu_get_policy): New stub.
(tofu_policy_str): Likewise.
* doc/DETAILS: Describe the TOFU Policy field.
* doc/gpg.texi: Document --tofu-set-policy, --trust-model=tofu,
--trust-model=tofu+pgp, --tofu-default-policy and --tofu-db-format.
* tests/openpgp/Makefile.am (TESTS): Add tofu.test.
(TEST_FILES): Add tofu-keys.asc, tofu-keys-secret.asc,
tofu-2183839A-1.txt, tofu-BC15C85A-1.txt and tofu-EE37CF96-1.txt.
(CLEANFILES): Add tofu.db.
(clean-local): Add tofu.d.
* tests/openpgp/tofu.test: New file.
* tests/openpgp/tofu-2183839A-1.txt: New file.
* tests/openpgp/tofu-BC15C85A-1.txt: New file.
* tests/openpgp/tofu-EE37CF96-1.txt: New file.
* tests/openpgp/tofu-keys.asc: New file.
* tests/openpgp/tofu-keys-secret.asc: New file.
--
Signed-off-by: Neal H. Walfield <neal@g10code.com>.
2015-10-18 18:44:05 +02:00
|
|
|
}
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc (':', es_stdout);
|
|
|
|
es_putc ('\n', es_stdout);
|
2010-01-09 20:00:46 +01:00
|
|
|
}
|
|
|
|
else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
|
|
|
{
|
|
|
|
u32 keyid2[2];
|
2010-10-13 17:57:08 +02:00
|
|
|
PKT_public_key *pk2;
|
|
|
|
|
|
|
|
pk2 = node->pkt->pkt.public_key;
|
|
|
|
xfree (hexgrip); hexgrip = NULL;
|
|
|
|
xfree (serialno); serialno = NULL;
|
2014-06-03 21:35:59 +02:00
|
|
|
if (secret || has_secret || opt.with_keygrip || opt.with_key_data)
|
2010-10-13 17:57:08 +02:00
|
|
|
{
|
|
|
|
rc = hexkeygrip_from_pk (pk2, &hexgrip);
|
|
|
|
if (rc)
|
|
|
|
log_error ("error computing a keygrip: %s\n",
|
|
|
|
gpg_strerror (rc));
|
|
|
|
}
|
|
|
|
stubkey = 0;
|
2014-06-03 21:35:59 +02:00
|
|
|
if ((secret||has_secret)
|
|
|
|
&& agent_get_keyinfo (NULL, hexgrip, &serialno))
|
2010-10-13 17:57:08 +02:00
|
|
|
stubkey = 1; /* Key not found. */
|
2010-01-09 20:00:46 +01:00
|
|
|
|
|
|
|
keyid_from_pk (pk2, keyid2);
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fputs (secret? "ssb:":"sub:", es_stdout);
|
2010-10-20 13:33:50 +02:00
|
|
|
if (!pk2->flags.valid)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('i', es_stdout);
|
2010-10-20 13:33:50 +02:00
|
|
|
else if (pk2->flags.revoked)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('r', es_stdout);
|
2010-01-09 20:00:46 +01:00
|
|
|
else if (pk2->has_expired)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('e', es_stdout);
|
2010-01-09 20:00:46 +01:00
|
|
|
else if (opt.fast_list_mode || opt.no_expensive_trust_checks)
|
|
|
|
;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* TRUSTLETTER should always be defined here. */
|
|
|
|
if (trustletter)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%c", trustletter);
|
2010-01-09 20:00:46 +01:00
|
|
|
}
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s:::::",
|
2010-01-09 20:00:46 +01:00
|
|
|
nbits_from_pk (pk2),
|
|
|
|
pk2->pubkey_algo,
|
|
|
|
(ulong) keyid2[0], (ulong) keyid2[1],
|
|
|
|
colon_datestr_from_pk (pk2), colon_strtime (pk2->expiredate)
|
|
|
|
/* fixme: add LID and ownertrust here */
|
|
|
|
);
|
2010-02-02 15:06:19 +01:00
|
|
|
print_capabilities (pk2, NULL);
|
2013-11-15 08:59:45 +01:00
|
|
|
es_putc (':', es_stdout); /* End of field 13. */
|
|
|
|
es_putc (':', es_stdout); /* End of field 14. */
|
2014-06-03 21:35:59 +02:00
|
|
|
if (secret || has_secret)
|
2010-02-02 15:06:19 +01:00
|
|
|
{
|
2010-10-13 17:57:08 +02:00
|
|
|
if (stubkey)
|
|
|
|
es_putc ('#', es_stdout);
|
|
|
|
else if (serialno)
|
|
|
|
es_fputs (serialno, es_stdout);
|
2014-06-03 21:35:59 +02:00
|
|
|
else if (has_secret)
|
|
|
|
es_putc ('+', es_stdout);
|
2010-02-02 15:06:19 +01:00
|
|
|
}
|
2013-11-15 08:59:45 +01:00
|
|
|
es_putc (':', es_stdout); /* End of field 15. */
|
|
|
|
es_putc (':', es_stdout); /* End of field 16. */
|
|
|
|
if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
|| pk->pubkey_algo == PUBKEY_ALGO_EDDSA
|
2013-11-15 08:59:45 +01:00
|
|
|
|| pk->pubkey_algo == PUBKEY_ALGO_ECDH)
|
|
|
|
{
|
|
|
|
char *curve = openpgp_oid_to_str (pk->pkey[0]);
|
2015-08-06 09:44:03 +02:00
|
|
|
const char *name = openpgp_oid_to_curve (curve, 0);
|
2015-07-08 08:05:06 +02:00
|
|
|
if (!name)
|
2013-11-15 08:59:45 +01:00
|
|
|
name = curve;
|
|
|
|
es_fputs (name, es_stdout);
|
|
|
|
xfree (curve);
|
|
|
|
}
|
|
|
|
es_putc (':', es_stdout); /* End of field 17. */
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc ('\n', es_stdout);
|
2010-01-09 20:00:46 +01:00
|
|
|
if (fpr > 1)
|
2014-03-27 12:59:55 +01:00
|
|
|
print_fingerprint (NULL, pk2, 0);
|
2010-10-08 13:11:08 +02:00
|
|
|
if (opt.with_key_data || opt.with_keygrip)
|
2010-04-20 19:57:50 +02:00
|
|
|
{
|
2010-10-13 17:57:08 +02:00
|
|
|
if (hexgrip)
|
|
|
|
es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
|
2010-10-08 13:11:08 +02:00
|
|
|
if (opt.with_key_data)
|
|
|
|
print_key_data (pk2);
|
2010-04-20 19:57:50 +02:00
|
|
|
}
|
2010-01-09 20:00:46 +01:00
|
|
|
}
|
|
|
|
else if (opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE)
|
|
|
|
{
|
|
|
|
PKT_signature *sig = node->pkt->pkt.signature;
|
|
|
|
int sigrc, fprokay = 0;
|
|
|
|
char *sigstr;
|
|
|
|
size_t fplen;
|
|
|
|
byte fparray[MAX_FINGERPRINT_LEN];
|
|
|
|
|
|
|
|
if (sig->sig_class == 0x20 || sig->sig_class == 0x28
|
|
|
|
|| sig->sig_class == 0x30)
|
|
|
|
sigstr = "rev";
|
|
|
|
else if ((sig->sig_class & ~3) == 0x10)
|
|
|
|
sigstr = "sig";
|
|
|
|
else if (sig->sig_class == 0x18)
|
|
|
|
sigstr = "sig";
|
|
|
|
else if (sig->sig_class == 0x1F)
|
|
|
|
sigstr = "sig";
|
|
|
|
else
|
|
|
|
{
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "sig::::::::::%02x%c:\n",
|
2010-01-09 20:00:46 +01:00
|
|
|
sig->sig_class, sig->flags.exportable ? 'x' : 'l');
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opt.check_sigs)
|
|
|
|
{
|
|
|
|
PKT_public_key *signer_pk = NULL;
|
|
|
|
|
|
|
|
fflush (stdout);
|
|
|
|
if (opt.no_sig_cache)
|
|
|
|
signer_pk = xmalloc_clear (sizeof (PKT_public_key));
|
|
|
|
|
|
|
|
rc = check_key_signature2 (keyblock, node, NULL, signer_pk,
|
|
|
|
NULL, NULL, NULL);
|
|
|
|
switch (gpg_err_code (rc))
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
sigrc = '!';
|
|
|
|
break;
|
|
|
|
case GPG_ERR_BAD_SIGNATURE:
|
|
|
|
sigrc = '-';
|
|
|
|
break;
|
|
|
|
case GPG_ERR_NO_PUBKEY:
|
|
|
|
case GPG_ERR_UNUSABLE_PUBKEY:
|
|
|
|
sigrc = '?';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sigrc = '%';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opt.no_sig_cache)
|
|
|
|
{
|
|
|
|
if (!rc)
|
|
|
|
{
|
|
|
|
fingerprint_from_pk (signer_pk, fparray, &fplen);
|
|
|
|
fprokay = 1;
|
|
|
|
}
|
|
|
|
free_public_key (signer_pk);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rc = 0;
|
|
|
|
sigrc = ' ';
|
|
|
|
}
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fputs (sigstr, es_stdout);
|
|
|
|
es_putc (':', es_stdout);
|
2010-01-09 20:00:46 +01:00
|
|
|
if (sigrc != ' ')
|
2010-03-15 12:15:45 +01:00
|
|
|
es_putc (sigrc, es_stdout);
|
|
|
|
es_fprintf (es_stdout, "::%d:%08lX%08lX:%s:%s:", sig->pubkey_algo,
|
2010-01-09 20:00:46 +01:00
|
|
|
(ulong) sig->keyid[0], (ulong) sig->keyid[1],
|
|
|
|
colon_datestr_from_sig (sig),
|
|
|
|
colon_expirestr_from_sig (sig));
|
|
|
|
|
|
|
|
if (sig->trust_depth || sig->trust_value)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%d %d", sig->trust_depth, sig->trust_value);
|
|
|
|
es_fprintf (es_stdout, ":");
|
2010-01-09 20:00:46 +01:00
|
|
|
|
|
|
|
if (sig->trust_regexp)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_write_sanitized (es_stdout, sig->trust_regexp,
|
|
|
|
strlen (sig->trust_regexp), ":", NULL);
|
|
|
|
es_fprintf (es_stdout, ":");
|
2010-01-09 20:00:46 +01:00
|
|
|
|
|
|
|
if (sigrc == '%')
|
2015-01-22 12:06:11 +01:00
|
|
|
es_fprintf (es_stdout, "[%s] ", gpg_strerror (rc));
|
2010-01-09 20:00:46 +01:00
|
|
|
else if (sigrc == '?')
|
|
|
|
;
|
|
|
|
else if (!opt.fast_list_mode)
|
|
|
|
{
|
|
|
|
size_t n;
|
2010-04-20 19:57:50 +02:00
|
|
|
p = get_user_id (sig->keyid, &n);
|
2010-03-15 12:15:45 +01:00
|
|
|
es_write_sanitized (es_stdout, p, n, ":", NULL);
|
2010-01-09 20:00:46 +01:00
|
|
|
xfree (p);
|
|
|
|
}
|
2012-05-24 10:13:39 +02:00
|
|
|
es_fprintf (es_stdout, ":%02x%c::", sig->sig_class,
|
2010-01-09 20:00:46 +01:00
|
|
|
sig->flags.exportable ? 'x' : 'l');
|
|
|
|
|
|
|
|
if (opt.no_sig_cache && opt.check_sigs && fprokay)
|
|
|
|
{
|
|
|
|
for (i = 0; i < fplen; i++)
|
2010-03-15 12:15:45 +01:00
|
|
|
es_fprintf (es_stdout, "%02X", fparray[i]);
|
2010-01-09 20:00:46 +01:00
|
|
|
}
|
|
|
|
|
2012-05-24 10:13:39 +02:00
|
|
|
es_fprintf (es_stdout, ":::%d:\n", sig->digest_algo);
|
2010-01-09 20:00:46 +01:00
|
|
|
|
|
|
|
if (opt.show_subpackets)
|
|
|
|
print_subpackets_colon (sig);
|
|
|
|
|
|
|
|
/* fixme: check or list other sigs here */
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2010-10-13 17:57:08 +02:00
|
|
|
|
|
|
|
xfree (hexgrip);
|
|
|
|
xfree (serialno);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reorder the keyblock so that the primary user ID (and not attribute
|
|
|
|
* packet) comes first. Fixme: Replace this by a generic sort
|
|
|
|
* function. */
|
2006-04-19 13:26:11 +02:00
|
|
|
static void
|
2010-01-09 20:00:46 +01:00
|
|
|
do_reorder_keyblock (KBNODE keyblock, int attr)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
KBNODE primary = NULL, primary0 = NULL, primary2 = NULL;
|
|
|
|
KBNODE last, node;
|
|
|
|
|
|
|
|
for (node = keyblock; node; primary0 = node, node = node->next)
|
|
|
|
{
|
|
|
|
if (node->pkt->pkttype == PKT_USER_ID &&
|
|
|
|
((attr && node->pkt->pkt.user_id->attrib_data) ||
|
|
|
|
(!attr && !node->pkt->pkt.user_id->attrib_data)) &&
|
|
|
|
node->pkt->pkt.user_id->is_primary)
|
|
|
|
{
|
|
|
|
primary = primary2 = node;
|
|
|
|
for (node = node->next; node; primary2 = node, node = node->next)
|
|
|
|
{
|
|
|
|
if (node->pkt->pkttype == PKT_USER_ID
|
|
|
|
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|
|
|
|
|| node->pkt->pkttype == PKT_SECRET_SUBKEY)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2010-01-09 20:00:46 +01:00
|
|
|
if (!primary)
|
|
|
|
return; /* No primary key flag found (should not happen). */
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
for (last = NULL, node = keyblock; node; last = node, node = node->next)
|
|
|
|
{
|
|
|
|
if (node->pkt->pkttype == PKT_USER_ID)
|
|
|
|
break;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2010-01-09 20:00:46 +01:00
|
|
|
assert (node);
|
|
|
|
assert (last); /* The user ID is never the first packet. */
|
|
|
|
assert (primary0); /* Ditto (this is the node before primary). */
|
|
|
|
if (node == primary)
|
|
|
|
return; /* Already the first one. */
|
|
|
|
|
|
|
|
last->next = primary;
|
|
|
|
primary0->next = primary2->next;
|
|
|
|
primary2->next = node;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
void
|
|
|
|
reorder_keyblock (KBNODE keyblock)
|
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
do_reorder_keyblock (keyblock, 1);
|
|
|
|
do_reorder_keyblock (keyblock, 0);
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
|
2015-04-06 19:46:25 +02:00
|
|
|
static void
|
2015-10-08 14:55:07 +02:00
|
|
|
list_keyblock (ctrl_t ctrl,
|
|
|
|
KBNODE keyblock, int secret, int has_secret, int fpr,
|
2015-04-06 19:46:25 +02:00
|
|
|
struct keylist_context *listctx)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
reorder_keyblock (keyblock);
|
2015-10-08 15:04:45 +02:00
|
|
|
if (opt.print_pka_records || opt.print_dane_records)
|
2015-10-08 14:55:07 +02:00
|
|
|
list_keyblock_pka (ctrl, keyblock);
|
2015-02-24 19:31:59 +01:00
|
|
|
else if (opt.with_colons)
|
2014-06-03 21:35:59 +02:00
|
|
|
list_keyblock_colon (keyblock, secret, has_secret, fpr);
|
2010-01-09 20:00:46 +01:00
|
|
|
else
|
2015-04-06 19:46:25 +02:00
|
|
|
list_keyblock_print (keyblock, secret, fpr, listctx);
|
2014-11-12 12:41:20 +01:00
|
|
|
if (secret)
|
|
|
|
es_fflush (es_stdout);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 17:54:05 +01:00
|
|
|
|
2015-04-06 19:46:25 +02:00
|
|
|
/* Public function used by keygen to list a keyblock. */
|
|
|
|
void
|
2015-10-08 14:55:07 +02:00
|
|
|
list_keyblock_direct (ctrl_t ctrl,
|
|
|
|
kbnode_t keyblock, int secret, int has_secret, int fpr)
|
2015-04-06 19:46:25 +02:00
|
|
|
{
|
|
|
|
struct keylist_context listctx;
|
|
|
|
|
|
|
|
memset (&listctx, 0, sizeof (listctx));
|
2015-10-08 14:55:07 +02:00
|
|
|
list_keyblock (ctrl, keyblock, secret, has_secret, fpr, &listctx);
|
2015-04-06 19:46:25 +02:00
|
|
|
keylist_context_release (&listctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-02-23 17:54:05 +01:00
|
|
|
/* Print an hex digit in ICAO spelling. */
|
|
|
|
static void
|
|
|
|
print_icao_hexdigit (estream_t fp, int c)
|
|
|
|
{
|
|
|
|
static const char *list[16] = {
|
|
|
|
"Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven",
|
|
|
|
"Eight", "Niner", "Alfa", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot"
|
|
|
|
};
|
|
|
|
|
|
|
|
tty_fprintf (fp, "%s", list[c&15]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
/*
|
2010-04-23 13:36:59 +02:00
|
|
|
* Function to print the finperprint.
|
2003-06-05 09:14:21 +02:00
|
|
|
* mode 0: as used in key listings, opt.with_colons is honored
|
|
|
|
* 1: print using log_info ()
|
|
|
|
* 2: direct use of tty
|
|
|
|
* 3: direct use of tty but only primary key.
|
2015-08-06 18:00:12 +02:00
|
|
|
* 4: direct use of tty but only subkey.
|
2015-02-24 19:31:59 +01:00
|
|
|
* 10: Same as 0 but with_colons etc is ignored.
|
2010-04-23 13:36:59 +02:00
|
|
|
*
|
|
|
|
* Modes 1 and 2 will try and print both subkey and primary key
|
2014-03-27 12:59:55 +01:00
|
|
|
* fingerprints. A MODE with bit 7 set is used internally. If
|
|
|
|
* OVERRIDE_FP is not NULL that stream will be used in 0 instead
|
|
|
|
* of es_stdout or instead of the TTY in modes 2 and 3.
|
2003-06-05 09:14:21 +02:00
|
|
|
*/
|
|
|
|
void
|
2014-03-27 12:59:55 +01:00
|
|
|
print_fingerprint (estream_t override_fp, PKT_public_key *pk, int mode)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2015-11-14 09:13:02 +01:00
|
|
|
char hexfpr[2*MAX_FINGERPRINT_LEN+1];
|
|
|
|
char *p;
|
|
|
|
size_t i;
|
2010-03-15 12:15:45 +01:00
|
|
|
estream_t fp;
|
2010-01-09 20:00:46 +01:00
|
|
|
const char *text;
|
|
|
|
int primary = 0;
|
2015-02-24 19:31:59 +01:00
|
|
|
int with_colons = opt.with_colons;
|
|
|
|
int with_icao = opt.with_icao_spelling;
|
|
|
|
|
|
|
|
if (mode == 10)
|
|
|
|
{
|
|
|
|
mode = 0;
|
|
|
|
with_colons = 0;
|
|
|
|
with_icao = 0;
|
|
|
|
}
|
2010-01-09 20:00:46 +01:00
|
|
|
|
2010-04-23 13:36:59 +02:00
|
|
|
if (pk->main_keyid[0] == pk->keyid[0]
|
|
|
|
&& pk->main_keyid[1] == pk->keyid[1])
|
|
|
|
primary = 1;
|
2010-01-09 20:00:46 +01:00
|
|
|
|
|
|
|
/* Just to be safe */
|
2010-04-23 13:36:59 +02:00
|
|
|
if ((mode & 0x80) && !primary)
|
2010-01-09 20:00:46 +01:00
|
|
|
{
|
|
|
|
log_error ("primary key is not really primary!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mode &= ~0x80;
|
|
|
|
|
|
|
|
if (!primary && (mode == 1 || mode == 2))
|
|
|
|
{
|
2010-04-23 13:36:59 +02:00
|
|
|
PKT_public_key *primary_pk = xmalloc_clear (sizeof (*primary_pk));
|
|
|
|
get_pubkey (primary_pk, pk->main_keyid);
|
2014-03-27 12:59:55 +01:00
|
|
|
print_fingerprint (override_fp, primary_pk, (mode | 0x80));
|
2010-04-23 13:36:59 +02:00
|
|
|
free_public_key (primary_pk);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2010-01-09 20:00:46 +01:00
|
|
|
|
|
|
|
if (mode == 1)
|
|
|
|
{
|
|
|
|
fp = log_get_stream ();
|
|
|
|
if (primary)
|
|
|
|
text = _("Primary key fingerprint:");
|
|
|
|
else
|
|
|
|
text = _(" Subkey fingerprint:");
|
|
|
|
}
|
|
|
|
else if (mode == 2)
|
|
|
|
{
|
2014-03-27 12:59:55 +01:00
|
|
|
fp = override_fp; /* Use tty or given stream. */
|
2010-01-09 20:00:46 +01:00
|
|
|
if (primary)
|
2015-08-06 18:00:12 +02:00
|
|
|
/* TRANSLATORS: this should fit into 24 bytes so that the
|
2010-01-09 20:00:46 +01:00
|
|
|
* fingerprint data is properly aligned with the user ID */
|
|
|
|
text = _(" Primary key fingerprint:");
|
|
|
|
else
|
|
|
|
text = _(" Subkey fingerprint:");
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2010-01-09 20:00:46 +01:00
|
|
|
else if (mode == 3)
|
|
|
|
{
|
2014-03-27 12:59:55 +01:00
|
|
|
fp = override_fp; /* Use tty or given stream. */
|
2010-01-09 20:00:46 +01:00
|
|
|
text = _(" Key fingerprint =");
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2015-08-06 18:00:12 +02:00
|
|
|
else if (mode == 4)
|
|
|
|
{
|
|
|
|
fp = override_fp; /* Use tty or given stream. */
|
|
|
|
text = _(" Subkey fingerprint:");
|
|
|
|
}
|
2010-01-09 20:00:46 +01:00
|
|
|
else
|
|
|
|
{
|
2014-03-27 12:59:55 +01:00
|
|
|
fp = override_fp? override_fp : es_stdout;
|
2010-01-09 20:00:46 +01:00
|
|
|
text = _(" Key fingerprint =");
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2010-01-09 20:00:46 +01:00
|
|
|
|
2015-11-14 09:13:02 +01:00
|
|
|
hexfingerprint (pk, hexfpr, sizeof hexfpr);
|
2015-02-24 19:31:59 +01:00
|
|
|
if (with_colons && !mode)
|
2010-01-09 20:00:46 +01:00
|
|
|
{
|
2015-11-14 09:13:02 +01:00
|
|
|
es_fprintf (fp, "fpr:::::::::%s:", hexfpr);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2010-01-09 20:00:46 +01:00
|
|
|
else
|
|
|
|
{
|
2015-11-14 09:13:02 +01:00
|
|
|
char fmtfpr[MAX_FORMATTED_FINGERPRINT_LEN + 1];
|
|
|
|
format_hexfingerprint (hexfpr, fmtfpr, sizeof fmtfpr);
|
|
|
|
tty_fprintf (fp, "%s %s", text, fmtfpr);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2010-03-15 12:15:45 +01:00
|
|
|
tty_fprintf (fp, "\n");
|
2015-02-24 19:31:59 +01:00
|
|
|
if (!with_colons && with_icao)
|
2015-02-23 17:54:05 +01:00
|
|
|
{
|
2015-11-14 09:13:02 +01:00
|
|
|
;
|
2015-02-23 17:54:05 +01:00
|
|
|
tty_fprintf (fp, "%*s\"", (int)strlen(text)+1, "");
|
2015-11-14 09:13:02 +01:00
|
|
|
for (i = 0, p = hexfpr; *p; i++, p++)
|
2015-02-23 17:54:05 +01:00
|
|
|
{
|
|
|
|
if (!i)
|
|
|
|
;
|
2015-11-14 09:13:02 +01:00
|
|
|
else if (!(i%8))
|
2015-02-23 17:54:05 +01:00
|
|
|
tty_fprintf (fp, "\n%*s ", (int)strlen(text)+1, "");
|
2015-11-14 09:13:02 +01:00
|
|
|
else if (!(i%4))
|
2015-02-23 17:54:05 +01:00
|
|
|
tty_fprintf (fp, " ");
|
|
|
|
else
|
|
|
|
tty_fprintf (fp, " ");
|
2015-11-14 09:13:02 +01:00
|
|
|
print_icao_hexdigit (fp, xtoi_1 (p));
|
2015-02-23 17:54:05 +01:00
|
|
|
}
|
|
|
|
tty_fprintf (fp, "\"\n");
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
/* Print the serial number of an OpenPGP card if available. */
|
2003-09-30 19:34:38 +02:00
|
|
|
static void
|
2010-10-13 17:57:08 +02:00
|
|
|
print_card_serialno (const char *serialno)
|
2003-09-30 19:34:38 +02:00
|
|
|
{
|
2010-10-13 17:57:08 +02:00
|
|
|
if (!serialno)
|
|
|
|
return;
|
|
|
|
if (opt.with_colons)
|
|
|
|
return; /* Handled elsewhere. */
|
2010-09-06 21:57:42 +02:00
|
|
|
|
2010-10-13 17:57:08 +02:00
|
|
|
es_fputs (_(" Card serial no. ="), es_stdout);
|
|
|
|
es_putc (' ', es_stdout);
|
|
|
|
if (strlen (serialno) == 32 && !strncmp (serialno, "D27600012401", 12))
|
|
|
|
{
|
|
|
|
/* This is an OpenPGP card. Print the relevant part. */
|
|
|
|
/* Example: D2760001240101010001000003470000 */
|
|
|
|
/* xxxxyyyyyyyy */
|
|
|
|
es_fprintf (es_stdout, "%.*s %.*s", 4, serialno+16, 8, serialno+20);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
es_fputs (serialno, es_stdout);
|
|
|
|
es_putc ('\n', es_stdout);
|
2003-09-30 19:34:38 +02:00
|
|
|
}
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
|
2008-12-09 09:58:02 +01:00
|
|
|
void
|
|
|
|
set_attrib_fd (int fd)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
static int last_fd = -1;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-01-09 20:00:46 +01:00
|
|
|
if (fd != -1 && last_fd == fd)
|
2003-06-05 09:14:21 +02:00
|
|
|
return;
|
|
|
|
|
2010-03-15 12:15:45 +01:00
|
|
|
/* Fixme: Do we need to check for the log stream here? */
|
|
|
|
if (attrib_fp && attrib_fp != log_get_stream ())
|
|
|
|
es_fclose (attrib_fp);
|
2003-06-05 09:14:21 +02:00
|
|
|
attrib_fp = NULL;
|
2010-01-09 20:00:46 +01:00
|
|
|
if (fd == -1)
|
2003-06-05 09:14:21 +02:00
|
|
|
return;
|
|
|
|
|
2008-12-09 09:58:02 +01:00
|
|
|
#ifdef HAVE_DOSISH_SYSTEM
|
2008-12-09 13:03:04 +01:00
|
|
|
setmode (fd, O_BINARY);
|
2008-12-09 09:58:02 +01:00
|
|
|
#endif
|
2010-01-09 20:00:46 +01:00
|
|
|
if (fd == 1)
|
2010-03-15 12:15:45 +01:00
|
|
|
attrib_fp = es_stdout;
|
2010-01-09 20:00:46 +01:00
|
|
|
else if (fd == 2)
|
2010-03-15 12:15:45 +01:00
|
|
|
attrib_fp = es_stderr;
|
2003-06-05 09:14:21 +02:00
|
|
|
else
|
2010-03-15 12:15:45 +01:00
|
|
|
attrib_fp = es_fdopen (fd, "wb");
|
2010-01-09 20:00:46 +01:00
|
|
|
if (!attrib_fp)
|
2008-12-09 09:58:02 +01:00
|
|
|
{
|
2010-01-09 20:00:46 +01:00
|
|
|
log_fatal ("can't open fd %d for attribute output: %s\n",
|
|
|
|
fd, strerror (errno));
|
2008-12-09 09:58:02 +01:00
|
|
|
}
|
2010-01-09 20:00:46 +01:00
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
last_fd = fd;
|
|
|
|
}
|