aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS6
-rw-r--r--Makefile.am2
-rw-r--r--NEWS67
-rw-r--r--agent/call-pinentry.c32
-rw-r--r--agent/command-ssh.c27
-rw-r--r--agent/command.c7
-rw-r--r--agent/divert-scd.c48
-rw-r--r--agent/gpg-agent.c6
-rw-r--r--agent/keyformat.txt6
-rw-r--r--agent/learncard.c2
-rw-r--r--agent/protect.c2
-rw-r--r--artwork/README8
-rw-r--r--build-aux/speedo.mk20
-rw-r--r--build-aux/texinfo.tex4
-rw-r--r--common/argparse.c6
-rw-r--r--common/audit.h2
-rw-r--r--common/convert.c2
-rw-r--r--common/dotlock.c2
-rw-r--r--common/iobuf.c58
-rw-r--r--common/mbox-util.c71
-rw-r--r--common/mbox-util.h3
-rwxr-xr-xcommon/mkerrors2
-rwxr-xr-xcommon/mkerrtok2
-rw-r--r--common/openpgp-oid.c4
-rw-r--r--common/percent.c2
-rw-r--r--common/sexp-parse.h2
-rw-r--r--common/sexputil.c2
-rw-r--r--common/simple-pwquery.c3
-rw-r--r--common/ssh-utils.c2
-rw-r--r--common/stringhelp.c2
-rw-r--r--common/sysutils.c11
-rw-r--r--common/t-exechelp.c2
-rw-r--r--common/t-mbox-util.c238
-rw-r--r--configure.ac13
-rw-r--r--dirmngr/Makefile.am4
-rw-r--r--dirmngr/cdb.h2
-rw-r--r--dirmngr/cdblib.c6
-rw-r--r--dirmngr/crlcache.c8
-rw-r--r--dirmngr/dirmngr-status.h39
-rw-r--r--dirmngr/dirmngr.c13
-rw-r--r--dirmngr/dirmngr.h10
-rw-r--r--dirmngr/dirmngr_ldap.c4
-rw-r--r--dirmngr/dns-stuff.c101
-rw-r--r--dirmngr/dns-stuff.h14
-rw-r--r--dirmngr/dns.c4
-rw-r--r--dirmngr/domaininfo.c2
-rw-r--r--dirmngr/http-ntbtls.c2
-rw-r--r--dirmngr/http.c36
-rw-r--r--dirmngr/http.h6
-rw-r--r--dirmngr/ks-action.c2
-rw-r--r--dirmngr/ks-engine-finger.c2
-rw-r--r--dirmngr/ks-engine-hkp.c110
-rw-r--r--dirmngr/ks-engine-http.c2
-rw-r--r--dirmngr/ks-engine-ldap.c33
-rw-r--r--dirmngr/ldap.c2
-rw-r--r--dirmngr/misc.c4
-rw-r--r--dirmngr/ocsp.c35
-rw-r--r--dirmngr/server.c134
-rw-r--r--dirmngr/t-dns-stuff.c12
-rw-r--r--dirmngr/t-http.c4
-rw-r--r--dirmngr/t-support.c43
-rw-r--r--dirmngr/workqueue.c2
-rw-r--r--doc/DETAILS12
-rw-r--r--doc/HACKING6
-rw-r--r--doc/Notes6
-rw-r--r--doc/dirmngr.texi2
-rw-r--r--doc/faq.org2
-rw-r--r--doc/gpg.texi69
-rw-r--r--doc/tools.texi6
-rw-r--r--doc/wks.texi74
-rw-r--r--doc/yat2m.c6
-rw-r--r--g10/Makefile.am1
-rw-r--r--g10/armor.c643
-rw-r--r--g10/build-packet.c4
-rw-r--r--g10/call-agent.c41
-rw-r--r--g10/call-agent.h13
-rw-r--r--g10/call-dirmngr.c27
-rw-r--r--g10/card-util.c171
-rw-r--r--g10/cipher-aead.c2
-rw-r--r--g10/cpr.c2
-rw-r--r--g10/decrypt-data.c117
-rw-r--r--g10/encrypt.c4
-rw-r--r--g10/export.c52
-rw-r--r--g10/filter.h7
-rw-r--r--g10/getkey.c607
-rw-r--r--g10/gpg.c24
-rw-r--r--g10/gpgcompose.c17
-rw-r--r--g10/gpgv.c2
-rw-r--r--g10/import.c104
-rw-r--r--g10/key-clean.c614
-rw-r--r--g10/key-clean.h52
-rw-r--r--g10/keydb.h51
-rw-r--r--g10/keyedit.c1
-rw-r--r--g10/keygen.c8
-rw-r--r--g10/keylist.c4
-rw-r--r--g10/keyserver.c2
-rw-r--r--g10/mainproc.c231
-rw-r--r--g10/misc.c6
-rw-r--r--g10/options.h2
-rw-r--r--g10/packet.h18
-rw-r--r--g10/parse-packet.c82
-rw-r--r--g10/pkclist.c4
-rw-r--r--g10/pubkey-enc.c129
-rw-r--r--g10/seskey.c4
-rw-r--r--g10/sig-check.c36
-rw-r--r--g10/sign.c1664
-rw-r--r--g10/skclist.c265
-rw-r--r--g10/tdbio.c35
-rw-r--r--g10/test-stubs.c2
-rw-r--r--g10/tofu.c2
-rw-r--r--g10/trust.c388
-rw-r--r--g10/trustdb.c5
-rw-r--r--g10/trustdb.h41
-rw-r--r--g10/verify.c2
-rw-r--r--g13/call-syshelp.c2
-rw-r--r--g13/mountinfo.c2
-rw-r--r--g13/runner.c2
-rw-r--r--kbx/keybox-blob.c2
-rw-r--r--kbx/keybox-errors.c2
-rw-r--r--kbx/keybox-search-desc.h2
-rw-r--r--kbx/keybox-search.c2
-rwxr-xr-xkbx/mkerrors2
-rw-r--r--m4/Makefile.am2
-rw-r--r--m4/gpg-error.m495
-rw-r--r--m4/ksba.m470
-rw-r--r--m4/libassuan.m4138
-rw-r--r--m4/libgcrypt.m452
-rw-r--r--m4/npth.m457
-rw-r--r--m4/ntbtls.m470
-rw-r--r--m4/tar-ustar.m443
-rw-r--r--po/Makevars58
-rw-r--r--po/POTFILES.in1
-rw-r--r--scd/apdu.c42
-rw-r--r--scd/apdu.h1
-rw-r--r--scd/app-dinsig.c2
-rw-r--r--scd/app-geldkarte.c2
-rw-r--r--scd/app-openpgp.c28
-rw-r--r--scd/app.c2
-rw-r--r--scd/ccid-driver.c42
-rw-r--r--scd/ccid-driver.h6
-rw-r--r--scd/command.c28
-rw-r--r--scd/iso7816.c4
-rw-r--r--scd/scdaemon.c2
-rw-r--r--scd/scdaemon.h1
-rw-r--r--sm/call-dirmngr.c2
-rw-r--r--sm/certchain.c10
-rw-r--r--sm/certlist.c4
-rw-r--r--sm/certreqgen-ui.c2
-rw-r--r--sm/gpgsm.c4
-rw-r--r--sm/gpgsm.h2
-rw-r--r--sm/keydb.c2
-rw-r--r--sm/minip12.c6
-rw-r--r--sm/qualified.c2
-rw-r--r--tests/asschk.c10
-rw-r--r--tests/gpgscm/scheme.c29
-rw-r--r--tools/Makefile.am5
-rw-r--r--tools/gpg-check-pattern.c2
-rw-r--r--tools/gpg-connect-agent.c6
-rw-r--r--tools/gpg-wks-client.c262
-rw-r--r--tools/gpg-wks-server.c33
-rw-r--r--tools/gpg-wks.h1
-rw-r--r--tools/gpg-zip.in148
-rw-r--r--tools/gpgconf.c2
-rw-r--r--tools/gpgtar.h2
-rw-r--r--tools/mime-maker.c47
-rw-r--r--tools/mime-parser.c2
-rw-r--r--tools/no-libgcrypt.c2
-rw-r--r--tools/rfc822parse.c113
-rw-r--r--tools/rfc822parse.h2
-rw-r--r--tools/wks-util.c6
170 files changed, 5004 insertions, 3435 deletions
diff --git a/AUTHORS b/AUTHORS
index f43208af9..d5d781438 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -193,6 +193,9 @@ Ineiev <[email protected]>
James Bottomley <[email protected]>
2018-02-01:[email protected]:
+Jiri Kerestes <[email protected]>
+2018-07-25:<[email protected]>:
+
Jonas Borgström <[email protected]>
2013-08-29:[email protected]:
@@ -205,6 +208,9 @@ Jussi Kivilinna <[email protected]>
Kyle Butt <[email protected]>
2013-05-29:CAAODAYLbCtqOG6msLLL0UTdASKWT6u2ptxsgUQ1JpusBESBoNQ@mail.gmail.com:
+Michael Haubenwallner <[email protected]>
+2018-07-13:[email protected]:
+
Phil Pennock <[email protected]>
Phil Pennock <[email protected]>
2017-01-19:[email protected]:
diff --git a/Makefile.am b/Makefile.am
index 680fe1be1..b59e9e3ec 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -189,7 +189,7 @@ release:
$(MAKE) -f $(RELEASE_NAME)/build-aux/speedo.mk w32-release ;\
echo "/* Build finished at $$(date -uIseconds) */" ;\
echo "/*" ;\
- echo " * Please run the final step interactivly:" ;\
+ echo " * Please run the final step interactively:" ;\
echo " * make sign-release" ;\
echo " */" ;\
) 2>&1 | tee "$(RELEASE_NAME).buildlog"
diff --git a/NEWS b/NEWS
index 232d8beef..245cc7044 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,46 @@
Noteworthy changes in version 2.3.0 (unreleased)
------------------------------------------------
+ Changes also found in 2.2.9:
+
+ * dirmngr: Fix recursive resolver mode and other bugs in the libdns
+ code. [#3374,#3803,#3610]
+
+ * dirmngr: When using libgpg-error 1.32 or later a GnuPG build with
+ NTBTLS support (e.g. the standard Windows installer) does not
+ anymore block for dozens of seconds before returning data.
+
+ * gpg: Fix bug in --show-keys which actually imported revocation
+ certificates. [#4017]
+
+ * gpg: Ignore too long user-ID and comment packets. [#4022]
+
+ * gpg: Fix crash due to bad German translation. Improved printf
+ format compile time check.
+
+ * gpg: Handle missing ISSUER sub packet gracefully in the presence of
+ the new ISSUER_FPR. [#4046]
+
+ * gpg: Allow decryption using several passphrases in most cases.
+ [#3795,#4050]
+
+ * gpg: Command --show-keys now enables the list options
+ show-unusable-uids, show-unusable-subkeys, show-notations and
+ show-policy-urls by default.
+
+ * gpg: Command --show-keys now prints revocation certificates. [#4018]
+
+ * gpg: Add revocation reason to the "rev" and "rvs" records of the
+ option --with-colons. [#1173]
+
+ * gpg: Export option export-clean does now remove certain expired
+ subkeys; export-minimal removes all expired subkeys. [#3622]
+
+ * gpg: New "usage" property for the drop-subkey filters. [#4019]
+
+ Release-info: https://dev.gnupg.org/T4036
+ See-also: gnupg-announce/2018q3/000427.html
+
Changes also found in 2.2.8:
* gpg: Decryption of messages not using the MDC mode will now lead
@@ -58,7 +98,7 @@ Noteworthy changes in version 2.3.0 (unreleased)
* dirmngr: Fallback to CRL if no default OCSP responder is configured.
* dirmngr: Implement CRL fetching via https. Here a redirection to
- http is explictly allowed.
+ http is explicitly allowed.
* dirmngr: Make LDAP searching and CRL fetching work under Windows.
This stopped working with 2.1. [#3937]
@@ -285,6 +325,7 @@ Noteworthy changes in version 2.3.0 (unreleased)
Version 2.2.6 (2018-04-09)
Version 2.2.7 (2018-05-02)
Version 2.2.8 (2018-06-08)
+ Version 2.2.9 (2018-07-12)
Noteworthy changes in version 2.2.0 (2017-08-28)
@@ -918,7 +959,7 @@ Noteworthy changes in version 2.1.11 (2016-01-26)
* gpg: Emit PROGRESS status lines during key generation.
- * gpg: Don't check for ambigious or non-matching key specification in
+ * gpg: Don't check for ambiguous or non-matching key specification in
the config file or given to --encrypt-to. This feature will return
in 2.3.x.
@@ -945,7 +986,7 @@ Noteworthy changes in version 2.1.11 (2016-01-26)
* dirmmgr: All configured keyservers are now searched.
* dirmngr: Install CA certificate for hkps.pool.sks-keyservers.net.
- Use this certiticate even if --hkp-cacert is not used.
+ Use this certificate even if --hkp-cacert is not used.
* gpgtar: Add actual encryption code. gpgtar does now fully replace
gpg-zip.
@@ -979,7 +1020,7 @@ Noteworthy changes in version 2.1.10 (2015-12-04)
* gpg: New option --only-sign-text-ids to exclude photo IDs from key
signing.
- * gpg: Check for ambigious or non-matching key specification in the
+ * gpg: Check for ambiguous or non-matching key specification in the
config file or given to --encrypt-to.
* gpg: Show the used card reader with --card-status.
@@ -1269,7 +1310,7 @@ Noteworthy changes in version 2.1.1 (2014-12-16)
* gpg: Fixed regression in --refresh-keys.
- * gpg: Fixed regresion in %g and %p codes for --sig-notation.
+ * gpg: Fixed regression in %g and %p codes for --sig-notation.
* gpg: Fixed best matching hash algo detection for ECDSA and EdDSA.
@@ -1349,7 +1390,7 @@ Noteworthy changes in version 2.1.0 (2014-11-06)
* gpg: Default keyring is now created with a .kbx suffix.
- * gpg: Add a shortcut to the key capabilies menu (e.g. "=e" sets the
+ * gpg: Add a shortcut to the key capabilities menu (e.g. "=e" sets the
encryption capabilities).
* gpg: Fixed obsolete options parsing.
@@ -1541,7 +1582,7 @@ Noteworthy changes in version 2.1.0 (2014-11-06)
* scdaemon: Does not anymore block after changing a card (regression
fix).
- * tools: gpg-connect-agent does now proberly display the help output
+ * tools: gpg-connect-agent does now properly display the help output
for "SCD HELP" commands.
@@ -1666,7 +1707,7 @@ Noteworthy changes in version 2.0.13 (2009-09-04)
* Add hack to the internal CCID driver to allow the use of some
Omnikey based card readers with 2048 bit keys.
- * GPG now repeatly asks the user to insert the requested OpenPGP
+ * GPG now repeatedly asks the user to insert the requested OpenPGP
card. This can be disabled with --limit-card-insert-tries=1.
* Minor bug fixes.
@@ -1792,7 +1833,7 @@ Noteworthy changes in version 2.0.9 (2008-03-26)
* Extended the PKITS framework.
- * Fixed a bug in the ambigious name detection.
+ * Fixed a bug in the ambiguous name detection.
* Fixed possible memory corruption while importing OpenPGP keys (bug
introduced with 2.0.8). [CVE-2008-1530]
@@ -2342,7 +2383,7 @@ Noteworthy changes in version 1.9.2 (2003-11-17)
command but from the menu provided by the new --card-edit command.
* PINs are now properly cached and there are only 2 PINs visible.
- The 3rd PIN (CHV2) is internally syncronized with the regular PIN.
+ The 3rd PIN (CHV2) is internally synchronized with the regular PIN.
* All kind of other internal stuff.
@@ -3046,7 +3087,7 @@ Noteworthy changes in version 1.0.1 (1999-12-16)
* Fixed some minor bugs and the problem with conventional encrypted
packets which did use the gpg v3 partial length headers.
- * Add Indonesian and Portugese translations.
+ * Add Indonesian and Portuguese translations.
* Fixed a bug with symmetric-only encryption using the non-default 3DES.
The option --emulate-3des-s2k-bug may be used to decrypt documents
@@ -3149,7 +3190,7 @@ Noteworthy changes in version 0.9.8 (1999-06-26)
* New option --with-key-data to list the public key parameters.
New option -N to insert notations and a --set-policy-url.
- A couple of other options to allow reseting of options.
+ A couple of other options to allow resetting of options.
* Better support for HPUX.
@@ -3628,7 +3669,7 @@ Noteworthy changes in version 0.2.19 (1998-05-29)
Noteworthy changes in version 0.2.18 (1998-05-15)
------------------------------------
- * Splitted cipher/random.c, add new option "--disable-dev-random"
+ * Split cipher/random.c, add new option "--disable-dev-random"
to configure to support the development of a random source for
other systems. Prepared sourcefiles rand-unix.c, rand-w32.c
and rand-dummy.c (which is used to allow compilation on systems
diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c
index af4eb06f2..38c01e26f 100644
--- a/agent/call-pinentry.c
+++ b/agent/call-pinentry.c
@@ -98,11 +98,15 @@ void
initialize_module_call_pinentry (void)
{
static int initialized;
+ int err;
if (!initialized)
{
- if (npth_mutex_init (&entry_lock, NULL))
- initialized = 1;
+ err = npth_mutex_init (&entry_lock, NULL);
+ if (err)
+ log_fatal ("error initializing mutex: %s\n", strerror (err));
+
+ initialized = 1;
}
}
@@ -497,14 +501,16 @@ start_pinentry (ctrl_t ctrl)
{
/* Provide a few default strings for use by the pinentries. This
- may help a pinentry to avoid implementing localization code. */
+ * may help a pinentry to avoid implementing localization code.
+ * Note that gpg-agent has been set to utf-8 so that the strings
+ * are in the expected encoding. */
static const struct { const char *key, *value; int what; } tbl[] = {
- /* TRANSLATORS: These are labels for buttons etc used in
- Pinentries. An underscore indicates that the next letter
- should be used as an accelerator. Double the underscore for
- a literal one. The actual to be translated text starts after
- the second vertical bar. Note that gpg-agent has been set to
- utf-8 so that the strings are in the expected encoding. */
+ /* TRANSLATORS: These are labels for buttons etc as used in
+ * Pinentries. In your translation copy the text before the
+ * second vertical bar verbatim; translate only the following
+ * text. An underscore indicates that the next letter should be
+ * used as an accelerator. Double the underscore to have
+ * pinentry display a literal underscore. */
{ "ok", N_("|pinentry-label|_OK") },
{ "cancel", N_("|pinentry-label|_Cancel") },
{ "yes", N_("|pinentry-label|_Yes") },
@@ -1537,14 +1543,6 @@ agent_popup_message_stop (ctrl_t ctrl)
TerminateProcess (process, 1);
}
#else
- else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
- { /* The daemon already died. No need to send a kill. However
- because we already waited for the process, we need to tell
- assuan that it should not wait again (done by
- unlock_pinentry). */
- if (rc == pid)
- assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
- }
else if (pid > 0)
kill (pid, SIGINT);
#endif
diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index df63ed713..8a4150539 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -2751,7 +2751,7 @@ data_hash (unsigned char *data, size_t data_n,
allow the use of signature algorithms that implement the hashing
internally (e.g. Ed25519). On success the created signature is
stored in ssh format at R_SIG and it's size at R_SIGLEN; the caller
- must use es_free to releaase this memory. */
+ must use es_free to release this memory. */
static gpg_error_t
data_sign (ctrl_t ctrl, ssh_key_type_spec_t *spec,
const void *hash, size_t hashlen,
@@ -3249,9 +3249,10 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response)
while (1)
{
err = stream_read_byte (request, &b);
- if (gpg_err_code (err) == GPG_ERR_EOF)
- {
- err = 0;
+ if (err)
+ {
+ if (gpg_err_code (err) == GPG_ERR_EOF)
+ err = 0;
break;
}
@@ -3625,7 +3626,7 @@ static void
get_client_info (int fd, struct peer_info_s *out)
{
pid_t client_pid = (pid_t)(-1);
- uid_t client_uid = (uid_t)-1;
+ int client_uid = -1;
#ifdef SO_PEERCRED
{
@@ -3640,10 +3641,10 @@ get_client_info (int fd, struct peer_info_s *out)
{
#if defined (HAVE_STRUCT_SOCKPEERCRED_PID) || defined (HAVE_STRUCT_UCRED_PID)
client_pid = cr.pid;
- client_uid = cr.uid;
+ client_uid = (int)cr.uid;
#elif defined (HAVE_STRUCT_UCRED_CR_PID)
client_pid = cr.cr_pid;
- client_pid = cr.cr_uid;
+ client_uid = (int)cr.cr_uid;
#else
#error "Unknown SO_PEERCRED struct"
#endif
@@ -3660,7 +3661,7 @@ get_client_info (int fd, struct peer_info_s *out)
len = sizeof (struct xucred);
if (!getsockopt (fd, SOL_LOCAL, LOCAL_PEERCRED, &cr, &len))
- client_uid = cr.cr_uid;
+ client_uid = (int)cr.cr_uid;
}
#endif
}
@@ -3670,8 +3671,10 @@ get_client_info (int fd, struct peer_info_s *out)
socklen_t unpl = sizeof unp;
if (getsockopt (fd, 0, LOCAL_PEEREID, &unp, &unpl) != -1)
- client_pid = unp.unp_pid;
- client_uid = unp.unp_euid;
+ {
+ client_pid = unp.unp_pid;
+ client_uid = (int)unp.unp_euid;
+ }
}
#elif defined (HAVE_GETPEERUCRED)
{
@@ -3680,7 +3683,7 @@ get_client_info (int fd, struct peer_info_s *out)
if (getpeerucred (fd, &ucred) != -1)
{
client_pid = ucred_getpid (ucred);
- client_uid = ucred_geteuid (ucred);
+ client_uid = (int)ucred_geteuid (ucred);
ucred_free (ucred);
}
}
@@ -3689,7 +3692,7 @@ get_client_info (int fd, struct peer_info_s *out)
#endif
out->pid = (client_pid == (pid_t)(-1)? 0 : (unsigned long)client_pid);
- out->uid = (int)client_uid;
+ out->uid = client_uid;
}
diff --git a/agent/command.c b/agent/command.c
index 925d1f780..7fbf1de1c 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -887,7 +887,7 @@ cmd_genkey (assuan_context_t ctx, char *line)
ctrl_t ctrl = assuan_get_pointer (ctx);
int rc;
int no_protection;
- unsigned char *value;
+ unsigned char *value = NULL;
size_t valuelen;
unsigned char *newpasswd = NULL;
membuf_t outbuf;
@@ -3588,8 +3588,13 @@ start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd)
}
else
{
+#ifdef HAVE_W32_SYSTEM
+ pid = assuan_get_pid (ctx);
+ ctrl->client_uid = -1;
+#else
pid = client_creds->pid;
ctrl->client_uid = client_creds->uid;
+#endif
}
ctrl->client_pid = (pid == ASSUAN_INVALID_PID)? 0 : (unsigned long)pid;
ctrl->server_local->connect_from_self = (pid == getpid ());
diff --git a/agent/divert-scd.c b/agent/divert-scd.c
index b85b490c1..b9781547d 100644
--- a/agent/divert-scd.c
+++ b/agent/divert-scd.c
@@ -195,7 +195,7 @@ has_percent0A_suffix (const char *string)
string with the passphrase, the buffer may optionally be padded
with arbitrary characters.
- If DESC_TEXT is not NULL it can be used as further informtion shown
+ If DESC_TEXT is not NULL it can be used as further information shown
atop of the INFO message.
INFO gets displayed as part of a generic string. However if the
@@ -278,25 +278,47 @@ getpin_cb (void *opaque, const char *desc_text, const char *info,
{
if (info)
{
- char *desc, *desc2;
+ char *desc;
+ const char *desc2;
- if ( asprintf (&desc,
- L_("%s%%0A%%0AUse the reader's pinpad for input."),
- info) < 0 )
- rc = gpg_error_from_syserror ();
+ if (!strcmp (info, "--ack"))
+ {
+ desc2 = L_("Push ACK button on card/token.");
+
+ if (desc_text)
+ {
+ desc = strconcat (desc_text,
+ has_percent0A_suffix (desc_text)
+ ? "%0A" : "%0A%0A",
+ desc2, NULL);
+ desc2 = NULL;
+ }
+ else
+ desc = NULL;
+ }
else
{
- /* Prepend DESC_TEXT to INFO. */
+ desc2 = NULL;
+
if (desc_text)
- desc2 = strconcat (desc_text,
- has_percent0A_suffix (desc_text)
- ? "%0A" : "%0A%0A",
- desc, NULL);
+ desc = strconcat (desc_text,
+ has_percent0A_suffix (desc_text)
+ ? "%0A" : "%0A%0A",
+ info, "%0A%0A",
+ L_("Use the reader's pinpad for input."),
+ NULL);
else
- desc2 = NULL;
+ desc = strconcat (info, "%0A%0A",
+ L_("Use the reader's pinpad for input."),
+ NULL);
+ }
+
+ if (!desc2 && !desc)
+ rc = gpg_error_from_syserror ();
+ else
+ {
rc = agent_popup_message_start (ctrl,
desc2? desc2:desc, NULL);
- xfree (desc2);
xfree (desc);
}
}
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 1fdc94d0f..911064cdc 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -851,7 +851,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
case oLogFile:
if (!reread)
- return 0; /* not handeld */
+ return 0; /* not handled */
if (!current_logfile || !pargs->r.ret_str
|| strcmp (current_logfile, pargs->r.ret_str))
{
@@ -1768,7 +1768,7 @@ main (int argc, char **argv )
/* Unless we are running with a program given on the command
* line we can assume that the inotify things works and thus
- * we can avoid tye regular stat calls. */
+ * we can avoid the regular stat calls. */
if (!argc)
reliable_homedir_inotify = 1;
}
@@ -2108,7 +2108,7 @@ get_agent_scd_notify_event (void)
GetCurrentProcess(), &h2,
EVENT_MODIFY_STATE|SYNCHRONIZE, TRUE, 0))
{
- log_error ("setting syncronize for scd notify event failed: %s\n",
+ log_error ("setting synchronize for scd notify event failed: %s\n",
w32_strerror (-1) );
CloseHandle (h);
}
diff --git a/agent/keyformat.txt b/agent/keyformat.txt
index 2e48b346e..c7426db9d 100644
--- a/agent/keyformat.txt
+++ b/agent/keyformat.txt
@@ -234,7 +234,7 @@ The currently defined protection modes are:
(csum n)
(protection PROTTYPE PROTALGO IV S2KMODE S2KHASH S2KSALT S2KCOUNT)))
- Note that the public key paramaters in SKEY are duplicated and
+ Note that the public key parameters in SKEY are duplicated and
should be identical to their copies in the standard parameter
elements. Here is an example of an entire protected private key
using this format:
@@ -359,8 +359,8 @@ KEY_1 to KEY_N are unique identifiers for the shared secret, for
example an URI. In case this information should be kept confidential
as well, they may not appear in the unprotected part; however they are
mandatory in the encrypted_octet_string. The list of keywords is
-optional. The oder of the "key" lists and the order of the "value"
-lists mut match, that is the first "key"-list is associated with the
+optional. The order of the "key" lists and the order of the "value"
+lists must match, that is the first "key"-list is associated with the
first "value" list in the encrypted_octet_string.
The protection mode etc. is identical to the protection mode as
diff --git a/agent/learncard.c b/agent/learncard.c
index abe1dd0bf..f3219ed8f 100644
--- a/agent/learncard.c
+++ b/agent/learncard.c
@@ -40,7 +40,7 @@ struct keypair_info_s
char hexgrip[1]; /* The keygrip (i.e. a hash over the public key
parameters) formatted as a hex string.
Allocated somewhat large to also act as
- memeory for the above ID field. */
+ memory for the above ID field. */
};
typedef struct keypair_info_s *KEYPAIR_INFO;
diff --git a/agent/protect.c b/agent/protect.c
index 16ae715e1..c7bd30b68 100644
--- a/agent/protect.c
+++ b/agent/protect.c
@@ -1109,7 +1109,7 @@ agent_unprotect (ctrl_t ctrl,
if (!protect_info[infidx].algo)
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
- /* See wether we have a protected-at timestamp. */
+ /* See whether we have a protected-at timestamp. */
protect_list = s; /* Save for later. */
if (protected_at)
{
diff --git a/artwork/README b/artwork/README
index 13b8653ec..068bdea1d 100644
--- a/artwork/README
+++ b/artwork/README
@@ -14,3 +14,11 @@ gnupg-logo-new.ai
gnupg-favicon-1.ico Icons for the website (rectangular)
gnupg-favicon-2.ico (round)
+
+The above GnuPG logos are Copyright (c) 2006 g10 Code GmbH, and are
+released under the terms of the GNU General Public License, version 3
+or any later version, or, at your option, of the Creative Commons
+Attribution-ShareAlike 4.0 International License.
+
+We would appreciate that you make a logo image a link to
+https://gnupg.org/ if you use it on a web page.
diff --git a/build-aux/speedo.mk b/build-aux/speedo.mk
index d9b4a7515..d0f97f3db 100644
--- a/build-aux/speedo.mk
+++ b/build-aux/speedo.mk
@@ -157,8 +157,9 @@ INST_NAME=gnupg-w32
# Use this to override the installaion directory for native builds.
INSTALL_PREFIX=none
-# The Authenticode key used to sign the Windows installer
+# The Authenticode key and cert chain used to sign the Windows installer
AUTHENTICODE_KEY=${HOME}/.gnupg/g10code-authenticode-key.p12
+AUTHENTICODE_CERTS=${HOME}/.gnupg/g10code-authenticode-certs.pem
# Directory names.
@@ -520,12 +521,12 @@ endif
# The LDFLAGS is needed for -lintl for glib.
ifeq ($(WITH_GUI),1)
speedo_pkg_gpgme_configure = \
- --enable-static --enable-w32-glib --disable-w32-qt \
+ --enable-static --enable-w32-glib \
--with-gpg-error-prefix=$(idir) \
LDFLAGS=-L$(idir)/lib
else
speedo_pkg_gpgme_configure = \
- --disable-static --disable-w32-glib --disable-w32-qt \
+ --disable-static --disable-w32-glib \
--with-gpg-error-prefix=$(idir) \
LDFLAGS=-L$(idir)/lib
endif
@@ -970,7 +971,7 @@ else
endif
@touch $(stampdir)/stamp-$(1)-01-configure
-# Note that unpack has no 64 bit version becuase it is just the source.
+# Note that unpack has no 64 bit version because it is just the source.
# Fixme: We should use templates to create the standard and w64
# version of these rules.
$(stampdir)/stamp-w64-$(1)-01-configure: $(stampdir)/stamp-$(1)-00-unpack
@@ -1142,7 +1143,7 @@ all-speedo: $(stampdir)/stamp-final
report-speedo: $(addprefix report-,$(speedo_build_list))
-# Just to check if we catched all stamps.
+# Just to check if we caught all stamps.
clean-stamps:
$(RM) -fR $(stampdir)
@@ -1266,8 +1267,11 @@ sign-installer:
echo "speedo: * Signing installer" ;\
echo "speedo: * Key: $(AUTHENTICODE_KEY)";\
echo "speedo: */" ;\
- osslsigncode sign -pkcs12 $(AUTHENTICODE_KEY) -askpass \
- -h sha256 -in "PLAY/inst/$$exefile" -out "../../$$exefile" ;\
+ osslsigncode sign -certs $(AUTHENTICODE_CERTS)\
+ -pkcs12 $(AUTHENTICODE_KEY) -askpass \
+ -ts "http://timestamp.globalsign.com/scripts/timstamp.dll" \
+ -h sha256 -n GnuPG -i https://gnupg.org \
+ -in "PLAY/inst/$$exefile" -out "../../$$exefile" ;\
exefile="../../$$exefile" ;\
$(call MKSWDB_commands,$${exefile},$${reldate}); \
echo "speedo: /*" ;\
@@ -1283,7 +1287,7 @@ endif
#
-# Check availibility of standard tools
+# Check availability of standard tools
#
check-tools:
diff --git a/build-aux/texinfo.tex b/build-aux/texinfo.tex
index 5a17f9793..9e1184868 100644
--- a/build-aux/texinfo.tex
+++ b/build-aux/texinfo.tex
@@ -3,7 +3,7 @@
% Load plain if necessary, i.e., if running under initex.
\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
%
-\def\texinfoversion{2007-05-03.09}
+\def\texinfoversion{2018-10-25.16}
%
% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
@@ -4598,7 +4598,7 @@ end
\chardef\maxseclevel = 3
%
% A numbered section within an unnumbered changes to unnumbered too.
-% To achive this, remember the "biggest" unnum. sec. we are currently in:
+% To achieve this, remember the "biggest" unnum. sec. we are currently in:
\chardef\unmlevel = \maxseclevel
%
% Trace whether the current chapter is an appendix or not:
diff --git a/common/argparse.c b/common/argparse.c
index 331998bb2..db0b7e079 100644
--- a/common/argparse.c
+++ b/common/argparse.c
@@ -408,7 +408,7 @@ static void
store_alias( ARGPARSE_ARGS *arg, char *name, char *value )
{
/* TODO: replace this dummy function with a rea one
- * and fix the probelms IRIX has with (ALIAS_DEV)arg..
+ * and fix the problems IRIX has with (ALIAS_DEV)arg..
* used as lvalue
*/
(void)arg;
@@ -439,7 +439,7 @@ ignore_invalid_option_p (ARGPARSE_ARGS *arg, const char *keyword)
/* Add the keywords up to the next LF to the list of to be ignored
options. After returning FP will either be at EOF or the next
- character read wll be the first of a new line. The function
+ character read will be the first of a new line. The function
returns 0 on success or true on malloc failure. */
static int
ignore_invalid_option_add (ARGPARSE_ARGS *arg, FILE *fp)
@@ -1280,7 +1280,7 @@ long_opt_strlen( ARGPARSE_OPTS *o )
* this option
* - a description,ine which starts with a '@' and is followed by
* any other characters is printed as is; this may be used for examples
- * ans such.
+ * and such.
* - A description which starts with a '|' outputs the string between this
* bar and the next one as arguments of the long option.
*/
diff --git a/common/audit.h b/common/audit.h
index 4ef2645da..05f39533d 100644
--- a/common/audit.h
+++ b/common/audit.h
@@ -185,7 +185,7 @@ typedef enum
if no real recipient has been given. */
AUDIT_SESSION_KEY, /* string */
- /* Mark the creation or availibility of the session key. The
+ /* Mark the creation or availability of the session key. The
parameter is the algorithm ID. */
AUDIT_ENCRYPTED_TO, /* cert, err */
diff --git a/common/convert.c b/common/convert.c
index 6d03adc3d..40fb4eecf 100644
--- a/common/convert.c
+++ b/common/convert.c
@@ -177,7 +177,7 @@ bin2hexcolon (const void *buffer, size_t length, char *stringbuf)
string or a white space character. The function makes sure that
the resulting string in BUFFER is terminated by a Nul byte. Note
that the returned string may include embedded Nul bytes; the extra
- Nul byte at the end is used to make sure tha the result can always
+ Nul byte at the end is used to make sure that the result can always
be used as a C-string.
BUFSIZE is the available length of BUFFER; if the converted result
diff --git a/common/dotlock.c b/common/dotlock.c
index 5227bb64e..1bc31d8a6 100644
--- a/common/dotlock.c
+++ b/common/dotlock.c
@@ -140,7 +140,7 @@
you pass (0) instead of (-1) the function does not wait in case the
file is already locked but returns -1 and sets ERRNO to EACCES.
Any other positive value for the second parameter is considered a
- timeout valuie in milliseconds.
+ timeout value in milliseconds.
To release the lock you call:
diff --git a/common/iobuf.c b/common/iobuf.c
index 02c9b491c..5eeba8fe6 100644
--- a/common/iobuf.c
+++ b/common/iobuf.c
@@ -68,8 +68,8 @@
/*-- End configurable part. --*/
-/* The size of the iobuffers. This can be chnages using the
- * iobuf_set_buffer_size fucntion. */
+/* The size of the iobuffers. This can be changed using the
+ * iobuf_set_buffer_size function. */
static unsigned int iobuf_buffer_size = DEFAULT_IOBUF_BUFFER_SIZE;
@@ -878,9 +878,9 @@ block_filter (void *opaque, int control, iobuf_t chain, byte * buffer,
}
else if (c == 255)
{
- a->size = (size_t)iobuf_get (chain) << 24;
- a->size |= iobuf_get (chain) << 16;
- a->size |= iobuf_get (chain) << 8;
+ a->size = iobuf_get_noeof (chain) << 24;
+ a->size |= iobuf_get_noeof (chain) << 16;
+ a->size |= iobuf_get_noeof (chain) << 8;
if ((c = iobuf_get (chain)) == -1)
{
log_error ("block_filter: invalid 4 byte length\n");
@@ -2610,12 +2610,50 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
}
p = buffer;
- while ((c = iobuf_get (a)) != -1)
+ while (1)
{
- *p++ = c;
- nbytes++;
- if (c == '\n')
- break;
+ if (!a->nofast && a->d.start < a->d.len && nbytes < length - 1)
+ /* Fast path for finding '\n' by using standard C library's optimized
+ memchr. */
+ {
+ unsigned size = a->d.len - a->d.start;
+ byte *newline_pos;
+
+ if (size > length - 1 - nbytes)
+ size = length - 1 - nbytes;
+
+ newline_pos = memchr (a->d.buf + a->d.start, '\n', size);
+ if (newline_pos)
+ {
+ /* Found newline, copy buffer and return. */
+ size = (newline_pos - (a->d.buf + a->d.start)) + 1;
+ memcpy (p, a->d.buf + a->d.start, size);
+ p += size;
+ nbytes += size;
+ a->d.start += size;
+ a->nbytes += size;
+ break;
+ }
+ else
+ {
+ /* No newline, copy buffer and continue. */
+ memcpy (p, a->d.buf + a->d.start, size);
+ p += size;
+ nbytes += size;
+ a->d.start += size;
+ a->nbytes += size;
+ }
+ }
+ else
+ {
+ c = iobuf_readbyte (a);
+ if (c == -1)
+ break;
+ *p++ = c;
+ nbytes++;
+ if (c == '\n')
+ break;
+ }
if (nbytes == length - 1)
/* We don't have enough space to add a \n and a \0. Increase
diff --git a/common/mbox-util.c b/common/mbox-util.c
index c1f05b834..a9086a3f5 100644
--- a/common/mbox-util.c
+++ b/common/mbox-util.c
@@ -173,11 +173,12 @@ is_valid_mailbox (const char *name)
/* Return the mailbox (local-part@domain) form a standard user id.
- All plain ASCII characters in the result are converted to
- lowercase. Caller must free the result. Returns NULL if no valid
- mailbox was found (or we are out of memory). */
+ * All plain ASCII characters in the result are converted to
+ * lowercase. If SUBADDRESS is 1, '+' denoted sub-addresses are not
+ * included in the result. Caller must free the result. Returns NULL
+ * if no valid mailbox was found (or we are out of memory). */
char *
-mailbox_from_userid (const char *userid)
+mailbox_from_userid (const char *userid, int subaddress)
{
const char *s, *s_end;
size_t len;
@@ -226,6 +227,29 @@ mailbox_from_userid (const char *userid)
else
errno = EINVAL;
+ if (result && subaddress == 1)
+ {
+ char *atsign, *plus;
+
+ if ((atsign = strchr (result, '@')))
+ {
+ /* We consider a subaddress only if there is a single '+'
+ * in the local part and the '+' is not the first or last
+ * character. */
+ *atsign = 0;
+ if ((plus = strchr (result, '+'))
+ && !strchr (plus+1, '+')
+ && result != plus
+ && plus[1] )
+ {
+ *atsign = '@';
+ memmove (plus, atsign, strlen (atsign)+1);
+ }
+ else
+ *atsign = '@';
+ }
+ }
+
return result? ascii_strlwr (result): NULL;
}
@@ -241,3 +265,42 @@ is_valid_user_id (const char *uid)
return 1;
}
+
+
+/* Returns true if STRING is a valid domain name according to the LDH
+ * rule. */
+int
+is_valid_domain_name (const char *string)
+{
+ static char const ldh_chars[] =
+ "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-";
+ const char *s;
+
+ /* Note that we do not check the length limit of a label or the
+ * entire name */
+
+ for (s=string; *s; s++)
+ if (*s == '.')
+ {
+ if (string == s)
+ return 0; /* Dot at the start of the string. */
+ /* (may also be at the end like in ".") */
+ if (s[1] == '.')
+ return 0; /* No - double dot. */
+ }
+ else if (!strchr (ldh_chars, *s))
+ return 0;
+ else if (*s == '-')
+ {
+ if (string == s)
+ return 0; /* Leading hyphen. */
+ if (s[-1] == '.')
+ return 0; /* Hyphen at begin of a label. */
+ if (s[1] == '.')
+ return 0; /* Hyphen at start of a label. */
+ if (!s[1])
+ return 0; /* Trailing hyphen. */
+ }
+
+ return !!*string;
+}
diff --git a/common/mbox-util.h b/common/mbox-util.h
index bce003f31..10ff2c4a0 100644
--- a/common/mbox-util.h
+++ b/common/mbox-util.h
@@ -22,8 +22,9 @@
int has_invalid_email_chars (const void *buffer, size_t length);
int is_valid_mailbox (const char *name);
int is_valid_mailbox_mem (const void *buffer, size_t length);
-char *mailbox_from_userid (const char *userid);
+char *mailbox_from_userid (const char *userid, int subaddress);
int is_valid_user_id (const char *uid);
+int is_valid_domain_name (const char *string);
#endif /*GNUPG_COMMON_MBOX_UTIL_H*/
diff --git a/common/mkerrors b/common/mkerrors
index 138d3c1d1..2a6960ab6 100755
--- a/common/mkerrors
+++ b/common/mkerrors
@@ -30,7 +30,7 @@ cat <<EOF
* gnupg_strerror:
* @err: Error code
*
- * This function returns a textual representaion of the given
+ * This function returns a textual representation of the given
* errorcode. If this is an unknown value, a string with the value
* is returned (Beware: it is hold in a static buffer).
*
diff --git a/common/mkerrtok b/common/mkerrtok
index e6310722a..49c10e595 100755
--- a/common/mkerrtok
+++ b/common/mkerrtok
@@ -26,7 +26,7 @@ cat <<EOF
* gnupg_error_token:
* @err: Error code
*
- * This function returns a textual representaion of the given
+ * This function returns a textual representation of the given
* errorcode. If this is an unknown value, a static string is returned.
* This function differs from gnupg_strerror that it yields the string
* representation of the macro which is never subject to i18n.
diff --git a/common/openpgp-oid.c b/common/openpgp-oid.c
index d800e7d57..86885e0aa 100644
--- a/common/openpgp-oid.c
+++ b/common/openpgp-oid.c
@@ -184,7 +184,7 @@ openpgp_oid_from_str (const char *string, gcry_mpi_t *r_mpi)
}
-/* Return a malloced string represenation of the OID in the opaque MPI
+/* Return a malloced string representation of the OID in the opaque MPI
A. In case of an error NULL is returned and ERRNO is set. */
char *
openpgp_oid_to_str (gcry_mpi_t a)
@@ -221,7 +221,7 @@ openpgp_oid_to_str (gcry_mpi_t a)
/* To calculate the length of the string we can safely assume an
upper limit of 3 decimal characters per byte. Two extra bytes
- account for the special first octect */
+ account for the special first octet */
string = p = xtrymalloc (length*(1+3)+2+1);
if (!string)
return NULL;
diff --git a/common/percent.c b/common/percent.c
index eeb026fbe..7b817684d 100644
--- a/common/percent.c
+++ b/common/percent.c
@@ -42,7 +42,7 @@
failure.
Note that we also escape the quote character to work around a bug
- in the mingw32 runtime which does not correcty handle command line
+ in the mingw32 runtime which does not correctly handle command line
quoting. We correctly double the quote mark when calling a program
(i.e. gpg-protect-tool), but the pre-main code does not notice the
double quote as an escaped quote. We do this also on POSIX systems
diff --git a/common/sexp-parse.h b/common/sexp-parse.h
index 4f77f1430..0403d65f5 100644
--- a/common/sexp-parse.h
+++ b/common/sexp-parse.h
@@ -105,7 +105,7 @@ smatch (unsigned char const **buf, size_t buflen, const char *token)
}
/* Format VALUE for use as the length indicatior of an S-expression.
- The caller needs to provide a buffer HELP_BUFFER wth a length of
+ The caller needs to provide a buffer HELP_BUFFER with a length of
HELP_BUFLEN. The return value is a pointer into HELP_BUFFER with
the formatted length string. The colon and a trailing nul are
appended. HELP_BUFLEN must be at least 3 - a more useful value is
diff --git a/common/sexputil.c b/common/sexputil.c
index f30790aa1..02e52d0ed 100644
--- a/common/sexputil.c
+++ b/common/sexputil.c
@@ -303,7 +303,7 @@ make_simple_sexp_from_hexstr (const char *line, size_t *nscanned)
for (; n > 1; n -=2, s += 2)
*p++ = xtoi_2 (s);
*p++ = ')';
- *p = 0; /* (Not really neaded.) */
+ *p = 0; /* (Not really needed.) */
return buf;
}
diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c
index e7f4af341..7688c846d 100644
--- a/common/simple-pwquery.c
+++ b/common/simple-pwquery.c
@@ -75,7 +75,7 @@
/* Name of the socket to be used. This is a kludge to keep on using
- the existsing code despite that we only support a standard socket. */
+ the existing code despite that we only support a standard socket. */
static char *default_gpg_agent_info;
@@ -246,6 +246,7 @@ agent_open (assuan_context_t *ctx)
#ifdef SPWQ_USE_LOGGING
log_error (_("no gpg-agent running in this session\n"));
#endif
+ *ctx = NULL;
return SPWQ_NO_AGENT;
}
diff --git a/common/ssh-utils.c b/common/ssh-utils.c
index 38d6e8aa2..013b28e5b 100644
--- a/common/ssh-utils.c
+++ b/common/ssh-utils.c
@@ -247,7 +247,7 @@ get_fingerprint (gcry_sexp_t key, int algo,
goto leave;
}
- strncpy (*r_fpr, algo_name, strlen (algo_name));
+ memcpy (*r_fpr, algo_name, strlen (algo_name));
fpr = (char *) *r_fpr + strlen (algo_name);
*fpr++ = ':';
diff --git a/common/stringhelp.c b/common/stringhelp.c
index 0abac8ae5..751e5711f 100644
--- a/common/stringhelp.c
+++ b/common/stringhelp.c
@@ -1400,7 +1400,7 @@ parse_version_number (const char *s, int *number)
/* This function breaks up the complete string-representation of the
- version number S, which is of the following struture: <major
+ version number S, which is of the following structure: <major
number>.<minor number>[.<micro number>]<patch level>. The major,
minor, and micro number components will be stored in *MAJOR, *MINOR
and *MICRO. If MICRO is not given 0 is used instead.
diff --git a/common/sysutils.c b/common/sysutils.c
index 55a7ee9ec..0a3dc2eaf 100644
--- a/common/sysutils.c
+++ b/common/sysutils.c
@@ -551,14 +551,13 @@ gnupg_tmpfile (void)
void
gnupg_reopen_std (const char *pgmname)
{
-#if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
- struct stat statbuf;
+#ifdef F_GETFD
int did_stdin = 0;
int did_stdout = 0;
int did_stderr = 0;
FILE *complain;
- if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
+ if (fcntl (STDIN_FILENO, F_GETFD) == -1 && errno ==EBADF)
{
if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
did_stdin = 1;
@@ -566,7 +565,7 @@ gnupg_reopen_std (const char *pgmname)
did_stdin = 2;
}
- if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
+ if (fcntl (STDOUT_FILENO, F_GETFD) == -1 && errno == EBADF)
{
if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
did_stdout = 1;
@@ -574,7 +573,7 @@ gnupg_reopen_std (const char *pgmname)
did_stdout = 2;
}
- if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
+ if (fcntl (STDERR_FILENO, F_GETFD)==-1 && errno==EBADF)
{
if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
did_stderr = 1;
@@ -607,7 +606,7 @@ gnupg_reopen_std (const char *pgmname)
if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
exit (3);
-#else /* !(HAVE_STAT && !HAVE_W32_SYSTEM) */
+#else /* !F_GETFD */
(void)pgmname;
#endif
}
diff --git a/common/t-exechelp.c b/common/t-exechelp.c
index cf967fcc7..3bf082bbb 100644
--- a/common/t-exechelp.c
+++ b/common/t-exechelp.c
@@ -131,7 +131,7 @@ test_close_all_fds (void)
free (array);
/* Now let's check the realloc we use. We do this and the next
- tests only if we are allowed to open enought descriptors. */
+ tests only if we are allowed to open enough descriptors. */
if (get_max_fds () > 32)
{
int except[] = { 20, 23, 24, -1 };
diff --git a/common/t-mbox-util.c b/common/t-mbox-util.c
index 979d4b37c..ae717f96f 100644
--- a/common/t-mbox-util.c
+++ b/common/t-mbox-util.c
@@ -25,6 +25,9 @@
#include "util.h"
#include "mbox-util.h"
+#define PGM "t-mbox-util"
+
+
#define pass() do { ; } while(0)
#define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\
__FILE__,__LINE__, (a)); \
@@ -32,8 +35,73 @@
} while(0)
+static int verbose;
+static int debug;
+
+
+static void
+run_mbox_test (void)
+{
+ static struct
+ {
+ const char *userid;
+ const char *mbox;
+ } testtbl[] =
+ {
+ { "Werner Koch <[email protected]>", "[email protected]" },
+ { "[email protected] ", NULL },
+ { " [email protected]", NULL },
+ { "Werner Koch (test) <[email protected]>", "[email protected]" },
+ { "Werner Koch <[email protected]> (test)", "[email protected]" },
+ { "Werner Koch <[email protected] (test)", NULL },
+ { "Werner Koch <[email protected] >", NULL },
+ { "Werner Koch <[email protected]", NULL },
+ { "", NULL },
+ { "@", NULL },
+ { "bar <>", NULL },
+ { "<[email protected].>", NULL },
+ { "<[email protected]>", NULL },
+ { "<foo@.>", NULL },
+ { "<@example.org>", NULL },
+ { "<foo@@example.org>", NULL },
+ { "<@[email protected]>", NULL },
+ { "<fo()[email protected]> ()", "fo()[email protected]" },
+ { "<fo()[email protected]> ()", "fo()[email protected]" },
+ { "fo()[email protected]", NULL},
+ { NULL, NULL }
+ };
+ int idx;
+
+ for (idx=0; testtbl[idx].userid; idx++)
+ {
+ char *mbox = mailbox_from_userid (testtbl[idx].userid, 0);
+
+ if (!testtbl[idx].mbox)
+ {
+ if (mbox)
+ fail (idx);
+ }
+ else if (!mbox)
+ fail (idx);
+ else if (strcmp (mbox, testtbl[idx].mbox))
+ fail (idx);
+
+ xfree (mbox);
+ }
+}
+
+
static void
-run_test (void)
+run_mbox_no_sub_test (void)
{
static struct
{
@@ -41,6 +109,7 @@ run_test (void)
const char *mbox;
} testtbl[] =
{
{ "Werner Koch <[email protected]>", "[email protected]" },
@@ -70,13 +139,30 @@ run_test (void)
{ "<fo()[email protected]> ()", "fo()[email protected]" },
{ "fo()[email protected]", NULL},
+
{ NULL, NULL }
};
int idx;
for (idx=0; testtbl[idx].userid; idx++)
{
- char *mbox = mailbox_from_userid (testtbl[idx].userid);
+ char *mbox = mailbox_from_userid (testtbl[idx].userid, 1);
if (!testtbl[idx].mbox)
{
@@ -93,13 +179,155 @@ run_test (void)
}
+static void
+run_dns_test (void)
+{
+ static struct
+ {
+ const char *name;
+ int valid;
+ } testtbl[] =
+ {
+ { "", 0 },
+ { ".", 0 },
+ { "-", 0 },
+ { "a", 1 },
+ { "ab", 1 },
+ { "a.b", 1 },
+ { "a.b.", 1 },
+ { ".a.b.", 0 },
+ { ".a.b", 0 },
+ { "-a.b", 0 },
+ { "a-.b", 0 },
+ { "a.-b", 0 },
+ { "a.b-", 0 },
+ { "a.b-.", 0 },
+ { "a..b", 0 },
+ { "ab.c", 1 },
+ { "a-b.c", 1 },
+ { "a-b-.c", 0 },
+ { "-a-b.c", 0 },
+ { "example.org", 1 },
+ { "x.example.org", 1 },
+ { "xy.example.org", 1 },
+ { "Xy.example.org", 1 },
+ { "-Xy.example.org", 0 },
+ { "Xy.example-.org", 0 },
+ { "foo.example.org..", 0 },
+ { "foo.example.org.", 1 },
+ { ".foo.example.org.", 0 },
+ { "..foo.example.org.", 0 },
+ { NULL, 0 }
+ };
+ int idx;
+
+ for (idx=0; testtbl[idx].name; idx++)
+ {
+ if (is_valid_domain_name (testtbl[idx].name) != testtbl[idx].valid)
+ fail (idx);
+ }
+}
+
+
+static void
+run_filter (int no_sub)
+{
+ char buf[4096];
+ int c;
+ char *p, *mbox;
+ unsigned int count1 = 0;
+ unsigned int count2 = 0;
+
+ while (fgets (buf, sizeof buf, stdin))
+ {
+ p = strchr (buf, '\n');
+ if (p)
+ *p = 0;
+ else
+ {
+ /* Skip to the end of the line. */
+ while ((c = getc (stdin)) != EOF && c != '\n')
+ ;
+ }
+ count1++;
+ trim_spaces (buf);
+ mbox = mailbox_from_userid (buf, no_sub);
+ if (mbox)
+ {
+ printf ("%s\n", mbox);
+ xfree (mbox);
+ count2++;
+ }
+ }
+ if (verbose)
+ fprintf (stderr, PGM ": lines=%u mboxes=%u\n", count1, count2);
+}
+
+
int
main (int argc, char **argv)
{
- (void)argc;
- (void)argv;
+ int last_argc = -1;
+ int opt_filter = 0;
+ int opt_no_sub = 0;
- run_test ();
+ if (argc)
+ { argc--; argv++; }
+ while (argc && last_argc != argc )
+ {
+ last_argc = argc;
+ if (!strcmp (*argv, "--"))
+ {
+ argc--; argv++;
+ break;
+ }
+ else if (!strcmp (*argv, "--help"))
+ {
+ fputs ("usage: " PGM " [FILE]\n"
+ "Options:\n"
+ " --verbose Print timings etc.\n"
+ " --debug Flyswatter\n"
+ " --filter Filter mboxes from input lines\n"
+ " --no-sub Ignore '+'-sub-addresses\n"
+ , stdout);
+ exit (0);
+ }
+ else if (!strcmp (*argv, "--verbose"))
+ {
+ verbose++;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--debug"))
+ {
+ verbose += 2;
+ debug++;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--filter"))
+ {
+ opt_filter = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--no-sub"))
+ {
+ opt_no_sub = 1;
+ argc--; argv++;
+ }
+ else if (!strncmp (*argv, "--", 2))
+ {
+ fprintf (stderr, PGM ": unknown option '%s'\n", *argv);
+ exit (1);
+ }
+ }
+
+ if (opt_filter)
+ run_filter (opt_no_sub);
+ else
+ {
+ run_mbox_test ();
+ run_mbox_no_sub_test ();
+ run_dns_test ();
+ }
return 0;
}
diff --git a/configure.ac b/configure.ac
index 03f3af9eb..9d3eb41f0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -129,7 +129,10 @@ GNUPG_BUILD_PROGRAM(symcryptrun, no)
# We use gpgtar to unpack test data, hence we always build it. If the
# user opts out, we simply don't install it.
GNUPG_BUILD_PROGRAM(gpgtar, yes)
-GNUPG_BUILD_PROGRAM(wks-tools, no)
+# We also install the gpg-wks-server tool by default but disable it
+# later for platforms where it can't be build.
+GNUPG_BUILD_PROGRAM(wks-tools, yes)
+
AC_SUBST(PACKAGE)
AC_SUBST(PACKAGE_GT)
@@ -623,7 +626,6 @@ AC_ARG_VAR(YAT2M, [tool to convert texi to man pages])
AM_CONDITIONAL(HAVE_YAT2M, test -n "$ac_cv_path_YAT2M")
AC_ISC_POSIX
AC_SYS_LARGEFILE
-GNUPG_CHECK_USTAR
# We need to compile and run a program on the build machine. A
@@ -682,6 +684,7 @@ case "${host}" in
try_gettext="no"
use_simple_gettext=yes
mmap_needed=no
+ build_wks_tools=no
;;
i?86-emx-os2 | i?86-*-os2*emx )
# OS/2 with the EMX environment
@@ -689,6 +692,7 @@ case "${host}" in
AC_DEFINE(HAVE_DRIVE_LETTERS)
have_dosish_system=yes
try_gettext="no"
+ build_wks_tools=no
;;
i?86-*-msdosdjgpp*)
@@ -697,6 +701,7 @@ case "${host}" in
AC_DEFINE(HAVE_DRIVE_LETTERS)
have_dosish_system=yes
try_gettext="no"
+ build_wks_tools=no
;;
*-*-hpux*)
@@ -727,6 +732,7 @@ case "${host}" in
# Android is fully utf-8 and we do not want to use iconv to
# keeps things simple
require_iconv=no
+ build_wks_tools=no
;;
*-apple-darwin*)
AC_DEFINE(_DARWIN_C_SOURCE, 900000L,
@@ -1482,7 +1488,7 @@ if test "$use_regex" = yes ; then
use_regex=no
else
if test x"$cross_compiling" = xyes; then
- AC_MSG_WARN([cross compiling; assuming regexp libray is not broken])
+ AC_MSG_WARN([cross compiling; assuming regexp library is not broken])
else
AC_CACHE_CHECK([whether your system's regexp library is broken],
[gnupg_cv_regex_broken],
@@ -2044,7 +2050,6 @@ agent/Makefile
scd/Makefile
g13/Makefile
dirmngr/Makefile
-tools/gpg-zip
tools/Makefile
doc/Makefile
tests/Makefile
diff --git a/dirmngr/Makefile.am b/dirmngr/Makefile.am
index 43f59bd45..22b8c1a3a 100644
--- a/dirmngr/Makefile.am
+++ b/dirmngr/Makefile.am
@@ -62,7 +62,7 @@ dirmngr_SOURCES = dirmngr.c dirmngr.h server.c crlcache.c crlfetch.c \
domaininfo.c \
workqueue.c \
loadswdb.c \
- cdb.h cdblib.c misc.c dirmngr-err.h \
+ cdb.h cdblib.c misc.c dirmngr-err.h dirmngr-status.h \
ocsp.c ocsp.h validate.c validate.h \
dns-stuff.c dns-stuff.h \
http.c http.h http-common.c http-common.h http-ntbtls.c \
@@ -111,7 +111,7 @@ dirmngr_client_LDADD = $(libcommon) \
dirmngr_client_LDFLAGS = $(extra_bin_ldflags)
-t_common_src = t-support.h
+t_common_src = t-support.h t-support.c
if USE_LIBDNS
t_common_src += dns.c dns.h
endif
diff --git a/dirmngr/cdb.h b/dirmngr/cdb.h
index 0c0d2702a..5d46f6956 100644
--- a/dirmngr/cdb.h
+++ b/dirmngr/cdb.h
@@ -85,7 +85,7 @@ int cdb_make_put(struct cdb_make *cdbmp,
const void *key, cdbi_t klen,
const void *val, cdbi_t vlen,
int flag);
-#define CDB_PUT_ADD 0 /* add unconditionnaly, like cdb_make_add() */
+#define CDB_PUT_ADD 0 /* add unconditionally, like cdb_make_add() */
#define CDB_PUT_REPLACE 1 /* replace: do not place to index OLD record */
#define CDB_PUT_INSERT 2 /* add only if not already exists */
#define CDB_PUT_WARN 3 /* add unconditionally but ret. 1 if exists */
diff --git a/dirmngr/cdblib.c b/dirmngr/cdblib.c
index 827399f7e..c40126396 100644
--- a/dirmngr/cdblib.c
+++ b/dirmngr/cdblib.c
@@ -19,7 +19,7 @@
length, meaning that corresponding hash table is empty.
Right after toc section, data section follows without any
- alingment. It consists of series of records, each is a key length,
+ alignment. It consists of series of records, each is a key length,
value (data) length, key and value. Again, key and value length
are 4-byte unsigned integers. Each next record follows previous
without any special alignment.
@@ -52,7 +52,7 @@
beginning of a table). When hash value in question is found in
hash table, look to key of corresponding record, comparing it with
key in question. If them of the same length and equals to each
- other, then record is found, overwise, repeat with next hash table
+ other, then record is found, otherwise, repeat with next hash table
slot. Note that there may be several records with the same key.
*/
@@ -245,7 +245,7 @@ cdb_find(struct cdb *cdbp, const void *key, cdbi_t klen)
pos = cdb_unpack(htp); /* htab position */
if (n > (cdbp->cdb_fsize >> 3) /* overflow of httodo ? */
|| pos > cdbp->cdb_fsize /* htab start within file ? */
- || httodo > cdbp->cdb_fsize - pos) /* entrie htab within file ? */
+ || httodo > cdbp->cdb_fsize - pos) /* htab entry within file ? */
{
gpg_err_set_errno (EPROTO);
return -1;
diff --git a/dirmngr/crlcache.c b/dirmngr/crlcache.c
index fbe3beea1..c9e5ca68f 100644
--- a/dirmngr/crlcache.c
+++ b/dirmngr/crlcache.c
@@ -1250,13 +1250,15 @@ crl_cache_deinit (void)
}
-/* Delete the cache from disk. Return 0 on success.*/
+/* Delete the cache from disk and memory. Return 0 on success.*/
int
crl_cache_flush (void)
{
int rc;
+ crl_cache_deinit ();
rc = cleanup_cache_dir (0)? -1 : 0;
+ crl_cache_init ();
return rc;
}
@@ -1782,7 +1784,7 @@ crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
ksba_sexp_t keyid;
/* We need to look for the issuer only after having read
- all items. The issuer itselfs comes before the items
+ all items. The issuer itself comes before the items
but the optional authorityKeyIdentifier comes after the
items. */
err = ksba_crl_get_issuer (crl, &crlissuer);
@@ -1907,7 +1909,7 @@ get_crl_number (ksba_crl_t crl)
/* Return the authorityKeyIdentifier or NULL if it is not available.
- The issuer name may consists of several parts - they are delimted by
+ The issuer name may consists of several parts - they are delimited by
0x01. */
static char *
get_auth_key_id (ksba_crl_t crl, char **serialno)
diff --git a/dirmngr/dirmngr-status.h b/dirmngr/dirmngr-status.h
new file mode 100644
index 000000000..2c3fd78a3
--- /dev/null
+++ b/dirmngr/dirmngr-status.h
@@ -0,0 +1,39 @@
+/* dirmngr-status.h - Status code helper functions for dirmnmgr.
+ * Copyright (C) 2004, 2014, 2015, 2018 g10 Code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0+
+ */
+
+/* We keep them separate so that we don't always need to include the
+ * entire dirmngr.h */
+
+#ifndef DIRMNGR_STATUS_H
+#define DIRMNGR_STATUS_H
+
+
+/*-- server.c --*/
+gpg_error_t dirmngr_status (ctrl_t ctrl, const char *keyword, ...);
+gpg_error_t dirmngr_status_help (ctrl_t ctrl, const char *text);
+gpg_error_t dirmngr_status_helpf (ctrl_t ctrl, const char *format,
+ ...) GPGRT_ATTR_PRINTF(2,3);
+gpg_error_t dirmngr_status_printf (ctrl_t ctrl, const char *keyword,
+ const char *format,
+ ...) GPGRT_ATTR_PRINTF(3,4);
+
+
+#endif /* DIRMNGR_STATUS_H */
diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c
index 6fdfe36c2..80fb13476 100644
--- a/dirmngr/dirmngr.c
+++ b/dirmngr/dirmngr.c
@@ -338,7 +338,7 @@ static int active_connections;
* thread to run background network tasks. */
static int network_activity_seen;
-/* A list of filenames registred with --hkp-cacert. */
+/* A list of filenames registered with --hkp-cacert. */
static strlist_t hkp_cacert_filenames;
@@ -411,7 +411,7 @@ my_strusage( int level )
/* Callback from libksba to hash a provided buffer. Our current
implementation does only allow SHA-1 for hashing. This may be
- extended by mapping the name, testing for algorithm availibility
+ extended by mapping the name, testing for algorithm availability
and adjust the length checks accordingly. */
static gpg_error_t
my_ksba_hash_buffer (void *arg, const char *oid,
@@ -520,7 +520,7 @@ set_tor_mode (void)
{
if (dirmngr_use_tor ())
{
- /* Enable Tor mode and when called again force a new curcuit
+ /* Enable Tor mode and when called again force a new circuit
* (e.g. on SIGHUP). */
enable_dns_tormode (1);
if (assuan_sock_set_flag (ASSUAN_INVALID_FD, "tor-mode", 1))
@@ -752,7 +752,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
}
-/* This fucntion is called after option parsing to adjust some values
+/* This function is called after option parsing to adjust some values
* and call option setup functions. */
static void
post_option_parsing (void)
@@ -1143,6 +1143,7 @@ main (int argc, char **argv)
thread_init ();
cert_cache_init (hkp_cacert_filenames);
crl_cache_init ();
+ ks_hkp_init ();
http_register_netactivity_cb (netactivity_action);
start_command_handler (ASSUAN_INVALID_FD, 0);
shutdown_reaper ();
@@ -1178,6 +1179,7 @@ main (int argc, char **argv)
thread_init ();
cert_cache_init (hkp_cacert_filenames);
crl_cache_init ();
+ ks_hkp_init ();
http_register_netactivity_cb (netactivity_action);
handle_connections (3);
shutdown_reaper ();
@@ -1399,6 +1401,7 @@ main (int argc, char **argv)
thread_init ();
cert_cache_init (hkp_cacert_filenames);
crl_cache_init ();
+ ks_hkp_init ();
http_register_netactivity_cb (netactivity_action);
handle_connections (fd);
shutdown_reaper ();
@@ -1421,6 +1424,7 @@ main (int argc, char **argv)
thread_init ();
cert_cache_init (hkp_cacert_filenames);
crl_cache_init ();
+ ks_hkp_init ();
if (!argc)
rc = crl_cache_load (&ctrlbuf, NULL);
else
@@ -1444,6 +1448,7 @@ main (int argc, char **argv)
thread_init ();
cert_cache_init (hkp_cacert_filenames);
crl_cache_init ();
+ ks_hkp_init ();
rc = crl_fetch (&ctrlbuf, argv[0], &reader);
if (rc)
log_error (_("fetching CRL from '%s' failed: %s\n"),
diff --git a/dirmngr/dirmngr.h b/dirmngr/dirmngr.h
index 5189f93b1..9c26c09e6 100644
--- a/dirmngr/dirmngr.h
+++ b/dirmngr/dirmngr.h
@@ -36,6 +36,7 @@
#include "../common/sysutils.h" /* (gnupg_fd_t) */
#include "../common/asshelp.h" /* (assuan_context_t) */
#include "../common/i18n.h"
+#include "dirmngr-status.h"
#include "http.h" /* (parsed_uri_t) */
/* This objects keeps information about a particular LDAP server and
@@ -217,7 +218,7 @@ int dirmngr_use_tor (void);
/*-- Various housekeeping functions. --*/
void ks_hkp_housekeeping (time_t curtime);
void ks_hkp_reload (void);
-
+void ks_hkp_init (void);
/*-- server.c --*/
ldap_server_t get_ldapservers_from_ctrl (ctrl_t ctrl);
@@ -229,13 +230,6 @@ gpg_error_t get_istrusted_from_client (ctrl_t ctrl, const char *hexfpr);
int dirmngr_assuan_log_monitor (assuan_context_t ctx, unsigned int cat,
const char *msg);
void start_command_handler (gnupg_fd_t fd, unsigned int session_id);
-gpg_error_t dirmngr_status (ctrl_t ctrl, const char *keyword, ...);
-gpg_error_t dirmngr_status_help (ctrl_t ctrl, const char *text);
-gpg_error_t dirmngr_status_helpf (ctrl_t ctrl, const char *format,
- ...) GPGRT_ATTR_PRINTF(2,3);
-gpg_error_t dirmngr_status_printf (ctrl_t ctrl, const char *keyword,
- const char *format,
- ...) GPGRT_ATTR_PRINTF(3,4);
gpg_error_t dirmngr_tick (ctrl_t ctrl);
/*-- http-ntbtls.c --*/
diff --git a/dirmngr/dirmngr_ldap.c b/dirmngr/dirmngr_ldap.c
index 8452c3ba0..dd7e4bda5 100644
--- a/dirmngr/dirmngr_ldap.c
+++ b/dirmngr/dirmngr_ldap.c
@@ -417,9 +417,9 @@ set_timeout (my_opt_t myopt)
sec_attr.nLength = sizeof sec_attr;
sec_attr.bInheritHandle = FALSE;
- /* Create a manual resetable timer. */
+ /* Create a manual resettable timer. */
timer = CreateWaitableTimer (NULL, TRUE, NULL);
- /* Intially set the timer. */
+ /* Initially set the timer. */
SetWaitableTimer (timer, &due_time, 0, NULL, NULL, 0);
if (CreateThread (&sec_attr, 0, alarm_thread, timer, 0, &tid))
diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c
index ffac816f9..7aa07c716 100644
--- a/dirmngr/dns-stuff.c
+++ b/dirmngr/dns-stuff.c
@@ -73,6 +73,7 @@
#include "./dirmngr-err.h"
#include "../common/util.h"
#include "../common/host2net.h"
+#include "dirmngr-status.h"
#include "dns-stuff.h"
#ifdef USE_NPTH
@@ -150,7 +151,7 @@ static char tor_socks_password[20];
#ifdef USE_LIBDNS
-/* Libdns gobal data. */
+/* Libdns global data. */
struct libdns_s
{
struct dns_resolv_conf *resolv_conf;
@@ -433,12 +434,13 @@ resolv_conf_changed_p (void)
/* Initialize libdns. Returns 0 on success; prints a diagnostic and
* returns an error code on failure. */
static gpg_error_t
-libdns_init (void)
+libdns_init (ctrl_t ctrl)
{
gpg_error_t err;
struct libdns_s ld;
int derr;
char *cfgstr = NULL;
+ const char *fname = NULL;
if (libdns.resolv_conf)
return 0; /* Already initialized. */
@@ -532,7 +534,6 @@ libdns_init (void)
xfree (ninfo);
#else /* Unix */
- const char *fname;
fname = RESOLV_CONF_NAME;
resolv_conf_changed_p (); /* Reset timestamp. */
@@ -622,6 +623,7 @@ libdns_init (void)
{
err = libdns_error_to_gpg_error (derr);
log_error ("failed to load DNS hints: %s\n", gpg_strerror (err));
+ fname = "[dns hints]";
goto leave;
}
@@ -632,6 +634,14 @@ libdns_init (void)
log_debug ("dns: libdns initialized%s\n", tor_mode?" (tor mode)":"");
leave:
+ if (!fname)
+ fname = cfgstr;
+ if (err && fname)
+ dirmngr_status_printf (ctrl, "WARNING",
+ "dns_config_problem %u"
+ " error accessing '%s': %s <%s>",
+ err, fname, gpg_strerror (err), gpg_strsource (err));
+
xfree (cfgstr);
return err;
}
@@ -686,7 +696,7 @@ reload_dns_stuff (int force)
* failure an error code is returned and NULL stored at R_RES.
*/
static gpg_error_t
-libdns_res_open (struct dns_resolver **r_res)
+libdns_res_open (ctrl_t ctrl, struct dns_resolver **r_res)
{
gpg_error_t err;
struct dns_resolver *res;
@@ -708,7 +718,7 @@ libdns_res_open (struct dns_resolver **r_res)
libdns_deinit ();
}
- err = libdns_init ();
+ err = libdns_init (ctrl);
if (err)
return err;
@@ -790,7 +800,7 @@ libdns_res_wait (struct dns_resolver *res)
#ifdef USE_LIBDNS
static gpg_error_t
-resolve_name_libdns (const char *name, unsigned short port,
+resolve_name_libdns (ctrl_t ctrl, const char *name, unsigned short port,
int want_family, int want_socktype,
dns_addrinfo_t *r_dai, char **r_canonname)
{
@@ -823,7 +833,7 @@ resolve_name_libdns (const char *name, unsigned short port,
portstr = portstr_;
}
- err = libdns_res_open (&res);
+ err = libdns_res_open (ctrl, &res);
if (err)
goto leave;
@@ -935,7 +945,7 @@ resolve_name_libdns (const char *name, unsigned short port,
/* Resolve a name using the standard system function. */
static gpg_error_t
-resolve_name_standard (const char *name, unsigned short port,
+resolve_name_standard (ctrl_t ctrl, const char *name, unsigned short port,
int want_family, int want_socktype,
dns_addrinfo_t *r_dai, char **r_canonname)
{
@@ -981,7 +991,7 @@ resolve_name_standard (const char *name, unsigned short port,
CNAME redirection again. */
char *cname;
- if (get_dns_cname (name, &cname))
+ if (get_dns_cname (ctrl, name, &cname))
goto leave; /* Still no success. */
ret = getaddrinfo (cname, *portstr? portstr : NULL, &hints, &aibuf);
@@ -1046,18 +1056,19 @@ resolve_name_standard (const char *name, unsigned short port,
/* This a wrapper around getaddrinfo with slightly different semantics.
- NAME is the name to resolve.
- PORT is the requested port or 0.
- WANT_FAMILY is either 0 (AF_UNSPEC), AF_INET6, or AF_INET4.
- WANT_SOCKETTYPE is either SOCK_STREAM or SOCK_DGRAM.
-
- On success the result is stored in a linked list with the head
- stored at the address R_AI; the caller must call gpg_addrinfo_free
- on this. If R_CANONNAME is not NULL the official name of the host
- is stored there as a malloced string; if that name is not available
- NULL is stored. */
+ * NAME is the name to resolve.
+ * PORT is the requested port or 0.
+ * WANT_FAMILY is either 0 (AF_UNSPEC), AF_INET6, or AF_INET4.
+ * WANT_SOCKETTYPE is either 0 for any socket type
+ * or SOCK_STREAM or SOCK_DGRAM.
+ *
+ * On success the result is stored in a linked list with the head
+ * stored at the address R_AI; the caller must call free_dns_addrinfo
+ * on this. If R_CANONNAME is not NULL the official name of the host
+ * is stored there as a malloced string; if that name is not available
+ * NULL is stored. */
gpg_error_t
-resolve_dns_name (const char *name, unsigned short port,
+resolve_dns_name (ctrl_t ctrl, const char *name, unsigned short port,
int want_family, int want_socktype,
dns_addrinfo_t *r_ai, char **r_canonname)
{
@@ -1066,15 +1077,15 @@ resolve_dns_name (const char *name, unsigned short port,
#ifdef USE_LIBDNS
if (!standard_resolver)
{
- err = resolve_name_libdns (name, port, want_family, want_socktype,
+ err = resolve_name_libdns (ctrl, name, port, want_family, want_socktype,
r_ai, r_canonname);
if (err && libdns_switch_port_p (err))
- err = resolve_name_libdns (name, port, want_family, want_socktype,
+ err = resolve_name_libdns (ctrl, name, port, want_family, want_socktype,
r_ai, r_canonname);
}
else
#endif /*USE_LIBDNS*/
- err = resolve_name_standard (name, port, want_family, want_socktype,
+ err = resolve_name_standard (ctrl, name, port, want_family, want_socktype,
r_ai, r_canonname);
if (opt_debug)
log_debug ("dns: resolve_dns_name(%s): %s\n", name, gpg_strerror (err));
@@ -1085,7 +1096,8 @@ resolve_dns_name (const char *name, unsigned short port,
#ifdef USE_LIBDNS
/* Resolve an address using libdns. */
static gpg_error_t
-resolve_addr_libdns (const struct sockaddr_storage *addr, int addrlen,
+resolve_addr_libdns (ctrl_t ctrl,
+ const struct sockaddr_storage *addr, int addrlen,
unsigned int flags, char **r_name)
{
gpg_error_t err;
@@ -1117,7 +1129,7 @@ resolve_addr_libdns (const struct sockaddr_storage *addr, int addrlen,
goto leave;
- err = libdns_res_open (&res);
+ err = libdns_res_open (ctrl, &res);
if (err)
goto leave;
@@ -1281,7 +1293,8 @@ resolve_addr_standard (const struct sockaddr_storage *addr, int addrlen,
/* A wrapper around getnameinfo. */
gpg_error_t
-resolve_dns_addr (const struct sockaddr_storage *addr, int addrlen,
+resolve_dns_addr (ctrl_t ctrl,
+ const struct sockaddr_storage *addr, int addrlen,
unsigned int flags, char **r_name)
{
gpg_error_t err;
@@ -1290,9 +1303,9 @@ resolve_dns_addr (const struct sockaddr_storage *addr, int addrlen,
/* Note that we divert to the standard resolver for NUMERICHOST. */
if (!standard_resolver && !(flags & DNS_NUMERICHOST))
{
- err = resolve_addr_libdns (addr, addrlen, flags, r_name);
+ err = resolve_addr_libdns (ctrl, addr, addrlen, flags, r_name);
if (err && libdns_switch_port_p (err))
- err = resolve_addr_libdns (addr, addrlen, flags, r_name);
+ err = resolve_addr_libdns (ctrl, addr, addrlen, flags, r_name);
}
else
#endif /*USE_LIBDNS*/
@@ -1390,7 +1403,7 @@ is_onion_address (const char *name)
/* libdns version of get_dns_cert. */
#ifdef USE_LIBDNS
static gpg_error_t
-get_dns_cert_libdns (const char *name, int want_certtype,
+get_dns_cert_libdns (ctrl_t ctrl, const char *name, int want_certtype,
void **r_key, size_t *r_keylen,
unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
{
@@ -1410,7 +1423,7 @@ get_dns_cert_libdns (const char *name, int want_certtype,
: (want_certtype - DNS_CERTTYPE_RRBASE));
- err = libdns_res_open (&res);
+ err = libdns_res_open (ctrl, &res);
if (err)
goto leave;
@@ -1776,7 +1789,7 @@ get_dns_cert_standard (const char *name, int want_certtype,
supported certtypes only records with this certtype are considered
and the first found is returned. (R_KEY,R_KEYLEN) are optional. */
gpg_error_t
-get_dns_cert (const char *name, int want_certtype,
+get_dns_cert (ctrl_t ctrl, const char *name, int want_certtype,
void **r_key, size_t *r_keylen,
unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
{
@@ -1793,10 +1806,10 @@ get_dns_cert (const char *name, int want_certtype,
#ifdef USE_LIBDNS
if (!standard_resolver)
{
- err = get_dns_cert_libdns (name, want_certtype, r_key, r_keylen,
+ err = get_dns_cert_libdns (ctrl, name, want_certtype, r_key, r_keylen,
r_fpr, r_fprlen, r_url);
if (err && libdns_switch_port_p (err))
- err = get_dns_cert_libdns (name, want_certtype, r_key, r_keylen,
+ err = get_dns_cert_libdns (ctrl, name, want_certtype, r_key, r_keylen,
r_fpr, r_fprlen, r_url);
}
else
@@ -1828,7 +1841,8 @@ priosort(const void *a,const void *b)
* R_COUNT. */
#ifdef USE_LIBDNS
static gpg_error_t
-getsrv_libdns (const char *name, struct srventry **list, unsigned int *r_count)
+getsrv_libdns (ctrl_t ctrl,
+ const char *name, struct srventry **list, unsigned int *r_count)
{
gpg_error_t err;
struct dns_resolver *res = NULL;
@@ -1839,7 +1853,7 @@ getsrv_libdns (const char *name, struct srventry **list, unsigned int *r_count)
int derr;
unsigned int srvcount = 0;
- err = libdns_res_open (&res);
+ err = libdns_res_open (ctrl, &res);
if (err)
goto leave;
@@ -2058,7 +2072,8 @@ getsrv_standard (const char *name,
* we do not return NONAME but simply store 0 at R_COUNT. On error an
* error code is returned and 0 stored at R_COUNT. */
gpg_error_t
-get_dns_srv (const char *name, const char *service, const char *proto,
+get_dns_srv (ctrl_t ctrl,
+ const char *name, const char *service, const char *proto,
struct srventry **list, unsigned int *r_count)
{
gpg_error_t err;
@@ -2087,9 +2102,9 @@ get_dns_srv (const char *name, const char *service, const char *proto,
#ifdef USE_LIBDNS
if (!standard_resolver)
{
- err = getsrv_libdns (name, list, &srvcount);
+ err = getsrv_libdns (ctrl, name, list, &srvcount);
if (err && libdns_switch_port_p (err))
- err = getsrv_libdns (name, list, &srvcount);
+ err = getsrv_libdns (ctrl, name, list, &srvcount);
}
else
#endif /*USE_LIBDNS*/
@@ -2194,7 +2209,7 @@ get_dns_srv (const char *name, const char *service, const char *proto,
#ifdef USE_LIBDNS
/* libdns version of get_dns_cname. */
gpg_error_t
-get_dns_cname_libdns (const char *name, char **r_cname)
+get_dns_cname_libdns (ctrl_t ctrl, const char *name, char **r_cname)
{
gpg_error_t err;
struct dns_resolver *res;
@@ -2202,7 +2217,7 @@ get_dns_cname_libdns (const char *name, char **r_cname)
struct dns_cname cname;
int derr;
- err = libdns_res_open (&res);
+ err = libdns_res_open (ctrl, &res);
if (err)
goto leave;
@@ -2347,7 +2362,7 @@ get_dns_cname_standard (const char *name, char **r_cname)
gpg_error_t
-get_dns_cname (const char *name, char **r_cname)
+get_dns_cname (ctrl_t ctrl, const char *name, char **r_cname)
{
gpg_error_t err;
@@ -2356,9 +2371,9 @@ get_dns_cname (const char *name, char **r_cname)
#ifdef USE_LIBDNS
if (!standard_resolver)
{
- err = get_dns_cname_libdns (name, r_cname);
+ err = get_dns_cname_libdns (ctrl, name, r_cname);
if (err && libdns_switch_port_p (err))
- err = get_dns_cname_libdns (name, r_cname);
+ err = get_dns_cname_libdns (ctrl, name, r_cname);
return err;
}
#endif /*USE_LIBDNS*/
diff --git a/dirmngr/dns-stuff.h b/dirmngr/dns-stuff.h
index 612b2e5f5..06a43122a 100644
--- a/dirmngr/dns-stuff.h
+++ b/dirmngr/dns-stuff.h
@@ -137,12 +137,14 @@ void reload_dns_stuff (int force);
void free_dns_addrinfo (dns_addrinfo_t ai);
/* Function similar to getaddrinfo. */
-gpg_error_t resolve_dns_name (const char *name, unsigned short port,
+gpg_error_t resolve_dns_name (ctrl_t ctrl,
+ const char *name, unsigned short port,
int want_family, int want_socktype,
dns_addrinfo_t *r_dai, char **r_canonname);
/* Function similar to getnameinfo. */
-gpg_error_t resolve_dns_addr (const struct sockaddr_storage *addr, int addrlen,
+gpg_error_t resolve_dns_addr (ctrl_t ctrl,
+ const struct sockaddr_storage *addr, int addrlen,
unsigned int flags, char **r_name);
/* Return true if NAME is a numerical IP address. */
@@ -152,16 +154,18 @@ int is_ip_address (const char *name);
int is_onion_address (const char *name);
/* Get the canonical name for NAME. */
-gpg_error_t get_dns_cname (const char *name, char **r_cname);
+gpg_error_t get_dns_cname (ctrl_t ctrl, const char *name, char **r_cname);
/* Return a CERT record or an arbitrary RR. */
-gpg_error_t get_dns_cert (const char *name, int want_certtype,
+gpg_error_t get_dns_cert (ctrl_t ctrl,
+ const char *name, int want_certtype,
void **r_key, size_t *r_keylen,
unsigned char **r_fpr, size_t *r_fprlen,
char **r_url);
/* Return an array of SRV records. */
-gpg_error_t get_dns_srv (const char *name,
+gpg_error_t get_dns_srv (ctrl_t ctrl,
+ const char *name,
const char *service, const char *proto,
struct srventry **list, unsigned int *r_count);
diff --git a/dirmngr/dns.c b/dirmngr/dns.c
index 77f83f437..596e81fc9 100644
--- a/dirmngr/dns.c
+++ b/dirmngr/dns.c
@@ -1832,7 +1832,7 @@ static void dns_p_free(struct dns_packet *P) {
} /* dns_p_free() */
-/* convience routine to free any existing packet before storing new packet */
+/* convenience routine to free any existing packet before storing new packet */
static struct dns_packet *dns_p_setptr(struct dns_packet **dst, struct dns_packet *src) {
dns_p_free(*dst);
@@ -7634,7 +7634,7 @@ retry:
goto udp_connect_retry;
} else if (error == ECONNREFUSED)
/* Error for previous socket operation may
- be reserverd asynchronously. */
+ be reserverd(?) asynchronously. */
goto udp_connect_retry;
if (error)
diff --git a/dirmngr/domaininfo.c b/dirmngr/domaininfo.c
index a2effffef..f6263b06d 100644
--- a/dirmngr/domaininfo.c
+++ b/dirmngr/domaininfo.c
@@ -119,7 +119,7 @@ domaininfo_print_stats (void)
}
-/* Return true if DOMAIN definitely does not support WKD. Noet that
+/* Return true if DOMAIN definitely does not support WKD. Note that
* DOMAIN is expected to be lowercase. */
int
domaininfo_is_wkd_not_supported (const char *domain)
diff --git a/dirmngr/http-ntbtls.c b/dirmngr/http-ntbtls.c
index ed4cdd496..924b8b25f 100644
--- a/dirmngr/http-ntbtls.c
+++ b/dirmngr/http-ntbtls.c
@@ -55,7 +55,7 @@ gnupg_http_tls_verify_cb (void *opaque,
log_assert (ctrl && ctrl->magic == SERVER_CONTROL_MAGIC);
log_assert (!ntbtls_check_context (tls));
- /* Get the peer's certs fron ntbtls. */
+ /* Get the peer's certs from ntbtls. */
for (idx = 0;
(cert = ntbtls_x509_get_peer_cert (tls, idx)); idx++)
{
diff --git a/dirmngr/http.c b/dirmngr/http.c
index 049aefc29..5fb7eed04 100644
--- a/dirmngr/http.c
+++ b/dirmngr/http.c
@@ -2,7 +2,7 @@
* Copyright (C) 1999, 2001, 2002, 2003, 2004, 2006, 2009, 2010,
* 2011 Free Software Foundation, Inc.
* Copyright (C) 2014 Werner Koch
- * Copyright (C) 2015-2017 g10 Code GmbH
+ * Copyright (C) 2015-2018 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -152,14 +152,15 @@ static int remove_escapes (char *string);
static int insert_escapes (char *buffer, const char *string,
const char *special);
static uri_tuple_t parse_tuple (char *string);
-static gpg_error_t send_request (http_t hd, const char *httphost,
+static gpg_error_t send_request (ctrl_t ctrl, http_t hd, const char *httphost,
const char *auth,const char *proxy,
const char *srvtag, unsigned int timeout,
strlist_t headers);
static char *build_rel_path (parsed_uri_t uri);
static gpg_error_t parse_response (http_t hd);
-static gpg_error_t connect_server (const char *server, unsigned short port,
+static gpg_error_t connect_server (ctrl_t ctrl,
+ const char *server, unsigned short port,
unsigned int flags, const char *srvtag,
unsigned int timeout, assuan_fd_t *r_sock);
static gpgrt_ssize_t read_server (assuan_fd_t sock, void *buffer, size_t size);
@@ -937,7 +938,7 @@ http_session_set_timeout (http_session_t sess, unsigned int timeout)
If HTTPHOST is not NULL it is used for the Host header instead of a
Host header derived from the URL. */
gpg_error_t
-http_open (http_t *r_hd, http_req_t reqtype, const char *url,
+http_open (ctrl_t ctrl, http_t *r_hd, http_req_t reqtype, const char *url,
const char *httphost,
const char *auth, unsigned int flags, const char *proxy,
http_session_t session, const char *srvtag, strlist_t headers)
@@ -961,7 +962,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
err = parse_uri (&hd->uri, url, 0, !!(flags & HTTP_FLAG_FORCE_TLS));
if (!err)
- err = send_request (hd, httphost, auth, proxy, srvtag,
+ err = send_request (ctrl, hd, httphost, auth, proxy, srvtag,
hd->session? hd->session->connect_timeout : 0,
headers);
@@ -985,7 +986,8 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
this http abstraction layer. This has the advantage of providing
service tags and an estream interface. TIMEOUT is in milliseconds. */
gpg_error_t
-http_raw_connect (http_t *r_hd, const char *server, unsigned short port,
+http_raw_connect (ctrl_t ctrl, http_t *r_hd,
+ const char *server, unsigned short port,
unsigned int flags, const char *srvtag, unsigned int timeout)
{
gpg_error_t err = 0;
@@ -1021,7 +1023,8 @@ http_raw_connect (http_t *r_hd, const char *server, unsigned short port,
{
assuan_fd_t sock;
- err = connect_server (server, port, hd->flags, srvtag, timeout, &sock);
+ err = connect_server (ctrl, server, port,
+ hd->flags, srvtag, timeout, &sock);
if (err)
{
xfree (hd);
@@ -1174,14 +1177,14 @@ http_wait_response (http_t hd)
be used as an HTTP proxy and any enabled $http_proxy gets
ignored. */
gpg_error_t
-http_open_document (http_t *r_hd, const char *document,
+http_open_document (ctrl_t ctrl, http_t *r_hd, const char *document,
const char *auth, unsigned int flags, const char *proxy,
http_session_t session,
const char *srvtag, strlist_t headers)
{
gpg_error_t err;
- err = http_open (r_hd, HTTP_REQ_GET, document, NULL, auth, flags,
+ err = http_open (ctrl, r_hd, HTTP_REQ_GET, document, NULL, auth, flags,
proxy, session, srvtag, headers);
if (err)
return err;
@@ -1712,7 +1715,7 @@ is_hostname_port (const char *string)
* Returns 0 if the request was successful
*/
static gpg_error_t
-send_request (http_t hd, const char *httphost, const char *auth,
+send_request (ctrl_t ctrl, http_t hd, const char *httphost, const char *auth,
const char *proxy, const char *srvtag, unsigned int timeout,
strlist_t headers)
{
@@ -1859,14 +1862,16 @@ send_request (http_t hd, const char *httphost, const char *auth,
}
}
- err = connect_server (*uri->host ? uri->host : "localhost",
+ err = connect_server (ctrl,
+ *uri->host ? uri->host : "localhost",
uri->port ? uri->port : 80,
hd->flags, NULL, timeout, &sock);
http_release_parsed_uri (uri);
}
else
{
- err = connect_server (server, port, hd->flags, srvtag, timeout, &sock);
+ err = connect_server (ctrl,
+ server, port, hd->flags, srvtag, timeout, &sock);
}
if (err)
@@ -2870,7 +2875,7 @@ connect_with_timeout (assuan_fd_t sock,
* function tries to connect to all known addresses and the timeout is
* for each one. */
static gpg_error_t
-connect_server (const char *server, unsigned short port,
+connect_server (ctrl_t ctrl, const char *server, unsigned short port,
unsigned int flags, const char *srvtag, unsigned int timeout,
assuan_fd_t *r_sock)
{
@@ -2923,7 +2928,7 @@ connect_server (const char *server, unsigned short port,
/* Do the SRV thing */
if (srvtag)
{
- err = get_dns_srv (server, srvtag, NULL, &serverlist, &srvcount);
+ err = get_dns_srv (ctrl, server, srvtag, NULL, &serverlist, &srvcount);
if (err)
log_info ("getting '%s' SRV for '%s' failed: %s\n",
srvtag, server, gpg_strerror (err));
@@ -2953,7 +2958,8 @@ connect_server (const char *server, unsigned short port,
if (opt_debug)
log_debug ("http.c:connect_server: trying name='%s' port=%hu\n",
serverlist[srv].target, port);
- err = resolve_dns_name (serverlist[srv].target, port, 0, SOCK_STREAM,
+ err = resolve_dns_name (ctrl,
+ serverlist[srv].target, port, 0, SOCK_STREAM,
&aibuf, NULL);
if (err)
{
diff --git a/dirmngr/http.h b/dirmngr/http.h
index 4cfb4c890..a86abbee7 100644
--- a/dirmngr/http.h
+++ b/dirmngr/http.h
@@ -135,12 +135,12 @@ gpg_error_t http_parse_uri (parsed_uri_t *ret_uri, const char *uri,
void http_release_parsed_uri (parsed_uri_t uri);
-gpg_error_t http_raw_connect (http_t *r_hd,
+gpg_error_t http_raw_connect (ctrl_t ctrl, http_t *r_hd,
const char *server, unsigned short port,
unsigned int flags, const char *srvtag,
unsigned int timeout);
-gpg_error_t http_open (http_t *r_hd, http_req_t reqtype,
+gpg_error_t http_open (ctrl_t ctrl, http_t *r_hd, http_req_t reqtype,
const char *url,
const char *httphost,
const char *auth,
@@ -156,7 +156,7 @@ gpg_error_t http_wait_response (http_t hd);
void http_close (http_t hd, int keep_read_stream);
-gpg_error_t http_open_document (http_t *r_hd,
+gpg_error_t http_open_document (ctrl_t ctrl, http_t *r_hd,
const char *document,
const char *auth,
unsigned int flags,
diff --git a/dirmngr/ks-action.c b/dirmngr/ks-action.c
index c1ecafb58..3651ca7db 100644
--- a/dirmngr/ks-action.c
+++ b/dirmngr/ks-action.c
@@ -88,7 +88,7 @@ ks_action_help (ctrl_t ctrl, const char *url)
return err;
}
- /* Call all engines to give them a chance to print a help sting. */
+ /* Call all engines to give them a chance to print a help string. */
err = ks_hkp_help (ctrl, parsed_uri);
if (!err)
err = ks_http_help (ctrl, parsed_uri);
diff --git a/dirmngr/ks-engine-finger.c b/dirmngr/ks-engine-finger.c
index e53a0ee78..30ede1573 100644
--- a/dirmngr/ks-engine-finger.c
+++ b/dirmngr/ks-engine-finger.c
@@ -82,7 +82,7 @@ ks_finger_fetch (ctrl_t ctrl, parsed_uri_t uri, estream_t *r_fp)
}
*server++ = 0;
- err = http_raw_connect (&http, server, 79,
+ err = http_raw_connect (ctrl, &http, server, 79,
((dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR : 0)
| (opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)
| (opt.disable_ipv6? HTTP_FLAG_IGNORE_IPv6 : 0)),
diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
index 32840e68e..790a8b1c5 100644
--- a/dirmngr/ks-engine-hkp.c
+++ b/dirmngr/ks-engine-hkp.c
@@ -35,6 +35,7 @@
# include <netdb.h>
#endif /*!HAVE_W32_SYSTEM*/
+#include <npth.h>
#include "dirmngr.h"
#include "misc.h"
#include "../common/userids.h"
@@ -108,6 +109,8 @@ struct hostinfo_s
resolved from a pool name and its allocated size.*/
static hostinfo_t *hosttable;
static int hosttable_size;
+/* A mutex used to serialize access to the hosttable. */
+static npth_mutex_t hosttable_lock;
/* The number of host slots we initially allocate for HOSTTABLE. */
#define INITIAL_HOSTTABLE_SIZE 50
@@ -304,7 +307,7 @@ tor_not_running_p (ctrl_t ctrl)
PROTOCOL. If NAME specifies a pool (as indicated by IS_POOL),
update the given reference table accordingly. */
static void
-add_host (const char *name, int is_pool,
+add_host (ctrl_t ctrl, const char *name, int is_pool,
const dns_addrinfo_t ai,
enum ks_protocol protocol, unsigned short port)
{
@@ -320,7 +323,7 @@ add_host (const char *name, int is_pool,
if (is_pool)
{
/* For a pool immediately convert the address to a string. */
- tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
+ tmperr = resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
(DNS_NUMERICHOST | DNS_WITHBRACKET), &tmphost);
}
else if (!is_ip_address (name))
@@ -337,7 +340,7 @@ add_host (const char *name, int is_pool,
{
/* Do a PTR lookup on AI. If a name was not found the function
* returns the numeric address (with brackets). */
- tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
+ tmperr = resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
DNS_WITHBRACKET, &tmphost);
}
@@ -498,7 +501,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
unsigned int srvscount;
/* Check for SRV records. */
- err = get_dns_srv (name, srvtag, NULL, &srvs, &srvscount);
+ err = get_dns_srv (ctrl, name, srvtag, NULL, &srvs, &srvscount);
if (err)
{
if (gpg_err_code (err) == GPG_ERR_ECONNREFUSED)
@@ -514,13 +517,13 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
for (i = 0; i < srvscount; i++)
{
- err = resolve_dns_name (srvs[i].target, 0,
+ err = resolve_dns_name (ctrl, srvs[i].target, 0,
AF_UNSPEC, SOCK_STREAM,
&ai, &cname);
if (err)
continue;
dirmngr_tick (ctrl);
- add_host (name, is_pool, ai, protocol, srvs[i].port);
+ add_host (ctrl, name, is_pool, ai, protocol, srvs[i].port);
new_hosts = 1;
}
@@ -535,7 +538,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
{
/* Find all A records for this entry and put them into the pool
list - if any. */
- err = resolve_dns_name (name, 0, 0, SOCK_STREAM, &aibuf, &cname);
+ err = resolve_dns_name (ctrl, name, 0, 0, SOCK_STREAM, &aibuf, &cname);
if (err)
{
log_error ("resolving '%s' failed: %s\n", name, gpg_strerror (err));
@@ -566,7 +569,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
continue;
dirmngr_tick (ctrl);
- add_host (name, is_pool, ai, 0, 0);
+ add_host (ctrl, name, is_pool, ai, 0, 0);
new_hosts = 1;
}
@@ -624,7 +627,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
* hosttable. */
char *host;
- err = resolve_dns_name (hi->name, 0, 0, SOCK_STREAM, &aibuf, NULL);
+ err = resolve_dns_name (ctrl, hi->name, 0, 0, SOCK_STREAM, &aibuf, NULL);
if (!err)
{
for (ai = aibuf; ai; ai = ai->next)
@@ -632,7 +635,8 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
if ((!opt.disable_ipv6 && ai->family == AF_INET6)
|| (!opt.disable_ipv4 && ai->family == AF_INET))
{
- err = resolve_dns_addr (ai->addr, ai->addrlen, 0, &host);
+ err = resolve_dns_addr (ctrl,
+ ai->addr, ai->addrlen, 0, &host);
if (!err)
{
/* Okay, we return the first found name. */
@@ -755,9 +759,15 @@ ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
if (!name || !*name || !strcmp (name, "localhost"))
return 0;
+ if (npth_mutex_lock (&hosttable_lock))
+ log_fatal ("failed to acquire mutex\n");
+
idx = find_hostinfo (name);
if (idx == -1)
- return gpg_error (GPG_ERR_NOT_FOUND);
+ {
+ err = gpg_error (GPG_ERR_NOT_FOUND);
+ goto leave;
+ }
hi = hosttable[idx];
if (alive && hi->dead)
@@ -816,6 +826,10 @@ ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
}
}
+ leave:
+ if (npth_mutex_unlock (&hosttable_lock))
+ log_fatal ("failed to release mutex\n");
+
return err;
}
@@ -836,7 +850,9 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
if (err)
return err;
- /* FIXME: We need a lock for the hosttable. */
+ if (npth_mutex_lock (&hosttable_lock))
+ log_fatal ("failed to acquire mutex\n");
+
curtime = gnupg_get_time ();
for (idx=0; idx < hosttable_size; idx++)
if ((hi=hosttable[idx]))
@@ -865,7 +881,7 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
/* Turn the numerical IP address string into an AI and
* then do a DNS PTR lookup. */
- if (!resolve_dns_name (hi->name, 0, 0,
+ if (!resolve_dns_name (ctrl, hi->name, 0, 0,
SOCK_STREAM,
&aibuf, &canon))
{
@@ -876,7 +892,7 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
}
for (ai = aibuf; !canon && ai; ai = ai->next)
{
- resolve_dns_addr (ai->addr, ai->addrlen,
+ resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
DNS_WITHBRACKET, &canon);
if (canon && is_ip_address (canon))
{
@@ -896,14 +912,14 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
/* Get the IP address as a string from a name. Note
* that resolve_dns_addr allocates CANON on success
* and thus terminates the loop. */
- if (!resolve_dns_name (hi->name, 0,
+ if (!resolve_dns_name (ctrl, hi->name, 0,
hi->v6? AF_INET6 : AF_INET,
SOCK_STREAM,
&aibuf, NULL))
{
for (ai = aibuf; !canon && ai; ai = ai->next)
{
- resolve_dns_addr (ai->addr, ai->addrlen,
+ resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
DNS_NUMERICHOST|DNS_WITHBRACKET,
&canon);
}
@@ -929,12 +945,12 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
diedstr? ")":"" );
xfree (died);
if (err)
- return err;
+ goto leave;
if (hi->cname)
err = ks_printf_help (ctrl, " . %s", hi->cname);
if (err)
- return err;
+ goto leave;
if (hi->pool)
{
@@ -949,14 +965,21 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
put_membuf( &mb, "", 1);
p = get_membuf (&mb, NULL);
if (!p)
- return gpg_error_from_syserror ();
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
err = ks_print_help (ctrl, p);
xfree (p);
if (err)
- return err;
+ goto leave;
}
}
- return 0;
+
+ leave:
+ if (npth_mutex_unlock (&hosttable_lock))
+ log_fatal ("failed to release mutex\n");
+ return err;
}
@@ -1025,9 +1048,16 @@ make_host_part (ctrl_t ctrl,
protocol = KS_PROTOCOL_HKP;
}
+ if (npth_mutex_lock (&hosttable_lock))
+ log_fatal ("failed to acquire mutex\n");
+
portstr[0] = 0;
err = map_host (ctrl, host, srvtag, force_reselect, protocol,
&hostname, portstr, r_httpflags, r_httphost);
+
+ if (npth_mutex_unlock (&hosttable_lock))
+ log_fatal ("failed to release mutex\n");
+
if (err)
return err;
@@ -1101,6 +1131,9 @@ ks_hkp_housekeeping (time_t curtime)
int idx;
hostinfo_t hi;
+ if (npth_mutex_lock (&hosttable_lock))
+ log_fatal ("failed to acquire mutex\n");
+
for (idx=0; idx < hosttable_size; idx++)
{
hi = hosttable[idx];
@@ -1117,6 +1150,9 @@ ks_hkp_housekeeping (time_t curtime)
log_info ("resurrected host '%s'", hi->name);
}
}
+
+ if (npth_mutex_unlock (&hosttable_lock))
+ log_fatal ("failed to release mutex\n");
}
@@ -1128,6 +1164,9 @@ ks_hkp_reload (void)
int idx, count;
hostinfo_t hi;
+ if (npth_mutex_lock (&hosttable_lock))
+ log_fatal ("failed to acquire mutex\n");
+
for (idx=count=0; idx < hosttable_size; idx++)
{
hi = hosttable[idx];
@@ -1141,6 +1180,9 @@ ks_hkp_reload (void)
}
if (count)
log_info ("number of resurrected hosts: %d", count);
+
+ if (npth_mutex_unlock (&hosttable_lock))
+ log_fatal ("failed to release mutex\n");
}
@@ -1182,7 +1224,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
http_session_set_timeout (session, ctrl->timeout);
once_more:
- err = http_open (&http,
+ err = http_open (ctrl, &http,
post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
request,
httphost,
@@ -1339,7 +1381,7 @@ handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
int retry = 0;
/* Fixme: Should we disable all hosts of a protocol family if a
- * request for an address of that familiy returned ENETDOWN? */
+ * request for an address of that family returned ENETDOWN? */
switch (gpg_err_code (err))
{
@@ -1493,7 +1535,11 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
goto again;
}
if (err)
- goto leave;
+ {
+ if (gpg_err_code (err) == GPG_ERR_NO_DATA)
+ dirmngr_status (ctrl, "SOURCE", hostport, NULL);
+ goto leave;
+ }
err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
if (err)
@@ -1628,7 +1674,11 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
goto again;
}
if (err)
- goto leave;
+ {
+ if (gpg_err_code (err) == GPG_ERR_NO_DATA)
+ dirmngr_status (ctrl, "SOURCE", hostport, NULL);
+ goto leave;
+ }
err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
if (err)
@@ -1748,3 +1798,13 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
xfree (httphost);
return err;
}
+
+void
+ks_hkp_init (void)
+{
+ int err;
+
+ err = npth_mutex_init (&hosttable_lock, NULL);
+ if (err)
+ log_fatal ("error initializing mutex: %s\n", strerror (err));
+}
diff --git a/dirmngr/ks-engine-http.c b/dirmngr/ks-engine-http.c
index 946c92769..9e6b9e1f5 100644
--- a/dirmngr/ks-engine-http.c
+++ b/dirmngr/ks-engine-http.c
@@ -103,7 +103,7 @@ ks_http_fetch (ctrl_t ctrl, const char *url, unsigned int flags,
http_session_set_timeout (session, ctrl->timeout);
*r_fp = NULL;
- err = http_open (&http,
+ err = http_open (ctrl, &http,
HTTP_REQ_GET,
url,
/* httphost */ NULL,
diff --git a/dirmngr/ks-engine-ldap.c b/dirmngr/ks-engine-ldap.c
index f50ba50d0..d94bd5e25 100644
--- a/dirmngr/ks-engine-ldap.c
+++ b/dirmngr/ks-engine-ldap.c
@@ -1694,26 +1694,16 @@ extract_attributes (LDAPMod ***modlist, char *line)
if (is_pub || is_sub)
{
- char *size = fields[2];
- int val = atoi (size);
- size = NULL;
+ char padded[6];
+ int val;
- if (val > 0)
- {
- /* We zero pad this on the left to make PGP happy. */
- char padded[6];
- if (val < 99999 && val > 0)
- {
- snprintf (padded, sizeof padded, "%05u", val);
- size = padded;
- }
- }
-
- if (size)
- {
- if (is_pub || is_sub)
- modlist_add (modlist, "pgpKeySize", size);
- }
+ val = atoi (fields[2]);
+ if (val < 99999 && val > 0)
+ {
+ /* We zero pad this on the left to make PGP happy. */
+ snprintf (padded, sizeof padded, "%05u", val);
+ modlist_add (modlist, "pgpKeySize", padded);
+ }
}
if (is_pub)
@@ -1736,10 +1726,7 @@ extract_attributes (LDAPMod ***modlist, char *line)
}
if (algo)
- {
- if (is_pub)
- modlist_add (modlist, "pgpKeyType", algo);
- }
+ modlist_add (modlist, "pgpKeyType", algo);
}
if (is_pub || is_sub || is_sig)
diff --git a/dirmngr/ldap.c b/dirmngr/ldap.c
index cb3c0b763..a04bb97a2 100644
--- a/dirmngr/ldap.c
+++ b/dirmngr/ldap.c
@@ -388,7 +388,7 @@ parse_one_pattern (const char *pattern)
}
/* Take the string STRING and escape it according to the URL rules.
- Retun a newly allocated string. */
+ Return a newly allocated string. */
static char *
escape4url (const char *string)
{
diff --git a/dirmngr/misc.c b/dirmngr/misc.c
index 1270b834d..9cedf911c 100644
--- a/dirmngr/misc.c
+++ b/dirmngr/misc.c
@@ -515,7 +515,7 @@ host_and_port_from_url (const char *url, int *port)
if ((p = strchr (buf, '/')))
*p++ = 0;
strlwr (buf);
- if ((p = strchr (p, ':')))
+ if ((p = strchr (buf, ':')))
{
*p++ = 0;
*port = atoi (p);
@@ -637,7 +637,7 @@ armor_data (char **r_string, const void *data, size_t datalen)
}
-/* Copy all data from IN to OUT. OUT may be NULL to use this fucntion
+/* Copy all data from IN to OUT. OUT may be NULL to use this function
* as a dummy reader. */
gpg_error_t
copy_stream (estream_t in, estream_t out)
diff --git a/dirmngr/ocsp.c b/dirmngr/ocsp.c
index 22391c32d..79c252d87 100644
--- a/dirmngr/ocsp.c
+++ b/dirmngr/ocsp.c
@@ -172,7 +172,7 @@ do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_md_hd_t md,
}
once_more:
- err = http_open (&http, HTTP_REQ_POST, url, NULL, NULL,
+ err = http_open (ctrl, &http, HTTP_REQ_POST, url, NULL, NULL,
((opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
| (dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR:0)
| (opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)
@@ -343,7 +343,7 @@ validate_responder_cert (ctrl_t ctrl, ksba_cert_t cert,
Note, that in theory we could simply ask the client via an
inquire to validate a certificate but this might involve
- calling DirMngr again recursivly - we can't do that as of now
+ calling DirMngr again recursively - we can't do that as of now
(neither DirMngr nor gpgsm have the ability for concurrent
access to DirMngr. */
@@ -391,7 +391,7 @@ check_signature_core (ctrl_t ctrl, ksba_cert_t cert, gcry_sexp_t s_sig,
}
-/* Check the signature of an OCSP repsonse. OCSP is the context,
+/* Check the signature of an OCSP response. OCSP is the context,
S_SIG the signature value and MD the handle of the hash we used for
the response. This function automagically finds the correct public
key. If SIGNER_FPR_LIST is not NULL, the default OCSP reponder has been
@@ -653,6 +653,33 @@ ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr,
if (err)
goto leave;
+ /* It is sometimes useful to know the responder ID. */
+ if (opt.verbose)
+ {
+ char *resp_name;
+ ksba_sexp_t resp_keyid;
+
+ err = ksba_ocsp_get_responder_id (ocsp, &resp_name, &resp_keyid);
+ if (err)
+ log_info (_("error getting responder ID: %s\n"), gpg_strerror (err));
+ else
+ {
+ log_info ("responder id: ");
+ if (resp_name)
+ log_printf ("'/%s' ", resp_name);
+ if (resp_keyid)
+ {
+ log_printf ("{");
+ dump_serial (resp_keyid);
+ log_printf ("} ");
+ }
+ log_printf ("\n");
+ }
+ ksba_free (resp_name);
+ ksba_free (resp_keyid);
+ err = 0;
+ }
+
/* We got a useful answer, check that the answer has a valid signature. */
sigval = ksba_ocsp_get_sig_val (ocsp, produced_at);
if (!sigval || !*produced_at)
@@ -761,7 +788,7 @@ ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr,
err = gpg_error (GPG_ERR_TIME_CONFLICT);
}
- /* Check that we are not beyound NEXT_UPDATE (plus some extra time). */
+ /* Check that we are not beyond NEXT_UPDATE (plus some extra time). */
if (*next_update)
{
gnupg_copy_time (tmp_time, next_update);
diff --git a/dirmngr/server.c b/dirmngr/server.c
index b7cdb24c9..4a242539b 100644
--- a/dirmngr/server.c
+++ b/dirmngr/server.c
@@ -666,7 +666,7 @@ static const char hlp_dns_cert[] =
static gpg_error_t
cmd_dns_cert (assuan_context_t ctx, char *line)
{
- /* ctrl_t ctrl = assuan_get_pointer (ctx); */
+ ctrl_t ctrl = assuan_get_pointer (ctx);
gpg_error_t err = 0;
int pka_mode, dane_mode;
char *mbox = NULL;
@@ -731,7 +731,7 @@ cmd_dns_cert (assuan_context_t ctx, char *line)
/* We lowercase ascii characters but the DANE I-D does not allow
this. FIXME: Check after the release of the RFC whether to
change this. */
- mbox = mailbox_from_userid (line);
+ mbox = mailbox_from_userid (line, 0);
if (!mbox || !(domain = strchr (mbox, '@')))
{
err = set_error (GPG_ERR_INV_USER_ID, "no mailbox in user id");
@@ -782,7 +782,7 @@ cmd_dns_cert (assuan_context_t ctx, char *line)
else
name = line;
- err = get_dns_cert (name, certtype, &key, &keylen, &fpr, &fprlen, &url);
+ err = get_dns_cert (ctrl, name, certtype, &key, &keylen, &fpr, &fprlen, &url);
if (err)
goto leave;
@@ -837,8 +837,11 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
gpg_error_t err = 0;
char *mbox = NULL;
char *domainbuf = NULL;
- char *domain; /* Points to mbox or domainbuf. */
- char *domain_orig;/* Points to mbox. */
+ char *domain; /* Points to mbox or domainbuf. This is used to
+ * connect to the host. */
+ char *domain_orig;/* Points to mbox. This is the used for the
+ * query; i.e. the domain part of the
+ * addrspec. */
char sha1buf[20];
char *uri = NULL;
char *encodedhash = NULL;
@@ -847,6 +850,7 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
int is_wkd_query; /* True if this is a real WKD query. */
int no_log = 0;
char portstr[20] = { 0 };
+ int subdomain_mode = 0;
opt_submission_addr = has_option (line, "--submission-address");
opt_policy_flags = has_option (line, "--policy-flags");
@@ -855,7 +859,7 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
line = skip_options (line);
is_wkd_query = !(opt_policy_flags || opt_submission_addr);
- mbox = mailbox_from_userid (line);
+ mbox = mailbox_from_userid (line, 0);
if (!mbox || !(domain = strchr (mbox, '@')))
{
err = set_error (GPG_ERR_INV_USER_ID, "no mailbox in user id");
@@ -864,7 +868,8 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
*domain++ = 0;
domain_orig = domain;
- /* First check whether we already know that the domain does not
+
+ /* Let's check whether we already know that the domain does not
* support WKD. */
if (is_wkd_query)
{
@@ -875,18 +880,63 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
}
}
- /* Check for SRV records. */
- if (1)
+
+ /* First try the new "openpgp" subdomain. We check that the domain
+ * is valid because it is later used as an unescaped filename part
+ * of the URI. */
+ if (is_valid_domain_name (domain_orig))
+ {
+ dns_addrinfo_t aibuf;
+
+ domainbuf = strconcat ( "openpgpkey.", domain_orig, NULL);
+ if (!domainbuf)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+
+ /* FIXME: We should put a cache into dns-stuff because the same
+ * query (with a different port and socket type, though) will be
+ * done later by http function. */
+ err = resolve_dns_name (ctrl, domainbuf, 0, 0, 0, &aibuf, NULL);
+ if (err)
+ {
+ err = 0;
+ xfree (domainbuf);
+ domainbuf = NULL;
+ }
+ else /* Got a subdomain. */
+ {
+ free_dns_addrinfo (aibuf);
+ subdomain_mode = 1;
+ domain = domainbuf;
+ }
+ }
+
+ /* Check for SRV records unless we have a subdomain. */
+ if (!subdomain_mode)
{
struct srventry *srvs;
unsigned int srvscount;
size_t domainlen, targetlen;
int i;
- err = get_dns_srv (domain, "openpgpkey", NULL, &srvs, &srvscount);
+ err = get_dns_srv (ctrl, domain, "openpgpkey", NULL, &srvs, &srvscount);
if (err)
goto leave;
+ /* Check for rogue DNS names. */
+ for (i = 0; i < srvscount; i++)
+ {
+ if (!is_valid_domain_name (srvs[i].target))
+ {
+ err = gpg_error (GPG_ERR_DNS_ADDRESS);
+ log_error ("rogue openpgpkey SRV record for '%s'\n", domain);
+ xfree (srvs);
+ goto leave;
+ }
+ }
+
/* Find the first target which also ends in DOMAIN or is equal
* to DOMAIN. */
domainlen = strlen (domain);
@@ -919,6 +969,7 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
xfree (srvs);
}
+ /* Prepare the hash of the local part. */
gcry_md_hash_buffer (GCRY_MD_SHA1, sha1buf, mbox, strlen (mbox));
encodedhash = zb32_encode (sha1buf, 8*20);
if (!encodedhash)
@@ -932,7 +983,10 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
uri = strconcat ("https://",
domain,
portstr,
- "/.well-known/openpgpkey/submission-address",
+ "/.well-known/openpgpkey/",
+ subdomain_mode? domain_orig : "",
+ subdomain_mode? "/" : "",
+ "submission-address",
NULL);
}
else if (opt_policy_flags)
@@ -940,24 +994,39 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
uri = strconcat ("https://",
domain,
portstr,
- "/.well-known/openpgpkey/policy",
+ "/.well-known/openpgpkey/",
+ subdomain_mode? domain_orig : "",
+ subdomain_mode? "/" : "",
+ "policy",
NULL);
}
else
{
- uri = strconcat ("https://",
- domain,
- portstr,
- "/.well-known/openpgpkey/hu/",
- encodedhash,
- NULL);
- no_log = 1;
- if (uri)
+ char *escapedmbox;
+
+ escapedmbox = http_escape_string (mbox, "%;?&=");
+ if (escapedmbox)
{
- err = dirmngr_status_printf (ctrl, "SOURCE", "https://%s%s",
- domain, portstr);
- if (err)
- goto leave;
+ uri = strconcat ("https://",
+ domain,
+ portstr,
+ "/.well-known/openpgpkey/",
+ subdomain_mode? domain_orig : "",
+ subdomain_mode? "/" : "",
+ "hu/",
+ encodedhash,
+ "?l=",
+ escapedmbox,
+ NULL);
+ xfree (escapedmbox);
+ no_log = 1;
+ if (uri)
+ {
+ err = dirmngr_status_printf (ctrl, "SOURCE", "https://%s%s",
+ domain, portstr);
+ if (err)
+ goto leave;
+ }
}
}
if (!uri)
@@ -2668,6 +2737,20 @@ cmd_reloaddirmngr (assuan_context_t ctx, char *line)
}
+static const char hlp_flushcrls[] =
+ "FLUSHCRLS\n"
+ "\n"
+ "Remove all cached CRLs from memory and\n"
+ "the file system.";
+static gpg_error_t
+cmd_flushcrls (assuan_context_t ctx, char *line)
+{
+ (void)line;
+
+ return leave_cmd (ctx, crl_cache_flush () ? GPG_ERR_GENERAL : 0);
+}
+
+
/* Tell the assuan library about our commands. */
static int
@@ -2698,6 +2781,7 @@ register_commands (assuan_context_t ctx)
{ "LOADSWDB", cmd_loadswdb, hlp_loadswdb },
{ "KILLDIRMNGR",cmd_killdirmngr,hlp_killdirmngr },
{ "RELOADDIRMNGR",cmd_reloaddirmngr,hlp_reloaddirmngr },
+ { "FLUSHCRLS", cmd_flushcrls, hlp_flushcrls },
{ NULL, NULL }
};
int i, j, rc;
@@ -2977,7 +3061,7 @@ dirmngr_status_printf (ctrl_t ctrl, const char *keyword,
va_list arg_ptr;
assuan_context_t ctx;
- if (!ctrl->server_local || !(ctx = ctrl->server_local->assuan_ctx))
+ if (!ctrl || !ctrl->server_local || !(ctx = ctrl->server_local->assuan_ctx))
return 0;
va_start (arg_ptr, format);
diff --git a/dirmngr/t-dns-stuff.c b/dirmngr/t-dns-stuff.c
index 5a3ede15b..6d52160bc 100644
--- a/dirmngr/t-dns-stuff.c
+++ b/dirmngr/t-dns-stuff.c
@@ -178,7 +178,7 @@ main (int argc, char **argv)
if (verbose || any_options)
printf ("CERT lookup on '%s'\n", name);
- err = get_dns_cert (name, DNS_CERTTYPE_ANY, &key, &keylen,
+ err = get_dns_cert (NULL, name, DNS_CERTTYPE_ANY, &key, &keylen,
&fpr, &fpr_len, &url);
if (err)
printf ("get_dns_cert failed: %s <%s>\n",
@@ -218,7 +218,7 @@ main (int argc, char **argv)
char *cname;
printf ("CNAME lookup on '%s'\n", name);
- err = get_dns_cname (name, &cname);
+ err = get_dns_cname (NULL, name, &cname);
if (err)
printf ("get_dns_cname failed: %s <%s>\n",
gpg_strerror (err), gpg_strsource (err));
@@ -234,7 +234,7 @@ main (int argc, char **argv)
unsigned int count;
int i;
- err = get_dns_srv (name? name : "_hkp._tcp.wwwkeys.pgp.net",
+ err = get_dns_srv (NULL, name? name : "_hkp._tcp.wwwkeys.pgp.net",
NULL, NULL, &srv, &count);
if (err)
printf ("get_dns_srv failed: %s <%s>\n",
@@ -261,7 +261,7 @@ main (int argc, char **argv)
printf ("Lookup on '%s'\n", name);
- err = resolve_dns_name (name, 0, 0, SOCK_STREAM, &aibuf, &cname);
+ err = resolve_dns_name (NULL, name, 0, 0, SOCK_STREAM, &aibuf, &cname);
if (err)
{
fprintf (stderr, PGM": resolving '%s' failed: %s\n",
@@ -278,7 +278,7 @@ main (int argc, char **argv)
ai->family == AF_INET? "inet4" : "? ",
ai->socktype, ai->protocol);
- err = resolve_dns_addr (ai->addr, ai->addrlen,
+ err = resolve_dns_addr (NULL, ai->addr, ai->addrlen,
(DNS_NUMERICHOST
| (opt_bracket? DNS_WITHBRACKET:0)),
&host);
@@ -290,7 +290,7 @@ main (int argc, char **argv)
xfree (host);
}
- err = resolve_dns_addr (ai->addr, ai->addrlen,
+ err = resolve_dns_addr (NULL, ai->addr, ai->addrlen,
(opt_bracket? DNS_WITHBRACKET:0),
&host);
if (err)
diff --git a/dirmngr/t-http.c b/dirmngr/t-http.c
index 440633db4..8b32613b6 100644
--- a/dirmngr/t-http.c
+++ b/dirmngr/t-http.c
@@ -137,7 +137,7 @@ my_http_tls_verify_cb (void *opaque,
(void)session;
(void)http_flags;
- /* Get the peer's certs fron ntbtls. */
+ /* Get the peer's certs from ntbtls. */
for (idx = 0;
(cert = ntbtls_x509_get_peer_cert (tls_context, idx)); idx++)
{
@@ -438,7 +438,7 @@ main (int argc, char **argv)
if (session)
http_session_set_timeout (session, timeout);
- rc = http_open_document (&hd, *argv, NULL, my_http_flags,
+ rc = http_open_document (NULL, &hd, *argv, NULL, my_http_flags,
NULL, session, NULL, NULL);
if (rc)
{
diff --git a/dirmngr/t-support.c b/dirmngr/t-support.c
new file mode 100644
index 000000000..fc9546a7d
--- /dev/null
+++ b/dirmngr/t-support.c
@@ -0,0 +1,43 @@
+/* t-support.c - Module test support (stubs etc).
+ * Copyright (C) 2018 g10 Code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-3.0+
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+
+#include "../common/util.h"
+#include "dirmngr-status.h"
+#include "t-support.h"
+
+
+
+/* Stub for testing. See server.c for the real implementation. */
+gpg_error_t
+dirmngr_status_printf (ctrl_t ctrl, const char *keyword,
+ const char *format, ...)
+{
+ (void)ctrl;
+ (void)keyword;
+ (void)format;
+
+ return 0;
+}
diff --git a/dirmngr/workqueue.c b/dirmngr/workqueue.c
index 2cb8573e8..a47cdebc8 100644
--- a/dirmngr/workqueue.c
+++ b/dirmngr/workqueue.c
@@ -116,7 +116,7 @@ workqueue_add_task (wqtask_t func, const char *args, unsigned int session_id,
/* Run the task described by ITEM. ITEM must have been detached from
- * the workqueue; its ownership is transferred to this fucntion. */
+ * the workqueue; its ownership is transferred to this function. */
static void
run_a_task (ctrl_t ctrl, wqitem_t item)
{
diff --git a/doc/DETAILS b/doc/DETAILS
index eb6d7dd4b..74a63ef00 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -59,7 +59,7 @@ described here.
- uat :: User attribute (same as user id except for field 10).
- sig :: Signature
- rev :: Revocation signature
- - rvs :: Recocation signature (standalone) [since 2.2.9]
+ - rvs :: Revocation signature (standalone) [since 2.2.9]
- fpr :: Fingerprint (fingerprint is in field 10)
- pkd :: Public key data [*]
- grp :: Keygrip
@@ -126,7 +126,7 @@ described here.
*** Field 4 - Public key algorithm
The values here are those from the OpenPGP specs or if they are
- greather than 255 the algorithm ids as used by Libgcrypt.
+ greater than 255 the algorithm ids as used by Libgcrypt.
*** Field 5 - KeyID
@@ -544,7 +544,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
*** DECRYPTION_KEY <fpr> <fpr2> <otrust>
This line is emitted when a public key decryption succeeded in
providing a session key. <fpr> is the hexified fingerprint of the
- actual key used for descryption. <fpr2> is the fingerprint of the
+ actual key used for decryption. <fpr2> is the fingerprint of the
primary key. <otrust> is the letter with the ownertrust; this is
in general a 'u' which stands for ultimately trusted.
*** DECRYPTION_INFO <mdc_method> <sym_algo> [<aead_algo>]
@@ -700,7 +700,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
- 0 :: No specific reason given
- 1 :: Not Found
- - 2 :: Ambigious specification
+ - 2 :: Ambiguous specification
- 3 :: Wrong key usage
- 4 :: Key revoked
- 5 :: Key expired
@@ -1016,7 +1016,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
- 2 :: bad PIN
*** SC_OP_SUCCESS
- A smart card operaion succeeded. This status is only printed for
+ A smart card operation succeeded. This status is only printed for
certain operation and is mostly useful to check whether a PIN
change really worked.
@@ -1073,7 +1073,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
Deleting a key failed. Reason codes are:
- 1 :: No such key
- 2 :: Must delete secret key first
- - 3 :: Ambigious specification
+ - 3 :: Ambiguous specification
- 4 :: Key is stored on a smartcard.
*** PROGRESS <what> <char> <cur> <total> [<units>]
diff --git a/doc/HACKING b/doc/HACKING
index 17c58269b..4781bf62c 100644
--- a/doc/HACKING
+++ b/doc/HACKING
@@ -150,7 +150,7 @@ Note that such a comment will be removed if the git commit option
if ( 42 == foo )
#+end_src
this is harder to read and modern compilers are pretty good in
- detecing accidential assignments. It is also suggested not to
+ detecing accidental assignments. It is also suggested not to
compare to 0 or NULL but to test the value direct or with a '!';
this makes it easier to see that a boolean test is done.
- We use our own printf style functions like =es_printf=, and
@@ -342,7 +342,7 @@ Note that such a comment will be removed if the git commit option
- g10/main.h :: Prototypes and some constants
- g10/mainproc.c :: Message processing
- g10/armor.c :: Ascii armor filter
- - g10/mdfilter.c :: Filter to calculate hashs
+ - g10/mdfilter.c :: Filter to calculate hashes
- g10/textfilter.c :: Filter to handle CR/LF and trailing white space
- g10/cipher.c :: En-/Decryption filter
- g10/misc.c :: Utility functions
@@ -395,7 +395,7 @@ The *secure versions allocate memory in the secure memory. That is,
swapping out of this memory is avoided and is gets overwritten on
free. Use this for passphrases, session keys and other sensitive
material. This memory set aside for secure memory is linited to a few
-k. In general the function don't print a memeory message and
+k. In general the function don't print a memory message and
terminate the process if there is not enough memory available. The
"try" versions of the functions return NULL instead.
diff --git a/doc/Notes b/doc/Notes
index 19241b7b7..33ef29278 100644
--- a/doc/Notes
+++ b/doc/Notes
@@ -1,5 +1,5 @@
-Add an infor page for watchgnupg.
+Add an info page for watchgnupg.
> * How to mark a CA certificate as trusted.
@@ -57,7 +57,7 @@ or
In general you should first import the root certificates and then down
to the end user certificate. You may put all into one file and gpgsm
-will do the right thing in this case independend of the order.
+will do the right thing in this case independent of the order.
While verifying a signature, all included certificates are
automagically imported.
@@ -82,7 +82,7 @@ you get an output like:
uid:::::::::CN=Werner Koch,OU=test,O=g10 Code,C=de::
uid:::::::::<[email protected]>::
-This should be familar to advanced gpg-users; see doc/DETAILS in gpg
+This should be familiar to advanced gpg-users; see doc/DETAILS in gpg
1.3 (CVS HEAD) for a description of the records. The value in the
"grp" tagged record is the so called keygrip and you should find a
file ~/.gnupg/private-keys-v1.d/C92DB9CFD588ADE846BE3AC4E7A2E1B11A4A2ADB.key
diff --git a/doc/dirmngr.texi b/doc/dirmngr.texi
index 76be5286c..f5910a884 100644
--- a/doc/dirmngr.texi
+++ b/doc/dirmngr.texi
@@ -1096,7 +1096,7 @@ as a binary blob.
@c In the end the same fucntionality is used, albeit hidden by a couple
@c of indirection and argument and result code mangling. It furthere
@c ingetrages OCSP checking depending on options are the way it is
-@c called. GPGSM still uses this command but might eventuall switch over
+@c called. GPGSM still uses this command but might eventually switch over
@c to CHECKCRL and CHECKOCSP so that ISVALID can be retired.
@c
@c
diff --git a/doc/faq.org b/doc/faq.org
index ddbeafaf8..2f873e600 100644
--- a/doc/faq.org
+++ b/doc/faq.org
@@ -1096,7 +1096,7 @@ update this FAQ in the next month. See the section "Changes" for recent updates
As of 1.0.3, keys generated with gpg are created with preferences to
TWOFISH (and AES since 1.0.4) and that also means that they have the
capability to use the new MDC encryption method. This will go into
- OpenPGP soon, and is also suppoted by PGP 7. This new method avoids
+ OpenPGP soon, and is also supported by PGP 7. This new method avoids
a (not so new) attack on all email encryption systems.
This in turn means that pre-1.0.3 gpg binaries have problems with
diff --git a/doc/gpg.texi b/doc/gpg.texi
index 4cfd00079..dedb8cc42 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -624,9 +624,9 @@ fingerprint (preferred) or their keyid.
@end table
-@c *******************************************
-@c ******* KEY MANGEMENT COMMANDS **********
-@c *******************************************
+@c ********************************************
+@c ******* KEY MANAGEMENT COMMANDS **********
+@c ********************************************
@node OpenPGP Key Management
@subsection How to manage your keys
@@ -675,6 +675,10 @@ supplied passphrase is used for the new key and the agent does not ask
for it. To create a key without any protection @code{--passphrase ''}
may be used.
+Note that it is possible to create a primary key and a subkey using
+non-default algorithms by using ``default'' and changing the default
+parameters using the option @option{--default-new-key-algo}.
+
@item --quick-set-expire @var{fpr} @var{expire} [*|@var{subfprs}]
@opindex quick-set-expire
With two arguments given, directly set the expiration time of the
@@ -702,7 +706,8 @@ and other ECC curves. For example the string ``rsa'' adds an RSA key
with the default key length; a string ``rsa4096'' requests that the
key length is 4096 bits. The string ``future-default'' is an alias
for the algorithm which will likely be used as default algorithm in
-future versions of gpg.
+future versions of gpg. To list the supported ECC curves the command
+@code{gpg --with-colons --list-config curve} can be used.
Depending on the given @var{algo} the subkey may either be an
encryption subkey or a signing subkey. If an algorithm is capable of
@@ -1719,7 +1724,8 @@ Set what trust model GnuPG should follow. The models are:
@opindex trust-model:auto
Select the trust model depending on whatever the internal trust
database says. This is the default model if such a database already
- exists.
+ exists. Note that a tofu trust model is not considered here and
+ must be enabled explicitly.
@end table
@item --auto-key-locate @var{mechanisms}
@@ -2258,9 +2264,8 @@ The AEAD encryption mode encrypts the data in chunks so that a
receiving side can check for transmission errors or tampering at the
end of each chunk and does not need to delay this until all data has
been received. The used chunk size is 2^@var{n} byte. The lowest
-allowed value for @var{n} is 6 (64 byte) and the largest is 62 (4
-EiB). The default value for @var{n} is 30 which creates chunks not
-larger than 1 GiB.
+allowed value for @var{n} is 6 (64 byte) and the largest is the
+default of 27 which creates chunks not larger than 128 MiB.
@item --input-size-hint @var{n}
@opindex input-size-hint
@@ -2338,6 +2343,11 @@ opposite meaning. The options are:
on the keyring. This option is the same as running the @option{--edit-key}
command "clean" after import. Defaults to no.
+ @item import-drop-uids
+ Do not import any user ids or their binding signatures. This option
+ can be used to update only the subkeys or other non-user id related
+ information.
+
@item repair-keys. After import, fix various problems with the
keys. For example, this reorders signatures, and strips duplicate
signatures. Defaults to yes.
@@ -2502,6 +2512,11 @@ opposite meaning. The options are:
running the @option{--edit-key} command "minimize" before export except
that the local copy of the key is not modified. Defaults to no.
+ @item export-drop-uids
+ Do no export any user id or attribute packets or their associates
+ signatures. Note that due to missing user ids the resulting output is
+ not strictly RFC-4880 compliant.
+
@item export-pka
Instead of outputting the key material output PKA records suitable
to put into DNS zone files. An ORIGIN line is printed before each
@@ -2608,7 +2623,7 @@ These options are obsolete and have no effect since GnuPG 2.1.
@item --force-aead
@opindex force-aead
Force the use of AEAD encryption over MDC encryption. AEAD is a
-modern and faster way to do authenticated encrytion than the old MDC
+modern and faster way to do authenticated encryption than the old MDC
method. See also options @option{--aead-algo} and
@option{--chunk-size}.
@@ -2621,7 +2636,7 @@ to declare that a not yet standardized feature is used.
@opindex disable-mdc
These options are obsolete and have no effect since GnuPG 2.2.8. The
MDC is always used unless the keys indicate that an AEAD algorithm can
-be used in which case AEAD is used. But note: If the creation or of a
+be used in which case AEAD is used. But note: If the creation of a
legacy non-MDC message is exceptionally required, the option
@option{--rfc2440} allows for this.
@@ -2764,7 +2779,7 @@ This option is obsolete; it is handled as an alias for @option{--pgp7}
@item --pgp7
@opindex pgp7
-Set up all options to be as PGP 7 compliant as possible. This allowd
+Set up all options to be as PGP 7 compliant as possible. This allowed
the ciphers IDEA, 3DES, CAST5,AES128, AES192, AES256, and TWOFISH.,
the hashes MD5, SHA1 and RIPEMD160, and the compression algorithms
none and ZIP. This option implies @option{--escape-from-lines} and
@@ -2862,6 +2877,13 @@ Change the buffer size of the IOBUFs to @var{n} kilobyte. Using 0
prints the current size. Note well: This is a maintainer only option
and may thus be changed or removed at any time without notice.
+@item --debug-allow-large-chunks
+@opindex debug-allow-large-chunks
+To facilitate in-memory decryption on the receiving site, the largest
+recommended chunk size is 128 MiB (@code{--chunk-size 27}). This
+option allows to specify a limit of up to 4 EiB (@code{--chunk-size
+62}) for experiments.
+
@item --faked-system-time @var{epoch}
@opindex faked-system-time
This option is only useful for testing; it sets the system time back or
@@ -2964,6 +2986,13 @@ smartcard, and "%%" results in a single "%". %k, %K, and %f are only
meaningful when making a key signature (certification), and %c is only
meaningful when using the OpenPGP smartcard.
+@item --known-notation @var{name}
+@opindex known-notation
+Adds @var{name} to a list of known critical signature notations. The
+effect of this is that gpg will not mark a signature with a critical
+signature notation of that name as bad. Note that gpg already knows
+by default about a few critical signatures notation names.
+
@item --sig-policy-url @var{string}
@itemx --cert-policy-url @var{string}
@itemx --set-policy-url @var{string}
@@ -3022,7 +3051,7 @@ same thing.
@opindex aead-algo
Specify that the AEAD algorithm @var{name} is to be used. This is
useful for symmetric encryption where no key preference are available
-to select the AEAD algorithm. Runing @command{@gpgname} with option
+to select the AEAD algorithm. Running @command{@gpgname} with option
@option{--version} shows the available AEAD algorithms. In general,
you do not want to use this option as it allows you to violate the
OpenPGP standard. The option @option{--personal-aead-preferences} is
@@ -3340,13 +3369,14 @@ user.
@opindex override-session-key
Don't use the public key but the session key @var{string} respective
the session key taken from the first line read from file descriptor
-@var{fd}. The format of this string is the same as the one printed
-by @option{--show-session-key}. This option is normally not used but
+@var{fd}. The format of this string is the same as the one printed by
+@option{--show-session-key}. This option is normally not used but
comes handy in case someone forces you to reveal the content of an
encrypted message; using this option you can do this without handing
out the secret key. Note that using @option{--override-session-key}
may reveal the session key to all local users via the global process
-table.
+table. Often it is useful to combine this option with
+@option{--no-keyring}.
@item --ask-sig-expire
@itemx --no-ask-sig-expire
@@ -3637,6 +3667,15 @@ Operation is further controlled by a few environment variables:
@end table
+When calling the gpg-agent component @command{@gpgname} sends a set of
+environment variables to gpg-agent. The names of these variables can
+be listed using the command:
+
+@example
+ gpg-connect-agent 'getinfo std_env_names' /bye | awk '$1=="D" @{print $2@}'
+@end example
+
+
@c *******************************************
@c *************** ****************
diff --git a/doc/tools.texi b/doc/tools.texi
index 7becf67e2..6256c05ed 100644
--- a/doc/tools.texi
+++ b/doc/tools.texi
@@ -1561,7 +1561,7 @@ string @code{true} or @code{yes}. The evaluation is done by passing
/subst
/let i 3
/while $i
- /echo loop couter is $i
+ /echo loop counter is $i
/let i $@{- $i 1@}
/end
@end smallexample
@@ -1962,7 +1962,7 @@ Extract all files from an encrypted archive.
@item --sign
@itemx -s
-Make a signed archive from the given files and directories. Thsi can
+Make a signed archive from the given files and directories. This can
be combined with option @option{--encrypt} to create a signed and then
encrypted archive.
@@ -2031,7 +2031,7 @@ linefeed to separate file names.
@item --openpgp
@opindex openpgp
-This option has no effect becuase OpenPGP encryption and signing is
+This option has no effect because OpenPGP encryption and signing is
the default.
@item --cms
diff --git a/doc/wks.texi b/doc/wks.texi
index 4508ae2a1..03d748255 100644
--- a/doc/wks.texi
+++ b/doc/wks.texi
@@ -61,11 +61,12 @@ Service provider. This is usuallay done to upload a key into a Web
Key Directory.
With the @option{--supported} command the caller can test whether a
-site supports the Web Key Service. The argument is an arbitray
+site supports the Web Key Service. The argument is an arbitrary
address in the to be tested domain. For example
@file{foo@@example.net}. The command returns success if the Web Key
Service is supported. The operation is silent; to get diagnostic
-output use the option @option{--verbose}.
+output use the option @option{--verbose}. See option
+@option{--with-colons} for a variant of this command.
With the @option{--check} command the caller can test whether a key
exists for a supplied mail address. The command returns success if a
@@ -109,6 +110,44 @@ $(gpgconf --list-dirs libexecdir)/gpg-wks-client --check foo@@example.net
Directly send created mails using the @command{sendmail} command.
Requires installation of that command.
+@item --with-colons
+@opindex with-colons
+This option has currently only an effect on the @option{--supported}
+command. If it is used all arguimenst on the command line are taken
+as domain names and tested for WKD support. The output format is one
+line per domain with colon delimited fields. The currently specified
+fields are (future versions may specify additional fields):
+
+@table @asis
+
+ @item 1 - domain
+ This is the domain name. Although quoting is not required for valid
+ domain names this field is specified to be quoted in standard C
+ manner.
+
+ @item 2 - WKD
+ If the value is true the domain supports the Web Key Directory.
+
+ @item 3 - WKS
+ If the value is true the domain supports the Web Key Service
+ protocol to upload keys to the directory.
+
+ @item 4 - error-code
+ This may contain an gpg-error code to describe certain
+ failures. Use @samp{gpg-error CODE} to explain the code.
+
+ @item 5 - protocol-version
+ The minimum protocol version supported by the server.
+
+ @item 6 - auth-submit
+ The auth-submit flag from the policy file of the server.
+
+ @item 7 - mailbox-only
+ The mailbox-only flag from the policy file of the server.
+@end table
+
+
+
@item --output @var{file}
@itemx -o
@opindex output
@@ -206,7 +245,7 @@ mail is processed. Commonly this command is used with the option
@option{--send} to directly send the crerated mails back. See below
for an installation example.
-The command @option{--cron} is used for regualr cleanup tasks. For
+The command @option{--cron} is used for regular cleanup tasks. For
example non-confirmed requested should be removed after their expire
time. It is best to run this command once a day from a cronjob.
@@ -215,9 +254,9 @@ Further it creates missing directories for the configuration and
prints warnings pertaining to problems in the configuration.
The command @option{--check-key} (or just @option{--check}) checks
-whether a key with the given user-id is installed. The process return
-success in this case; to also print a diagnostic, use option
-@option{-v}. If the key is not installed a diagnostics is printed and
+whether a key with the given user-id is installed. The process returns
+success in this case; to also print a diagnostic use the option
+@option{-v}. If the key is not installed a diagnostic is printed and
the process returns failure; to suppress the diagnostic, use option
@option{-q}. More than one user-id can be given; see also option
@option{with-file}.
@@ -243,6 +282,12 @@ The command @option{--revoke-key} is not yet functional.
@table @gnupgtabopt
+@item -C @var{dir}
+@itemx --directory @var{dir}
+@opindex directory
+Use @var{dir} as top level directory for domains. The default is
+@file{/var/lib/gnupg/wks}.
+
@item --from @var{mailaddr}
@opindex from
Use @var{mailaddr} as the default sender address.
@@ -256,21 +301,22 @@ Add the mail header "@var{name}: @var{value}" to all outgoing mails.
Directly send created mails using the @command{sendmail} command.
Requires installation of that command.
-@item --output @var{file}
-@itemx -o
+@item -o @var{file}
+@itemx --output @var{file}
@opindex output
Write the created mail also to @var{file}. Note that the value
@code{-} for @var{file} would write it to stdout.
@item --with-dir
@opindex with-dir
-Also print the directory name for each domain listed by command
-@option{--list-domains}.
+When used with the command @option{--list-domains} print for each
+installed domain the domain name and its directory name.
@item --with-file
@opindex with-file
-With command @option{--check-key} print for each user-id, the address,
-'i' for installed key or 'n' for not installed key, and the filename.
+When used with the command @option{--check-key} print for each user-id,
+the address, 'i' for installed key or 'n' for not installed key, and
+the filename.
@item --verbose
@opindex verbose
@@ -316,7 +362,7 @@ Finally run
$ gpg-wks-server --list-domains
@end example
-to create the required sub-directories with the permission set
+to create the required sub-directories with the permissions set
correctly. For each domain a submission address needs to be
configured. All service mails are directed to that address. It can
be the same address for all configured domains, for example:
@@ -326,7 +372,7 @@ be the same address for all configured domains, for example:
$ echo key-submission@@example.net >submission-address
@end example
-The protocol requires that the key to be published is sent with an
+The protocol requires that the key to be published is send with an
encrypted mail to the service. Thus you need to create a key for
the submission address:
diff --git a/doc/yat2m.c b/doc/yat2m.c
index c7bec338f..be0ef17fd 100644
--- a/doc/yat2m.c
+++ b/doc/yat2m.c
@@ -55,7 +55,7 @@
.B whateever you want
@end ifset
- alternativly a special comment may be used:
+ alternatively a special comment may be used:
@c man:.B whatever you want
@@ -704,7 +704,7 @@ write_th (FILE *fp)
/* Process the texinfo command COMMAND (without the leading @) and
- write output if needed to FP. REST is the remainer of the line
+ write output if needed to FP. REST is the remainder of the line
which should either point to an opening brace or to a white space.
The function returns the number of characters already processed
from REST. LEN is the usable length of REST. TABLE_LEVEL is used to
@@ -1197,7 +1197,7 @@ parse_file (const char *fname, FILE *fp, char **section_name, int in_pause)
if (*p == '@' && !strncmp (p+1, "item", 4))
item_indent = p - line; /* Set a new indent level. */
else if (p - line < item_indent)
- item_indent = 0; /* Switch off indention. */
+ item_indent = 0; /* Switch off indentation. */
if (item_indent)
{
diff --git a/g10/Makefile.am b/g10/Makefile.am
index b8b92d702..3b4464364 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -152,6 +152,7 @@ gpg_sources = server.c \
trust.c $(trust_source) $(tofu_source) \
$(card_source) \
exec.c exec.h \
+ key-clean.c key-clean.h \
key-check.c key-check.h
gpg_SOURCES = gpg.c \
diff --git a/g10/armor.c b/g10/armor.c
index cc8096862..972766503 100644
--- a/g10/armor.c
+++ b/g10/armor.c
@@ -1,4 +1,4 @@
-/* armor.c - Armor flter
+/* armor.c - Armor filter
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
* 2007 Free Software Foundation, Inc.
*
@@ -37,17 +37,10 @@
#define MAX_LINELEN 20000
-#define CRCINIT 0xB704CE
-#define CRCPOLY 0X864CFB
-#define CRCUPDATE(a,c) do { \
- a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \
- a &= 0x00ffffff; \
- } while(0)
-static u32 crc_table[256];
-static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789+/";
-static byte asctobin[256]; /* runtime initialized */
+static const byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+static u32 asctobin[4][256]; /* runtime initialized */
static int is_initialized;
@@ -121,9 +114,22 @@ armor_filter_context_t *
new_armor_context (void)
{
armor_filter_context_t *afx;
+ gpg_error_t err;
afx = xcalloc (1, sizeof *afx);
- afx->refcount = 1;
+ if (afx)
+ {
+ err = gcry_md_open (&afx->crc_md, GCRY_MD_CRC24_RFC2440, 0);
+ if (err != 0)
+ {
+ log_error ("gcry_md_open failed for GCRY_MD_CRC24_RFC2440: %s",
+ gpg_strerror (err));
+ xfree (afx);
+ return NULL;
+ }
+
+ afx->refcount = 1;
+ }
return afx;
}
@@ -138,6 +144,7 @@ release_armor_context (armor_filter_context_t *afx)
log_assert (afx->refcount);
if ( --afx->refcount )
return;
+ gcry_md_close (afx->crc_md);
xfree (afx);
}
@@ -161,35 +168,42 @@ push_armor_filter (armor_filter_context_t *afx, iobuf_t iobuf)
static void
initialize(void)
{
- int i, j;
- u32 t;
- byte *s;
-
- /* init the crc lookup table */
- crc_table[0] = 0;
- for(i=j=0; j < 128; j++ ) {
- t = crc_table[j];
- if( t & 0x00800000 ) {
- t <<= 1;
- crc_table[i++] = t ^ CRCPOLY;
- crc_table[i++] = t;
- }
- else {
- t <<= 1;
- crc_table[i++] = t;
- crc_table[i++] = t ^ CRCPOLY;
- }
- }
- /* build the helptable for radix64 to bin conversion */
- for(i=0; i < 256; i++ )
- asctobin[i] = 255; /* used to detect invalid characters */
+ u32 i;
+ const byte *s;
+
+ /* Build the helptable for radix64 to bin conversion. Value 0xffffffff is
+ used to detect invalid characters. */
+ memset (asctobin, 0xff, sizeof(asctobin));
for(s=bintoasc,i=0; *s; s++,i++ )
- asctobin[*s] = i;
+ {
+ asctobin[0][*s] = i << (0 * 6);
+ asctobin[1][*s] = i << (1 * 6);
+ asctobin[2][*s] = i << (2 * 6);
+ asctobin[3][*s] = i << (3 * 6);
+ }
is_initialized=1;
}
+static inline u32
+get_afx_crc (armor_filter_context_t *afx)
+{
+ const byte *crc_buf;
+ u32 crc;
+
+ crc_buf = gcry_md_read (afx->crc_md, GCRY_MD_CRC24_RFC2440);
+
+ crc = crc_buf[0];
+ crc <<= 8;
+ crc |= crc_buf[1];
+ crc <<= 8;
+ crc |= crc_buf[2];
+
+ return crc;
+}
+
+
/*
* Check whether this is an armored file. See also
* parse-packet.c for details on this code.
@@ -592,7 +606,7 @@ check_input( armor_filter_context_t *afx, IOBUF a )
afx->faked = 1;
else {
afx->inp_checked = 1;
- afx->crc = CRCINIT;
+ gcry_md_reset (afx->crc_md);
afx->idx = 0;
afx->radbuf[0] = 0;
}
@@ -768,7 +782,7 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
}
}
afx->inp_checked = 1;
- afx->crc = CRCINIT;
+ gcry_md_reset (afx->crc_md);
afx->idx = 0;
afx->radbuf[0] = 0;
}
@@ -793,14 +807,14 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
byte *buf, size_t size )
{
byte val;
- int c=0, c2; /*init c because gcc is not clever enough for the continue*/
+ int c;
+ u32 binc;
int checkcrc=0;
int rc = 0;
size_t n = 0;
- int idx, i, onlypad=0;
- u32 crc;
+ int idx, onlypad=0;
+ int skip_fast = 0;
- crc = afx->crc;
idx = afx->idx;
val = afx->radbuf[0];
for( n=0; n < size; ) {
@@ -820,6 +834,122 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
}
again:
+ binc = asctobin[0][c];
+
+ if( binc != 0xffffffffUL )
+ {
+ if( idx == 0 && skip_fast == 0
+ && afx->buffer_pos + (16 - 1) < afx->buffer_len
+ && n + 12 < size)
+ {
+ /* Fast path for radix64 to binary conversion. */
+ u32 b0,b1,b2,b3;
+
+ /* Speculatively load 15 more input bytes. */
+ b0 = binc << (3 * 6);
+ b0 |= asctobin[2][afx->buffer[afx->buffer_pos + 0]];
+ b0 |= asctobin[1][afx->buffer[afx->buffer_pos + 1]];
+ b0 |= asctobin[0][afx->buffer[afx->buffer_pos + 2]];
+ b1 = asctobin[3][afx->buffer[afx->buffer_pos + 3]];
+ b1 |= asctobin[2][afx->buffer[afx->buffer_pos + 4]];
+ b1 |= asctobin[1][afx->buffer[afx->buffer_pos + 5]];
+ b1 |= asctobin[0][afx->buffer[afx->buffer_pos + 6]];
+ b2 = asctobin[3][afx->buffer[afx->buffer_pos + 7]];
+ b2 |= asctobin[2][afx->buffer[afx->buffer_pos + 8]];
+ b2 |= asctobin[1][afx->buffer[afx->buffer_pos + 9]];
+ b2 |= asctobin[0][afx->buffer[afx->buffer_pos + 10]];
+ b3 = asctobin[3][afx->buffer[afx->buffer_pos + 11]];
+ b3 |= asctobin[2][afx->buffer[afx->buffer_pos + 12]];
+ b3 |= asctobin[1][afx->buffer[afx->buffer_pos + 13]];
+ b3 |= asctobin[0][afx->buffer[afx->buffer_pos + 14]];
+
+ /* Check if any of the input bytes were invalid. */
+ if( (b0 | b1 | b2 | b3) != 0xffffffffUL )
+ {
+ /* All 16 bytes are valid. */
+ buf[n + 0] = b0 >> (2 * 8);
+ buf[n + 1] = b0 >> (1 * 8);
+ buf[n + 2] = b0 >> (0 * 8);
+ buf[n + 3] = b1 >> (2 * 8);
+ buf[n + 4] = b1 >> (1 * 8);
+ buf[n + 5] = b1 >> (0 * 8);
+ buf[n + 6] = b2 >> (2 * 8);
+ buf[n + 7] = b2 >> (1 * 8);
+ buf[n + 8] = b2 >> (0 * 8);
+ buf[n + 9] = b3 >> (2 * 8);
+ buf[n + 10] = b3 >> (1 * 8);
+ buf[n + 11] = b3 >> (0 * 8);
+ afx->buffer_pos += 16 - 1;
+ n += 12;
+ continue;
+ }
+ else if( b0 == 0xffffffffUL )
+ {
+ /* byte[1..3] have invalid character(s). Switch to slow
+ path. */
+ skip_fast = 1;
+ }
+ else if( b1 == 0xffffffffUL )
+ {
+ /* byte[4..7] have invalid character(s), first 4 bytes are
+ valid. */
+ buf[n + 0] = b0 >> (2 * 8);
+ buf[n + 1] = b0 >> (1 * 8);
+ buf[n + 2] = b0 >> (0 * 8);
+ afx->buffer_pos += 4 - 1;
+ n += 3;
+ skip_fast = 1;
+ continue;
+ }
+ else if( b2 == 0xffffffffUL )
+ {
+ /* byte[8..11] have invalid character(s), first 8 bytes are
+ valid. */
+ buf[n + 0] = b0 >> (2 * 8);
+ buf[n + 1] = b0 >> (1 * 8);
+ buf[n + 2] = b0 >> (0 * 8);
+ buf[n + 3] = b1 >> (2 * 8);
+ buf[n + 4] = b1 >> (1 * 8);
+ buf[n + 5] = b1 >> (0 * 8);
+ afx->buffer_pos += 8 - 1;
+ n += 6;
+ skip_fast = 1;
+ continue;
+ }
+ else /*if( b3 == 0xffffffffUL )*/
+ {
+ /* byte[12..15] have invalid character(s), first 12 bytes
+ are valid. */
+ buf[n + 0] = b0 >> (2 * 8);
+ buf[n + 1] = b0 >> (1 * 8);
+ buf[n + 2] = b0 >> (0 * 8);
+ buf[n + 3] = b1 >> (2 * 8);
+ buf[n + 4] = b1 >> (1 * 8);
+ buf[n + 5] = b1 >> (0 * 8);
+ buf[n + 6] = b2 >> (2 * 8);
+ buf[n + 7] = b2 >> (1 * 8);
+ buf[n + 8] = b2 >> (0 * 8);
+ afx->buffer_pos += 12 - 1;
+ n += 9;
+ skip_fast = 1;
+ continue;
+ }
+ }
+
+ switch(idx)
+ {
+ case 0: val = binc << 2; break;
+ case 1: val |= (binc>>4)&3; buf[n++]=val;val=(binc<<4)&0xf0;break;
+ case 2: val |= (binc>>2)&15; buf[n++]=val;val=(binc<<6)&0xc0;break;
+ case 3: val |= binc&0x3f; buf[n++] = val; break;
+ }
+ idx = (idx+1) % 4;
+
+ continue;
+ }
+
+ skip_fast = 0;
+
if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
continue;
else if( c == '=' ) { /* pad character: stop */
@@ -850,10 +980,10 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
if (afx->buffer_pos + 6 < afx->buffer_len
&& afx->buffer[afx->buffer_pos + 0] == '3'
&& afx->buffer[afx->buffer_pos + 1] == 'D'
- && asctobin[afx->buffer[afx->buffer_pos + 2]] != 255
- && asctobin[afx->buffer[afx->buffer_pos + 3]] != 255
- && asctobin[afx->buffer[afx->buffer_pos + 4]] != 255
- && asctobin[afx->buffer[afx->buffer_pos + 5]] != 255
+ && asctobin[0][afx->buffer[afx->buffer_pos + 2]] != 0xffffffffUL
+ && asctobin[0][afx->buffer[afx->buffer_pos + 3]] != 0xffffffffUL
+ && asctobin[0][afx->buffer[afx->buffer_pos + 4]] != 0xffffffffUL
+ && asctobin[0][afx->buffer[afx->buffer_pos + 5]] != 0xffffffffUL
&& afx->buffer[afx->buffer_pos + 6] == '\n')
{
afx->buffer_pos += 2;
@@ -868,27 +998,20 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
checkcrc++;
break;
}
- else if( (c = asctobin[(c2=c)]) == 255 ) {
- log_error(_("invalid radix64 character %02X skipped\n"), c2);
+ else {
+ log_error(_("invalid radix64 character %02X skipped\n"), c);
continue;
}
- switch(idx) {
- case 0: val = c << 2; break;
- case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break;
- case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break;
- case 3: val |= c&0x3f; buf[n++] = val; break;
- }
- idx = (idx+1) % 4;
}
- for(i=0; i < n; i++ )
- crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
- crc &= 0x00ffffff;
- afx->crc = crc;
afx->idx = idx;
afx->radbuf[0] = val;
+ if( n )
+ gcry_md_write (afx->crc_md, buf, n);
+
if( checkcrc ) {
+ gcry_md_final (afx->crc_md);
afx->any_data = 1;
afx->inp_checked=0;
afx->faked = 0;
@@ -911,19 +1034,19 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
continue;
break;
}
- if( c == -1 )
+ if( !afx->buffer_len )
log_error(_("premature eof (no CRC)\n"));
else {
u32 mycrc = 0;
idx = 0;
do {
- if( (c = asctobin[c]) == 255 )
+ if( (binc = asctobin[0][c]) == 0xffffffffUL )
break;
switch(idx) {
- case 0: val = c << 2; break;
- case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break;
- case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break;
- case 3: val |= c&0x3f; mycrc |= val; break;
+ case 0: val = binc << 2; break;
+ case 1: val |= (binc>>4)&3; mycrc |= val << 16;val=(binc<<4)&0xf0;break;
+ case 2: val |= (binc>>2)&15; mycrc |= val << 8;val=(binc<<6)&0xc0;break;
+ case 3: val |= binc&0x3f; mycrc |= val; break;
}
for(;;) {
if( afx->buffer_pos < afx->buffer_len )
@@ -945,7 +1068,7 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
if( !afx->buffer_len )
break; /* eof */
} while( ++idx < 4 );
- if( c == -1 ) {
+ if( !afx->buffer_len ) {
log_info(_("premature eof (in CRC)\n"));
rc = invalid_crc();
}
@@ -957,10 +1080,10 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
log_info(_("malformed CRC\n"));
rc = invalid_crc();
}
- else if( mycrc != afx->crc ) {
- log_info (_("CRC error; %06lX - %06lX\n"),
- (ulong)afx->crc, (ulong)mycrc);
- rc = invalid_crc();
+ else if( mycrc != get_afx_crc (afx) ) {
+ log_info (_("CRC error; %06lX - %06lX\n"),
+ (ulong)get_afx_crc (afx), (ulong)mycrc);
+ rc = invalid_crc();
}
else {
rc = 0;
@@ -997,6 +1120,121 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
return rc;
}
+static void
+armor_output_buf_as_radix64 (armor_filter_context_t *afx, IOBUF a,
+ byte *buf, size_t size)
+{
+ byte radbuf[sizeof (afx->radbuf)];
+ byte outbuf[64 + sizeof (afx->eol)];
+ unsigned int eollen = strlen (afx->eol);
+ u32 in, in2;
+ int idx, idx2;
+ int i;
+
+ idx = afx->idx;
+ idx2 = afx->idx2;
+ memcpy (radbuf, afx->radbuf, sizeof (afx->radbuf));
+
+ if (size && (idx || idx2))
+ {
+ /* preload eol to outbuf buffer */
+ memcpy (outbuf + 4, afx->eol, sizeof (afx->eol));
+
+ for (; size && (idx || idx2); buf++, size--)
+ {
+ radbuf[idx++] = *buf;
+ if (idx > 2)
+ {
+ idx = 0;
+ in = (u32)radbuf[0] << (2 * 8);
+ in |= (u32)radbuf[1] << (1 * 8);
+ in |= (u32)radbuf[2] << (0 * 8);
+ outbuf[0] = bintoasc[(in >> 18) & 077];
+ outbuf[1] = bintoasc[(in >> 12) & 077];
+ outbuf[2] = bintoasc[(in >> 6) & 077];
+ outbuf[3] = bintoasc[(in >> 0) & 077];
+ if (++idx2 >= (64/4))
+ { /* pgp doesn't like 72 here */
+ idx2=0;
+ iobuf_write (a, outbuf, 4 + eollen);
+ }
+ else
+ {
+ iobuf_write (a, outbuf, 4);
+ }
+ }
+ }
+ }
+
+ if (size >= (64/4)*3)
+ {
+ /* preload eol to outbuf buffer */
+ memcpy (outbuf + 64, afx->eol, sizeof(afx->eol));
+
+ do
+ {
+ /* idx and idx2 == 0 */
+
+ for (i = 0; i < (64/8); i++)
+ {
+ in = (u32)buf[0] << (2 * 8);
+ in |= (u32)buf[1] << (1 * 8);
+ in |= (u32)buf[2] << (0 * 8);
+ in2 = (u32)buf[3] << (2 * 8);
+ in2 |= (u32)buf[4] << (1 * 8);
+ in2 |= (u32)buf[5] << (0 * 8);
+ outbuf[i*8+0] = bintoasc[(in >> 18) & 077];
+ outbuf[i*8+1] = bintoasc[(in >> 12) & 077];
+ outbuf[i*8+2] = bintoasc[(in >> 6) & 077];
+ outbuf[i*8+3] = bintoasc[(in >> 0) & 077];
+ outbuf[i*8+4] = bintoasc[(in2 >> 18) & 077];
+ outbuf[i*8+5] = bintoasc[(in2 >> 12) & 077];
+ outbuf[i*8+6] = bintoasc[(in2 >> 6) & 077];
+ outbuf[i*8+7] = bintoasc[(in2 >> 0) & 077];
+ buf+=6;
+ size-=6;
+ }
+
+ /* pgp doesn't like 72 here */
+ iobuf_write (a, outbuf, 64 + eollen);
+ }
+ while (size >= (64/4)*3);
+
+ /* restore eol for tail handling */
+ if (size)
+ memcpy (outbuf + 4, afx->eol, sizeof (afx->eol));
+ }
+
+ for (; size; buf++, size--)
+ {
+ radbuf[idx++] = *buf;
+ if (idx > 2)
+ {
+ idx = 0;
+ in = (u32)radbuf[0] << (2 * 8);
+ in |= (u32)radbuf[1] << (1 * 8);
+ in |= (u32)radbuf[2] << (0 * 8);
+ outbuf[0] = bintoasc[(in >> 18) & 077];
+ outbuf[1] = bintoasc[(in >> 12) & 077];
+ outbuf[2] = bintoasc[(in >> 6) & 077];
+ outbuf[3] = bintoasc[(in >> 0) & 077];
+ if (++idx2 >= (64/4))
+ { /* pgp doesn't like 72 here */
+ idx2=0;
+ iobuf_write (a, outbuf, 4 + eollen);
+ }
+ else
+ {
+ iobuf_write (a, outbuf, 4);
+ }
+ }
+ }
+
+ memcpy (afx->radbuf, radbuf, sizeof (afx->radbuf));
+ afx->idx = idx;
+ afx->idx2 = idx2;
+}
+
/****************
* This filter is used to handle the armor stuff
*/
@@ -1006,7 +1244,7 @@ armor_filter( void *opaque, int control,
{
size_t size = *ret_len;
armor_filter_context_t *afx = opaque;
- int rc=0, i, c;
+ int rc=0, c;
byte radbuf[3];
int idx, idx2;
size_t n=0;
@@ -1188,43 +1426,13 @@ armor_filter( void *opaque, int control,
afx->status++;
afx->idx = 0;
afx->idx2 = 0;
- afx->crc = CRCINIT;
-
+ gcry_md_reset (afx->crc_md);
}
- crc = afx->crc;
- idx = afx->idx;
- idx2 = afx->idx2;
- for(i=0; i < idx; i++ )
- radbuf[i] = afx->radbuf[i];
-
- for(i=0; i < size; i++ )
- crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
- crc &= 0x00ffffff;
-
- for( ; size; buf++, size-- ) {
- radbuf[idx++] = *buf;
- if( idx > 2 ) {
- idx = 0;
- c = bintoasc[(*radbuf >> 2) & 077];
- iobuf_put(a, c);
- c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
- iobuf_put(a, c);
- c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
- iobuf_put(a, c);
- c = bintoasc[radbuf[2]&077];
- iobuf_put(a, c);
- if( ++idx2 >= (64/4) )
- { /* pgp doesn't like 72 here */
- iobuf_writestr(a,afx->eol);
- idx2=0;
- }
- }
- }
- for(i=0; i < idx; i++ )
- afx->radbuf[i] = radbuf[i];
- afx->idx = idx;
- afx->idx2 = idx2;
- afx->crc = crc;
+
+ if( size ) {
+ gcry_md_write (afx->crc_md, buf, size);
+ armor_output_buf_as_radix64 (afx, a, buf, size);
+ }
}
else if( control == IOBUFCTRL_INIT )
{
@@ -1250,7 +1458,8 @@ armor_filter( void *opaque, int control,
if( afx->cancel )
;
else if( afx->status ) { /* pad, write cecksum, and bottom line */
- crc = afx->crc;
+ gcry_md_final (afx->crc_md);
+ crc = get_afx_crc (afx);
idx = afx->idx;
idx2 = afx->idx2;
if( idx ) {
@@ -1350,221 +1559,3 @@ make_radix64_string( const byte *data, size_t len )
*p = 0;
return buffer;
}
-
-
-/***********************************************
- * For the pipemode command we can't use the armor filter for various
- * reasons, so we use this new unarmor_pump stuff to remove the armor
- */
-
-enum unarmor_state_e {
- STA_init = 0,
- STA_bypass,
- STA_wait_newline,
- STA_wait_dash,
- STA_first_dash,
- STA_compare_header,
- STA_found_header_wait_newline,
- STA_skip_header_lines,
- STA_skip_header_lines_non_ws,
- STA_read_data,
- STA_wait_crc,
- STA_read_crc,
- STA_ready
-};
-
-struct unarmor_pump_s {
- enum unarmor_state_e state;
- byte val;
- int checkcrc;
- int pos; /* counts from 0..3 */
- u32 crc;
- u32 mycrc; /* the one store in the data */
-};
-
-
-
-UnarmorPump
-unarmor_pump_new (void)
-{
- UnarmorPump x;
-
- if( !is_initialized )
- initialize();
- x = xmalloc_clear (sizeof *x);
- return x;
-}
-
-void
-unarmor_pump_release (UnarmorPump x)
-{
- xfree (x);
-}
-
-/*
- * Get the next character from the ascii armor taken from the IOBUF
- * created earlier by unarmor_pump_new().
- * Return: c = Character
- * 256 = ignore this value
- * -1 = End of current armor
- * -2 = Premature EOF (not used)
- * -3 = Invalid armor
- */
-int
-unarmor_pump (UnarmorPump x, int c)
-{
- int rval = 256; /* default is to ignore the return value */
-
- switch (x->state) {
- case STA_init:
- {
- byte tmp[2];
- tmp[0] = c;
- tmp[1] = 0;
- if ( is_armored (tmp) )
- x->state = c == '-'? STA_first_dash : STA_wait_newline;
- else {
- x->state = STA_bypass;
- return c;
- }
- }
- break;
- case STA_bypass:
- return c; /* return here to avoid crc calculation */
- case STA_wait_newline:
- if (c == '\n')
- x->state = STA_wait_dash;
- break;
- case STA_wait_dash:
- x->state = c == '-'? STA_first_dash : STA_wait_newline;
- break;
- case STA_first_dash: /* just need for initialization */
- x->pos = 0;
- x->state = STA_compare_header; /* fall through */
- case STA_compare_header:
- if ( "-----BEGIN PGP SIGNATURE-----"[++x->pos] == c ) {
- if ( x->pos == 28 )
- x->state = STA_found_header_wait_newline;
- }
- else
- x->state = c == '\n'? STA_wait_dash : STA_wait_newline;
- break;
- case STA_found_header_wait_newline:
- /* to make CR,LF issues easier we simply allow for white space
- behind the 5 dashes */
- if ( c == '\n' )
- x->state = STA_skip_header_lines;
- else if ( c != '\r' && c != ' ' && c != '\t' )
- x->state = STA_wait_dash; /* garbage after the header line */
- break;
- case STA_skip_header_lines:
- /* i.e. wait for one empty line */
- if ( c == '\n' ) {
- x->state = STA_read_data;
- x->crc = CRCINIT;
- x->val = 0;
- x->pos = 0;
- }
- else if ( c != '\r' && c != ' ' && c != '\t' )
- x->state = STA_skip_header_lines_non_ws;
- break;
- case STA_skip_header_lines_non_ws:
- /* like above but we already encountered non white space */
- if ( c == '\n' )
- x->state = STA_skip_header_lines;
- break;
- case STA_read_data:
- /* fixme: we don't check for the trailing dash lines but rely
- * on the armor stop characters */
- if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
- break; /* skip all kind of white space */
-
- if( c == '=' ) { /* pad character: stop */
- if( x->pos == 1 ) /* in this case val has some value */
- rval = x->val;
- x->state = STA_wait_crc;
- break;
- }
-
- {
- int c2;
- if( (c = asctobin[(c2=c)]) == 255 ) {
- log_error(_("invalid radix64 character %02X skipped\n"), c2);
- break;
- }
- }
-
- switch(x->pos) {
- case 0:
- x->val = c << 2;
- break;
- case 1:
- x->val |= (c>>4)&3;
- rval = x->val;
- x->val = (c<<4)&0xf0;
- break;
- case 2:
- x->val |= (c>>2)&15;
- rval = x->val;
- x->val = (c<<6)&0xc0;
- break;
- case 3:
- x->val |= c&0x3f;
- rval = x->val;
- break;
- }
- x->pos = (x->pos+1) % 4;
- break;
- case STA_wait_crc:
- if( c == '\n' || c == ' ' || c == '\r' || c == '\t' || c == '=' )
- break; /* skip ws and pad characters */
- /* assume that we are at the next line */
- x->state = STA_read_crc;
- x->pos = 0;
- x->mycrc = 0; /* fall through */
- case STA_read_crc:
- if( (c = asctobin[c]) == 255 ) {
- rval = -1; /* ready */
- if( x->crc != x->mycrc ) {
- log_info (_("CRC error; %06lX - %06lX\n"),
- (ulong)x->crc, (ulong)x->mycrc);
- if ( invalid_crc() )
- rval = -3;
- }
- x->state = STA_ready; /* not sure whether this is correct */
- break;
- }
-
- switch(x->pos) {
- case 0:
- x->val = c << 2;
- break;
- case 1:
- x->val |= (c>>4)&3;
- x->mycrc |= x->val << 16;
- x->val = (c<<4)&0xf0;
- break;
- case 2:
- x->val |= (c>>2)&15;
- x->mycrc |= x->val << 8;
- x->val = (c<<6)&0xc0;
- break;
- case 3:
- x->val |= c&0x3f;
- x->mycrc |= x->val;
- break;
- }
- x->pos = (x->pos+1) % 4;
- break;
- case STA_ready:
- rval = -1;
- break;
- }
-
- if ( !(rval & ~255) ) { /* compute the CRC */
- x->crc = (x->crc << 8) ^ crc_table[((x->crc >> 16)&0xff) ^ rval];
- x->crc &= 0x00ffffff;
- }
-
- return rval;
-}
diff --git a/g10/build-packet.c b/g10/build-packet.c
index b4e03d007..dd4ad54bf 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -1297,7 +1297,7 @@ string_to_notation(const char *string,int is_utf8)
}
notation->name=xmalloc((s-string)+1);
- strncpy(notation->name,string,s-string);
+ memcpy(notation->name,string,s-string);
notation->name[s-string]='\0';
if(!saw_at && !opt.expert)
@@ -1536,7 +1536,7 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
else
iobuf_put( a, sig->version );
if ( sig->version < 4 )
- iobuf_put (a, 5 ); /* Constant */
+ iobuf_put (a, 5 ); /* Constant used by pre-v4 signatures. */
iobuf_put (a, sig->sig_class );
if ( sig->version < 4 )
{
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 1445f4e44..e9ea82e4f 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -388,22 +388,23 @@ unescape_status_string (const unsigned char *s)
}
-/* Take a 20 byte hexencoded string and put it into the provided
- 20 byte buffer FPR in binary format. */
-static int
-unhexify_fpr (const char *hexstr, unsigned char *fpr)
+/* Take a 20 or 32 byte hexencoded string and put it into the provided
+ * FPRLEN byte long buffer FPR in binary format. Returns the actual
+ * used length of the FPR buffer or 0 on error. */
+static unsigned int
+unhexify_fpr (const char *hexstr, unsigned char *fpr, unsigned int fprlen)
{
const char *s;
int n;
for (s=hexstr, n=0; hexdigitp (s); s++, n++)
;
- if ((*s && *s != ' ') || (n != 40))
+ if ((*s && *s != ' ') || !(n == 40 || n == 64))
return 0; /* no fingerprint (invalid or wrong length). */
- for (s=hexstr, n=0; *s && n < 20; s += 2, n++)
+ for (s=hexstr, n=0; *s && n < fprlen; s += 2, n++)
fpr[n] = xtoi_2 (s);
- return 1; /* okay */
+ return (n == 20 || n == 32)? n : 0;
}
/* Take the serial number from LINE and return it verbatim in a newly
@@ -488,8 +489,8 @@ agent_release_card_info (struct agent_card_info_s *info)
xfree (info->disp_lang); info->disp_lang = NULL;
xfree (info->pubkey_url); info->pubkey_url = NULL;
xfree (info->login_data); info->login_data = NULL;
- info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
- info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
+ info->cafpr1len = info->cafpr2len = info->cafpr3len = 0;
+ info->fpr1len = info->fpr2len = info->fpr3len = 0;
for (i=0; i < DIM(info->private_do); i++)
{
xfree (info->private_do[i]);
@@ -608,6 +609,8 @@ learn_status_cb (void *opaque, const char *line)
parm->extcap.ki = abool;
else if (!strcmp (p, "aac"))
parm->extcap.aac = abool;
+ else if (!strcmp (p, "bt"))
+ parm->extcap.bt = abool;
else if (!strcmp (p, "kdf"))
parm->extcap.kdf = abool;
else if (!strcmp (p, "si"))
@@ -625,11 +628,11 @@ learn_status_cb (void *opaque, const char *line)
while (spacep (line))
line++;
if (no == 1)
- parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
+ parm->fpr1len = unhexify_fpr (line, parm->fpr1, sizeof parm->fpr1);
else if (no == 2)
- parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
+ parm->fpr2len = unhexify_fpr (line, parm->fpr2, sizeof parm->fpr2);
else if (no == 3)
- parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
+ parm->fpr3len = unhexify_fpr (line, parm->fpr3, sizeof parm->fpr3);
}
else if (keywordlen == 8 && !memcmp (keyword, "KEY-TIME", keywordlen))
{
@@ -657,11 +660,11 @@ learn_status_cb (void *opaque, const char *line)
if (strncmp (line, "OPENPGP.", 8))
;
else if ((no = atoi (line+8)) == 1)
- unhexify_fpr (hexgrp, parm->grp1);
+ unhexify_fpr (hexgrp, parm->grp1, sizeof parm->grp1);
else if (no == 2)
- unhexify_fpr (hexgrp, parm->grp2);
+ unhexify_fpr (hexgrp, parm->grp2, sizeof parm->grp2);
else if (no == 3)
- unhexify_fpr (hexgrp, parm->grp3);
+ unhexify_fpr (hexgrp, parm->grp3, sizeof parm->grp3);
}
else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
{
@@ -671,11 +674,11 @@ learn_status_cb (void *opaque, const char *line)
while (spacep (line))
line++;
if (no == 1)
- parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
+ parm->cafpr1len = unhexify_fpr (line, parm->cafpr1,sizeof parm->cafpr1);
else if (no == 2)
- parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
+ parm->cafpr2len = unhexify_fpr (line, parm->cafpr2,sizeof parm->cafpr2);
else if (no == 3)
- parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
+ parm->cafpr3len = unhexify_fpr (line, parm->cafpr3,sizeof parm->cafpr3);
}
else if (keywordlen == 8 && !memcmp (keyword, "KEY-ATTR", keywordlen))
{
@@ -823,6 +826,8 @@ agent_keytocard (const char *hexgrip, int keyno, int force,
return rc;
}
+
+
/* Call the agent to retrieve a data object. This function returns
the data in the same structure as used by the learn command. It is
diff --git a/g10/call-agent.h b/g10/call-agent.h
index 7314ae87b..1055b5ef9 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -39,15 +39,15 @@ struct agent_card_info_s
char *pubkey_url; /* malloced. */
char *login_data; /* malloced. */
char *private_do[4]; /* malloced. */
- char cafpr1valid;
- char cafpr2valid;
- char cafpr3valid;
+ char cafpr1len; /* Length of the CA-fingerprint or 0 if invalid. */
+ char cafpr2len;
+ char cafpr3len;
char cafpr1[20];
char cafpr2[20];
char cafpr3[20];
- char fpr1valid;
- char fpr2valid;
- char fpr3valid;
+ unsigned char fpr1len; /* Length of the fingerprint or 0 if invalid. */
+ unsigned char fpr2len;
+ unsigned char fpr3len;
char fpr1[20];
char fpr2[20];
char fpr3[20];
@@ -69,6 +69,7 @@ struct agent_card_info_s
unsigned int ki:1; /* Key import available. */
unsigned int aac:1; /* Algorithm attributes are changeable. */
unsigned int kdf:1; /* KDF object to support PIN hashing available. */
+ unsigned int bt:1; /* Button for confirmation available. */
} extcap;
unsigned int status_indicator;
};
diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c
index 9bc90fb2d..8f83c087f 100644
--- a/g10/call-dirmngr.c
+++ b/g10/call-dirmngr.c
@@ -41,6 +41,12 @@
#include "call-dirmngr.h"
+/* Keys retrieved from the web key directory should be small. There
+ * is only one UID and we can expect that the number of subkeys is
+ * reasonable. So we set a generous limit of 256 KiB. */
+#define MAX_WKD_RESULT_LENGTH (256 * 1024)
+
+
/* Parameter structure used to gather status info. Note that it is
* also used for WKD requests. */
struct ks_status_parm_s
@@ -406,6 +412,8 @@ ks_status_cb (void *opaque, const char *line)
warn = _("Tor is not running");
else if ((s2 = has_leading_keyword (s, "tor_config_problem")))
warn = _("Tor is not properly configured");
+ else if ((s2 = has_leading_keyword (s, "dns_config_problem")))
+ warn = _("DNS is not properly configured");
else
warn = NULL;
@@ -600,6 +608,12 @@ gpg_dirmngr_ks_search (ctrl_t ctrl, const char *searchstr,
NULL, NULL, ks_status_cb, &stparm);
if (!err)
err = cb (cb_value, 0, NULL); /* Send EOF. */
+ else if (parm.stparm->source)
+ {
+ /* Error but we received a SOURCE status. Tell via callback but
+ * ignore errors. */
+ parm.data_cb (parm.data_cb_value, 1, parm.stparm->source);
+ }
xfree (get_membuf (&parm.saveddata, NULL));
xfree (parm.helpbuf);
@@ -642,6 +656,7 @@ ks_get_data_cb (void *opaque, const void *data, size_t datalen)
If R_SOURCE is not NULL the source of the data is stored as a
malloced string there. If a source is not known NULL is stored.
+ Note that this may even be returned after an error.
If there are too many patterns the function returns an error. That
could be fixed by issuing several search commands or by
@@ -729,13 +744,13 @@ gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern,
*r_fp = parm.memfp;
parm.memfp = NULL;
- if (r_source)
+
+ leave:
+ if (r_source && stparm.source)
{
*r_source = stparm.source;
stparm.source = NULL;
}
-
- leave:
es_fclose (parm.memfp);
xfree (stparm.source);
xfree (line);
@@ -1068,7 +1083,7 @@ ks_put_inq_cb (void *opaque, const char *line)
/* Send a key to the configured server. {DATA,DATLEN} contains the
key in OpenPGP binary transport format. If KEYBLOCK is not NULL it
- has the internal representaion of that key; this is for example
+ has the internal representation of that key; this is for example
used to convey meta data to LDAP keyservers. */
gpg_error_t
gpg_dirmngr_ks_put (ctrl_t ctrl, void *data, size_t datalen, kbnode_t keyblock)
@@ -1365,7 +1380,7 @@ gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, int quick,
goto leave;
}
- parm.memfp = es_fopenmem (0, "rwb");
+ parm.memfp = es_fopenmem (MAX_WKD_RESULT_LENGTH, "rwb");
if (!parm.memfp)
{
err = gpg_error_from_syserror ();
@@ -1373,6 +1388,8 @@ gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, int quick,
}
err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
NULL, NULL, ks_status_cb, &stparm);
+ if (gpg_err_code (err) == GPG_ERR_ENOSPC)
+ err = gpg_error (GPG_ERR_TOO_LARGE);
if (err)
goto leave;
diff --git a/g10/card-util.c b/g10/card-util.c
index b7eedc0c8..a1a099d85 100644
--- a/g10/card-util.c
+++ b/g10/card-util.c
@@ -216,6 +216,7 @@ get_manufacturer (unsigned int no)
case 0x1337: return "Warsaw Hackerspace";
case 0x2342: return "warpzone"; /* hackerspace Muenster. */
+ case 0x4354: return "Confidential Technologies"; /* cotech.de */
case 0x63AF: return "Trustica";
case 0xBD0E: return "Paranoidlabs";
case 0xF517: return "FSIJ";
@@ -231,13 +232,14 @@ get_manufacturer (unsigned int no)
static void
-print_sha1_fpr (estream_t fp, const unsigned char *fpr)
+print_shax_fpr (estream_t fp, const unsigned char *fpr, unsigned int fprlen)
{
int i;
if (fpr)
{
- for (i=0; i < 20 ; i+=2, fpr += 2 )
+ /* FIXME: Fix formatting for FPRLEN != 20 */
+ for (i=0; i < fprlen ; i+=2, fpr += 2 )
{
if (i == 10 )
tty_fprintf (fp, " ");
@@ -251,13 +253,14 @@ print_sha1_fpr (estream_t fp, const unsigned char *fpr)
static void
-print_sha1_fpr_colon (estream_t fp, const unsigned char *fpr)
+print_shax_fpr_colon (estream_t fp,
+ const unsigned char *fpr, unsigned int fprlen)
{
int i;
if (fpr)
{
- for (i=0; i < 20 ; i++, fpr++)
+ for (i=0; i < fprlen ; i++, fpr++)
es_fprintf (fp, "%02X", *fpr);
}
es_putc (':', fp);
@@ -273,7 +276,7 @@ print_keygrip (estream_t fp, const unsigned char *grp)
{
tty_fprintf (fp, " keygrip ....: ");
for (i=0; i < 20 ; i++, grp++)
- es_fprintf (fp, "%02X", *grp);
+ tty_fprintf (fp, "%02X", *grp);
tty_fprintf (fp, "\n");
}
}
@@ -356,25 +359,25 @@ print_isoname (estream_t fp, const char *text,
/* Return true if the SHA1 fingerprint FPR consists only of zeroes. */
static int
-fpr_is_zero (const char *fpr)
+fpr_is_zero (const char *fpr, unsigned int fprlen)
{
int i;
- for (i=0; i < 20 && !fpr[i]; i++)
+ for (i=0; i < fprlen && !fpr[i]; i++)
;
- return (i == 20);
+ return (i == fprlen);
}
-/* Return true if the SHA1 fingerprint FPR consists only of 0xFF. */
+/* Return true if the fingerprint FPR consists only of 0xFF. */
static int
-fpr_is_ff (const char *fpr)
+fpr_is_ff (const char *fpr, unsigned int fprlen)
{
int i;
- for (i=0; i < 20 && fpr[i] == '\xff'; i++)
+ for (i=0; i < fprlen && fpr[i] == '\xff'; i++)
;
- return (i == 20);
+ return (i == fprlen);
}
@@ -389,6 +392,7 @@ current_card_status (ctrl_t ctrl, estream_t fp,
int rc;
unsigned int uval;
const unsigned char *thefpr;
+ unsigned int thefprlen;
int i;
if (serialno && serialnobuflen)
@@ -521,22 +525,25 @@ current_card_status (ctrl_t ctrl, estream_t fp,
}
es_fputs ("cafpr:", fp);
- print_sha1_fpr_colon (fp, info.cafpr1valid? info.cafpr1:NULL);
- print_sha1_fpr_colon (fp, info.cafpr2valid? info.cafpr2:NULL);
- print_sha1_fpr_colon (fp, info.cafpr3valid? info.cafpr3:NULL);
+ print_shax_fpr_colon (fp, info.cafpr1len? info.cafpr1:NULL,
+ info.cafpr2len);
+ print_shax_fpr_colon (fp, info.cafpr2len? info.cafpr2:NULL,
+ info.cafpr2len);
+ print_shax_fpr_colon (fp, info.cafpr3len? info.cafpr3:NULL,
+ info.cafpr3len);
es_putc ('\n', fp);
es_fputs ("fpr:", fp);
- print_sha1_fpr_colon (fp, info.fpr1valid? info.fpr1:NULL);
- print_sha1_fpr_colon (fp, info.fpr2valid? info.fpr2:NULL);
- print_sha1_fpr_colon (fp, info.fpr3valid? info.fpr3:NULL);
+ print_shax_fpr_colon (fp, info.fpr1len? info.fpr1:NULL, info.fpr1len);
+ print_shax_fpr_colon (fp, info.fpr2len? info.fpr2:NULL, info.fpr2len);
+ print_shax_fpr_colon (fp, info.fpr3len? info.fpr3:NULL, info.fpr3len);
es_putc ('\n', fp);
es_fprintf (fp, "fprtime:%lu:%lu:%lu:\n",
(unsigned long)info.fpr1time, (unsigned long)info.fpr2time,
(unsigned long)info.fpr3time);
es_fputs ("grp:", fp);
- print_sha1_fpr_colon (fp, info.grp1);
- print_sha1_fpr_colon (fp, info.grp2);
- print_sha1_fpr_colon (fp, info.grp3);
+ print_shax_fpr_colon (fp, info.grp1, sizeof info.grp1);
+ print_shax_fpr_colon (fp, info.grp2, sizeof info.grp2);
+ print_shax_fpr_colon (fp, info.grp3, sizeof info.grp3);
es_putc ('\n', fp);
}
else
@@ -566,20 +573,20 @@ current_card_status (ctrl_t ctrl, estream_t fp,
print_name (fp, "Private DO 3 .....: ", info.private_do[2]);
if (info.private_do[3])
print_name (fp, "Private DO 4 .....: ", info.private_do[3]);
- if (info.cafpr1valid)
+ if (info.cafpr1len)
{
tty_fprintf (fp, "CA fingerprint %d .:", 1);
- print_sha1_fpr (fp, info.cafpr1);
+ print_shax_fpr (fp, info.cafpr1, info.cafpr1len);
}
- if (info.cafpr2valid)
+ if (info.cafpr2len)
{
tty_fprintf (fp, "CA fingerprint %d .:", 2);
- print_sha1_fpr (fp, info.cafpr2);
+ print_shax_fpr (fp, info.cafpr2, info.cafpr2len);
}
- if (info.cafpr3valid)
+ if (info.cafpr3len)
{
tty_fprintf (fp, "CA fingerprint %d .:", 3);
- print_sha1_fpr (fp, info.cafpr3);
+ print_shax_fpr (fp, info.cafpr3, info.cafpr3len);
}
tty_fprintf (fp, "Signature PIN ....: %s\n",
info.chv1_cached? _("not forced"): _("forced"));
@@ -612,24 +619,24 @@ current_card_status (ctrl_t ctrl, estream_t fp,
info.chvretry[0], info.chvretry[1], info.chvretry[2]);
tty_fprintf (fp, "Signature counter : %lu\n", info.sig_counter);
tty_fprintf (fp, "Signature key ....:");
- print_sha1_fpr (fp, info.fpr1valid? info.fpr1:NULL);
- if (info.fpr1valid && info.fpr1time)
+ print_shax_fpr (fp, info.fpr1len? info.fpr1:NULL, info.fpr1len);
+ if (info.fpr1len && info.fpr1time)
{
tty_fprintf (fp, " created ....: %s\n",
isotimestamp (info.fpr1time));
print_keygrip (fp, info.grp1);
}
tty_fprintf (fp, "Encryption key....:");
- print_sha1_fpr (fp, info.fpr2valid? info.fpr2:NULL);
- if (info.fpr2valid && info.fpr2time)
+ print_shax_fpr (fp, info.fpr2len? info.fpr2:NULL, info.fpr2len);
+ if (info.fpr2len && info.fpr2time)
{
tty_fprintf (fp, " created ....: %s\n",
isotimestamp (info.fpr2time));
print_keygrip (fp, info.grp2);
}
tty_fprintf (fp, "Authentication key:");
- print_sha1_fpr (fp, info.fpr3valid? info.fpr3:NULL);
- if (info.fpr3valid && info.fpr3time)
+ print_shax_fpr (fp, info.fpr3len? info.fpr3:NULL, info.fpr3len);
+ if (info.fpr3len && info.fpr3time)
{
tty_fprintf (fp, " created ....: %s\n",
isotimestamp (info.fpr3time));
@@ -637,12 +644,14 @@ current_card_status (ctrl_t ctrl, estream_t fp,
}
tty_fprintf (fp, "General key info..: ");
- thefpr = (info.fpr1valid? info.fpr1 : info.fpr2valid? info.fpr2 :
- info.fpr3valid? info.fpr3 : NULL);
- /* If the fingerprint is all 0xff, the key has no asssociated
+ thefpr = (info.fpr1len? info.fpr1 : info.fpr2len? info.fpr2 :
+ info.fpr3len? info.fpr3 : NULL);
+ thefprlen = (info.fpr1len? info.fpr1len : info.fpr2len? info.fpr2len :
+ info.fpr3len? info.fpr3len : 0);
+ /* If the fingerprint is all 0xff, the key has no associated
OpenPGP certificate. */
- if ( thefpr && !fpr_is_ff (thefpr)
- && !get_pubkey_byfprint (ctrl, pk, &keyblock, thefpr, 20))
+ if ( thefpr && !fpr_is_ff (thefpr, thefprlen)
+ && !get_pubkey_byfprint (ctrl, pk, &keyblock, thefpr, thefprlen))
{
print_pubkey_info (ctrl, fp, pk);
if (keyblock)
@@ -666,7 +675,7 @@ card_status (ctrl_t ctrl, estream_t fp, const char *serialno)
{
int err;
strlist_t card_list, sl;
- char *serialno0;
+ char *serialno0, *serialno1;
int all_cards = 0;
if (serialno == NULL)
@@ -692,8 +701,6 @@ card_status (ctrl_t ctrl, estream_t fp, const char *serialno)
for (sl = card_list; sl; sl = sl->next)
{
- char *serialno1;
-
if (!all_cards && strcmp (serialno, sl->d))
continue;
@@ -714,7 +721,8 @@ card_status (ctrl_t ctrl, estream_t fp, const char *serialno)
}
/* Select the original card again. */
- err = agent_scd_serialno (&serialno0, serialno0);
+ err = agent_scd_serialno (&serialno1, serialno0);
+ xfree (serialno1);
leave:
xfree (serialno0);
@@ -845,9 +853,10 @@ fetch_url (ctrl_t ctrl)
rc = keyserver_fetch (ctrl, sl, KEYORG_URL);
free_strlist (sl);
}
- else if (info.fpr1valid)
+ else if (info.fpr1len)
{
- rc = keyserver_import_fprint (ctrl, info.fpr1, 20, opt.keyserver, 0);
+ rc = keyserver_import_fprint (ctrl, info.fpr1, info.fpr1len,
+ opt.keyserver, 0);
}
}
@@ -1309,11 +1318,11 @@ static void
show_card_key_info (struct agent_card_info_s *info)
{
tty_fprintf (NULL, "Signature key ....:");
- print_sha1_fpr (NULL, info->fpr1valid? info->fpr1:NULL);
+ print_shax_fpr (NULL, info->fpr1len? info->fpr1:NULL, info->fpr1len);
tty_fprintf (NULL, "Encryption key....:");
- print_sha1_fpr (NULL, info->fpr2valid? info->fpr2:NULL);
+ print_shax_fpr (NULL, info->fpr2len? info->fpr2:NULL, info->fpr2len);
tty_fprintf (NULL, "Authentication key:");
- print_sha1_fpr (NULL, info->fpr3valid? info->fpr3:NULL);
+ print_shax_fpr (NULL, info->fpr3len? info->fpr3:NULL, info->fpr3len);
tty_printf ("\n");
}
@@ -1324,9 +1333,9 @@ replace_existing_key_p (struct agent_card_info_s *info, int keyno)
{
log_assert (keyno >= 0 && keyno <= 3);
- if ((keyno == 1 && info->fpr1valid)
- || (keyno == 2 && info->fpr2valid)
- || (keyno == 3 && info->fpr3valid))
+ if ((keyno == 1 && info->fpr1len)
+ || (keyno == 2 && info->fpr2len)
+ || (keyno == 3 && info->fpr3len))
{
tty_printf ("\n");
log_info ("WARNING: such a key has already been stored on the card!\n");
@@ -1620,9 +1629,9 @@ generate_card_keys (ctrl_t ctrl)
else
want_backup = 0;
- if ( (info.fpr1valid && !fpr_is_zero (info.fpr1))
- || (info.fpr2valid && !fpr_is_zero (info.fpr2))
- || (info.fpr3valid && !fpr_is_zero (info.fpr3)))
+ if ( (info.fpr1len && !fpr_is_zero (info.fpr1, info.fpr1len))
+ || (info.fpr2len && !fpr_is_zero (info.fpr2, info.fpr2len))
+ || (info.fpr3len && !fpr_is_zero (info.fpr3, info.fpr3len)))
{
tty_printf ("\n");
log_info (_("Note: keys are already stored on the card!\n"));
@@ -2101,6 +2110,49 @@ kdf_setup (const char *args)
leave:
agent_release_card_info (&info);
}
+
+static void
+uif (int arg_number, const char *arg_rest)
+{
+ struct agent_card_info_s info;
+ int feature_available;
+ gpg_error_t err;
+ char name[100];
+ unsigned char data[2];
+
+ memset (&info, 0, sizeof info);
+
+ err = agent_scd_getattr ("EXTCAP", &info);
+ if (err)
+ {
+ log_error (_("error getting card info: %s\n"), gpg_strerror (err));
+ return;
+ }
+
+ feature_available = info.extcap.bt;
+ agent_release_card_info (&info);
+
+ if (!feature_available)
+ {
+ log_error (_("This command is not supported by this card\n"));
+ tty_printf ("\n");
+ return;
+ }
+
+ snprintf (name, sizeof name, "UIF-%d", arg_number);
+ if ( !strcmp (arg_rest, "off") )
+ data[0] = 0x00;
+ else if ( !strcmp (arg_rest, "on") )
+ data[0] = 0x01;
+ else if ( !strcmp (arg_rest, "permanent") )
+ data[0] = 0x02;
+
+ data[1] = 0x20;
+
+ err = agent_scd_setattr (name, data, 2, NULL);
+ if (err)
+ log_error (_("error for setup UIF: %s\n"), gpg_strerror (err));
+}
/* Data used by the command parser. This needs to be outside of the
function scope to allow readline based command completion. */
@@ -2111,7 +2163,7 @@ enum cmdids
cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR,
cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT,
cmdREADCERT, cmdUNBLOCK, cmdFACTORYRESET, cmdKDFSETUP,
- cmdKEYATTR,
+ cmdKEYATTR, cmdUIF,
cmdINVCMD
};
@@ -2143,10 +2195,11 @@ static struct
{ "generate", cmdGENERATE, 1, N_("generate new keys")},
{ "passwd" , cmdPASSWD, 0, N_("menu to change or unblock the PIN")},
{ "verify" , cmdVERIFY, 0, N_("verify the PIN and list all data")},
- { "unblock" , cmdUNBLOCK,0, N_("unblock the PIN using a Reset Code") },
+ { "unblock" , cmdUNBLOCK,0, N_("unblock the PIN using a Reset Code")},
{ "factory-reset", cmdFACTORYRESET, 1, N_("destroy all keys and data")},
{ "kdf-setup", cmdKDFSETUP, 1, N_("setup KDF for PIN authentication")},
{ "key-attr", cmdKEYATTR, 1, N_("change the key attribute")},
+ { "uif", cmdUIF, 1, N_("change the User Interaction Flag")},
/* Note, that we do not announce these command yet. */
{ "privatedo", cmdPRIVATEDO, 0, NULL },
{ "readcert", cmdREADCERT, 0, NULL },
@@ -2438,6 +2491,14 @@ card_edit (ctrl_t ctrl, strlist_t commands)
key_attr ();
break;
+ case cmdUIF:
+ if ( arg_number < 1 || arg_number > 3 )
+ tty_printf ("usage: uif N [on|off|permanent]\n"
+ " 1 <= N <= 3\n");
+ else
+ uif (arg_number, arg_rest);
+ break;
+
case cmdQUIT:
goto leave;
diff --git a/g10/cipher-aead.c b/g10/cipher-aead.c
index f9a996c80..b14b85444 100644
--- a/g10/cipher-aead.c
+++ b/g10/cipher-aead.c
@@ -278,7 +278,7 @@ do_flush (cipher_filter_context_t *cfx, iobuf_t a, byte *buf, size_t size)
if (DBG_FILTER)
log_debug ("chunksize %ju reached;"
" cur buflen=%zu using %zu of %zu\n",
- (uintmax_t)cfx->chunksize, (uintmax_t)cfx->buflen,
+ cfx->chunksize, cfx->buflen,
n1, n);
n = n1;
}
diff --git a/g10/cpr.c b/g10/cpr.c
index 435442636..ed68b3f15 100644
--- a/g10/cpr.c
+++ b/g10/cpr.c
@@ -187,7 +187,7 @@ write_status_text (int no, const char *text)
}
-/* Write a status line with code NO followed by the outout of the
+/* Write a status line with code NO followed by the output of the
* printf style FORMAT. The caller needs to make sure that LFs and
* CRs are not printed. */
void
diff --git a/g10/decrypt-data.c b/g10/decrypt-data.c
index a3151b5ed..4d9dc86d9 100644
--- a/g10/decrypt-data.c
+++ b/g10/decrypt-data.c
@@ -42,7 +42,7 @@ static int decode_filter ( void *opaque, int control, IOBUF a,
/* Our context object. */
struct decode_filter_context_s
{
- /* Recounter (max value is 2). We need it becuase we do not know
+ /* Recounter (max value is 2). We need it because we do not know
* whether the iobuf or the outer control code frees this object
* first. */
int refcount;
@@ -551,31 +551,42 @@ fill_buffer (decode_filter_ctx_t dfx, iobuf_t stream,
byte *buffer, size_t nbytes, size_t offset)
{
size_t nread = offset;
- int c;
+ size_t curr;
+ int ret;
if (dfx->partial)
{
- for (; nread < nbytes; nread++ )
+ while (nread < nbytes)
{
- if ((c = iobuf_get (stream)) == -1)
+ curr = nbytes - nread;
+
+ ret = iobuf_read (stream, &buffer[nread], curr);
+ if (ret == -1)
{
dfx->eof_seen = 1; /* Normal EOF. */
break;
}
- buffer[nread] = c;
+
+ nread += ret;
}
}
else
{
- for (; nread < nbytes && dfx->length; nread++, dfx->length--)
+ while (nread < nbytes && dfx->length)
{
- c = iobuf_get (stream);
- if (c == -1)
+ curr = nbytes - nread;
+ if (curr > dfx->length)
+ curr = dfx->length;
+
+ ret = iobuf_read (stream, &buffer[nread], curr);
+ if (ret == -1)
{
dfx->eof_seen = 3; /* Premature EOF. */
break;
}
- buffer[nread] = c;
+
+ nread += ret;
+ dfx->length -= ret;
}
if (!dfx->length)
dfx->eof_seen = 1; /* Normal EOF. */
@@ -647,7 +658,7 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
* case when a chunk ends within the buffer. */
if (DBG_FILTER)
log_debug ("decrypt: chunklen=%ju total=%ju size=%zu len=%zu%s\n",
- (uintmax_t)dfx->chunklen, (uintmax_t)dfx->total, size, len,
+ dfx->chunklen, dfx->total, size, len,
dfx->eof_seen? " eof":"");
while (len && dfx->chunklen + len >= dfx->chunksize)
@@ -683,7 +694,7 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
len -= n;
if (DBG_FILTER)
- log_debug ("ndecrypted: %zu (nchunk=%zu) bytes left: %zu at off=%zu\n",
+ log_debug ("ndecrypted: %zu (nchunk=%ju) bytes left: %zu at off=%zu\n",
totallen, dfx->chunklen, len, off);
/* Check the tag. */
@@ -765,7 +776,7 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
dfx->chunklen += len;
dfx->total += len;
if (DBG_FILTER)
- log_debug ("ndecrypted: %zu (nchunk=%zu)\n", totallen, dfx->chunklen);
+ log_debug ("ndecrypted: %zu (nchunk=%ju)\n", totallen, dfx->chunklen);
}
if (dfx->eof_seen)
@@ -873,7 +884,6 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
decode_filter_ctx_t dfx = opaque;
size_t n, size = *ret_len;
int rc = 0;
- int c;
/* Note: We need to distinguish between a partial and a fixed length
packet. The first is the usual case as created by GPG. However
@@ -894,25 +904,7 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
log_assert (size > 44); /* Our code requires at least this size. */
/* Get at least 22 bytes and put it ahead in the buffer. */
- if (dfx->partial)
- {
- for (n=22; n < 44; n++)
- {
- if ( (c = iobuf_get(a)) == -1 )
- break;
- buf[n] = c;
- }
- }
- else
- {
- for (n=22; n < 44 && dfx->length; n++, dfx->length--)
- {
- c = iobuf_get (a);
- if (c == -1)
- break; /* Premature EOF. */
- buf[n] = c;
- }
- }
+ n = fill_buffer (dfx, a, buf, 44, 22);
if (n == 44)
{
/* We have enough stuff - flush the holdback buffer. */
@@ -923,37 +915,11 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
}
else
{
-
memcpy (buf, dfx->holdback, 22);
}
+
/* Fill up the buffer. */
- if (dfx->partial)
- {
- for (; n < size; n++ )
- {
- if ( (c = iobuf_get(a)) == -1 )
- {
- dfx->eof_seen = 1; /* Normal EOF. */
- break;
- }
- buf[n] = c;
- }
- }
- else
- {
- for (; n < size && dfx->length; n++, dfx->length--)
- {
- c = iobuf_get(a);
- if (c == -1)
- {
- dfx->eof_seen = 3; /* Premature EOF. */
- break;
- }
- buf[n] = c;
- }
- if (!dfx->length)
- dfx->eof_seen = 1; /* Normal EOF. */
- }
+ n = fill_buffer (dfx, a, buf, size, n);
/* Move the trailing 22 bytes back to the holdback buffer. We
have at least 44 bytes thus a memmove is not needed. */
@@ -1008,7 +974,7 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
decode_filter_ctx_t fc = opaque;
size_t size = *ret_len;
size_t n;
- int c, rc = 0;
+ int rc = 0;
if ( control == IOBUFCTRL_UNDERFLOW && fc->eof_seen )
@@ -1020,34 +986,7 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
{
log_assert (a);
- if (fc->partial)
- {
- for (n=0; n < size; n++ )
- {
- c = iobuf_get(a);
- if (c == -1)
- {
- fc->eof_seen = 1; /* Normal EOF. */
- break;
- }
- buf[n] = c;
- }
- }
- else
- {
- for (n=0; n < size && fc->length; n++, fc->length--)
- {
- c = iobuf_get(a);
- if (c == -1)
- {
- fc->eof_seen = 3; /* Premature EOF. */
- break;
- }
- buf[n] = c;
- }
- if (!fc->length)
- fc->eof_seen = 1; /* Normal EOF. */
- }
+ n = fill_buffer (fc, a, buf, size, 0);
if (n)
{
if (fc->cipher_hd)
diff --git a/g10/encrypt.c b/g10/encrypt.c
index 04a9ab214..972d13c7c 100644
--- a/g10/encrypt.c
+++ b/g10/encrypt.c
@@ -732,7 +732,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
/* In case 3DES has been selected, print a warning if any key
does not have a preference for AES. This should help to
- indentify why encrypting to several recipients falls back to
+ identify why encrypting to several recipients falls back to
3DES. */
if (opt.verbose && cfx.dek->algo == CIPHER_ALGO_3DES)
warn_missing_aes_from_pklist (pk_list);
@@ -1003,7 +1003,7 @@ encrypt_filter (void *opaque, int control,
/* In case 3DES has been selected, print a warning if
any key does not have a preference for AES. This
- should help to indentify why encrypting to several
+ should help to identify why encrypting to several
recipients falls back to 3DES. */
if (opt.verbose
&& efx->cfx.dek->algo == CIPHER_ALGO_3DES)
diff --git a/g10/export.c b/g10/export.c
index c538dc1f1..d53be99fe 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -41,6 +41,8 @@
#include "../common/init.h"
#include "trustdb.h"
#include "call-agent.h"
+#include "key-clean.h"
+
/* An object to keep track of subkeys. */
struct subkey_list_s
@@ -95,7 +97,7 @@ cleanup_export_globals (void)
}
-/* Option parser for export options. See parse_options fro
+/* Option parser for export options. See parse_options for
details. */
int
parse_export_options(char *str,unsigned int *options,int noisy)
@@ -112,6 +114,8 @@ parse_export_options(char *str,unsigned int *options,int noisy)
N_("remove unusable parts from key during export")},
{"export-minimal",EXPORT_MINIMAL|EXPORT_CLEAN,NULL,
N_("remove as much as possible from key during export")},
+ {"export-drop-uids", EXPORT_DROP_UIDS, NULL,
+ N_("Do not export user id or attribute packets")},
{"export-pka", EXPORT_PKA_FORMAT, NULL, NULL },
{"export-dane", EXPORT_DANE_FORMAT, NULL, NULL },
@@ -134,14 +138,20 @@ parse_export_options(char *str,unsigned int *options,int noisy)
int rc;
rc = parse_options (str, options, export_opts, noisy);
- if (rc && (*options & EXPORT_BACKUP))
+ if (!rc)
+ return 0;
+
+ /* Alter other options we want or don't want for restore. */
+ if ((*options & EXPORT_BACKUP))
{
- /* Alter other options we want or don't want for restore. */
*options |= (EXPORT_LOCAL_SIGS | EXPORT_ATTRIBUTES
| EXPORT_SENSITIVE_REVKEYS);
*options &= ~(EXPORT_CLEAN | EXPORT_MINIMAL
| EXPORT_PKA_FORMAT | EXPORT_DANE_FORMAT);
}
+ /* Dropping uids also means to drop attributes. */
+ if ((*options & EXPORT_DROP_UIDS))
+ *options &= ~(EXPORT_ATTRIBUTES);
return rc;
}
@@ -1169,7 +1179,7 @@ print_status_exported (PKT_public_key *pk)
* passphrase-protected. Otherwise, store secret key material in the
* clear.
*
- * CACHE_NONCE_ADDR is used to share nonce for multple key retrievals.
+ * CACHE_NONCE_ADDR is used to share nonce for multiple key retrievals.
*/
gpg_error_t
receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
@@ -1459,7 +1469,7 @@ print_pka_or_dane_records (iobuf_t out, kbnode_t keyblock, PKT_public_key *pk,
continue;
xfree (mbox);
- mbox = mailbox_from_userid (uid->name);
+ mbox = mailbox_from_userid (uid->name, 0);
if (!mbox)
continue;
@@ -1573,7 +1583,7 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
if (node->pkt->pkttype == PKT_COMMENT)
continue;
- /* Skip ring trust packets - they should not ne here anyway. */
+ /* Skip ring trust packets - they should not be here anyway. */
if (node->pkt->pkttype == PKT_RING_TRUST)
continue;
@@ -1648,6 +1658,19 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
}
}
+ /* Don't export user ids (and attributes)? This is not RFC-4880
+ * compliant but we allow it anyway. */
+ if ((options & EXPORT_DROP_UIDS)
+ && node->pkt->pkttype == PKT_USER_ID)
+ {
+ /* Skip until we get to something that is not a user id (or
+ * attrib) or a signature on it. */
+ while (kbctx->next && kbctx->next->pkt->pkttype == PKT_SIGNATURE)
+ kbctx = kbctx->next;
+
+ continue;
+ }
+
/* Don't export attribs? */
if (!(options & EXPORT_ATTRIBUTES)
&& node->pkt->pkttype == PKT_USER_ID
@@ -2001,12 +2024,19 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
}
/* Always do the cleaning on the public key part if requested.
- * Note that both export-clean and export-minimal only apply to
- * UID sigs (0x10, 0x11, 0x12, and 0x13). A designated
- * revocation is never stripped, even with export-minimal set. */
+ * A designated revocation is never stripped, even with
+ * export-minimal set. */
if ((options & EXPORT_CLEAN))
- clean_key (ctrl, keyblock, opt.verbose,
- (options&EXPORT_MINIMAL), NULL, NULL);
+ {
+ merge_keys_and_selfsig (ctrl, keyblock);
+ clean_all_uids (ctrl, keyblock, opt.verbose,
+ (options&EXPORT_MINIMAL), NULL, NULL);
+ clean_all_subkeys (ctrl, keyblock, opt.verbose,
+ (options&EXPORT_MINIMAL)? KEY_CLEAN_ALL
+ /**/ : KEY_CLEAN_AUTHENCR,
+ NULL, NULL);
+ commit_kbnode (&keyblock);
+ }
if (export_keep_uid)
{
diff --git a/g10/filter.h b/g10/filter.h
index 6daf273fa..b2ef3828f 100644
--- a/g10/filter.h
+++ b/g10/filter.h
@@ -61,7 +61,7 @@ typedef struct {
byte radbuf[4];
int idx, idx2;
- u32 crc;
+ gcry_md_hd_t crc_md;
int status; /* an internal state flag */
int cancel;
@@ -69,8 +69,6 @@ typedef struct {
int pending_lf; /* used together with faked */
} armor_filter_context_t;
-struct unarmor_pump_s;
-typedef struct unarmor_pump_s *UnarmorPump;
struct compress_filter_context_s {
@@ -172,9 +170,6 @@ armor_filter_context_t *new_armor_context (void);
void release_armor_context (armor_filter_context_t *afx);
int push_armor_filter (armor_filter_context_t *afx, iobuf_t iobuf);
int use_armor_filter( iobuf_t a );
-UnarmorPump unarmor_pump_new (void);
-void unarmor_pump_release (UnarmorPump x);
-int unarmor_pump (UnarmorPump x, int c);
/*-- compress.c --*/
gpg_error_t push_compress_filter (iobuf_t out, compress_filter_context_t *zfx,
diff --git a/g10/getkey.c b/g10/getkey.c
index f0132bb08..c776a6100 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -60,7 +60,7 @@ struct getkey_ctx_s
search or not. A search that is exact requires that a key or
subkey meet all of the specified criteria. A search that is not
exact allows selecting a different key or subkey from the
- keyblock that matched the critera. Further, an exact search
+ keyblock that matched the criteria. Further, an exact search
returns the key or subkey that matched whereas a non-exact search
typically returns the primary key. See finish_lookup for
details. */
@@ -88,6 +88,9 @@ struct getkey_ctx_s
their address used in ITEMS. */
strlist_t extra_list;
+ /* Hack to return the mechanism (AKL_foo) used to find the key. */
+ int found_via_akl;
+
/* Part of the search criteria: The low-level search specification
as passed to keydb_search. */
int nitems;
@@ -391,280 +394,21 @@ getkey_disable_caches ()
}
-void
-pubkey_free (pubkey_t key)
-{
- if (key)
- {
- xfree (key->pk);
- release_kbnode (key->keyblock);
- xfree (key);
- }
-}
-
+/* Free a list of pubkey_t objects. */
void
pubkeys_free (pubkey_t keys)
{
while (keys)
{
pubkey_t next = keys->next;
- pubkey_free (keys);
+ xfree (keys->pk);
+ release_kbnode (keys->keyblock);
+ xfree (keys);
keys = next;
}
}
-/* Returns all keys that match the search specification SEARCH_TERMS.
- *
- * This function also checks for and warns about duplicate entries in
- * the keydb, which can occur if the user has configured multiple
- * keyrings or keyboxes or if a keyring or keybox was corrupted.
- *
- * Note: SEARCH_TERMS will not be expanded (i.e., it may not be a
- * group).
- *
- * USE is the operation for which the key is required. It must be
- * either PUBKEY_USAGE_ENC, PUBKEY_USAGE_SIG, PUBKEY_USAGE_CERT or
- * PUBKEY_USAGE_AUTH.
- *
- * INCLUDE_UNUSABLE indicates whether disabled keys are allowed.
- * (Recipients specified with --encrypt-to and --hidden-encrypt-to may
- * be disabled. It is possible to edit disabled keys.)
- *
- * SOURCE is the context in which SEARCH_TERMS was specified, e.g.,
- * "--encrypt-to", etc. If this function is called interactively,
- * then this should be NULL.
- *
- * If WARN_POSSIBLY_AMBIGUOUS is set, then emits a warning if the user
- * does not specify a long key id or a fingerprint.
- *
- * The results are placed in *KEYS. *KEYS must be NULL!
- *
- * Fixme: Currently, only PUBKEY_USAGE_ENC and PUBKEY_USAGE_SIG are
- * implemented. */
-gpg_error_t
-get_pubkeys (ctrl_t ctrl,
- char *search_terms, int use, int include_unusable, char *source,
- int warn_possibly_ambiguous,
- pubkey_t *r_keys)
-{
- /* We show a warning when a key appears multiple times in the DB.
- * This can happen for two reasons:
- *
- * - The user has configured multiple keyrings or keyboxes.
- *
- * - The keyring or keybox has been corrupted in some way, e.g., a
- * bug or a random process changing them.
- *
- * For each duplicate, we only want to show the key once. Hence,
- * this list. */
- static strlist_t key_dups;
- gpg_error_t err;
- char *use_str; /* USE transformed to a string. */
- KEYDB_SEARCH_DESC desc;
- GETKEY_CTX ctx;
- pubkey_t results = NULL;
- pubkey_t r;
- int count;
- char fingerprint[2 * MAX_FINGERPRINT_LEN + 1];
-
- if (DBG_LOOKUP)
- {
- log_debug ("\n");
- log_debug ("%s: Checking %s=%s\n",
- __func__, source ? source : "user input", search_terms);
- }
-
- if (*r_keys)
- log_bug ("%s: KEYS should be NULL!\n", __func__);
-
- switch (use)
- {
- case PUBKEY_USAGE_ENC: use_str = "encrypt"; break;
- case PUBKEY_USAGE_SIG: use_str = "sign"; break;
- case PUBKEY_USAGE_CERT: use_str = "cetify"; break;
- case PUBKEY_USAGE_AUTH: use_str = "authentication"; break;
- default: log_bug ("%s: Bad value for USE (%d)\n", __func__, use);
- }
-
- if (use == PUBKEY_USAGE_CERT || use == PUBKEY_USAGE_AUTH)
- log_bug ("%s: use=%s is unimplemented.\n", __func__, use_str);
-
- err = classify_user_id (search_terms, &desc, 1);
- if (err)
- {
- log_info (_("key \"%s\" not found: %s\n"),
- search_terms, gpg_strerror (err));
- if (!opt.quiet && source)
- log_info (_("(check argument of option '%s')\n"), source);
- goto leave;
- }
-
- if (warn_possibly_ambiguous
- && ! (desc.mode == KEYDB_SEARCH_MODE_LONG_KID
- || desc.mode == KEYDB_SEARCH_MODE_FPR16
- || desc.mode == KEYDB_SEARCH_MODE_FPR20
- || desc.mode == KEYDB_SEARCH_MODE_FPR))
- {
- log_info (_("Warning: '%s' should be a long key ID or a fingerprint\n"),
- search_terms);
- if (!opt.quiet && source)
- log_info (_("(check argument of option '%s')\n"), source);
- }
-
- /* Gather all of the results. */
- ctx = NULL;
- count = 0;
- do
- {
- PKT_public_key *pk;
- KBNODE kb;
-
- pk = xtrycalloc (1, sizeof *pk);
- if (!pk)
- {
- err = gpg_error_from_syserror ();
- goto leave;
- }
-
- pk->req_usage = use;
-
- if (! ctx)
- err = get_pubkey_byname (ctrl, &ctx, pk, search_terms, &kb, NULL,
- include_unusable, 1);
- else
- err = getkey_next (ctrl, ctx, pk, &kb);
-
- if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) /* No more results. */
- {
- xfree (pk);
- break;
- }
- else if (err) /* An error (other than "not found"). */
- {
- log_error (_("error looking up: %s\n"), gpg_strerror (err));
- xfree (pk);
- break;
- }
-
- /* Another result! */
- count ++;
-
- r = xtrycalloc (1, sizeof (*r));
- if (!r)
- {
- err = gpg_error_from_syserror ();
- xfree (pk);
- goto leave;
- }
- r->pk = pk;
- r->keyblock = kb;
- r->next = results;
- results = r;
- }
- while (ctx);
- getkey_end (ctrl, ctx);
-
- if (DBG_LOOKUP)
- {
- log_debug ("%s resulted in %d matches.\n", search_terms, count);
- for (r = results; r; r = r->next)
- log_debug (" %s\n",
- hexfingerprint (r->keyblock->pkt->pkt.public_key,
- fingerprint, sizeof (fingerprint)));
- }
-
- if (! results && gpg_err_code (err) == GPG_ERR_NOT_FOUND)
- { /* No match. */
- if (DBG_LOOKUP)
- log_debug ("%s: '%s' not found.\n", __func__, search_terms);
-
- log_info (_("key \"%s\" not found\n"), search_terms);
- if (!opt.quiet && source)
- log_info (_("(check argument of option '%s')\n"), source);
-
- goto leave;
- }
- else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
- ; /* No more matches. */
- else if (err)
- { /* Some other error. An error message was already printed out.
- * Free RESULTS and continue. */
- goto leave;
- }
-
- /* Check for duplicates. */
- if (DBG_LOOKUP)
- log_debug ("%s: Checking results of %s='%s' for dups\n",
- __func__, source ? source : "user input", search_terms);
- count = 0;
- for (r = results; r; r = r->next)
- {
- pubkey_t *prevp;
- pubkey_t next;
- pubkey_t r2;
- int dups = 0;
-
- prevp = &r->next;
- next = r->next;
- while ((r2 = next))
- {
- if (cmp_public_keys (r->keyblock->pkt->pkt.public_key,
- r2->keyblock->pkt->pkt.public_key) != 0)
- { /* Not a dup. */
- prevp = &r2->next;
- next = r2->next;
- continue;
- }
-
- dups ++;
- count ++;
-
- /* Remove R2 from the list. */
- *prevp = r2->next;
- release_kbnode (r2->keyblock);
- next = r2->next;
- xfree (r2);
- }
-
- if (dups)
- {
- hexfingerprint (r->keyblock->pkt->pkt.public_key,
- fingerprint, sizeof fingerprint);
- if (! strlist_find (key_dups, fingerprint))
- {
- char fingerprint_formatted[MAX_FORMATTED_FINGERPRINT_LEN + 1];
-
- log_info (_("Warning: %s appears in the keyring %d times\n"),
- format_hexfingerprint (fingerprint,
- fingerprint_formatted,
- sizeof fingerprint_formatted),
- 1 + dups);
- add_to_strlist (&key_dups, fingerprint);
- }
- }
- }
-
- if (DBG_LOOKUP && count)
- {
- log_debug ("After removing %d dups:\n", count);
- for (r = results, count = 0; r; r = r->next)
- log_debug (" %d: %s\n",
- count,
- hexfingerprint (r->keyblock->pkt->pkt.public_key,
- fingerprint, sizeof fingerprint));
- }
-
- leave:
- if (err)
- pubkeys_free (results);
- else
- *r_keys = results;
-
- return err;
-}
-
-
static void
pk_from_block (PKT_public_key *pk, kbnode_t keyblock, kbnode_t found_key)
{
@@ -677,6 +421,24 @@ pk_from_block (PKT_public_key *pk, kbnode_t keyblock, kbnode_t found_key)
}
+/* Specialized version of get_pubkey which retrieves the key based on
+ * information in SIG. In contrast to get_pubkey PK is required. */
+gpg_error_t
+get_pubkey_for_sig (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig)
+{
+ const byte *fpr;
+ size_t fprlen;
+
+ /* First try the new ISSUER_FPR info. */
+ fpr = issuer_fpr_raw (sig, &fprlen);
+ if (fpr && !get_pubkey_byfprint (ctrl, pk, NULL, fpr, fprlen))
+ return 0;
+
+ /* Fallback to use the ISSUER_KEYID. */
+ return get_pubkey (ctrl, pk, sig->keyid);
+}
+
+
/* Return the public key with the key id KEYID and store it at PK.
* The resources in *PK should be released using
* release_public_key_parts(). This function also stores a copy of
@@ -739,8 +501,9 @@ get_pubkey (ctrl_t ctrl, PKT_public_key * pk, u32 * keyid)
/* Do a lookup. */
{
struct getkey_ctx_s ctx;
- KBNODE kb = NULL;
- KBNODE found_key = NULL;
+ kbnode_t kb = NULL;
+ kbnode_t found_key = NULL;
+
memset (&ctx, 0, sizeof ctx);
ctx.exact = 1; /* Use the key ID exactly as given. */
ctx.not_allocated = 1;
@@ -863,6 +626,28 @@ get_pubkey_fast (PKT_public_key * pk, u32 * keyid)
}
+/* Return the entire keyblock used to create SIG. This is a
+ * specialized version of get_pubkeyblock.
+ *
+ * FIXME: This is a hack because get_pubkey_for_sig was already called
+ * and it could have used a cache to hold the key. */
+kbnode_t
+get_pubkeyblock_for_sig (ctrl_t ctrl, PKT_signature *sig)
+{
+ const byte *fpr;
+ size_t fprlen;
+ kbnode_t keyblock;
+
+ /* First try the new ISSUER_FPR info. */
+ fpr = issuer_fpr_raw (sig, &fprlen);
+ if (fpr && !get_pubkey_byfprint (ctrl, NULL, &keyblock, fpr, fprlen))
+ return keyblock;
+
+ /* Fallback to use the ISSUER_KEYID. */
+ return get_pubkeyblock (ctrl, sig->keyid);
+}
+
+
/* Return the key block for the key with key id KEYID or NULL, if an
* error occurs. Use release_kbnode() to release the key block.
*
@@ -1224,6 +1009,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
int is_mbox;
int nodefault = 0;
int anylocalfirst = 0;
+ int mechanism_type = AKL_NODEFAULT;
/* If RETCTX is not NULL, then RET_KDBHD must be NULL. */
log_assert (retctx == NULL || ret_kdbhd == NULL);
@@ -1313,18 +1099,19 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
size_t fpr_len;
int did_akl_local = 0;
int no_fingerprint = 0;
- const char *mechanism = "?";
+ const char *mechanism_string = "?";
- switch (akl->type)
+ mechanism_type = akl->type;
+ switch (mechanism_type)
{
case AKL_NODEFAULT:
/* This is a dummy mechanism. */
- mechanism = "None";
+ mechanism_string = "None";
rc = GPG_ERR_NO_PUBKEY;
break;
case AKL_LOCAL:
- mechanism = "Local";
+ mechanism_string = "Local";
did_akl_local = 1;
if (retctx)
{
@@ -1338,35 +1125,35 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
break;
case AKL_CERT:
- mechanism = "DNS CERT";
+ mechanism_string = "DNS CERT";
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_cert (ctrl, name, 0, &fpr, &fpr_len);
glo_ctrl.in_auto_key_retrieve--;
break;
case AKL_PKA:
- mechanism = "PKA";
+ mechanism_string = "PKA";
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_pka (ctrl, name, &fpr, &fpr_len);
glo_ctrl.in_auto_key_retrieve--;
break;
case AKL_DANE:
- mechanism = "DANE";
+ mechanism_string = "DANE";
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_cert (ctrl, name, 1, &fpr, &fpr_len);
glo_ctrl.in_auto_key_retrieve--;
break;
case AKL_WKD:
- mechanism = "WKD";
+ mechanism_string = "WKD";
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_wkd (ctrl, name, 0, &fpr, &fpr_len);
glo_ctrl.in_auto_key_retrieve--;
break;
case AKL_LDAP:
- mechanism = "LDAP";
+ mechanism_string = "LDAP";
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_ldap (ctrl, name, &fpr, &fpr_len);
glo_ctrl.in_auto_key_retrieve--;
@@ -1379,7 +1166,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
* and getting a whole lot of keys back. */
if (keyserver_any_configured (ctrl))
{
- mechanism = "keyserver";
+ mechanism_string = "keyserver";
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_name (ctrl, name, &fpr, &fpr_len,
opt.keyserver);
@@ -1387,7 +1174,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
}
else
{
- mechanism = "Unconfigured keyserver";
+ mechanism_string = "Unconfigured keyserver";
rc = GPG_ERR_NO_PUBKEY;
}
break;
@@ -1396,7 +1183,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
{
struct keyserver_spec *keyserver;
- mechanism = akl->spec->uri;
+ mechanism_string = akl->spec->uri;
keyserver = keyserver_match (akl->spec);
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_name (ctrl,
@@ -1458,13 +1245,13 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
/* Key found. */
if (opt.verbose)
log_info (_("automatically retrieved '%s' via %s\n"),
- name, mechanism);
+ name, mechanism_string);
break;
}
if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY
|| opt.verbose || no_fingerprint)
log_info (_("error retrieving '%s' via %s: %s\n"),
- name, mechanism,
+ name, mechanism_string,
no_fingerprint ? _("No fingerprint") : gpg_strerror (rc));
}
}
@@ -1480,6 +1267,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
{
log_assert (!(*retctx)->extra_list);
(*retctx)->extra_list = namelist;
+ (*retctx)->found_via_akl = mechanism_type;
}
else
free_strlist (namelist);
@@ -1527,6 +1315,34 @@ subkey_is_ok (const PKT_public_key *sub)
return ! sub->flags.revoked && sub->flags.valid && ! sub->flags.disabled;
}
+/* Return true if KEYBLOCK has only expired encryption subkyes. Note
+ * that the function returns false if the key has no encryption
+ * subkeys at all or the subkecys are revoked. */
+static int
+only_expired_enc_subkeys (kbnode_t keyblock)
+{
+ kbnode_t node;
+ PKT_public_key *sub;
+ int any = 0;
+
+ for (node = find_next_kbnode (keyblock, PKT_PUBLIC_SUBKEY);
+ node; node = find_next_kbnode (node, PKT_PUBLIC_SUBKEY))
+ {
+ sub = node->pkt->pkt.public_key;
+
+ if (!(sub->pubkey_usage & PUBKEY_USAGE_ENC))
+ continue;
+
+ if (!subkey_is_ok (sub))
+ continue;
+
+ any = 1;
+ if (!sub->has_expired)
+ return 0;
+ }
+
+ return any? 1 : 0;
+}
/* Finally this function compares a NEW key to the former candidate
* OLD. Returns < 0 if the old key is worse, > 0 if the old key is
@@ -1557,7 +1373,7 @@ pubkey_cmp (ctrl_t ctrl, const char *name, struct pubkey_cmp_cookie *old,
n; n = find_next_kbnode (n, PKT_USER_ID))
{
PKT_user_id *uid = n->pkt->pkt.user_id;
- char *mbox = mailbox_from_userid (uid->name);
+ char *mbox = mailbox_from_userid (uid->name, 0);
int match = mbox ? strcasecmp (name, mbox) == 0 : 0;
xfree (mbox);
@@ -1595,23 +1411,68 @@ pubkey_cmp (ctrl_t ctrl, const char *name, struct pubkey_cmp_cookie *old,
gpg_error_t
get_best_pubkey_byname (ctrl_t ctrl, GETKEY_CTX *retctx, PKT_public_key *pk,
const char *name, KBNODE *ret_keyblock,
- int include_unusable, int no_akl)
+ int include_unusable)
{
gpg_error_t err;
struct getkey_ctx_s *ctx = NULL;
+ int is_mbox = is_valid_mailbox (name);
+ int wkd_tried = 0;
if (retctx)
*retctx = NULL;
+ start_over:
+ if (ctx) /* Clear in case of a start over. */
+ {
+ if (ret_keyblock)
+ {
+ release_kbnode (*ret_keyblock);
+ *ret_keyblock = NULL;
+ }
+ getkey_end (ctrl, ctx);
+ ctx = NULL;
+ }
err = get_pubkey_byname (ctrl, &ctx, pk, name, ret_keyblock,
- NULL, include_unusable, no_akl);
+ NULL, include_unusable, 0);
if (err)
{
getkey_end (ctrl, ctx);
return err;
}
- if (is_valid_mailbox (name) && ctx)
+ /* If the keyblock was retrieved from the local database and the key
+ * has expired, do further checks. However, we can do this only if
+ * the caller requested a keyblock. */
+ if (is_mbox && ctx && ctx->found_via_akl == AKL_LOCAL && ret_keyblock)
+ {
+ u32 now = make_timestamp ();
+ PKT_public_key *pk2 = (*ret_keyblock)->pkt->pkt.public_key;
+ int found;
+
+ /* If the key has expired and its origin was the WKD then try to
+ * get a fresh key from the WKD. We also try this if the key
+ * has any only expired encryption subkeys. In case we checked
+ * for a fresh copy in the last 3 hours we won't do that again.
+ * Unfortunately that does not yet work because KEYUPDATE is
+ * only updated during import iff the key has actually changed
+ * (see import.c:import_one). */
+ if (!wkd_tried && pk2->keyorg == KEYORG_WKD
+ && (pk2->keyupdate + 3*3600) < now
+ && (pk2->has_expired || only_expired_enc_subkeys (*ret_keyblock)))
+ {
+ if (opt.verbose)
+ log_info (_("checking for a fresh copy of an expired key via %s\n"),
+ "WKD");
+ wkd_tried = 1;
+ glo_ctrl.in_auto_key_retrieve++;
+ found = !keyserver_import_wkd (ctrl, name, 0, NULL, NULL);
+ glo_ctrl.in_auto_key_retrieve--;
+ if (found)
+ goto start_over;
+ }
+ }
+
+ if (is_mbox && ctx)
{
/* Rank results and return only the most relevant key. */
struct pubkey_cmp_cookie best = { 0 };
@@ -1802,6 +1663,8 @@ get_pubkey_byfprint (ctrl_t ctrl, PKT_public_key *pk, kbnode_t *r_keyblock,
memset (&ctx, 0, sizeof ctx);
ctx.exact = 1;
ctx.not_allocated = 1;
+ /* FIXME: We should get the handle from the cache like we do in
+ * get_pubkey. */
ctx.kr_handle = keydb_new ();
if (!ctx.kr_handle)
return gpg_error_from_syserror ();
@@ -3501,7 +3364,7 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock)
*
* 1. No requested usage and no primary key requested
* Examples for this case are that we have a keyID to be used
- * for decrytion or verification.
+ * for decryption or verification.
* 2. No usage but primary key requested
* This is the case for all functions which work on an
* entire keyblock, e.g. for editing or listing
@@ -3904,180 +3767,6 @@ lookup (ctrl_t ctrl, getkey_ctx_t ctx, int want_secret,
}
-/* Enumerate some secret keys (specifically, those specified with
- * --default-key and --try-secret-key). Use the following procedure:
- *
- * 1) Initialize a void pointer to NULL
- * 2) Pass a reference to this pointer to this function (content)
- * and provide space for the secret key (sk)
- * 3) Call this function as long as it does not return an error (or
- * until you are done). The error code GPG_ERR_EOF indicates the
- * end of the listing.
- * 4) Call this function a last time with SK set to NULL,
- * so that can free it's context.
- *
- * In pseudo-code:
- *
- * void *ctx = NULL;
- * PKT_public_key *sk = xmalloc_clear (sizeof (*sk));
- *
- * while ((err = enum_secret_keys (&ctx, sk)))
- * { // Process SK.
- * if (done)
- * break;
- * free_public_key (sk);
- * sk = xmalloc_clear (sizeof (*sk));
- * }
- *
- * // Release any resources used by CTX.
- * enum_secret_keys (&ctx, NULL);
- * free_public_key (sk);
- *
- * if (gpg_err_code (err) != GPG_ERR_EOF)
- * ; // An error occurred.
- */
-gpg_error_t
-enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk)
-{
- gpg_error_t err = 0;
- const char *name;
- kbnode_t keyblock;
- struct
- {
- int eof;
- int state;
- strlist_t sl;
- kbnode_t keyblock;
- kbnode_t node;
- getkey_ctx_t ctx;
- } *c = *context;
-
- if (!c)
- {
- /* Make a new context. */
- c = xtrycalloc (1, sizeof *c);
- if (!c)
- return gpg_error_from_syserror ();
- *context = c;
- }
-
- if (!sk)
- {
- /* Free the context. */
- release_kbnode (c->keyblock);
- getkey_end (ctrl, c->ctx);
- xfree (c);
- *context = NULL;
- return 0;
- }
-
- if (c->eof)
- return gpg_error (GPG_ERR_EOF);
-
- for (;;)
- {
- /* Loop until we have a keyblock. */
- while (!c->keyblock)
- {
- /* Loop over the list of secret keys. */
- do
- {
- name = NULL;
- keyblock = NULL;
- switch (c->state)
- {
- case 0: /* First try to use the --default-key. */
- name = parse_def_secret_key (ctrl);
- c->state = 1;
- break;
-
- case 1: /* Init list of keys to try. */
- c->sl = opt.secret_keys_to_try;
- c->state++;
- break;
-
- case 2: /* Get next item from list. */
- if (c->sl)
- {
- name = c->sl->d;
- c->sl = c->sl->next;
- }
- else
- c->state++;
- break;
-
- case 3: /* Init search context to enum all secret keys. */
- err = getkey_bynames (ctrl, &c->ctx, NULL, NULL, 1,
- &keyblock);
- if (err)
- {
- release_kbnode (keyblock);
- keyblock = NULL;
- getkey_end (ctrl, c->ctx);
- c->ctx = NULL;
- }
- c->state++;
- break;
-
- case 4: /* Get next item from the context. */
- if (c->ctx)
- {
- err = getkey_next (ctrl, c->ctx, NULL, &keyblock);
- if (err)
- {
- release_kbnode (keyblock);
- keyblock = NULL;
- getkey_end (ctrl, c->ctx);
- c->ctx = NULL;
- }
- }
- else
- c->state++;
- break;
-
- default: /* No more names to check - stop. */
- c->eof = 1;
- return gpg_error (GPG_ERR_EOF);
- }
- }
- while ((!name || !*name) && !keyblock);
-
- if (keyblock)
- c->node = c->keyblock = keyblock;
- else
- {
- err = getkey_byname (ctrl, NULL, NULL, name, 1, &c->keyblock);
- if (err)
- {
- /* getkey_byname might return a keyblock even in the
- error case - I have not checked. Thus better release
- it. */
- release_kbnode (c->keyblock);
- c->keyblock = NULL;
- }
- else
- c->node = c->keyblock;
- }
- }
-
- /* Get the next key from the current keyblock. */
- for (; c->node; c->node = c->node->next)
- {
- if (c->node->pkt->pkttype == PKT_PUBLIC_KEY
- || c->node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
- {
- copy_public_key (sk, c->node->pkt->pkt.public_key);
- c->node = c->node->next;
- return 0; /* Found. */
- }
- }
-
- /* Dispose the keyblock and continue. */
- release_kbnode (c->keyblock);
- c->keyblock = NULL;
- }
-}
-
gpg_error_t
get_seckey_default_or_card (ctrl_t ctrl, PKT_public_key *pk,
const byte *fpr_card, size_t fpr_len)
diff --git a/g10/gpg.c b/g10/gpg.c
index 600f8440d..110289243 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -110,6 +110,7 @@ enum cmd_and_opt_values
oCertNotation,
oShowNotation,
oNoShowNotation,
+ oKnownNotation,
aEncrFiles,
aEncrSym,
aDecryptFiles,
@@ -225,6 +226,7 @@ enum cmd_and_opt_values
oDebugAll,
oDebugIOLBF,
oDebugSetIobufSize,
+ oDebugAllowLargeChunks,
oStatusFD,
oStatusFile,
oAttributeFD,
@@ -634,6 +636,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oDebugAll, "debug-all", "@"),
ARGPARSE_s_n (oDebugIOLBF, "debug-iolbf", "@"),
ARGPARSE_s_u (oDebugSetIobufSize, "debug-set-iobuf-size", "@"),
+ ARGPARSE_s_u (oDebugAllowLargeChunks, "debug-allow-large-chunks", "@"),
ARGPARSE_s_i (oStatusFD, "status-fd", "@"),
ARGPARSE_s_s (oStatusFile, "status-file", "@"),
ARGPARSE_s_i (oAttributeFD, "attribute-fd", "@"),
@@ -680,6 +683,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_s (oSetNotation, "set-notation", "@"),
ARGPARSE_s_s (oSigNotation, "sig-notation", "@"),
ARGPARSE_s_s (oCertNotation, "cert-notation", "@"),
+ ARGPARSE_s_s (oKnownNotation, "known-notation", "@"),
ARGPARSE_group (302, N_(
"@\n(See the man page for a complete listing of all commands and options)\n"
@@ -2347,6 +2351,7 @@ main (int argc, char **argv)
static int print_dane_records;
static int print_pka_records;
+ static int allow_large_chunks;
#ifdef __riscos__
@@ -2761,6 +2766,10 @@ main (int argc, char **argv)
opt_set_iobuf_size_used = 1;
break;
+ case oDebugAllowLargeChunks:
+ allow_large_chunks = 1;
+ break;
+
case oStatusFD:
set_status_fd ( translate_sys2libc_fd_int (pargs.r.ret_int, 1) );
break;
@@ -3121,7 +3130,7 @@ main (int argc, char **argv)
break;
case oSender:
{
- char *mbox = mailbox_from_userid (pargs.r.ret_str);
+ char *mbox = mailbox_from_userid (pargs.r.ret_str, 0);
if (!mbox)
log_error (_("\"%s\" is not a proper mail address\n"),
pargs.r.ret_str);
@@ -3358,6 +3367,7 @@ main (int argc, char **argv)
break;
case oSigNotation: add_notation_data( pargs.r.ret_str, 0 ); break;
case oCertNotation: add_notation_data( pargs.r.ret_str, 1 ); break;
+ case oKnownNotation: register_known_notation (pargs.r.ret_str); break;
case oShowNotation:
deprecated_warning(configname,configlineno,"--show-notation",
"--list-options ","show-notations");
@@ -3881,18 +3891,18 @@ main (int argc, char **argv)
keygen_set_std_prefs(pers_compress_list,PREFTYPE_ZIP))
log_error(_("invalid personal compress preferences\n"));
- /* Check chunk size. Please fix also the man page if you chnage
+ /* Check chunk size. Please fix also the man page if you change
* the default. The limits are given by the specs. */
if (!opt.chunk_size)
- opt.chunk_size = 30; /* Default to 1 GiB chunks. */
+ opt.chunk_size = 27; /* Default to the suggested max of 128 MiB. */
else if (opt.chunk_size < 6)
{
opt.chunk_size = 6;
log_info (_("chunk size invalid - using %d\n"), opt.chunk_size);
}
- else if (opt.chunk_size > 62)
+ else if (opt.chunk_size > (allow_large_chunks? 62 : 27))
{
- opt.chunk_size = 62;
+ opt.chunk_size = (allow_large_chunks? 62 : 27);
log_info (_("chunk size invalid - using %d\n"), opt.chunk_size);
}
@@ -4865,9 +4875,9 @@ main (int argc, char **argv)
while( endless || count ) {
byte *p;
- /* Wee need a multiple of 3, so that in case of
+ /* We need a multiple of 3, so that in case of
armored output we get a correct string. No
- linefolding is done, as it is best to levae this to
+ linefolding is done, as it is best to leave this to
other tools */
size_t n = !endless && count < 99? count : 99;
diff --git a/g10/gpgcompose.c b/g10/gpgcompose.c
index b3f7ecdce..6f573ce46 100644
--- a/g10/gpgcompose.c
+++ b/g10/gpgcompose.c
@@ -2281,16 +2281,27 @@ sk_esk (const char *option, int argc, char *argv[], void *cookie)
/* Encrypt the session key using the s2k specifier. */
{
DEK *sesdekp = &sesdek;
+ void *enckey;
+ size_t enckeylen;
/* Now encrypt the session key (or rather, the algorithm used to
- encrypt the SKESK plus the session key) using ENCKEY. */
- err = encrypt_seskey (&s2kdek, 0, &sesdekp,
- (void**)&ske->seskey, (size_t *)&ske->seskeylen);
+ encrypt the SKESK plus the session key) using S2KDEK. */
+ err = encrypt_seskey (&s2kdek, 0, &sesdekp, &enckey, &enckeylen);
+
if (err)
log_fatal ("encrypt_seskey failed: %s\n", gpg_strerror (err));
+ if (enckeylen - 1 > sesdek.keylen)
+ log_fatal ("key size is too big: %zu\n", enckeylen);
+ else
+ {
+ ske->seskeylen = (byte)enckeylen;
+ memcpy (ske->seskey, enckey, enckeylen);
+ }
+
/* Save the session key for later. */
session_key = sesdek;
+ xfree (enckey);
}
pkt.pkttype = PKT_SYMKEY_ENC;
diff --git a/g10/gpgv.c b/g10/gpgv.c
index c142cef86..b33590655 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -490,7 +490,7 @@ read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
* No encryption here but mainproc links to these functions.
*/
gpg_error_t
-get_session_key (ctrl_t ctrl, PKT_pubkey_enc *k, DEK *dek)
+get_session_key (ctrl_t ctrl, struct pubkey_enc_list *k, DEK *dek)
{
(void)ctrl;
(void)k;
diff --git a/g10/import.c b/g10/import.c
index 5be7952d6..8ea5144b5 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -41,6 +41,7 @@
#include "../common/init.h"
#include "../common/mbox-util.h"
#include "key-check.h"
+#include "key-clean.h"
struct import_stats_s
@@ -120,6 +121,7 @@ static int chk_self_sigs (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
static int delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock,
u32 *keyid, unsigned int options);
static int any_uid_left (kbnode_t keyblock);
+static int remove_all_uids (kbnode_t *keyblock);
static int merge_blocks (ctrl_t ctrl, unsigned int options,
kbnode_t keyblock_orig,
kbnode_t keyblock, u32 *keyid,
@@ -180,6 +182,9 @@ parse_import_options(char *str,unsigned int *options,int noisy)
{"import-minimal",IMPORT_MINIMAL|IMPORT_CLEAN,NULL,
N_("remove as much as possible from key after import")},
+ {"import-drop-uids", IMPORT_DROP_UIDS, NULL,
+ N_("Do not import user id or attribute packets")},
+
{"import-export", IMPORT_EXPORT, NULL,
N_("run import filters and export key immediately")},
@@ -923,6 +928,8 @@ read_block( IOBUF a, int with_meta,
add_kbnode (root, new_kbnode (pkt));
pkt = xmalloc (sizeof *pkt);
}
+ else
+ free_packet (pkt, &parsectx);
init_packet(pkt);
break;
}
@@ -1257,7 +1264,7 @@ impex_filter_getval (void *cookie, const char *propname)
{
if (!uid->mbox)
{
- uid->mbox = mailbox_from_userid (uid->name);
+ uid->mbox = mailbox_from_userid (uid->name, 0);
}
result = uid->mbox;
}
@@ -1725,7 +1732,9 @@ import_one (ctrl_t ctrl,
}
- if (!uidnode )
+ /* Unless import-drop-uids has been requested we don't allow import
+ * of a key without UIDs. */
+ if (!uidnode && !(options & IMPORT_DROP_UIDS))
{
if (!silent)
log_error( _("key %s: no user ID\n"), keystr_from_pk(pk));
@@ -1752,15 +1761,24 @@ import_one (ctrl_t ctrl,
return 0;
}
- collapse_uids(&keyblock);
+ /* Remove or collapse the user ids. */
+ if ((options & IMPORT_DROP_UIDS))
+ remove_all_uids (&keyblock);
+ else
+ collapse_uids (&keyblock);
/* Clean the key that we're about to import, to cut down on things
that we have to clean later. This has no practical impact on the
end result, but does result in less logging which might confuse
the user. */
- if (options&IMPORT_CLEAN)
- clean_key (ctrl, keyblock,
- opt.verbose, (options&IMPORT_MINIMAL), NULL, NULL);
+ if ((options & IMPORT_CLEAN))
+ {
+ merge_keys_and_selfsig (ctrl, keyblock);
+ clean_all_uids (ctrl, keyblock,
+ opt.verbose, (options&IMPORT_MINIMAL), NULL, NULL);
+ clean_all_subkeys (ctrl, keyblock, opt.verbose, KEY_CLEAN_NONE,
+ NULL, NULL);
+ }
clear_kbnode_flags( keyblock );
@@ -1794,7 +1812,10 @@ import_one (ctrl_t ctrl,
}
}
- if (!delete_inv_parts (ctrl, keyblock, keyid, options ) )
+ /* Delete invalid parts and without the drop option bail out if
+ * there are no user ids. */
+ if (!delete_inv_parts (ctrl, keyblock, keyid, options)
+ && !(options & IMPORT_DROP_UIDS) )
{
if (!silent)
{
@@ -1901,8 +1922,13 @@ import_one (ctrl_t ctrl,
log_info (_("writing to '%s'\n"), keydb_get_resource_name (hd) );
if ((options & IMPORT_CLEAN))
- clean_key (ctrl, keyblock, opt.verbose, (options&IMPORT_MINIMAL),
- &n_uids_cleaned,&n_sigs_cleaned);
+ {
+ merge_keys_and_selfsig (ctrl, keyblock);
+ clean_all_uids (ctrl, keyblock, opt.verbose, (options&IMPORT_MINIMAL),
+ &n_uids_cleaned,&n_sigs_cleaned);
+ clean_all_subkeys (ctrl, keyblock, opt.verbose, KEY_CLEAN_NONE,
+ NULL, NULL);
+ }
/* Unless we are in restore mode apply meta data to the
* keyblock. Note that this will never change the first packet
@@ -1987,8 +2013,14 @@ import_one (ctrl_t ctrl,
goto leave;
if ((options & IMPORT_CLEAN))
- clean_key (ctrl, keyblock_orig, opt.verbose, (options&IMPORT_MINIMAL),
- &n_uids_cleaned,&n_sigs_cleaned);
+ {
+ merge_keys_and_selfsig (ctrl, keyblock_orig);
+ clean_all_uids (ctrl, keyblock_orig, opt.verbose,
+ (options&IMPORT_MINIMAL),
+ &n_uids_cleaned,&n_sigs_cleaned);
+ clean_all_subkeys (ctrl, keyblock_orig, opt.verbose, KEY_CLEAN_NONE,
+ NULL, NULL);
+ }
if (n_uids || n_sigs || n_subk || n_sigs_cleaned || n_uids_cleaned)
{
@@ -2071,9 +2103,12 @@ import_one (ctrl_t ctrl,
keydb_release (hd);
hd = NULL;
- /* Fixme: we do not track the time we last checked a key for
+ /* FIXME: We do not track the time we last checked a key for
* updates. To do this we would need to rewrite even the
- * keys which have no changes. */
+ * keys which have no changes. Adding this would be useful
+ * for the automatic update of expired keys via the WKD in
+ * case the WKD still carries the expired key. See
+ * get_best_pubkey_byname. */
same_key = 1;
if (is_status_enabled ())
print_import_ok (pk, 0);
@@ -3038,7 +3073,7 @@ chk_self_sigs (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid, int *non_self)
kbnode_t bsnode = NULL; /* Subkey binding signature node. */
u32 bsdate = 0; /* Timestamp of that node. */
kbnode_t rsnode = NULL; /* Subkey recocation signature node. */
- u32 rsdate = 0; /* Timestamp of tha node. */
+ u32 rsdate = 0; /* Timestamp of that node. */
PKT_signature *sig;
int rc;
kbnode_t n;
@@ -3395,14 +3430,51 @@ any_uid_left (kbnode_t keyblock)
-/****************
+/* Delete all user ids from KEYBLOCK.
+ * Returns: True if the keyblock has changed. */
+static int
+remove_all_uids (kbnode_t *keyblock)
+{
+ kbnode_t node;
+ int any = 0;
+
+ for (node = *keyblock; node; node = node->next)
+ {
+ if (is_deleted_kbnode (node))
+ continue;
+
+ if (node->pkt->pkttype != PKT_USER_ID)
+ continue;
+
+ /* We are at the first user id. Delete everything up to the
+ * first subkey. */
+ for (; node; node = node->next)
+ {
+ if (is_deleted_kbnode (node))
+ continue;
+
+ if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || node->pkt->pkttype == PKT_SECRET_SUBKEY)
+ break;
+ delete_kbnode (node);
+ any = 1;
+ }
+ break; /* All done. */
+ }
+
+ commit_kbnode (keyblock);
+ return any;
+}
+
+
+/*
* It may happen that the imported keyblock has duplicated user IDs.
* We check this here and collapse those user IDs together with their
* sigs into one.
* Returns: True if the keyblock has changed.
*/
int
-collapse_uids( kbnode_t *keyblock )
+collapse_uids (kbnode_t *keyblock)
{
kbnode_t uid1;
int any=0;
diff --git a/g10/key-clean.c b/g10/key-clean.c
new file mode 100644
index 000000000..d701a6665
--- /dev/null
+++ b/g10/key-clean.c
@@ -0,0 +1,614 @@
+/* key-clean.c - Functions to clean a keyblock
+ * Copyright (C) 1998-2008, 2010-2011 Free Software Foundation, Inc.
+ * Copyright (C) 2014, 2016-2018 Werner Koch
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gpg.h"
+#include "keydb.h"
+#include "../common/util.h"
+#include "../common/host2net.h"
+#include "../common/i18n.h"
+#include "options.h"
+#include "packet.h"
+#include "main.h"
+#include "key-clean.h"
+
+
+/*
+ * Mark the signature of the given UID which are used to certify it.
+ * To do this, we first revmove all signatures which are not valid and
+ * from the remain ones we look for the latest one. If this is not a
+ * certification revocation signature we mark the signature by setting
+ * node flag bit 8. Revocations are marked with flag 11, and sigs
+ * from unavailable keys are marked with flag 12. Note that flag bits
+ * 9 and 10 are used for internal purposes.
+ */
+void
+mark_usable_uid_certs (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
+ u32 *main_kid, struct key_item *klist,
+ u32 curtime, u32 *next_expire)
+{
+ kbnode_t node;
+ PKT_signature *sig;
+
+ /* First check all signatures. */
+ for (node=uidnode->next; node; node = node->next)
+ {
+ int rc;
+
+ node->flag &= ~(1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12);
+ if (node->pkt->pkttype == PKT_USER_ID
+ || node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || node->pkt->pkttype == PKT_SECRET_SUBKEY)
+ break; /* ready */
+ if (node->pkt->pkttype != PKT_SIGNATURE)
+ continue;
+ sig = node->pkt->pkt.signature;
+ if (main_kid
+ && sig->keyid[0] == main_kid[0] && sig->keyid[1] == main_kid[1])
+ continue; /* ignore self-signatures if we pass in a main_kid */
+ if (!IS_UID_SIG(sig) && !IS_UID_REV(sig))
+ continue; /* we only look at these signature classes */
+ if(sig->sig_class>=0x11 && sig->sig_class<=0x13 &&
+ sig->sig_class-0x10<opt.min_cert_level)
+ continue; /* treat anything under our min_cert_level as an
+ invalid signature */
+ if (klist && !is_in_klist (klist, sig))
+ continue; /* no need to check it then */
+ if ((rc=check_key_signature (ctrl, keyblock, node, NULL)))
+ {
+ /* we ignore anything that won't verify, but tag the
+ no_pubkey case */
+ if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY)
+ node->flag |= 1<<12;
+ continue;
+ }
+ node->flag |= 1<<9;
+ }
+ /* Reset the remaining flags. */
+ for (; node; node = node->next)
+ node->flag &= ~(1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12);
+
+ /* kbnode flag usage: bit 9 is here set for signatures to consider,
+ * bit 10 will be set by the loop to keep track of keyIDs already
+ * processed, bit 8 will be set for the usable signatures, and bit
+ * 11 will be set for usable revocations. */
+
+ /* For each cert figure out the latest valid one. */
+ for (node=uidnode->next; node; node = node->next)
+ {
+ KBNODE n, signode;
+ u32 kid[2];
+ u32 sigdate;
+
+ if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || node->pkt->pkttype == PKT_SECRET_SUBKEY)
+ break;
+ if ( !(node->flag & (1<<9)) )
+ continue; /* not a node to look at */
+ if ( (node->flag & (1<<10)) )
+ continue; /* signature with a keyID already processed */
+ node->flag |= (1<<10); /* mark this node as processed */
+ sig = node->pkt->pkt.signature;
+ signode = node;
+ sigdate = sig->timestamp;
+ kid[0] = sig->keyid[0]; kid[1] = sig->keyid[1];
+
+ /* Now find the latest and greatest signature */
+ for (n=uidnode->next; n; n = n->next)
+ {
+ if (n->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || n->pkt->pkttype == PKT_SECRET_SUBKEY)
+ break;
+ if ( !(n->flag & (1<<9)) )
+ continue;
+ if ( (n->flag & (1<<10)) )
+ continue; /* shortcut already processed signatures */
+ sig = n->pkt->pkt.signature;
+ if (kid[0] != sig->keyid[0] || kid[1] != sig->keyid[1])
+ continue;
+ n->flag |= (1<<10); /* mark this node as processed */
+
+ /* If signode is nonrevocable and unexpired and n isn't,
+ then take signode (skip). It doesn't matter which is
+ older: if signode was older then we don't want to take n
+ as signode is nonrevocable. If n was older then we're
+ automatically fine. */
+
+ if(((IS_UID_SIG(signode->pkt->pkt.signature) &&
+ !signode->pkt->pkt.signature->flags.revocable &&
+ (signode->pkt->pkt.signature->expiredate==0 ||
+ signode->pkt->pkt.signature->expiredate>curtime))) &&
+ (!(IS_UID_SIG(n->pkt->pkt.signature) &&
+ !n->pkt->pkt.signature->flags.revocable &&
+ (n->pkt->pkt.signature->expiredate==0 ||
+ n->pkt->pkt.signature->expiredate>curtime))))
+ continue;
+
+ /* If n is nonrevocable and unexpired and signode isn't,
+ then take n. Again, it doesn't matter which is older: if
+ n was older then we don't want to take signode as n is
+ nonrevocable. If signode was older then we're
+ automatically fine. */
+
+ if((!(IS_UID_SIG(signode->pkt->pkt.signature) &&
+ !signode->pkt->pkt.signature->flags.revocable &&
+ (signode->pkt->pkt.signature->expiredate==0 ||
+ signode->pkt->pkt.signature->expiredate>curtime))) &&
+ ((IS_UID_SIG(n->pkt->pkt.signature) &&
+ !n->pkt->pkt.signature->flags.revocable &&
+ (n->pkt->pkt.signature->expiredate==0 ||
+ n->pkt->pkt.signature->expiredate>curtime))))
+ {
+ signode = n;
+ sigdate = sig->timestamp;
+ continue;
+ }
+
+ /* At this point, if it's newer, it goes in as the only
+ remaining possibilities are signode and n are both either
+ revocable or expired or both nonrevocable and unexpired.
+ If the timestamps are equal take the later ordered
+ packet, presuming that the key packets are hopefully in
+ their original order. */
+
+ if (sig->timestamp >= sigdate)
+ {
+ signode = n;
+ sigdate = sig->timestamp;
+ }
+ }
+
+ sig = signode->pkt->pkt.signature;
+ if (IS_UID_SIG (sig))
+ { /* this seems to be a usable one which is not revoked.
+ * Just need to check whether there is an expiration time,
+ * We do the expired certification after finding a suitable
+ * certification, the assumption is that a signator does not
+ * want that after the expiration of his certificate the
+ * system falls back to an older certification which has a
+ * different expiration time */
+ const byte *p;
+ u32 expire;
+
+ p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_EXPIRE, NULL );
+ expire = p? sig->timestamp + buf32_to_u32(p) : 0;
+
+ if (expire==0 || expire > curtime )
+ {
+ signode->flag |= (1<<8); /* yeah, found a good cert */
+ if (next_expire && expire && expire < *next_expire)
+ *next_expire = expire;
+ }
+ }
+ else
+ signode->flag |= (1<<11);
+ }
+}
+
+
+static int
+clean_sigs_from_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
+ int noisy, int self_only)
+{
+ int deleted = 0;
+ kbnode_t node;
+ u32 keyid[2];
+
+ log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY
+ || keyblock->pkt->pkttype == PKT_SECRET_KEY);
+
+ keyid_from_pk (keyblock->pkt->pkt.public_key, keyid);
+
+ /* Passing in a 0 for current time here means that we'll never weed
+ out an expired sig. This is correct behavior since we want to
+ keep the most recent expired sig in a series. */
+ mark_usable_uid_certs (ctrl, keyblock, uidnode, NULL, NULL, 0, NULL);
+
+ /* What we want to do here is remove signatures that are not
+ considered as part of the trust calculations. Thus, all invalid
+ signatures are out, as are any signatures that aren't the last of
+ a series of uid sigs or revocations It breaks down like this:
+ coming out of mark_usable_uid_certs, if a sig is unflagged, it is
+ not even a candidate. If a sig has flag 9 or 10, that means it
+ was selected as a candidate and vetted. If a sig has flag 8 it
+ is a usable signature. If a sig has flag 11 it is a usable
+ revocation. If a sig has flag 12 it was issued by an unavailable
+ key. "Usable" here means the most recent valid
+ signature/revocation in a series from a particular signer.
+
+ Delete everything that isn't a usable uid sig (which might be
+ expired), a usable revocation, or a sig from an unavailable
+ key. */
+
+ for (node=uidnode->next;
+ node && node->pkt->pkttype==PKT_SIGNATURE;
+ node=node->next)
+ {
+ int keep;
+
+ keep = self_only? (node->pkt->pkt.signature->keyid[0] == keyid[0]
+ && node->pkt->pkt.signature->keyid[1] == keyid[1]) : 1;
+
+ /* Keep usable uid sigs ... */
+ if ((node->flag & (1<<8)) && keep)
+ continue;
+
+ /* ... and usable revocations... */
+ if ((node->flag & (1<<11)) && keep)
+ continue;
+
+ /* ... and sigs from unavailable keys. */
+ /* disabled for now since more people seem to want sigs from
+ unavailable keys removed altogether. */
+ /*
+ if(node->flag & (1<<12))
+ continue;
+ */
+
+ /* Everything else we delete */
+
+ /* At this point, if 12 is set, the signing key was unavailable.
+ If 9 or 10 is set, it's superseded. Otherwise, it's
+ invalid. */
+
+ if (noisy)
+ log_info ("removing signature from key %s on user ID \"%s\": %s\n",
+ keystr (node->pkt->pkt.signature->keyid),
+ uidnode->pkt->pkt.user_id->name,
+ node->flag&(1<<12)? "key unavailable":
+ node->flag&(1<<9)? "signature superseded"
+ /* */ :"invalid signature" );
+
+ delete_kbnode (node);
+ deleted++;
+ }
+
+ return deleted;
+}
+
+
+/* This is substantially easier than clean_sigs_from_uid since we just
+ have to establish if the uid has a valid self-sig, is not revoked,
+ and is not expired. Note that this does not take into account
+ whether the uid has a trust path to it - just whether the keyholder
+ themselves has certified the uid. Returns true if the uid was
+ compacted. To "compact" a user ID, we simply remove ALL signatures
+ except the self-sig that caused the user ID to be remove-worthy.
+ We don't actually remove the user ID packet itself since it might
+ be resurrected in a later merge. Note that this function requires
+ that the caller has already done a merge_keys_and_selfsig().
+
+ TODO: change the import code to allow importing a uid with only a
+ revocation if the uid already exists on the keyring. */
+
+static int
+clean_uid_from_key (kbnode_t keyblock, kbnode_t uidnode, int noisy)
+{
+ kbnode_t node;
+ PKT_user_id *uid = uidnode->pkt->pkt.user_id;
+ int deleted = 0;
+
+ log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY
+ || keyblock->pkt->pkttype == PKT_SECRET_KEY);
+ log_assert (uidnode->pkt->pkttype==PKT_USER_ID);
+
+ /* Skip valid user IDs, compacted user IDs, and non-self-signed user
+ IDs if --allow-non-selfsigned-uid is set. */
+ if (uid->created
+ || uid->flags.compacted
+ || (!uid->flags.expired && !uid->flags.revoked && opt.allow_non_selfsigned_uid))
+ return 0;
+
+ for (node=uidnode->next;
+ node && node->pkt->pkttype == PKT_SIGNATURE;
+ node=node->next)
+ {
+ if (!node->pkt->pkt.signature->flags.chosen_selfsig)
+ {
+ delete_kbnode (node);
+ deleted = 1;
+ uidnode->pkt->pkt.user_id->flags.compacted = 1;
+ }
+ }
+
+ if (noisy)
+ {
+ const char *reason;
+ char *user = utf8_to_native (uid->name, uid->len, 0);
+
+ if (uid->flags.revoked)
+ reason = _("revoked");
+ else if (uid->flags.expired)
+ reason = _("expired");
+ else
+ reason = _("invalid");
+
+ log_info ("compacting user ID \"%s\" on key %s: %s\n",
+ user, keystr_from_pk (keyblock->pkt->pkt.public_key),
+ reason);
+
+ xfree (user);
+ }
+
+ return deleted;
+}
+
+
+/* Needs to be called after a merge_keys_and_selfsig() */
+void
+clean_one_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
+ int noisy, int self_only, int *uids_cleaned, int *sigs_cleaned)
+{
+ int dummy = 0;
+
+ log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY
+ || keyblock->pkt->pkttype == PKT_SECRET_KEY);
+ log_assert (uidnode->pkt->pkttype==PKT_USER_ID);
+
+ if (!uids_cleaned)
+ uids_cleaned = &dummy;
+
+ if (!sigs_cleaned)
+ sigs_cleaned = &dummy;
+
+ /* Do clean_uid_from_key first since if it fires off, we don't have
+ to bother with the other. */
+ *uids_cleaned += clean_uid_from_key (keyblock, uidnode, noisy);
+ if (!uidnode->pkt->pkt.user_id->flags.compacted)
+ *sigs_cleaned += clean_sigs_from_uid (ctrl, keyblock, uidnode,
+ noisy, self_only);
+}
+
+
+/* NB: This function marks the deleted nodes only and the caller is
+ * responsible to skip or remove them. Needs to be called after a
+ * merge_keys_and_selfsig(). */
+void
+clean_all_uids (ctrl_t ctrl, kbnode_t keyblock, int noisy, int self_only,
+ int *uids_cleaned, int *sigs_cleaned)
+{
+ kbnode_t node;
+
+ for (node = keyblock->next;
+ node && !(node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || node->pkt->pkttype == PKT_SECRET_SUBKEY);
+ node = node->next)
+ {
+ if (node->pkt->pkttype == PKT_USER_ID)
+ clean_one_uid (ctrl, keyblock, node, noisy, self_only,
+ uids_cleaned, sigs_cleaned);
+ }
+
+ /* Remove bogus subkey binding signatures: The only signatures
+ * allowed are of class 0x18 and 0x28. */
+ log_assert (!node || (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || node->pkt->pkttype == PKT_SECRET_SUBKEY));
+}
+
+
+/* Helper for clean_all_subkeys. */
+static int
+clean_one_subkey (ctrl_t ctrl, kbnode_t subkeynode, int noisy, int clean_level)
+{
+ kbnode_t node;
+ PKT_public_key *pk = subkeynode->pkt->pkt.public_key;
+ unsigned int use = pk->pubkey_usage;
+ int do_clean = 0;
+
+ (void)ctrl;
+ (void)noisy;
+
+ log_assert (subkeynode->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || subkeynode->pkt->pkttype == PKT_SECRET_SUBKEY);
+
+ if (DBG_LOOKUP)
+ log_debug ("\tchecking subkey %08lX [%c%c%c%c%c]\n",
+ (ulong) keyid_from_pk (pk, NULL),
+ (use & PUBKEY_USAGE_ENC)? 'e':'-',
+ (use & PUBKEY_USAGE_SIG)? 's':'-',
+ (use & PUBKEY_USAGE_CERT)? 'c':'-',
+ (use & PUBKEY_USAGE_AUTH)? 'a':'-',
+ (use & PUBKEY_USAGE_UNKNOWN)? '?':'-');
+
+ if (!pk->flags.valid)
+ {
+ if (DBG_LOOKUP)
+ log_debug ("\tsubkey not valid\n");
+ if (clean_level == KEY_CLEAN_INVALID)
+ do_clean = 1;
+ }
+ if (pk->has_expired)
+ {
+ if (DBG_LOOKUP)
+ log_debug ("\tsubkey has expired\n");
+ if (clean_level == KEY_CLEAN_ALL)
+ do_clean = 1;
+ else if (clean_level == KEY_CLEAN_AUTHENCR
+ && (use & (PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH))
+ && !(use & (PUBKEY_USAGE_SIG | PUBKEY_USAGE_CERT)))
+ do_clean = 1;
+ else if (clean_level == KEY_CLEAN_ENCR
+ && (use & PUBKEY_USAGE_ENC)
+ && !(use & (PUBKEY_USAGE_SIG | PUBKEY_USAGE_CERT
+ | PUBKEY_USAGE_AUTH)))
+ do_clean = 1;
+ }
+ if (pk->flags.revoked)
+ {
+ if (DBG_LOOKUP)
+ log_debug ("\tsubkey has been revoked (keeping)\n");
+ /* Avoid any cleaning because revocations are important. */
+ do_clean = 0;
+ }
+ if (!do_clean)
+ return 0;
+
+ if (DBG_LOOKUP)
+ log_debug ("\t=> removing this subkey\n");
+
+ delete_kbnode (subkeynode);
+ for (node = subkeynode->next;
+ node && !(node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || node->pkt->pkttype == PKT_SECRET_SUBKEY);
+ node = node->next)
+ delete_kbnode (node);
+
+ return 1;
+}
+
+
+/* Helper for clean_all_subkeys. Here duplicate signatures from a
+ * subkey are removed. This should in general not happen because
+ * import takes care of that. However, sometimes other tools are used
+ * to manage a keyring or key has been imported a long time ago. */
+static int
+clean_one_subkey_dupsigs (ctrl_t ctrl, kbnode_t subkeynode)
+{
+ kbnode_t node;
+ PKT_public_key *pk = subkeynode->pkt->pkt.public_key;
+ int any_choosen = 0;
+ int count = 0;
+
+ (void)ctrl;
+
+ log_assert (subkeynode->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || subkeynode->pkt->pkttype == PKT_SECRET_SUBKEY);
+
+ if (DBG_LOOKUP)
+ log_debug ("\tchecking subkey %08lX for dupsigs\n",
+ (ulong) keyid_from_pk (pk, NULL));
+
+ /* First check that the chosen flag has been set. Note that we
+ * only look at plain signatures so to keep all revocation
+ * signatures which may carry important information. */
+ for (node = subkeynode->next;
+ node && !(node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || node->pkt->pkttype == PKT_SECRET_SUBKEY);
+ node = node->next)
+ {
+ if (!is_deleted_kbnode (node)
+ && node->pkt->pkttype == PKT_SIGNATURE
+ && IS_SUBKEY_SIG (node->pkt->pkt.signature)
+ && node->pkt->pkt.signature->flags.chosen_selfsig)
+ {
+ any_choosen = 1;
+ break;
+ }
+ }
+
+ if (!any_choosen)
+ return 0; /* Ooops no chosen flag set - we can't decide. */
+
+ for (node = subkeynode->next;
+ node && !(node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || node->pkt->pkttype == PKT_SECRET_SUBKEY);
+ node = node->next)
+ {
+ if (!is_deleted_kbnode (node)
+ && node->pkt->pkttype == PKT_SIGNATURE
+ && IS_SUBKEY_SIG (node->pkt->pkt.signature)
+ && !node->pkt->pkt.signature->flags.chosen_selfsig)
+ {
+ delete_kbnode (node);
+ count++;
+ }
+ }
+
+ return count;
+}
+
+
+/* This function only marks the deleted nodes and the caller is
+ * responsible to skip or remove them. Needs to be called after a
+ * merge_keys_and_selfsig. CLEAN_LEVEL is one of the KEY_CLEAN_*
+ * values. */
+void
+clean_all_subkeys (ctrl_t ctrl, kbnode_t keyblock, int noisy, int clean_level,
+ int *subkeys_cleaned, int *sigs_cleaned)
+{
+ kbnode_t first_subkey, node;
+ int n;
+
+ if (DBG_LOOKUP)
+ log_debug ("clean_all_subkeys: checking key %08lX\n",
+ (ulong) keyid_from_pk (keyblock->pkt->pkt.public_key, NULL));
+
+ for (node = keyblock->next; node; node = node->next)
+ if (!is_deleted_kbnode (node)
+ && (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || node->pkt->pkttype == PKT_SECRET_SUBKEY))
+ break;
+ first_subkey = node;
+
+ /* Remove bogus subkey binding signatures: The only signatures
+ * allowed are of class 0x18 and 0x28. */
+ for (node = first_subkey; node; node = node->next)
+ {
+ if (is_deleted_kbnode (node))
+ continue;
+ if (node->pkt->pkttype == PKT_SIGNATURE
+ && !(IS_SUBKEY_SIG (node->pkt->pkt.signature)
+ || IS_SUBKEY_REV (node->pkt->pkt.signature)))
+ {
+ delete_kbnode (node);
+ if (sigs_cleaned)
+ ++*sigs_cleaned;
+ }
+ }
+
+ /* Do the selected cleaning. */
+ if (clean_level > KEY_CLEAN_NONE)
+ {
+ /* Clean enitre subkeys. */
+ for (node = first_subkey; node; node = node->next)
+ {
+ if (is_deleted_kbnode (node))
+ continue;
+ if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || node->pkt->pkttype == PKT_SECRET_SUBKEY)
+ {
+ if (clean_one_subkey (ctrl, node, noisy, clean_level))
+ {
+ if (subkeys_cleaned)
+ ++*subkeys_cleaned;
+ }
+ }
+ }
+
+ /* Clean duplicate signatures from a subkey. */
+ for (node = first_subkey; node; node = node->next)
+ {
+ if (is_deleted_kbnode (node))
+ continue;
+ if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || node->pkt->pkttype == PKT_SECRET_SUBKEY)
+ {
+ n = clean_one_subkey_dupsigs (ctrl, node);
+ if (sigs_cleaned)
+ *sigs_cleaned += n;
+ }
+ }
+ }
+}
diff --git a/g10/key-clean.h b/g10/key-clean.h
new file mode 100644
index 000000000..c4f164928
--- /dev/null
+++ b/g10/key-clean.h
@@ -0,0 +1,52 @@
+/* key-clean.h - Functions to clean a keyblock
+ * Copyright (C) 2018 Werner Koch
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#ifndef GNUPG_G10_KEY_CLEAN_H
+#define GNUPG_G10_KEY_CLEAN_H
+
+#include "gpg.h"
+
+/* No explicit cleaning. */
+#define KEY_CLEAN_NONE 0
+/* Remove only invalid subkeys (ie. missing key-bindings) */
+#define KEY_CLEAN_INVALID 1
+/* Remove expired encryption keys */
+#define KEY_CLEAN_ENCR 2
+/* Remove expired authentication and encryption keys. */
+#define KEY_CLEAN_AUTHENCR 3
+/* Remove all expired subkeys. */
+#define KEY_CLEAN_ALL 4
+
+
+void mark_usable_uid_certs (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
+ u32 *main_kid, struct key_item *klist,
+ u32 curtime, u32 *next_expire);
+
+void clean_one_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
+ int noisy, int self_only,
+ int *uids_cleaned, int *sigs_cleaned);
+void clean_all_uids (ctrl_t ctrl, kbnode_t keyblock, int noisy, int self_only,
+ int *uids_cleaned,int *sigs_cleaned);
+void clean_all_subkeys (ctrl_t ctrl, kbnode_t keyblock,
+ int noisy, int clean_level,
+ int *subkeys_cleaned, int *sigs_cleaned);
+
+
+#endif /*GNUPG_G10_KEY_CLEAN_H*/
diff --git a/g10/keydb.h b/g10/keydb.h
index bd156a6a3..1def2bb81 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -64,6 +64,20 @@ struct kbnode_struct {
#define is_cloned_kbnode(a) ((a)->private_flag & 2)
+/*
+ * A structure to store key identification as well as some stuff
+ * needed for key validation.
+ */
+struct key_item {
+ struct key_item *next;
+ unsigned int ownertrust,min_ownertrust;
+ byte trust_depth;
+ byte trust_value;
+ char *trust_regexp;
+ u32 kid[2];
+};
+
+
/* Bit flags used with build_pk_list. */
enum
{
@@ -133,6 +147,22 @@ enum
};
+/*
+ * Check whether the signature SIG is in the klist K.
+ */
+static inline struct key_item *
+is_in_klist (struct key_item *k, PKT_signature *sig)
+{
+ for (; k; k = k->next)
+ {
+ if (k->kid[0] == sig->keyid[0] && k->kid[1] == sig->keyid[1])
+ return k;
+ }
+ return NULL;
+}
+
+
+
/*-- keydb.c --*/
#define KEYDB_RESOURCE_FLAG_PRIMARY 2 /* The primary resource. */
@@ -283,6 +313,10 @@ void cache_public_key( PKT_public_key *pk );
/* Disable and drop the public key cache. */
void getkey_disable_caches(void);
+/* Return the public key used for signature SIG and store it at PK. */
+gpg_error_t get_pubkey_for_sig (ctrl_t ctrl,
+ PKT_public_key *pk, PKT_signature *sig);
+
/* Return the public key with the key id KEYID and store it at PK. */
int get_pubkey (ctrl_t ctrl, PKT_public_key *pk, u32 *keyid);
@@ -291,6 +325,10 @@ int get_pubkey (ctrl_t ctrl, PKT_public_key *pk, u32 *keyid);
also only considers primary keys. */
int get_pubkey_fast (PKT_public_key *pk, u32 *keyid);
+/* Return the entire keyblock used to create SIG. This is a
+ * specialized version of get_pubkeyblock. */
+kbnode_t get_pubkeyblock_for_sig (ctrl_t ctrl, PKT_signature *sig);
+
/* Return the key block for the key with KEYID. */
kbnode_t get_pubkeyblock (ctrl_t ctrl, u32 *keyid);
@@ -304,20 +342,9 @@ struct pubkey_s
};
typedef struct pubkey_s *pubkey_t;
-/* Free a single key. This does not remove key from any list! */
-void pubkey_free (pubkey_t key);
-
/* Free a list of public keys. */
void pubkeys_free (pubkey_t keys);
-/* Returns all keys that match the search specification SEARCH_TERMS.
- The returned keys should be freed using pubkeys_free. */
-gpg_error_t
-get_pubkeys (ctrl_t ctrl,
- char *search_terms, int use, int include_unusable, char *source,
- int warn_possibly_ambiguous,
- pubkey_t *r_keys);
-
/* Find a public key identified by NAME. */
int get_pubkey_byname (ctrl_t ctrl,
GETKEY_CTX *retctx, PKT_public_key *pk,
@@ -330,7 +357,7 @@ int get_pubkey_byname (ctrl_t ctrl,
gpg_error_t get_best_pubkey_byname (ctrl_t ctrl,
GETKEY_CTX *retctx, PKT_public_key *pk,
const char *name, KBNODE *ret_keyblock,
- int include_unusable, int no_akl);
+ int include_unusable);
/* Get a public key directly from file FNAME. */
gpg_error_t get_pubkey_fromfile (ctrl_t ctrl,
diff --git a/g10/keyedit.c b/g10/keyedit.c
index 00b4e7280..9716ed9d6 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -49,6 +49,7 @@
#include "../common/host2net.h"
#include "tofu.h"
#include "key-check.h"
+#include "key-clean.h"
#include "keyedit.h"
static void show_prefs (PKT_user_id * uid, PKT_signature * selfsig,
diff --git a/g10/keygen.c b/g10/keygen.c
index 9e9cead07..145b871b0 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -450,7 +450,7 @@ keygen_set_std_prefs (const char *string,int personal)
}
/* In case we have no compress algo at all, declare that
- we prefer no compresssion. */
+ we prefer no compression. */
if (!any_compress)
strcat(dummy_string,"Z0 ");
@@ -3293,7 +3293,7 @@ parse_key_parameter_string (const char *string, int part,
* part consider this to be the subkey algo. In case a
* SUGGESTED_USE has been given and the usage of the secondary
* part does not match SUGGESTED_USE try again using the primary
- * part. Noet thar when falling back to the primary key we need
+ * part. Note that when falling back to the primary key we need
* to force clearing the cert usage. */
if (secondary)
{
@@ -4238,8 +4238,10 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
if (opt.batch && card_serialno)
{
- /* We don't yet support unattended key generation. */
+ /* We don't yet support unattended key generation with a card
+ * serial number. */
log_error (_("can't do this in batch mode\n"));
+ print_further_info ("key generation with card serial number");
return;
}
diff --git a/g10/keylist.c b/g10/keylist.c
index 39b87e49f..793f7dacd 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -653,7 +653,7 @@ locate_one (ctrl_t ctrl, strlist_t names)
for (sl = names; sl; sl = sl->next)
{
- rc = get_best_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, 1, 0);
+ rc = get_best_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, 1);
if (rc)
{
if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)
@@ -1020,7 +1020,7 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
char *mbox, *hash, *p;
char hashbuf[32];
- mbox = mailbox_from_userid (uid->name);
+ mbox = mailbox_from_userid (uid->name, 0);
if (mbox && (p = strchr (mbox, '@')))
{
*p++ = 0;
diff --git a/g10/keyserver.c b/g10/keyserver.c
index a8c222d3f..44870a610 100644
--- a/g10/keyserver.c
+++ b/g10/keyserver.c
@@ -2053,7 +2053,7 @@ keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick,
/* We want to work on the mbox. That is what dirmngr will do anyway
* and we need the mbox for the import filter anyway. */
- mbox = mailbox_from_userid (name);
+ mbox = mailbox_from_userid (name, 0);
if (!mbox)
{
err = gpg_error_from_syserror ();
diff --git a/g10/mainproc.c b/g10/mainproc.c
index a9da08f74..7eceb7e0b 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -46,16 +46,6 @@
#define MAX_NESTING_DEPTH 32
-/* An object to build a list of keyid related info. */
-struct kidlist_item
-{
- struct kidlist_item *next;
- u32 kid[2];
- int pubkey_algo;
- int reason;
-};
-
-
/*
* Object to hold the processing context.
*/
@@ -95,7 +85,8 @@ struct mainproc_context
iobuf_t iobuf; /* Used to get the filename etc. */
int trustletter; /* Temporary usage in list_node. */
ulong symkeys; /* Number of symmetrically encrypted session keys. */
- struct kidlist_item *pkenc_list; /* List of encryption packets. */
+ struct pubkey_enc_list *pkenc_list; /* List of encryption packets. */
+ int seen_pkt_encrypted_aead; /* PKT_ENCRYPTED_AEAD packet seen. */
struct {
unsigned int sig_seen:1; /* Set to true if a signature packet
has been seen. */
@@ -112,7 +103,7 @@ static int literals_seen;
/*** Local prototypes. ***/
-static int do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a);
+static int do_proc_packets (CTX c, iobuf_t a);
static void list_node (CTX c, kbnode_t node);
static void proc_tree (CTX c, kbnode_t node);
@@ -135,7 +126,10 @@ release_list( CTX c )
release_kbnode (c->list);
while (c->pkenc_list)
{
- struct kidlist_item *tmp = c->pkenc_list->next;
+ struct pubkey_enc_list *tmp = c->pkenc_list->next;
+
+ mpi_release (c->pkenc_list->data[0]);
+ mpi_release (c->pkenc_list->data[1]);
xfree (c->pkenc_list);
c->pkenc_list = tmp;
}
@@ -144,6 +138,7 @@ release_list( CTX c )
c->any.data = 0;
c->any.uncompress_failed = 0;
c->last_was_session_key = 0;
+ c->seen_pkt_encrypted_aead = 0;
xfree (c->dek);
c->dek = NULL;
}
@@ -458,10 +453,9 @@ proc_symkey_enc (CTX c, PACKET *pkt)
static void
-proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
+proc_pubkey_enc (CTX c, PACKET *pkt)
{
PKT_pubkey_enc *enc;
- int result = 0;
/* Check whether the secret key is available and store in this case. */
c->last_was_session_key = 1;
@@ -472,76 +466,29 @@ proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
if (opt.verbose)
log_info (_("public key is %s\n"), keystr (enc->keyid));
- if (is_status_enabled())
+ if (is_status_enabled ())
{
char buf[50];
snprintf (buf, sizeof buf, "%08lX%08lX %d 0",
- (ulong)enc->keyid[0], (ulong)enc->keyid[1], enc->pubkey_algo);
+ (ulong)enc->keyid[0], (ulong)enc->keyid[1], enc->pubkey_algo);
write_status_text (STATUS_ENC_TO, buf);
}
- if (!opt.list_only && opt.override_session_key)
+ if (!opt.list_only && !opt.override_session_key)
{
- /* It does not make much sense to store the session key in
- * secure memory because it has already been passed on the
- * command line and the GCHQ knows about it. */
- c->dek = xmalloc_clear (sizeof *c->dek);
- result = get_override_session_key (c->dek, opt.override_session_key);
- if (result)
- {
- xfree (c->dek);
- c->dek = NULL;
- }
- }
- else if (enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E
- || enc->pubkey_algo == PUBKEY_ALGO_ECDH
- || enc->pubkey_algo == PUBKEY_ALGO_RSA
- || enc->pubkey_algo == PUBKEY_ALGO_RSA_E
- || enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL)
- {
- /* Note that we also allow type 20 Elgamal keys for decryption.
- There are still a couple of those keys in active use as a
- subkey. */
-
- /* FIXME: Store this all in a list and process it later so that
- we can prioritize what key to use. This gives a better user
- experience if wildcard keyids are used. */
- if (!c->dek && ((!enc->keyid[0] && !enc->keyid[1])
- || opt.try_all_secrets
- || have_secret_key_with_kid (enc->keyid)))
- {
- if(opt.list_only)
- result = GPG_ERR_MISSING_ACTION; /* fixme: Use better error code. */
- else
- {
- c->dek = xmalloc_secure_clear (sizeof *c->dek);
- if ((result = get_session_key (ctrl, enc, c->dek)))
- {
- /* Error: Delete the DEK. */
- xfree (c->dek);
- c->dek = NULL;
- }
- }
- }
- else
- result = GPG_ERR_NO_SECKEY;
- }
- else
- result = GPG_ERR_PUBKEY_ALGO;
+ struct pubkey_enc_list *x = xmalloc (sizeof *x);
- if (1)
- {
- /* Store it for later display. */
- struct kidlist_item *x = xmalloc (sizeof *x);
- x->kid[0] = enc->keyid[0];
- x->kid[1] = enc->keyid[1];
+ x->keyid[0] = enc->keyid[0];
+ x->keyid[1] = enc->keyid[1];
x->pubkey_algo = enc->pubkey_algo;
- x->reason = result;
+ x->data[0] = x->data[1] = NULL;
+ if (enc->data[0])
+ {
+ x->data[0] = mpi_copy (enc->data[0]);
+ x->data[1] = mpi_copy (enc->data[1]);
+ }
x->next = c->pkenc_list;
c->pkenc_list = x;
-
- if (!result && opt.verbose > 1)
- log_info (_("public key encrypted data: good DEK\n"));
}
free_packet(pkt, NULL);
@@ -553,60 +500,34 @@ proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
* not decrypt.
*/
static void
-print_pkenc_list (ctrl_t ctrl, struct kidlist_item *list, int failed)
+print_pkenc_list (ctrl_t ctrl, struct pubkey_enc_list *list)
{
for (; list; list = list->next)
{
PKT_public_key *pk;
const char *algstr;
- if (failed && !list->reason)
- continue;
- if (!failed && list->reason)
- continue;
-
algstr = openpgp_pk_algo_name (list->pubkey_algo);
pk = xmalloc_clear (sizeof *pk);
if (!algstr)
algstr = "[?]";
pk->pubkey_algo = list->pubkey_algo;
- if (!get_pubkey (ctrl, pk, list->kid))
+ if (!get_pubkey (ctrl, pk, list->keyid))
{
char *p;
log_info (_("encrypted with %u-bit %s key, ID %s, created %s\n"),
nbits_from_pk (pk), algstr, keystr_from_pk(pk),
strtimestamp (pk->timestamp));
- p = get_user_id_native (ctrl, list->kid);
+ p = get_user_id_native (ctrl, list->keyid);
log_printf (_(" \"%s\"\n"), p);
xfree (p);
}
else
log_info (_("encrypted with %s key, ID %s\n"),
- algstr, keystr(list->kid));
+ algstr, keystr(list->keyid));
free_public_key (pk);
-
- if (gpg_err_code (list->reason) == GPG_ERR_NO_SECKEY)
- {
- if (is_status_enabled())
- {
- char buf[20];
- snprintf (buf, sizeof buf, "%08lX%08lX",
- (ulong)list->kid[0], (ulong)list->kid[1]);
- write_status_text (STATUS_NO_SECKEY, buf);
- }
- }
- else if (gpg_err_code (list->reason) == GPG_ERR_MISSING_ACTION)
- {
- /* Not tested for secret key due to --list-only mode. */
- }
- else if (list->reason)
- {
- log_info (_("public key decryption failed: %s\n"),
- gpg_strerror (list->reason));
- write_status_error ("pkdecrypt_failed", list->reason);
- }
}
}
@@ -617,6 +538,9 @@ proc_encrypted (CTX c, PACKET *pkt)
int result = 0;
int early_plaintext = literals_seen;
+ if (pkt->pkttype == PKT_ENCRYPTED_AEAD)
+ c->seen_pkt_encrypted_aead = 1;
+
if (early_plaintext)
{
log_info (_("WARNING: multiple plaintexts seen\n"));
@@ -630,11 +554,58 @@ proc_encrypted (CTX c, PACKET *pkt)
log_info (_("encrypted with %lu passphrases\n"), c->symkeys);
else if (c->symkeys == 1)
log_info (_("encrypted with 1 passphrase\n"));
- print_pkenc_list (c->ctrl, c->pkenc_list, 1 );
- print_pkenc_list (c->ctrl, c->pkenc_list, 0 );
+ print_pkenc_list (c->ctrl, c->pkenc_list);
}
- /* FIXME: Figure out the session key by looking at all pkenc packets. */
+ /* Figure out the session key by looking at all pkenc packets. */
+ if (opt.list_only || c->dek)
+ ;
+ else if (opt.override_session_key)
+ {
+ c->dek = xmalloc_clear (sizeof *c->dek);
+ result = get_override_session_key (c->dek, opt.override_session_key);
+ if (result)
+ {
+ xfree (c->dek);
+ c->dek = NULL;
+ log_info (_("public key decryption failed: %s\n"),
+ gpg_strerror (result));
+ write_status_error ("pkdecrypt_failed", result);
+ }
+ }
+ else
+ {
+ c->dek = xmalloc_secure_clear (sizeof *c->dek);
+ result = get_session_key (c->ctrl, c->pkenc_list, c->dek);
+ if (result == GPG_ERR_NO_SECKEY)
+ {
+ if (is_status_enabled ())
+ {
+ struct pubkey_enc_list *list;
+
+ for (list = c->pkenc_list; list; list = list->next)
+ {
+ char buf[20];
+ snprintf (buf, sizeof buf, "%08lX%08lX",
+ (ulong)list->keyid[0], (ulong)list->keyid[1]);
+ write_status_text (STATUS_NO_SECKEY, buf);
+ }
+ }
+ }
+ else if (result)
+ {
+ log_info (_("public key decryption failed: %s\n"),
+ gpg_strerror (result));
+ write_status_error ("pkdecrypt_failed", result);
+
+ /* Error: Delete the DEK. */
+ xfree (c->dek);
+ c->dek = NULL;
+ }
+ }
+
+ if (c->dek && opt.verbose > 1)
+ log_info (_("public key encrypted data: good DEK\n"));
write_status (STATUS_BEGIN_DECRYPTION);
@@ -709,7 +680,7 @@ proc_encrypted (CTX c, PACKET *pkt)
&& gnupg_cipher_is_compliant (CO_DE_VS, c->dek->algo,
GCRY_CIPHER_MODE_CFB))
{
- struct kidlist_item *i;
+ struct pubkey_enc_list *i;
int compliant = 1;
PKT_public_key *pk = xmalloc (sizeof *pk);
@@ -722,7 +693,7 @@ proc_encrypted (CTX c, PACKET *pkt)
{
memset (pk, 0, sizeof *pk);
pk->pubkey_algo = i->pubkey_algo;
- if (get_pubkey (c->ctrl, pk, i->kid) != 0
+ if (get_pubkey (c->ctrl, pk, i->keyid) != 0
|| ! gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, pk->pkey,
nbits_from_pk (pk), NULL))
compliant = 0;
@@ -738,7 +709,6 @@ proc_encrypted (CTX c, PACKET *pkt)
}
-
if (!result)
result = decrypt_data (c->ctrl, c, pkt->pkt.encrypted, c->dek );
@@ -838,6 +808,21 @@ proc_encrypted (CTX c, PACKET *pkt)
}
+static int
+have_seen_pkt_encrypted_aead( CTX c )
+{
+ CTX cc;
+
+ for (cc = c; cc; cc = cc->anchor)
+ {
+ if (cc->seen_pkt_encrypted_aead)
+ return 1;
+ }
+
+ return 0;
+}
+
+
static void
proc_plaintext( CTX c, PACKET *pkt )
{
@@ -845,7 +830,7 @@ proc_plaintext( CTX c, PACKET *pkt )
int any, clearsig, rc;
kbnode_t n;
- /* This is a literal data packet. Bumb a counter for later checks. */
+ /* This is a literal data packet. Bump a counter for later checks. */
literals_seen++;
if (pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8))
@@ -908,7 +893,7 @@ proc_plaintext( CTX c, PACKET *pkt )
}
}
- if (!any && !opt.skip_verify)
+ if (!any && !opt.skip_verify && !have_seen_pkt_encrypted_aead(c))
{
/* This is for the old GPG LITERAL+SIG case. It's not legal
according to 2440, so hopefully it won't come up that often.
@@ -1367,7 +1352,7 @@ proc_packets (ctrl_t ctrl, void *anchor, iobuf_t a )
c->ctrl = ctrl;
c->anchor = anchor;
- rc = do_proc_packets (ctrl, c, a);
+ rc = do_proc_packets (c, a);
xfree (c);
return rc;
@@ -1390,7 +1375,7 @@ proc_signature_packets (ctrl_t ctrl, void *anchor, iobuf_t a,
c->signed_data.used = !!signedfiles;
c->sigfilename = sigfilename;
- rc = do_proc_packets (ctrl, c, a);
+ rc = do_proc_packets (c, a);
/* If we have not encountered any signature we print an error
messages, send a NODATA status back and return an error code.
@@ -1433,7 +1418,7 @@ proc_signature_packets_by_fd (ctrl_t ctrl,
c->signed_data.data_names = NULL;
c->signed_data.used = (signed_data_fd != -1);
- rc = do_proc_packets (ctrl, c, a);
+ rc = do_proc_packets (c, a);
/* If we have not encountered any signature we print an error
messages, send a NODATA status back and return an error code.
@@ -1466,7 +1451,7 @@ proc_encryption_packets (ctrl_t ctrl, void *anchor, iobuf_t a )
c->ctrl = ctrl;
c->anchor = anchor;
c->encrypt_only = 1;
- rc = do_proc_packets (ctrl, c, a);
+ rc = do_proc_packets (c, a);
xfree (c);
return rc;
}
@@ -1492,7 +1477,7 @@ check_nesting (CTX c)
static int
-do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
+do_proc_packets (CTX c, iobuf_t a)
{
PACKET *pkt;
struct parse_packet_ctx_s parsectx;
@@ -1526,7 +1511,7 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
{
switch (pkt->pkttype)
{
- case PKT_PUBKEY_ENC: proc_pubkey_enc (ctrl, c, pkt); break;
+ case PKT_PUBKEY_ENC: proc_pubkey_enc (c, pkt); break;
case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break;
case PKT_ENCRYPTED:
case PKT_ENCRYPTED_MDC:
@@ -1572,7 +1557,7 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
case PKT_SIGNATURE: newpkt = add_signature (c, pkt); break;
case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break;
- case PKT_PUBKEY_ENC: proc_pubkey_enc (ctrl, c, pkt); break;
+ case PKT_PUBKEY_ENC: proc_pubkey_enc (c, pkt); break;
case PKT_ENCRYPTED:
case PKT_ENCRYPTED_MDC:
case PKT_ENCRYPTED_AEAD: proc_encrypted (c, pkt); break;
@@ -1599,7 +1584,7 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
break;
case PKT_USER_ID: newpkt = add_user_id (c, pkt); break;
case PKT_SIGNATURE: newpkt = add_signature (c, pkt); break;
- case PKT_PUBKEY_ENC: proc_pubkey_enc (ctrl, c, pkt); break;
+ case PKT_PUBKEY_ENC: proc_pubkey_enc (c, pkt); break;
case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break;
case PKT_ENCRYPTED:
case PKT_ENCRYPTED_MDC:
@@ -1751,7 +1736,7 @@ akl_has_wkd_method (void)
/* Return the ISSUER fingerprint buffer and its lenbgth at R_LEN.
* Returns NULL if not available. The returned buffer is valid as
* long as SIG is not modified. */
-static const byte *
+const byte *
issuer_fpr_raw (PKT_signature *sig, size_t *r_len)
{
const byte *p;
@@ -1768,7 +1753,7 @@ issuer_fpr_raw (PKT_signature *sig, size_t *r_len)
}
-/* Return the ISSUER fingerprint string in human readbale format if
+/* Return the ISSUER fingerprint string in human readable format if
* available. Caller must release the string. */
/* FIXME: Move to another file. */
char *
@@ -2134,7 +2119,7 @@ check_sig_and_print (CTX c, kbnode_t node)
* keyblock has already been fetched. Thus we could use the
* fingerprint or PK itself to lookup the entire keyblock. That
* would best be done with a cache. */
- keyblock = get_pubkeyblock (c->ctrl, sig->keyid);
+ keyblock = get_pubkeyblock_for_sig (c->ctrl, sig);
snprintf (keyid_str, sizeof keyid_str, "%08lX%08lX [uncertain] ",
(ulong)sig->keyid[0], (ulong)sig->keyid[1]);
diff --git a/g10/misc.c b/g10/misc.c
index d7a3ee3f2..f129e8327 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -549,7 +549,7 @@ openpgp_cipher_blocklen (cipher_algo_t algo)
/****************
* Wrapper around the libgcrypt function with additional checks on
- * the OpenPGP contraints for the algo ID.
+ * the OpenPGP constraints for the algo ID.
*/
int
openpgp_cipher_test_algo (cipher_algo_t algo)
@@ -712,7 +712,7 @@ openpgp_pk_test_algo2 (pubkey_algo_t algo, unsigned int use)
#endif
case PUBKEY_ALGO_ELGAMAL:
- /* Dont't allow type 20 keys unless in rfc2440 mode. */
+ /* Don't allow type 20 keys unless in rfc2440 mode. */
if (RFC2440)
ga = GCRY_PK_ELG;
break;
@@ -1521,6 +1521,8 @@ optlen(const char *s)
return strlen(s);
}
+
+/* Note: This function returns true on success. */
int
parse_options(char *str,unsigned int *options,
struct parse_options *opts,int noisy)
diff --git a/g10/options.h b/g10/options.h
index 7defbda76..faaf53503 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -360,6 +360,7 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
#define IMPORT_RESTORE (1<<10)
#define IMPORT_REPAIR_KEYS (1<<11)
#define IMPORT_DRY_RUN (1<<12)
+#define IMPORT_DROP_UIDS (1<<13)
#define EXPORT_LOCAL_SIGS (1<<0)
#define EXPORT_ATTRIBUTES (1<<1)
@@ -370,6 +371,7 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
#define EXPORT_PKA_FORMAT (1<<6)
#define EXPORT_DANE_FORMAT (1<<7)
#define EXPORT_BACKUP (1<<10)
+#define EXPORT_DROP_UIDS (1<<13)
#define LIST_SHOW_PHOTOS (1<<0)
#define LIST_SHOW_POLICY_URLS (1<<1)
diff --git a/g10/packet.h b/g10/packet.h
index 40a8c4bf6..d088bf432 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -131,6 +131,16 @@ typedef struct {
} PKT_pubkey_enc;
+/* An object to build a list of public-key encrypted session key. */
+struct pubkey_enc_list
+{
+ struct pubkey_enc_list *next;
+ u32 keyid[2];
+ int pubkey_algo;
+ gcry_mpi_t data[PUBKEY_MAX_NENC];
+};
+
+
/* A one-pass signature packet as defined in RFC 4880, Section
5.4. All fields are serialized. */
typedef struct {
@@ -234,7 +244,7 @@ typedef struct
const byte *trust_regexp;
struct revocation_key *revkey;
int numrevkeys;
- int help_counter; /* Used internally bu some fucntions. */
+ int help_counter; /* Used internally bu some functions. */
pka_info_t *pka_info; /* Malloced PKA data or NULL if not
available. See also flags.pka_tried. */
char *signers_uid; /* Malloced value of the SIGNERS_UID
@@ -621,10 +631,14 @@ int proc_signature_packets_by_fd (ctrl_t ctrl,
int proc_encryption_packets (ctrl_t ctrl, void *ctx, iobuf_t a);
int list_packets( iobuf_t a );
+const byte *issuer_fpr_raw (PKT_signature *sig, size_t *r_len);
char *issuer_fpr_string (PKT_signature *sig);
/*-- parse-packet.c --*/
+
+void register_known_notation (const char *string);
+
/* Sets the packet list mode to MODE (i.e., whether we are dumping a
packet or not). Returns the current mode. This allows for
temporarily suspending dumping by doing the following:
@@ -888,7 +902,7 @@ gpg_error_t check_signature2 (ctrl_t ctrl,
/*-- pubkey-enc.c --*/
-gpg_error_t get_session_key (ctrl_t ctrl, PKT_pubkey_enc *k, DEK *dek);
+gpg_error_t get_session_key (ctrl_t ctrl, struct pubkey_enc_list *k, DEK *dek);
gpg_error_t get_override_session_key (DEK *dek, const char *string);
/*-- compress.c --*/
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index e933abfa0..c0f2ca12e 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -43,11 +43,15 @@
#define MAX_COMMENT_PACKET_LENGTH ( 64 * 1024)
#define MAX_ATTR_PACKET_LENGTH ( 16 * 1024*1024)
-
static int mpi_print_mode;
static int list_mode;
static estream_t listfp;
+/* A linked list of known notation names. Note that the FLAG is used
+ * to store the length of the name to speed up the check. */
+static strlist_t known_notations_list;
+
+
static int parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts,
off_t * retpos, int *skip, IOBUF out, int do_skip
#if DEBUG_PARSE_PACKET
@@ -189,6 +193,36 @@ mpi_read (iobuf_t inp, unsigned int *ret_nread, int secure)
}
+/* Register STRING as a known critical notation name. */
+void
+register_known_notation (const char *string)
+{
+ strlist_t sl;
+
+ if (!known_notations_list)
+ {
+ sl = add_to_strlist (&known_notations_list,
+ sl->flags = 32;
+ sl = add_to_strlist (&known_notations_list, "[email protected]");
+ sl->flags = 21;
+ }
+ if (!string)
+ return; /* Only initialized the default known notations. */
+
+ /* In --set-notation we use an exclamation mark to indicate a
+ * critical notation. As a convenience skip this here. */
+ if (*string == '!')
+ string++;
+
+ if (!*string || strlist_find (known_notations_list, string))
+ return; /* Empty string or already registered. */
+
+ sl = add_to_strlist (&known_notations_list, string);
+ sl->flags = strlen (string);
+}
+
+
int
set_packet_list_mode (int mode)
{
@@ -1186,7 +1220,7 @@ parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen,
}
if (s2kmode == 3)
{
- k->s2k.count = iobuf_get (inp);
+ k->s2k.count = iobuf_get_noeof (inp);
pktlen--;
}
k->seskeylen = seskeylen;
@@ -1640,14 +1674,24 @@ parse_one_sig_subpkt (const byte * buffer, size_t n, int type)
/* Return true if we understand the critical notation. */
static int
-can_handle_critical_notation (const byte * name, size_t len)
+can_handle_critical_notation (const byte *name, size_t len)
{
- if (len == 32 && memcmp (name, "[email protected]", 32) == 0)
- return 1;
- if (len == 21 && memcmp (name, "[email protected]", 21) == 0)
- return 1;
+ strlist_t sl;
- return 0;
+ register_known_notation (NULL); /* Make sure it is initialized. */
+
+ for (sl = known_notations_list; sl; sl = sl->next)
+ if (sl->flags == len && !memcmp (sl->d, name, len))
+ return 1; /* Known */
+
+ if (opt.verbose)
+ {
+ log_info(_("Unknown critical signature notation: ") );
+ print_utf8_buffer (log_get_stream(), name, len);
+ log_printf ("\n");
+ }
+
+ return 0; /* Unknown. */
}
@@ -1888,7 +1932,7 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
{
int md5_len = 0;
unsigned n;
- int is_v4 = 0;
+ int is_v4or5 = 0;
int rc = 0;
int i, ndata;
@@ -1901,8 +1945,8 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
}
sig->version = iobuf_get_noeof (inp);
pktlen--;
- if (sig->version == 4)
- is_v4 = 1;
+ if (sig->version == 4 || sig->version == 5)
+ is_v4or5 = 1;
else if (sig->version != 2 && sig->version != 3)
{
log_error ("packet(%d) with unknown version %d\n",
@@ -1913,7 +1957,7 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
goto leave;
}
- if (!is_v4)
+ if (!is_v4or5)
{
if (pktlen == 0)
goto underflow;
@@ -1924,7 +1968,7 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
goto underflow;
sig->sig_class = iobuf_get_noeof (inp);
pktlen--;
- if (!is_v4)
+ if (!is_v4or5)
{
if (pktlen < 12)
goto underflow;
@@ -1943,7 +1987,7 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
pktlen--;
sig->flags.exportable = 1;
sig->flags.revocable = 1;
- if (is_v4) /* Read subpackets. */
+ if (is_v4or5) /* Read subpackets. */
{
if (pktlen < 2)
goto underflow;
@@ -2014,7 +2058,7 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
sig->digest_start[1] = iobuf_get_noeof (inp);
pktlen--;
- if (is_v4 && sig->pubkey_algo) /* Extract required information. */
+ if (is_v4or5 && sig->pubkey_algo) /* Extract required information. */
{
const byte *p;
size_t len;
@@ -2115,7 +2159,7 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
(ulong) sig->keyid[0], (ulong) sig->keyid[1],
sig->version, (ulong) sig->timestamp, md5_len, sig->sig_class,
sig->digest_algo, sig->digest_start[0], sig->digest_start[1]);
- if (is_v4)
+ if (is_v4or5)
{
parse_sig_subpkt (sig->hashed, SIGSUBPKT_LIST_HASHED, NULL);
parse_sig_subpkt (sig->unhashed, SIGSUBPKT_LIST_UNHASHED, NULL);
@@ -2307,7 +2351,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
{
log_error ("packet(%d) too large\n", pkttype);
if (list_mode)
- es_fputs (":key packet: [too larget]\n", listfp);
+ es_fputs (":key packet: [too large]\n", listfp);
err = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
@@ -2528,7 +2572,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
err = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
- ski->s2k.count = iobuf_get (inp);
+ ski->s2k.count = iobuf_get_noeof (inp);
pktlen--;
if (list_mode)
es_fprintf (listfp, "\tprotect count: %lu (%lu)\n",
@@ -3136,7 +3180,7 @@ parse_plaintext (IOBUF inp, int pkttype, unsigned long pktlen,
pt->name[i] = c;
}
/* Fill up NAME so that a check with valgrind won't complain about
- * reading from uninitalized memory. This case may be triggred by
+ * reading from uninitialized memory. This case may be triggred by
* corrupted packets. */
for (; i < namelen; i++)
pt->name[i] = 0;
diff --git a/g10/pkclist.c b/g10/pkclist.c
index 2322f7807..46258bf85 100644
--- a/g10/pkclist.c
+++ b/g10/pkclist.c
@@ -548,7 +548,7 @@ check_signatures_trust (ctrl_t ctrl, PKT_signature *sig)
unsigned int trustlevel = TRUST_UNKNOWN;
int rc=0;
- rc = get_pubkey (ctrl, pk, sig->keyid );
+ rc = get_pubkey_for_sig (ctrl, pk, sig);
if (rc)
{ /* this should not happen */
log_error("Ooops; the key vanished - can't check the trust\n");
@@ -834,7 +834,7 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
if (from_file)
rc = get_pubkey_fromfile (ctrl, pk, name);
else
- rc = get_best_pubkey_byname (ctrl, NULL, pk, name, &keyblock, 0, 0);
+ rc = get_best_pubkey_byname (ctrl, NULL, pk, name, &keyblock, 0);
if (rc)
{
int code;
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index 0185097a4..ad0a77e59 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -38,7 +38,7 @@
#include "../common/compliance.h"
-static gpg_error_t get_it (ctrl_t ctrl, PKT_pubkey_enc *k,
+static gpg_error_t get_it (ctrl_t ctrl, struct pubkey_enc_list *k,
DEK *dek, PKT_public_key *sk, u32 *keyid);
@@ -72,92 +72,103 @@ is_algo_in_prefs (kbnode_t keyblock, preftype_t type, int algo)
* which should have been allocated in secure memory by the caller.
*/
gpg_error_t
-get_session_key (ctrl_t ctrl, PKT_pubkey_enc * k, DEK * dek)
+get_session_key (ctrl_t ctrl, struct pubkey_enc_list *list, DEK *dek)
{
PKT_public_key *sk = NULL;
int rc;
+ void *enum_context = NULL;
+ u32 keyid[2];
+ int search_for_secret_keys = 1;
if (DBG_CLOCK)
log_clock ("get_session_key enter");
- rc = openpgp_pk_test_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC);
- if (rc)
- goto leave;
-
- if ((k->keyid[0] || k->keyid[1]) && !opt.try_all_secrets)
+ while (search_for_secret_keys)
{
+ struct pubkey_enc_list *k;
+
sk = xmalloc_clear (sizeof *sk);
- sk->pubkey_algo = k->pubkey_algo; /* We want a pubkey with this algo. */
- if (!(rc = get_seckey (ctrl, sk, k->keyid)))
+ rc = enum_secret_keys (ctrl, &enum_context, sk);
+ if (rc)
{
- /* Check compliance. */
- if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION,
- sk->pubkey_algo,
- sk->pkey, nbits_from_pk (sk), NULL))
- {
- log_info (_("key %s is not suitable for decryption"
- " in %s mode\n"),
- keystr_from_pk (sk),
- gnupg_compliance_option_string (opt.compliance));
- rc = gpg_error (GPG_ERR_PUBKEY_ALGO);
- }
- else
- rc = get_it (ctrl, k, dek, sk, k->keyid);
+ rc = GPG_ERR_NO_SECKEY;
+ break;
}
- }
- else if (opt.skip_hidden_recipients)
- rc = gpg_error (GPG_ERR_NO_SECKEY);
- else /* Anonymous receiver: Try all available secret keys. */
- {
- void *enum_context = NULL;
- u32 keyid[2];
- for (;;)
+ if (!(sk->pubkey_usage & PUBKEY_USAGE_ENC))
+ continue;
+
+ /* Check compliance. */
+ if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION,
+ sk->pubkey_algo,
+ sk->pkey, nbits_from_pk (sk), NULL))
{
- free_public_key (sk);
- sk = xmalloc_clear (sizeof *sk);
- rc = enum_secret_keys (ctrl, &enum_context, sk);
- if (rc)
- {
- rc = GPG_ERR_NO_SECKEY;
- break;
- }
- if (sk->pubkey_algo != k->pubkey_algo)
+ log_info (_("key %s is not suitable for decryption"
+ " in %s mode\n"),
+ keystr_from_pk (sk),
+ gnupg_compliance_option_string (opt.compliance));
+ continue;
+ }
+
+ /* FIXME: The list needs to be sorted so that we try the keys in
+ * an appropriate order. For example:
+ * - On-disk keys w/o protection
+ * - On-disk keys with a cached passphrase
+ * - On-card keys of an active card
+ * - On-disk keys with protection
+ * - On-card keys from cards which are not plugged it. Here a
+ * cancel-all button should stop aksing for other cards.
+ * Without any anonymous keys the sorting can be skipped.
+ */
+ for (k = list; k; k = k->next)
+ {
+ if (!(k->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E
+ || k->pubkey_algo == PUBKEY_ALGO_ECDH
+ || k->pubkey_algo == PUBKEY_ALGO_RSA
+ || k->pubkey_algo == PUBKEY_ALGO_RSA_E
+ || k->pubkey_algo == PUBKEY_ALGO_ELGAMAL))
continue;
- if (!(sk->pubkey_usage & PUBKEY_USAGE_ENC))
+
+ if (openpgp_pk_test_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC))
+ continue;
+
+ if (sk->pubkey_algo != k->pubkey_algo)
continue;
+
keyid_from_pk (sk, keyid);
- if (!opt.quiet)
- log_info (_("anonymous recipient; trying secret key %s ...\n"),
- keystr (keyid));
-
- /* Check compliance. */
- if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION,
- sk->pubkey_algo,
- sk->pkey, nbits_from_pk (sk), NULL))
+
+ if (!k->keyid[0] && !k->keyid[1])
{
- log_info (_("key %s is not suitable for decryption"
- " in %s mode\n"),
- keystr_from_pk (sk),
- gnupg_compliance_option_string (opt.compliance));
- continue;
+ if (opt.skip_hidden_recipients)
+ continue;
+
+ if (!opt.quiet)
+ log_info (_("anonymous recipient; trying secret key %s ...\n"),
+ keystr (keyid));
}
+ else if (opt.try_all_secrets
+ || (k->keyid[0] == keyid[0] && k->keyid[1] == keyid[1]))
+ ;
+ else
+ continue;
rc = get_it (ctrl, k, dek, sk, keyid);
if (!rc)
{
- if (!opt.quiet)
+ if (!opt.quiet && !k->keyid[0] && !k->keyid[1])
log_info (_("okay, we are the anonymous recipient.\n"));
+ search_for_secret_keys = 0;
break;
}
else if (gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
- break; /* Don't try any more secret keys. */
+ {
+ search_for_secret_keys = 0;
+ break; /* Don't try any more secret keys. */
+ }
}
- enum_secret_keys (ctrl, &enum_context, NULL); /* free context */
}
+ enum_secret_keys (ctrl, &enum_context, NULL); /* free context */
- leave:
- free_public_key (sk);
if (DBG_CLOCK)
log_clock ("get_session_key leave");
return rc;
@@ -166,7 +177,7 @@ get_session_key (ctrl_t ctrl, PKT_pubkey_enc * k, DEK * dek)
static gpg_error_t
get_it (ctrl_t ctrl,
- PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
+ struct pubkey_enc_list *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
{
gpg_error_t err;
byte *frame = NULL;
diff --git a/g10/seskey.c b/g10/seskey.c
index 15490179d..fb71ad5cd 100644
--- a/g10/seskey.c
+++ b/g10/seskey.c
@@ -95,7 +95,7 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
output be a multiple of 8 bytes. */
if (openpgp_pk_algo == PUBKEY_ALGO_ECDH)
{
- /* Pad to 8 byte granulatiry; the padding byte is the number of
+ /* Pad to 8 byte granularity; the padding byte is the number of
* padded bytes.
*
* A DEK(k bytes) CSUM(2 bytes) 0x 0x 0x 0x ... 0x
@@ -143,7 +143,7 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
*
* 0 2 RND(i bytes) 0 A DEK(k bytes) CSUM(2 bytes)
*
- * (But how can we store the leading 0 - the external representaion
+ * (But how can we store the leading 0 - the external representation
* of MPIs doesn't allow leading zeroes =:-)
*
* RND are (at least 1) non-zero random bytes.
diff --git a/g10/sig-check.c b/g10/sig-check.c
index a68e031f6..6d7f1afbd 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.c
@@ -156,7 +156,7 @@ check_signature2 (ctrl_t ctrl,
log_info(_("WARNING: signature digest conflict in message\n"));
rc = gpg_error (GPG_ERR_GENERAL);
}
- else if (get_pubkey (ctrl, pk, sig->keyid))
+ else if (get_pubkey_for_sig (ctrl, pk, sig))
rc = gpg_error (GPG_ERR_NO_PUBKEY);
else if (!gnupg_pk_is_allowed (opt.compliance, PK_USE_VERIFICATION,
pk->pubkey_algo, pk->pkey,
@@ -480,7 +480,8 @@ check_signature_end_simple (PKT_public_key *pk, PKT_signature *sig,
}
/* For data signatures check that the key has sign usage. */
- if (IS_SIG (sig) && !(pk->pubkey_usage & PUBKEY_USAGE_SIG))
+ if (!IS_BACK_SIG (sig) && IS_SIG (sig)
+ && !(pk->pubkey_usage & PUBKEY_USAGE_SIG))
{
rc = gpg_error (GPG_ERR_WRONG_KEY_USAGE);
if (!opt.quiet)
@@ -509,7 +510,8 @@ check_signature_end_simple (PKT_public_key *pk, PKT_signature *sig,
}
else
{
- byte buf[6];
+ byte buf[10];
+ int i;
size_t n;
gcry_md_putc (digest, sig->pubkey_algo);
gcry_md_putc (digest, sig->digest_algo);
@@ -530,13 +532,21 @@ check_signature_end_simple (PKT_public_key *pk, PKT_signature *sig,
n = 6;
}
/* add some magic per Section 5.2.4 of RFC 4880. */
- buf[0] = sig->version;
- buf[1] = 0xff;
- buf[2] = n >> 24;
- buf[3] = n >> 16;
- buf[4] = n >> 8;
- buf[5] = n;
- gcry_md_write( digest, buf, 6 );
+ i = 0;
+ buf[i++] = sig->version;
+ buf[i++] = 0xff;
+ if (sig->version >= 5)
+ {
+ buf[i++] = 0;
+ buf[i++] = 0;
+ buf[i++] = 0;
+ buf[i++] = 0;
+ }
+ buf[i++] = n >> 24;
+ buf[i++] = n >> 16;
+ buf[i++] = n >> 8;
+ buf[i++] = n;
+ gcry_md_write (digest, buf, i);
}
gcry_md_final( digest );
@@ -571,7 +581,7 @@ hash_uid_packet (PKT_user_id *uid, gcry_md_hd_t md, PKT_signature *sig )
{
if (uid->attrib_data)
{
- if (sig->version >=4)
+ if (sig->version >= 4)
{
byte buf[5];
buf[0] = 0xd1; /* packet of type 17 */
@@ -585,7 +595,7 @@ hash_uid_packet (PKT_user_id *uid, gcry_md_hd_t md, PKT_signature *sig )
}
else
{
- if (sig->version >=4)
+ if (sig->version >= 4)
{
byte buf[5];
buf[0] = 0xb4; /* indicates a userid packet */
@@ -926,7 +936,7 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer,
if (IS_CERT (sig))
signer->req_usage = PUBKEY_USAGE_CERT;
- rc = get_pubkey (ctrl, signer, sig->keyid);
+ rc = get_pubkey_for_sig (ctrl, signer, sig);
if (rc)
{
xfree (signer);
diff --git a/g10/sign.c b/g10/sign.c
index 581a08f5b..b2d1c1826 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -51,8 +51,9 @@
static int recipient_digest_algo=0;
-/****************
- * Create notations and other stuff. It is assumed that the stings in
+
+/*
+ * Create notations and other stuff. It is assumed that the strings in
* STRLIST are already checked to contain only printable data and have
* a valid NAME=VALUE format.
*/
@@ -152,7 +153,8 @@ mk_notation_policy_etc (PKT_signature *sig,
char *mbox;
/* For now we use the uid which was used to locate the key. */
- if (pksk->user_id && (mbox = mailbox_from_userid (pksk->user_id->name)))
+ if (pksk->user_id
+ && (mbox = mailbox_from_userid (pksk->user_id->name, 0)))
{
if (DBG_LOOKUP)
log_debug ("setting Signer's UID to '%s'\n", mbox);
@@ -219,7 +221,8 @@ hash_uid (gcry_md_hd_t md, int sigversion, const PKT_user_id *uid)
static void
hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig)
{
- byte buf[6];
+ byte buf[10];
+ int i;
size_t n;
gcry_md_putc (md, sig->version);
@@ -241,13 +244,21 @@ hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig)
n = 6;
}
/* Add some magic. */
- buf[0] = sig->version;
- buf[1] = 0xff;
- buf[2] = n >> 24; /* (n is only 16 bit, so this is always 0) */
- buf[3] = n >> 16;
- buf[4] = n >> 8;
- buf[5] = n;
- gcry_md_write (md, buf, 6);
+ i = 0;
+ buf[i++] = sig->version;
+ buf[i++] = 0xff;
+ if (sig->version >= 5)
+ {
+ buf[i++] = 0;
+ buf[i++] = 0;
+ buf[i++] = 0;
+ buf[i++] = 0;
+ }
+ buf[i++] = n >> 24; /* (n is only 16 bit, so this is always 0) */
+ buf[i++] = n >> 16;
+ buf[i++] = n >> 8;
+ buf[i++] = n;
+ gcry_md_write (md, buf, i);
}
@@ -574,129 +585,135 @@ print_status_sig_created (PKT_public_key *pk, PKT_signature *sig, int what)
* Loop over the secret certificates in SK_LIST and build the one pass
* signature packets. OpenPGP says that the data should be bracket by
* the onepass-sig and signature-packet; so we build these onepass
- * packet here in reverse order
+ * packet here in reverse order.
*/
static int
write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass )
{
- int skcount;
- SK_LIST sk_rover;
+ int skcount;
+ SK_LIST sk_rover;
- for (skcount=0, sk_rover=sk_list; sk_rover; sk_rover = sk_rover->next)
- skcount++;
+ for (skcount=0, sk_rover=sk_list; sk_rover; sk_rover = sk_rover->next)
+ skcount++;
- for (; skcount; skcount--) {
- PKT_public_key *pk;
- PKT_onepass_sig *ops;
- PACKET pkt;
- int i, rc;
+ for (; skcount; skcount--)
+ {
+ PKT_public_key *pk;
+ PKT_onepass_sig *ops;
+ PACKET pkt;
+ int i, rc;
- for (i=0, sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
- if (++i == skcount)
- break;
- }
+ for (i=0, sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next)
+ if (++i == skcount)
+ break;
- pk = sk_rover->pk;
- ops = xmalloc_clear (sizeof *ops);
- ops->sig_class = sigclass;
- ops->digest_algo = hash_for (pk);
- ops->pubkey_algo = pk->pubkey_algo;
- keyid_from_pk (pk, ops->keyid);
- ops->last = (skcount == 1);
-
- init_packet(&pkt);
- pkt.pkttype = PKT_ONEPASS_SIG;
- pkt.pkt.onepass_sig = ops;
- rc = build_packet (out, &pkt);
- free_packet (&pkt, NULL);
- if (rc) {
- log_error ("build onepass_sig packet failed: %s\n",
- gpg_strerror (rc));
- return rc;
+ pk = sk_rover->pk;
+ ops = xmalloc_clear (sizeof *ops);
+ ops->sig_class = sigclass;
+ ops->digest_algo = hash_for (pk);
+ ops->pubkey_algo = pk->pubkey_algo;
+ keyid_from_pk (pk, ops->keyid);
+ ops->last = (skcount == 1);
+
+ init_packet (&pkt);
+ pkt.pkttype = PKT_ONEPASS_SIG;
+ pkt.pkt.onepass_sig = ops;
+ rc = build_packet (out, &pkt);
+ free_packet (&pkt, NULL);
+ if (rc)
+ {
+ log_error ("build onepass_sig packet failed: %s\n",
+ gpg_strerror (rc));
+ return rc;
}
}
- return 0;
+ return 0;
}
+
/*
* Helper to write the plaintext (literal data) packet
*/
static int
write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
{
- PKT_plaintext *pt = NULL;
- u32 filesize;
- int rc = 0;
+ PKT_plaintext *pt = NULL;
+ u32 filesize;
+ int rc = 0;
- if (!opt.no_literal)
- pt=setup_plaintext_name(fname,inp);
+ if (!opt.no_literal)
+ pt = setup_plaintext_name (fname, inp);
- /* try to calculate the length of the data */
- if ( !iobuf_is_pipe_filename (fname) && *fname )
- {
- off_t tmpsize;
- int overflow;
-
- if( !(tmpsize = iobuf_get_filelength(inp, &overflow))
- && !overflow && opt.verbose)
- log_info (_("WARNING: '%s' is an empty file\n"), fname);
-
- /* We can't encode the length of very large files because
- OpenPGP uses only 32 bit for file sizes. So if the size of
- a file is larger than 2^32 minus some bytes for packet
- headers, we switch to partial length encoding. */
- if ( tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
- filesize = tmpsize;
- else
- filesize = 0;
-
- /* Because the text_filter modifies the length of the
- * data, it is not possible to know the used length
- * without a double read of the file - to avoid that
- * we simple use partial length packets. */
- if ( ptmode == 't' || ptmode == 'u' || ptmode == 'm')
- filesize = 0;
- }
- else
- filesize = opt.set_filesize? opt.set_filesize : 0; /* stdin */
-
- if (!opt.no_literal) {
- PACKET pkt;
-
- /* Note that PT has been initialized above in no_literal mode. */
- pt->timestamp = make_timestamp ();
- pt->mode = ptmode;
- pt->len = filesize;
- pt->new_ctb = !pt->len;
- pt->buf = inp;
- init_packet(&pkt);
- pkt.pkttype = PKT_PLAINTEXT;
- pkt.pkt.plaintext = pt;
- /*cfx.datalen = filesize? calc_packet_length( &pkt ) : 0;*/
- if( (rc = build_packet (out, &pkt)) )
- log_error ("build_packet(PLAINTEXT) failed: %s\n",
- gpg_strerror (rc) );
- pt->buf = NULL;
- free_packet (&pkt, NULL);
+ /* Try to calculate the length of the data. */
+ if ( !iobuf_is_pipe_filename (fname) && *fname)
+ {
+ off_t tmpsize;
+ int overflow;
+
+ if (!(tmpsize = iobuf_get_filelength (inp, &overflow))
+ && !overflow && opt.verbose)
+ log_info (_("WARNING: '%s' is an empty file\n"), fname);
+
+ /* We can't encode the length of very large files because
+ * OpenPGP uses only 32 bit for file sizes. So if the size of a
+ * file is larger than 2^32 minus some bytes for packet headers,
+ * we switch to partial length encoding. */
+ if (tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536))
+ filesize = tmpsize;
+ else
+ filesize = 0;
+
+ /* Because the text_filter modifies the length of the
+ * data, it is not possible to know the used length
+ * without a double read of the file - to avoid that
+ * we simple use partial length packets. */
+ if (ptmode == 't' || ptmode == 'u' || ptmode == 'm')
+ filesize = 0;
}
- else {
- byte copy_buffer[4096];
- int bytes_copied;
-
- while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
- if ( (rc=iobuf_write(out, copy_buffer, bytes_copied)) ) {
- log_error ("copying input to output failed: %s\n",
- gpg_strerror (rc));
- break;
- }
- wipememory(copy_buffer,4096); /* burn buffer */
+ else
+ filesize = opt.set_filesize? opt.set_filesize : 0; /* stdin */
+
+ if (!opt.no_literal)
+ {
+ PACKET pkt;
+
+ /* Note that PT has been initialized above in no_literal mode. */
+ pt->timestamp = make_timestamp ();
+ pt->mode = ptmode;
+ pt->len = filesize;
+ pt->new_ctb = !pt->len;
+ pt->buf = inp;
+ init_packet (&pkt);
+ pkt.pkttype = PKT_PLAINTEXT;
+ pkt.pkt.plaintext = pt;
+ /*cfx.datalen = filesize? calc_packet_length( &pkt ) : 0;*/
+ if ((rc = build_packet (out, &pkt)))
+ log_error ("build_packet(PLAINTEXT) failed: %s\n",
+ gpg_strerror (rc) );
+ pt->buf = NULL;
+ free_packet (&pkt, NULL);
}
- /* fixme: it seems that we never freed pt/pkt */
+ else
+ {
+ byte copy_buffer[4096];
+ int bytes_copied;
- return rc;
+ while ((bytes_copied = iobuf_read (inp, copy_buffer, 4096)) != -1)
+ if ((rc = iobuf_write (out, copy_buffer, bytes_copied)))
+ {
+ log_error ("copying input to output failed: %s\n",
+ gpg_strerror (rc));
+ break;
+ }
+ wipememory (copy_buffer, 4096); /* burn buffer */
+ }
+ /* fixme: it seems that we never freed pt/pkt */
+
+ return rc;
}
+
/*
* Write the signatures from the SK_LIST to OUT. HASH must be a non-finalized
* hash which will not be changes here.
@@ -724,11 +741,10 @@ write_signature_packets (ctrl_t ctrl,
if (!sig)
return gpg_error_from_syserror ();
- if (duration || opt.sig_policy_url
- || opt.sig_notations || opt.sig_keyserver_url)
- sig->version = 4;
+ if (pk->version >= 5)
+ sig->version = 5; /* Required for v5 keys. */
else
- sig->version = pk->version;
+ sig->version = 4; /*Required. */
keyid_from_pk (pk, sig->keyid);
sig->digest_algo = hash_for (pk);
@@ -744,12 +760,8 @@ write_signature_packets (ctrl_t ctrl,
if (gcry_md_copy (&md, hash))
BUG ();
- if (sig->version >= 4)
- {
- build_sig_subpkt_from_sig (sig, pk);
- mk_notation_policy_etc (sig, NULL, pk);
- }
-
+ build_sig_subpkt_from_sig (sig, pk);
+ mk_notation_policy_etc (sig, NULL, pk);
hash_sigversion_to_magic (md, sig);
gcry_md_final (md);
@@ -782,7 +794,7 @@ write_signature_packets (ctrl_t ctrl,
}
-/****************
+/*
* Sign the files whose names are in FILENAME.
* If DETACHED has the value true,
* make a detached signature. If FILENAMES->d is NULL read from stdin
@@ -798,62 +810,65 @@ int
sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
int encryptflag, strlist_t remusr, const char *outfile )
{
- const char *fname;
- armor_filter_context_t *afx;
- compress_filter_context_t zfx;
- md_filter_context_t mfx;
- text_filter_context_t tfx;
- progress_filter_context_t *pfx;
- encrypt_filter_context_t efx;
- IOBUF inp = NULL, out = NULL;
- PACKET pkt;
- int rc = 0;
- PK_LIST pk_list = NULL;
- SK_LIST sk_list = NULL;
- SK_LIST sk_rover = NULL;
- int multifile = 0;
- u32 duration=0;
-
- pfx = new_progress_context ();
- afx = new_armor_context ();
- memset( &zfx, 0, sizeof zfx);
- memset( &mfx, 0, sizeof mfx);
- memset( &efx, 0, sizeof efx);
- efx.ctrl = ctrl;
- init_packet( &pkt );
-
- if( filenames ) {
- fname = filenames->d;
- multifile = !!filenames->next;
+ const char *fname;
+ armor_filter_context_t *afx;
+ compress_filter_context_t zfx;
+ md_filter_context_t mfx;
+ text_filter_context_t tfx;
+ progress_filter_context_t *pfx;
+ encrypt_filter_context_t efx;
+ iobuf_t inp = NULL;
+ iobuf_t out = NULL;
+ PACKET pkt;
+ int rc = 0;
+ PK_LIST pk_list = NULL;
+ SK_LIST sk_list = NULL;
+ SK_LIST sk_rover = NULL;
+ int multifile = 0;
+ u32 duration=0;
+
+ pfx = new_progress_context ();
+ afx = new_armor_context ();
+ memset (&zfx, 0, sizeof zfx);
+ memset (&mfx, 0, sizeof mfx);
+ memset (&efx, 0, sizeof efx);
+ efx.ctrl = ctrl;
+ init_packet (&pkt);
+
+ if (filenames)
+ {
+ fname = filenames->d;
+ multifile = !!filenames->next;
}
- else
- fname = NULL;
+ else
+ fname = NULL;
- if( fname && filenames->next && (!detached || encryptflag) )
- log_bug("multiple files can only be detached signed");
+ if (fname && filenames->next && (!detached || encryptflag))
+ log_bug ("multiple files can only be detached signed");
- if(encryptflag==2
- && (rc=setup_symkey(&efx.symkey_s2k,&efx.symkey_dek)))
- goto leave;
+ if (encryptflag == 2
+ && (rc = setup_symkey (&efx.symkey_s2k, &efx.symkey_dek)))
+ goto leave;
- if (opt.ask_sig_expire && !opt.batch)
- duration = ask_expire_interval(1,opt.def_sig_expire);
- else
- duration = parse_expire_string(opt.def_sig_expire);
+ if (opt.ask_sig_expire && !opt.batch)
+ duration = ask_expire_interval(1,opt.def_sig_expire);
+ else
+ duration = parse_expire_string(opt.def_sig_expire);
- /* Note: In the old non-agent version the following call used to
- unprotect the secret key. This is now done on demand by the agent. */
- if( (rc = build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_SIG )) )
- goto leave;
+ /* Note: In the old non-agent version the following call used to
+ * unprotect the secret key. This is now done on demand by the agent. */
+ if ((rc = build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_SIG )))
+ goto leave;
- if (encryptflag
- && (rc=build_pk_list (ctrl, remusr, &pk_list)))
- goto leave;
+ if (encryptflag
+ && (rc = build_pk_list (ctrl, remusr, &pk_list)))
+ goto leave;
- /* prepare iobufs */
- if( multifile ) /* have list of filenames */
- inp = NULL; /* we do it later */
- else {
+ /* Prepare iobufs. */
+ if (multifile) /* have list of filenames */
+ inp = NULL; /* we do it later */
+ else
+ {
inp = iobuf_open(fname);
if (inp && is_secured_file (iobuf_get_fd (inp)))
{
@@ -861,407 +876,435 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
inp = NULL;
gpg_err_set_errno (EPERM);
}
- if( !inp )
+ if (!inp)
{
rc = gpg_error_from_syserror ();
log_error (_("can't open '%s': %s\n"), fname? fname: "[stdin]",
- strerror(errno) );
+ strerror (errno));
goto leave;
}
- handle_progress (pfx, inp, fname);
+ handle_progress (pfx, inp, fname);
}
- if( outfile ) {
- if (is_secured_filename ( outfile )) {
- out = NULL;
- gpg_err_set_errno (EPERM);
+ if (outfile)
+ {
+ if (is_secured_filename (outfile))
+ {
+ out = NULL;
+ gpg_err_set_errno (EPERM);
}
- else
- out = iobuf_create (outfile, 0);
- if( !out )
- {
- rc = gpg_error_from_syserror ();
- log_error(_("can't create '%s': %s\n"), outfile, strerror(errno) );
- goto leave;
- }
- else if( opt.verbose )
- log_info(_("writing to '%s'\n"), outfile );
+ else
+ out = iobuf_create (outfile, 0);
+ if (!out)
+ {
+ rc = gpg_error_from_syserror ();
+ log_error (_("can't create '%s': %s\n"), outfile, gpg_strerror (rc));
+ goto leave;
+ }
+ else if (opt.verbose)
+ log_info (_("writing to '%s'\n"), outfile);
+ }
+ else if ((rc = open_outfile (-1, fname,
+ opt.armor? 1 : detached? 2 : 0, 0, &out)))
+ {
+ goto leave;
}
- else if( (rc = open_outfile (-1, fname,
- opt.armor? 1: detached? 2:0, 0, &out)))
- goto leave;
- /* prepare to calculate the MD over the input */
- if( opt.textmode && !outfile && !multifile )
- {
- memset( &tfx, 0, sizeof tfx);
- iobuf_push_filter( inp, text_filter, &tfx );
- }
+ /* Prepare to calculate the MD over the input. */
+ if (opt.textmode && !outfile && !multifile)
+ {
+ memset (&tfx, 0, sizeof tfx);
+ iobuf_push_filter (inp, text_filter, &tfx);
+ }
- if ( gcry_md_open (&mfx.md, 0, 0) )
- BUG ();
- if (DBG_HASHING)
- gcry_md_debug (mfx.md, "sign");
-
- /* If we're encrypting and signing, it is reasonable to pick the
- hash algorithm to use out of the recipient key prefs. This is
- best effort only, as in a DSA2 and smartcard world there are
- cases where we cannot please everyone with a single hash (DSA2
- wants >160 and smartcards want =160). In the future this could
- be more complex with different hashes for each sk, but the
- current design requires a single hash for all SKs. */
- if(pk_list)
- {
- if(opt.def_digest_algo)
- {
- if(!opt.expert &&
- select_algo_from_prefs(pk_list,PREFTYPE_HASH,
- opt.def_digest_algo,
- NULL)!=opt.def_digest_algo)
- log_info(_("WARNING: forcing digest algorithm %s (%d)"
- " violates recipient preferences\n"),
- gcry_md_algo_name (opt.def_digest_algo),
- opt.def_digest_algo );
- }
- else
- {
- int algo, smartcard=0;
- union pref_hint hint;
-
- hint.digest_length = 0;
-
- /* Of course, if the recipient asks for something
- unreasonable (like the wrong hash for a DSA key) then
- don't do it. Check all sk's - if any are DSA or live
- on a smartcard, then the hash has restrictions and we
- may not be able to give the recipient what they want.
- For DSA, pass a hint for the largest q we have. Note
- that this means that a q>160 key will override a q=160
- key and force the use of truncation for the q=160 key.
- The alternative would be to ignore the recipient prefs
- completely and get a different hash for each DSA key in
- hash_for(). The override behavior here is more or less
- reasonable as it is under the control of the user which
- keys they sign with for a given message and the fact
- that the message with multiple signatures won't be
- usable on an implementation that doesn't understand
- DSA2 anyway. */
-
- for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next )
- {
- if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_DSA
- || sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA)
- {
- int temp_hashlen = (gcry_mpi_get_nbits
- (sk_rover->pk->pkey[1]));
-
- if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA)
- temp_hashlen = ecdsa_qbits_from_Q (temp_hashlen);
- temp_hashlen = (temp_hashlen+7)/8;
-
- /* Pick a hash that is large enough for our
- largest q */
-
- if (hint.digest_length<temp_hashlen)
- hint.digest_length=temp_hashlen;
- }
- /* FIXME: need to check gpg-agent for this. */
- /* else if (sk_rover->pk->is_protected */
- /* && sk_rover->pk->protect.s2k.mode == 1002) */
- /* smartcard = 1; */
- }
-
- /* Current smartcards only do 160-bit hashes. If we have
- to have a >160-bit hash, then we can't use the
- recipient prefs as we'd need both =160 and >160 at the
- same time and recipient prefs currently require a
- single hash for all signatures. All this may well have
- to change as the cards add algorithms. */
-
- if (!smartcard || (smartcard && hint.digest_length==20))
- if ( (algo=
- select_algo_from_prefs(pk_list,PREFTYPE_HASH,-1,&hint)) > 0)
- recipient_digest_algo=algo;
- }
- }
+ if (gcry_md_open (&mfx.md, 0, 0))
+ BUG ();
+ if (DBG_HASHING)
+ gcry_md_debug (mfx.md, "sign");
+
+ /* If we're encrypting and signing, it is reasonable to pick the
+ * hash algorithm to use out of the recipient key prefs. This is
+ * best effort only, as in a DSA2 and smartcard world there are
+ * cases where we cannot please everyone with a single hash (DSA2
+ * wants >160 and smartcards want =160). In the future this could
+ * be more complex with different hashes for each sk, but the
+ * current design requires a single hash for all SKs. */
+ if (pk_list)
+ {
+ if (opt.def_digest_algo)
+ {
+ if (!opt.expert
+ && select_algo_from_prefs (pk_list,PREFTYPE_HASH,
+ opt.def_digest_algo,
+ NULL) != opt.def_digest_algo)
+ {
+ log_info (_("WARNING: forcing digest algorithm %s (%d)"
+ " violates recipient preferences\n"),
+ gcry_md_algo_name (opt.def_digest_algo),
+ opt.def_digest_algo);
+ }
+ }
+ else
+ {
+ int algo;
+ int smartcard=0;
+ union pref_hint hint;
+
+ hint.digest_length = 0;
+
+ /* Of course, if the recipient asks for something
+ * unreasonable (like the wrong hash for a DSA key) then
+ * don't do it. Check all sk's - if any are DSA or live
+ * on a smartcard, then the hash has restrictions and we
+ * may not be able to give the recipient what they want.
+ * For DSA, pass a hint for the largest q we have. Note
+ * that this means that a q>160 key will override a q=160
+ * key and force the use of truncation for the q=160 key.
+ * The alternative would be to ignore the recipient prefs
+ * completely and get a different hash for each DSA key in
+ * hash_for(). The override behavior here is more or less
+ * reasonable as it is under the control of the user which
+ * keys they sign with for a given message and the fact
+ * that the message with multiple signatures won't be
+ * usable on an implementation that doesn't understand
+ * DSA2 anyway. */
+ for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next )
+ {
+ if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_DSA
+ || sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA)
+ {
+ int temp_hashlen = gcry_mpi_get_nbits (sk_rover->pk->pkey[1]);
+
+ if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA)
+ temp_hashlen = ecdsa_qbits_from_Q (temp_hashlen);
+
+ temp_hashlen = (temp_hashlen+7)/8;
+
+ /* Pick a hash that is large enough for our largest Q */
+ if (hint.digest_length < temp_hashlen)
+ hint.digest_length = temp_hashlen;
+ }
+ /* FIXME: need to check gpg-agent for this. */
+ /* else if (sk_rover->pk->is_protected */
+ /* && sk_rover->pk->protect.s2k.mode == 1002) */
+ /* smartcard = 1; */
+ }
- for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next)
- gcry_md_enable (mfx.md, hash_for (sk_rover->pk));
+ /* Current smartcards only do 160-bit hashes. If we have
+ * to have a >160-bit hash, then we can't use the
+ * recipient prefs as we'd need both =160 and >160 at the
+ * same time and recipient prefs currently require a
+ * single hash for all signatures. All this may well have
+ * to change as the cards add algorithms. */
+ if ((!smartcard || (smartcard && hint.digest_length==20))
+ && ((algo = select_algo_from_prefs (pk_list, PREFTYPE_HASH,
+ -1, &hint)) > 0))
+ {
+ recipient_digest_algo = algo;
+ }
+ }
+ }
- if( !multifile )
- iobuf_push_filter( inp, md_filter, &mfx );
+ for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next)
+ gcry_md_enable (mfx.md, hash_for (sk_rover->pk));
- if( detached && !encryptflag)
- afx->what = 2;
+ if (!multifile)
+ iobuf_push_filter (inp, md_filter, &mfx);
- if( opt.armor && !outfile )
- push_armor_filter (afx, out);
+ if (detached && !encryptflag)
+ afx->what = 2;
+
+ if (opt.armor && !outfile)
+ push_armor_filter (afx, out);
- if( encryptflag ) {
- efx.pk_list = pk_list;
- /* fixme: set efx.cfx.datalen if known */
- iobuf_push_filter( out, encrypt_filter, &efx );
+ if (encryptflag)
+ {
+ efx.pk_list = pk_list;
+ /* fixme: set efx.cfx.datalen if known */
+ iobuf_push_filter (out, encrypt_filter, &efx);
}
- if (opt.compress_algo && !outfile && !detached)
- {
- int compr_algo=opt.compress_algo;
-
- /* If not forced by user */
- if(compr_algo==-1)
- {
- /* If we're not encrypting, then select_algo_from_prefs
- will fail and we'll end up with the default. If we are
- encrypting, select_algo_from_prefs cannot fail since
- there is an assumed preference for uncompressed data.
- Still, if it did fail, we'll also end up with the
- default. */
-
- if((compr_algo=
- select_algo_from_prefs(pk_list,PREFTYPE_ZIP,-1,NULL))==-1)
- compr_algo=default_compress_algo();
- }
- else if(!opt.expert && pk_list
- && select_algo_from_prefs(pk_list,PREFTYPE_ZIP,
- compr_algo,NULL)!=compr_algo)
- log_info(_("WARNING: forcing compression algorithm %s (%d)"
- " violates recipient preferences\n"),
- compress_algo_to_string(compr_algo),compr_algo);
-
- /* algo 0 means no compression */
- if( compr_algo )
- push_compress_filter(out,&zfx,compr_algo);
- }
+ if (opt.compress_algo && !outfile && !detached)
+ {
+ int compr_algo = opt.compress_algo;
- /* Write the one-pass signature packets if needed */
- if (!detached) {
- rc = write_onepass_sig_packets (sk_list, out,
- opt.textmode && !outfile ? 0x01:0x00);
- if (rc)
- goto leave;
+ /* If not forced by user */
+ if (compr_algo==-1)
+ {
+ /* If we're not encrypting, then select_algo_from_prefs
+ * will fail and we'll end up with the default. If we are
+ * encrypting, select_algo_from_prefs cannot fail since
+ * there is an assumed preference for uncompressed data.
+ * Still, if it did fail, we'll also end up with the
+ * default. */
+ if ((compr_algo = select_algo_from_prefs (pk_list, PREFTYPE_ZIP,
+ -1, NULL)) == -1)
+ {
+ compr_algo = default_compress_algo();
+ }
+ }
+ else if (!opt.expert && pk_list
+ && select_algo_from_prefs (pk_list, PREFTYPE_ZIP,
+ compr_algo, NULL) != compr_algo)
+ {
+ log_info (_("WARNING: forcing compression algorithm %s (%d)"
+ " violates recipient preferences\n"),
+ compress_algo_to_string (compr_algo), compr_algo);
+ }
+
+ /* Algo 0 means no compression. */
+ if (compr_algo)
+ push_compress_filter (out, &zfx, compr_algo);
+ }
+
+ /* Write the one-pass signature packets if needed */
+ if (!detached)
+ {
+ rc = write_onepass_sig_packets (sk_list, out,
+ opt.textmode && !outfile ? 0x01:0x00);
+ if (rc)
+ goto leave;
}
- write_status_begin_signing (mfx.md);
-
- /* Setup the inner packet. */
- if( detached ) {
- if( multifile ) {
- strlist_t sl;
-
- if( opt.verbose )
- log_info(_("signing:") );
- /* must walk reverse trough this list */
- for( sl = strlist_last(filenames); sl;
- sl = strlist_prev( filenames, sl ) ) {
- inp = iobuf_open(sl->d);
- if (inp && is_secured_file (iobuf_get_fd (inp)))
- {
- iobuf_close (inp);
- inp = NULL;
- gpg_err_set_errno (EPERM);
- }
- if( !inp )
- {
- rc = gpg_error_from_syserror ();
- log_error(_("can't open '%s': %s\n"),
- sl->d,strerror(errno));
- goto leave;
- }
- handle_progress (pfx, inp, sl->d);
- if( opt.verbose )
- log_printf (" '%s'", sl->d );
- if(opt.textmode)
- {
- memset( &tfx, 0, sizeof tfx);
- iobuf_push_filter( inp, text_filter, &tfx );
- }
- iobuf_push_filter( inp, md_filter, &mfx );
- while( iobuf_get(inp) != -1 )
- ;
- iobuf_close(inp); inp = NULL;
+ write_status_begin_signing (mfx.md);
+
+ /* Setup the inner packet. */
+ if (detached)
+ {
+ if (multifile)
+ {
+ strlist_t sl;
+
+ if (opt.verbose)
+ log_info (_("signing:") );
+ /* Must walk reverse trough this list. */
+ for (sl = strlist_last(filenames);
+ sl;
+ sl = strlist_prev( filenames, sl))
+ {
+ inp = iobuf_open (sl->d);
+ if (inp && is_secured_file (iobuf_get_fd (inp)))
+ {
+ iobuf_close (inp);
+ inp = NULL;
+ gpg_err_set_errno (EPERM);
+ }
+ if (!inp)
+ {
+ rc = gpg_error_from_syserror ();
+ log_error (_("can't open '%s': %s\n"),
+ sl->d, gpg_strerror (rc));
+ goto leave;
+ }
+ handle_progress (pfx, inp, sl->d);
+ if (opt.verbose)
+ log_printf (" '%s'", sl->d );
+ if (opt.textmode)
+ {
+ memset (&tfx, 0, sizeof tfx);
+ iobuf_push_filter (inp, text_filter, &tfx);
+ }
+ iobuf_push_filter (inp, md_filter, &mfx);
+ while (iobuf_get (inp) != -1)
+ ;
+ iobuf_close (inp);
+ inp = NULL;
}
- if( opt.verbose )
- log_printf ("\n");
+ if (opt.verbose)
+ log_printf ("\n");
}
- else {
- /* read, so that the filter can calculate the digest */
- while( iobuf_get(inp) != -1 )
- ;
+ else
+ {
+ /* Read, so that the filter can calculate the digest. */
+ while (iobuf_get(inp) != -1)
+ ;
}
}
- else {
- rc = write_plaintext_packet (out, inp, fname,
- opt.textmode && !outfile ?
- (opt.mimemode? 'm':'t'):'b');
+ else
+ {
+ rc = write_plaintext_packet (out, inp, fname,
+ (opt.textmode && !outfile) ?
+ (opt.mimemode? 'm' : 't') : 'b');
}
- /* catch errors from above */
- if (rc)
- goto leave;
+ /* Catch errors from above. */
+ if (rc)
+ goto leave;
- /* write the signatures */
- rc = write_signature_packets (ctrl, sk_list, out, mfx.md,
- opt.textmode && !outfile? 0x01 : 0x00,
- 0, duration, detached ? 'D':'S', NULL);
- if( rc )
- goto leave;
+ /* Write the signatures. */
+ rc = write_signature_packets (ctrl, sk_list, out, mfx.md,
+ opt.textmode && !outfile? 0x01 : 0x00,
+ 0, duration, detached ? 'D':'S', NULL);
+ if (rc)
+ goto leave;
- leave:
- if( rc )
- iobuf_cancel(out);
- else {
- iobuf_close(out);
- if (encryptflag)
- write_status( STATUS_END_ENCRYPTION );
+ leave:
+ if (rc)
+ iobuf_cancel (out);
+ else
+ {
+ iobuf_close (out);
+ if (encryptflag)
+ write_status (STATUS_END_ENCRYPTION);
}
- iobuf_close(inp);
- gcry_md_close ( mfx.md );
- release_sk_list( sk_list );
- release_pk_list( pk_list );
- recipient_digest_algo=0;
- release_progress_context (pfx);
- release_armor_context (afx);
- return rc;
+ iobuf_close (inp);
+ gcry_md_close (mfx.md);
+ release_sk_list (sk_list);
+ release_pk_list (pk_list);
+ recipient_digest_algo = 0;
+ release_progress_context (pfx);
+ release_armor_context (afx);
+ return rc;
}
-
-/****************
- * make a clear signature. note that opt.armor is not needed
+/*
+ * Make a clear signature. Note that opt.armor is not needed.
*/
int
clearsign_file (ctrl_t ctrl,
- const char *fname, strlist_t locusr, const char *outfile )
+ const char *fname, strlist_t locusr, const char *outfile)
{
- armor_filter_context_t *afx;
- progress_filter_context_t *pfx;
- gcry_md_hd_t textmd = NULL;
- IOBUF inp = NULL, out = NULL;
- PACKET pkt;
- int rc = 0;
- SK_LIST sk_list = NULL;
- SK_LIST sk_rover = NULL;
- u32 duration=0;
-
- pfx = new_progress_context ();
- afx = new_armor_context ();
- init_packet( &pkt );
-
- if (opt.ask_sig_expire && !opt.batch)
- duration = ask_expire_interval (1,opt.def_sig_expire);
- else
- duration = parse_expire_string (opt.def_sig_expire);
-
- /* Note: In the old non-agent version the following call used to
- unprotect the secret key. This is now done on demand by the agent. */
- if( (rc=build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_SIG )) )
- goto leave;
-
- /* prepare iobufs */
- inp = iobuf_open(fname);
- if (inp && is_secured_file (iobuf_get_fd (inp)))
- {
- iobuf_close (inp);
- inp = NULL;
- gpg_err_set_errno (EPERM);
- }
- if( !inp ) {
- rc = gpg_error_from_syserror ();
- log_error (_("can't open '%s': %s\n"),
- fname? fname: "[stdin]", strerror(errno) );
- goto leave;
+ armor_filter_context_t *afx;
+ progress_filter_context_t *pfx;
+ gcry_md_hd_t textmd = NULL;
+ iobuf_t inp = NULL;
+ iobuf_t out = NULL;
+ PACKET pkt;
+ int rc = 0;
+ SK_LIST sk_list = NULL;
+ SK_LIST sk_rover = NULL;
+ u32 duration = 0;
+
+ pfx = new_progress_context ();
+ afx = new_armor_context ();
+ init_packet( &pkt );
+
+ if (opt.ask_sig_expire && !opt.batch)
+ duration = ask_expire_interval (1, opt.def_sig_expire);
+ else
+ duration = parse_expire_string (opt.def_sig_expire);
+
+ /* Note: In the old non-agent version the following call used to
+ * unprotect the secret key. This is now done on demand by the agent. */
+ if ((rc=build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_SIG)))
+ goto leave;
+
+ /* Prepare iobufs. */
+ inp = iobuf_open (fname);
+ if (inp && is_secured_file (iobuf_get_fd (inp)))
+ {
+ iobuf_close (inp);
+ inp = NULL;
+ gpg_err_set_errno (EPERM);
+ }
+ if (!inp)
+ {
+ rc = gpg_error_from_syserror ();
+ log_error (_("can't open '%s': %s\n"),
+ fname? fname: "[stdin]", gpg_strerror (rc));
+ goto leave;
}
- handle_progress (pfx, inp, fname);
+ handle_progress (pfx, inp, fname);
- if( outfile ) {
- if (is_secured_filename (outfile) ) {
- outfile = NULL;
- gpg_err_set_errno (EPERM);
+ if (outfile)
+ {
+ if (is_secured_filename (outfile))
+ {
+ outfile = NULL;
+ gpg_err_set_errno (EPERM);
}
- else
- out = iobuf_create (outfile, 0);
- if( !out )
- {
- rc = gpg_error_from_syserror ();
- log_error(_("can't create '%s': %s\n"), outfile, strerror(errno) );
- goto leave;
- }
- else if( opt.verbose )
- log_info(_("writing to '%s'\n"), outfile );
- }
- else if ((rc = open_outfile (-1, fname, 1, 0, &out)))
- goto leave;
+ else
+ out = iobuf_create (outfile, 0);
- iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----" LF );
+ if (!out)
+ {
+ rc = gpg_error_from_syserror ();
+ log_error (_("can't create '%s': %s\n"), outfile, gpg_strerror (rc));
+ goto leave;
+ }
+ else if (opt.verbose)
+ log_info (_("writing to '%s'\n"), outfile);
+ }
+ else if ((rc = open_outfile (-1, fname, 1, 0, &out)))
{
- const char *s;
- int any = 0;
- byte hashs_seen[256];
-
- memset( hashs_seen, 0, sizeof hashs_seen );
- iobuf_writestr(out, "Hash: " );
- for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
- int i = hash_for (sk_rover->pk);
-
- if( !hashs_seen[ i & 0xff ] ) {
- s = gcry_md_algo_name ( i );
- if( s ) {
- hashs_seen[ i & 0xff ] = 1;
- if( any )
- iobuf_put(out, ',' );
- iobuf_writestr(out, s );
- any = 1;
- }
- }
- }
- log_assert(any);
- iobuf_writestr(out, LF );
+ goto leave;
}
- if( opt.not_dash_escaped )
- iobuf_writestr( out,
- "NotDashEscaped: You need "GPG_NAME
- " to verify this message" LF );
- iobuf_writestr(out, LF );
+ iobuf_writestr (out, "-----BEGIN PGP SIGNED MESSAGE-----" LF);
+
+ {
+ const char *s;
+ int any = 0;
+ byte hashs_seen[256];
- if ( gcry_md_open (&textmd, 0, 0) )
- BUG ();
+ memset (hashs_seen, 0, sizeof hashs_seen);
+ iobuf_writestr (out, "Hash: " );
for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next)
- gcry_md_enable (textmd, hash_for(sk_rover->pk));
+ {
+ int i = hash_for (sk_rover->pk);
- if ( DBG_HASHING )
- gcry_md_debug ( textmd, "clearsign" );
+ if (!hashs_seen[ i & 0xff ])
+ {
+ s = gcry_md_algo_name (i);
+ if (s)
+ {
+ hashs_seen[ i & 0xff ] = 1;
+ if (any)
+ iobuf_put (out, ',');
+ iobuf_writestr (out, s);
+ any = 1;
+ }
+ }
+ }
+ log_assert (any);
+ iobuf_writestr (out, LF);
+ }
+
+ if (opt.not_dash_escaped)
+ iobuf_writestr (out,
+ "NotDashEscaped: You need "GPG_NAME
+ " to verify this message" LF);
+ iobuf_writestr (out, LF );
+
+ if (gcry_md_open (&textmd, 0, 0))
+ BUG ();
+ for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next)
+ gcry_md_enable (textmd, hash_for(sk_rover->pk));
- copy_clearsig_text (out, inp, textmd, !opt.not_dash_escaped,
- opt.escape_from);
- /* fixme: check for read errors */
+ if (DBG_HASHING)
+ gcry_md_debug (textmd, "clearsign");
- /* now write the armor */
- afx->what = 2;
- push_armor_filter (afx, out);
+ copy_clearsig_text (out, inp, textmd, !opt.not_dash_escaped, opt.escape_from);
+ /* fixme: check for read errors */
- /* Write the signatures. */
- rc = write_signature_packets (ctrl, sk_list, out, textmd, 0x01, 0,
- duration, 'C', NULL);
- if( rc )
- goto leave;
+ /* Now write the armor. */
+ afx->what = 2;
+ push_armor_filter (afx, out);
+
+ /* Write the signatures. */
+ rc = write_signature_packets (ctrl, sk_list, out, textmd, 0x01, 0,
+ duration, 'C', NULL);
+ if (rc)
+ goto leave;
- leave:
- if( rc )
- iobuf_cancel(out);
- else
- iobuf_close(out);
- iobuf_close(inp);
- gcry_md_close ( textmd );
- release_sk_list( sk_list );
- release_progress_context (pfx);
- release_armor_context (afx);
- return rc;
+ leave:
+ if (rc)
+ iobuf_cancel (out);
+ else
+ iobuf_close (out);
+ iobuf_close (inp);
+ gcry_md_close (textmd);
+ release_sk_list (sk_list);
+ release_progress_context (pfx);
+ release_armor_context (afx);
+ return rc;
}
+
/*
* Sign and conventionally encrypt the given file.
* FIXME: Far too much code is duplicated - revamp the whole file.
@@ -1269,175 +1312,179 @@ clearsign_file (ctrl_t ctrl,
int
sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr)
{
- armor_filter_context_t *afx;
- progress_filter_context_t *pfx;
- compress_filter_context_t zfx;
- md_filter_context_t mfx;
- text_filter_context_t tfx;
- cipher_filter_context_t cfx;
- IOBUF inp = NULL, out = NULL;
- PACKET pkt;
- STRING2KEY *s2k = NULL;
- int rc = 0;
- SK_LIST sk_list = NULL;
- SK_LIST sk_rover = NULL;
- int algo;
- u32 duration=0;
- int canceled;
-
- pfx = new_progress_context ();
- afx = new_armor_context ();
- memset( &zfx, 0, sizeof zfx);
- memset( &mfx, 0, sizeof mfx);
- memset( &tfx, 0, sizeof tfx);
- memset( &cfx, 0, sizeof cfx);
- init_packet( &pkt );
-
- if (opt.ask_sig_expire && !opt.batch)
- duration = ask_expire_interval (1, opt.def_sig_expire);
- else
- duration = parse_expire_string (opt.def_sig_expire);
-
- /* Note: In the old non-agent version the following call used to
- unprotect the secret key. This is now done on demand by the agent. */
- rc = build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_SIG);
- if (rc)
- goto leave;
-
- /* prepare iobufs */
- inp = iobuf_open(fname);
- if (inp && is_secured_file (iobuf_get_fd (inp)))
- {
- iobuf_close (inp);
- inp = NULL;
- gpg_err_set_errno (EPERM);
- }
- if( !inp ) {
- rc = gpg_error_from_syserror ();
- log_error (_("can't open '%s': %s\n"),
- fname? fname: "[stdin]", strerror(errno) );
- goto leave;
+ armor_filter_context_t *afx;
+ progress_filter_context_t *pfx;
+ compress_filter_context_t zfx;
+ md_filter_context_t mfx;
+ text_filter_context_t tfx;
+ cipher_filter_context_t cfx;
+ iobuf_t inp = NULL;
+ iobuf_t out = NULL;
+ PACKET pkt;
+ STRING2KEY *s2k = NULL;
+ int rc = 0;
+ SK_LIST sk_list = NULL;
+ SK_LIST sk_rover = NULL;
+ int algo;
+ u32 duration = 0;
+ int canceled;
+
+ pfx = new_progress_context ();
+ afx = new_armor_context ();
+ memset (&zfx, 0, sizeof zfx);
+ memset (&mfx, 0, sizeof mfx);
+ memset (&tfx, 0, sizeof tfx);
+ memset (&cfx, 0, sizeof cfx);
+ init_packet (&pkt);
+
+ if (opt.ask_sig_expire && !opt.batch)
+ duration = ask_expire_interval (1, opt.def_sig_expire);
+ else
+ duration = parse_expire_string (opt.def_sig_expire);
+
+ /* Note: In the old non-agent version the following call used to
+ * unprotect the secret key. This is now done on demand by the agent. */
+ rc = build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_SIG);
+ if (rc)
+ goto leave;
+
+ /* Prepare iobufs. */
+ inp = iobuf_open (fname);
+ if (inp && is_secured_file (iobuf_get_fd (inp)))
+ {
+ iobuf_close (inp);
+ inp = NULL;
+ gpg_err_set_errno (EPERM);
}
- handle_progress (pfx, inp, fname);
+ if (!inp)
+ {
+ rc = gpg_error_from_syserror ();
+ log_error (_("can't open '%s': %s\n"),
+ fname? fname: "[stdin]", gpg_strerror (rc));
+ goto leave;
+ }
+ handle_progress (pfx, inp, fname);
- /* prepare key */
- s2k = xmalloc_clear( sizeof *s2k );
- s2k->mode = opt.s2k_mode;
- s2k->hash_algo = S2K_DIGEST_ALGO;
+ /* Prepare key. */
+ s2k = xmalloc_clear (sizeof *s2k);
+ s2k->mode = opt.s2k_mode;
+ s2k->hash_algo = S2K_DIGEST_ALGO;
- algo = default_cipher_algo();
- cfx.dek = passphrase_to_dek (algo, s2k, 1, 1, NULL, &canceled);
+ algo = default_cipher_algo ();
+ cfx.dek = passphrase_to_dek (algo, s2k, 1, 1, NULL, &canceled);
- if (!cfx.dek || !cfx.dek->keylen) {
- rc = gpg_error (canceled?GPG_ERR_CANCELED:GPG_ERR_BAD_PASSPHRASE);
- log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc) );
- goto leave;
+ if (!cfx.dek || !cfx.dek->keylen)
+ {
+ rc = gpg_error (canceled?GPG_ERR_CANCELED:GPG_ERR_BAD_PASSPHRASE);
+ log_error (_("error creating passphrase: %s\n"), gpg_strerror (rc));
+ goto leave;
}
- cfx.dek->use_aead = use_aead (NULL, cfx.dek->algo);
- if (!cfx.dek->use_aead)
- cfx.dek->use_mdc = !!use_mdc (NULL, cfx.dek->algo);
-
- if (!opt.quiet || !opt.batch)
- log_info (_("%s.%s encryption will be used\n"),
- openpgp_cipher_algo_name (algo),
- cfx.dek->use_aead? openpgp_aead_algo_name (cfx.dek->use_aead)
- /**/ : "CFB");
-
- /* now create the outfile */
- rc = open_outfile (-1, fname, opt.armor? 1:0, 0, &out);
- if (rc)
- goto leave;
-
- /* prepare to calculate the MD over the input */
- if (opt.textmode)
- iobuf_push_filter (inp, text_filter, &tfx);
- if ( gcry_md_open (&mfx.md, 0, 0) )
- BUG ();
- if ( DBG_HASHING )
- gcry_md_debug (mfx.md, "symc-sign");
+ cfx.dek->use_aead = use_aead (NULL, cfx.dek->algo);
+ if (!cfx.dek->use_aead)
+ cfx.dek->use_mdc = !!use_mdc (NULL, cfx.dek->algo);
+
+ if (!opt.quiet || !opt.batch)
+ log_info (_("%s.%s encryption will be used\n"),
+ openpgp_cipher_algo_name (algo),
+ cfx.dek->use_aead? openpgp_aead_algo_name (cfx.dek->use_aead)
+ /**/ : "CFB");
+
+ /* Now create the outfile. */
+ rc = open_outfile (-1, fname, opt.armor? 1:0, 0, &out);
+ if (rc)
+ goto leave;
+
+ /* Prepare to calculate the MD over the input. */
+ if (opt.textmode)
+ iobuf_push_filter (inp, text_filter, &tfx);
+ if (gcry_md_open (&mfx.md, 0, 0))
+ BUG ();
+ if (DBG_HASHING)
+ gcry_md_debug (mfx.md, "symc-sign");
- for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next)
- gcry_md_enable (mfx.md, hash_for (sk_rover->pk));
+ for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next)
+ gcry_md_enable (mfx.md, hash_for (sk_rover->pk));
- iobuf_push_filter (inp, md_filter, &mfx);
+ iobuf_push_filter (inp, md_filter, &mfx);
- /* Push armor output filter */
- if (opt.armor)
- push_armor_filter (afx, out);
+ /* Push armor output filter */
+ if (opt.armor)
+ push_armor_filter (afx, out);
- /* Write the symmetric key packet */
- /*(current filters: armor)*/
+ /* Write the symmetric key packet */
+ /* (current filters: armor)*/
+ {
+ PKT_symkey_enc *enc = xmalloc_clear( sizeof *enc );
+
+ enc->version = 4;
+ enc->cipher_algo = cfx.dek->algo;
+ enc->s2k = *s2k;
+ pkt.pkttype = PKT_SYMKEY_ENC;
+ pkt.pkt.symkey_enc = enc;
+ if ((rc = build_packet (out, &pkt)))
+ log_error ("build symkey packet failed: %s\n", gpg_strerror (rc));
+ xfree (enc);
+ }
+
+ /* Push the encryption filter */
+ iobuf_push_filter (out,
+ cfx.dek->use_aead? cipher_filter_aead
+ /**/ : cipher_filter_cfb,
+ &cfx);
+
+ /* Push the compress filter */
+ if (default_compress_algo())
{
- PKT_symkey_enc *enc = xmalloc_clear( sizeof *enc );
- enc->version = 4;
- enc->cipher_algo = cfx.dek->algo;
- enc->s2k = *s2k;
- pkt.pkttype = PKT_SYMKEY_ENC;
- pkt.pkt.symkey_enc = enc;
- if( (rc = build_packet( out, &pkt )) )
- log_error("build symkey packet failed: %s\n", gpg_strerror (rc) );
- xfree(enc);
+ if (cfx.dek && (cfx.dek->use_mdc || cfx.dek->use_aead))
+ zfx.new_ctb = 1;
+ push_compress_filter (out, &zfx,default_compress_algo() );
}
- /* Push the encryption filter */
- iobuf_push_filter (out,
- cfx.dek->use_aead? cipher_filter_aead
- /**/ : cipher_filter_cfb,
- &cfx);
+ /* Write the one-pass signature packets */
+ /* (current filters: zip - encrypt - armor) */
+ rc = write_onepass_sig_packets (sk_list, out, opt.textmode? 0x01:0x00);
+ if (rc)
+ goto leave;
- /* Push the compress filter */
- if (default_compress_algo())
- {
- if (cfx.dek && (cfx.dek->use_mdc || cfx.dek->use_aead))
- zfx.new_ctb = 1;
- push_compress_filter (out, &zfx,default_compress_algo() );
- }
+ write_status_begin_signing (mfx.md);
- /* Write the one-pass signature packets */
- /*(current filters: zip - encrypt - armor)*/
- rc = write_onepass_sig_packets (sk_list, out,
- opt.textmode? 0x01:0x00);
- if (rc)
- goto leave;
+ /* Pipe data through all filters; i.e. write the signed stuff. */
+ /* (current filters: zip - encrypt - armor) */
+ rc = write_plaintext_packet (out, inp, fname,
+ opt.textmode ? (opt.mimemode?'m':'t'):'b');
+ if (rc)
+ goto leave;
- write_status_begin_signing (mfx.md);
-
- /* Pipe data through all filters; i.e. write the signed stuff */
- /*(current filters: zip - encrypt - armor)*/
- rc = write_plaintext_packet (out, inp, fname,
- opt.textmode ? (opt.mimemode?'m':'t'):'b');
- if (rc)
- goto leave;
-
- /* Write the signatures */
- /*(current filters: zip - encrypt - armor)*/
- rc = write_signature_packets (ctrl, sk_list, out, mfx.md,
- opt.textmode? 0x01 : 0x00,
- 0, duration, 'S', NULL);
- if( rc )
- goto leave;
+ /* Write the signatures. */
+ /* (current filters: zip - encrypt - armor) */
+ rc = write_signature_packets (ctrl, sk_list, out, mfx.md,
+ opt.textmode? 0x01 : 0x00,
+ 0, duration, 'S', NULL);
+ if (rc)
+ goto leave;
- leave:
- if( rc )
- iobuf_cancel(out);
- else {
- iobuf_close(out);
- write_status( STATUS_END_ENCRYPTION );
+ leave:
+ if (rc)
+ iobuf_cancel (out);
+ else
+ {
+ iobuf_close (out);
+ write_status (STATUS_END_ENCRYPTION);
}
- iobuf_close(inp);
- release_sk_list( sk_list );
- gcry_md_close( mfx.md );
- xfree(cfx.dek);
- xfree(s2k);
- release_progress_context (pfx);
- release_armor_context (afx);
- return rc;
+ iobuf_close (inp);
+ release_sk_list (sk_list);
+ gcry_md_close (mfx.md);
+ xfree (cfx.dek);
+ xfree (s2k);
+ release_progress_context (pfx);
+ release_armor_context (afx);
+ return rc;
}
-/****************
+/*
* Create a v4 signature in *RET_SIG.
*
* PK is the primary key to sign (required for all sigs)
@@ -1472,105 +1519,102 @@ make_keysig_packet (ctrl_t ctrl,
int (*mksubpkt)(PKT_signature *, void *), void *opaque,
const char *cache_nonce)
{
- PKT_signature *sig;
- int rc=0;
- int sigversion;
- gcry_md_hd_t md;
+ PKT_signature *sig;
+ int rc = 0;
+ int sigversion;
+ gcry_md_hd_t md;
- log_assert ((sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F
- || sigclass == 0x20 || sigclass == 0x18 || sigclass == 0x19
- || sigclass == 0x30 || sigclass == 0x28 );
+ log_assert ((sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F
+ || sigclass == 0x20 || sigclass == 0x18 || sigclass == 0x19
+ || sigclass == 0x30 || sigclass == 0x28 );
+ if (pksk->version >= 5)
+ sigversion = 5;
+ else
sigversion = 4;
- if (sigversion < pksk->version)
- sigversion = pksk->version;
- if( !digest_algo )
- {
- /* Basically, this means use SHA1 always unless the user
- specified something (use whatever they said), or it's DSA
- (use the best match). They still can't pick an
- inappropriate hash for DSA or the signature will fail.
- Note that this still allows the caller of
- make_keysig_packet to override the user setting if it
- must. */
-
- if(opt.cert_digest_algo)
- digest_algo=opt.cert_digest_algo;
- else if(pksk->pubkey_algo == PUBKEY_ALGO_DSA)
- digest_algo = match_dsa_hash (gcry_mpi_get_nbits (pksk->pkey[1])/8);
- else if (pksk->pubkey_algo == PUBKEY_ALGO_ECDSA
- || pksk->pubkey_algo == PUBKEY_ALGO_EDDSA)
- {
- if (openpgp_oid_is_ed25519 (pksk->pkey[0]))
- digest_algo = DIGEST_ALGO_SHA256;
- else
- digest_algo = match_dsa_hash
- (ecdsa_qbits_from_Q (gcry_mpi_get_nbits (pksk->pkey[1]))/8);
- }
- else
- digest_algo = DEFAULT_DIGEST_ALGO;
- }
+ if (!digest_algo)
+ {
+ /* Basically, this means use SHA1 always unless the user
+ * specified something (use whatever they said), or it's DSA
+ * (use the best match). They still can't pick an inappropriate
+ * hash for DSA or the signature will fail. Note that this
+ * still allows the caller of make_keysig_packet to override the
+ * user setting if it must. */
+
+ if (opt.cert_digest_algo)
+ digest_algo = opt.cert_digest_algo;
+ else if (pksk->pubkey_algo == PUBKEY_ALGO_DSA)
+ digest_algo = match_dsa_hash (gcry_mpi_get_nbits (pksk->pkey[1])/8);
+ else if (pksk->pubkey_algo == PUBKEY_ALGO_ECDSA
+ || pksk->pubkey_algo == PUBKEY_ALGO_EDDSA)
+ {
+ if (openpgp_oid_is_ed25519 (pksk->pkey[0]))
+ digest_algo = DIGEST_ALGO_SHA256;
+ else
+ digest_algo = match_dsa_hash
+ (ecdsa_qbits_from_Q (gcry_mpi_get_nbits (pksk->pkey[1]))/8);
+ }
+ else
+ digest_algo = DEFAULT_DIGEST_ALGO;
+ }
- if ( gcry_md_open (&md, digest_algo, 0 ) )
- BUG ();
+ if (gcry_md_open (&md, digest_algo, 0))
+ BUG ();
- /* Hash the public key certificate. */
- hash_public_key( md, pk );
+ /* Hash the public key certificate. */
+ hash_public_key (md, pk);
- if( sigclass == 0x18 || sigclass == 0x19 || sigclass == 0x28 )
- {
- /* hash the subkey binding/backsig/revocation */
- hash_public_key( md, subpk );
- }
- else if( sigclass != 0x1F && sigclass != 0x20 )
- {
- /* hash the user id */
- hash_uid (md, sigversion, uid);
- }
- /* and make the signature packet */
- sig = xmalloc_clear( sizeof *sig );
- sig->version = sigversion;
- sig->flags.exportable=1;
- sig->flags.revocable=1;
- keyid_from_pk (pksk, sig->keyid);
- sig->pubkey_algo = pksk->pubkey_algo;
- sig->digest_algo = digest_algo;
- if(timestamp)
- sig->timestamp=timestamp;
- else
- sig->timestamp=make_timestamp();
- if(duration)
- sig->expiredate=sig->timestamp+duration;
- sig->sig_class = sigclass;
-
- build_sig_subpkt_from_sig (sig, pksk);
- mk_notation_policy_etc (sig, pk, pksk);
-
- /* Crucial that the call to mksubpkt comes LAST before the calls
- to finalize the sig as that makes it possible for the mksubpkt
- function to get a reliable pointer to the subpacket area. */
- if (mksubpkt)
- rc = (*mksubpkt)( sig, opaque );
-
- if( !rc ) {
- hash_sigversion_to_magic (md, sig);
- gcry_md_final (md);
-
- rc = complete_sig (ctrl, sig, pksk, md, cache_nonce);
+ if (sigclass == 0x18 || sigclass == 0x19 || sigclass == 0x28)
+ {
+ /* Hash the subkey binding/backsig/revocation. */
+ hash_public_key (md, subpk);
+ }
+ else if (sigclass != 0x1F && sigclass != 0x20)
+ {
+ /* Hash the user id. */
+ hash_uid (md, sigversion, uid);
+ }
+ /* Make the signature packet. */
+ sig = xmalloc_clear (sizeof *sig);
+ sig->version = sigversion;
+ sig->flags.exportable = 1;
+ sig->flags.revocable = 1;
+ keyid_from_pk (pksk, sig->keyid);
+ sig->pubkey_algo = pksk->pubkey_algo;
+ sig->digest_algo = digest_algo;
+ sig->timestamp = timestamp? timestamp : make_timestamp ();
+ if (duration)
+ sig->expiredate = sig->timestamp + duration;
+ sig->sig_class = sigclass;
+
+ build_sig_subpkt_from_sig (sig, pksk);
+ mk_notation_policy_etc (sig, pk, pksk);
+
+ /* Crucial that the call to mksubpkt comes LAST before the calls
+ * to finalize the sig as that makes it possible for the mksubpkt
+ * function to get a reliable pointer to the subpacket area. */
+ if (mksubpkt)
+ rc = (*mksubpkt)(sig, opaque);
+
+ if (!rc)
+ {
+ hash_sigversion_to_magic (md, sig);
+ gcry_md_final (md);
+ rc = complete_sig (ctrl, sig, pksk, md, cache_nonce);
}
- gcry_md_close (md);
- if( rc )
- free_seckey_enc( sig );
- else
- *ret_sig = sig;
- return rc;
+ gcry_md_close (md);
+ if (rc)
+ free_seckey_enc (sig);
+ else
+ *ret_sig = sig;
+ return rc;
}
-/****************
+/*
* Create a new signature packet based on an existing one.
* Only user ID signatures are supported for now.
* PK is the public key to work on.
@@ -1589,82 +1633,82 @@ update_keysig_packet (ctrl_t ctrl,
int (*mksubpkt)(PKT_signature *, void *),
void *opaque)
{
- PKT_signature *sig;
- gpg_error_t rc = 0;
- int digest_algo;
- gcry_md_hd_t md;
-
- if ((!orig_sig || !pk || !pksk)
- || (orig_sig->sig_class >= 0x10 && orig_sig->sig_class <= 0x13 && !uid)
- || (orig_sig->sig_class == 0x18 && !subpk))
- return GPG_ERR_GENERAL;
-
- if ( opt.cert_digest_algo )
- digest_algo = opt.cert_digest_algo;
- else
- digest_algo = orig_sig->digest_algo;
+ PKT_signature *sig;
+ gpg_error_t rc = 0;
+ int digest_algo;
+ gcry_md_hd_t md;
+
+ if ((!orig_sig || !pk || !pksk)
+ || (orig_sig->sig_class >= 0x10 && orig_sig->sig_class <= 0x13 && !uid)
+ || (orig_sig->sig_class == 0x18 && !subpk))
+ return GPG_ERR_GENERAL;
+
+ if (opt.cert_digest_algo)
+ digest_algo = opt.cert_digest_algo;
+ else
+ digest_algo = orig_sig->digest_algo;
- if ( gcry_md_open (&md, digest_algo, 0 ) )
- BUG ();
+ if (gcry_md_open (&md, digest_algo, 0))
+ BUG ();
- /* Hash the public key certificate and the user id. */
- hash_public_key( md, pk );
+ /* Hash the public key certificate and the user id. */
+ hash_public_key (md, pk);
- if( orig_sig->sig_class == 0x18 )
- hash_public_key( md, subpk );
- else
- hash_uid (md, orig_sig->version, uid);
+ if (orig_sig->sig_class == 0x18)
+ hash_public_key (md, subpk);
+ else
+ hash_uid (md, orig_sig->version, uid);
- /* create a new signature packet */
- sig = copy_signature (NULL, orig_sig);
+ /* Create a new signature packet. */
+ sig = copy_signature (NULL, orig_sig);
- sig->digest_algo=digest_algo;
+ sig->digest_algo = digest_algo;
- /* We need to create a new timestamp so that new sig expiration
- calculations are done correctly... */
- sig->timestamp=make_timestamp();
+ /* We need to create a new timestamp so that new sig expiration
+ * calculations are done correctly... */
+ sig->timestamp = make_timestamp();
- /* ... but we won't make a timestamp earlier than the existing
- one. */
- {
- int tmout = 0;
- while(sig->timestamp<=orig_sig->timestamp)
- {
- if (++tmout > 5 && !opt.ignore_time_conflict)
- {
- rc = gpg_error (GPG_ERR_TIME_CONFLICT);
- goto leave;
- }
- gnupg_sleep (1);
- sig->timestamp=make_timestamp();
- }
- }
-
- /* Note that already expired sigs will remain expired (with a
- duration of 1) since build-packet.c:build_sig_subpkt_from_sig
- detects this case. */
+ /* ... but we won't make a timestamp earlier than the existing
+ * one. */
+ {
+ int tmout = 0;
+ while (sig->timestamp <= orig_sig->timestamp)
+ {
+ if (++tmout > 5 && !opt.ignore_time_conflict)
+ {
+ rc = gpg_error (GPG_ERR_TIME_CONFLICT);
+ goto leave;
+ }
+ gnupg_sleep (1);
+ sig->timestamp = make_timestamp();
+ }
+ }
- /* Put the updated timestamp into the sig. Note that this will
- automagically lower any sig expiration dates to correctly
- correspond to the differences in the timestamps (i.e. the
- duration will shrink). */
- build_sig_subpkt_from_sig (sig, pksk);
+ /* Note that already expired sigs will remain expired (with a
+ * duration of 1) since build-packet.c:build_sig_subpkt_from_sig
+ * detects this case. */
- if (mksubpkt)
- rc = (*mksubpkt)(sig, opaque);
+ /* Put the updated timestamp into the sig. Note that this will
+ * automagically lower any sig expiration dates to correctly
+ * correspond to the differences in the timestamps (i.e. the
+ * duration will shrink). */
+ build_sig_subpkt_from_sig (sig, pksk);
- if (!rc) {
- hash_sigversion_to_magic (md, sig);
- gcry_md_final (md);
+ if (mksubpkt)
+ rc = (*mksubpkt)(sig, opaque);
- rc = complete_sig (ctrl, sig, pksk, md, NULL);
+ if (!rc)
+ {
+ hash_sigversion_to_magic (md, sig);
+ gcry_md_final (md);
+ rc = complete_sig (ctrl, sig, pksk, md, NULL);
}
leave:
- gcry_md_close (md);
- if( rc )
- free_seckey_enc (sig);
- else
- *ret_sig = sig;
- return rc;
+ gcry_md_close (md);
+ if (rc)
+ free_seckey_enc (sig);
+ else
+ *ret_sig = sig;
+ return rc;
}
diff --git a/g10/skclist.c b/g10/skclist.c
index 78890dc42..c9c41d0d9 100644
--- a/g10/skclist.c
+++ b/g10/skclist.c
@@ -149,7 +149,8 @@ build_sk_list (ctrl_t ctrl,
}
err = get_seckey_default_or_card (ctrl, pk,
- info.fpr1valid? info.fpr1 : NULL, 20);
+ info.fpr1len? info.fpr1 : NULL,
+ info.fpr1len);
if (err)
{
free_public_key (pk);
@@ -286,3 +287,265 @@ build_sk_list (ctrl_t ctrl,
*ret_sk_list = sk_list;
return err;
}
+
+
+/* Enumerate some secret keys (specifically, those specified with
+ * --default-key and --try-secret-key). Use the following procedure:
+ *
+ * 1) Initialize a void pointer to NULL
+ * 2) Pass a reference to this pointer to this function (content)
+ * and provide space for the secret key (sk)
+ * 3) Call this function as long as it does not return an error (or
+ * until you are done). The error code GPG_ERR_EOF indicates the
+ * end of the listing.
+ * 4) Call this function a last time with SK set to NULL,
+ * so that can free it's context.
+ *
+ * In pseudo-code:
+ *
+ * void *ctx = NULL;
+ * PKT_public_key *sk = xmalloc_clear (sizeof (*sk));
+ *
+ * while ((err = enum_secret_keys (&ctx, sk)))
+ * { // Process SK.
+ * if (done)
+ * break;
+ * sk = xmalloc_clear (sizeof (*sk));
+ * }
+ *
+ * // Release any resources used by CTX.
+ * enum_secret_keys (&ctx, NULL);
+ *
+ * if (gpg_err_code (err) != GPG_ERR_EOF)
+ * ; // An error occurred.
+ */
+gpg_error_t
+enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk)
+{
+ gpg_error_t err = 0;
+ const char *name;
+ kbnode_t keyblock;
+ struct
+ {
+ int eof;
+ int state;
+ strlist_t sl;
+ strlist_t card_list;
+ char *serialno;
+ char fpr2[2 * MAX_FINGERPRINT_LEN + 3 ];
+ struct agent_card_info_s info;
+ kbnode_t keyblock;
+ kbnode_t node;
+ getkey_ctx_t ctx;
+ SK_LIST results;
+ } *c = *context;
+
+ if (!c)
+ {
+ /* Make a new context. */
+ c = xtrycalloc (1, sizeof *c);
+ if (!c)
+ {
+ err = gpg_error_from_syserror ();
+ free_public_key (sk);
+ return err;
+ }
+ *context = c;
+ }
+
+ if (!sk)
+ {
+ /* Free the context. */
+ xfree (c->serialno);
+ free_strlist (c->card_list);
+ release_sk_list (c->results);
+ release_kbnode (c->keyblock);
+ getkey_end (ctrl, c->ctx);
+ xfree (c);
+ *context = NULL;
+ return 0;
+ }
+
+ if (c->eof)
+ {
+ free_public_key (sk);
+ return gpg_error (GPG_ERR_EOF);
+ }
+
+ for (;;)
+ {
+ /* Loop until we have a keyblock. */
+ while (!c->keyblock)
+ {
+ /* Loop over the list of secret keys. */
+ do
+ {
+ char *serialno;
+
+ name = NULL;
+ keyblock = NULL;
+ switch (c->state)
+ {
+ case 0: /* First try to use the --default-key. */
+ name = parse_def_secret_key (ctrl);
+ c->state = 1;
+ break;
+
+ case 1: /* Init list of keys to try. */
+ c->sl = opt.secret_keys_to_try;
+ c->state++;
+ break;
+
+ case 2: /* Get next item from list. */
+ if (c->sl)
+ {
+ name = c->sl->d;
+ c->sl = c->sl->next;
+ }
+ else
+ c->state++;
+ break;
+
+ case 3: /* Init list of card keys to try. */
+ err = agent_scd_cardlist (&c->card_list);
+ if (!err)
+ agent_scd_serialno (&c->serialno, NULL);
+ c->sl = c->card_list;
+ c->state++;
+ break;
+
+ case 4: /* Get next item from card list. */
+ if (c->sl)
+ {
+ err = agent_scd_serialno (&serialno, c->sl->d);
+ if (err)
+ {
+ if (opt.verbose)
+ log_info (_("error getting serial number of card: %s\n"),
+ gpg_strerror (err));
+ continue;
+ }
+
+ xfree (serialno);
+ c->info.fpr2len = 0;
+ err = agent_scd_getattr ("KEY-FPR", &c->info);
+ if (err)
+ log_error ("error retrieving key fingerprint from card: %s\n",
+ gpg_strerror (err));
+
+ if (c->info.fpr2len)
+ {
+ c->fpr2[0] = '0';
+ c->fpr2[1] = 'x';
+ bin2hex (c->info.fpr2, sizeof c->info.fpr2,c->fpr2+2);
+ name = c->fpr2;
+ }
+ c->sl = c->sl->next;
+ }
+ else
+ {
+ serialno = c->serialno;
+ if (serialno)
+ {
+ /* Select the original card again. */
+ agent_scd_serialno (&c->serialno, serialno);
+ xfree (serialno);
+ }
+ c->state++;
+ }
+ break;
+
+ case 5: /* Init search context to enum all secret keys. */
+ err = getkey_bynames (ctrl, &c->ctx, NULL, NULL, 1,
+ &keyblock);
+ if (err)
+ {
+ release_kbnode (keyblock);
+ keyblock = NULL;
+ getkey_end (ctrl, c->ctx);
+ c->ctx = NULL;
+ }
+ c->state++;
+ break;
+
+ case 6: /* Get next item from the context. */
+ if (c->ctx)
+ {
+ err = getkey_next (ctrl, c->ctx, NULL, &keyblock);
+ if (err)
+ {
+ release_kbnode (keyblock);
+ keyblock = NULL;
+ getkey_end (ctrl, c->ctx);
+ c->ctx = NULL;
+ }
+ }
+ else
+ c->state++;
+ break;
+
+ default: /* No more names to check - stop. */
+ c->eof = 1;
+ free_public_key (sk);
+ return gpg_error (GPG_ERR_EOF);
+ }
+ }
+ while ((!name || !*name) && !keyblock);
+
+ if (keyblock)
+ c->node = c->keyblock = keyblock;
+ else
+ {
+ err = getkey_byname (ctrl, NULL, NULL, name, 1, &c->keyblock);
+ if (err)
+ {
+ /* getkey_byname might return a keyblock even in the
+ error case - I have not checked. Thus better release
+ it. */
+ release_kbnode (c->keyblock);
+ c->keyblock = NULL;
+ }
+ else
+ c->node = c->keyblock;
+ }
+ }
+
+ /* Get the next key from the current keyblock. */
+ for (; c->node; c->node = c->node->next)
+ {
+ if (c->node->pkt->pkttype == PKT_PUBLIC_KEY
+ || c->node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
+ {
+ SK_LIST r;
+
+ /* Skip this candidate if it's already enumerated. */
+ for (r = c->results; r; r = r->next)
+ if (!cmp_public_keys (r->pk, c->node->pkt->pkt.public_key))
+ break;
+ if (r)
+ continue;
+
+ copy_public_key (sk, c->node->pkt->pkt.public_key);
+ c->node = c->node->next;
+
+ r = xtrycalloc (1, sizeof (*r));
+ if (!r)
+ {
+ err = gpg_error_from_syserror ();
+ free_public_key (sk);
+ return err;
+ }
+
+ r->pk = sk;
+ r->next = c->results;
+ c->results = r;
+
+ return 0; /* Found. */
+ }
+ }
+
+ /* Dispose the keyblock and continue. */
+ release_kbnode (c->keyblock);
+ c->keyblock = NULL;
+ }
+}
diff --git a/g10/tdbio.c b/g10/tdbio.c
index fed0cf5ab..b6c38bd24 100644
--- a/g10/tdbio.c
+++ b/g10/tdbio.c
@@ -106,7 +106,7 @@ struct cmp_xdir_struct
static char *db_name;
/* The handle for locking the trustdb file and a counter to record how
- * often this lock has been taken. That counter is required becuase
+ * often this lock has been taken. That counter is required because
* dotlock does not implemen recursive locks. */
static dotlock_t lockhandle;
static unsigned int is_locked;
@@ -562,6 +562,12 @@ tdbio_update_version_record (ctrl_t ctrl)
{
TRUSTREC rec;
int rc;
+ int opt_tm;
+
+ /* Never store a TOFU trust model in the trustdb. Use PGP instead. */
+ opt_tm = opt.trust_model;
+ if (opt_tm == TM_TOFU || opt_tm == TM_TOFU_PGP)
+ opt_tm = TM_PGP;
memset (&rec, 0, sizeof rec);
@@ -572,7 +578,7 @@ tdbio_update_version_record (ctrl_t ctrl)
rec.r.ver.marginals = opt.marginals_needed;
rec.r.ver.completes = opt.completes_needed;
rec.r.ver.cert_depth = opt.max_cert_depth;
- rec.r.ver.trust_model = opt.trust_model;
+ rec.r.ver.trust_model = opt_tm;
rec.r.ver.min_cert_level = opt.min_cert_level;
rc = tdbio_write_record (ctrl, &rec);
}
@@ -583,7 +589,7 @@ tdbio_update_version_record (ctrl_t ctrl)
/*
* Create and write the trustdb version record.
- * This is called with the writelock activ.
+ * This is called with the writelock active.
* Returns: 0 on success or an error code.
*/
static int
@@ -591,6 +597,12 @@ create_version_record (ctrl_t ctrl)
{
TRUSTREC rec;
int rc;
+ int opt_tm;
+
+ /* Never store a TOFU trust model in the trustdb. Use PGP instead. */
+ opt_tm = opt.trust_model;
+ if (opt_tm == TM_TOFU || opt_tm == TM_TOFU_PGP)
+ opt_tm = TM_PGP;
memset (&rec, 0, sizeof rec);
rec.r.ver.version = 3;
@@ -598,8 +610,8 @@ create_version_record (ctrl_t ctrl)
rec.r.ver.marginals = opt.marginals_needed;
rec.r.ver.completes = opt.completes_needed;
rec.r.ver.cert_depth = opt.max_cert_depth;
- if (opt.trust_model == TM_PGP || opt.trust_model == TM_CLASSIC)
- rec.r.ver.trust_model = opt.trust_model;
+ if (opt_tm == TM_PGP || opt_tm == TM_CLASSIC)
+ rec.r.ver.trust_model = opt_tm;
else
rec.r.ver.trust_model = TM_PGP;
rec.r.ver.min_cert_level = opt.min_cert_level;
@@ -883,16 +895,25 @@ tdbio_db_matches_options()
{
TRUSTREC vr;
int rc;
+ int opt_tm, tm;
rc = tdbio_read_record (0, &vr, RECTYPE_VER);
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, gpg_strerror (rc) );
+ /* Consider tofu and pgp the same. */
+ tm = vr.r.ver.trust_model;
+ if (tm == TM_TOFU || tm == TM_TOFU_PGP)
+ tm = TM_PGP;
+ opt_tm = opt.trust_model;
+ if (opt_tm == TM_TOFU || opt_tm == TM_TOFU_PGP)
+ opt_tm = TM_PGP;
+
yes_no = vr.r.ver.marginals == opt.marginals_needed
&& vr.r.ver.completes == opt.completes_needed
&& vr.r.ver.cert_depth == opt.max_cert_depth
- && vr.r.ver.trust_model == opt.trust_model
+ && tm == opt_tm
&& vr.r.ver.min_cert_level == opt.min_cert_level;
}
@@ -1118,7 +1139,7 @@ upd_hashtable (ctrl_t ctrl, ulong table, byte *key, int keylen, ulong newrecnum)
if (rec.r.hlst.next)
{
- /* read the next reord of the list. */
+ /* read the next record of the list. */
rc = tdbio_read_record (rec.r.hlst.next, &rec, RECTYPE_HLST);
if (rc)
{
diff --git a/g10/test-stubs.c b/g10/test-stubs.c
index 1e1363266..a2b0d2906 100644
--- a/g10/test-stubs.c
+++ b/g10/test-stubs.c
@@ -253,7 +253,7 @@ read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
* No encryption here but mainproc links to these functions.
*/
gpg_error_t
-get_session_key (ctrl_t ctrl, PKT_pubkey_enc *k, DEK *dek)
+get_session_key (ctrl_t ctrl, struct pubkey_enc_list *k, DEK *dek)
{
(void)ctrl;
(void)k;
diff --git a/g10/tofu.c b/g10/tofu.c
index 762b19b7a..44f354512 100644
--- a/g10/tofu.c
+++ b/g10/tofu.c
@@ -3292,7 +3292,7 @@ show_warning (const char *fingerprint, strlist_t user_id_list)
static char *
email_from_user_id (const char *user_id)
{
- char *email = mailbox_from_userid (user_id);
+ char *email = mailbox_from_userid (user_id, 0);
if (! email)
{
/* Hmm, no email address was provided or we are out of core. Just
diff --git a/g10/trust.c b/g10/trust.c
index 6d4f0e74b..bd1c89458 100644
--- a/g10/trust.c
+++ b/g10/trust.c
@@ -437,391 +437,3 @@ get_validity_string (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid)
return _("revoked");
return trust_value_to_string (trustlevel);
}
-
-
-
-/*
- * Mark the signature of the given UID which are used to certify it.
- * To do this, we first revmove all signatures which are not valid and
- * from the remain ones we look for the latest one. If this is not a
- * certification revocation signature we mark the signature by setting
- * node flag bit 8. Revocations are marked with flag 11, and sigs
- * from unavailable keys are marked with flag 12. Note that flag bits
- * 9 and 10 are used for internal purposes.
- */
-void
-mark_usable_uid_certs (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
- u32 *main_kid, struct key_item *klist,
- u32 curtime, u32 *next_expire)
-{
- kbnode_t node;
- PKT_signature *sig;
-
- /* First check all signatures. */
- for (node=uidnode->next; node; node = node->next)
- {
- int rc;
-
- node->flag &= ~(1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12);
- if (node->pkt->pkttype == PKT_USER_ID
- || node->pkt->pkttype == PKT_PUBLIC_SUBKEY
- || node->pkt->pkttype == PKT_SECRET_SUBKEY)
- break; /* ready */
- if (node->pkt->pkttype != PKT_SIGNATURE)
- continue;
- sig = node->pkt->pkt.signature;
- if (main_kid
- && sig->keyid[0] == main_kid[0] && sig->keyid[1] == main_kid[1])
- continue; /* ignore self-signatures if we pass in a main_kid */
- if (!IS_UID_SIG(sig) && !IS_UID_REV(sig))
- continue; /* we only look at these signature classes */
- if(sig->sig_class>=0x11 && sig->sig_class<=0x13 &&
- sig->sig_class-0x10<opt.min_cert_level)
- continue; /* treat anything under our min_cert_level as an
- invalid signature */
- if (klist && !is_in_klist (klist, sig))
- continue; /* no need to check it then */
- if ((rc=check_key_signature (ctrl, keyblock, node, NULL)))
- {
- /* we ignore anything that won't verify, but tag the
- no_pubkey case */
- if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY)
- node->flag |= 1<<12;
- continue;
- }
- node->flag |= 1<<9;
- }
- /* Reset the remaining flags. */
- for (; node; node = node->next)
- node->flag &= ~(1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12);
-
- /* kbnode flag usage: bit 9 is here set for signatures to consider,
- * bit 10 will be set by the loop to keep track of keyIDs already
- * processed, bit 8 will be set for the usable signatures, and bit
- * 11 will be set for usable revocations. */
-
- /* For each cert figure out the latest valid one. */
- for (node=uidnode->next; node; node = node->next)
- {
- KBNODE n, signode;
- u32 kid[2];
- u32 sigdate;
-
- if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
- || node->pkt->pkttype == PKT_SECRET_SUBKEY)
- break;
- if ( !(node->flag & (1<<9)) )
- continue; /* not a node to look at */
- if ( (node->flag & (1<<10)) )
- continue; /* signature with a keyID already processed */
- node->flag |= (1<<10); /* mark this node as processed */
- sig = node->pkt->pkt.signature;
- signode = node;
- sigdate = sig->timestamp;
- kid[0] = sig->keyid[0]; kid[1] = sig->keyid[1];
-
- /* Now find the latest and greatest signature */
- for (n=uidnode->next; n; n = n->next)
- {
- if (n->pkt->pkttype == PKT_PUBLIC_SUBKEY
- || n->pkt->pkttype == PKT_SECRET_SUBKEY)
- break;
- if ( !(n->flag & (1<<9)) )
- continue;
- if ( (n->flag & (1<<10)) )
- continue; /* shortcut already processed signatures */
- sig = n->pkt->pkt.signature;
- if (kid[0] != sig->keyid[0] || kid[1] != sig->keyid[1])
- continue;
- n->flag |= (1<<10); /* mark this node as processed */
-
- /* If signode is nonrevocable and unexpired and n isn't,
- then take signode (skip). It doesn't matter which is
- older: if signode was older then we don't want to take n
- as signode is nonrevocable. If n was older then we're
- automatically fine. */
-
- if(((IS_UID_SIG(signode->pkt->pkt.signature) &&
- !signode->pkt->pkt.signature->flags.revocable &&
- (signode->pkt->pkt.signature->expiredate==0 ||
- signode->pkt->pkt.signature->expiredate>curtime))) &&
- (!(IS_UID_SIG(n->pkt->pkt.signature) &&
- !n->pkt->pkt.signature->flags.revocable &&
- (n->pkt->pkt.signature->expiredate==0 ||
- n->pkt->pkt.signature->expiredate>curtime))))
- continue;
-
- /* If n is nonrevocable and unexpired and signode isn't,
- then take n. Again, it doesn't matter which is older: if
- n was older then we don't want to take signode as n is
- nonrevocable. If signode was older then we're
- automatically fine. */
-
- if((!(IS_UID_SIG(signode->pkt->pkt.signature) &&
- !signode->pkt->pkt.signature->flags.revocable &&
- (signode->pkt->pkt.signature->expiredate==0 ||
- signode->pkt->pkt.signature->expiredate>curtime))) &&
- ((IS_UID_SIG(n->pkt->pkt.signature) &&
- !n->pkt->pkt.signature->flags.revocable &&
- (n->pkt->pkt.signature->expiredate==0 ||
- n->pkt->pkt.signature->expiredate>curtime))))
- {
- signode = n;
- sigdate = sig->timestamp;
- continue;
- }
-
- /* At this point, if it's newer, it goes in as the only
- remaining possibilities are signode and n are both either
- revocable or expired or both nonrevocable and unexpired.
- If the timestamps are equal take the later ordered
- packet, presuming that the key packets are hopefully in
- their original order. */
-
- if (sig->timestamp >= sigdate)
- {
- signode = n;
- sigdate = sig->timestamp;
- }
- }
-
- sig = signode->pkt->pkt.signature;
- if (IS_UID_SIG (sig))
- { /* this seems to be a usable one which is not revoked.
- * Just need to check whether there is an expiration time,
- * We do the expired certification after finding a suitable
- * certification, the assumption is that a signator does not
- * want that after the expiration of his certificate the
- * system falls back to an older certification which has a
- * different expiration time */
- const byte *p;
- u32 expire;
-
- p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_EXPIRE, NULL );
- expire = p? sig->timestamp + buf32_to_u32(p) : 0;
-
- if (expire==0 || expire > curtime )
- {
- signode->flag |= (1<<8); /* yeah, found a good cert */
- if (next_expire && expire && expire < *next_expire)
- *next_expire = expire;
- }
- }
- else
- signode->flag |= (1<<11);
- }
-}
-
-
-static int
-clean_sigs_from_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
- int noisy, int self_only)
-{
- int deleted = 0;
- kbnode_t node;
- u32 keyid[2];
-
- log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY
- || keyblock->pkt->pkttype == PKT_SECRET_KEY);
-
- keyid_from_pk (keyblock->pkt->pkt.public_key, keyid);
-
- /* Passing in a 0 for current time here means that we'll never weed
- out an expired sig. This is correct behavior since we want to
- keep the most recent expired sig in a series. */
- mark_usable_uid_certs (ctrl, keyblock, uidnode, NULL, NULL, 0, NULL);
-
- /* What we want to do here is remove signatures that are not
- considered as part of the trust calculations. Thus, all invalid
- signatures are out, as are any signatures that aren't the last of
- a series of uid sigs or revocations It breaks down like this:
- coming out of mark_usable_uid_certs, if a sig is unflagged, it is
- not even a candidate. If a sig has flag 9 or 10, that means it
- was selected as a candidate and vetted. If a sig has flag 8 it
- is a usable signature. If a sig has flag 11 it is a usable
- revocation. If a sig has flag 12 it was issued by an unavailable
- key. "Usable" here means the most recent valid
- signature/revocation in a series from a particular signer.
-
- Delete everything that isn't a usable uid sig (which might be
- expired), a usable revocation, or a sig from an unavailable
- key. */
-
- for (node=uidnode->next;
- node && node->pkt->pkttype==PKT_SIGNATURE;
- node=node->next)
- {
- int keep;
-
- keep = self_only? (node->pkt->pkt.signature->keyid[0] == keyid[0]
- && node->pkt->pkt.signature->keyid[1] == keyid[1]) : 1;
-
- /* Keep usable uid sigs ... */
- if ((node->flag & (1<<8)) && keep)
- continue;
-
- /* ... and usable revocations... */
- if ((node->flag & (1<<11)) && keep)
- continue;
-
- /* ... and sigs from unavailable keys. */
- /* disabled for now since more people seem to want sigs from
- unavailable keys removed altogether. */
- /*
- if(node->flag & (1<<12))
- continue;
- */
-
- /* Everything else we delete */
-
- /* At this point, if 12 is set, the signing key was unavailable.
- If 9 or 10 is set, it's superseded. Otherwise, it's
- invalid. */
-
- if (noisy)
- log_info ("removing signature from key %s on user ID \"%s\": %s\n",
- keystr (node->pkt->pkt.signature->keyid),
- uidnode->pkt->pkt.user_id->name,
- node->flag&(1<<12)? "key unavailable":
- node->flag&(1<<9)? "signature superseded"
- /* */ :"invalid signature" );
-
- delete_kbnode (node);
- deleted++;
- }
-
- return deleted;
-}
-
-
-/* This is substantially easier than clean_sigs_from_uid since we just
- have to establish if the uid has a valid self-sig, is not revoked,
- and is not expired. Note that this does not take into account
- whether the uid has a trust path to it - just whether the keyholder
- themselves has certified the uid. Returns true if the uid was
- compacted. To "compact" a user ID, we simply remove ALL signatures
- except the self-sig that caused the user ID to be remove-worthy.
- We don't actually remove the user ID packet itself since it might
- be resurrected in a later merge. Note that this function requires
- that the caller has already done a merge_keys_and_selfsig().
-
- TODO: change the import code to allow importing a uid with only a
- revocation if the uid already exists on the keyring. */
-
-static int
-clean_uid_from_key (kbnode_t keyblock, kbnode_t uidnode, int noisy)
-{
- kbnode_t node;
- PKT_user_id *uid = uidnode->pkt->pkt.user_id;
- int deleted = 0;
-
- log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY
- || keyblock->pkt->pkttype == PKT_SECRET_KEY);
- log_assert (uidnode->pkt->pkttype==PKT_USER_ID);
-
- /* Skip valid user IDs, compacted user IDs, and non-self-signed user
- IDs if --allow-non-selfsigned-uid is set. */
- if (uid->created
- || uid->flags.compacted
- || (!uid->flags.expired && !uid->flags.revoked && opt.allow_non_selfsigned_uid))
- return 0;
-
- for (node=uidnode->next;
- node && node->pkt->pkttype == PKT_SIGNATURE;
- node=node->next)
- {
- if (!node->pkt->pkt.signature->flags.chosen_selfsig)
- {
- delete_kbnode (node);
- deleted = 1;
- uidnode->pkt->pkt.user_id->flags.compacted = 1;
- }
- }
-
- if (noisy)
- {
- const char *reason;
- char *user = utf8_to_native (uid->name, uid->len, 0);
-
- if (uid->flags.revoked)
- reason = _("revoked");
- else if (uid->flags.expired)
- reason = _("expired");
- else
- reason = _("invalid");
-
- log_info ("compacting user ID \"%s\" on key %s: %s\n",
- user, keystr_from_pk (keyblock->pkt->pkt.public_key),
- reason);
-
- xfree (user);
- }
-
- return deleted;
-}
-
-
-/* Needs to be called after a merge_keys_and_selfsig() */
-void
-clean_one_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
- int noisy, int self_only, int *uids_cleaned, int *sigs_cleaned)
-{
- int dummy = 0;
-
- log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY
- || keyblock->pkt->pkttype == PKT_SECRET_KEY);
- log_assert (uidnode->pkt->pkttype==PKT_USER_ID);
-
- if (!uids_cleaned)
- uids_cleaned = &dummy;
-
- if (!sigs_cleaned)
- sigs_cleaned = &dummy;
-
- /* Do clean_uid_from_key first since if it fires off, we don't have
- to bother with the other. */
- *uids_cleaned += clean_uid_from_key (keyblock, uidnode, noisy);
- if (!uidnode->pkt->pkt.user_id->flags.compacted)
- *sigs_cleaned += clean_sigs_from_uid (ctrl, keyblock, uidnode,
- noisy, self_only);
-}
-
-
-/* NB: This function marks the deleted nodes only and the caller is
- * responsible to skip or remove them. */
-void
-clean_key (ctrl_t ctrl, kbnode_t keyblock, int noisy, int self_only,
- int *uids_cleaned, int *sigs_cleaned)
-{
- kbnode_t node;
-
- merge_keys_and_selfsig (ctrl, keyblock);
-
- for (node = keyblock->next;
- node && !(node->pkt->pkttype == PKT_PUBLIC_SUBKEY
- || node->pkt->pkttype == PKT_SECRET_SUBKEY);
- node = node->next)
- {
- if (node->pkt->pkttype == PKT_USER_ID)
- clean_one_uid (ctrl, keyblock, node, noisy, self_only,
- uids_cleaned, sigs_cleaned);
- }
-
- /* Remove bogus subkey binding signatures: The only signatures
- * allowed are of class 0x18 and 0x28. */
- log_assert (!node || (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
- || node->pkt->pkttype == PKT_SECRET_SUBKEY));
- for (; node; node = node->next)
- {
- if (is_deleted_kbnode (node))
- continue;
- if (node->pkt->pkttype == PKT_SIGNATURE
- && !(IS_SUBKEY_SIG (node->pkt->pkt.signature)
- || IS_SUBKEY_REV (node->pkt->pkt.signature)))
- {
- delete_kbnode (node);
- if (sigs_cleaned)
- ++*sigs_cleaned;
- }
- }
-}
diff --git a/g10/trustdb.c b/g10/trustdb.c
index 2c2d2394a..a230a6c03 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -41,6 +41,7 @@
#include "tdbio.h"
#include "trustdb.h"
#include "tofu.h"
+#include "key-clean.h"
typedef struct key_item **KeyHashTable; /* see new_key_hash_table() */
@@ -1130,7 +1131,7 @@ tdb_get_validity_core (ctrl_t ctrl,
if (sig && sig->signers_uid)
/* Make sure the UID matches. */
{
- char *email = mailbox_from_userid (user_id->name);
+ char *email = mailbox_from_userid (user_id->name, 0);
if (!email || !*email || strcmp (sig->signers_uid, email) != 0)
{
if (DBG_TRUST)
@@ -1505,7 +1506,7 @@ store_validation_status (ctrl_t ctrl, int depth,
/* Returns a sanitized copy of the regexp (which might be "", but not
NULL). */
#ifndef DISABLE_REGEX
-/* Operator charactors except '.' and backslash.
+/* Operator characters except '.' and backslash.
See regex(7) on BSD. */
#define REGEXP_OPERATOR_CHARS "^[$()|*+?{"
diff --git a/g10/trustdb.h b/g10/trustdb.h
index 4bc4ca971..d52fc53f2 100644
--- a/g10/trustdb.h
+++ b/g10/trustdb.h
@@ -46,36 +46,6 @@
#define NAMEHASH_LEN 20
-/*
- * A structure to store key identification as well as some stuff needed
- * for validation
- */
-struct key_item {
- struct key_item *next;
- unsigned int ownertrust,min_ownertrust;
- byte trust_depth;
- byte trust_value;
- char *trust_regexp;
- u32 kid[2];
-};
-
-
-/*
- * Check whether the signature SIG is in the klist K.
- */
-static inline struct key_item *
-is_in_klist (struct key_item *k, PKT_signature *sig)
-{
- for (; k; k = k->next)
- {
- if (k->kid[0] == sig->keyid[0] && k->kid[1] == sig->keyid[1])
- return k;
- }
- return NULL;
-}
-
-
-
/*-- trust.c --*/
int cache_disabled_value (ctrl_t ctrl, PKT_public_key *pk);
void register_trusted_keyid (u32 *keyid);
@@ -103,17 +73,6 @@ int get_validity_info (ctrl_t ctrl, kbnode_t kb, PKT_public_key *pk,
const char *get_validity_string (ctrl_t ctrl,
PKT_public_key *pk, PKT_user_id *uid);
-void mark_usable_uid_certs (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
- u32 *main_kid, struct key_item *klist,
- u32 curtime, u32 *next_expire);
-
-void clean_one_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
- int noisy, int self_only,
- int *uids_cleaned, int *sigs_cleaned);
-void clean_key (ctrl_t ctrl, kbnode_t keyblock, int noisy, int self_only,
- int *uids_cleaned,int *sigs_cleaned);
-
-
/*-- trustdb.c --*/
void tdb_register_trusted_keyid (u32 *keyid);
diff --git a/g10/verify.c b/g10/verify.c
index caeb1a244..73ac4bad8 100644
--- a/g10/verify.c
+++ b/g10/verify.c
@@ -69,7 +69,7 @@ verify_signatures (ctrl_t ctrl, int nfiles, char **files )
* we can do it is by reading one byte from stdin and then unget
* it; the problem here is that we may be reading from the
* terminal (which could be detected using isatty() but won't work
- * when under contol of a pty using program (e.g. expect)) and
+ * when under control of a pty using program (e.g. expect)) and
* might get us in trouble when stdin is used for another purpose
* (--passphrase-fd 0). So we have to break with the behaviour
* prior to gpg 1.0.4 by assuming that case 3 is a normal
diff --git a/g13/call-syshelp.c b/g13/call-syshelp.c
index b160ba32d..a69573bd1 100644
--- a/g13/call-syshelp.c
+++ b/g13/call-syshelp.c
@@ -174,7 +174,7 @@ call_syshelp_release (ctrl_t ctrl)
-/* Staus callback for call_syshelp_find_device. */
+/* Status callback for call_syshelp_find_device. */
static gpg_error_t
finddevice_status_cb (void *opaque, const char *line)
{
diff --git a/g13/mountinfo.c b/g13/mountinfo.c
index ed898b836..50cc153fa 100644
--- a/g13/mountinfo.c
+++ b/g13/mountinfo.c
@@ -117,7 +117,7 @@ mountinfo_del_mount (const char *container, const char *mountpoint,
size_t idx;
mtab_t m;
- /* If a container or mountpint is givem search the RID via the
+ /* If a container or mountpint is given search the RID via the
standard find function. */
if (container || mountpoint)
{
diff --git a/g13/runner.c b/g13/runner.c
index 138269d21..b08d99030 100644
--- a/g13/runner.c
+++ b/g13/runner.c
@@ -278,7 +278,7 @@ runner_set_pid (runner_t runner, pid_t pid)
}
-/* Register the engine handler fucntions HANDLER and HANDLER_CLEANUP
+/* Register the engine handler functions HANDLER and HANDLER_CLEANUP
and its private HANDLER_DATA with RUNNER. */
void
runner_set_handler (runner_t runner,
diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c
index 687421219..817253590 100644
--- a/kbx/keybox-blob.c
+++ b/kbx/keybox-blob.c
@@ -616,7 +616,7 @@ create_blob_header (KEYBOXBLOB blob, int blobtype, int as_ephemeral)
if (blobtype == KEYBOX_BLOBTYPE_X509)
{
/* We don't want to point to ASN.1 encoded UserIDs (DNs) but to
- the utf-8 string represenation of them */
+ the utf-8 string representation of them */
for (i=0; i < blob->nuids; i++ )
{
if (blob->uids[i].name)
diff --git a/kbx/keybox-errors.c b/kbx/keybox-errors.c
index ce2b498d0..cb5a092d9 100644
--- a/kbx/keybox-errors.c
+++ b/kbx/keybox-errors.c
@@ -8,7 +8,7 @@
* keybox_strerror:
* @err: Error code
*
- * This function returns a textual representaion of the given
+ * This function returns a textual representation of the given
* errorcode. If this is an unknown value, a string with the value
* is returned (Beware: it is hold in a static buffer).
*
diff --git a/kbx/keybox-search-desc.h b/kbx/keybox-search-desc.h
index 6298994e9..c75bfa4c7 100644
--- a/kbx/keybox-search-desc.h
+++ b/kbx/keybox-search-desc.h
@@ -69,7 +69,7 @@ struct keydb_search_desc
int snlen; /* -1 := sn is a hex string */
union {
const char *name;
- unsigned char fpr[24];
+ unsigned char fpr[32];
u32 kid[2]; /* Note that this is in native endianness. */
unsigned char grip[20];
} u;
diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c
index e309cce98..0a050ff9b 100644
--- a/kbx/keybox-search.c
+++ b/kbx/keybox-search.c
@@ -1069,7 +1069,7 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
/* Return the last found keyblock. Returns 0 on success and stores a
- * new iobuf at R_IOBUF. R_UID_NO and R_PK_NO are used to retun the
+ * new iobuf at R_IOBUF. R_UID_NO and R_PK_NO are used to return the
* number of the key or user id which was matched the search criteria;
* if not known they are set to 0. */
gpg_error_t
diff --git a/kbx/mkerrors b/kbx/mkerrors
index 629485ae0..c0bca108c 100755
--- a/kbx/mkerrors
+++ b/kbx/mkerrors
@@ -29,7 +29,7 @@ cat <<EOF
* keybox_strerror:
* @err: Error code
*
- * This function returns a textual representaion of the given
+ * This function returns a textual representation of the given
* errorcode. If this is an unknown value, a string with the value
* is returned (Beware: it is hold in a static buffer).
*
diff --git a/m4/Makefile.am b/m4/Makefile.am
index 3232413a5..250a4ac2c 100644
--- a/m4/Makefile.am
+++ b/m4/Makefile.am
@@ -1,6 +1,6 @@
EXTRA_DIST = intl.m4 intldir.m4 glibc2.m4 lock.m4 visibility.m4 intmax.m4 longdouble.m4 printf-posix.m4 signed.m4 size_max.m4 wchar_t.m4 wint_t.m4 xsize.m4 codeset.m4 gettext.m4 glibc21.m4 iconv.m4 intdiv0.m4 inttypes.m4 inttypes_h.m4 inttypes-pri.m4 isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 progtest.m4 stdint_h.m4 uintmax_t.m4
-EXTRA_DIST += ldap.m4 libcurl.m4 libusb.m4 tar-ustar.m4 readline.m4 pkg.m4
+EXTRA_DIST += ldap.m4 libcurl.m4 libusb.m4 readline.m4 pkg.m4
EXTRA_DIST += gnupg-pth.m4
diff --git a/m4/gpg-error.m4 b/m4/gpg-error.m4
index 1661204c2..a9d572fb5 100644
--- a/m4/gpg-error.m4
+++ b/m4/gpg-error.m4
@@ -1,5 +1,5 @@
# gpg-error.m4 - autoconf macro to detect libgpg-error.
-# Copyright (C) 2002, 2003, 2004, 2011, 2014 g10 Code GmbH
+# Copyright (C) 2002, 2003, 2004, 2011, 2014, 2018 g10 Code GmbH
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
@@ -9,7 +9,7 @@
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
-# Last-changed: 2014-10-02
+# Last-changed: 2018-11-02
dnl AM_PATH_GPG_ERROR([MINIMUM-VERSION,
@@ -61,16 +61,55 @@ AC_DEFUN([AM_PATH_GPG_ERROR],
fi
AC_PATH_PROG(GPG_ERROR_CONFIG, gpg-error-config, no)
- min_gpg_error_version=ifelse([$1], ,0.0,$1)
- AC_MSG_CHECKING(for GPG Error - version >= $min_gpg_error_version)
+ min_gpg_error_version=ifelse([$1], ,1.33,$1)
ok=no
- if test "$GPG_ERROR_CONFIG" != "no" \
- && test -f "$GPG_ERROR_CONFIG" ; then
+
+ if test "$prefix" = NONE ; then
+ prefix_option_expanded=/usr/local
+ else
+ prefix_option_expanded="$prefix"
+ fi
+ if test "$exec_prefix" = NONE ; then
+ exec_prefix_option_expanded=$prefix_option_expanded
+ else
+ exec_prefix_option_expanded=$(prefix=$prefix_option_expanded eval echo $exec_prefix)
+ fi
+ libdir_option_expanded=$(prefix=$prefix_option_expanded exec_prefix=$exec_prefix_option_expanded eval echo $libdir)
+
+ if test -f $libdir_option_expanded/pkgconfig/gpg-error.pc; then
+ gpgrt_libdir=$libdir_option_expanded
+ else
+ if crt1_path=$(${CC:-cc} -print-file-name=crt1.o 2>/dev/null); then
+ if possible_libdir=$(cd ${crt1_path%/*} && pwd 2>/dev/null); then
+ if test -f $possible_libdir/pkgconfig/gpg-error.pc; then
+ gpgrt_libdir=$possible_libdir
+ fi
+ fi
+ fi
+ fi
+
+ if test "$GPG_ERROR_CONFIG" = "no" -a -n "$gpgrt_libdir"; then
+ AC_PATH_PROG(GPGRT_CONFIG, gpgrt-config, no)
+ if test "$GPGRT_CONFIG" = "no"; then
+ unset GPGRT_CONFIG
+ else
+ GPGRT_CONFIG="$GPGRT_CONFIG --libdir=$gpgrt_libdir"
+ if $GPGRT_CONFIG gpg-error >/dev/null 2>&1; then
+ GPG_ERROR_CONFIG="$GPGRT_CONFIG gpg-error"
+ AC_MSG_NOTICE([Use gpgrt-config with $gpgrt_libdir as gpg-error-config])
+ gpg_error_config_version=`$GPG_ERROR_CONFIG --modversion`
+ else
+ unset GPGRT_CONFIG
+ fi
+ fi
+ else
+ gpg_error_config_version=`$GPG_ERROR_CONFIG --version`
+ fi
+ if test "$GPG_ERROR_CONFIG" != "no"; then
req_major=`echo $min_gpg_error_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
req_minor=`echo $min_gpg_error_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
- gpg_error_config_version=`$GPG_ERROR_CONFIG $gpg_error_config_args --version`
major=`echo $gpg_error_config_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
minor=`echo $gpg_error_config_version | \
@@ -84,23 +123,51 @@ AC_DEFUN([AM_PATH_GPG_ERROR],
fi
fi
fi
+ if test -z "$GPGRT_CONFIG" -a -n "$gpgrt_libdir"; then
+ if test "$major" -gt 1 -o "$major" -eq 1 -a "$minor" -ge 33; then
+ AC_PATH_PROG(GPGRT_CONFIG, gpgrt-config, no)
+ if test "$GPGRT_CONFIG" = "no"; then
+ unset GPGRT_CONFIG
+ else
+ GPGRT_CONFIG="$GPGRT_CONFIG --libdir=$gpgrt_libdir"
+ if $GPGRT_CONFIG gpg-error >/dev/null 2>&1; then
+ GPG_ERROR_CONFIG="$GPGRT_CONFIG gpg-error"
+ AC_MSG_NOTICE([Use gpgrt-config with $gpgrt_libdir as gpg-error-config])
+ else
+ unset GPGRT_CONFIG
+ fi
+ fi
+ fi
+ fi
fi
+ AC_MSG_CHECKING(for GPG Error - version >= $min_gpg_error_version)
if test $ok = yes; then
- GPG_ERROR_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --cflags`
- GPG_ERROR_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --libs`
- GPG_ERROR_MT_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --mt --cflags 2>/dev/null`
- GPG_ERROR_MT_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --mt --libs 2>/dev/null`
+ GPG_ERROR_CFLAGS=`$GPG_ERROR_CONFIG --cflags`
+ GPG_ERROR_LIBS=`$GPG_ERROR_CONFIG --libs`
+ if test -z "$GPGRT_CONFIG"; then
+ GPG_ERROR_MT_CFLAGS=`$GPG_ERROR_CONFIG --mt --cflags 2>/dev/null`
+ GPG_ERROR_MT_LIBS=`$GPG_ERROR_CONFIG --mt --libs 2>/dev/null`
+ else
+ GPG_ERROR_MT_CFLAGS=`$GPG_ERROR_CONFIG --variable=mtcflags 2>/dev/null`
+ GPG_ERROR_MT_CFLAGS="$GPG_ERROR_CFLAGS${GPG_ERROR_CFLAGS:+ }$GPG_ERROR_MT_CFLAGS"
+ GPG_ERROR_MT_LIBS=`$GPG_ERROR_CONFIG --variable=mtlibs 2>/dev/null`
+ GPG_ERROR_MT_LIBS="$GPG_ERROR_LIBS${GPG_ERROR_LIBS:+ }$GPG_ERROR_MT_LIBS"
+ fi
AC_MSG_RESULT([yes ($gpg_error_config_version)])
ifelse([$2], , :, [$2])
- gpg_error_config_host=`$GPG_ERROR_CONFIG $gpg_error_config_args --host 2>/dev/null || echo none`
+ if test -z "$GPGRT_CONFIG"; then
+ gpg_error_config_host=`$GPG_ERROR_CONFIG --host 2>/dev/null || echo none`
+ else
+ gpg_error_config_host=`$GPG_ERROR_CONFIG --variable=host 2>/dev/null || echo none`
+ fi
if test x"$gpg_error_config_host" != xnone ; then
if test x"$gpg_error_config_host" != x"$host" ; then
AC_MSG_WARN([[
***
-*** The config script $GPG_ERROR_CONFIG was
+*** The config script "$GPG_ERROR_CONFIG" was
*** built for $gpg_error_config_host and thus may not match the
*** used host $host.
-*** You may want to use the configure option --with-gpg-error-prefix
+*** You may want to use the configure option --with-libgpg-error-prefix
*** to specify a matching config script or use \$SYSROOT.
***]])
gpg_config_script_warn="$gpg_config_script_warn libgpg-error"
diff --git a/m4/ksba.m4 b/m4/ksba.m4
index 3e14e6744..ad8de4f32 100644
--- a/m4/ksba.m4
+++ b/m4/ksba.m4
@@ -1,5 +1,5 @@
# ksba.m4 - autoconf macro to detect ksba
-# Copyright (C) 2002 g10 Code GmbH
+# Copyright (C) 2002, 2018 g10 Code GmbH
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
@@ -13,27 +13,47 @@
dnl AM_PATH_KSBA([MINIMUM-VERSION,
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
dnl Test for libksba and define KSBA_CFLAGS and KSBA_LIBS
-dnl MINIMUM-VERSION is a string with the version number optionalliy prefixed
+dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed
dnl with the API version to also check the API compatibility. Example:
-dnl a MINIMUM-VERSION of 1:1.0.7 won't pass the test unless the installed
+dnl a MINIMUN-VERSION of 1:1.0.7 won't pass the test unless the installed
dnl version of libksba is at least 1.0.7 *and* the API number is 1. Using
-dnl this feature prevents building against newer versions of libksba
+dnl this features allows to prevent build against newer versions of libksba
dnl with a changed API.
dnl
AC_DEFUN([AM_PATH_KSBA],
-[AC_REQUIRE([AC_CANONICAL_HOST])
- AC_ARG_WITH(ksba-prefix,
- AC_HELP_STRING([--with-ksba-prefix=PFX],
- [prefix where KSBA is installed (optional)]),
+[ AC_REQUIRE([AC_CANONICAL_HOST])
+ dnl --with-libksba-prefix=PFX is the preferred name for this option,
+ dnl since that is consistent with how our three siblings use the directory/
+ dnl package name in --with-$dir_name-prefix=PFX.
+ AC_ARG_WITH(libksba-prefix,
+ AC_HELP_STRING([--with-libksba-prefix=PFX],
+ [prefix where KSBA is installed (optional)]),
ksba_config_prefix="$withval", ksba_config_prefix="")
+
+ dnl Accept --with-ksba-prefix and make it work the same as
+ dnl --with-libksba-prefix above, for backwards compatibility,
+ dnl but do not document this old, inconsistently-named option.
+ AC_ARG_WITH(ksba-prefix,,
+ ksba_config_prefix="$withval", ksba_config_prefix="")
+
if test x$ksba_config_prefix != x ; then
- ksba_config_args="$ksba_config_args --prefix=$ksba_config_prefix"
- if test x${KSBA_CONFIG+set} != xset ; then
- KSBA_CONFIG=$ksba_config_prefix/bin/ksba-config
- fi
+ if test x${KSBA_CONFIG+set} != xset ; then
+ KSBA_CONFIG=$ksba_config_prefix/bin/ksba-config
+ fi
+ fi
+
+ use_gpgrt_config=""
+ if test x"$KSBA_CONFIG" = x -a x"$GPGRT_CONFIG" != x -a "$GPGRT_CONFIG" != "no"; then
+ if $GPGRT_CONFIG ksba --exists; then
+ KSBA_CONFIG="$GPGRT_CONFIG ksba"
+ AC_MSG_NOTICE([Use gpgrt-config as ksba-config])
+ use_gpgrt_config=yes
+ fi
+ fi
+ if test -z "$use_gpgrt_config"; then
+ AC_PATH_PROG(KSBA_CONFIG, ksba-config, no)
fi
- AC_PATH_PROG(KSBA_CONFIG, ksba-config, no)
tmp=ifelse([$1], ,1:1.0.0,$1)
if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
req_ksba_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'`
@@ -52,7 +72,11 @@ AC_DEFUN([AM_PATH_KSBA],
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
req_micro=`echo $min_ksba_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
- ksba_config_version=`$KSBA_CONFIG $ksba_config_args --version`
+ if test -z "$use_gpgrt_config"; then
+ ksba_config_version=`$KSBA_CONFIG --version`
+ else
+ ksba_config_version=`$KSBA_CONFIG --modversion`
+ fi
major=`echo $ksba_config_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
minor=`echo $ksba_config_version | \
@@ -84,7 +108,11 @@ AC_DEFUN([AM_PATH_KSBA],
# Even if we have a recent libksba, we should check that the
# API is compatible.
if test "$req_ksba_api" -gt 0 ; then
- tmp=`$KSBA_CONFIG --api-version 2>/dev/null || echo 0`
+ if test -z "$use_gpgrt_config"; then
+ tmp=`$KSBA_CONFIG --api-version 2>/dev/null || echo 0`
+ else
+ tmp=`$KSBA_CONFIG --variable=api_version 2>/dev/null || echo 0`
+ fi
if test "$tmp" -gt 0 ; then
AC_MSG_CHECKING([KSBA API version])
if test "$req_ksba_api" -eq "$tmp" ; then
@@ -97,15 +125,19 @@ AC_DEFUN([AM_PATH_KSBA],
fi
fi
if test $ok = yes; then
- KSBA_CFLAGS=`$KSBA_CONFIG $ksba_config_args --cflags`
- KSBA_LIBS=`$KSBA_CONFIG $ksba_config_args --libs`
+ KSBA_CFLAGS=`$KSBA_CONFIG --cflags`
+ KSBA_LIBS=`$KSBA_CONFIG --libs`
ifelse([$2], , :, [$2])
- libksba_config_host=`$LIBKSBA_CONFIG $ksba_config_args --host 2>/dev/null || echo none`
+ if test -z "$use_gpgrt_config"; then
+ libksba_config_host=`$KSBA_CONFIG --host 2>/dev/null || echo none`
+ else
+ libksba_config_host=`$KSBA_CONFIG --variable=host 2>/dev/null || echo none`
+ fi
if test x"$libksba_config_host" != xnone ; then
if test x"$libksba_config_host" != x"$host" ; then
AC_MSG_WARN([[
***
-*** The config script $LIBKSBA_CONFIG was
+*** The config script "$KSBA_CONFIG" was
*** built for $libksba_config_host and thus may not match the
*** used host $host.
*** You may want to use the configure option --with-libksba-prefix
diff --git a/m4/libassuan.m4 b/m4/libassuan.m4
index 004eee392..4af2d04f5 100644
--- a/m4/libassuan.m4
+++ b/m4/libassuan.m4
@@ -1,5 +1,5 @@
dnl Autoconf macros for libassuan
-dnl Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+dnl Copyright (C) 2002, 2003, 2011 Free Software Foundation, Inc.
dnl
dnl This file is free software; as a special exception the author gives
dnl unlimited permission to copy and/or distribute it, with or without
@@ -8,23 +8,35 @@ dnl
dnl This file is distributed in the hope that it will be useful, but
dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+dnl SPDX-License-Identifier: FSFULLR
dnl
dnl Common code used for libassuan detection [internal]
dnl Returns ok set to yes or no.
dnl
AC_DEFUN([_AM_PATH_LIBASSUAN_COMMON],
-[ AC_ARG_WITH(libassuan-prefix,
+[ AC_REQUIRE([AC_CANONICAL_HOST])
+ AC_ARG_WITH(libassuan-prefix,
AC_HELP_STRING([--with-libassuan-prefix=PFX],
[prefix where LIBASSUAN is installed (optional)]),
libassuan_config_prefix="$withval", libassuan_config_prefix="")
if test x$libassuan_config_prefix != x ; then
- libassuan_config_args="$libassuan_config_args --prefix=$libassuan_config_prefix"
if test x${LIBASSUAN_CONFIG+set} != xset ; then
LIBASSUAN_CONFIG=$libassuan_config_prefix/bin/libassuan-config
fi
fi
- AC_PATH_PROG(LIBASSUAN_CONFIG, libassuan-config, no)
+
+ use_gpgrt_config=""
+ if test x"${LIBASSUAN_CONFIG}" = x -a x"$GPGRT_CONFIG" != x -a "$GPGRT_CONFIG" != "no"; then
+ if $GPGRT_CONFIG libassuan --exists; then
+ LIBASSUAN_CONFIG="$GPGRT_CONFIG libassuan"
+ AC_MSG_NOTICE([Use gpgrt-config as libassuan-config])
+ use_gpgrt_config=yes
+ fi
+ fi
+ if test -z "$use_gpgrt_config"; then
+ AC_PATH_PROG(LIBASSUAN_CONFIG, libassuan-config, no)
+ fi
tmp=ifelse([$1], ,1:0.9.2,$1)
if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
@@ -35,55 +47,60 @@ AC_DEFUN([_AM_PATH_LIBASSUAN_COMMON],
min_libassuan_version="$tmp"
fi
- if test "$LIBASSUAN_CONFIG" != "no" ; then
- libassuan_version=`$LIBASSUAN_CONFIG --version`
- fi
- libassuan_version_major=`echo $libassuan_version | \
- sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
- libassuan_version_minor=`echo $libassuan_version | \
- sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
- libassuan_version_micro=`echo $libassuan_version | \
- sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'`
-
- AC_MSG_CHECKING(for LIBASSUAN ifelse([$2], ,,[$2 ])- version >= $min_libassuan_version)
+ AC_MSG_CHECKING(for LIBASSUAN - version >= $min_libassuan_version)
ok=no
- if test "$LIBASSUAN_CONFIG" != "no" ; then
- ifelse([$2], ,,[if `$LIBASSUAN_CONFIG --thread=$2 2> /dev/null` ; then])
+ if test "$LIBASSUAN_CONFIG" != "no"; then
req_major=`echo $min_libassuan_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
req_minor=`echo $min_libassuan_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
req_micro=`echo $min_libassuan_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
- if test "$libassuan_version_major" -gt "$req_major"; then
+
+ if test -z "$use_gpgrt_config"; then
+ libassuan_config_version=`$LIBASSUAN_CONFIG --version`
+ else
+ libassuan_config_version=`$LIBASSUAN_CONFIG --modversion`
+ fi
+ major=`echo $libassuan_config_version | \
+ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
+ minor=`echo $libassuan_config_version | \
+ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
+ micro=`echo $libassuan_config_version | \
+ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'`
+
+ if test "$major" -gt "$req_major"; then
ok=yes
- else
- if test "$libassuan_version_major" -eq "$req_major"; then
- if test "$libassuan_version_minor" -gt "$req_minor"; then
+ else
+ if test "$major" -eq "$req_major"; then
+ if test "$minor" -gt "$req_minor"; then
ok=yes
else
- if test "$libassuan_version_minor" -eq "$req_minor"; then
- if test "$libassuan_version_micro" -ge "$req_micro"; then
+ if test "$minor" -eq "$req_minor"; then
+ if test "$micro" -ge "$req_micro"; then
ok=yes
fi
fi
fi
fi
fi
- ifelse([$2], ,,[fi])
fi
if test $ok = yes; then
- AC_MSG_RESULT([yes ($libassuan_version)])
+ AC_MSG_RESULT([yes ($libassuan_config_version)])
else
AC_MSG_RESULT(no)
fi
if test $ok = yes; then
if test "$req_libassuan_api" -gt 0 ; then
- tmp=`$LIBASSUAN_CONFIG --api-version 2>/dev/null || echo 0`
+ if test -z "$use_gpgrt_config"; then
+ tmp=`$LIBASSUAN_CONFIG --api-version 2>/dev/null || echo 0`
+ else
+ tmp=`$LIBASSUAN_CONFIG --variable=api_version 2>/dev/null || echo 0`
+ fi
if test "$tmp" -gt 0 ; then
- AC_MSG_CHECKING([LIBASSUAN ifelse([$2], ,,[$2 ])API version])
+ AC_MSG_CHECKING([LIBASSUAN API version])
if test "$req_libassuan_api" -eq "$tmp" ; then
AC_MSG_RESULT(okay)
else
@@ -94,6 +111,27 @@ AC_DEFUN([_AM_PATH_LIBASSUAN_COMMON],
fi
fi
+ if test $ok = yes; then
+ if test x"$host" != x ; then
+ if test -z "$use_gpgrt_config"; then
+ libassuan_config_host=`$LIBASSUAN_CONFIG --host 2>/dev/null || echo none`
+ else
+ libassuan_config_host=`$LIBASSUAN_CONFIG --variable=host 2>/dev/null || echo none`
+ fi
+ if test x"$libassuan_config_host" != xnone ; then
+ if test x"$libassuan_config_host" != x"$host" ; then
+ AC_MSG_WARN([[
+***
+*** The config script "$LIBASSUAN_CONFIG" was
+*** built for $libassuan_config_host and thus may not match the
+*** used host $host.
+*** You may want to use the configure option --with-libassuan-prefix
+*** to specify a matching config script.
+***]])
+ fi
+ fi
+ fi
+ fi
])
dnl AM_CHECK_LIBASSUAN([MINIMUM-VERSION,
@@ -120,8 +158,8 @@ dnl
AC_DEFUN([AM_PATH_LIBASSUAN],
[ _AM_PATH_LIBASSUAN_COMMON($1)
if test $ok = yes; then
- LIBASSUAN_CFLAGS=`$LIBASSUAN_CONFIG $libassuan_config_args --cflags`
- LIBASSUAN_LIBS=`$LIBASSUAN_CONFIG $libassuan_config_args --libs`
+ LIBASSUAN_CFLAGS=`$LIBASSUAN_CONFIG --cflags`
+ LIBASSUAN_LIBS=`$LIBASSUAN_CONFIG --libs`
ifelse([$2], , :, [$2])
else
LIBASSUAN_CFLAGS=""
@@ -131,45 +169,3 @@ AC_DEFUN([AM_PATH_LIBASSUAN],
AC_SUBST(LIBASSUAN_CFLAGS)
AC_SUBST(LIBASSUAN_LIBS)
])
-
-
-dnl AM_PATH_LIBASSUAN_PTH([MINIMUM-VERSION,
-dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
-dnl Test for libassuan and define LIBASSUAN_PTH_CFLAGS and LIBASSUAN_PTH_LIBS
-dnl
-AC_DEFUN([AM_PATH_LIBASSUAN_PTH],
-[ _AM_PATH_LIBASSUAN_COMMON($1,pth)
- if test $ok = yes; then
- LIBASSUAN_PTH_CFLAGS=`$LIBASSUAN_CONFIG $libassuan_config_args --thread=pth --cflags`
- LIBASSUAN_PTH_LIBS=`$LIBASSUAN_CONFIG $libassuan_config_args --thread=pth --libs`
- ifelse([$2], , :, [$2])
- else
- LIBASSUAN_PTH_CFLAGS=""
- LIBASSUAN_PTH_LIBS=""
- ifelse([$3], , :, [$3])
- fi
- AC_SUBST(LIBASSUAN_PTH_CFLAGS)
- AC_SUBST(LIBASSUAN_PTH_LIBS)
-])
-
-
-dnl AM_PATH_LIBASSUAN_PTHREAD([MINIMUM-VERSION,
-dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
-dnl Test for libassuan and define LIBASSUAN_PTHREAD_CFLAGS
-dnl and LIBASSUAN_PTHREAD_LIBS
-dnl
-AC_DEFUN([AM_PATH_LIBASSUAN_PTHREAD],
-[ _AM_PATH_LIBASSUAN_COMMON($1,pthread)
- if test $ok = yes; then
- LIBASSUAN_PTHREAD_CFLAGS=`$LIBASSUAN_CONFIG $libassuan_config_args --thread=pthread --cflags`
- LIBASSUAN_PTHREAD_LIBS=`$LIBASSUAN_CONFIG $libassuan_config_args --thread=pthread --libs`
- ifelse([$2], , :, [$2])
- else
- LIBASSUAN_PTHREAD_CFLAGS=""
- LIBASSUAN_PTHREAD_LIBS=""
- ifelse([$3], , :, [$3])
- fi
- AC_SUBST(LIBASSUAN_PTHREAD_CFLAGS)
- AC_SUBST(LIBASSUAN_PTHREAD_LIBS)
-])
-
diff --git a/m4/libgcrypt.m4 b/m4/libgcrypt.m4
index d89fe1137..37dfbea24 100644
--- a/m4/libgcrypt.m4
+++ b/m4/libgcrypt.m4
@@ -1,5 +1,5 @@
# libgcrypt.m4 - Autoconf macros to detect libgcrypt
-# Copyright (C) 2002, 2003, 2004, 2011, 2014 g10 Code GmbH
+# Copyright (C) 2002, 2003, 2004, 2011, 2014, 2018 g10 Code GmbH
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
@@ -9,17 +9,17 @@
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
-# Last-changed: 2014-10-02
+# Last-changed: 2018-11-13
dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION,
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS.
-dnl MINIMUM-VERSION is a string with the version number optionalliy prefixed
+dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed
dnl with the API version to also check the API compatibility. Example:
-dnl a MINIMUM-VERSION of 1:1.2.5 won't pass the test unless the installed
+dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed
dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using
-dnl this feature prevents building against newer versions of libgcrypt
+dnl this features allows to prevent build against newer versions of libgcrypt
dnl with a changed API.
dnl
dnl If a prefix option is not used, the config script is first
@@ -36,8 +36,20 @@ AC_DEFUN([AM_PATH_LIBGCRYPT],
if test x"${LIBGCRYPT_CONFIG}" = x ; then
if test x"${libgcrypt_config_prefix}" != x ; then
LIBGCRYPT_CONFIG="${libgcrypt_config_prefix}/bin/libgcrypt-config"
- else
- case "${SYSROOT}" in
+ fi
+ fi
+
+ use_gpgrt_config=""
+ if test x"${LIBGCRYPT_CONFIG}" = x -a x"$GPGRT_CONFIG" != x -a "$GPGRT_CONFIG" != "no"; then
+ if $GPGRT_CONFIG libgcrypt --exists; then
+ LIBGCRYPT_CONFIG="$GPGRT_CONFIG libgcrypt"
+ AC_MSG_NOTICE([Use gpgrt-config as libgcrypt-config])
+ use_gpgrt_config=yes
+ fi
+ fi
+ if test -z "$use_gpgrt_config"; then
+ if test x"${LIBGCRYPT_CONFIG}" = x ; then
+ case "${SYSROOT}" in
/*)
if test -x "${SYSROOT}/bin/libgcrypt-config" ; then
LIBGCRYPT_CONFIG="${SYSROOT}/bin/libgcrypt-config"
@@ -48,11 +60,11 @@ AC_DEFUN([AM_PATH_LIBGCRYPT],
*)
AC_MSG_WARN([Ignoring \$SYSROOT as it is not an absolute path.])
;;
- esac
- fi
+ esac
+ fi
+ AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no)
fi
- AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no)
tmp=ifelse([$1], ,1:1.2.0,$1)
if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'`
@@ -71,7 +83,11 @@ AC_DEFUN([AM_PATH_LIBGCRYPT],
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
req_micro=`echo $min_libgcrypt_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
- libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version`
+ if test -z "$use_gpgrt_config"; then
+ libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version`
+ else
+ libgcrypt_config_version=`$LIBGCRYPT_CONFIG --modversion`
+ fi
major=`echo $libgcrypt_config_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
minor=`echo $libgcrypt_config_version | \
@@ -103,7 +119,11 @@ AC_DEFUN([AM_PATH_LIBGCRYPT],
# If we have a recent libgcrypt, we should also check that the
# API is compatible
if test "$req_libgcrypt_api" -gt 0 ; then
- tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0`
+ if test -z "$use_gpgrt_config"; then
+ tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0`
+ else
+ tmp=`$LIBGCRYPT_CONFIG --variable=api_version 2>/dev/null || echo 0`
+ fi
if test "$tmp" -gt 0 ; then
AC_MSG_CHECKING([LIBGCRYPT API version])
if test "$req_libgcrypt_api" -eq "$tmp" ; then
@@ -119,12 +139,16 @@ AC_DEFUN([AM_PATH_LIBGCRYPT],
LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags`
LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs`
ifelse([$2], , :, [$2])
- libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none`
+ if test -z "$use_gpgrt_config"; then
+ libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none`
+ else
+ libgcrypt_config_host=`$LIBGCRYPT_CONFIG --variable=host 2>/dev/null || echo none`
+ fi
if test x"$libgcrypt_config_host" != xnone ; then
if test x"$libgcrypt_config_host" != x"$host" ; then
AC_MSG_WARN([[
***
-*** The config script $LIBGCRYPT_CONFIG was
+*** The config script "$LIBGCRYPT_CONFIG" was
*** built for $libgcrypt_config_host and thus may not match the
*** used host $host.
*** You may want to use the configure option --with-libgcrypt-prefix
diff --git a/m4/npth.m4 b/m4/npth.m4
index 17c264491..7d3e73f00 100644
--- a/m4/npth.m4
+++ b/m4/npth.m4
@@ -1,5 +1,5 @@
# npth.m4 - autoconf macro to detect NPTH.
-# Copyright (C) 2002, 2003, 2004, 2011 g10 Code GmbH
+# Copyright (C) 2002, 2003, 2004, 2011, 2018 g10 Code GmbH
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
@@ -17,10 +17,25 @@ AC_DEFUN([_AM_PATH_NPTH_CONFIG],
if test "x$npth_config_prefix" != x ; then
NPTH_CONFIG="$npth_config_prefix/bin/npth-config"
fi
- AC_PATH_PROG(NPTH_CONFIG, npth-config, no)
+
+ use_gpgrt_config=""
+ if test x"$NPTH_CONFIG" = x -a x"$GPGRT_CONFIG" != x -a "$GPGRT_CONFIG" != "no"; then
+ if $GPGRT_CONFIG npth --exists; then
+ NPTH_CONFIG="$GPGRT_CONFIG npth"
+ AC_MSG_NOTICE([Use gpgrt-config as npth-config])
+ use_gpgrt_config=yes
+ fi
+ fi
+ if test -z "$use_gpgrt_config"; then
+ AC_PATH_PROG(NPTH_CONFIG, npth-config, no)
+ fi
if test "$NPTH_CONFIG" != "no" ; then
- npth_version=`$NPTH_CONFIG --version`
+ if test -z "$use_gpgrt_config"; then
+ npth_version=`$NPTH_CONFIG --version`
+ else
+ npth_version=`$NPTH_CONFIG --modversion`
+ fi
fi
npth_version_major=`echo $npth_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
@@ -70,31 +85,39 @@ AC_DEFUN([AM_PATH_NPTH],
AC_MSG_RESULT(no)
fi
if test $ok = yes; then
- # If we have a recent NPTH, we should also check that the
- # API is compatible.
- if test "$req_npth_api" -gt 0 ; then
+ # If we have a recent NPTH, we should also check that the
+ # API is compatible.
+ if test "$req_npth_api" -gt 0 ; then
+ if test -z "$use_gpgrt_config"; then
tmp=`$NPTH_CONFIG --api-version 2>/dev/null || echo 0`
- if test "$tmp" -gt 0 ; then
- AC_MSG_CHECKING([NPTH API version])
- if test "$req_npth_api" -eq "$tmp" ; then
- AC_MSG_RESULT([okay])
- else
- ok=no
- AC_MSG_RESULT([does not match. want=$req_npth_api got=$tmp])
- fi
+ else
+ tmp=`$NPTH_CONFIG --variable=api_version 2>/dev/null || echo 0`
+ fi
+ if test "$tmp" -gt 0 ; then
+ AC_MSG_CHECKING([NPTH API version])
+ if test "$req_npth_api" -eq "$tmp" ; then
+ AC_MSG_RESULT([okay])
+ else
+ ok=no
+ AC_MSG_RESULT([does not match. want=$req_npth_api got=$tmp])
fi
- fi
+ fi
+ fi
fi
if test $ok = yes; then
NPTH_CFLAGS=`$NPTH_CONFIG --cflags`
NPTH_LIBS=`$NPTH_CONFIG --libs`
ifelse([$2], , :, [$2])
- npth_config_host=`$NPTH_CONFIG --host 2>/dev/null || echo none`
+ if test -z "$use_gpgrt_config"; then
+ npth_config_host=`$NPTH_CONFIG --host 2>/dev/null || echo none`
+ else
+ npth_config_host=`$NPTH_CONFIG --variable=host 2>/dev/null || echo none`
+ fi
if test x"$npth_config_host" != xnone ; then
if test x"$npth_config_host" != x"$host" ; then
AC_MSG_WARN([[
***
-*** The config script $NPTH_CONFIG was
+*** The config script "$NPTH_CONFIG" was
*** built for $npth_config_host and thus may not match the
*** used host $host.
*** You may want to use the configure option --with-npth-prefix
diff --git a/m4/ntbtls.m4 b/m4/ntbtls.m4
index 0a30d9200..18b43d939 100644
--- a/m4/ntbtls.m4
+++ b/m4/ntbtls.m4
@@ -8,17 +8,19 @@ dnl
dnl This file is distributed in the hope that it will be useful, but
dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+dnl
+dnl Last-changed: 2018-11-13
dnl AM_PATH_NTBTLS([MINIMUM-VERSION,
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
dnl
dnl Test for NTBTLS and define NTBTLS_CFLAGS and NTBTLS_LIBS.
-dnl MINIMUM-VERSION is a string with the version number optionalliy prefixed
+dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed
dnl with the API version to also check the API compatibility. Example:
-dnl a MINIMUM-VERSION of 1:1.2.5 won't pass the test unless the installed
-dnl version of ntbtls is at least 1.2.5 *and* the API number is 1. Using
-dnl this feature prevents building against newer versions of ntbtls
+dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed
+dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using
+dnl this features allows to prevent build against newer versions of libgcrypt
dnl with a changed API.
dnl
AC_DEFUN([AM_PATH_NTBTLS],
@@ -30,23 +32,35 @@ AC_DEFUN([AM_PATH_NTBTLS],
if test x"${NTBTLS_CONFIG}" = x ; then
if test x"${ntbtls_config_prefix}" != x ; then
NTBTLS_CONFIG="${ntbtls_config_prefix}/bin/ntbtls-config"
- else
- case "${SYSROOT}" in
- /*)
- if test -x "${SYSROOT}/bin/ntbtls-config" ; then
- NTBTLS_CONFIG="${SYSROOT}/bin/ntbtls-config"
- fi
- ;;
- '')
- ;;
- *)
- AC_MSG_WARN([Ignoring \$SYSROOT as it is not an absolute path.])
- ;;
- esac
fi
fi
- AC_PATH_PROG(NTBTLS_CONFIG, ntbtls-config, no)
+ use_gpgrt_config=""
+ if test x"${NTBTLS_CONFIG}" = x -a x"$GPGRT_CONFIG" != x -a "$GPGRT_CONFIG" != "no"; then
+ if $GPGRT_CONFIG ntbtls --exists; then
+ NTBTLS_CONFIG="$GPGRT_CONFIG ntbtls"
+ AC_MSG_NOTICE([Use gpgrt-config as ntbtls-config])
+ use_gpgrt_config=yes
+ fi
+ fi
+ if test -z "$use_gpgrt_config"; then
+ if test x"${NTBTLS_CONFIG}" = x ; then
+ case "${SYSROOT}" in
+ /*)
+ if test -x "${SYSROOT}/bin/ntbtls-config" ; then
+ NTBTLS_CONFIG="${SYSROOT}/bin/ntbtls-config"
+ fi
+ ;;
+ '')
+ ;;
+ *)
+ AC_MSG_WARN([Ignoring \$SYSROOT as it is not an absolute path.])
+ ;;
+ esac
+ fi
+ AC_PATH_PROG(NTBTLS_CONFIG, ntbtls-config, no)
+ fi
+
tmp=ifelse([$1], ,1:1.0.0,$1)
if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
req_ntbtls_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'`
@@ -65,7 +79,11 @@ AC_DEFUN([AM_PATH_NTBTLS],
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
req_micro=`echo $min_ntbtls_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
- ntbtls_config_version=`$NTBTLS_CONFIG --version`
+ if test -z "$use_gpgrt_config"; then
+ ntbtls_config_version=`$NTBTLS_CONFIG --version`
+ else
+ ntbtls_config_version=`$NTBTLS_CONFIG --modversion`
+ fi
major=`echo $ntbtls_config_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
minor=`echo $ntbtls_config_version | \
@@ -97,7 +115,11 @@ AC_DEFUN([AM_PATH_NTBTLS],
# If we have a recent ntbtls, we should also check that the
# API is compatible
if test "$req_ntbtls_api" -gt 0 ; then
- tmp=`$NTBTLS_CONFIG --api-version 2>/dev/null || echo 0`
+ if test -z "$use_gpgrt_config"; then
+ tmp=`$NTBTLS_CONFIG --api-version 2>/dev/null || echo 0`
+ else
+ tmp=`$NTBTLS_CONFIG --variable=api_version 2>/dev/null || echo 0`
+ fi
if test "$tmp" -gt 0 ; then
AC_MSG_CHECKING([NTBTLS API version])
if test "$req_ntbtls_api" -eq "$tmp" ; then
@@ -113,12 +135,16 @@ AC_DEFUN([AM_PATH_NTBTLS],
NTBTLS_CFLAGS=`$NTBTLS_CONFIG --cflags`
NTBTLS_LIBS=`$NTBTLS_CONFIG --libs`
ifelse([$2], , :, [$2])
- ntbtls_config_host=`$NTBTLS_CONFIG --host 2>/dev/null || echo none`
+ if test -z "$use_gpgrt_config"; then
+ ntbtls_config_host=`$NTBTLS_CONFIG --host 2>/dev/null || echo none`
+ else
+ ntbtls_config_host=`$NTBTLS_CONFIG --variable=host 2>/dev/null || echo none`
+ fi
if test x"$ntbtls_config_host" != xnone ; then
if test x"$ntbtls_config_host" != x"$host" ; then
AC_MSG_WARN([[
***
-*** The config script $NTBTLS_CONFIG was
+*** The config script "$NTBTLS_CONFIG" was
*** built for $ntbtls_config_host and thus may not match the
*** used host $host.
*** You may want to use the configure option --with-ntbtls-prefix
diff --git a/m4/tar-ustar.m4 b/m4/tar-ustar.m4
deleted file mode 100644
index 4ae9e63aa..000000000
--- a/m4/tar-ustar.m4
+++ /dev/null
@@ -1,43 +0,0 @@
-dnl Check for a tar program that speaks ustar format
-dnl Copyright (C) 2005, 2006 Free Software Foundation, Inc.
-dnl
-dnl This file is free software, distributed under the terms of the GNU
-dnl General Public License. As a special exception to the GNU General
-dnl Public License, this file may be distributed as part of a program
-dnl that contains a configuration script generated by Autoconf, under
-dnl the same distribution terms as the rest of that program.
-
-AC_DEFUN([GNUPG_CHECK_USTAR],
-[
- AC_ARG_WITH(tar,
- AC_HELP_STRING([--with-tar=PATH],[look for a tar program in PATH]),
- [_do_tar=$withval])
-
- if test x$_do_tar != xno ; then
-
- if test x$_do_tar = x ; then
- AC_PATH_PROG(TAR,"tar")
- _mytar=$ac_cv_path_TAR
- fi
-
- # Check if our tar is ustar format. If so, it's good. TODO: Add some
- # code to check various options, etc, to try and create ustar
- # format.
-
- if test x$_mytar != x ; then
- AC_MSG_CHECKING([whether $_mytar speaks USTAR])
- echo hithere > conftest.txt
- $_mytar -cf - conftest.txt | (dd skip=257 bs=1 count=5 2>/dev/null || cat) | grep ustar > /dev/null
- _tar_bad=$?
- rm conftest.txt
-
- if test x$_tar_bad = x0 ; then
- AC_MSG_RESULT([yes])
- else
- AC_MSG_RESULT([no])
- fi
- fi
- fi
-
- AM_CONDITIONAL(HAVE_USTAR, test x$_tar_bad = x0)
-])dnl
diff --git a/po/Makevars b/po/Makevars
index 485c72ca7..90b0c5b83 100644
--- a/po/Makevars
+++ b/po/Makevars
@@ -8,7 +8,63 @@ subdir = po
top_builddir = ..
# These options get passed to xgettext.
-XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ --keyword=L_
+XGETTEXT_OPTIONS = \
+ --keyword=_ --keyword=N_ --keyword=L_ \
+ --flag=gcry_log_debug:1:c-format \
+ --flag=gpgrt_fprintf:2:c-format \
+ --flag=gpgrt_fprintf_unlocked:2:c-format \
+ --flag=gpgrt_printf:1:c-format \
+ --flag=gpgrt_printf_unlocked:1:c-format \
+ --flag=gpgrt_vfprintf:2:c-format \
+ --flag=gpgrt_vfprintf_unlocked:2:c-format \
+ --flag=gpgrt_asprintf:2:c-format \
+ --flag=gpgrt_vasprintf:2:c-format \
+ --flag=gpgrt_bsprintf:1:c-format \
+ --flag=gpgrt_vbsprintf:1:c-format \
+ --flag=gpgrt_snprintf:3:c-format \
+ --flag=gpgrt_vsnprintf:3:c-format \
+ --flag=gpgrt_log:2:c-format \
+ --flag=gpgrt_log_bug:1:c-format \
+ --flag=gpgrt_log_fatal:1:c-format \
+ --flag=gpgrt_log_error:1:c-format \
+ --flag=gpgrt_log_info:1:c-format \
+ --flag=gpgrt_log_debug:1:c-format \
+ --flag=gpgrt_log_debug_string:2:c-format \
+ --flag=gpgrt_log_printf:1:c-format \
+ --flag=gpgrt_log_printhex:3:c-format \
+ --flag=gpgrt_log_clock:1:c-format \
+ --flag=log_log:2:c-format \
+ --flag=log_bug:1:c-format \
+ --flag=log_fatal:1:c-format \
+ --flag=log_error:1:c-format \
+ --flag=log_info:1:c-format \
+ --flag=log_debug:1:c-format \
+ --flag=log_debug_string:2:c-format \
+ --flag=log_printf:1:c-format \
+ --flag=log_printhex:3:c-format \
+ --flag=log_clock:1:c-format
+ --flag=put_membuf_printf:2:c-format \
+ --flag=tty_printf:1:c-format \
+ --flag=tty_fprintf:2:c-format \
+ --flag=tty_getf:1:c-format \
+ --flag=writeout_para:2:c-format \
+ --flag=writeout_li:3:c-format \
+ --flag=writeout_rem:2:c-format \
+ --flag=xasprintf:1:c-format \
+ --flag=xtryasprintf:1:c-format \
+ --flag=log_debug_with_string:2:c-format \
+ --flag=print_assuan_status:3:c-format \
+ --flag=vprint_assuan_status:3:c-format \
+ --flag=agent_print_status:3:c-format \
+ --flag=dirmngr_status_helpf:2:c-format \
+ --flag=dirmngr_status_printf:3:c-format \
+ --flag=ks_printf_help:2:c-format \
+ --flag=print_further_info:1:c-format \
+ --flag=write_status_printf:2:c-format \
+ --flag=kbxd_print_status:3:c-format \
+ --flag=gpgconf_write_status:2:c-format \
+ --flag=wks_write_status:2:c-format
+
# This is the copyright holder that gets inserted into the header of the
# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f19cb49c4..fe8d45f7e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -26,7 +26,6 @@ common/gettime.c
common/ksba-io-support.c
common/argparse.c
-common/logging.c
common/utf8conv.c
common/dotlock.c
common/init.c
diff --git a/scd/apdu.c b/scd/apdu.c
index 66a16f820..f3e2a12e7 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -105,6 +105,7 @@ struct reader_table_s {
int (*check_pinpad)(int, int, pininfo_t *);
void (*dump_status_reader)(int);
int (*set_progress_cb)(int, gcry_handler_progress_t, void*);
+ int (*set_prompt_cb)(int, void (*) (void *, int), void*);
int (*pinpad_verify)(int, int, int, int, int, pininfo_t *);
int (*pinpad_modify)(int, int, int, int, int, pininfo_t *);
@@ -444,6 +445,7 @@ new_reader_slot (void)
reader_table[reader].check_pinpad = check_pcsc_pinpad;
reader_table[reader].dump_status_reader = NULL;
reader_table[reader].set_progress_cb = NULL;
+ reader_table[reader].set_prompt_cb = NULL;
reader_table[reader].pinpad_verify = pcsc_pinpad_verify;
reader_table[reader].pinpad_modify = pcsc_pinpad_modify;
@@ -965,7 +967,8 @@ pcsc_vendor_specific_init (int slot)
else if (strstr (reader_table[slot].rdrname, "cyberJack")
|| strstr (reader_table[slot].rdrname, "DIGIPASS")
|| strstr (reader_table[slot].rdrname, "Gnuk")
- || strstr (reader_table[slot].rdrname, "KAAN"))
+ || strstr (reader_table[slot].rdrname, "KAAN")
+ || strstr (reader_table[slot].rdrname, "Trustica"))
reader_table[slot].pinpad_varlen_supported = 1;
}
@@ -1039,7 +1042,8 @@ pcsc_vendor_specific_init (int slot)
else if (vendor == 0x0c4b /* Tested with Reiner cyberJack GO */
|| vendor == 0x1a44 /* Tested with Vasco DIGIPASS 920 */
|| vendor == 0x234b /* Tested with FSIJ Gnuk Token */
- || vendor == 0x0d46 /* Tested with KAAN Advanced??? */)
+ || vendor == 0x0d46 /* Tested with KAAN Advanced??? */
+ || (vendor == 0x1fc9 && product == 0x81e6) /* Tested with Trustica Cryptoucan */)
reader_table[slot].pinpad_varlen_supported = 1;
return 0;
@@ -1402,6 +1406,14 @@ set_progress_cb_ccid_reader (int slot, gcry_handler_progress_t cb, void *cb_arg)
return ccid_set_progress_cb (slotp->ccid.handle, cb, cb_arg);
}
+static int
+set_prompt_cb_ccid_reader (int slot, void (*cb) (void *, int ), void *cb_arg)
+{
+ reader_table_t slotp = reader_table + slot;
+
+ return ccid_set_prompt_cb (slotp->ccid.handle, cb, cb_arg);
+}
+
static int
get_status_ccid (int slot, unsigned int *status, int on_wire)
@@ -1541,6 +1553,7 @@ open_ccid_reader (struct dev_list *dl)
reader_table[slot].check_pinpad = check_ccid_pinpad;
reader_table[slot].dump_status_reader = dump_ccid_reader_status;
reader_table[slot].set_progress_cb = set_progress_cb_ccid_reader;
+ reader_table[slot].set_prompt_cb = set_prompt_cb_ccid_reader;
reader_table[slot].pinpad_verify = ccid_pinpad_operation;
reader_table[slot].pinpad_modify = ccid_pinpad_operation;
/* Our CCID reader code does not support T=0 at all, thus reset the
@@ -2380,6 +2393,29 @@ apdu_set_progress_cb (int slot, gcry_handler_progress_t cb, void *cb_arg)
}
+int
+apdu_set_prompt_cb (int slot, void (*cb) (void *, int), void *cb_arg)
+{
+ int sw;
+
+ if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
+ return SW_HOST_NO_DRIVER;
+
+ if (reader_table[slot].set_prompt_cb)
+ {
+ sw = lock_slot (slot);
+ if (!sw)
+ {
+ sw = reader_table[slot].set_prompt_cb (slot, cb, cb_arg);
+ unlock_slot (slot);
+ }
+ }
+ else
+ sw = 0;
+ return sw;
+}
+
+
/* Do a reset for the card in reader at SLOT. */
int
apdu_reset (int slot)
@@ -2610,7 +2646,7 @@ send_apdu (int slot, unsigned char *apdu, size_t apdulen,
}
-/* Core APDU tranceiver function. Parameters are described at
+/* Core APDU transceiver function. Parameters are described at
apdu_send_le with the exception of PININFO which indicates pinpad
related operations if not NULL. If EXTENDED_MODE is not 0
command chaining or extended length will be used according to these
diff --git a/scd/apdu.h b/scd/apdu.h
index 8a0d4bda8..8621ddc41 100644
--- a/scd/apdu.h
+++ b/scd/apdu.h
@@ -117,6 +117,7 @@ int apdu_connect (int slot);
int apdu_disconnect (int slot);
int apdu_set_progress_cb (int slot, gcry_handler_progress_t cb, void *cb_arg);
+int apdu_set_prompt_cb (int slot, void (*cb) (void *, int), void *cb_arg);
int apdu_reset (int slot);
int apdu_get_status (int slot, int hang, unsigned int *status);
diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c
index bea285687..983bed6e1 100644
--- a/scd/app-dinsig.c
+++ b/scd/app-dinsig.c
@@ -415,7 +415,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
&& indatalen != (15+20) && indatalen != (19+32))
return gpg_error (GPG_ERR_INV_VALUE);
- /* Check that the provided ID is vaid. This is not really needed
+ /* Check that the provided ID is valid. This is not really needed
but we do it to enforce correct usage by the caller. */
if (strncmp (keyidstr, "DINSIG.", 7) )
return gpg_error (GPG_ERR_INV_ID);
diff --git a/scd/app-geldkarte.c b/scd/app-geldkarte.c
index 510beb550..85bcedc4f 100644
--- a/scd/app-geldkarte.c
+++ b/scd/app-geldkarte.c
@@ -254,7 +254,7 @@ copy_bcd (const unsigned char *string, size_t length)
}
-/* Convert the BCD number at STING of LENGTH into an integer and store
+/* Convert the BCD number at STRING of LENGTH into an integer and store
that at RESULT. Return 0 on success. */
static gpg_error_t
bcd_to_int (const unsigned char *string, size_t length, int *result)
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index c17452555..789b72f00 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -119,8 +119,11 @@ static struct {
{ 0x0104, 0, 0, 0, 0, 0, 0, 2, "Private DO 4"},
{ 0x7F21, 1, 0, 1, 0, 0, 0, 1, "Cardholder certificate"},
/* V3.0 */
- { 0x7F74, 0, 0, 1, 0, 0, 0, 0, "General Feature Management"},
+ { 0x7F74, 0, 0x6E, 1, 0, 0, 0, 0, "General Feature Management"},
{ 0x00D5, 0, 0, 1, 0, 0, 0, 0, "AES key data"},
+ { 0x00D6, 0, 0x6E, 1, 0, 0, 0, 0, "UIF for Signature"},
+ { 0x00D7, 0, 0x6E, 1, 0, 0, 0, 0, "UIF for decryption"},
+ { 0x00D8, 0, 0x6E, 1, 0, 0, 0, 0, "UIF for authentication"},
{ 0x00F9, 0, 0, 1, 0, 0, 0, 0, "KDF data object"},
{ 0 }
};
@@ -640,7 +643,7 @@ count_bits (const unsigned char *a, size_t len)
Where FLAGS is a plain hexadecimal number representing flag values.
The lsb is here the rightmost bit. Defined flags bits are:
- Bit 0 = CHV1 and CHV2 are not syncronized
+ Bit 0 = CHV1 and CHV2 are not synchronized
Bit 1 = CHV2 has been set to the default PIN of "123456"
(this implies that bit 0 is also set).
@@ -985,6 +988,9 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
{ "PRIVATE-DO-4", 0x0104 },
{ "$AUTHKEYID", 0x0000, -3 },
{ "$DISPSERIALNO",0x0000, -4 },
+ { "UIF-1", 0x00D6, 0 },
+ { "UIF-2", 0x00D7, 0 },
+ { "UIF-3", 0x00D8, 0 },
{ "KDF", 0x00F9 },
{ NULL, 0 }
};
@@ -1827,6 +1833,9 @@ do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
do_getattr (app, ctrl, "CA-FPR");
do_getattr (app, ctrl, "CHV-STATUS");
do_getattr (app, ctrl, "SIG-COUNTER");
+ do_getattr (app, ctrl, "UIF-1");
+ do_getattr (app, ctrl, "UIF-2");
+ do_getattr (app, ctrl, "UIF-3");
if (app->app_local->extcap.private_dos)
{
do_getattr (app, ctrl, "PRIVATE-DO-1");
@@ -2459,6 +2468,9 @@ do_setattr (app_t app, const char *name,
{ "SM-KEY-MAC", 0x00D2, 3, 0, 1 },
{ "KEY-ATTR", 0, 0, 3, 1 },
{ "AESKEY", 0x00D5, 3, 0, 1 },
+ { "UIF-1", 0x00D6, 3, 5, 1 },
+ { "UIF-2", 0x00D7, 3, 5, 1 },
+ { "UIF-3", 0x00D8, 3, 5, 1 },
{ "KDF", 0x00F9, 3, 4, 1 },
{ NULL, 0 }
};
@@ -2471,6 +2483,9 @@ do_setattr (app_t app, const char *name,
if (table[idx].need_v2 && !app->app_local->extcap.is_v2)
return gpg_error (GPG_ERR_NOT_SUPPORTED); /* Not yet supported. */
+ if (table[idx].special == 5 && app->app_local->extcap.has_button == 0)
+ return gpg_error (GPG_ERR_INV_OBJ);
+
if (table[idx].special == 3)
return change_keyattr_from_string (app, pincb, pincb_arg, value, valuelen);
@@ -2839,10 +2854,10 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */
}
else
- {
+ {
rc = pin2hash_if_kdf (app, chvno, oldpinvalue, &pinlen0);
if (!rc)
- rc = pin2hash_if_kdf (app, chvno, pinvalue, &pinlen);
+ rc = pin2hash_if_kdf (app, chvno, pinvalue, &pinlen);
if (!rc)
rc = iso7816_change_reference_data (app->slot, 0x80 + chvno,
oldpinvalue, pinlen0,
@@ -4381,7 +4396,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
log_info (_("signatures created so far: %lu\n"), sigcount);
/* Check CHV if needed. */
- if (!app->did_chv1 || app->force_chv1 )
+ if (!app->did_chv1 || app->force_chv1)
{
char *pinvalue;
int pinlen;
@@ -4429,6 +4444,9 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
}
rc = iso7816_compute_ds (app->slot, exmode, data, datalen, le_value,
outdata, outdatalen);
+ if (!rc && app->force_chv1)
+ app->did_chv1 = 0;
+
return rc;
}
diff --git a/scd/app.c b/scd/app.c
index f3f1205f8..a82db26cd 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -67,6 +67,7 @@ lock_app (app_t app, ctrl_t ctrl)
}
apdu_set_progress_cb (app->slot, print_progress_line, ctrl);
+ apdu_set_prompt_cb (app->slot, popup_prompt, ctrl);
return 0;
}
@@ -76,6 +77,7 @@ static void
unlock_app (app_t app)
{
apdu_set_progress_cb (app->slot, NULL, NULL);
+ apdu_set_prompt_cb (app->slot, NULL, NULL);
if (npth_mutex_unlock (&app->lock))
{
diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index f33a36c83..ff82ef38b 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -255,6 +255,9 @@ struct ccid_driver_s
void (*progress_cb)(void *, const char *, int, int, int);
void *progress_cb_arg;
+ void (*prompt_cb)(void *, int);
+ void *prompt_cb_arg;
+
unsigned char intr_buf[64];
struct libusb_transfer *transfer;
};
@@ -1802,6 +1805,19 @@ ccid_set_progress_cb (ccid_driver_t handle,
}
+int
+ccid_set_prompt_cb (ccid_driver_t handle,
+ void (*cb)(void *, int), void *cb_arg)
+{
+ if (!handle)
+ return CCID_DRIVER_ERR_INV_VALUE;
+
+ handle->prompt_cb = cb;
+ handle->prompt_cb_arg = cb_arg;
+ return 0;
+}
+
+
/* Close the reader HANDLE. */
int
ccid_close_reader (ccid_driver_t handle)
@@ -1921,7 +1937,7 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen,
is the sequence number used to send the request and EXPECTED_TYPE
the type of message we expect. Does checks on the ccid
header. TIMEOUT is the timeout value in ms. NO_DEBUG may be set to
- avoid debug messages in case of no error; this can be overriden
+ avoid debug messages in case of no error; this can be overridden
with a glibal debug level of at least 3. Returns 0 on success. */
static int
bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
@@ -1930,6 +1946,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
{
int rc;
int msglen;
+ int notified = 0;
/* Fixme: The next line for the current Valgrind without support
for USB IOCTLs. */
@@ -1982,14 +1999,25 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
we got the expected message type. This is in particular required
for the Cherry keyboard which sends a time extension request for
each key hit. */
- if ( !(buffer[7] & 0x03) && (buffer[7] & 0xC0) == 0x80)
+ if (!(buffer[7] & 0x03) && (buffer[7] & 0xC0) == 0x80)
{
/* Card present and active, time extension requested. */
DEBUGOUT_2 ("time extension requested (%02X,%02X)\n",
buffer[7], buffer[8]);
+
+ /* Gnuk enhancement to prompt user input by ack button */
+ if (buffer[8] == 0xff && !notified)
+ {
+ notified = 1;
+ handle->prompt_cb (handle->prompt_cb_arg, 1);
+ }
+
goto retry;
}
+ if (notified)
+ handle->prompt_cb (handle->prompt_cb_arg, 0);
+
if (buffer[0] != expected_type && buffer[0] != RDR_to_PC_SlotStatus)
{
DEBUGOUT_1 ("unexpected bulk-in msg type (%02x)\n", buffer[0]);
@@ -2928,7 +2956,7 @@ ccid_transceive_apdu_level (ccid_driver_t handle,
bit 3 unused
bit 2..0 Source Node Address (SAD)
- If node adresses are not used, SAD and DAD should be set to 0 on
+ If node addresses are not used, SAD and DAD should be set to 0 on
the first block sent to the card. If they are used they should
have different values (0 for one is okay); that first block sets up
the addresses of the nodes.
@@ -3270,7 +3298,7 @@ ccid_transceive (ccid_driver_t handle,
/* Wait time extension request. */
unsigned char bwi = tpdu[3];
- /* Check if it's unsual value which can't be expressed in ATR. */
+ /* Check if it's unusual value which can't be expressed in ATR. */
if (bwi > 15)
wait_more = 1;
@@ -3387,6 +3415,12 @@ ccid_transceive_secure (ccid_driver_t handle,
if (handle->id_product != CHERRY_ST2000)
cherry_mode = 1;
break;
+ case VENDOR_NXP:
+ if (handle->id_product == CRYPTOUCAN){
+ pininfo->maxlen = 25;
+ enable_varlen = 1;
+ }
+ break;
default:
if ((handle->id_vendor == VENDOR_GEMPC &&
handle->id_product == GEMPC_PINPAD)
diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h
index b6da30c07..1550b3eba 100644
--- a/scd/ccid-driver.h
+++ b/scd/ccid-driver.h
@@ -68,7 +68,8 @@ enum {
VENDOR_REINER = 0x0c4b,
VENDOR_KAAN = 0x0d46,
VENDOR_FSIJ = 0x234b,
- VENDOR_VASCO = 0x1a44
+ VENDOR_VASCO = 0x1a44,
+ VENDOR_NXP = 0x1fc9,
};
@@ -84,6 +85,7 @@ enum {
#define GEMPC_CT30 0x3437
#define VEGA_ALPHA 0x0008
#define CYBERJACK_GO 0x0504
+#define CRYPTOUCAN 0x81e6
#endif /*CCID_DRIVER_INCLUDE_USB_IDS*/
@@ -124,6 +126,8 @@ int ccid_open_reader (const char *spec_reader_name,
int ccid_set_progress_cb (ccid_driver_t handle,
void (*cb)(void *, const char *, int, int, int),
void *cb_arg);
+int ccid_set_prompt_cb (ccid_driver_t handle, void (*cb)(void *, int),
+ void *cb_arg);
int ccid_shutdown_reader (ccid_driver_t handle);
int ccid_close_reader (ccid_driver_t handle);
int ccid_get_atr (ccid_driver_t handle,
diff --git a/scd/command.c b/scd/command.c
index 66d9fb971..0a9654693 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -1898,6 +1898,34 @@ send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
}
+void
+popup_prompt (void *opaque, int on)
+{
+ ctrl_t ctrl = opaque;
+
+ if (ctrl)
+ {
+ assuan_context_t ctx = ctrl->server_local->assuan_ctx;
+
+ if (ctx)
+ {
+ const char *cmd;
+ gpg_error_t err;
+ unsigned char *value;
+ size_t valuelen;
+
+ if (on)
+ cmd = "POPUPPINPADPROMPT --ack";
+ else
+ cmd = "DISMISSPINPADPROMPT";
+ err = assuan_inquire (ctx, cmd, &value, &valuelen, 100);
+ if (!err)
+ xfree (value);
+ }
+ }
+}
+
+
/* Helper to send the clients a status change notification. */
void
send_client_notifications (app_t app, int removal)
diff --git a/scd/iso7816.c b/scd/iso7816.c
index 29208c254..01faca5b4 100644
--- a/scd/iso7816.c
+++ b/scd/iso7816.c
@@ -427,7 +427,7 @@ iso7816_put_data_odd (int slot, int extended_mode, int tag,
/* Manage Security Environment. This is a weird operation and there
is no easy abstraction for it. Furthermore, some card seem to have
- a different interpreation of 7816-8 and thus we resort to let the
+ a different interpretation of 7816-8 and thus we resort to let the
caller decide what to do. */
gpg_error_t
iso7816_manage_security_env (int slot, int p1, int p2,
@@ -445,7 +445,7 @@ iso7816_manage_security_env (int slot, int p1, int p2,
/* Perform the security operation COMPUTE DIGITAL SIGANTURE. On
- success 0 is returned and the data is availavle in a newly
+ success 0 is returned and the data is available in a newly
allocated buffer stored at RESULT with its length stored at
RESULTLEN. For LE see do_generate_keypair. */
gpg_error_t
diff --git a/scd/scdaemon.c b/scd/scdaemon.c
index 8f8a02619..507108db0 100644
--- a/scd/scdaemon.c
+++ b/scd/scdaemon.c
@@ -1069,7 +1069,7 @@ handle_signal (int signo)
/* Create a name for the socket. We check for valid characters as
well as against a maximum allowed length for a unix domain socket
is done. The function terminates the process in case of an error.
- Retunrs: Pointer to an allcoated string with the absolute name of
+ Returns: Pointer to an allcoated string with the absolute name of
the socket used. */
static char *
create_socket_name (char *standard_name)
diff --git a/scd/scdaemon.h b/scd/scdaemon.h
index 4797f3df0..238e6a8fd 100644
--- a/scd/scdaemon.h
+++ b/scd/scdaemon.h
@@ -123,6 +123,7 @@ int scd_command_handler (ctrl_t, int);
void send_status_info (ctrl_t ctrl, const char *keyword, ...)
GPGRT_ATTR_SENTINEL(1);
void send_status_direct (ctrl_t ctrl, const char *keyword, const char *args);
+void popup_prompt (void *opaque, int on);
void send_client_notifications (app_t app, int removal);
void scd_kick_the_loop (void);
int get_active_connection_count (void);
diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c
index 3a38bca50..bff7dd652 100644
--- a/sm/call-dirmngr.c
+++ b/sm/call-dirmngr.c
@@ -474,7 +474,7 @@ isvalid_status_cb (void *opaque, const char *line)
{
parm->seen++;
if (!*s || !unhexify_fpr (s, parm->fpr))
- parm->seen++; /* Bumb it to indicate an error. */
+ parm->seen++; /* Bump it to indicate an error. */
}
return 0;
}
diff --git a/sm/certchain.c b/sm/certchain.c
index 4e18caf55..79d98c736 100644
--- a/sm/certchain.c
+++ b/sm/certchain.c
@@ -669,7 +669,7 @@ find_up (ctrl_t ctrl, KEYDB_HANDLE kh,
log_debug (" found via authid and sn+issuer\n");
/* In case of an error, try to get the certificate from the
- dirmngr. That is done by trying to put that certifcate
+ dirmngr. That is done by trying to put that certificate
into the ephemeral DB and let the code below do the
actual retrieve. Thus there is no error checking.
Skipped in find_next mode as usual. */
@@ -908,7 +908,7 @@ is_root_cert (ksba_cert_t cert, const char *issuerdn, const char *subjectdn)
{
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
return 1; /* Yes. Without a authorityKeyIdentifier this needs
- to be the Root certifcate (our trust anchor). */
+ to be the Root certificate (our trust anchor). */
log_error ("error getting authorityKeyIdentifier: %s\n",
gpg_strerror (err));
return 0; /* Well, it is broken anyway. Return No. */
@@ -1103,7 +1103,7 @@ check_validity_period (ksba_isotime_t current_time,
}
/* This is a variant of check_validity_period used with the chain
- model. The dextra contraint here is that notBefore and notAfter
+ model. The extra constraint here is that notBefore and notAfter
must exists and if the additional argument CHECK_TIME is given this
time is used to check the validity period of SUBJECT_CERT. */
static gpg_error_t
@@ -1171,7 +1171,7 @@ check_validity_period_cm (ksba_isotime_t current_time,
|| strcmp (check_time, not_after) > 0))
{
/* Note that we don't need a case for the root certificate
- because its own consitency has already been checked. */
+ because its own consistency has already been checked. */
do_list(opt.ignore_expiration?0:1, listmode, listfp,
depth == 0 ?
_("signature not created during lifetime of certificate") :
@@ -1553,7 +1553,7 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg,
if (rc)
goto leave;
- break; /* Okay: a self-signed certicate is an end-point. */
+ break; /* Okay: a self-signed certificate is an end-point. */
} /* End is_root. */
diff --git a/sm/certlist.c b/sm/certlist.c
index c9e275e9d..12a492518 100644
--- a/sm/certlist.c
+++ b/sm/certlist.c
@@ -395,7 +395,7 @@ gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret,
Further we ignore them if they are due to an
identical certificate (which may happen if a
- certificate is accidential duplicated in the
+ certificate is accidentally duplicated in the
keybox). */
if (!keydb_get_cert (kh, &cert2))
{
@@ -533,7 +533,7 @@ gpgsm_find_cert (ctrl_t ctrl,
}
/* If we don't have the KEYID filter we need to check for
- ambiguous search results. Note, that it is somehwat
+ ambiguous search results. Note, that it is somewhat
reasonable to assume that a specification of a KEYID
won't lead to ambiguous names. */
if (!rc && !keyid)
diff --git a/sm/certreqgen-ui.c b/sm/certreqgen-ui.c
index 4f8a1ac9d..f64baf365 100644
--- a/sm/certreqgen-ui.c
+++ b/sm/certreqgen-ui.c
@@ -86,7 +86,7 @@ store_mb_lines (membuf_t *mb, membuf_t *lines)
}
-/* Chech whether we have a key for the key with HEXGRIP. Returns NULL
+/* Check whether we have a key for the key with HEXGRIP. Returns NULL
if not or a string describing the type of the key (RSA, ELG, DSA,
etc..). */
static const char *
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index b0547876a..2f9e5bfd2 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -1571,7 +1571,7 @@ main ( int argc, char **argv)
set_debug ();
- /* Although we always use gpgsm_exit, we better install a regualr
+ /* Although we always use gpgsm_exit, we better install a regular
exit handler so that at least the secure memory gets wiped
out. */
if (atexit (emergency_cleanup))
@@ -1666,7 +1666,7 @@ main ( int argc, char **argv)
|| cmd == aClearsign,
opt.extra_digest_algo))
log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
- forced_digest_algo,
+ extra_digest_algo,
gnupg_compliance_option_string (opt.compliance));
if (log_get_errorcount(0))
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index d3fbde515..7a5e4917d 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -76,7 +76,7 @@ struct
const char *protect_tool_program;
char *outfile; /* name of output file */
- int with_key_data;/* include raw key in the column delimted output */
+ int with_key_data;/* include raw key in the column delimited output */
int fingerprint; /* list fingerprints in all key listings */
diff --git a/sm/keydb.c b/sm/keydb.c
index d85679a3b..a6ea9f77f 100644
--- a/sm/keydb.c
+++ b/sm/keydb.c
@@ -106,7 +106,7 @@ try_make_homedir (const char *fname)
/* Handle the creation of a keybox if it does not yet exist. Take
- into acount that other processes might have the keybox already
+ into account that other processes might have the keybox already
locked. This lock check does not work if the directory itself is
not yet available. If R_CREATED is not NULL it will be set to true
if the function created a new keybox. */
diff --git a/sm/minip12.c b/sm/minip12.c
index f066892a0..76ce07376 100644
--- a/sm/minip12.c
+++ b/sm/minip12.c
@@ -853,7 +853,7 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length,
if (ti.class == ASNCONTEXT && ti.tag == 0 && ti.is_constructed && ti.ndef)
{
/* Mozilla exported certs now come with single byte chunks of
- octect strings. (Mozilla Firefox 1.0.4). Arghh. */
+ octet strings. (Mozilla Firefox 1.0.4). Arghh. */
where = "cram-rc2or3des-ciphertext";
cram_buffer = cram_octet_string ( p, &n, &consumed);
if (!cram_buffer)
@@ -1210,7 +1210,7 @@ parse_bag_data (const unsigned char *buffer, size_t length, int startoffset,
if (ti.is_constructed && ti.ndef)
{
/* Mozilla exported certs now come with single byte chunks of
- octect strings. (Mozilla Firefox 1.0.4). Arghh. */
+ octet strings. (Mozilla Firefox 1.0.4). Arghh. */
where = "cram-data.outersegs";
cram_buffer = cram_octet_string ( p, &n, &consumed);
if (!cram_buffer)
@@ -1550,7 +1550,7 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw,
if (ti.is_constructed && ti.ndef)
{
/* Mozilla exported certs now come with single byte chunks of
- octect strings. (Mozilla Firefox 1.0.4). Arghh. */
+ octet strings. (Mozilla Firefox 1.0.4). Arghh. */
where = "cram-bags";
cram_buffer = cram_octet_string ( p, &n, NULL);
if (!cram_buffer)
diff --git a/sm/qualified.c b/sm/qualified.c
index 6a7b47306..70d03aed3 100644
--- a/sm/qualified.c
+++ b/sm/qualified.c
@@ -140,7 +140,7 @@ read_list (char *key, char *country, int *lnr)
Returns: 0 if the certificate is included. GPG_ERR_NOT_FOUND if it
is not in the list or any other error (e.g. if no list of
qualified signatures is available. If COUNTRY has not been passed
- as NULL a string witha maximum length of 2 will be copied into it;
+ as NULL a string with a maximum length of 2 will be copied into it;
thus the caller needs to provide a buffer of length 3. */
gpg_error_t
gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert, char *country)
diff --git a/tests/asschk.c b/tests/asschk.c
index 65828e5b2..c77fd7c23 100644
--- a/tests/asschk.c
+++ b/tests/asschk.c
@@ -30,7 +30,7 @@
expanded once and non existing macros expand to the empty string.
A macro is dereferenced by prefixing its name with a dollar sign;
the end of the name is currently indicated by a white space, a
- dollar sign or a slash. To use a dollor sign verbatim, double it.
+ dollar sign or a slash. To use a dollar sign verbatim, double it.
A macro is assigned by prefixing a statement with the macro name
and an equal sign. The value is assigned verbatim if it does not
@@ -47,7 +47,7 @@
[<name> =] <statement> [<args>]
- If NAME is not specifed but the statement returns a value it is
+ If NAME is not specified but the statement returns a value it is
assigned to the name "?" so that it can be referenced using "$?".
The following commands are implemented:
@@ -274,7 +274,7 @@ writen (int fd, const char *buffer, size_t length)
type and store that in recv_type. The function terminates on a
communication error. Returns a pointer into the inputline to the
first byte of the arguments. The parsing is very strict to match
- exaclty what we want to send. */
+ exactly what we want to send. */
static char *
read_assuan (int fd)
{
@@ -397,7 +397,7 @@ write_assuan (int fd, const char *line)
/* Start the server with path PGMNAME and connect its stdout and
strerr to a newly created pipes; the file descriptors are then
- store in the gloabl variables SERVER_SEND_FD and
+ store in the global variables SERVER_SEND_FD and
SERVER_RECV_FD. The initial handcheck is performed.*/
static void
start_server (const char *pgmname)
@@ -468,7 +468,7 @@ start_server (const char *pgmname)
-/* Script intepreter. */
+/* Script interpreter. */
static void
unset_var (const char *name)
diff --git a/tests/gpgscm/scheme.c b/tests/gpgscm/scheme.c
index 4384841a7..feb313349 100644
--- a/tests/gpgscm/scheme.c
+++ b/tests/gpgscm/scheme.c
@@ -2990,13 +2990,23 @@ _Error_1(scheme *sc, const char *s, pointer a) {
/* Define a label OP and emit a case statement for OP. For use in the
* dispatch function. The slightly peculiar goto that is never
* executed avoids warnings about unused labels. */
+#if __GNUC__ > 6
+#define CASE(OP) OP: __attribute__((unused)); case OP
+#else
#define CASE(OP) case OP: if (0) goto OP; OP
+#endif
#else /* USE_THREADED_CODE */
#define s_thread_to(sc, a) s_goto(sc, a)
#define CASE(OP) case OP
#endif /* USE_THREADED_CODE */
+#if __GNUC__ > 6
+#define FALLTHROUGH __attribute__ ((fallthrough))
+#else
+#define FALLTHROUGH /* fallthrough */
+#endif
+
/* Return to the previous frame on the dump stack, setting the current
* value to A. */
#define s_return(sc, a) s_goto(sc, _s_return(sc, a, 0))
@@ -3557,7 +3567,7 @@ Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
putstr(sc,"\nEval: ");
s_thread_to(sc,OP_P0LIST);
}
- /* fall through */
+ FALLTHROUGH;
CASE(OP_REAL_EVAL):
#endif
if (is_symbol(sc->code)) { /* symbol */
@@ -3635,7 +3645,7 @@ Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
free_cons(sc, sc->args, &callsite, &sc->args);
sc->code = car(sc->args);
sc->args = cdr(sc->args);
- /* Fallthrough. */
+ FALLTHROUGH;
CASE(OP_APPLY): /* apply 'code' to 'args' */
#if USE_TRACING
@@ -3646,7 +3656,7 @@ Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
putstr(sc,"\nApply to: ");
s_thread_to(sc,OP_P0LIST);
}
- /* fall through */
+ FALLTHROUGH;
CASE(OP_REAL_APPLY):
#endif
#if USE_HISTORY
@@ -3727,12 +3737,11 @@ Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
s_thread_to(sc,OP_APPLY);
}
}
- /* Fallthrough. */
#else
CASE(OP_LAMBDA): /* lambda */
sc->value = sc->code;
- /* Fallthrough. */
#endif
+ FALLTHROUGH;
CASE(OP_LAMBDA1):
gc_disable(sc, 1);
@@ -4655,13 +4664,9 @@ Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
CASE(OP_NULLP): /* null? */
s_retbool(car(sc->args) == sc->NIL);
CASE(OP_NUMEQ): /* = */
- /* Fallthrough. */
CASE(OP_LESS): /* < */
- /* Fallthrough. */
CASE(OP_GRE): /* > */
- /* Fallthrough. */
CASE(OP_LEQ): /* <= */
- /* Fallthrough. */
CASE(OP_GEQ): /* >= */
switch(op) {
case OP_NUMEQ: comp_func=num_eq; break;
@@ -4750,9 +4755,7 @@ Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
s_return(sc,sc->value);
CASE(OP_WRITE): /* write */
- /* Fallthrough. */
CASE(OP_DISPLAY): /* display */
- /* Fallthrough. */
CASE(OP_WRITE_CHAR): /* write-char */
if(is_pair(cdr(sc->args))) {
if(cadr(sc->args)!=sc->outport) {
@@ -4900,9 +4903,7 @@ Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
s_return(sc,sc->outport);
CASE(OP_OPEN_INFILE): /* open-input-file */
- /* Fallthrough. */
CASE(OP_OPEN_OUTFILE): /* open-output-file */
- /* Fallthrough. */
CASE(OP_OPEN_INOUTFILE): /* open-input-output-file */ {
int prop=0;
pointer p;
@@ -4922,7 +4923,6 @@ Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
#if USE_STRING_PORTS
CASE(OP_OPEN_INSTRING): /* open-input-string */
- /* Fallthrough. */
CASE(OP_OPEN_INOUTSTRING): /* open-input-output-string */ {
int prop=0;
pointer p;
@@ -5003,7 +5003,6 @@ Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
s_thread_to(sc,OP_READ_INTERNAL);
CASE(OP_READ_CHAR): /* read-char */
- /* Fallthrough. */
CASE(OP_PEEK_CHAR): /* peek-char */ {
int c;
if(is_pair(sc->args)) {
diff --git a/tools/Makefile.am b/tools/Makefile.am
index a15427622..196bf5210 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -34,11 +34,6 @@ AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) $(LIBASSUAN_CFLAGS)
sbin_SCRIPTS = addgnupghome applygnupgdefaults
-if HAVE_USTAR
-# bin_SCRIPTS += gpg-zip
-noinst_SCRIPTS = gpg-zip
-endif
-
if BUILD_SYMCRYPTRUN
symcryptrun = symcryptrun
else
diff --git a/tools/gpg-check-pattern.c b/tools/gpg-check-pattern.c
index 4db8f3706..dee5d5d47 100644
--- a/tools/gpg-check-pattern.c
+++ b/tools/gpg-check-pattern.c
@@ -91,7 +91,7 @@ static struct
enum {
PAT_NULL, /* Indicates end of the array. */
PAT_STRING, /* The pattern is a simple string. */
- PAT_REGEX /* The pattern is an extended regualr expression. */
+ PAT_REGEX /* The pattern is an extended regular expression. */
};
diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c
index 00482a32e..7eb7ffa3a 100644
--- a/tools/gpg-connect-agent.c
+++ b/tools/gpg-connect-agent.c
@@ -983,7 +983,7 @@ do_open (char *line)
name, mode, strerror (errno));
return;
}
- fd = fileno (fp);
+ fd = dup (fileno (fp));
if (fd >= 0 && fd < DIM (open_fd_table))
{
open_fd_table[fd].inuse = 1;
@@ -1030,8 +1030,10 @@ do_open (char *line)
else
{
log_error ("can't put fd %d into table\n", fd);
- close (fd);
+ if (fd != -1)
+ close (fd); /* Table was full. */
}
+ fclose (fp);
}
diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c
index 73945ff30..0be5ea89b 100644
--- a/tools/gpg-wks-client.c
+++ b/tools/gpg-wks-client.c
@@ -61,6 +61,7 @@ enum cmd_and_opt_values
oSend,
oFakeSubmissionAddr,
oStatusFD,
+ oWithColons,
oDummy
};
@@ -90,6 +91,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oSend, "send", "send the mail using sendmail"),
ARGPARSE_s_s (oOutput, "output", "|FILE|write the mail to FILE"),
ARGPARSE_s_i (oStatusFD, "status-fd", N_("|FD|write status info to this FD")),
+ ARGPARSE_s_n (oWithColons, "with-colons", "@"),
ARGPARSE_s_s (oFakeSubmissionAddr, "fake-submission-addr", "@"),
@@ -204,6 +206,9 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
case oStatusFD:
wks_set_status_fd (translate_sys2libc_fd_int (pargs->r.ret_int, 1));
break;
+ case oWithColons:
+ opt.with_colons = 1;
+ break;
case aSupported:
case aCreate:
@@ -271,11 +276,20 @@ main (int argc, char **argv)
switch (cmd)
{
case aSupported:
- if (argc != 1)
- wrong_args ("--supported USER-ID");
- err = command_supported (argv[0]);
- if (err && gpg_err_code (err) != GPG_ERR_FALSE)
- log_error ("checking support failed: %s\n", gpg_strerror (err));
+ if (opt.with_colons)
+ {
+ for (; argc; argc--, argv++)
+ command_supported (*argv);
+ err = 0;
+ }
+ else
+ {
+ if (argc != 1)
+ wrong_args ("--supported DOMAIN");
+ err = command_supported (argv[0]);
+ if (err && gpg_err_code (err) != GPG_ERR_FALSE)
+ log_error ("checking support failed: %s\n", gpg_strerror (err));
+ }
break;
case aCreate:
@@ -471,6 +485,134 @@ decrypt_stream (estream_t *r_output, struct decrypt_stream_parm_s *decinfo,
}
+/* Return the submission address for the address or just the domain in
+ * ADDRSPEC. The submission address is stored as a malloced string at
+ * R_SUBMISSION_ADDRESS. At R_POLICY the policy flags of the domain
+ * are stored. The caller needs to free them with wks_free_policy.
+ * The function returns an error code on failure to find a submission
+ * address or policy file. Note: The function may store NULL at
+ * R_SUBMISSION_ADDRESS but return success to indicate that the web
+ * key directory is supported but not the web key service. As per WKD
+ * specs a policy file is always required and will thus be return on
+ * success. */
+static gpg_error_t
+get_policy_and_sa (const char *addrspec, int silent,
+ policy_flags_t *r_policy, char **r_submission_address)
+{
+ gpg_error_t err;
+ estream_t mbuf = NULL;
+ const char *domain;
+ const char *s;
+ policy_flags_t policy = NULL;
+ char *submission_to = NULL;
+
+ *r_submission_address = NULL;
+ *r_policy = NULL;
+
+ domain = strchr (addrspec, '@');
+ if (domain)
+ domain++;
+
+ if (opt.with_colons)
+ {
+ s = domain? domain : addrspec;
+ es_write_sanitized (es_stdout, s, strlen (s), ":", NULL);
+ es_putc (':', es_stdout);
+ }
+
+ /* We first try to get the submission address from the policy file
+ * (this is the new method). If both are available we check that
+ * they match and print a warning if not. In the latter case we
+ * keep on using the one from the submission-address file. */
+ err = wkd_get_policy_flags (addrspec, &mbuf);
+ if (err && gpg_err_code (err) != GPG_ERR_NO_DATA
+ && gpg_err_code (err) != GPG_ERR_NO_NAME)
+ {
+ if (!opt.with_colons)
+ log_error ("error reading policy flags for '%s': %s\n",
+ domain, gpg_strerror (err));
+ goto leave;
+ }
+ if (!mbuf)
+ {
+ if (!opt.with_colons)
+ log_error ("provider for '%s' does NOT support the Web Key Directory\n",
+ addrspec);
+ err = gpg_error (GPG_ERR_FALSE);
+ goto leave;
+ }
+
+ policy = xtrycalloc (1, sizeof *policy);
+ if (!policy)
+ err = gpg_error_from_syserror ();
+ else
+ err = wks_parse_policy (policy, mbuf, 1);
+ es_fclose (mbuf);
+ mbuf = NULL;
+ if (err)
+ goto leave;
+
+ err = wkd_get_submission_address (addrspec, &submission_to);
+ if (err && !policy->submission_address)
+ {
+ if (!silent && !opt.with_colons)
+ log_error (_("error looking up submission address for domain '%s'"
+ ": %s\n"), domain, gpg_strerror (err));
+ if (!silent && gpg_err_code (err) == GPG_ERR_NO_DATA && !opt.with_colons)
+ log_error (_("this domain probably doesn't support WKS.\n"));
+ goto leave;
+ }
+
+ if (submission_to && policy->submission_address
+ && ascii_strcasecmp (submission_to, policy->submission_address))
+ log_info ("Warning: different submission addresses (sa=%s, po=%s)\n",
+ submission_to, policy->submission_address);
+
+ if (!submission_to && policy->submission_address)
+ {
+ submission_to = xtrystrdup (policy->submission_address);
+ if (!submission_to)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ }
+
+ leave:
+ *r_submission_address = submission_to;
+ submission_to = NULL;
+ *r_policy = policy;
+ policy = NULL;
+
+ if (opt.with_colons)
+ {
+ if (*r_policy && !*r_submission_address)
+ es_fprintf (es_stdout, "1:0::");
+ else if (*r_policy && *r_submission_address)
+ es_fprintf (es_stdout, "1:1::");
+ else if (err && !(gpg_err_code (err) == GPG_ERR_FALSE
+ || gpg_err_code (err) == GPG_ERR_NO_DATA
+ || gpg_err_code (err) == GPG_ERR_UNKNOWN_HOST))
+ es_fprintf (es_stdout, "0:0:%d:", err);
+ else
+ es_fprintf (es_stdout, "0:0::");
+ if (*r_policy)
+ {
+ es_fprintf (es_stdout, "%u:%u:%u:",
+ (*r_policy)->protocol_version,
+ (*r_policy)->auth_submit,
+ (*r_policy)->mailbox_only);
+ }
+ es_putc ('\n', es_stdout);
+ }
+
+ xfree (submission_to);
+ wks_free_policy (policy);
+ xfree (policy);
+ es_fclose (mbuf);
+ return err;
+}
+
/* Check whether the provider supports the WKS protocol. */
@@ -480,15 +622,16 @@ command_supported (char *userid)
gpg_error_t err;
char *addrspec = NULL;
char *submission_to = NULL;
+ policy_flags_t policy = NULL;
if (!strchr (userid, '@'))
{
char *tmp = xstrconcat ("foo@", userid, NULL);
- addrspec = mailbox_from_userid (tmp);
+ addrspec = mailbox_from_userid (tmp, 0);
xfree (tmp);
}
else
- addrspec = mailbox_from_userid (userid);
+ addrspec = mailbox_from_userid (userid, 0);
if (!addrspec)
{
log_error (_("\"%s\" is not a proper mail address\n"), userid);
@@ -497,24 +640,41 @@ command_supported (char *userid)
}
/* Get the submission address. */
- err = wkd_get_submission_address (addrspec, &submission_to);
- if (err)
+ err = get_policy_and_sa (addrspec, 1, &policy, &submission_to);
+ if (err || !submission_to)
{
- if (gpg_err_code (err) == GPG_ERR_NO_DATA
- || gpg_err_code (err) == GPG_ERR_UNKNOWN_HOST)
+ if (!submission_to
+ || gpg_err_code (err) == GPG_ERR_FALSE
+ || gpg_err_code (err) == GPG_ERR_NO_DATA
+ || gpg_err_code (err) == GPG_ERR_UNKNOWN_HOST
+ )
{
- if (opt.verbose)
- log_info ("provider for '%s' does NOT support WKS (%s)\n",
- addrspec, gpg_strerror (err));
+ /* FALSE is returned if we already figured out that even the
+ * Web Key Directory is not supported and thus printed an
+ * error message. */
+ if (opt.verbose && gpg_err_code (err) != GPG_ERR_FALSE
+ && !opt.with_colons)
+ {
+ if (gpg_err_code (err) == GPG_ERR_NO_DATA)
+ log_info ("provider for '%s' does NOT support WKS\n",
+ addrspec);
+ else
+ log_info ("provider for '%s' does NOT support WKS (%s)\n",
+ addrspec, gpg_strerror (err));
+ }
err = gpg_error (GPG_ERR_FALSE);
- log_inc_errorcount ();
+ if (!opt.with_colons)
+ log_inc_errorcount ();
}
goto leave;
}
- if (opt.verbose)
+
+ if (opt.verbose && !opt.with_colons)
log_info ("provider for '%s' supports WKS\n", addrspec);
leave:
+ wks_free_policy (policy);
+ xfree (policy);
xfree (submission_to);
xfree (addrspec);
return err;
@@ -534,7 +694,7 @@ command_check (char *userid)
uidinfo_list_t sl;
int found = 0;
- addrspec = mailbox_from_userid (userid);
+ addrspec = mailbox_from_userid (userid, 0);
if (!addrspec)
{
log_error (_("\"%s\" is not a proper mail address\n"), userid);
@@ -628,7 +788,7 @@ command_send (const char *fingerprint, const char *userid)
estream_t keyenc = NULL;
char *submission_to = NULL;
mime_maker_t mime = NULL;
- struct policy_flags_s policy;
+ policy_flags_t policy = NULL;
int no_encrypt = 0;
int posteo_hack = 0;
const char *domain;
@@ -636,8 +796,6 @@ command_send (const char *fingerprint, const char *userid)
uidinfo_list_t uid, thisuid;
time_t thistime;
- memset (&policy, 0, sizeof policy);
-
if (classify_user_id (fingerprint, &desc, 1)
|| !(desc.mode == KEYDB_SEARCH_MODE_FPR
|| desc.mode == KEYDB_SEARCH_MODE_FPR20))
@@ -647,7 +805,7 @@ command_send (const char *fingerprint, const char *userid)
goto leave;
}
- addrspec = mailbox_from_userid (userid);
+ addrspec = mailbox_from_userid (userid, 0);
if (!addrspec)
{
log_error (_("\"%s\" is not a proper mail address\n"), userid);
@@ -665,62 +823,26 @@ command_send (const char *fingerprint, const char *userid)
/* Get the submission address. */
if (fake_submission_addr)
{
+ policy = xcalloc (1, sizeof *policy);
submission_to = xstrdup (fake_submission_addr);
err = 0;
}
else
{
- /* We first try to get the submission address from the policy
- * file (this is the new method). If both are available we
- * check that they match and print a warning if not. In the
- * latter case we keep on using the one from the
- * submission-address file. */
- estream_t mbuf;
-
- err = wkd_get_policy_flags (addrspec, &mbuf);
- if (err && gpg_err_code (err) != GPG_ERR_NO_DATA)
- {
- log_error ("error reading policy flags for '%s': %s\n",
- domain, gpg_strerror (err));
- goto leave;
- }
- if (mbuf)
- {
- err = wks_parse_policy (&policy, mbuf, 1);
- es_fclose (mbuf);
- if (err)
- goto leave;
- }
-
- err = wkd_get_submission_address (addrspec, &submission_to);
- if (err && !policy.submission_address)
- {
- log_error (_("error looking up submission address for domain '%s'"
- ": %s\n"), domain, gpg_strerror (err));
- if (gpg_err_code (err) == GPG_ERR_NO_DATA)
- log_error (_("this domain probably doesn't support WKS.\n"));
- goto leave;
- }
-
- if (submission_to && policy.submission_address
- && ascii_strcasecmp (submission_to, policy.submission_address))
- log_info ("Warning: different submission addresses (sa=%s, po=%s)\n",
- submission_to, policy.submission_address);
-
+ err = get_policy_and_sa (addrspec, 0, &policy, &submission_to);
+ if (err)
+ goto leave;
if (!submission_to)
{
- submission_to = xtrystrdup (policy.submission_address);
- if (!submission_to)
- {
- err = gpg_error_from_syserror ();
- goto leave;
- }
+ log_error (_("this domain probably doesn't support WKS.\n"));
+ err = gpg_error (GPG_ERR_NO_DATA);
+ goto leave;
}
}
log_info ("submitting request to '%s'\n", submission_to);
- if (policy.auth_submit)
+ if (policy->auth_submit)
log_info ("no confirmation required for '%s'\n", addrspec);
/* In case the key has several uids with the same addr-spec we will
@@ -738,8 +860,7 @@ command_send (const char *fingerprint, const char *userid)
{
if (!uid->mbox)
continue; /* Should not happen anyway. */
- if (policy.mailbox_only
- && ascii_strcasecmp (uid->uid, uid->mbox))
+ if (policy->mailbox_only && ascii_strcasecmp (uid->uid, uid->mbox))
continue; /* UID has more than just the mailbox. */
if (uid->created > thistime)
{
@@ -770,7 +891,7 @@ command_send (const char *fingerprint, const char *userid)
key = newkey;
}
- if (policy.mailbox_only
+ if (policy->mailbox_only
&& (!thisuid->mbox || ascii_strcasecmp (thisuid->uid, thisuid->mbox)))
{
log_info ("Warning: policy requires 'mailbox-only'"
@@ -791,7 +912,7 @@ command_send (const char *fingerprint, const char *userid)
/* Hack to support posteo but let them disable this by setting the
* new policy-version flag. */
- if (policy.protocol_version < 3
+ if (policy->protocol_version < 3
&& !ascii_strcasecmp (domain, "posteo.de"))
{
log_info ("Warning: Using draft-1 method for domain '%s'\n", domain);
@@ -908,7 +1029,8 @@ command_send (const char *fingerprint, const char *userid)
free_uidinfo_list (uidlist);
es_fclose (keyenc);
es_fclose (key);
- wks_free_policy (&policy);
+ wks_free_policy (policy);
+ xfree (policy);
xfree (addrspec);
return err;
}
diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c
index a5881557f..1b533124a 100644
--- a/tools/gpg-wks-server.c
+++ b/tools/gpg-wks-server.c
@@ -58,6 +58,7 @@ enum cmd_and_opt_values
oQuiet = 'q',
oVerbose = 'v',
oOutput = 'o',
+ oDirectory = 'C',
oDebug = 500,
@@ -108,6 +109,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_s (oGpgProgram, "gpg", "@"),
ARGPARSE_s_n (oSend, "send", "send the mail using sendmail"),
ARGPARSE_s_s (oOutput, "output", "|FILE|write the mail to FILE"),
+ ARGPARSE_s_s (oDirectory, "directory", "|DIR|use DIR as top directory"),
ARGPARSE_s_s (oFrom, "from", "|ADDR|use ADDR as the default sender"),
ARGPARSE_s_s (oHeader, "header" ,
"|NAME=VALUE|add \"NAME: VALUE\" as header to all mails"),
@@ -225,6 +227,9 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
case oGpgProgram:
opt.gpg_program = pargs->r.ret_str;
break;
+ case oDirectory:
+ opt.directory = pargs->r.ret_str;
+ break;
case oFrom:
opt.default_from = pargs->r.ret_str;
break;
@@ -350,6 +355,7 @@ main (int argc, char **argv)
{
log_error ("directory '%s' has too relaxed permissions\n",
opt.directory);
+ log_info ("Fix by running: chmod o-rw '%s'\n", opt.directory);
exit (2);
}
}
@@ -1667,7 +1673,7 @@ command_receive_cb (void *opaque, const char *mediatype,
-/* Return a list of all configured domains. ECh list element is the
+/* Return a list of all configured domains. Each list element is the
* top directory for the domain. To figure out the actual domain
* name strrchr(name, '/') can be used. */
static gpg_error_t
@@ -1946,7 +1952,17 @@ command_list_domains (void)
if (!fp)
{
err = gpg_error_from_syserror ();
- if (gpg_err_code (err) != GPG_ERR_ENOENT)
+ if (gpg_err_code (err) == GPG_ERR_ENOENT)
+ {
+ fp = es_fopen (fname, "w");
+ if (!fp)
+ log_error ("domain %s: can't create policy file: %s\n",
+ domain, gpg_strerror (err));
+ else
+ es_fclose (fp);
+ fp = NULL;
+ }
+ else
log_error ("domain %s: error in policy file: %s\n",
domain, gpg_strerror (err));
}
@@ -1955,17 +1971,8 @@ command_list_domains (void)
struct policy_flags_s policy;
err = wks_parse_policy (&policy, fp, 0);
es_fclose (fp);
- if (!err)
- {
- struct policy_flags_s empty_policy;
- memset (&empty_policy, 0, sizeof empty_policy);
- if (!memcmp (&empty_policy, &policy, sizeof policy))
- log_error ("domain %s: empty policy file\n", domain);
- }
wks_free_policy (&policy);
}
-
-
}
err = 0;
@@ -2013,7 +2020,7 @@ command_install_key (const char *fname, const char *userid)
char *huname = NULL;
int any;
- addrspec = mailbox_from_userid (userid);
+ addrspec = mailbox_from_userid (userid, 0);
if (!addrspec)
{
log_error ("\"%s\" is not a proper mail address\n", userid);
@@ -2146,7 +2153,7 @@ fname_from_userid (const char *userid, char **r_fname, char **r_addrspec)
if (r_addrspec)
*r_addrspec = NULL;
- addrspec = mailbox_from_userid (userid);
+ addrspec = mailbox_from_userid (userid, 0);
if (!addrspec)
{
if (opt.verbose)
diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h
index 1b91b6504..fba73f085 100644
--- a/tools/gpg-wks.h
+++ b/tools/gpg-wks.h
@@ -36,6 +36,7 @@ struct
unsigned int debug;
int quiet;
int use_sendmail;
+ int with_colons;
const char *output;
const char *gpg_program;
const char *directory;
diff --git a/tools/gpg-zip.in b/tools/gpg-zip.in
deleted file mode 100644
index 48c4766b1..000000000
--- a/tools/gpg-zip.in
+++ /dev/null
@@ -1,148 +0,0 @@
-#!/bin/sh
-
-# gpg-archive - gpg-ized tar using the same format as PGP's PGP Zip.
-# Copyright (C) 2005 Free Software Foundation, Inc.
-#
-# This file is part of GnuPG.
-#
-# GnuPG is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# GnuPG is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
-# Despite the name, PGP Zip format is actually an OpenPGP-wrapped tar
-# file. To be compatible with PGP itself, this must be a USTAR format
-# tar file. Unclear on whether there is a distinction here between
-# the GNU or POSIX variant of USTAR.
-
-VERSION=@VERSION@
-TAR=@TAR@
-GPG=gpg
-
-usage="\
-Usage: gpg-zip [--help] [--version] [--encrypt] [--decrypt] [--symmetric]
- [--list-archive] [--output FILE] [--gpg GPG] [--gpg-args ARGS]
- [--tar TAR] [--tar-args ARGS] filename1 [filename2, ...]
- directory1 [directory2, ...]
-
-Encrypt or sign files into an archive."
-
-tar_verbose_opt="v"
-
-while test $# -gt 0 ; do
- case $1 in
- -h | --help | --h*)
- echo "$usage"
- exit 0
- ;;
- --list-archive)
- list=yes
- create=no
- unpack=no
- shift
- ;;
- --encrypt | -e)
- gpg_args="$gpg_args --encrypt"
- list=no
- create=yes
- unpack=no
- shift
- ;;
- --decrypt | -d)
- gpg_args="$gpg_args --decrypt"
- list=no
- create=no
- unpack=yes
- shift
- ;;
- --symmetric | -c)
- gpg_args="$gpg_args --symmetric"
- list=no
- create=yes
- unpack=no
- shift
- ;;
- --sign | -s)
- gpg_args="$gpg_args --sign"
- list=no
- create=yes
- unpack=no
- shift
- ;;
- --recipient | -r)
- gpg_args="$gpg_args --recipient $2"
- shift
- shift
- ;;
- --local-user | -u)
- gpg_args="$gpg_args --local-user $2"
- shift
- shift
- ;;
- --output | -o)
- gpg_args="$gpg_args --output $2"
- shift
- shift
- ;;
- --version)
- echo "gpg-zip (GnuPG) $VERSION"
- exit 0
- ;;
- --gpg)
- GPG=$2
- shift
- shift
- ;;
- --gpg-args)
- gpg_args="$gpg_args $2"
- shift
- shift
- ;;
- --tar)
- TAR=$2
- shift
- shift
- ;;
- --tar-args)
- tar_args="$tar_args $2"
- shift
- shift
- ;;
- --quiet)
- tar_verbose_opt=""
- shift
- ;;
- --)
- shift
- break
- ;;
- -*)
- echo "$usage" 1>&2
- exit 1
- ;;
- *)
- break
- ;;
- esac
-done
-
-if test x$create = xyes ; then
-# echo "$TAR $tar_args -cf - "$@" | $GPG --set-filename x.tar $gpg_args" 1>&2
- $TAR $tar_args -cf - "$@" | $GPG --set-filename x.tar $gpg_args
-elif test x$list = xyes ; then
-# echo "cat \"$1\" | $GPG $gpg_args | $TAR $tar_args -tf -" 1>&2
- cat "$1" | $GPG $gpg_args | $TAR $tar_args -tf -
-elif test x$unpack = xyes ; then
-# echo "cat \"$1\" | $GPG $gpg_args | $TAR $tar_args -xvf -" 1>&2
- cat "$1" | $GPG $gpg_args | $TAR $tar_args -x${tar_verbose_opt}f -
-else
- echo "$usage" 1>&2
- exit 1
-fi
diff --git a/tools/gpgconf.c b/tools/gpgconf.c
index 59085d8b5..df3ae8cab 100644
--- a/tools/gpgconf.c
+++ b/tools/gpgconf.c
@@ -823,7 +823,7 @@ main (int argc, char **argv)
;
else if (rmdir (socketdir))
{
- /* If the director is not empty we first try to delet
+ /* If the director is not empty we first try to delete
* socket files. */
err = gpg_error_from_syserror ();
if (gpg_err_code (err) == GPG_ERR_ENOTEMPTY
diff --git a/tools/gpgtar.h b/tools/gpgtar.h
index 8cbe80bbb..28d3d88b1 100644
--- a/tools/gpgtar.h
+++ b/tools/gpgtar.h
@@ -88,7 +88,7 @@ typedef enum
} typeflag_t;
-/* The internal represenation of a TAR header. */
+/* The internal representation of a TAR header. */
struct tar_header_s;
typedef struct tar_header_s *tar_header_t;
struct tar_header_s
diff --git a/tools/mime-maker.c b/tools/mime-maker.c
index 0edc14d78..91eab8258 100644
--- a/tools/mime-maker.c
+++ b/tools/mime-maker.c
@@ -25,14 +25,10 @@
#include "../common/util.h"
#include "../common/zb32.h"
+#include "rfc822parse.h"
#include "mime-maker.h"
-/* All valid characters in a header name. */
-#define HEADER_NAME_CHARS ("abcdefghijklmnopqrstuvwxyz" \
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
- "-01234567890")
-
/* An object to store an header. Also used for a list of headers. */
struct header_s
{
@@ -269,38 +265,6 @@ ensure_part (mime_maker_t ctx, part_t *r_parent)
}
-/* Transform a header name into a standard capitalized format.
- * "Content-Type". Conversion stops at the colon. */
-static void
-capitalize_header_name (char *name)
-{
- unsigned char *p = name;
- int first = 1;
-
- /* Special cases first. */
- if (!ascii_strcasecmp (name, "MIME-Version"))
- {
- strcpy (name, "MIME-Version");
- return;
- }
-
- /* Regular cases. */
- for (; *p && *p != ':'; p++)
- {
- if (*p == '-')
- first = 1;
- else if (first)
- {
- if (*p >= 'a' && *p <= 'z')
- *p = *p - 'a' + 'A';
- first = 0;
- }
- else if (*p >= 'A' && *p <= 'Z')
- *p = *p - 'A' + 'a';
- }
-}
-
-
/* Check whether a header with NAME has already been set into PART.
* NAME must be in canonical capitalized format. Return true or
* false. */
@@ -344,17 +308,14 @@ add_header (part_t part, const char *name, const char *value)
memcpy (hdr->name, name, namelen);
hdr->name[namelen] = 0;
- /* Check that the header name is valid. We allow all lower and
- * uppercase letters and, except for the first character, digits and
- * the dash. */
- if (strspn (hdr->name, HEADER_NAME_CHARS) != namelen
- || strchr ("-0123456789", *hdr->name))
+ /* Check that the header name is valid. */
+ if (!rfc822_valid_header_name_p (hdr->name))
{
xfree (hdr);
return gpg_error (GPG_ERR_INV_NAME);
}
- capitalize_header_name (hdr->name);
+ rfc822_capitalize_header_name (hdr->name);
hdr->value = xtrystrdup (value);
if (!hdr->value)
{
diff --git a/tools/mime-parser.c b/tools/mime-parser.c
index a151dc65e..98f27105c 100644
--- a/tools/mime-parser.c
+++ b/tools/mime-parser.c
@@ -50,7 +50,7 @@ struct mime_parser_context_s
{
void *cookie; /* Cookie passed to all callbacks. */
- /* The callback to announce the transation from header to body. */
+ /* The callback to announce the transition from header to body. */
gpg_error_t (*t2body) (void *cookie, int level);
/* The callback to announce a new part. */
diff --git a/tools/no-libgcrypt.c b/tools/no-libgcrypt.c
index 873996889..3b577567a 100644
--- a/tools/no-libgcrypt.c
+++ b/tools/no-libgcrypt.c
@@ -114,7 +114,7 @@ gcry_free (void *a)
/* We need this dummy because exechelp.c uses gcry_control to
- terminate the secure memeory. */
+ terminate the secure memory. */
gcry_error_t
gcry_control (enum gcry_ctl_cmds cmd, ...)
{
diff --git a/tools/rfc822parse.c b/tools/rfc822parse.c
index e8cdb0215..f1e95bd34 100644
--- a/tools/rfc822parse.c
+++ b/tools/rfc822parse.c
@@ -41,6 +41,12 @@
#include "rfc822parse.h"
+/* All valid characters in a header name. */
+#define HEADER_NAME_CHARS ("abcdefghijklmnopqrstuvwxyz" \
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
+ "-01234567890")
+
+
enum token_type
{
tSPACE,
@@ -90,7 +96,7 @@ struct rfc822parse_context
void *callback_value;
int callback_error;
int in_body;
- int in_preamble; /* Wether we are before the first boundary. */
+ int in_preamble; /* Whether we are before the first boundary. */
part_t parts; /* The tree of parts. */
part_t current_part; /* Whom we are processing (points into parts). */
const char *boundary; /* Current boundary. */
@@ -131,28 +137,31 @@ lowercase_string (unsigned char *string)
*string = *string - 'A' + 'a';
}
-/* Transform a header name into a standard capitalized format; i.e
- "Content-Type". Conversion stops at the colon. As usual we don't
- use the localized versions of ctype.h.
- */
-static void
-capitalize_header_name (unsigned char *name)
+
+static int
+my_toupper (int c)
{
- int first = 1;
+ if (c >= 'a' && c <= 'z')
+ c &= ~0x20;
+ return c;
+}
+
+/* This is the same as ascii_strcasecmp. */
+static int
+my_strcasecmp (const char *a, const char *b)
+{
+ if (a == b)
+ return 0;
- for (; *name && *name != ':'; name++)
- if (*name == '-')
- first = 1;
- else if (first)
- {
- if (*name >= 'a' && *name <= 'z')
- *name = *name - 'a' + 'A';
- first = 0;
- }
- else if (*name >= 'A' && *name <= 'Z')
- *name = *name - 'A' + 'a';
+ for (; *a && *b; a++, b++)
+ {
+ if (*a != *b && my_toupper(*a) != my_toupper(*b))
+ break;
+ }
+ return *a == *b? 0 : (my_toupper (*a) - my_toupper (*b));
}
+
#ifndef HAVE_STPCPY
static char *
my_stpcpy (char *a,const char *b)
@@ -167,7 +176,7 @@ my_stpcpy (char *a,const char *b)
#endif
-/* If a callback has been registerd, call it for the event of type
+/* If a callback has been registered, call it for the event of type
EVENT. */
static int
do_callback (rfc822parse_t msg, rfc822parse_event_t event)
@@ -228,6 +237,62 @@ release_handle_data (rfc822parse_t msg)
}
+/* Check that the header name is valid. We allow all lower and
+ * uppercase letters and, except for the first character, digits and
+ * the dash. The check stops at the first colon or at string end.
+ * Returns true if the name is valid. */
+int
+rfc822_valid_header_name_p (const char *name)
+{
+ const char *s;
+ size_t namelen;
+
+ if ((s=strchr (name, ':')))
+ namelen = s - name;
+ else
+ namelen = strlen (name);
+
+ if (!namelen
+ || strspn (name, HEADER_NAME_CHARS) != namelen
+ || strchr ("-0123456789", *name))
+ return 0;
+ return 1;
+}
+
+
+/* Transform a header NAME into a standard capitalized format.
+ * Conversion stops at the colon. */
+void
+rfc822_capitalize_header_name (char *name)
+{
+ unsigned char *p = name;
+ int first = 1;
+
+ /* Special cases first. */
+ if (!my_strcasecmp (name, "MIME-Version"))
+ {
+ strcpy (name, "MIME-Version");
+ return;
+ }
+
+ /* Regular cases. */
+ for (; *p && *p != ':'; p++)
+ {
+ if (*p == '-')
+ first = 1;
+ else if (first)
+ {
+ if (*p >= 'a' && *p <= 'z')
+ *p = *p - 'a' + 'A';
+ first = 0;
+ }
+ else if (*p >= 'A' && *p <= 'Z')
+ *p = *p - 'A' + 'a';
+ }
+}
+
+
+
/* Create a new parsing context for an entire rfc822 message and
return it. CB and CB_VALUE may be given to callback for certain
events. NULL is returned on error with errno set appropriately. */
@@ -432,7 +497,7 @@ insert_header (rfc822parse_t msg, const unsigned char *line, size_t length)
/* Transform a field name into canonical format. */
if (!hdr->cont && strchr (line, ':'))
- capitalize_header_name (hdr->line);
+ rfc822_capitalize_header_name (hdr->line);
*msg->current_part->hdr_lines_tail = hdr;
msg->current_part->hdr_lines_tail = &hdr->next;
@@ -578,7 +643,7 @@ rfc822parse_get_field (rfc822parse_t msg, const char *name, int which,
/****************
* Enumerate all header. Caller has to provide the address of a pointer
- * which has to be initialzed to NULL, the caller should then never change this
+ * which has to be initialized to NULL, the caller should then never change this
* pointer until he has closed the enumeration by passing again the address
* of the pointer but with msg set to NULL.
* The function returns pointers to all the header lines or NULL when
@@ -616,7 +681,7 @@ rfc822parse_enum_header_lines (rfc822parse_t msg, void **context)
* >0 : Retrieve the n-th field
* RPREV may be used to return the predecessor of the returned field;
- * which may be NULL for the very first one. It has to be initialzed
+ * which may be NULL for the very first one. It has to be initialized
* to either NULL in which case the search start at the first header line,
* or it may point to a headerline, where the search should start
*/
@@ -1013,7 +1078,7 @@ is_parameter (TOKEN t)
parse context is valid; NULL is returned in case that attr is not
defined in the header, a missing value is reppresented by an empty string.
- With LOWER_VALUE set to true, a matching field valuebe be
+ With LOWER_VALUE set to true, a matching field value will be
lowercased.
Note, that ATTR should be lowercase.
diff --git a/tools/rfc822parse.h b/tools/rfc822parse.h
index 177d8271a..e2f2bedac 100644
--- a/tools/rfc822parse.h
+++ b/tools/rfc822parse.h
@@ -48,6 +48,8 @@ typedef int (*rfc822parse_cb_t) (void *opaque,
rfc822parse_event_t event,
rfc822parse_t msg);
+int rfc822_valid_header_name_p (const char *name);
+void rfc822_capitalize_header_name (char *name);
rfc822parse_t rfc822parse_open (rfc822parse_cb_t cb, void *opaque_value);
diff --git a/tools/wks-util.c b/tools/wks-util.c
index 3fd824c1a..cf80a25bc 100644
--- a/tools/wks-util.c
+++ b/tools/wks-util.c
@@ -65,7 +65,7 @@ wks_set_status_fd (int fd)
}
-/* Write a status line with code NO followed by the outout of the
+/* Write a status line with code NO followed by the output of the
* printf style FORMAT. The caller needs to make sure that LFs and
* CRs are not printed. */
void
@@ -104,7 +104,7 @@ append_to_uidinfo_list (uidinfo_list_t *list, const char *uid, time_t created)
strcpy (sl->uid, uid);
sl->created = created;
- sl->mbox = mailbox_from_userid (uid);
+ sl->mbox = mailbox_from_userid (uid, 0);
sl->next = NULL;
if (!*list)
*list = sl;
@@ -556,7 +556,7 @@ wks_send_mime (mime_maker_t mime)
/* Parse the policy flags by reading them from STREAM and storing them
- * into FLAGS. If IGNORE_UNKNOWN is iset unknown keywords are
+ * into FLAGS. If IGNORE_UNKNOWN is set unknown keywords are
* ignored. */
gpg_error_t
wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown)