summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS12
-rw-r--r--ChangeLog259
-rw-r--r--LICENSES38
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.in18
-rw-r--r--NEWS46
-rw-r--r--VERSION2
-rw-r--r--aclocal.m459
-rwxr-xr-xconfigure231
-rw-r--r--configure.ac24
-rw-r--r--doc/Makefile.in9
-rw-r--r--doc/defsincdate2
-rw-r--r--doc/gpgme.info162
-rw-r--r--doc/gpgme.info-145
-rw-r--r--doc/gpgme.info-212
-rw-r--r--doc/gpgme.texi40
-rw-r--r--gpgme.spec2
-rw-r--r--lang/Makefile.in4
-rw-r--r--lang/cl/Makefile.in4
-rw-r--r--lang/cl/gpgme.asd2
-rw-r--r--lang/cpp/Makefile.in4
-rw-r--r--lang/cpp/src/Makefile.in4
-rw-r--r--lang/cpp/src/editinteractor.cpp13
-rw-r--r--lang/cpp/src/gpgsignkeyeditinteractor.cpp50
-rw-r--r--lang/cpp/src/gpgsignkeyeditinteractor.h5
-rw-r--r--lang/cpp/src/key.cpp23
-rw-r--r--lang/cpp/src/key.h11
-rw-r--r--lang/cpp/tests/Makefile.in4
-rw-r--r--lang/js/BrowserTestExtension/Makefile.in4
-rw-r--r--lang/js/DemoExtension/Makefile.in4
-rw-r--r--lang/js/Makefile.in4
-rw-r--r--lang/js/src/Makefile.in4
-rw-r--r--lang/python/Makefile.in4
-rw-r--r--lang/python/doc/Makefile.in4
-rw-r--r--lang/python/examples/Makefile.in4
-rw-r--r--lang/python/src/Makefile.in4
-rw-r--r--lang/python/src/core.py12
-rw-r--r--lang/python/tests/Makefile.in9
-rw-r--r--lang/qt/Makefile.in4
-rw-r--r--lang/qt/doc/Doxyfile.in2
-rw-r--r--lang/qt/doc/Makefile.in4
-rw-r--r--lang/qt/src/Makefile.am2
-rw-r--r--lang/qt/src/Makefile.in11
-rw-r--r--lang/qt/src/cryptoconfig.cpp20
-rw-r--r--lang/qt/src/cryptoconfig.h22
-rw-r--r--lang/qt/src/dataprovider.cpp12
-rw-r--r--lang/qt/src/qgpgme_debug.cpp4
-rw-r--r--lang/qt/src/qgpgme_debug.h7
-rw-r--r--lang/qt/src/qgpgmenewcryptoconfig.cpp87
-rw-r--r--lang/qt/src/qgpgmesignkeyjob.cpp137
-rw-r--r--lang/qt/src/qgpgmesignkeyjob.h23
-rw-r--r--lang/qt/src/signkeyjob.h38
-rw-r--r--lang/qt/tests/Makefile.am8
-rw-r--r--lang/qt/tests/Makefile.in41
-rw-r--r--lang/qt/tests/t-trustsignatures.cpp565
-rw-r--r--lang/qt/tests/t-various.cpp132
-rw-r--r--m4/gpg-error.m4119
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.in6
-rw-r--r--src/cJSON.c20
-rw-r--r--src/context.h3
-rw-r--r--src/conversion.c11
-rw-r--r--src/data-identify.c4
-rw-r--r--src/data.c118
-rw-r--r--src/data.h49
-rw-r--r--src/engine-gpg.c39
-rw-r--r--src/export.c1
-rw-r--r--src/gpgme.c12
-rw-r--r--src/gpgme.h.in18
-rw-r--r--src/key.c1
-rw-r--r--src/keylist.c30
-rw-r--r--src/util.h3
-rw-r--r--tests/Makefile.in4
-rw-r--r--tests/gpg/Makefile.am4
-rw-r--r--tests/gpg/Makefile.in46
-rw-r--r--tests/gpg/t-edit-sign.c201
-rw-r--r--tests/gpgsm/Makefile.in10
-rw-r--r--tests/json/Makefile.in10
-rw-r--r--tests/opassuan/Makefile.in4
-rw-r--r--tests/run-decrypt.c34
-rw-r--r--tests/run-keylist.c12
-rw-r--r--tests/run-keysign.c6
-rw-r--r--tests/run-threaded.c3
-rw-r--r--tests/run-verify.c3
84 files changed, 2438 insertions, 594 deletions
diff --git a/AUTHORS b/AUTHORS
index 59831ac..f8cb309 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -9,10 +9,13 @@ License (software): LGPL-2.1-or-later
License (manual+tools): GPL-3.0-or-later
-GPGME is free software. See the files COPYING for copying conditions.
-License copyright years may be listed using range notation, e.g.,
-2000-2013, indicating that every year in the range, inclusive, is a
-copyrightable year that would otherwise be listed individually.
+GPGME is free software. See the files COPYING.LESSER and COPYING for
+copying conditions, , and LICENSES for notices about contributions
+that require these additional notices to be distributed. License
+copyright years may be listed using range notation, e.g., 2000-2013,
+indicating that every year in the range, inclusive, is a copyrightable
+year that would otherwise be listed individually.
+
List of Copyright holders
=========================
@@ -23,6 +26,7 @@ List of Copyright holders
Copyright (C) 2002 Klarälvdalens Datakonsult AB
Copyright (C) 2004-2008 Igor Belyi
Copyright (C) 2002 John Goerzen
+ Copyright (c) 2009 Dave Gamble
Copyright (C) 2014, 2015 Martin Albrecht
Copyright (C) 2015, 2018 Ben McGinnes
Copyright (C) 2015, 2016, 2018
diff --git a/ChangeLog b/ChangeLog
index bd305c5..ba800db 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,262 @@
+2021-06-24 Werner Koch <wk@gnupg.org>
+
+ Release 1.16.0.
+ + commit 1021c8645555502d914afffaa3707609809c9459
+
+
+2021-06-22 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ qt: Extend SignKeyJob to create signatures with expiration date.
+ + commit ac4536990a4fed4a45a0851260c029e69d0cadf6
+ * lang/qt/src/signkeyjob.h (SignKeyJob::setExpirationDate): New.
+ * lang/qt/src/qgpgmesignkeyjob.h, lang/qt/src/qgpgmesignkeyjob.cpp
+ (QGpgMESignKeyJob::setExpirationDate): New.
+ * lang/qt/src/qgpgmesignkeyjob.cpp (QGpgMESignKeyJob::Private): Add
+ member m_expiration.
+ (sign_key): Handle expiration date.
+ (QGpgMESignKeyJob::start): Pass expiration date to sign_key.
+
+ * lang/qt/tests/t-various.cpp
+ (TestVarious::testSignKeyWithoutExpiration,
+ TestVarious::testSignKeyWithExpiration): New.
+ (TestVarious::initTestCase): Add "allow-weak-key-signatures" to
+ gpg.conf.
+
+ core: Allow specifying an expiration date for key signatures.
+ + commit 34d9defc42bacfaf2bb1ce70b2c3f0fdf0a106c3
+ * src/context.h (struct gpgme_context): Add 'cert_expire'.
+ * src/engine-gpg.c (append_args_from_cert_expire): New.
+ (gpg_edit): Set option according to the new flag.
+ * src/gpgme.c (gpgme_release): Free 'cert_expire'.
+ (gpgme_set_ctx_flag, gpgme_get_ctx_flag): Add "cert-expire".
+
+ * tests/gpg/Makefile.am (c_tests): Add new test.
+ (gpg.conf): Write "allow-weak-key-signatures" to gpg.conf.
+ * tests/gpg/t-edit-sign.c: New.
+
+2021-06-21 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ Update NEWS.
+ + commit ab1d4ef580794a86da754d516db35091f6997e2c
+ * NEWS: Add news for recent changes
+
+2021-06-18 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ qt: Add missing }
+ + commit 5340bb7ccfa7086054823fac48d178e6206d66c0
+ * lang/qt/src/qgpgmenewcryptoconfig.cpp (parseURL): Add missing }.
+
+2021-06-17 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ qt: Add some error logging.
+ + commit 72de06417e32bd6573acd0b73a72fcf98232fe81
+ * lang/qt/src/qgpgmenewcryptoconfig.cpp (setURLValueList): Log error
+ if setting config value failed.
+
+ qt: Do not set empty base DN as query of keyserver URL.
+ + commit 1dca8c2b3c6d6aa3dfd4215c911207f08a3bf9f1
+ * lang/qt/src/qgpgmenewcryptoconfig.cpp (parseURL): Only set non-empty
+ base DN as URL query.
+
+ qt: Fix API documentation.
+ + commit 0d03f31e07e683efbdb206cc3407bf222d71d8fe
+ * lang/qt/src/signkeyjob.h (SignKeyJob::start,
+ SignKeyJob::setUserIDsToSign, SignKeyJob::setCheckLevel): Fix
+ documentation of parameters.
+
+2021-06-14 Werner Koch <wk@gnupg.org>
+
+ core: New data flags "io-buffer-size" and "sensitive".
+ + commit fde20940b5ca6986dc12215209e8858601bb0c2e
+ * src/data.c (_gpgme_data_release): Free buffers.
+ (gpgme_data_seek): Adjust from renamed fields.
+ (gpgme_data_set_flag): Implement new flags.
+ (_gpgme_data_inbound_handler): Allow the use of a malloced buffer.
+ (_gpgme_data_outbound_handler): Ditto.
+ * src/data.h (BUFFER_SIZE): Move out of the struct definition.
+ (struct gpgme_data): Remove pending filed and introduce inbound and
+ outbound fields.
+
+ * src/conversion.c (_gpgme_wipememory): New. Taken from GnuPG.
+ * src/cJSON.c (wipememory): Use this here too.
+
+ * tests/run-decrypt.c (main): Add options "--large-buffers" and
+ "--sensitive".
+
+ core: Also detect AuthEnvelopedData (AEAD for CMS)
+ + commit ea290108e4df9f93eda79789d9cde5441d6bdd55
+ * src/data-identify.c (basic_detection): Add OID.
+
+2021-06-10 Andre Heinecke <aheinecke@gnupg.org>
+
+ qt: Flush output after write for QProcess output.
+ + commit b3b75c37e2d3ef313031ceba8063feeccb0583ec
+ * lang/qt/src/dataprovider.cpp (QIODeviceDataProvider::write): Call
+ waitForBytesWritten.
+
+ core,w32: Increase BUFFER_SIZE to 4096.
+ + commit ceb8387460b05de5c8cec6e02950176b09c4f38b
+ * src/data.h (BUFFER_SIZE): Increase to 4096 for Windows.
+
+2021-06-09 Andre Heinecke <aheinecke@gnupg.org>
+
+ qt: Explicitly link libgpg-error.
+ + commit e6095e54718fe2463fb54adf5879d55e2fba4fef
+ * lang/qt/src/Makefile.am (libqgpgme_la_LIBADD): Explicitly link
+ gpg-error.
+
+ core: Explicitly add GPG_ERROR_CFLAGS.
+ + commit 4041e2c62a10a149776a78e9221de6732693dad9
+ * src/Makefile.am (AM_CFLAGS): Add GPG_ERROR_CFLAGS
+
+2021-06-02 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ qt: Add separate logging category for result of config loading.
+ + commit 5bc4e23a57f149c2a7008c1b88ab3d398ce75e9b
+ * lang/qt/src/qgpgme_debug.h: Make include guard match file name.
+ * lang/qt/src/qgpgme_debug.h, lang/qt/src/qgpgme_debug.cpp
+ (QGPGME_CONFIG_LOADING_LOG): New.
+ * lang/qt/src/qgpgmenewcryptoconfig.cpp
+ (QGpgMENewCryptoConfig::reloadConfiguration): Use new logging category.
+
+ core: Fix a few checks for number of fields in keylist result parser.
+ + commit 5512133de4e9bca2defb744e2b42e55b5487d72c
+ * src/keylist.c (keylist_colon_handler): Check for correct number of
+ fields.
+
+2021-06-01 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ qt: Add support for flags in LDAP server options.
+ + commit 27aa7c4a0fc8f7cef6219443cee0d040c2774746
+ * lang/qt/src/qgpgmenewcryptoconfig.cpp (parseURL): Handle extended
+ LDAP server option syntax.
+ (portToString): New.
+ (splitURL): Append flags to LDAP server option.
+
+2021-05-28 Werner Koch <wk@gnupg.org>
+
+ tests: Improve the output of the run-keylist helper.
+ + commit 31eb45f01620d3e8811fe18460c281837bb3359f
+ * tests/run-keylist.c (main): Print all infos from the primary key.
+
+2021-05-27 NIIBE Yutaka <gniibe@fsij.org>
+
+ build: _DARWIN_C_SOURCE should be 1.
+ + commit 367b9e7488601cdf2cbec4d593a235c89f9a4281
+ * configure.ac (*-apple-darwin*): Set _DARWIN_C_SOURCE 1.
+
+ build: Update gpg-error.m4.
+ + commit 792a7e7f04ead7643561439b773e740549340b99
+ * m4/gpg-error.m4: Update from libgpg-error.
+
+2021-05-12 Werner Koch <wk@gnupg.org>
+
+ core: Allow for older compilers.
+ + commit aa98081356b5f7c9ef2422021e05aed01a7e4d46
+ * tests/run-verify.c (main): Remove C99-only syntax.
+ * tests/run-threaded.c (start_keylistings): Ditto.
+
+ core: Make sure to stay ABI compatible.
+ + commit 88db69e1a964c9a36989e36fe5d972548432fb5c
+ * src/gpgme.h.in (struct _gpgme_key_sig): Move trust_scope to the end
+ of the struct.
+
+2021-05-06 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ cpp: Do not close stdout/stderr when destroying EditInteractor.
+ + commit 58a217b108e4c4c92306542bf9f2995254809ffb
+ * lang/cpp/src/editinteractor.cpp (EditInteractor::Private): Initialize
+ members 'state' and 'debug' in-class. Add member 'debugNeedsClosing'.
+ (EditInteractor::Private::Private): Remove members initializers.
+ Remember if 'debug' needs to be closed.
+ (EditInteractor::Private::~Private): Only close 'debug' if it needs to
+ be closed.
+
+2021-05-05 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ qt: Extend SignKeyJob to create trust signatures.
+ + commit f0858e45b0be260730e742643e741547123d4287
+ * lang/qt/src/signkeyjob.h (SignKeyJob::setTrustSignature): New.
+ * lang/qt/src/qgpgmesignkeyjob.h, lang/qt/src/qgpgmesignkeyjob.cpp
+ (QGpgMESignKeyJob::setTrustSignature): New.
+ * lang/qt/src/qgpgmesignkeyjob.cpp (sign_key): Handle trust signatures.
+ (QGpgMESignKeyJob::start): Pass trust signature attributes to sign_key.
+ (QGpgMESignKeyJob::setTrustSignature): New.
+
+ qt: Pimpl QGpgMESignKeyJob.
+ + commit dae01f8185e0f1bc9c65d93078c7ccda0b79611f
+ * lang/qt/src/qgpgmesignkeyjob.h: Remove unneeded includes. Include
+ <memory>.
+ (QGpgMESignKeyJob): Remove all member variables. Add pimpl pointer.
+ * lang/qt/src/qgpgmesignkeyjob.cpp: Include <QString>. Don't include
+ <memory>.
+ (QGpgMESignKeyJob::Private): New.
+ (QGpgMESignKeyJob::QGpgMESignKeyJob): Remove initialization of removed
+ members. Initialize d.
+ (QGpgMESignKeyJob::start, QGpgMESignKeyJob::setUserIDsToSign,
+ QGpgMESignKeyJob::setCheckLevel, QGpgMESignKeyJob::setExportable,
+ QGpgMESignKeyJob::setSigningKey, QGpgMESignKeyJob::setNonRevocable,
+ QGpgMESignKeyJob::setRemark, QGpgMESignKeyJob::setDupeOk): Adapt to move
+ of member variables to pimpl.
+
+ cpp: Add support for trust signatures to sign key edit interactor.
+ + commit a8d7b9d16796efd6f21abaeb43ccaeb2388eb6e4
+ * lang/cpp/src/gpgsignkeyeditinteractor.h,
+ lang/cpp/src/gpgsignkeyeditinteractor.cpp
+ (GpgSignKeyEditInteractor::setTrustSignatureTrust): New.
+ (GpgSignKeyEditInteractor::setTrustSignatureDepth): New.
+ (GpgSignKeyEditInteractor::setTrustSignatureScope): New.
+ * lang/cpp/src/gpgsignkeyeditinteractor.cpp
+ (GpgSignKeyEditInteractor::Private::Private): Initialize new member.
+ (makeTable): Add new transition. Fix typos in existing transitions.
+ (GpgSignKeyEditInteractor::action): Handle SET_TRUST_VALUE,
+ SET_TRUST_DEPTH, and SET_TRUST_REGEXP.
+
+ cpp: Add getters for the attributes of a trust signature.
+ + commit e391a08c6f96cd2d93c49b888459ee3f42058118
+ * lang/cpp/src/key.h (TrustSignatureTrust): New enum.
+ * lang/cpp/src/key.h, lang/cpp/src/key.cpp
+ (UserID::Signature::isTrustSignature): New.
+ (UserID::Signature::trustValue): New.
+ (UserID::Signature::trustDepth): New.
+ (UserID::Signature::trustScope): New.
+
+ core: Extend gpgme_key_sig_t with trust signature members.
+ + commit 276187f6b62a73e92b1c20f589510f80ab9e88d2
+ * src/gpgme.h.in (struct _gpgme_key_sig): Add fields 'trust_depth',
+ 'trust_value', and 'trust_scope'.
+ * src/key.c (gpgme_key_unref): Free trust_scope.
+ * src/keylist.c (keylist_colon_handler): Set the fields.
+ * tests/run-keylist.c (main): Print the fields.
+
+2021-03-11 Werner Koch <wk@gnupg.org>
+
+ doc: Add MIT license notice.
+ + commit 3ffd7bd4039d90cd15fbf76f8c116814bffdab7c
+ * LICENSES: New.
+
+ core: New flag GPGME_KEYSIGN_FORCE.
+ + commit 0821e2b1495e8944a5a1b5ba20ad5f403dde0dd0
+ * src/gpgme.h.in (GPGME_KEYSIGN_FORCE): New.
+ * src/engine-gpg.c (gpg_keysign): Implement.
+
+ * tests/run-keysign.c (show_usage): Add option --force
+
+2021-03-05 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ qt: Add method for getting config entries for components by entry name.
+ + commit fe900a41bf809b263f05d5df21b6ed7fbfb2bbbc
+ * lang/qt/src/cryptoconfig.h, lang/qt/src/cryptoconfig.cpp
+ (CryptoConfig::entry): Move implementation to cpp. Add overload not
+ requiring a group name.
+
+2021-02-01 Werner Koch <wk@gnupg.org>
+
+ core: Remove experimental feature GPGME_EXPORT_MODE_NOUID.
+ + commit c8fd8870b3bf089f99156448b7d1e59c1150f994
+ * src/export.c (export_start): Remove GPGME_EXPORT_MODE_NOUID check.
+ * src/engine-gpg.c (export_common): Ditto.
+
2021-01-08 Werner Koch <wk@gnupg.org>
Release 1.15.1.
diff --git a/LICENSES b/LICENSES
new file mode 100644
index 0000000..acfd614
--- /dev/null
+++ b/LICENSES
@@ -0,0 +1,38 @@
+Additional license notices for GPGME. -*- org -*-
+
+This file contains the copying permission notices for various files in
+the GPGME distribution which are not covered by the GNU Lesser
+General Public License (LGPL) or the GNU General Public License (GPL).
+
+These notices all require that a copy of the notice be included
+in the accompanying documentation and be distributed with binary
+distributions of the code, so be sure to include this file along
+with any binary distributions derived from the GNU C Library.
+
+* MIT License
+
+ For files:
+ - cJSON.c, cJSON.h
+
+#+begin_quote
+ Copyright (c) 2009 Dave Gamble
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a opy of this software and associated documentation files (the
+ "Software"), to eal in the Software without restriction, including
+ without limitation the ights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING ROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#+end_quote
diff --git a/Makefile.am b/Makefile.am
index 7dcf2f3..914d418 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -36,7 +36,7 @@ DISTCHECK_CONFIGURE_FLAGS =
EXTRA_DIST = autogen.sh autogen.rc gpgme.spec.in \
ChangeLog-2011 m4/ChangeLog-2011 \
- conf/whatisthis VERSION
+ conf/whatisthis VERSION LICENSES
if RUN_GPG_TESTS
diff --git a/Makefile.in b/Makefile.in
index a89eca4..bcc36e5 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -238,6 +238,8 @@ am__relativize = \
GZIP_ENV = --best
DIST_ARCHIVES = $(distdir).tar.bz2
DIST_TARGETS = dist-bzip2
+# Exists only to be overridden by the user if desired.
+AM_DISTCHECK_DVI_TARGET = dvi
distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
@@ -454,7 +456,7 @@ ACLOCAL_AMFLAGS = -I m4
DISTCHECK_CONFIGURE_FLAGS =
EXTRA_DIST = autogen.sh autogen.rc gpgme.spec.in \
ChangeLog-2011 m4/ChangeLog-2011 \
- conf/whatisthis VERSION
+ conf/whatisthis VERSION LICENSES
@RUN_GPG_TESTS_FALSE@tests =
@RUN_GPG_TESTS_TRUE@tests = tests
@@ -715,6 +717,10 @@ dist-xz: distdir
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
$(am__post_remove_distdir)
+dist-zstd: distdir
+ tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst
+ $(am__post_remove_distdir)
+
dist-tarZ: distdir
@echo WARNING: "Support for distribution archives compressed with" \
"legacy program 'compress' is deprecated." >&2
@@ -757,6 +763,8 @@ distcheck: dist
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
+ *.tar.zst*) \
+ zstd -dc $(distdir).tar.zst | $(am__untar) ;;\
esac
chmod -R a-w $(distdir)
chmod u+w $(distdir)
@@ -773,7 +781,7 @@ distcheck: dist
$(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=../.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \
- && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
@@ -935,7 +943,7 @@ uninstall-am:
am--refresh check check-am clean clean-cscope clean-generic \
clean-libtool cscope cscopelist-am ctags ctags-am dist \
dist-all dist-bzip2 dist-gzip dist-hook dist-lzip dist-shar \
- dist-tarZ dist-xz dist-zip distcheck distclean \
+ dist-tarZ dist-xz dist-zip dist-zstd distcheck distclean \
distclean-generic distclean-hdr distclean-libtool \
distclean-tags distcleancheck distdir distuninstallcheck dvi \
dvi-am html html-am info info-am install install-am \
diff --git a/NEWS b/NEWS
index f6c2b0d..0cae3f2 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,49 @@
+Noteworthy changes in version 1.16.0 (2021-06-24)
+-------------------------------------------------
+
+ * New context flag "cert-expire". [#5505]
+
+ * New data flags "io-buffer-size" and "sensitive". [#5478]
+
+ * Increase I/O buffer size from 512 to 4k under Windows.
+
+ * cpp,qt: Add support for trust signatures. [#5421]
+
+ * qt: Add support for flags in LDAP server options. [#5217]
+
+ * qt: Fix too high memory consumption due to QProcess. [#5475]
+
+ * qt: Do not set empty base DN as query of keyserver URL. [#5465]
+
+ * qt: Extend SignKeyJob to create signatures with expiration date.
+ [5506]
+
+ * python: New optional parameter filter_signatures for decrypt.
+ [#5292]
+
+ * Interface changes relative to the 1.15.1 release:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ gpgme_set_ctx_flag EXTENDED: New flag 'cert-expire'.
+ cpp: SignKeyJob::setTrustSignature NEW.
+ cpp: TrustSignatureTrust NEW.
+ cpp: GpgSignKeyEditInteractor::setTrustSignatureTrust NEW.
+ cpp: GpgSignKeyEditInteractor::setTrustSignatureDepth NEW.
+ cpp: GpgSignKeyEditInteractor::setTrustSignatureScope NEW.
+ cpp: UserID::Signature::isTrustSignature NEW.
+ cpp: UserID::Signature::trustValue NEW.
+ cpp: UserID::Signature::trustDepth NEW.
+ cpp: UserID::Signature::trustScope NEW.
+ gpgme_key_sig_t EXTENDED: New field 'trust_depth'.
+ gpgme_key_sig_t EXTENDED: New field 'trust_value'.
+ gpgme_key_sig_t EXTENDED: New field 'trust_scope'.
+ GPGME_KEYSIGN_FORCE NEW.
+ qt: CryptoConfig::entry CHANGED: Added overload; deprecated old
+
+ [c=C36/A25/R0 cpp=C19/A13/R0 qt=C13/A6/R0]
+
+ Release-info: https://dev.gnupg.org/T5499
+
+
Noteworthy changes in version 1.15.1 (2021-01-08)
-------------------------------------------------
diff --git a/VERSION b/VERSION
index ace4423..15b989e 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.15.1
+1.16.0
diff --git a/aclocal.m4 b/aclocal.m4
index fe217a1..9427cda 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,6 +1,6 @@
-# generated automatically by aclocal 1.16.1 -*- Autoconf -*-
+# generated automatically by aclocal 1.16.3 -*- Autoconf -*-
-# Copyright (C) 1996-2018 Free Software Foundation, Inc.
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -20,7 +20,7 @@ You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
-# Copyright (C) 2002-2018 Free Software Foundation, Inc.
+# Copyright (C) 2002-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -35,7 +35,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.16'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
-m4_if([$1], [1.16.1], [],
+m4_if([$1], [1.16.3], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
@@ -51,14 +51,14 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.16.1])dnl
+[AM_AUTOMAKE_VERSION([1.16.3])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
-# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -110,7 +110,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
# AM_COND_IF -*- Autoconf -*-
-# Copyright (C) 2008-2018 Free Software Foundation, Inc.
+# Copyright (C) 2008-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -147,7 +147,7 @@ fi[]dnl
# AM_CONDITIONAL -*- Autoconf -*-
-# Copyright (C) 1997-2018 Free Software Foundation, Inc.
+# Copyright (C) 1997-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -178,7 +178,7 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]])
fi])])
-# Copyright (C) 1999-2018 Free Software Foundation, Inc.
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -369,7 +369,7 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
# Generate code to set up dependency tracking. -*- Autoconf -*-
-# Copyright (C) 1999-2018 Free Software Foundation, Inc.
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -408,7 +408,9 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
done
if test $am_rc -ne 0; then
AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
- for automatic dependency tracking. Try re-running configure with the
+ for automatic dependency tracking. If GNU make was not used, consider
+ re-running the configure script with MAKE="gmake" (or whatever is
+ necessary). You can also try re-running configure with the
'--disable-dependency-tracking' option to at least be able to build
the package (albeit without support for automatic dependency tracking).])
fi
@@ -435,7 +437,7 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
# Do all the work for Automake. -*- Autoconf -*-
-# Copyright (C) 1996-2018 Free Software Foundation, Inc.
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -632,7 +634,7 @@ for _am_header in $config_headers :; do
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
-# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -653,7 +655,7 @@ if test x"${install_sh+set}" != xset; then
fi
AC_SUBST([install_sh])])
-# Copyright (C) 2003-2018 Free Software Foundation, Inc.
+# Copyright (C) 2003-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -675,7 +677,7 @@ AC_SUBST([am__leading_dot])])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering
-# Copyright (C) 1996-2018 Free Software Foundation, Inc.
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -710,7 +712,7 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
# Check to see how 'make' treats includes. -*- Autoconf -*-
-# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -753,7 +755,7 @@ AC_SUBST([am__quote])])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
-# Copyright (C) 1997-2018 Free Software Foundation, Inc.
+# Copyright (C) 1997-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -774,12 +776,7 @@ AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then
- case $am_aux_dir in
- *\ * | *\ *)
- MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
- *)
- MISSING="\${SHELL} $am_aux_dir/missing" ;;
- esac
+ MISSING="\${SHELL} '$am_aux_dir/missing'"
fi
# Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then
@@ -792,7 +789,7 @@ fi
# Helper functions for option handling. -*- Autoconf -*-
-# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -821,7 +818,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
-# Copyright (C) 1999-2018 Free Software Foundation, Inc.
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -868,7 +865,7 @@ AC_LANG_POP([C])])
# For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
-# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -887,7 +884,7 @@ AC_DEFUN([AM_RUN_LOG],
# Check to make sure that the build environment is sane. -*- Autoconf -*-
-# Copyright (C) 1996-2018 Free Software Foundation, Inc.
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -968,7 +965,7 @@ AC_CONFIG_COMMANDS_PRE(
rm -f conftest.file
])
-# Copyright (C) 2009-2018 Free Software Foundation, Inc.
+# Copyright (C) 2009-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -1028,7 +1025,7 @@ AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
])
-# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -1056,7 +1053,7 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
-# Copyright (C) 2006-2018 Free Software Foundation, Inc.
+# Copyright (C) 2006-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -1075,7 +1072,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
-# Copyright (C) 2004-2018 Free Software Foundation, Inc.
+# Copyright (C) 2004-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/configure b/configure
index 2c2601b..f307736 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for gpgme 1.15.1.
+# Generated by GNU Autoconf 2.69 for gpgme 1.16.0.
#
# Report bugs to <https://bugs.gnupg.org>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='gpgme'
PACKAGE_TARNAME='gpgme'
-PACKAGE_VERSION='1.15.1'
-PACKAGE_STRING='gpgme 1.15.1'
+PACKAGE_VERSION='1.16.0'
+PACKAGE_STRING='gpgme 1.16.0'
PACKAGE_BUGREPORT='https://bugs.gnupg.org'
PACKAGE_URL=''
@@ -1469,7 +1469,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures gpgme 1.15.1 to adapt to many kinds of systems.
+\`configure' configures gpgme 1.16.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1540,7 +1540,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of gpgme 1.15.1:";;
+ short | recursive ) echo "Configuration of gpgme 1.16.0:";;
esac
cat <<\_ACEOF
@@ -1690,7 +1690,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-gpgme configure 1.15.1
+gpgme configure 1.16.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2520,7 +2520,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by gpgme $as_me 1.15.1, which was
+It was created by gpgme $as_me 1.16.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2884,20 +2884,20 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
# (Interfaces added: AGE++)
# (Interfaces removed: AGE=0)
#
-LIBGPGME_LT_CURRENT=35
-LIBGPGME_LT_AGE=24
-LIBGPGME_LT_REVISION=1
+LIBGPGME_LT_CURRENT=36
+LIBGPGME_LT_AGE=25
+LIBGPGME_LT_REVISION=0
# If there is an ABI break in gpgmepp or qgpgme also bump the
# version in IMPORTED_LOCATION in the GpgmeppConfig-w32.cmake.in.in
-LIBGPGMEPP_LT_CURRENT=18
-LIBGPGMEPP_LT_AGE=12
-LIBGPGMEPP_LT_REVISION=1
+LIBGPGMEPP_LT_CURRENT=19
+LIBGPGMEPP_LT_AGE=13
+LIBGPGMEPP_LT_REVISION=0
-LIBQGPGME_LT_CURRENT=12
-LIBQGPGME_LT_AGE=5
-LIBQGPGME_LT_REVISION=1
+LIBQGPGME_LT_CURRENT=13
+LIBQGPGME_LT_AGE=6
+LIBQGPGME_LT_REVISION=0
################################################
@@ -2922,8 +2922,8 @@ NEED_LIBASSUAN_VERSION=2.4.2
VERSION_MAJOR=1
-VERSION_MINOR=15
-VERSION_MICRO=1
+VERSION_MINOR=16
+VERSION_MICRO=0
ac_aux_dir=
for ac_dir in build-aux "$srcdir"/build-aux; do
@@ -3134,12 +3134,7 @@ program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
am_aux_dir=`cd "$ac_aux_dir" && pwd`
if test x"${MISSING+set}" != xset; then
- case $am_aux_dir in
- *\ * | *\ *)
- MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
- *)
- MISSING="\${SHELL} $am_aux_dir/missing" ;;
- esac
+ MISSING="\${SHELL} '$am_aux_dir/missing'"
fi
# Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then
@@ -3444,7 +3439,7 @@ fi
# Define the identity of the package.
PACKAGE='gpgme'
- VERSION='1.15.1'
+ VERSION='1.16.0'
cat >>confdefs.h <<_ACEOF
@@ -6504,7 +6499,7 @@ test -n "$GITLOG_TO_CHANGELOG" || GITLOG_TO_CHANGELOG="gitlog-to-changelog"
-VERSION_NUMBER=0x010f01
+VERSION_NUMBER=0x011000
# We need to compile and run a program on the build machine. A
@@ -17397,7 +17392,7 @@ case "${host}" in
;;
*-apple-darwin*)
-$as_echo "#define _DARWIN_C_SOURCE 900000L" >>confdefs.h
+$as_echo "#define _DARWIN_C_SOURCE 1" >>confdefs.h
$as_echo "#define _XOPEN_SOURCE 500" >>confdefs.h
@@ -24571,7 +24566,7 @@ ENABLED_LANGUAGES=$enabled_languages
#
# Provide information about the build.
#
-BUILD_REVISION="bb988077"
+BUILD_REVISION="1021c864"
cat >>confdefs.h <<_ACEOF
@@ -24580,7 +24575,7 @@ _ACEOF
BUILD_VERSION=`echo "$PACKAGE_VERSION" | sed 's/\([0-9.]*\).*/\1./'`
-BUILD_VERSION="${BUILD_VERSION}48024"
+BUILD_VERSION="${BUILD_VERSION}4129"
BUILD_FILEVERSION=`echo "${BUILD_VERSION}" | tr . ,`
@@ -25649,32 +25644,7 @@ fi
min_gpg_error_version="$NEED_GPG_ERROR_VERSION"
ok=no
- 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
- # Extract the first word of "gpgrt-config", so it can be a program name with args.
+ # Extract the first word of "gpgrt-config", so it can be a program name with args.
set dummy gpgrt-config; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
@@ -25687,7 +25657,8 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
+as_dummy="$prefix/bin:$PATH"
+for as_dir in $as_dummy
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -25715,20 +25686,79 @@ $as_echo "no" >&6; }
fi
- if test "$GPGRT_CONFIG" = "no"; then
- unset GPGRT_CONFIG
+ if test "$GPGRT_CONFIG" != "no"; then
+ # Determine gpgrt_libdir
+ #
+ # Get the prefix of gpgrt-config assuming it's something like:
+ # <PREFIX>/bin/gpgrt-config
+ gpgrt_prefix=${GPGRT_CONFIG%/*/*}
+ possible_libdir1=${gpgrt_prefix}/lib
+ # Determine by using system libdir-format with CC, it's like:
+ # Normal style: /usr/lib
+ # GNU cross style: /usr/<triplet>/lib
+ # Debian style: /usr/lib/<multiarch-name>
+ # Fedora/openSUSE style: /usr/lib, /usr/lib32 or /usr/lib64
+ # It is assumed that CC is specified to the one of host on cross build.
+ if libdir_candidates=$(${CC:-cc} -print-search-dirs | \
+ sed -n -e "/^libraries/{s/libraries: =//;s/:/\\
+/g;p;}"); then
+ # From the output of -print-search-dirs, select valid pkgconfig dirs.
+ libdir_candidates=$(for dir in $libdir_candidates; do
+ if p=$(cd $dir 2>/dev/null && pwd); then
+ test -d "$p/pkgconfig" && echo $p;
+ fi
+ done)
+
+ for possible_libdir0 in $libdir_candidates; do
+ # possible_libdir0:
+ # Fallback candidate, the one of system-installed (by $CC)
+ # (/usr/<triplet>/lib, /usr/lib/<multiarch-name> or /usr/lib32)
+ # possible_libdir1:
+ # Another candidate, user-locally-installed
+ # (<gpgrt_prefix>/lib)
+ # possible_libdir2
+ # Most preferred
+ # (<gpgrt_prefix>/<triplet>/lib,
+ # <gpgrt_prefix>/lib/<multiarch-name> or <gpgrt_prefix>/lib32)
+ if test "${possible_libdir0##*/}" = "lib"; then
+ possible_prefix0=${possible_libdir0%/lib}
+ possible_prefix0_triplet=${possible_prefix0##*/}
+ if test -z "$possible_prefix0_triplet"; then
+ continue
+ fi
+ possible_libdir2=${gpgrt_prefix}/$possible_prefix0_triplet/lib
+ else
+ possible_prefix0=${possible_libdir0%%/lib*}
+ possible_libdir2=${gpgrt_prefix}${possible_libdir0#$possible_prefix0}
+ fi
+ if test -f ${possible_libdir2}/pkgconfig/gpg-error.pc; then
+ gpgrt_libdir=${possible_libdir2}
+ elif test -f ${possible_libdir1}/pkgconfig/gpg-error.pc; then
+ gpgrt_libdir=${possible_libdir1}
+ elif test -f ${possible_libdir0}/pkgconfig/gpg-error.pc; then
+ gpgrt_libdir=${possible_libdir0}
+ fi
+ if test -n "$gpgrt_libdir"; then break; fi
+ done
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"
- { $as_echo "$as_me:${as_lineno-$LINENO}: Use gpgrt-config with $gpgrt_libdir as gpg-error-config" >&5
-$as_echo "$as_me: Use gpgrt-config with $gpgrt_libdir as gpg-error-config" >&6;}
- gpg_error_config_version=`$GPG_ERROR_CONFIG --modversion`
- else
- unset GPGRT_CONFIG
- fi
+ # When we cannot determine system libdir-format, use this:
+ gpgrt_libdir=${possible_libdir1}
fi
else
+ unset GPGRT_CONFIG
+ fi
+
+ if test -n "$gpgrt_libdir"; then
+ GPGRT_CONFIG="$GPGRT_CONFIG --libdir=$gpgrt_libdir"
+ if $GPGRT_CONFIG gpg-error >/dev/null 2>&1; then
+ GPG_ERROR_CONFIG="$GPGRT_CONFIG gpg-error"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Use gpgrt-config with $gpgrt_libdir as gpg-error-config" >&5
+$as_echo "$as_me: Use gpgrt-config with $gpgrt_libdir as gpg-error-config" >&6;}
+ gpg_error_config_version=`$GPG_ERROR_CONFIG --modversion`
+ else
+ unset GPGRT_CONFIG
+ fi
+ elif test "$GPG_ERROR_CONFIG" != "no"; then
gpg_error_config_version=`$GPG_ERROR_CONFIG --version`
fi
if test "$GPG_ERROR_CONFIG" != "no"; then
@@ -25749,63 +25779,6 @@ $as_echo "$as_me: Use gpgrt-config with $gpgrt_libdir as gpg-error-config" >&6;}
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
- # Extract the first word of "gpgrt-config", so it can be a program name with args.
-set dummy gpgrt-config; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_GPGRT_CONFIG+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- case $GPGRT_CONFIG in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_GPGRT_CONFIG="$GPGRT_CONFIG" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_GPGRT_CONFIG="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
- test -z "$ac_cv_path_GPGRT_CONFIG" && ac_cv_path_GPGRT_CONFIG="no"
- ;;
-esac
-fi
-GPGRT_CONFIG=$ac_cv_path_GPGRT_CONFIG
-if test -n "$GPGRT_CONFIG"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GPGRT_CONFIG" >&5
-$as_echo "$GPGRT_CONFIG" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- 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"
- { $as_echo "$as_me:${as_lineno-$LINENO}: Use gpgrt-config with $gpgrt_libdir as gpg-error-config" >&5
-$as_echo "$as_me: Use gpgrt-config with $gpgrt_libdir as gpg-error-config" >&6;}
- else
- unset GPGRT_CONFIG
- fi
- fi
- fi
- fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GPG Error - version >= $min_gpg_error_version" >&5
$as_echo_n "checking for GPG Error - version >= $min_gpg_error_version... " >&6; }
@@ -26955,7 +26928,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by gpgme $as_me 1.15.1, which was
+This file was extended by gpgme $as_me 1.16.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -27021,7 +26994,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-gpgme config.status 1.15.1
+gpgme config.status 1.16.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -28336,7 +28309,9 @@ $as_echo X/"$am_mf" |
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "Something went wrong bootstrapping makefile fragments
- for automatic dependency tracking. Try re-running configure with the
+ for automatic dependency tracking. If GNU make was not used, consider
+ re-running the configure script with MAKE=\"gmake\" (or whatever is
+ necessary). You can also try re-running configure with the
'--disable-dependency-tracking' option to at least be able to build
the package (albeit without support for automatic dependency tracking).
See \`config.log' for more details" "$LINENO" 5; }
@@ -29345,7 +29320,7 @@ fi
echo "
GPGME v${VERSION} has been configured as follows:
- Revision: bb988077 (48024)
+ Revision: 1021c864 (4129)
Platform: $host
UI Server: $uiserver
diff --git a/configure.ac b/configure.ac
index 628e5ff..4d32366 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,8 +31,8 @@ min_automake_version="1.14"
# for the LT versions.
m4_define([mym4_package],[gpgme])
m4_define([mym4_major], [1])
-m4_define([mym4_minor], [15])
-m4_define([mym4_micro], [1])
+m4_define([mym4_minor], [16])
+m4_define([mym4_micro], [0])
# Below is m4 magic to extract and compute the git revision number,
# the decimalized short revision number, a beta version string and a
@@ -53,20 +53,20 @@ AC_INIT([mym4_package],[mym4_version],[https://bugs.gnupg.org])
# (Interfaces added: AGE++)
# (Interfaces removed: AGE=0)
#
-LIBGPGME_LT_CURRENT=35
-LIBGPGME_LT_AGE=24
-LIBGPGME_LT_REVISION=1
+LIBGPGME_LT_CURRENT=36
+LIBGPGME_LT_AGE=25
+LIBGPGME_LT_REVISION=0
# If there is an ABI break in gpgmepp or qgpgme also bump the
# version in IMPORTED_LOCATION in the GpgmeppConfig-w32.cmake.in.in
-LIBGPGMEPP_LT_CURRENT=18
-LIBGPGMEPP_LT_AGE=12
-LIBGPGMEPP_LT_REVISION=1
+LIBGPGMEPP_LT_CURRENT=19
+LIBGPGMEPP_LT_AGE=13
+LIBGPGMEPP_LT_REVISION=0
-LIBQGPGME_LT_CURRENT=12
-LIBQGPGME_LT_AGE=5
-LIBQGPGME_LT_REVISION=1
+LIBQGPGME_LT_CURRENT=13
+LIBQGPGME_LT_AGE=6
+LIBQGPGME_LT_REVISION=0
################################################
AC_SUBST(LIBGPGME_LT_CURRENT)
@@ -198,7 +198,7 @@ case "${host}" in
have_ld_version_script=yes
;;
*-apple-darwin*)
- AC_DEFINE(_DARWIN_C_SOURCE, 900000L,
+ AC_DEFINE(_DARWIN_C_SOURCE, 1,
Expose all libc features (__DARWIN_C_FULL).)
AC_DEFINE(_XOPEN_SOURCE, 500, Activate POSIX interface on MacOS X)
;;
diff --git a/doc/Makefile.in b/doc/Makefile.in
index f9e1bec..5f4bebe 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -660,7 +660,8 @@ installdirs:
done
install: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-am
-install-exec: install-exec-am
+install-exec: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-am
install-data: install-data-am
uninstall: uninstall-am
@@ -852,7 +853,7 @@ ps-am: $(PSS)
uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \
uninstall-pdf-am uninstall-ps-am
-.MAKE: all check install install-am install-strip
+.MAKE: all check install install-am install-exec install-strip
.PHONY: all all-am check check-am clean clean-aminfo clean-generic \
clean-libtool cscopelist-am ctags-am dist-hook dist-info \
diff --git a/doc/defsincdate b/doc/defsincdate
index 0f4c290..683840f 100644
--- a/doc/defsincdate
+++ b/doc/defsincdate
@@ -1 +1 @@
-1603972630
+1624372503
diff --git a/doc/gpgme.info b/doc/gpgme.info
index adf62a4..0008e70 100644
--- a/doc/gpgme.info
+++ b/doc/gpgme.info
@@ -19,8 +19,8 @@ END-INFO-DIR-ENTRY
This file documents the GPGME library.
- This is Edition 1.14.1-beta35, last updated 13 December 2019, of ‘The
-‘GnuPG Made Easy’ Reference Manual’, for Version 1.14.1-beta35.
+ This is Edition 1.15.2-beta35, last updated 13 December 2019, of ‘The
+‘GnuPG Made Easy’ Reference Manual’, for Version 1.15.2-beta35.
Copyright © 2002–2008, 2010, 2012–2018 g10 Code GmbH.
@@ -38,7 +38,7 @@ Public License for more details.

Indirect:
gpgme.info-1: 1688
-gpgme.info-2: 301751
+gpgme.info-2: 303542

Tag Table:
(Indirect)
@@ -82,84 +82,84 @@ Node: Destroying Data Buffers80270
Node: Manipulating Data Buffers81777
Node: Data Buffer I/O Operations82269
Node: Data Buffer Meta-Data84642
-Node: Data Buffer Convenience89161
-Node: Contexts91381
-Node: Creating Contexts92500
-Node: Destroying Contexts93347
-Node: Result Management93686
-Node: Context Attributes95267
-Node: Protocol Selection96434
-Node: Crypto Engine97480
-Node: Setting the Sender99369
-Node: ASCII Armor100882
-Node: Text Mode101511
-Node: Offline Mode102445
-Node: Pinentry Mode103943
-Node: Included Certificates105837
-Node: Key Listing Mode107283
-Node: Passphrase Callback112407
-Node: Progress Meter Callback115969
-Node: Status Message Callback117954
-Node: Context Flags119719
-Node: Locale126330
-Node: Additional Logs127922
-Node: Key Management130120
-Node: Key objects131344
-Node: Listing Keys145918
-Node: Information About Keys154571
-Node: Manipulating Keys155879
-Node: Generating Keys158777
-Node: Signing Keys177097
-Node: Exporting Keys182611
-Node: Importing Keys189891
-Ref: Importing Keys-Footnote-1197294
-Node: Deleting Keys197422
-Node: Changing Passphrases199702
-Node: Changing TOFU Data201029
-Node: Advanced Key Editing203137
-Node: Crypto Operations205870
-Node: Decrypt207127
-Node: Verify214407
-Node: Decrypt and Verify227500
-Node: Sign230355
-Node: Selecting Signers230919
-Node: Creating a Signature232325
-Node: Signature Notation Data237095
-Node: Encrypt239380
-Node: Encrypting a Plaintext239736
-Node: Miscellaneous254148
-Node: Running other Programs254560
-Node: Using the Assuan protocol256723
-Node: Checking for updates259521
-Node: Run Control264338
-Node: Waiting For Completion265082
-Node: Using External Event Loops267207
-Node: I/O Callback Interface269179
-Node: Registering I/O Callbacks274107
-Node: I/O Callback Example276146
-Node: I/O Callback Example GTK+282771
-Node: I/O Callback Example GDK284560
-Node: I/O Callback Example Qt286202
-Node: Cancellation288490
-Node: UI Server Protocol290798
-Ref: UI Server Protocol-Footnote-1292233
-Node: UI Server Encrypt292352
-Node: UI Server Sign297710
-Node: UI Server Decrypt301751
-Node: UI Server Verify303406
-Node: UI Server Set Input Files306978
-Node: UI Server Sign/Encrypt Files308048
-Node: UI Server Verify/Decrypt Files309856
-Node: UI Server Import/Export Keys311732
-Node: UI Server Checksum Files312794
-Node: Miscellaneous UI Server Commands315012
-Ref: command SENDER316943
-Node: Debugging318645
-Node: Deprecated Functions320394
-Node: Library Copying343403
-Node: Copying371623
-Node: Concept Index409373
-Node: Function and Data Index424085
+Node: Data Buffer Convenience89961
+Node: Contexts92181
+Node: Creating Contexts93300
+Node: Destroying Contexts94147
+Node: Result Management94486
+Node: Context Attributes96067
+Node: Protocol Selection97234
+Node: Crypto Engine98280
+Node: Setting the Sender100169
+Node: ASCII Armor101682
+Node: Text Mode102311
+Node: Offline Mode103245
+Node: Pinentry Mode104743
+Node: Included Certificates106637
+Node: Key Listing Mode108083
+Node: Passphrase Callback113207
+Node: Progress Meter Callback116769
+Node: Status Message Callback118754
+Node: Context Flags120519
+Node: Locale127446
+Node: Additional Logs129038
+Node: Key Management131236
+Node: Key objects132460
+Node: Listing Keys147464
+Node: Information About Keys156117
+Node: Manipulating Keys157425
+Node: Generating Keys160323
+Node: Signing Keys178643
+Node: Exporting Keys184402
+Node: Importing Keys191682
+Ref: Importing Keys-Footnote-1199085
+Node: Deleting Keys199213
+Node: Changing Passphrases201493
+Node: Changing TOFU Data202820
+Node: Advanced Key Editing204928
+Node: Crypto Operations207661
+Node: Decrypt208918
+Node: Verify216198
+Node: Decrypt and Verify229291
+Node: Sign232146
+Node: Selecting Signers232710
+Node: Creating a Signature234116
+Node: Signature Notation Data238886
+Node: Encrypt241171
+Node: Encrypting a Plaintext241527
+Node: Miscellaneous255939
+Node: Running other Programs256351
+Node: Using the Assuan protocol258514
+Node: Checking for updates261312
+Node: Run Control266129
+Node: Waiting For Completion266873
+Node: Using External Event Loops268998
+Node: I/O Callback Interface270970
+Node: Registering I/O Callbacks275898
+Node: I/O Callback Example277937
+Node: I/O Callback Example GTK+284562
+Node: I/O Callback Example GDK286351
+Node: I/O Callback Example Qt287993
+Node: Cancellation290281
+Node: UI Server Protocol292589
+Ref: UI Server Protocol-Footnote-1294024
+Node: UI Server Encrypt294143
+Node: UI Server Sign299501
+Node: UI Server Decrypt303542
+Node: UI Server Verify305197
+Node: UI Server Set Input Files308769
+Node: UI Server Sign/Encrypt Files309839
+Node: UI Server Verify/Decrypt Files311647
+Node: UI Server Import/Export Keys313523
+Node: UI Server Checksum Files314585
+Node: Miscellaneous UI Server Commands316803
+Ref: command SENDER318734
+Node: Debugging320436
+Node: Deprecated Functions322185
+Node: Library Copying345194
+Node: Copying373414
+Node: Concept Index411164
+Node: Function and Data Index425876

End Tag Table
diff --git a/doc/gpgme.info-1 b/doc/gpgme.info-1
index 8c9aaa5..2014184 100644
--- a/doc/gpgme.info-1
+++ b/doc/gpgme.info-1
@@ -19,8 +19,8 @@ END-INFO-DIR-ENTRY
This file documents the GPGME library.
- This is Edition 1.14.1-beta35, last updated 13 December 2019, of ‘The
-‘GnuPG Made Easy’ Reference Manual’, for Version 1.14.1-beta35.
+ This is Edition 1.15.2-beta35, last updated 13 December 2019, of ‘The
+‘GnuPG Made Easy’ Reference Manual’, for Version 1.15.2-beta35.
Copyright © 2002–2008, 2010, 2012–2018 g10 Code GmbH.
@@ -41,8 +41,8 @@ File: gpgme.info, Node: Top, Next: Introduction, Up: (dir)
Main Menu
*********
-This is Edition 1.14.1-beta35, last updated 13 December 2019, of ‘The
-‘GnuPG Made Easy’ Reference Manual’, for Version 1.14.1-beta35 of the
+This is Edition 1.15.2-beta35, last updated 13 December 2019, of ‘The
+‘GnuPG Made Easy’ Reference Manual’, for Version 1.15.2-beta35 of the
GPGME library.
* Menu:
@@ -2101,6 +2101,21 @@ File: gpgme.info, Node: Data Buffer Meta-Data, Next: Data Buffer Convenience,
strategies and to provide a total value for its progress
information.
+ ‘io-buffer-size’
+ The value is a decimal number with the length of internal
+ buffers to used for internal I/O operations. The value is
+ capped at 1048576 (1 MiB). In certain environments large
+ buffers can yield a performance boost for callback bases data
+ object, but the details depend a lot on the circumstances and
+ the operating system. This flag may only be set once and must
+ be set before any actual I/O happens ion the data objects.
+
+ ‘sensitive’
+ If the numeric value is not 0 the data object is considered to
+ contain sensitive information like passwords or key material.
+ If this is set the internal buffers are securely overwritten
+ with zeroes by gpgme_data_release.
+
This function returns ‘0’ on success.

@@ -2969,6 +2984,12 @@ File: gpgme.info, Node: Context Flags, Next: Locale, Prev: Status Message Cal
This flag passes the option ‘--expert’ to gpg key edit. This
can be used to get additional callbacks in ‘gpgme_op_edit’.
+ ‘"cert-expire"’
+ SINCE: 1.15.2 The string given in VALUE is passed to the GnuPG
+ engine to set the expiration time to use for key signature
+ expiration. Valid values are documented in the GnuPG manual
+ and the gpg man page under the option ‘--default-cert-expire’.
+
This function returns ‘0’ on success.
-- Function: const char * gpgme_get_ctx_flag (gpgme_ctx_t CTX,
@@ -3487,6 +3508,13 @@ long as the key object itself is valid.
‘unsigned int exportable : 1’
This is true if the key signature is exportable.
+ ‘unsigned int trust_depth : 8’
+ This is the depth of a trust signature, or 0 if the key
+ signature is not a trust signature.
+
+ ‘unsigned int trust_value : 8’
+ This is the trust amount of a trust signature.
+
‘gpgme_pubkey_algo_t pubkey_algo’
This is the public key algorithm used to create the signature.
@@ -3502,6 +3530,10 @@ long as the key object itself is valid.
This is the expiration timestamp of the key signature, or 0 if
the key signature does not expire.
+ ‘char *trust_scope’
+ This is a regular expression that limits the scope of a trust
+ signature. Users must be prepared to see a ‘NULL’ value here.
+
‘gpgme_error_t status’
This is the status of the signature and has the same meaning
as the member of the same name in a ‘gpgme_signature_t’
@@ -4321,6 +4353,11 @@ to create key signatures when using modern GnuPG versions.
date. This overrides EXPIRE and any local configuration of
the engine.
+ ‘GPGME_KEYSIGN_FORCE’
+ Force the creation of a new signature even if one already
+ exists. This flag has an effect only if the gpg version is at
+ least 2.2.28 but won’t return an error with older versions.
+
The function returns zero on success, ‘GPG_ERR_NOT_SUPPORTED’ if
the engine does not support the command, or a bunch of other error
codes.
diff --git a/doc/gpgme.info-2 b/doc/gpgme.info-2
index 0e6df34..c88c51f 100644
--- a/doc/gpgme.info-2
+++ b/doc/gpgme.info-2
@@ -19,8 +19,8 @@ END-INFO-DIR-ENTRY
This file documents the GPGME library.
- This is Edition 1.14.1-beta35, last updated 13 December 2019, of ‘The
-‘GnuPG Made Easy’ Reference Manual’, for Version 1.14.1-beta35.
+ This is Edition 1.15.2-beta35, last updated 13 December 2019, of ‘The
+‘GnuPG Made Easy’ Reference Manual’, for Version 1.15.2-beta35.
Copyright © 2002–2008, 2010, 2012–2018 g10 Code GmbH.
@@ -2642,7 +2642,7 @@ Function and Data Index
(line 25)
* gpgme_genkey_result_t: Generating Keys. (line 381)
* gpgme_get_armor: ASCII Armor. (line 13)
-* gpgme_get_ctx_flag: Context Flags. (line 135)
+* gpgme_get_ctx_flag: Context Flags. (line 141)
* gpgme_get_dirinfo: Engine Version Check.
(line 6)
* gpgme_get_engine_info: Engine Information. (line 46)
@@ -2776,7 +2776,7 @@ Function and Data Index
* gpgme_op_keylist_result: Listing Keys. (line 166)
* gpgme_op_keylist_start: Listing Keys. (line 6)
* gpgme_op_keysign: Signing Keys. (line 12)
-* gpgme_op_keysign_start: Signing Keys. (line 73)
+* gpgme_op_keysign_start: Signing Keys. (line 78)
* gpgme_op_passwd: Changing Passphrases.
(line 6)
* gpgme_op_passwd_start: Changing Passphrases.
@@ -2785,8 +2785,8 @@ Function and Data Index
(line 68)
* gpgme_op_query_swdb_result: Checking for updates.
(line 80)
-* gpgme_op_revsig: Signing Keys. (line 84)
-* gpgme_op_revsig_start: Signing Keys. (line 119)
+* gpgme_op_revsig: Signing Keys. (line 89)
+* gpgme_op_revsig_start: Signing Keys. (line 124)
* gpgme_op_revuid: Generating Keys. (line 224)
* gpgme_op_revuid_start: Manipulating Keys. (line 58)
* gpgme_op_revuid_start <1>: Generating Keys. (line 252)
diff --git a/doc/gpgme.texi b/doc/gpgme.texi
index 99a228b..4a705b1 100644
--- a/doc/gpgme.texi
+++ b/doc/gpgme.texi
@@ -2253,6 +2253,22 @@ the data. If this is set the OpenPGP engine may use this to decide on
buffer allocation strategies and to provide a total value for its
progress information.
+@item io-buffer-size
+The value is a decimal number with the length of internal buffers to
+used for internal I/O operations. The value is capped at 1048576 (1
+MiB). In certain environments large buffers can yield a performance
+boost for callback bases data object, but the details depend a lot on
+the circumstances and the operating system. This flag may only be set
+once and must be set before any actual I/O happens ion the data
+objects.
+
+@item sensitive
+If the numeric value is not 0 the data object is considered to contain
+sensitive information like passwords or key material. If this is set
+the internal buffers are securely overwritten with zeroes by
+gpgme_data_release.
+
+
@end table
This function returns @code{0} on success.
@@ -3163,6 +3179,14 @@ rebuilding the trust-db.
This flag passes the option @option{--expert} to gpg key edit. This
can be used to get additional callbacks in @code{gpgme_op_edit}.
+@item "cert-expire"
+@since{1.15.2}
+The string given in @var{value} is passed to the GnuPG engine to set
+the expiration time to use for key signature expiration. Valid values
+are documented in the GnuPG manual and the gpg man page under
+the option @option{--default-cert-expire}.
+
+
@end table
This function returns @code{0} on success.
@@ -3706,6 +3730,13 @@ This is true if the key signature is invalid.
@item unsigned int exportable : 1
This is true if the key signature is exportable.
+@item unsigned int trust_depth : 8
+This is the depth of a trust signature, or 0 if the key signature is not
+a trust signature.
+
+@item unsigned int trust_value : 8
+This is the trust amount of a trust signature.
+
@item gpgme_pubkey_algo_t pubkey_algo
This is the public key algorithm used to create the signature.
@@ -3721,6 +3752,10 @@ the timestamp is invalid, and 0 if it is not available.
This is the expiration timestamp of the key signature, or 0 if the key
signature does not expire.
+@item char *trust_scope
+This is a regular expression that limits the scope of a trust signature.
+Users must be prepared to see a @code{NULL} value here.
+
@item gpgme_error_t status
This is the status of the signature and has the same meaning as the
member of the same name in a @code{gpgme_signature_t} object.
@@ -4699,6 +4734,11 @@ separated user IDs.
Force the creation of a key signature without an expiration date. This
overrides @var{expire} and any local configuration of the engine.
+@item GPGME_KEYSIGN_FORCE
+Force the creation of a new signature even if one already exists.
+This flag has an effect only if the gpg version is at least 2.2.28 but
+won't return an error with older versions.
+
@end table
The function returns zero on success, @code{GPG_ERR_NOT_SUPPORTED} if
diff --git a/gpgme.spec b/gpgme.spec
index 7912581..32d4439 100644
--- a/gpgme.spec
+++ b/gpgme.spec
@@ -1,7 +1,7 @@
# This is a template. The dist target uses it to create the real file.
Summary: GPGME - GnuPG Made Easy
Name: gpgme
-Version: 1.15.1
+Version: 1.16.0
Release: 1
URL: https://gnupg.org/gpgme.html
Source: https://www.gnupg.org/ftp/gcrypt/gpgme/%{name}-%{version}.tar.gz
diff --git a/lang/Makefile.in b/lang/Makefile.in
index 3e27eae..c080aa4 100644
--- a/lang/Makefile.in
+++ b/lang/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/lang/cl/Makefile.in b/lang/cl/Makefile.in
index d30c361..d9639d4 100644
--- a/lang/cl/Makefile.in
+++ b/lang/cl/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/lang/cl/gpgme.asd b/lang/cl/gpgme.asd
index c22940a..f0a15d8 100644
--- a/lang/cl/gpgme.asd
+++ b/lang/cl/gpgme.asd
@@ -27,7 +27,7 @@
(defsystem gpgme
:description "GnuPG Made Easy."
:author "g10 Code GmbH"
- :version "1.15.1"
+ :version "1.16.0"
:licence "GPL"
:defsystem-depends-on ("cffi-grovel")
:depends-on ("cffi" "gpg-error" "trivial-garbage")
diff --git a/lang/cpp/Makefile.in b/lang/cpp/Makefile.in
index 628f808..14315ac 100644
--- a/lang/cpp/Makefile.in
+++ b/lang/cpp/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/lang/cpp/src/Makefile.in b/lang/cpp/src/Makefile.in
index 958a057..5dc6fcc 100644
--- a/lang/cpp/src/Makefile.in
+++ b/lang/cpp/src/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/lang/cpp/src/editinteractor.cpp b/lang/cpp/src/editinteractor.cpp
index 774903d..e411ada 100644
--- a/lang/cpp/src/editinteractor.cpp
+++ b/lang/cpp/src/editinteractor.cpp
@@ -62,9 +62,10 @@ public:
~Private();
private:
- unsigned int state;
+ unsigned int state = StartState;
Error error;
- std::FILE *debug;
+ std::FILE *debug = nullptr;
+ bool debugNeedsClosing = false;
};
class GpgME::CallbackHelper
@@ -174,10 +175,7 @@ static gpgme_error_t edit_interactor_callback(void *opaque, gpgme_status_code_t
const gpgme_edit_cb_t GpgME::edit_interactor_callback = ::edit_interactor_callback;
EditInteractor::Private::Private(EditInteractor *qq)
- : q(qq),
- state(StartState),
- error(),
- debug(nullptr)
+ : q(qq)
{
const char *debug_env = std::getenv("GPGMEPP_INTERACTOR_DEBUG");
if (!debug_env) {
@@ -189,12 +187,13 @@ EditInteractor::Private::Private(EditInteractor *qq)
debug = stderr;
} else if (debug_env) {
debug = std::fopen(debug_env, "a+");
+ debugNeedsClosing = true;
}
}
EditInteractor::Private::~Private()
{
- if (debug) {
+ if (debug && debugNeedsClosing) {
std::fclose(debug);
}
}
diff --git a/lang/cpp/src/gpgsignkeyeditinteractor.cpp b/lang/cpp/src/gpgsignkeyeditinteractor.cpp
index 33ffbcf..4b5d274 100644
--- a/lang/cpp/src/gpgsignkeyeditinteractor.cpp
+++ b/lang/cpp/src/gpgsignkeyeditinteractor.cpp
@@ -66,6 +66,11 @@ public:
unsigned int checkLevel;
bool dupeOk;
Key key;
+ struct {
+ TrustSignatureTrust trust;
+ std::string depth;
+ std::string scope;
+ } trustSignature;
const char *command() const
{
@@ -129,7 +134,8 @@ GpgSignKeyEditInteractor::Private::Private()
currentId(),
nextId(),
checkLevel(0),
- dupeOk(false)
+ dupeOk(false),
+ trustSignature{TrustSignatureTrust::None, "0", {}}
{
}
@@ -190,26 +196,31 @@ static GpgSignKeyEditInteractor_Private::TransitionMap makeTable()
addEntry(COMMAND, GET_BOOL, "sign_uid.okay", CONFIRM);
addEntry(COMMAND, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM2);
addEntry(COMMAND, GET_BOOL, "sign_uid.dupe_okay", DUPE_OK);
+ addEntry(COMMAND, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
addEntry(UIDS_ANSWER_SIGN_ALL, GET_BOOL, "sign_uid.okay", CONFIRM);
+ addEntry(UIDS_ANSWER_SIGN_ALL, GET_BOOL, "sign_uid.dupe_okay", DUPE_OK);
addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "sign_uid.expire", SET_EXPIRE);
addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL);
- addEntry(SET_TRUST_VALUE, GET_LINE, "trustsign_prompt.trust_depth", SET_TRUST_DEPTH);
- addEntry(SET_TRUST_DEPTH, GET_LINE, "trustsign_prompt.trust_regexp", SET_TRUST_REGEXP);
- addEntry(SET_TRUST_REGEXP, GET_LINE, "sign_uid.okay", CONFIRM);
+ addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
+ addEntry(SET_TRUST_VALUE, GET_LINE, "trustsig_prompt.trust_depth", SET_TRUST_DEPTH);
+ addEntry(SET_TRUST_DEPTH, GET_LINE, "trustsig_prompt.trust_regexp", SET_TRUST_REGEXP);
+ addEntry(SET_TRUST_REGEXP, GET_BOOL, "sign_uid.okay", CONFIRM);
addEntry(SET_CHECK_LEVEL, GET_BOOL, "sign_uid.okay", CONFIRM);
addEntry(SET_EXPIRE, GET_BOOL, "sign_uid.class", SET_CHECK_LEVEL);
addEntry(CONFIRM, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM);
addEntry(DUPE_OK, GET_BOOL, "sign_uid.okay", CONFIRM);
addEntry(DUPE_OK2, GET_BOOL, "sign_uid.okay", CONFIRM);
+ addEntry(DUPE_OK, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
+ addEntry(DUPE_OK2, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
addEntry(CONFIRM, GET_BOOL, "sign_uid.okay", CONFIRM);
addEntry(CONFIRM2, GET_BOOL, "sign_uid.okay", CONFIRM);
addEntry(CONFIRM, GET_LINE, "keyedit.prompt", COMMAND);
- addEntry(CONFIRM, GET_LINE, "trustsign_prompt.trust_value", SET_TRUST_VALUE);
+ addEntry(CONFIRM, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
addEntry(CONFIRM, GET_LINE, "sign_uid.expire", SET_EXPIRE);
addEntry(CONFIRM, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL);
addEntry(UIDS_LIST_SEPARATELY_DONE, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM);
addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "keyedit.prompt", COMMAND);
- addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "trustsign_prompt.trust_value", SET_TRUST_VALUE);
+ addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "sign_uid.expire", SET_EXPIRE);
addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL);
addEntry(UIDS_LIST_SEPARATELY_DONE, GET_BOOL, "sign_uid.okay", CONFIRM);
@@ -239,12 +250,11 @@ const char *GpgSignKeyEditInteractor::action(Error &err) const
case SET_EXPIRE:
return answer(true);
case SET_TRUST_VALUE:
- // TODO
+ return d->trustSignature.trust == TrustSignatureTrust::Partial ? "1" : "2";
case SET_TRUST_DEPTH:
- //TODO
+ return d->trustSignature.depth.c_str();
case SET_TRUST_REGEXP:
- //TODO
- return nullptr;
+ return d->trustSignature.scope.c_str();
case SET_CHECK_LEVEL:
return check_level_strings[d->checkLevel];
case DUPE_OK:
@@ -360,3 +370,23 @@ void GpgSignKeyEditInteractor::setDupeOk(bool value)
assert(!d->started);
d->dupeOk = value;
}
+
+void GpgSignKeyEditInteractor::setTrustSignatureTrust(GpgME::TrustSignatureTrust trust)
+{
+ assert(!d->started);
+ assert(trust != TrustSignatureTrust::None);
+ d->trustSignature.trust = trust;
+}
+
+void GpgSignKeyEditInteractor::setTrustSignatureDepth(unsigned short depth)
+{
+ assert(!d->started);
+ assert(depth <= 255);
+ d->trustSignature.depth = std::to_string(depth);
+}
+
+void GpgSignKeyEditInteractor::setTrustSignatureScope(const std::string &scope)
+{
+ assert(!d->started);
+ d->trustSignature.scope = scope;
+}
diff --git a/lang/cpp/src/gpgsignkeyeditinteractor.h b/lang/cpp/src/gpgsignkeyeditinteractor.h
index d459687..889ed56 100644
--- a/lang/cpp/src/gpgsignkeyeditinteractor.h
+++ b/lang/cpp/src/gpgsignkeyeditinteractor.h
@@ -35,6 +35,7 @@ namespace GpgME
class Key;
class UserID;
+enum class TrustSignatureTrust : char;
class GPGMEPP_EXPORT GpgSignKeyEditInteractor : public EditInteractor
{
@@ -58,6 +59,10 @@ public:
* Context::setFlag before calling edit.*/
void setDupeOk(bool value);
+ void setTrustSignatureTrust(TrustSignatureTrust trust);
+ void setTrustSignatureDepth(unsigned short depth);
+ void setTrustSignatureScope(const std::string &scope);
+
private:
const char *action(Error &err) const override;
unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const override;
diff --git a/lang/cpp/src/key.cpp b/lang/cpp/src/key.cpp
index f9cc2b6..b893a7c 100644
--- a/lang/cpp/src/key.cpp
+++ b/lang/cpp/src/key.cpp
@@ -1083,6 +1083,29 @@ const char *UserID::Signature::policyURL() const
return nullptr;
}
+bool UserID::Signature::isTrustSignature() const
+{
+ return sig && sig->trust_depth > 0;
+}
+
+TrustSignatureTrust UserID::Signature::trustValue() const
+{
+ if (!sig || !isTrustSignature()) {
+ return TrustSignatureTrust::None;
+ }
+ return sig->trust_value >= 120 ? TrustSignatureTrust::Complete : TrustSignatureTrust::Partial;
+}
+
+unsigned int UserID::Signature::trustDepth() const
+{
+ return sig ? sig->trust_depth : 0;
+}
+
+const char *UserID::Signature::trustScope() const
+{
+ return sig ? sig->trust_scope : nullptr;
+}
+
std::string UserID::addrSpecFromString(const char *userid)
{
if (!userid) {
diff --git a/lang/cpp/src/key.h b/lang/cpp/src/key.h
index 515bf18..0e6380d 100644
--- a/lang/cpp/src/key.h
+++ b/lang/cpp/src/key.h
@@ -47,6 +47,12 @@ class TofuInfo;
typedef std::shared_ptr< std::remove_pointer<gpgme_key_t>::type > shared_gpgme_key_t;
+enum class TrustSignatureTrust : char {
+ None = 0,
+ Partial,
+ Complete,
+};
+
//
// class Key
//
@@ -514,6 +520,11 @@ public:
GpgME::Notation notation(unsigned int idx) const;
std::vector<GpgME::Notation> notations() const;
+ bool isTrustSignature() const;
+ TrustSignatureTrust trustValue() const;
+ unsigned int trustDepth() const;
+ const char *trustScope() const;
+
private:
shared_gpgme_key_t key;
gpgme_user_id_t uid;
diff --git a/lang/cpp/tests/Makefile.in b/lang/cpp/tests/Makefile.in
index b065f61..a675bf1 100644
--- a/lang/cpp/tests/Makefile.in
+++ b/lang/cpp/tests/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/lang/js/BrowserTestExtension/Makefile.in b/lang/js/BrowserTestExtension/Makefile.in
index 057f9e5..68fa1ac 100644
--- a/lang/js/BrowserTestExtension/Makefile.in
+++ b/lang/js/BrowserTestExtension/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/lang/js/DemoExtension/Makefile.in b/lang/js/DemoExtension/Makefile.in
index 4290886..ce14e1f 100644
--- a/lang/js/DemoExtension/Makefile.in
+++ b/lang/js/DemoExtension/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/lang/js/Makefile.in b/lang/js/Makefile.in
index 15383e2..8810732 100644
--- a/lang/js/Makefile.in
+++ b/lang/js/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/lang/js/src/Makefile.in b/lang/js/src/Makefile.in
index 3fff929..05f1d7a 100644
--- a/lang/js/src/Makefile.in
+++ b/lang/js/src/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/lang/python/Makefile.in b/lang/python/Makefile.in
index 19ed6f3..c0fc091 100644
--- a/lang/python/Makefile.in
+++ b/lang/python/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/lang/python/doc/Makefile.in b/lang/python/doc/Makefile.in
index 36eef56..a53283b 100644
--- a/lang/python/doc/Makefile.in
+++ b/lang/python/doc/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/lang/python/examples/Makefile.in b/lang/python/examples/Makefile.in
index a674e9b..06ea925 100644
--- a/lang/python/examples/Makefile.in
+++ b/lang/python/examples/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/lang/python/src/Makefile.in b/lang/python/src/Makefile.in
index 33d7e0b..f250242 100644
--- a/lang/python/src/Makefile.in
+++ b/lang/python/src/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/lang/python/src/core.py b/lang/python/src/core.py
index 5e57e4a..9618adc 100644
--- a/lang/python/src/core.py
+++ b/lang/python/src/core.py
@@ -342,7 +342,7 @@ class Context(GpgmeWrapper):
return self.__read__(sink, ciphertext), result, sig_result
- def decrypt(self, ciphertext, sink=None, passphrase=None, verify=True):
+ def decrypt(self, ciphertext, sink=None, passphrase=None, verify=True, filter_signatures=True):
"""Decrypt data
Decrypt the given ciphertext and verify any signatures. If
@@ -354,6 +354,10 @@ class Context(GpgmeWrapper):
signatures are required and no MissingSignatures error will be
raised).
+ The filter_signatures argument can be used to force this
+ function to return signatures that are not fully trusted - for
+ example because they were made by unknown keys.
+
If the ciphertext is symmetrically encrypted using a
passphrase, that passphrase can be given as parameter, using a
callback registered at the context, or out-of-band via
@@ -364,6 +368,8 @@ class Context(GpgmeWrapper):
passphrase -- for symmetric decryption
verify -- check signatures (boolean or iterable of keys,
see above) (default True)
+ filter_signatures -- if this function should filter out signatures
+ that are not completely OK (default True)
Returns:
plaintext -- the decrypted data (or None if sink is given)
@@ -437,8 +443,8 @@ class Context(GpgmeWrapper):
results=results)
if do_sig_verification:
- # filter out all invalid signatures
- verify_result.signatures = list(filter(lambda s: s.status == errors.NO_ERROR, verify_result.signatures))
+ if filter_signatures:
+ verify_result.signatures = list(filter(lambda s: s.status == errors.NO_ERROR, verify_result.signatures))
if required_keys is not None:
missing = []
for key in required_keys:
diff --git a/lang/python/tests/Makefile.in b/lang/python/tests/Makefile.in
index 306b904..9e60086 100644
--- a/lang/python/tests/Makefile.in
+++ b/lang/python/tests/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -461,7 +461,8 @@ all-am: Makefile
installdirs:
install: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-am
-install-exec: install-exec-am
+install-exec: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-am
install-data: install-data-am
uninstall: uninstall-am
@@ -558,7 +559,7 @@ ps-am:
uninstall-am:
-.MAKE: all check install install-am install-strip
+.MAKE: all check install install-am install-exec install-strip
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
clean-local cscopelist-am ctags-am distclean distclean-generic \
diff --git a/lang/qt/Makefile.in b/lang/qt/Makefile.in
index da82af8..d186d88 100644
--- a/lang/qt/Makefile.in
+++ b/lang/qt/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/lang/qt/doc/Doxyfile.in b/lang/qt/doc/Doxyfile.in
index 8ccd11c..ccccbc4 100644
--- a/lang/qt/doc/Doxyfile.in
+++ b/lang/qt/doc/Doxyfile.in
@@ -140,7 +140,7 @@ INLINE_INHERITED_MEMB = NO
# shortest path that makes the file name unique will be used
# The default value is: YES.
-FULL_PATH_NAMES = YES
+FULL_PATH_NAMES = NO
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
diff --git a/lang/qt/doc/Makefile.in b/lang/qt/doc/Makefile.in
index 9b43d7f..eadc021 100644
--- a/lang/qt/doc/Makefile.in
+++ b/lang/qt/doc/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/lang/qt/src/Makefile.am b/lang/qt/src/Makefile.am
index 94e88f3..683b44c 100644
--- a/lang/qt/src/Makefile.am
+++ b/lang/qt/src/Makefile.am
@@ -233,7 +233,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
-Wzero-as-null-pointer-constant
libqgpgme_la_LIBADD = ../../cpp/src/libgpgmepp.la ../../../src/libgpgme.la \
- @LIBASSUAN_LIBS@ @GPGME_QT_LIBS@
+ @LIBASSUAN_LIBS@ @GPG_ERROR_LIBS@ @GPGME_QT_LIBS@
libqgpgme_la_LDFLAGS = -no-undefined -version-info \
@LIBQGPGME_LT_CURRENT@:@LIBQGPGME_LT_REVISION@:@LIBQGPGME_LT_AGE@
diff --git a/lang/qt/src/Makefile.in b/lang/qt/src/Makefile.in
index a89b904..8e37198 100644
--- a/lang/qt/src/Makefile.in
+++ b/lang/qt/src/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -728,7 +728,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
-Wzero-as-null-pointer-constant
libqgpgme_la_LIBADD = ../../cpp/src/libgpgmepp.la ../../../src/libgpgme.la \
- @LIBASSUAN_LIBS@ @GPGME_QT_LIBS@
+ @LIBASSUAN_LIBS@ @GPG_ERROR_LIBS@ @GPGME_QT_LIBS@
libqgpgme_la_LDFLAGS = -no-undefined -version-info \
@LIBQGPGME_LT_CURRENT@:@LIBQGPGME_LT_REVISION@:@LIBQGPGME_LT_AGE@
@@ -1058,7 +1058,8 @@ installdirs:
done
install: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-am
-install-exec: install-exec-am
+install-exec: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-am
install-data: install-data-am
uninstall: uninstall-am
@@ -1239,7 +1240,7 @@ uninstall-am: uninstall-camelcaseincludeHEADERS \
uninstall-nodist_qgpgmeincludeHEADERS \
uninstall-qgpgmeincludeHEADERS
-.MAKE: all check install install-am install-strip
+.MAKE: all check install install-am install-exec install-strip
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \
diff --git a/lang/qt/src/cryptoconfig.cpp b/lang/qt/src/cryptoconfig.cpp
index 7121220..d52dce7 100644
--- a/lang/qt/src/cryptoconfig.cpp
+++ b/lang/qt/src/cryptoconfig.cpp
@@ -43,3 +43,23 @@ QStringList CryptoConfigEntry::stringValueList() const
}
return entry->stringValueList();
}
+
+QGpgME::CryptoConfigEntry *CryptoConfig::entry(const QString &componentName, const QString &entryName) const
+{
+ const CryptoConfigComponent *comp = component(componentName);
+ const QStringList groupNames = comp->groupList();
+ for (const auto &groupName : groupNames) {
+ const CryptoConfigGroup *group = comp ? comp->group(groupName) : nullptr;
+ if (CryptoConfigEntry *entry = group->entry(entryName)) {
+ return entry;
+ }
+ }
+ return nullptr;
+}
+
+QGpgME::CryptoConfigEntry *CryptoConfig::entry(const QString &componentName, const QString &groupName, const QString &entryName) const
+{
+ const CryptoConfigComponent *comp = component(componentName);
+ const CryptoConfigGroup *group = comp ? comp->group(groupName) : nullptr;
+ return group ? group->entry(entryName) : nullptr;
+}
diff --git a/lang/qt/src/cryptoconfig.h b/lang/qt/src/cryptoconfig.h
index d7aae9d..651e2af 100644
--- a/lang/qt/src/cryptoconfig.h
+++ b/lang/qt/src/cryptoconfig.h
@@ -373,18 +373,26 @@ public:
/**
* Convenience method to get hold of a single configuration entry when
- * its component, group and name are known. This can be used to read
+ * its component and name are known. This can be used to read
* the value and/or to set a value to it.
*
* @return the configuration object for a single configuration entry, 0 if not found.
* The object is owned by CryptoConfig, don't delete it.
*/
- CryptoConfigEntry *entry(const QString &componentName, const QString &groupName, const QString &entryName) const
- {
- const QGpgME::CryptoConfigComponent *comp = component(componentName);
- const QGpgME::CryptoConfigGroup *group = comp ? comp->group(groupName) : nullptr;
- return group ? group->entry(entryName) : nullptr;
- }
+ CryptoConfigEntry *entry(const QString &componentName, const QString &entryName) const;
+
+ /**
+ * This function is obsolete. It is provided to keep old source code working.
+ * We strongly advise against using it in new code.
+ *
+ * This function overloads @ref entry().
+ *
+ * Use the entry overload that does not require a group name instead. The group name
+ * is not needed to identify a configuration entry because it only provides logical
+ * grouping for user interfaces. Sometimes configuration entries are moved to different
+ * groups to improve usability.
+ */
+ QGPGME_DEPRECATED CryptoConfigEntry *entry(const QString &componentName, const QString &groupName, const QString &entryName) const;
/**
* Write back changes
diff --git a/lang/qt/src/dataprovider.cpp b/lang/qt/src/dataprovider.cpp
index a025a03..820ccbb 100644
--- a/lang/qt/src/dataprovider.cpp
+++ b/lang/qt/src/dataprovider.cpp
@@ -248,7 +248,17 @@ ssize_t QIODeviceDataProvider::write(const void *buffer, size_t bufSize)
return -1;
}
- return mIO->write(static_cast<const char *>(buffer), bufSize);
+ ssize_t ret = mIO->write(static_cast<const char *>(buffer), bufSize);
+ if (mHaveQProcess) {
+ /* XXX: With at least Qt 5.12 we have the problem that the acutal write
+ * would be triggered by an event / slot. So as we have moved the io
+ * device to our thread this is never triggered until the job is finished
+ * calling waitForBytesWritten internally triggers a _q_canWrite which will
+ * actually write. This is what we want as we want to stream and not to
+ * buffer endlessly. */
+ qobject_cast<QProcess *>(mIO.get())->waitForBytesWritten(0);
+ }
+ return ret;
}
off_t QIODeviceDataProvider::seek(off_t offset, int whence)
diff --git a/lang/qt/src/qgpgme_debug.cpp b/lang/qt/src/qgpgme_debug.cpp
index 4ed859e..513a9b0 100644
--- a/lang/qt/src/qgpgme_debug.cpp
+++ b/lang/qt/src/qgpgme_debug.cpp
@@ -1,5 +1,3 @@
-// This file is autogenerated by CMake: DO NOT EDIT
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -9,6 +7,8 @@
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
Q_LOGGING_CATEGORY(QGPGME_LOG, "gpg.qgpgme", QtWarningMsg)
+Q_LOGGING_CATEGORY(QGPGME_CONFIG_LOADING_LOG, "gpg.qgpgme.config_loading", QtInfoMsg)
#else
Q_LOGGING_CATEGORY(QGPGME_LOG, "gpg.qgpgme")
+Q_LOGGING_CATEGORY(QGPGME_CONFIG_LOADING_LOG, "gpg.qgpgme.config_loading")
#endif
diff --git a/lang/qt/src/qgpgme_debug.h b/lang/qt/src/qgpgme_debug.h
index 38c16ad..9cdd1a8 100644
--- a/lang/qt/src/qgpgme_debug.h
+++ b/lang/qt/src/qgpgme_debug.h
@@ -1,11 +1,10 @@
-// This file is autogenerated by CMake: DO NOT EDIT
-
-#ifndef QGPGME_LOG_H
-#define QGPGME_LOG_H
+#ifndef QGPGME_QGPGME_DEBUG_H
+#define QGPGME_QGPGME_DEBUG_H
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(QGPGME_LOG)
+Q_DECLARE_LOGGING_CATEGORY(QGPGME_CONFIG_LOADING_LOG)
#endif
diff --git a/lang/qt/src/qgpgmenewcryptoconfig.cpp b/lang/qt/src/qgpgmenewcryptoconfig.cpp
index fba20fa..b93db76 100644
--- a/lang/qt/src/qgpgmenewcryptoconfig.cpp
+++ b/lang/qt/src/qgpgmenewcryptoconfig.cpp
@@ -46,7 +46,7 @@
#include "global.h"
#include "error.h"
-
+#include "debug.h"
#include <sstream>
#include <string>
@@ -101,7 +101,7 @@ void QGpgMENewCryptoConfig::reloadConfiguration(bool)
<< "components:\n";
std::copy(components.begin(), components.end(),
std::ostream_iterator<Component>(ss, "\n"));
- qCDebug(QGPGME_LOG) << ss.str().c_str();
+ qCDebug(QGPGME_CONFIG_LOADING_LOG) << ss.str().c_str();
}
#endif
#if 0
@@ -468,50 +468,74 @@ static QUrl parseURL(int mRealArgType, const QString &str)
{
if (mRealArgType == 33) { // LDAP server
// The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN
- QStringList items = str.split(QLatin1Char(':'));
- if (items.count() == 5) {
- QStringList::const_iterator it = items.constBegin();
- QUrl url;
- url.setScheme(QStringLiteral("ldap"));
- url.setHost(urlpart_decode(*it++));
-
- bool ok;
- const int port = (*it++).toInt(&ok);
- if (ok) {
- url.setPort(port);
- } else if (!it->isEmpty()) {
- qCWarning(QGPGME_LOG) << "parseURL: malformed LDAP server port, ignoring: \"" << *it << "\"";
- }
+ // or, since gpg 2.2.18, e.g. for dirmngr/ldapserver: [ldap:]hostname:port:username:password:base_dn:flags[:]
+ const bool isLdapUrl = str.startsWith(QLatin1String("ldap://")) || str.startsWith(QLatin1String("ldaps://"));
+ if (!isLdapUrl) {
+ const bool hasOptionalPrefix = str.startsWith(QLatin1String("ldap:"));
+ const QStringList items = hasOptionalPrefix ? str.mid(5).split(QLatin1Char(':')) : str.split(QLatin1Char(':'));
+ if (items.size() >= 5) {
+ QUrl url;
+ url.setScheme(QStringLiteral("ldap"));
+ url.setHost(urlpart_decode(items[0]), QUrl::DecodedMode);
+
+ const auto portString = items[1];
+ if (!portString.isEmpty()) {
+ bool ok;
+ const int port = portString.toInt(&ok);
+ if (ok) {
+ url.setPort(port);
+ } else {
+ qCWarning(QGPGME_LOG) << "parseURL: malformed LDAP server port, ignoring:" << portString;
+ }
+ }
- const QString userName = urlpart_decode(*it++);
- if (!userName.isEmpty()) {
- url.setUserName(userName);
- }
- const QString passWord = urlpart_decode(*it++);
- if (!passWord.isEmpty()) {
- url.setPassword(passWord);
+ const QString userName = urlpart_decode(items[2]);
+ if (!userName.isEmpty()) {
+ url.setUserName(userName, QUrl::DecodedMode);
+ }
+ const QString passWord = urlpart_decode(items[3]);
+ if (!passWord.isEmpty()) {
+ url.setPassword(passWord, QUrl::DecodedMode);
+ }
+ const auto baseDn = urlpart_decode(items[4]);
+ if (!baseDn.isEmpty()) {
+ url.setQuery(baseDn, QUrl::DecodedMode);
+ }
+ if (items.size() >= 6) {
+ const auto flags = urlpart_decode(items[5]);
+ if (!flags.isEmpty()) {
+ url.setFragment(flags, QUrl::DecodedMode);
+ }
+ }
+ return url;
+ } else {
+ qCWarning(QGPGME_LOG) << "parseURL: malformed LDAP server:" << str;
}
- url.setQuery(urlpart_decode(*it));
- return url;
- } else {
- qCWarning(QGPGME_LOG) << "parseURL: malformed LDAP server:" << str;
}
}
// other URLs : assume wellformed URL syntax.
return QUrl(str);
}
+static QString portToString(int port)
+{
+ // -1 is used for default ports => empty string
+ return port != -1 ? QString::number(port) : QString();
+}
+
// The opposite of parseURL
static QString splitURL(int mRealArgType, const QUrl &url)
{
if (mRealArgType == 33) { // LDAP server
// The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN
+ // or, since gpg 2.2.18, e.g. for dirmngr/ldapserver: [ldap:]hostname:port:username:password:base_dn:flags[:]
Q_ASSERT(url.scheme() == QLatin1String("ldap"));
return urlpart_encode(url.host()) + QLatin1Char(':') +
- (url.port() != -1 ? QString::number(url.port()) : QString()) + QLatin1Char(':') + // -1 is used for default ports, omit
+ portToString(url.port()) + QLatin1Char(':') +
urlpart_encode(url.userName()) + QLatin1Char(':') +
urlpart_encode(url.password()) + QLatin1Char(':') +
- urlpart_encode(url.query());
+ urlpart_encode(url.query()) + QLatin1Char(':') +
+ urlpart_encode(url.fragment());
}
return url.path();
}
@@ -675,7 +699,10 @@ void QGpgMENewCryptoConfigEntry::setURLValueList(const QList<QUrl> &urls)
} else {
values.push_back(splitURL(type, url).toUtf8().constData());
}
- m_option.setNewValue(m_option.createStringListArgument(values));
+ const auto err = m_option.setNewValue(m_option.createStringListArgument(values));
+ if (err) {
+ qCWarning(QGPGME_LOG) << "setURLValueList: failed to set new value:" << err;
+ }
}
bool QGpgMENewCryptoConfigEntry::isDirty() const
diff --git a/lang/qt/src/qgpgmesignkeyjob.cpp b/lang/qt/src/qgpgmesignkeyjob.cpp
index ee0c537..5036a9b 100644
--- a/lang/qt/src/qgpgmesignkeyjob.cpp
+++ b/lang/qt/src/qgpgmesignkeyjob.cpp
@@ -38,27 +38,51 @@
#include "qgpgmesignkeyjob.h"
+#include <QDate>
+#include <QString>
+
#include "dataprovider.h"
#include "context.h"
#include "data.h"
#include "gpgsignkeyeditinteractor.h"
+#include "qgpgme_debug.h"
+
#include <cassert>
-#include <memory>
using namespace QGpgME;
using namespace GpgME;
+namespace
+{
+struct TrustSignatureProperties {
+ TrustSignatureTrust trust = TrustSignatureTrust::None;
+ unsigned int depth = 0;
+ QString scope;
+};
+}
+
+class QGpgMESignKeyJob::Private
+{
+public:
+ Private() = default;
+
+ std::vector<unsigned int> m_userIDsToSign;
+ GpgME::Key m_signingKey;
+ unsigned int m_checkLevel = 0;
+ bool m_exportable = false;
+ bool m_nonRevocable = false;
+ bool m_started = false;
+ bool m_dupeOk = false;
+ QString m_remark;
+ TrustSignatureProperties m_trustSignature;
+ QDate m_expiration;
+};
+
QGpgMESignKeyJob::QGpgMESignKeyJob(Context *context)
- : mixin_type(context),
- m_userIDsToSign(),
- m_signingKey(),
- m_checkLevel(0),
- m_exportable(false),
- m_nonRevocable(false),
- m_started(false),
- m_dupeOk(false)
+ : mixin_type(context)
+ , d{std::unique_ptr<Private>(new Private())}
{
lateInitialization();
}
@@ -67,7 +91,9 @@ QGpgMESignKeyJob::~QGpgMESignKeyJob() {}
static QGpgMESignKeyJob::result_type sign_key(Context *ctx, const Key &key, const std::vector<unsigned int> &uids,
unsigned int checkLevel, const Key &signer, unsigned int opts,
- bool dupeOk, const QString &remark)
+ bool dupeOk, const QString &remark,
+ const TrustSignatureProperties &trustSignature,
+ const QDate &expirationDate)
{
QGpgME::QByteArrayDataProvider dp;
Data data(&dp);
@@ -87,10 +113,38 @@ static QGpgMESignKeyJob::result_type sign_key(Context *ctx, const Key &key, cons
ctx->addSignatureNotation("rem@gnupg.org", remark.toUtf8().constData());
}
- if (!signer.isNull())
+ if (opts & GpgSignKeyEditInteractor::Trust) {
+ skei->setTrustSignatureTrust(trustSignature.trust);
+ skei->setTrustSignatureDepth(trustSignature.depth);
+ skei->setTrustSignatureScope(trustSignature.scope.toUtf8().toStdString());
+ }
+
+ if (!signer.isNull()) {
if (const Error err = ctx->addSigningKey(signer)) {
return std::make_tuple(err, QString(), Error());
}
+ }
+
+ if (expirationDate.isValid()) {
+ // on 2106-02-07, the Unix time will reach 0xFFFFFFFF; since gpg uses uint32 internally
+ // for the expiration date clip it at 2106-02-06
+ static const QDate maxAllowedDate{2106, 2, 6};
+ const auto clippedExpirationDate = expirationDate <= maxAllowedDate ? expirationDate : maxAllowedDate;
+ if (clippedExpirationDate != expirationDate) {
+ qCWarning(QGPGME_LOG) << "Expiration of certification has been changed to" << clippedExpirationDate;
+ }
+ // use the "days from now" format to specify the expiration date of the certification;
+ // this format is the most appropriate regardless of the local timezone
+ const auto daysFromNow = QDate::currentDate().daysTo(clippedExpirationDate);
+ if (daysFromNow > 0) {
+ const auto certExpire = std::to_string(daysFromNow) + "d";
+ ctx->setFlag("cert-expire", certExpire.c_str());
+ }
+ } else {
+ // explicitly set "cert-expire" to "0" (no expiration) to override default-cert-expire set in gpg.conf
+ ctx->setFlag("cert-expire", "0");
+ }
+
const Error err = ctx->edit(key, std::unique_ptr<EditInteractor> (skei), data);
Error ae;
const QString log = _detail::audit_log_as_html(ctx, ae);
@@ -100,57 +154,80 @@ static QGpgMESignKeyJob::result_type sign_key(Context *ctx, const Key &key, cons
Error QGpgMESignKeyJob::start(const Key &key)
{
unsigned int opts = 0;
- if (m_nonRevocable) {
+ if (d->m_nonRevocable) {
opts |= GpgSignKeyEditInteractor::NonRevocable;
}
- if (m_exportable) {
+ if (d->m_exportable) {
opts |= GpgSignKeyEditInteractor::Exportable;
}
- run(std::bind(&sign_key, std::placeholders::_1, key, m_userIDsToSign, m_checkLevel, m_signingKey, opts,
- m_dupeOk, m_remark));
- m_started = true;
+ switch (d->m_trustSignature.trust) {
+ case TrustSignatureTrust::Partial:
+ case TrustSignatureTrust::Complete:
+ opts |= GpgSignKeyEditInteractor::Trust;
+ break;
+ default:
+ opts &= ~GpgSignKeyEditInteractor::Trust;
+ break;
+ }
+ run(std::bind(&sign_key, std::placeholders::_1, key, d->m_userIDsToSign, d->m_checkLevel, d->m_signingKey,
+ opts, d->m_dupeOk, d->m_remark, d->m_trustSignature, d->m_expiration));
+ d->m_started = true;
return Error();
}
void QGpgMESignKeyJob::setUserIDsToSign(const std::vector<unsigned int> &idsToSign)
{
- assert(!m_started);
- m_userIDsToSign = idsToSign;
+ assert(!d->m_started);
+ d->m_userIDsToSign = idsToSign;
}
void QGpgMESignKeyJob::setCheckLevel(unsigned int checkLevel)
{
- assert(!m_started);
- m_checkLevel = checkLevel;
+ assert(!d->m_started);
+ d->m_checkLevel = checkLevel;
}
void QGpgMESignKeyJob::setExportable(bool exportable)
{
- assert(!m_started);
- m_exportable = exportable;
+ assert(!d->m_started);
+ d->m_exportable = exportable;
}
void QGpgMESignKeyJob::setSigningKey(const Key &key)
{
- assert(!m_started);
- m_signingKey = key;
+ assert(!d->m_started);
+ d->m_signingKey = key;
}
void QGpgMESignKeyJob::setNonRevocable(bool nonRevocable)
{
- assert(!m_started);
- m_nonRevocable = nonRevocable;
+ assert(!d->m_started);
+ d->m_nonRevocable = nonRevocable;
}
void QGpgMESignKeyJob::setRemark(const QString &remark)
{
- assert(!m_started);
- m_remark = remark;
+ assert(!d->m_started);
+ d->m_remark = remark;
}
void QGpgMESignKeyJob::setDupeOk(bool value)
{
- assert(!m_started);
- m_dupeOk = value;
+ assert(!d->m_started);
+ d->m_dupeOk = value;
}
+
+void QGpgMESignKeyJob::setTrustSignature(GpgME::TrustSignatureTrust trust, unsigned short depth, const QString &scope)
+{
+ assert(!d->m_started);
+ assert(depth <= 255);
+ d->m_trustSignature = {trust, depth, scope};
+}
+
+void QGpgMESignKeyJob::setExpirationDate(const QDate &expiration)
+{
+ assert(!d->m_started);
+ d->m_expiration = expiration;
+}
+
#include "qgpgmesignkeyjob.moc"
diff --git a/lang/qt/src/qgpgmesignkeyjob.h b/lang/qt/src/qgpgmesignkeyjob.h
index 9c19c02..2ea9e94 100644
--- a/lang/qt/src/qgpgmesignkeyjob.h
+++ b/lang/qt/src/qgpgmesignkeyjob.h
@@ -39,13 +39,7 @@
#include "threadedjobmixin.h"
-#include <QString>
-
-#ifdef BUILDING_QGPGME
-# include "key.h"
-#else
-#include <gpgme++/key.h>
-#endif
+#include <memory>
namespace QGpgME
{
@@ -90,15 +84,14 @@ public:
/* from SignKeyJob */
void setDupeOk(bool value) Q_DECL_OVERRIDE;
+ /* from SignKeyJob */
+ void setTrustSignature(GpgME::TrustSignatureTrust trust, unsigned short depth, const QString &scope) Q_DECL_OVERRIDE;
+
+ void setExpirationDate(const QDate &expiration) override;
+
private:
- std::vector<unsigned int> m_userIDsToSign;
- GpgME::Key m_signingKey;
- unsigned int m_checkLevel;
- bool m_exportable;
- bool m_nonRevocable;
- bool m_started;
- bool m_dupeOk;
- QString m_remark;
+ class Private;
+ std::unique_ptr<Private> d;
};
}
diff --git a/lang/qt/src/signkeyjob.h b/lang/qt/src/signkeyjob.h
index e3ae75f..666af92 100644
--- a/lang/qt/src/signkeyjob.h
+++ b/lang/qt/src/signkeyjob.h
@@ -43,8 +43,10 @@ namespace GpgME
{
class Error;
class Key;
+enum class TrustSignatureTrust : char;
}
+class QDate;
class QString;
namespace QGpgME
@@ -74,22 +76,19 @@ public:
/**
Starts the key signing operation. \a key is the key to sign.
@param keyToSign the key to be signed
- @param idsToSign the user IDs to sign
- @param signingKey the secret key to use for signing
- @param option the signing mode, either local or exportable
*/
virtual GpgME::Error start(const GpgME::Key &keyToSign) = 0;
/**
* If explicitly specified, only the listed user IDs will be signed. Otherwise all user IDs
* are signed.
- * @param list of user ID indexes (of the key to be signed).
+ * @param idsToSign list of user ID indexes (of the key to be signed).
*/
virtual void setUserIDsToSign(const std::vector<unsigned int> &idsToSign) = 0;
/**
* sets the check level
- * @param the check level, ranges from 0 (no claim) and 3 (extensively checked),
+ * @param checkLevel the check level, ranges from 0 (no claim) and 3 (extensively checked),
* default is 0
*/
virtual void setCheckLevel(unsigned int checkLevel) = 0;
@@ -127,6 +126,35 @@ public:
**/
virtual void setRemark(const QString &) {};
+ /**
+ * If set, then the created signature will be a trust signature. By default,
+ * no trust signatures are created.
+ *
+ * @a trust is the amount of trust to put into the signed key, either
+ * @c TrustSignatureTrust::Partial or @c TrustSignatureTrust::Complete.
+ * @a depth is the level of the trust signature. Values between 0 and 255 are
+ * allowed. Level 0 has the same meaning as an ordinary validity signature.
+ * Level 1 means that the signed key is asserted to be a valid trusted
+ * introducer. Level n >= 2 means that the signed key is asserted to be
+ * trusted to issue level n-1 trust signatures, i.e., that it is a "meta
+ * introducer".
+ * @a scope is a domain name that limits the scope of trust of the signed key
+ * to user IDs with email addresses matching the domain (or a subdomain).
+ *
+ * Not pure virtual for ABI compatibility.
+ **/
+ virtual void setTrustSignature(GpgME::TrustSignatureTrust trust, unsigned short depth, const QString &scope) { Q_UNUSED(trust); Q_UNUSED(depth); Q_UNUSED(scope); };
+
+ /**
+ * Sets the expiration date of the key signature to @a expiration. By default,
+ * key signatures do not expire.
+ *
+ * Note: Expiration dates after 2106-02-06 will be set to 2106-02-06.
+ *
+ * Not pure virtual for ABI compatibility.
+ **/
+ virtual void setExpirationDate(const QDate &expiration) { Q_UNUSED(expiration); }
+
Q_SIGNALS:
void result(const GpgME::Error &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
};
diff --git a/lang/qt/tests/Makefile.am b/lang/qt/tests/Makefile.am
index ace5082..41ea808 100644
--- a/lang/qt/tests/Makefile.am
+++ b/lang/qt/tests/Makefile.am
@@ -27,11 +27,11 @@ TESTS_ENVIRONMENT = GNUPGHOME=$(GNUPGHOME)
EXTRA_DIST = initial.test
TESTS = initial.test t-keylist t-keylocate t-ownertrust t-tofuinfo \
- t-encrypt t-verify t-various t-config t-remarks
+ t-encrypt t-verify t-various t-config t-remarks t-trustsignatures
moc_files = t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
- t-various.moc t-config.moc t-remarks.moc
+ t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc
AM_LDFLAGS = -no-install
@@ -57,6 +57,7 @@ t_verify_SOURCES = t-verify.cpp $(support_src)
t_various_SOURCES = t-various.cpp $(support_src)
t_config_SOURCES = t-config.cpp $(support_src)
t_remarks_SOURCES = t-remarks.cpp $(support_src)
+t_trustsignatures_SOURCES = t-trustsignatures.cpp $(support_src)
run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp
nodist_t_keylist_SOURCES = $(moc_files)
@@ -64,7 +65,8 @@ nodist_t_keylist_SOURCES = $(moc_files)
BUILT_SOURCES = $(moc_files) pubring-stamp
noinst_PROGRAMS = t-keylist t-keylocate t-ownertrust t-tofuinfo t-encrypt \
- run-keyformailboxjob t-wkspublish t-verify t-various t-config t-remarks
+ run-keyformailboxjob t-wkspublish t-verify t-various t-config t-remarks \
+ t-trustsignatures
CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
gpg-agent.conf pubring.kbx~ S.gpg-agent gpg.conf pubring.gpg~ \
diff --git a/lang/qt/tests/Makefile.in b/lang/qt/tests/Makefile.in
index dd7f342..2b0e0ee 100644
--- a/lang/qt/tests/Makefile.in
+++ b/lang/qt/tests/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -110,12 +110,12 @@ host_triplet = @host@
TESTS = initial.test t-keylist$(EXEEXT) t-keylocate$(EXEEXT) \
t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) t-encrypt$(EXEEXT) \
t-verify$(EXEEXT) t-various$(EXEEXT) t-config$(EXEEXT) \
- t-remarks$(EXEEXT)
+ t-remarks$(EXEEXT) t-trustsignatures$(EXEEXT)
noinst_PROGRAMS = t-keylist$(EXEEXT) t-keylocate$(EXEEXT) \
t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) t-encrypt$(EXEEXT) \
run-keyformailboxjob$(EXEEXT) t-wkspublish$(EXEEXT) \
t-verify$(EXEEXT) t-various$(EXEEXT) t-config$(EXEEXT) \
- t-remarks$(EXEEXT)
+ t-remarks$(EXEEXT) t-trustsignatures$(EXEEXT)
subdir = lang/qt/tests
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
@@ -185,6 +185,12 @@ t_tofuinfo_OBJECTS = $(am_t_tofuinfo_OBJECTS)
t_tofuinfo_LDADD = $(LDADD)
t_tofuinfo_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
../src/libqgpgme.la ../../../src/libgpgme.la
+am_t_trustsignatures_OBJECTS = t-trustsignatures.$(OBJEXT) \
+ $(am__objects_1)
+t_trustsignatures_OBJECTS = $(am_t_trustsignatures_OBJECTS)
+t_trustsignatures_LDADD = $(LDADD)
+t_trustsignatures_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
am_t_various_OBJECTS = t-various.$(OBJEXT) $(am__objects_1)
t_various_OBJECTS = $(am_t_various_OBJECTS)
t_various_LDADD = $(LDADD)
@@ -220,8 +226,8 @@ am__depfiles_remade = ./$(DEPDIR)/run-keyformailboxjob.Po \
./$(DEPDIR)/t-keylist.Po ./$(DEPDIR)/t-keylocate.Po \
./$(DEPDIR)/t-ownertrust.Po ./$(DEPDIR)/t-remarks.Po \
./$(DEPDIR)/t-support.Po ./$(DEPDIR)/t-tofuinfo.Po \
- ./$(DEPDIR)/t-various.Po ./$(DEPDIR)/t-verify.Po \
- ./$(DEPDIR)/t-wkspublish.Po
+ ./$(DEPDIR)/t-trustsignatures.Po ./$(DEPDIR)/t-various.Po \
+ ./$(DEPDIR)/t-verify.Po ./$(DEPDIR)/t-wkspublish.Po
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
@@ -263,14 +269,15 @@ SOURCES = $(run_keyformailboxjob_SOURCES) $(t_config_SOURCES) \
$(t_encrypt_SOURCES) $(t_keylist_SOURCES) \
$(nodist_t_keylist_SOURCES) $(t_keylocate_SOURCES) \
$(t_ownertrust_SOURCES) $(t_remarks_SOURCES) \
- $(t_tofuinfo_SOURCES) $(t_various_SOURCES) $(t_verify_SOURCES) \
+ $(t_tofuinfo_SOURCES) $(t_trustsignatures_SOURCES) \
+ $(t_various_SOURCES) $(t_verify_SOURCES) \
$(t_wkspublish_SOURCES)
DIST_SOURCES = $(run_keyformailboxjob_SOURCES) $(t_config_SOURCES) \
$(t_encrypt_SOURCES) $(t_keylist_SOURCES) \
$(t_keylocate_SOURCES) $(t_ownertrust_SOURCES) \
$(t_remarks_SOURCES) $(t_tofuinfo_SOURCES) \
- $(t_various_SOURCES) $(t_verify_SOURCES) \
- $(t_wkspublish_SOURCES)
+ $(t_trustsignatures_SOURCES) $(t_various_SOURCES) \
+ $(t_verify_SOURCES) $(t_wkspublish_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -525,7 +532,7 @@ TESTS_ENVIRONMENT = GNUPGHOME=$(GNUPGHOME)
EXTRA_DIST = initial.test
moc_files = t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
- t-various.moc t-config.moc t-remarks.moc
+ t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc
AM_LDFLAGS = -no-install
LDADD = ../../cpp/src/libgpgmepp.la ../src/libqgpgme.la \
@@ -549,6 +556,7 @@ t_verify_SOURCES = t-verify.cpp $(support_src)
t_various_SOURCES = t-various.cpp $(support_src)
t_config_SOURCES = t-config.cpp $(support_src)
t_remarks_SOURCES = t-remarks.cpp $(support_src)
+t_trustsignatures_SOURCES = t-trustsignatures.cpp $(support_src)
run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp
nodist_t_keylist_SOURCES = $(moc_files)
BUILT_SOURCES = $(moc_files) pubring-stamp
@@ -633,6 +641,10 @@ t-tofuinfo$(EXEEXT): $(t_tofuinfo_OBJECTS) $(t_tofuinfo_DEPENDENCIES) $(EXTRA_t_
@rm -f t-tofuinfo$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_tofuinfo_OBJECTS) $(t_tofuinfo_LDADD) $(LIBS)
+t-trustsignatures$(EXEEXT): $(t_trustsignatures_OBJECTS) $(t_trustsignatures_DEPENDENCIES) $(EXTRA_t_trustsignatures_DEPENDENCIES)
+ @rm -f t-trustsignatures$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_trustsignatures_OBJECTS) $(t_trustsignatures_LDADD) $(LIBS)
+
t-various$(EXEEXT): $(t_various_OBJECTS) $(t_various_DEPENDENCIES) $(EXTRA_t_various_DEPENDENCIES)
@rm -f t-various$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_various_OBJECTS) $(t_various_LDADD) $(LIBS)
@@ -660,6 +672,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-remarks.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-support.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-tofuinfo.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-trustsignatures.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-various.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-verify.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-wkspublish.Po@am__quote@ # am--include-marker
@@ -883,7 +896,8 @@ all-am: Makefile $(PROGRAMS)
installdirs:
install: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-am
-install-exec: install-exec-am
+install-exec: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-am
install-data: install-data-am
uninstall: uninstall-am
@@ -929,6 +943,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/t-remarks.Po
-rm -f ./$(DEPDIR)/t-support.Po
-rm -f ./$(DEPDIR)/t-tofuinfo.Po
+ -rm -f ./$(DEPDIR)/t-trustsignatures.Po
-rm -f ./$(DEPDIR)/t-various.Po
-rm -f ./$(DEPDIR)/t-verify.Po
-rm -f ./$(DEPDIR)/t-wkspublish.Po
@@ -986,6 +1001,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/t-remarks.Po
-rm -f ./$(DEPDIR)/t-support.Po
-rm -f ./$(DEPDIR)/t-tofuinfo.Po
+ -rm -f ./$(DEPDIR)/t-trustsignatures.Po
-rm -f ./$(DEPDIR)/t-various.Po
-rm -f ./$(DEPDIR)/t-verify.Po
-rm -f ./$(DEPDIR)/t-wkspublish.Po
@@ -1007,7 +1023,8 @@ ps-am:
uninstall-am:
-.MAKE: all check check-am install install-am install-strip
+.MAKE: all check check-am install install-am install-exec \
+ install-strip
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \
check-am clean clean-generic clean-libtool clean-local \
diff --git a/lang/qt/tests/t-trustsignatures.cpp b/lang/qt/tests/t-trustsignatures.cpp
new file mode 100644
index 0000000..d392b2f
--- /dev/null
+++ b/lang/qt/tests/t-trustsignatures.cpp
@@ -0,0 +1,565 @@
+/* t-remarks.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME 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 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME 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, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "t-support.h"
+
+#include "context.h"
+#include "engineinfo.h"
+#include "protocol.h"
+#include "signkeyjob.h"
+
+#include <QSignalSpy>
+#include <QTemporaryDir>
+#include <QTest>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+class TestTrustSignatures: public QGpgMETest
+{
+ Q_OBJECT
+
+Q_SIGNALS:
+ void asyncDone();
+
+private Q_SLOTS:
+ void test_tsign_single_uid_key_and_then_tsign_it_again()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the signing key (alfa@example.net)
+ auto seckey = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!seckey.isNull());
+
+ // Get the target key (victor@example.org)
+ auto target = ctx->key("E8143C489C8D41124DC40D0B47AF4B6961F04784", err, false);
+ QVERIFY(!err);
+ QVERIFY(!target.isNull());
+ QVERIFY(target.numUserIDs() > 0);
+
+ // Create first trust signature
+ {
+ // Create the job
+ auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
+ QVERIFY(job);
+
+ // Hack in the passphrase provider
+ auto jobCtx = Job::context(job.get());
+ TestPassphraseProvider provider;
+ jobCtx->setPassphraseProvider(&provider);
+ jobCtx->setPinentryMode(Context::PinentryLoopback);
+
+ // Setup the job
+ job->setExportable(true);
+ job->setSigningKey(seckey);
+ job->setTrustSignature(TrustSignatureTrust::Complete, 1, QStringLiteral("example.org"));
+
+ connect(job.get(), &SignKeyJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ if (err2.code() == GPG_ERR_GENERAL) {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.\n"
+ "Hint: Run with GPGMEPP_INTERACTOR_DEBUG=stderr to debug the edit interaction.").arg(err2.asString())));
+ } else {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.").arg(err2.asString())));
+ }
+ }
+ });
+
+ job->start(target);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the trust signature should have been added.
+ target.update();
+ const auto trustSignature = target.userID(0).signature(target.userID(0).numSignatures() - 1);
+ QVERIFY(trustSignature.isTrustSignature());
+ QCOMPARE(trustSignature.trustDepth(), 1u);
+ QCOMPARE(trustSignature.trustValue(), TrustSignatureTrust::Complete);
+ QVERIFY(trustSignature.trustScope());
+ const auto trustScope = QString::fromUtf8(trustSignature.trustScope());
+ QVERIFY(!trustScope.isEmpty());
+ const QRegExp regex{trustScope};
+ QVERIFY(regex.isValid());
+ QVERIFY(regex.indexIn(QStringLiteral("Foo <foo@example.org>")) != -1);
+ }
+
+ // Create second trust signature
+ {
+ // Create the job
+ auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
+ QVERIFY(job);
+
+ // Hack in the passphrase provider
+ auto jobCtx = Job::context(job.get());
+ TestPassphraseProvider provider;
+ jobCtx->setPassphraseProvider(&provider);
+ jobCtx->setPinentryMode(Context::PinentryLoopback);
+
+ // Setup the job
+ job->setExportable(true);
+ job->setSigningKey(seckey);
+ job->setDupeOk(true);
+ job->setTrustSignature(TrustSignatureTrust::Partial, 2, QStringLiteral("example.net"));
+
+ connect(job.get(), &SignKeyJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ if (err2.code() == GPG_ERR_GENERAL) {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.\n"
+ "Hint: Run with GPGMEPP_INTERACTOR_DEBUG=stderr to debug the edit interaction.").arg(err2.asString())));
+ } else {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.").arg(err2.asString())));
+ }
+ }
+ });
+
+ err = job->start(target);
+ QVERIFY(!err);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the trust signature should have been added.
+ target.update();
+ const auto trustSignature = target.userID(0).signature(target.userID(0).numSignatures() - 1);
+ QVERIFY(trustSignature.isTrustSignature());
+ QCOMPARE(trustSignature.trustDepth(), 2u);
+ QCOMPARE(trustSignature.trustValue(), TrustSignatureTrust::Partial);
+ QVERIFY(trustSignature.trustScope());
+ const auto trustScope = QString::fromUtf8(trustSignature.trustScope());
+ QVERIFY(!trustScope.isEmpty());
+ const QRegExp regex{trustScope};
+ QVERIFY(regex.isValid());
+ QVERIFY(regex.indexIn(QStringLiteral("Foo <foo@example.net>")) != -1);
+ }
+ }
+
+ void test_tsign_multi_uid_key_and_then_tsign_it_again()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the signing key (alfa@example.net)
+ auto seckey = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!seckey.isNull());
+
+ // Get the target key (Bob / Bravo Test)
+ auto target = ctx->key("D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", err, false);
+ QVERIFY(!err);
+ QVERIFY(!target.isNull());
+ QVERIFY(target.numUserIDs() > 0);
+
+ // Create first trust signature
+ {
+ // Create the job
+ auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
+ QVERIFY(job);
+
+ // Hack in the passphrase provider
+ auto jobCtx = Job::context(job);
+ TestPassphraseProvider provider;
+ jobCtx->setPassphraseProvider(&provider);
+ jobCtx->setPinentryMode(Context::PinentryLoopback);
+
+ // Setup the job
+ job->setExportable(true);
+ job->setSigningKey(seckey);
+ job->setTrustSignature(TrustSignatureTrust::Complete, 1, QStringLiteral("example.org"));
+
+ connect(job, &SignKeyJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ if (err2.code() == GPG_ERR_GENERAL) {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.\n"
+ "Hint: Run with GPGMEPP_INTERACTOR_DEBUG=stderr to debug the edit interaction.").arg(err2.asString())));
+ } else {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.").arg(err2.asString())));
+ }
+ }
+ });
+
+ job->start(target);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the trust signature should have been added.
+ target.update();
+ const auto trustSignature = target.userID(0).signature(target.userID(0).numSignatures() - 1);
+ QVERIFY(trustSignature.isTrustSignature());
+ QCOMPARE(trustSignature.trustDepth(), 1u);
+ QCOMPARE(trustSignature.trustValue(), TrustSignatureTrust::Complete);
+ QVERIFY(trustSignature.trustScope());
+ const auto trustScope = QString::fromUtf8(trustSignature.trustScope());
+ QVERIFY(!trustScope.isEmpty());
+ const QRegExp regex{trustScope};
+ QVERIFY(regex.isValid());
+ QVERIFY(regex.indexIn(QStringLiteral("Foo <foo@example.org>")) != -1);
+ }
+
+ // Create second trust signature
+ {
+ // Create the job
+ auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
+ QVERIFY(job);
+
+ // Hack in the passphrase provider
+ auto jobCtx = Job::context(job);
+ TestPassphraseProvider provider;
+ jobCtx->setPassphraseProvider(&provider);
+ jobCtx->setPinentryMode(Context::PinentryLoopback);
+
+ // Setup the job
+ job->setExportable(true);
+ job->setSigningKey(seckey);
+ job->setDupeOk(true);
+ job->setTrustSignature(TrustSignatureTrust::Partial, 2, QStringLiteral("example.net"));
+
+ connect(job, &SignKeyJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ if (err2.code() == GPG_ERR_GENERAL) {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.\n"
+ "Hint: Run with GPGMEPP_INTERACTOR_DEBUG=stderr to debug the edit interaction.").arg(err2.asString())));
+ } else {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.").arg(err2.asString())));
+ }
+ }
+ });
+
+ err = job->start(target);
+ QVERIFY(!err);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the trust signature should have been added.
+ target.update();
+ const auto trustSignature = target.userID(0).signature(target.userID(0).numSignatures() - 1);
+ QVERIFY(trustSignature.isTrustSignature());
+ QCOMPARE(trustSignature.trustDepth(), 2u);
+ QCOMPARE(trustSignature.trustValue(), TrustSignatureTrust::Partial);
+ QVERIFY(trustSignature.trustScope());
+ const auto trustScope = QString::fromUtf8(trustSignature.trustScope());
+ QVERIFY(!trustScope.isEmpty());
+ const QRegExp regex{trustScope};
+ QVERIFY(regex.isValid());
+ QVERIFY(regex.indexIn(QStringLiteral("Foo <foo@example.net>")) != -1);
+ }
+ }
+
+ void test_tsign_first_uid_and_then_tsign_both_uids()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the signing key (alfa@example.net)
+ auto seckey = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!seckey.isNull());
+
+ // Get the target key (Mallory / Mike Test)
+ auto target = ctx->key("2686AA191A278013992C72EBBE794852BE5CF886", err, false);
+ QVERIFY(!err);
+ QVERIFY(!target.isNull());
+ QVERIFY(target.numUserIDs() > 0);
+
+ // Create first trust signature
+ {
+ // Create the job
+ auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
+ QVERIFY(job);
+
+ // Hack in the passphrase provider
+ auto jobCtx = Job::context(job);
+ TestPassphraseProvider provider;
+ jobCtx->setPassphraseProvider(&provider);
+ jobCtx->setPinentryMode(Context::PinentryLoopback);
+
+ // Setup the job
+ job->setExportable(true);
+ job->setSigningKey(seckey);
+ job->setUserIDsToSign({0});
+ job->setTrustSignature(TrustSignatureTrust::Complete, 1, QStringLiteral("example.org"));
+
+ connect(job, &SignKeyJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ if (err2.code() == GPG_ERR_GENERAL) {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.\n"
+ "Hint: Run with GPGMEPP_INTERACTOR_DEBUG=stderr to debug the edit interaction.").arg(err2.asString())));
+ } else {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.").arg(err2.asString())));
+ }
+ }
+ });
+
+ job->start(target);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the trust signature should have been added.
+ target.update();
+ const auto trustSignature = target.userID(0).signature(target.userID(0).numSignatures() - 1);
+ QVERIFY(trustSignature.isTrustSignature());
+ QCOMPARE(trustSignature.trustDepth(), 1u);
+ QCOMPARE(trustSignature.trustValue(), TrustSignatureTrust::Complete);
+ QVERIFY(trustSignature.trustScope());
+ const auto trustScope = QString::fromUtf8(trustSignature.trustScope());
+ QVERIFY(!trustScope.isEmpty());
+ const QRegExp regex{trustScope};
+ QVERIFY(regex.isValid());
+ QVERIFY(regex.indexIn(QStringLiteral("Foo <foo@example.org>")) != -1);
+ }
+
+ // Create second trust signature
+ {
+ // Create the job
+ auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
+ QVERIFY(job);
+
+ // Hack in the passphrase provider
+ auto jobCtx = Job::context(job);
+ TestPassphraseProvider provider;
+ jobCtx->setPassphraseProvider(&provider);
+ jobCtx->setPinentryMode(Context::PinentryLoopback);
+
+ // Setup the job
+ job->setExportable(true);
+ job->setSigningKey(seckey);
+ job->setDupeOk(true);
+ job->setTrustSignature(TrustSignatureTrust::Partial, 2, QStringLiteral("example.net"));
+
+ connect(job, &SignKeyJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ if (err2.code() == GPG_ERR_GENERAL) {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.\n"
+ "Hint: Run with GPGMEPP_INTERACTOR_DEBUG=stderr to debug the edit interaction.").arg(err2.asString())));
+ } else {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.").arg(err2.asString())));
+ }
+ }
+ });
+
+ err = job->start(target);
+ QVERIFY(!err);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the trust signature should have been added.
+ target.update();
+ const auto trustSignature = target.userID(0).signature(target.userID(0).numSignatures() - 1);
+ QVERIFY(trustSignature.isTrustSignature());
+ QCOMPARE(trustSignature.trustDepth(), 2u);
+ QCOMPARE(trustSignature.trustValue(), TrustSignatureTrust::Partial);
+ QVERIFY(trustSignature.trustScope());
+ const auto trustScope = QString::fromUtf8(trustSignature.trustScope());
+ QVERIFY(!trustScope.isEmpty());
+ const QRegExp regex{trustScope};
+ QVERIFY(regex.isValid());
+ QVERIFY(regex.indexIn(QStringLiteral("Foo <foo@example.net>")) != -1);
+ }
+ }
+
+ void test_tsign_all_uids_and_then_tsign_first_uid()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the signing key (alfa@example.net)
+ auto seckey = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!seckey.isNull());
+
+ // Get the target key (Echelon / Echo Test / Eve)
+ auto target = ctx->key("3531152DE293E26A07F504BC318C1FAEFAEF6D1B", err, false);
+ QVERIFY(!err);
+ QVERIFY(!target.isNull());
+ QVERIFY(target.numUserIDs() > 0);
+
+ // Create first trust signature
+ {
+ // Create the job
+ auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
+ QVERIFY(job);
+
+ // Hack in the passphrase provider
+ auto jobCtx = Job::context(job);
+ TestPassphraseProvider provider;
+ jobCtx->setPassphraseProvider(&provider);
+ jobCtx->setPinentryMode(Context::PinentryLoopback);
+
+ // Setup the job
+ job->setExportable(true);
+ job->setSigningKey(seckey);
+ job->setTrustSignature(TrustSignatureTrust::Complete, 1, QStringLiteral("example.org"));
+
+ connect(job, &SignKeyJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ if (err2.code() == GPG_ERR_GENERAL) {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.\n"
+ "Hint: Run with GPGMEPP_INTERACTOR_DEBUG=stderr to debug the edit interaction.").arg(err2.asString())));
+ } else {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.").arg(err2.asString())));
+ }
+ }
+ });
+
+ job->start(target);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the trust signature should have been added.
+ target.update();
+ const auto trustSignature = target.userID(0).signature(target.userID(0).numSignatures() - 1);
+ QVERIFY(trustSignature.isTrustSignature());
+ QCOMPARE(trustSignature.trustDepth(), 1u);
+ QCOMPARE(trustSignature.trustValue(), TrustSignatureTrust::Complete);
+ QVERIFY(trustSignature.trustScope());
+ const auto trustScope = QString::fromUtf8(trustSignature.trustScope());
+ QVERIFY(!trustScope.isEmpty());
+ const QRegExp regex{trustScope};
+ QVERIFY(regex.isValid());
+ QVERIFY(regex.indexIn(QStringLiteral("Foo <foo@example.org>")) != -1);
+ }
+
+ // Create second trust signature
+ {
+ // Create the job
+ auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
+ QVERIFY(job);
+
+ // Hack in the passphrase provider
+ auto jobCtx = Job::context(job);
+ TestPassphraseProvider provider;
+ jobCtx->setPassphraseProvider(&provider);
+ jobCtx->setPinentryMode(Context::PinentryLoopback);
+
+ // Setup the job
+ job->setExportable(true);
+ job->setSigningKey(seckey);
+ job->setUserIDsToSign({0});
+ job->setDupeOk(true);
+ job->setTrustSignature(TrustSignatureTrust::Partial, 2, QStringLiteral("example.net"));
+
+ connect(job, &SignKeyJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ if (err2.code() == GPG_ERR_GENERAL) {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.\n"
+ "Hint: Run with GPGMEPP_INTERACTOR_DEBUG=stderr to debug the edit interaction.").arg(err2.asString())));
+ } else {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.").arg(err2.asString())));
+ }
+ }
+ });
+
+ err = job->start(target);
+ QVERIFY(!err);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the trust signature should have been added.
+ target.update();
+ const auto trustSignature = target.userID(0).signature(target.userID(0).numSignatures() - 1);
+ QVERIFY(trustSignature.isTrustSignature());
+ QCOMPARE(trustSignature.trustDepth(), 2u);
+ QCOMPARE(trustSignature.trustValue(), TrustSignatureTrust::Partial);
+ QVERIFY(trustSignature.trustScope());
+ const auto trustScope = QString::fromUtf8(trustSignature.trustScope());
+ QVERIFY(!trustScope.isEmpty());
+ const QRegExp regex{trustScope};
+ QVERIFY(regex.isValid());
+ QVERIFY(regex.indexIn(QStringLiteral("Foo <foo@example.net>")) != -1);
+ }
+ }
+
+ void initTestCase()
+ {
+ QGpgMETest::initTestCase();
+ const QString gpgHome = qgetenv("GNUPGHOME");
+ QVERIFY(copyKeyrings(gpgHome, mDir.path()));
+ qputenv("GNUPGHOME", mDir.path().toUtf8());
+ QFile conf(mDir.path() + QStringLiteral("/gpg.conf"));
+ QVERIFY(conf.open(QIODevice::WriteOnly));
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() >= "2.2.18") {
+ conf.write("allow-weak-key-signatures");
+ }
+ conf.close();
+ }
+
+private:
+ QTemporaryDir mDir;
+};
+
+QTEST_MAIN(TestTrustSignatures)
+
+#include "t-trustsignatures.moc"
diff --git a/lang/qt/tests/t-various.cpp b/lang/qt/tests/t-various.cpp
index bec0a57..8563b68 100644
--- a/lang/qt/tests/t-various.cpp
+++ b/lang/qt/tests/t-various.cpp
@@ -46,6 +46,7 @@
#include "dn.h"
#include "data.h"
#include "dataprovider.h"
+#include "signkeyjob.h"
#include "t-support.h"
@@ -233,6 +234,131 @@ private Q_SLOTS:
delete ctx;
}
+ void testSignKeyWithoutExpiration()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the signing key (alfa@example.net)
+ auto seckey = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!seckey.isNull());
+
+ // Get the target key (Bob / Bravo Test)
+ auto target = ctx->key("D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", err, false);
+ QVERIFY(!err);
+ QVERIFY(!target.isNull());
+ QVERIFY(target.numUserIDs() > 0);
+
+ // Create the job
+ auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
+ QVERIFY(job);
+
+ // Hack in the passphrase provider
+ auto jobCtx = Job::context(job.get());
+ TestPassphraseProvider provider;
+ jobCtx->setPassphraseProvider(&provider);
+ jobCtx->setPinentryMode(Context::PinentryLoopback);
+
+ // Setup the job
+ job->setExportable(true);
+ job->setSigningKey(seckey);
+ job->setDupeOk(true);
+
+ connect(job.get(), &SignKeyJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ if (err2.code() == GPG_ERR_GENERAL) {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.\n"
+ "Hint: Run with GPGMEPP_INTERACTOR_DEBUG=stderr to debug the edit interaction.").arg(err2.asString())));
+ } else {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.").arg(err2.asString())));
+ }
+ }
+ });
+
+ job->start(target);
+ QSignalSpy spy{this, &TestVarious::asyncDone};
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the signature should have been added.
+ target.update();
+ const auto keySignature = target.userID(0).signature(target.userID(0).numSignatures() - 1);
+ QVERIFY(keySignature.neverExpires());
+ }
+
+ void testSignKeyWithExpiration()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the signing key (alfa@example.net)
+ auto seckey = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!seckey.isNull());
+
+ // Get the target key (Bob / Bravo Test)
+ auto target = ctx->key("D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", err, false);
+ QVERIFY(!err);
+ QVERIFY(!target.isNull());
+ QVERIFY(target.numUserIDs() > 0);
+
+ // Create the job
+ auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
+ QVERIFY(job);
+
+ // Hack in the passphrase provider
+ auto jobCtx = Job::context(job.get());
+ TestPassphraseProvider provider;
+ jobCtx->setPassphraseProvider(&provider);
+ jobCtx->setPinentryMode(Context::PinentryLoopback);
+
+ // Setup the job
+ job->setExportable(true);
+ job->setSigningKey(seckey);
+ job->setDupeOk(true);
+ job->setExpirationDate(QDate{2222, 2, 22});
+
+ connect(job.get(), &SignKeyJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ if (err2.code() == GPG_ERR_GENERAL) {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.\n"
+ "Hint: Run with GPGMEPP_INTERACTOR_DEBUG=stderr to debug the edit interaction.").arg(err2.asString())));
+ } else {
+ QFAIL(qPrintable(QString("The SignKeyJob failed with '%1'.").arg(err2.asString())));
+ }
+ }
+ });
+
+ QTest::ignoreMessage(QtWarningMsg, "Expiration of certification has been changed to QDate(\"2106-02-06\")");
+
+ job->start(target);
+ QSignalSpy spy{this, &TestVarious::asyncDone};
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the signature should have been added.
+ target.update();
+ const auto keySignature = target.userID(0).signature(target.userID(0).numSignatures() - 1);
+ QVERIFY(!keySignature.neverExpires());
+ const auto expirationDate = QDateTime::fromSecsSinceEpoch(keySignature.expirationTime()).date();
+ QCOMPARE(expirationDate, QDate(2106, 2, 6)); // expiration date is capped at 2106-02-06
+ }
+
void testVersion()
{
QVERIFY(EngineInfo::Version("2.1.0") < EngineInfo::Version("2.1.1"));
@@ -285,6 +411,12 @@ private Q_SLOTS:
const QString gpgHome = qgetenv("GNUPGHOME");
QVERIFY(copyKeyrings(gpgHome, mDir.path()));
qputenv("GNUPGHOME", mDir.path().toUtf8());
+ QFile conf(mDir.path() + QStringLiteral("/gpg.conf"));
+ QVERIFY(conf.open(QIODevice::WriteOnly));
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() >= "2.2.18") {
+ conf.write("allow-weak-key-signatures");
+ }
+ conf.close();
}
private:
diff --git a/m4/gpg-error.m4 b/m4/gpg-error.m4
index c9b235f..56a5d07 100644
--- a/m4/gpg-error.m4
+++ b/m4/gpg-error.m4
@@ -1,5 +1,6 @@
# gpg-error.m4 - autoconf macro to detect libgpg-error.
-# Copyright (C) 2002, 2003, 2004, 2011, 2014, 2018, 2020 g10 Code GmbH
+# Copyright (C) 2002, 2003, 2004, 2011, 2014, 2018, 2020, 2021
+# 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 +10,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: 2020-11-17
+# Last-changed: 2021-03-31
dnl AM_PATH_GPG_ERROR([MINIMUM-VERSION,
@@ -64,45 +65,79 @@ AC_DEFUN([AM_PATH_GPG_ERROR],
min_gpg_error_version=ifelse([$1], ,1.33,$1)
ok=no
- 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)
+ AC_PATH_PROG(GPGRT_CONFIG, gpgrt-config, no, [$prefix/bin:$PATH])
+ if test "$GPGRT_CONFIG" != "no"; then
+ # Determine gpgrt_libdir
+ #
+ # Get the prefix of gpgrt-config assuming it's something like:
+ # <PREFIX>/bin/gpgrt-config
+ gpgrt_prefix=${GPGRT_CONFIG%/*/*}
+ possible_libdir1=${gpgrt_prefix}/lib
+ # Determine by using system libdir-format with CC, it's like:
+ # Normal style: /usr/lib
+ # GNU cross style: /usr/<triplet>/lib
+ # Debian style: /usr/lib/<multiarch-name>
+ # Fedora/openSUSE style: /usr/lib, /usr/lib32 or /usr/lib64
+ # It is assumed that CC is specified to the one of host on cross build.
+ if libdir_candidates=$(${CC:-cc} -print-search-dirs | \
+ sed -n -e "/^libraries/{s/libraries: =//;s/:/\\
+/g;p;}"); then
+ # From the output of -print-search-dirs, select valid pkgconfig dirs.
+ libdir_candidates=$(for dir in $libdir_candidates; do
+ if p=$(cd $dir 2>/dev/null && pwd); then
+ test -d "$p/pkgconfig" && echo $p;
+ fi
+ done)
- 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
+ for possible_libdir0 in $libdir_candidates; do
+ # possible_libdir0:
+ # Fallback candidate, the one of system-installed (by $CC)
+ # (/usr/<triplet>/lib, /usr/lib/<multiarch-name> or /usr/lib32)
+ # possible_libdir1:
+ # Another candidate, user-locally-installed
+ # (<gpgrt_prefix>/lib)
+ # possible_libdir2
+ # Most preferred
+ # (<gpgrt_prefix>/<triplet>/lib,
+ # <gpgrt_prefix>/lib/<multiarch-name> or <gpgrt_prefix>/lib32)
+ if test "${possible_libdir0##*/}" = "lib"; then
+ possible_prefix0=${possible_libdir0%/lib}
+ possible_prefix0_triplet=${possible_prefix0##*/}
+ if test -z "$possible_prefix0_triplet"; then
+ continue
+ fi
+ possible_libdir2=${gpgrt_prefix}/$possible_prefix0_triplet/lib
+ else
+ possible_prefix0=${possible_libdir0%%/lib*}
+ possible_libdir2=${gpgrt_prefix}${possible_libdir0#$possible_prefix0}
fi
- fi
+ if test -f ${possible_libdir2}/pkgconfig/gpg-error.pc; then
+ gpgrt_libdir=${possible_libdir2}
+ elif test -f ${possible_libdir1}/pkgconfig/gpg-error.pc; then
+ gpgrt_libdir=${possible_libdir1}
+ elif test -f ${possible_libdir0}/pkgconfig/gpg-error.pc; then
+ gpgrt_libdir=${possible_libdir0}
+ fi
+ if test -n "$gpgrt_libdir"; then break; fi
+ done
+ else
+ # When we cannot determine system libdir-format, use this:
+ gpgrt_libdir=${possible_libdir1}
fi
+ else
+ unset GPGRT_CONFIG
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
+ if test -n "$gpgrt_libdir"; then
+ 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
- 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
+ unset GPGRT_CONFIG
fi
- else
+ elif test "$GPG_ERROR_CONFIG" != "no"; then
gpg_error_config_version=`$GPG_ERROR_CONFIG --version`
fi
if test "$GPG_ERROR_CONFIG" != "no"; then
@@ -123,22 +158,6 @@ 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
diff --git a/src/Makefile.am b/src/Makefile.am
index 35add9c..39c341f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -101,7 +101,7 @@ endif
# We use a global CFLAGS setting for all libraries
# versions, because then every object file is only compiled once.
-AM_CFLAGS = @LIBASSUAN_CFLAGS@ @GLIB_CFLAGS@
+AM_CFLAGS = @LIBASSUAN_CFLAGS@ @GPG_ERROR_CFLAGS@ @GLIB_CFLAGS@
gpgme_tool_SOURCES = gpgme-tool.c argparse.c argparse.h
gpgme_tool_LDADD = libgpgme.la @LIBASSUAN_LIBS@ @GPG_ERROR_LIBS@
diff --git a/src/Makefile.in b/src/Makefile.in
index 8b323ed..65d40af 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -617,7 +617,7 @@ libgpgme_la_SOURCES = $(main_sources) $(system_components_not_extra)
# We use a global CFLAGS setting for all libraries
# versions, because then every object file is only compiled once.
-AM_CFLAGS = @LIBASSUAN_CFLAGS@ @GLIB_CFLAGS@
+AM_CFLAGS = @LIBASSUAN_CFLAGS@ @GPG_ERROR_CFLAGS@ @GLIB_CFLAGS@
gpgme_tool_SOURCES = gpgme-tool.c argparse.c argparse.h
gpgme_tool_LDADD = libgpgme.la @LIBASSUAN_LIBS@ @GPG_ERROR_LIBS@
gpgme_json_SOURCES = gpgme-json.c cJSON.c cJSON.h
diff --git a/src/cJSON.c b/src/cJSON.c
index 7769b0e..1925a04 100644
--- a/src/cJSON.c
+++ b/src/cJSON.c
@@ -50,21 +50,13 @@
#include "cJSON.h"
+
/* Only use calloc. */
#define CALLOC_ONLY 1
/* Maximum recursion depth */
#define MAX_DEPTH 512
-/* To avoid that a compiler optimizes certain memset calls away, these
- macros may be used instead. */
-#define wipememory2(_ptr,_set,_len) do { \
- volatile char *_vptr=(volatile char *)(_ptr); \
- size_t _vlen=(_len); \
- while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
- } while(0)
-#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
-
/* We use malloc function wrappers from gpgrt (aka libgpg-error). */
#include <gpgrt.h>
#define xtrycalloc(a,b) gpgrt_calloc ((a), (b))
@@ -77,6 +69,16 @@
#endif
+static void
+wipememory (void *ptr, size_t len)
+{
+ /* Prevent compiler from optimizing away the call to memset by accessing
+ * memset through volatile pointer. */
+ static void *(*volatile memset_ptr)(void *, int, size_t) = (void *)memset;
+ memset_ptr (ptr, 0, len);
+}
+
+
static int
cJSON_strcasecmp (const char *s1, const char *s2)
{
diff --git a/src/context.h b/src/context.h
index 3ed3818..2792a16 100644
--- a/src/context.h
+++ b/src/context.h
@@ -174,6 +174,9 @@ struct gpgme_context
/* The optional trust-model override. */
char *trust_model;
+ /* The optional expiration date of a certification. */
+ char *cert_expire;
+
/* The operation data hooked into the context. */
ctx_op_data_t op_data;
diff --git a/src/conversion.c b/src/conversion.c
index 1d28096..17dce7f 100644
--- a/src/conversion.c
+++ b/src/conversion.c
@@ -43,6 +43,17 @@
+void
+_gpgme_wipememory (void *ptr, size_t len)
+{
+ /* Prevent compiler from optimizing away the call to memset by accessing
+ * memset through volatile pointer. */
+ static void *(*volatile memset_ptr)(void *, int, size_t) = (void *)memset;
+ memset_ptr (ptr, 0, len);
+}
+
+
+
static char *
do_strconcat (const char *s1, va_list arg_ptr)
{
diff --git a/src/data-identify.c b/src/data-identify.c
index eb65786..8e0295e 100644
--- a/src/data-identify.c
+++ b/src/data-identify.c
@@ -416,8 +416,8 @@ basic_detection (char *data, size_t datalen)
}
else if (ti.length == 11)
{
- if (!memcmp (s, "\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x02", 11))
- return GPGME_DATA_TYPE_CMS_OTHER; /* Auth Data. */
+ if (!memcmp (s, "\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x17", 11))
+ return GPGME_DATA_TYPE_CMS_ENCRYPTED; /* AuthEnveloped Data. */
}
}
diff --git a/src/data.c b/src/data.c
index 7059590..62b7231 100644
--- a/src/data.c
+++ b/src/data.c
@@ -52,7 +52,7 @@
*/
struct property_s
{
- gpgme_data_t dh; /* The data objcet or NULL if the slot is not used. */
+ gpgme_data_t dh; /* The data object or NULL if the slot is not used. */
uint64_t dserial; /* The serial number of the data object. */
struct {
unsigned int blankout : 1; /* Void the held data. */
@@ -339,6 +339,21 @@ _gpgme_data_release (gpgme_data_t dh)
remove_from_property_table (dh, dh->propidx);
if (dh->file_name)
free (dh->file_name);
+ if (dh->inbound_buffer)
+ {
+ if (dh->sensitive)
+ _gpgme_wipememory (dh->inbound_buffer, dh->io_buffer_size);
+ free (dh->inbound_buffer);
+ }
+ if (dh->outbound_buffer)
+ {
+ if (dh->sensitive)
+ _gpgme_wipememory (dh->outbound_buffer, dh->io_buffer_size);
+ free (dh->outbound_buffer);
+ }
+ if (dh->sensitive)
+ _gpgme_wipememory (dh->outboundspace, BUFFER_SIZE);
+
free (dh);
}
@@ -431,11 +446,11 @@ gpgme_data_seek (gpgme_data_t dh, gpgme_off_t offset, int whence)
/* For relative movement, we must take into account the actual
position of the read counter. */
if (whence == SEEK_CUR)
- offset -= dh->pending_len;
+ offset -= dh->outbound_pending;
offset = (*dh->cbs->seek) (dh, offset, whence);
if (offset >= 0)
- dh->pending_len = 0;
+ dh->outbound_pending = 0;
return TRACE_SYSRES ((int)offset);
}
@@ -555,6 +570,28 @@ gpgme_data_set_flag (gpgme_data_t dh, const char *name, const char *value)
{
dh->size_hint= value? _gpgme_string_to_off (value) : 0;
}
+ else if (!strcmp (name, "io-buffer-size"))
+ {
+ gpgme_off_t val;
+
+ /* We may set this only once. */
+ if (dh->io_buffer_size)
+ return gpg_error (GPG_ERR_CONFLICT);
+
+ val = value? _gpgme_string_to_off (value) : 0;
+ if (val > 1024*1024)
+ val = 1024*1024; /* Cap at 1MiB */
+ else if (val < BUFFER_SIZE)
+ val = 0; /* We can use the default buffer. */
+
+ /* Actual allocation happens as needed but we round it to a
+ * multiple of 1k. */
+ dh->io_buffer_size = ((val + 1023)/1024)*1024;
+ }
+ else if (!strcmp (name, "sensitive"))
+ {
+ dh->sensitive = (value && *value)? !!atoi (value) : 0;
+ }
else
return gpg_error (GPG_ERR_UNKNOWN_NAME);
@@ -569,14 +606,35 @@ gpgme_error_t
_gpgme_data_inbound_handler (void *opaque, int fd)
{
struct io_cb_data *data = (struct io_cb_data *) opaque;
+ gpg_error_t err;
gpgme_data_t dh = (gpgme_data_t) data->handler_value;
- char buffer[BUFFER_SIZE];
- char *bufp = buffer;
+ char bufferspace[BUFFER_SIZE];
+ char *buffer;
+ size_t buffer_size;
+ char *bufp;
gpgme_ssize_t buflen;
TRACE_BEG (DEBUG_CTX, "_gpgme_data_inbound_handler", dh,
"fd=%d", fd);
- buflen = _gpgme_io_read (fd, buffer, BUFFER_SIZE);
+ if (dh->io_buffer_size)
+ {
+ if (!dh->inbound_buffer)
+ {
+ dh->inbound_buffer = malloc (dh->io_buffer_size);
+ if (!dh->inbound_buffer)
+ return TRACE_ERR (gpg_error_from_syserror ());
+ }
+ buffer_size = dh->io_buffer_size;
+ buffer = dh->inbound_buffer;
+ }
+ else
+ {
+ buffer_size = BUFFER_SIZE;
+ buffer = bufferspace;
+ }
+ bufp = buffer;
+
+ buflen = _gpgme_io_read (fd, buffer, buffer_size);
if (buflen < 0)
return gpg_error_from_syserror ();
if (buflen == 0)
@@ -589,12 +647,21 @@ _gpgme_data_inbound_handler (void *opaque, int fd)
{
gpgme_ssize_t amt = gpgme_data_write (dh, bufp, buflen);
if (amt == 0 || (amt < 0 && errno != EINTR))
- return TRACE_ERR (gpg_error_from_syserror ());
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
bufp += amt;
buflen -= amt;
}
while (buflen > 0);
- return TRACE_ERR (0);
+ err = 0;
+
+ leave:
+ if (dh->sensitive && buffer == bufferspace)
+ _gpgme_wipememory (bufferspace, BUFFER_SIZE);
+
+ return TRACE_ERR (err);
}
@@ -603,13 +670,34 @@ _gpgme_data_outbound_handler (void *opaque, int fd)
{
struct io_cb_data *data = (struct io_cb_data *) opaque;
gpgme_data_t dh = (gpgme_data_t) data->handler_value;
+ char *buffer;
+ size_t buffer_size;
gpgme_ssize_t nwritten;
TRACE_BEG (DEBUG_CTX, "_gpgme_data_outbound_handler", dh,
"fd=%d", fd);
- if (!dh->pending_len)
+ if (dh->io_buffer_size)
+ {
+ if (!dh->outbound_buffer)
+ {
+ dh->outbound_buffer = malloc (dh->io_buffer_size);
+ if (!dh->outbound_buffer)
+ return TRACE_ERR (gpg_error_from_syserror ());
+ dh->outbound_pending = 0;
+ }
+ buffer_size = dh->io_buffer_size;
+ buffer = dh->outbound_buffer;
+ }
+ else
+ {
+ buffer_size = BUFFER_SIZE;
+ buffer = dh->outboundspace;
+ }
+
+
+ if (!dh->outbound_pending)
{
- gpgme_ssize_t amt = gpgme_data_read (dh, dh->pending, BUFFER_SIZE);
+ gpgme_ssize_t amt = gpgme_data_read (dh, buffer, buffer_size);
if (amt < 0)
return TRACE_ERR (gpg_error_from_syserror ());
if (amt == 0)
@@ -617,10 +705,10 @@ _gpgme_data_outbound_handler (void *opaque, int fd)
_gpgme_io_close (fd);
return TRACE_ERR (0);
}
- dh->pending_len = amt;
+ dh->outbound_pending = amt;
}
- nwritten = _gpgme_io_write (fd, dh->pending, dh->pending_len);
+ nwritten = _gpgme_io_write (fd, buffer, dh->outbound_pending);
if (nwritten == -1 && errno == EAGAIN)
return TRACE_ERR (0);
@@ -637,9 +725,9 @@ _gpgme_data_outbound_handler (void *opaque, int fd)
if (nwritten <= 0)
return TRACE_ERR (gpg_error_from_syserror ());
- if (nwritten < dh->pending_len)
- memmove (dh->pending, dh->pending + nwritten, dh->pending_len - nwritten);
- dh->pending_len -= nwritten;
+ if (nwritten < dh->outbound_pending)
+ memmove (buffer, buffer + nwritten, dh->outbound_pending - nwritten);
+ dh->outbound_pending -= nwritten;
return TRACE_ERR (0);
}
diff --git a/src/data.h b/src/data.h
index 481a245..648d976 100644
--- a/src/data.h
+++ b/src/data.h
@@ -33,6 +33,22 @@
#include "gpgme.h"
+/* Figure out the standard size for internal data buffers. */
+#ifdef PIPE_BUF
+# define BUFFER_SIZE PIPE_BUF
+#else
+# ifdef _POSIX_PIPE_BUF
+# define BUFFER_SIZE _POSIX_PIPE_BUF
+# else
+# ifdef HAVE_W32_SYSTEM
+# define BUFFER_SIZE 4096
+# else
+# define BUFFER_SIZE 512
+# endif
+# endif
+#endif
+
+
/* Read up to SIZE bytes into buffer BUFFER from the data object with
the handle DH. Return the number of characters read, 0 on EOF and
@@ -76,24 +92,33 @@ struct gpgme_data
gpgme_data_encoding_t encoding;
unsigned int propidx; /* Index into the property table. */
-#ifdef PIPE_BUF
-#define BUFFER_SIZE PIPE_BUF
-#else
-#ifdef _POSIX_PIPE_BUF
-#define BUFFER_SIZE _POSIX_PIPE_BUF
-#else
-#define BUFFER_SIZE 512
-#endif
-#endif
- char pending[BUFFER_SIZE];
- int pending_len;
-
/* File name of the data object. */
char *file_name;
/* Hint on the to be expected total size of the data. */
gpgme_off_t size_hint;
+ /* If no 0 the size of an allocated inbound or outpund buffers. The
+ * value is at least BUFFER_SIZE and capped at 1MiB. */
+ unsigned int io_buffer_size;
+
+ /* If not NULL a malloced buffer used for inbound data used instead
+ * of the handler's static buffer. Its size is io_buffer_size. */
+ char *inbound_buffer;
+
+ /* A default memory space for the outbound handler and the number of
+ * actual pending bytes. If outbound_buffer is not NULL, this is a
+ * malloced buffer used instead of the outboundspace. Its malloced
+ * size is io_buffer_size. */
+ char outboundspace[BUFFER_SIZE];
+ unsigned int outbound_pending;
+ char *outbound_buffer;
+
+ /* If set sensitive data is conveyed via the internal buffer. This
+ * flags overwrites the memory of the buffers with zero before they
+ * are released. */
+ unsigned int sensitive:1;
+
union
{
/* For gpgme_data_new_from_fd. */
diff --git a/src/engine-gpg.c b/src/engine-gpg.c
index 9a9a26e..b51ea17 100644
--- a/src/engine-gpg.c
+++ b/src/engine-gpg.c
@@ -1961,6 +1961,27 @@ append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */,
static gpgme_error_t
+append_args_from_cert_expire (engine_gpg_t gpg, gpgme_ctx_t ctx)
+{
+ gpgme_error_t err;
+
+ if (ctx->cert_expire)
+ {
+ /* Override ask-cert-expire set in the configuration, so that the specified
+ * default is actually used. */
+ err = add_arg (gpg, "--no-ask-cert-expire");
+ if (!err)
+ err = add_arg (gpg, "--default-cert-expire");
+ if (!err)
+ err = add_arg (gpg, ctx->cert_expire);
+ }
+ else
+ err = 0;
+ return err;
+}
+
+
+static gpgme_error_t
gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,
gpgme_ctx_t ctx /* FIXME */)
{
@@ -1976,6 +1997,8 @@ gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,
if (!err)
err = append_args_from_sig_notations (gpg, ctx, NOTATION_FLAG_CERT);
if (!err)
+ err = append_args_from_cert_expire (gpg, ctx);
+ if (!err)
err = add_arg (gpg, type == 0 ? "--edit-key" : "--card-edit");
if (!err)
err = add_data (gpg, out, 1, 1);
@@ -2336,13 +2359,8 @@ export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
if ((mode & GPGME_EXPORT_MODE_MINIMAL))
{
- if ((mode & GPGME_EXPORT_MODE_NOUID))
- err = add_arg (gpg, "--export-options=export-minimal,export-drop-uids");
- else
- err = add_arg (gpg, "--export-options=export-minimal");
+ err = add_arg (gpg, "--export-options=export-minimal");
}
- else if ((mode & GPGME_EXPORT_MODE_NOUID))
- err = add_arg (gpg, "--export-options=export-drop-uids");
if (err)
;
@@ -2358,8 +2376,6 @@ export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
else if ((mode & GPGME_EXPORT_MODE_EXTERN))
{
err = add_arg (gpg, "--send-keys");
- if (!err && (mode & GPGME_EXPORT_MODE_NOUID))
- err = add_arg (gpg, "--keyserver-options=export-drop-uids");
}
else
{
@@ -3171,6 +3187,13 @@ gpg_keysign (void *engine, gpgme_key_t key, const char *userid,
else
err = add_arg (gpg, "--quick-sign-key");
+ /* The force flag as only an effect with recent gpg versions; if the
+ * gpg version is too old, the signature will simply not be created.
+ * I think this is better than bailing out. */
+ if (!err && (flags & GPGME_KEYSIGN_FORCE)
+ && have_gpg_version (gpg, "2.2.28"))
+ err = add_arg (gpg, "--force-sign-key");
+
if (!err)
err = append_args_from_signers (gpg, ctx);
diff --git a/src/export.c b/src/export.c
index 879a54f..4cee0ef 100644
--- a/src/export.c
+++ b/src/export.c
@@ -129,7 +129,6 @@ export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern,
|GPGME_EXPORT_MODE_SECRET
|GPGME_EXPORT_MODE_SSH
|GPGME_EXPORT_MODE_RAW
- |GPGME_EXPORT_MODE_NOUID
|GPGME_EXPORT_MODE_PKCS12)))
return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE. */
diff --git a/src/gpgme.c b/src/gpgme.c
index 8bc11d5..255d116 100644
--- a/src/gpgme.c
+++ b/src/gpgme.c
@@ -253,6 +253,7 @@ gpgme_release (gpgme_ctx_t ctx)
free (ctx->request_origin);
free (ctx->auto_key_locate);
free (ctx->trust_model);
+ free (ctx->cert_expire);
_gpgme_engine_info_release (ctx->engine_info);
ctx->engine_info = NULL;
DESTROY_LOCK (ctx->lock);
@@ -578,6 +579,13 @@ gpgme_set_ctx_flag (gpgme_ctx_t ctx, const char *name, const char *value)
{
ctx->extended_edit = abool;
}
+ else if (!strcmp (name, "cert-expire"))
+ {
+ free (ctx->cert_expire);
+ ctx->cert_expire = strdup (value);
+ if (!ctx->cert_expire)
+ err = gpg_error_from_syserror ();
+ }
else
err = gpg_error (GPG_ERR_UNKNOWN_NAME);
@@ -647,6 +655,10 @@ gpgme_get_ctx_flag (gpgme_ctx_t ctx, const char *name)
{
return ctx->extended_edit ? "1":"";
}
+ else if (!strcmp (name, "cert-expire"))
+ {
+ return ctx->cert_expire? ctx->cert_expire : "";
+ }
else
return NULL;
}
diff --git a/src/gpgme.h.in b/src/gpgme.h.in
index 1defa4d..5c74afd 100644
--- a/src/gpgme.h.in
+++ b/src/gpgme.h.in
@@ -406,7 +406,6 @@ gpgme_pinentry_mode_t;
#define GPGME_EXPORT_MODE_SECRET 16
#define GPGME_EXPORT_MODE_RAW 32
#define GPGME_EXPORT_MODE_PKCS12 64
-#define GPGME_EXPORT_MODE_NOUID 128 /* Experimental(!)*/
#define GPGME_EXPORT_MODE_SSH 256
typedef unsigned int gpgme_export_mode_t;
@@ -628,7 +627,13 @@ struct _gpgme_key_sig
unsigned int exportable : 1;
/* Internal to GPGME, do not use. */
- unsigned int _unused : 28;
+ unsigned int _unused : 12;
+
+ /* The depth of a trust signature, 0 if no trust signature. */
+ unsigned int trust_depth : 8;
+
+ /* The trust value of a trust signature, 0 if no trust signature. */
+ unsigned int trust_value : 8;
/* The public key algorithm used to create the signature. */
gpgme_pubkey_algo_t pubkey_algo;
@@ -675,6 +680,9 @@ struct _gpgme_key_sig
/* Internal to GPGME, do not use. */
gpgme_sig_notation_t _last_notation;
+
+ /* The scope of a trust signature. Might be NULL. */
+ char *trust_scope;
};
typedef struct _gpgme_key_sig *gpgme_key_sig_t;
@@ -1906,6 +1914,7 @@ gpgme_error_t gpgme_op_delete_ext (gpgme_ctx_t ctx, const gpgme_key_t key,
#define GPGME_KEYSIGN_LOCAL (1 << 7) /* Create a local signature. */
#define GPGME_KEYSIGN_LFSEP (1 << 8) /* Indicate LF separated user ids. */
#define GPGME_KEYSIGN_NOEXPIRE (1 << 9) /* Force no expiration. */
+#define GPGME_KEYSIGN_FORCE (1 << 10) /* Force creation. */
/* Sign the USERID of KEY using the current set of signers. */
@@ -2463,6 +2472,11 @@ char *gpgme_addrspec_from_uid (const char *uid);
* Deprecated types, constants and functions.
*/
+/* This is a former experimental only features. The constant is
+ * provided to not break existing code in the compiler phase. */
+#define GPGME_EXPORT_MODE_NOUID 128 /* Do not use! */
+
+
/* The possible stati for gpgme_op_edit. The use of that function and
* these status codes are deprecated in favor of gpgme_op_interact. */
typedef enum
diff --git a/src/key.c b/src/key.c
index e4b8577..322bd0a 100644
--- a/src/key.c
+++ b/src/key.c
@@ -369,6 +369,7 @@ gpgme_key_unref (gpgme_key_t key)
notation = next_notation;
}
+ free (keysig->trust_scope);
free (keysig);
keysig = next_keysig;
}
diff --git a/src/keylist.c b/src/keylist.c
index a4de3ad..f2c90d2 100644
--- a/src/keylist.c
+++ b/src/keylist.c
@@ -734,7 +734,7 @@ keylist_colon_handler (void *priv, char *line)
}
/* Field 18 has the compliance flags. */
- if (fields >= 17 && *field[17])
+ if (fields >= 18 && *field[17])
PARSE_COMPLIANCE_FLAGS (field[17], subkey);
if (fields >= 20)
@@ -817,7 +817,7 @@ keylist_colon_handler (void *priv, char *line)
}
/* Field 18 has the compliance flags. */
- if (fields >= 17 && *field[17])
+ if (fields >= 18 && *field[17])
PARSE_COMPLIANCE_FLAGS (field[17], subkey);
break;
@@ -967,6 +967,30 @@ keylist_colon_handler (void *priv, char *line)
if (fields >= 7)
keysig->expires = _gpgme_parse_timestamp (field[6], NULL);
+ /* Field 8 has the trust depth and the trust value. */
+ if (fields >= 8 && *field[7])
+ {
+ const char *trust_depth = field[7];
+ char *trust_value = strchr (field[7] + 1, ' ');
+ if (trust_value)
+ *(trust_value++) = '\0';
+ if (trust_value)
+ {
+ int depth = atoi (trust_depth);
+ int value = atoi (trust_value);
+
+ if (depth >= 1 && depth < 256)
+ keysig->trust_depth = depth;
+ if (value >= 1 && value < 256)
+ keysig->trust_value = value;
+ }
+ }
+
+ /* Field 9 has the trust signature scope (a regular expression). */
+ if (fields >= 9)
+ if (_gpgme_decode_c_string (field[8], &keysig->trust_scope, 0))
+ return gpg_error (GPG_ERR_ENOMEM); /* FIXME */
+
/* Field 11 has the signature class (eg, 0x30 means revoked). */
if (fields >= 11)
if (field[10][0] && field[10][1])
@@ -991,7 +1015,7 @@ keylist_colon_handler (void *priv, char *line)
return 0;
assert (opd->tmp_keysig == key->_last_uid->_last_keysig);
- if (fields >= 4)
+ if (fields >= 5)
{
/* Field 2 has the subpacket type. */
int type = atoi (field[1]);
diff --git a/src/util.h b/src/util.h
index bc78c9b..8907584 100644
--- a/src/util.h
+++ b/src/util.h
@@ -96,6 +96,9 @@ int _gpgme_ttyname_r (int fd, char *buf, size_t buflen);
/*-- conversion.c --*/
+/* Make sure to to erase the memory (PTR,LEN). */
+void _gpgme_wipememory (void *ptr, size_t len);
+
/* Concatenate the string S1 with all the following strings up to a
NULL. Returns a malloced buffer with the new string or NULL on a
malloc error or if too many arguments are given. */
diff --git a/tests/Makefile.in b/tests/Makefile.in
index 689ec3b..abf1aae 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/tests/gpg/Makefile.am b/tests/gpg/Makefile.am
index 594a642..d24a312 100644
--- a/tests/gpg/Makefile.am
+++ b/tests/gpg/Makefile.am
@@ -39,7 +39,7 @@ c_tests = \
t-encrypt t-encrypt-sym t-encrypt-sign t-sign t-signers \
t-decrypt t-verify t-decrypt-verify t-sig-notation t-export \
t-import t-edit t-keylist t-keylist-sig t-keylist-secret-sig t-wait \
- t-encrypt-large t-file-name t-gpgconf t-encrypt-mixed \
+ t-encrypt-large t-file-name t-gpgconf t-encrypt-mixed t-edit-sign \
$(tests_unix)
TESTS = initial.test $(c_tests) final.test
@@ -104,6 +104,8 @@ pubring-stamp: $(srcdir)/pubdemo.asc gpg-sample.stamp
gpg.conf:
# This is required for t-sig-notations.
echo no-force-v3-sigs > ./gpg.conf
+# This is required for t-edit-sign.
+ echo allow-weak-key-signatures >> ./gpg.conf
gpg-agent.conf:
# This is required for gpg2, which does not support command fd for the
diff --git a/tests/gpg/Makefile.in b/tests/gpg/Makefile.in
index edb021e..9fcd92b 100644
--- a/tests/gpg/Makefile.in
+++ b/tests/gpg/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -143,7 +143,8 @@ am__EXEEXT_2 = t-encrypt$(EXEEXT) t-encrypt-sym$(EXEEXT) \
t-edit$(EXEEXT) t-keylist$(EXEEXT) t-keylist-sig$(EXEEXT) \
t-keylist-secret-sig$(EXEEXT) t-wait$(EXEEXT) \
t-encrypt-large$(EXEEXT) t-file-name$(EXEEXT) \
- t-gpgconf$(EXEEXT) t-encrypt-mixed$(EXEEXT) $(am__EXEEXT_1)
+ t-gpgconf$(EXEEXT) t-encrypt-mixed$(EXEEXT) \
+ t-edit-sign$(EXEEXT) $(am__EXEEXT_1)
@HAVE_W32_SYSTEM_FALSE@am__EXEEXT_3 = t-cancel$(EXEEXT)
am__EXEEXT_4 = t-genkey$(EXEEXT) $(am__EXEEXT_3)
PROGRAMS = $(noinst_PROGRAMS)
@@ -166,6 +167,10 @@ t_edit_SOURCES = t-edit.c
t_edit_OBJECTS = t-edit.$(OBJEXT)
t_edit_LDADD = $(LDADD)
t_edit_DEPENDENCIES = ../../src/libgpgme.la
+t_edit_sign_SOURCES = t-edit-sign.c
+t_edit_sign_OBJECTS = t-edit-sign.$(OBJEXT)
+t_edit_sign_LDADD = $(LDADD)
+t_edit_sign_DEPENDENCIES = ../../src/libgpgme.la
t_encrypt_SOURCES = t-encrypt.c
t_encrypt_OBJECTS = t-encrypt.$(OBJEXT)
t_encrypt_LDADD = $(LDADD)
@@ -268,13 +273,13 @@ depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/t-cancel.Po \
./$(DEPDIR)/t-decrypt-verify.Po ./$(DEPDIR)/t-decrypt.Po \
- ./$(DEPDIR)/t-edit.Po ./$(DEPDIR)/t-encrypt-large.Po \
- ./$(DEPDIR)/t-encrypt-mixed.Po ./$(DEPDIR)/t-encrypt-sign.Po \
- ./$(DEPDIR)/t-encrypt-sym.Po ./$(DEPDIR)/t-encrypt.Po \
- ./$(DEPDIR)/t-eventloop.Po ./$(DEPDIR)/t-export.Po \
- ./$(DEPDIR)/t-file-name.Po ./$(DEPDIR)/t-genkey.Po \
- ./$(DEPDIR)/t-gpgconf.Po ./$(DEPDIR)/t-import.Po \
- ./$(DEPDIR)/t-keylist-secret-sig.Po \
+ ./$(DEPDIR)/t-edit-sign.Po ./$(DEPDIR)/t-edit.Po \
+ ./$(DEPDIR)/t-encrypt-large.Po ./$(DEPDIR)/t-encrypt-mixed.Po \
+ ./$(DEPDIR)/t-encrypt-sign.Po ./$(DEPDIR)/t-encrypt-sym.Po \
+ ./$(DEPDIR)/t-encrypt.Po ./$(DEPDIR)/t-eventloop.Po \
+ ./$(DEPDIR)/t-export.Po ./$(DEPDIR)/t-file-name.Po \
+ ./$(DEPDIR)/t-genkey.Po ./$(DEPDIR)/t-gpgconf.Po \
+ ./$(DEPDIR)/t-import.Po ./$(DEPDIR)/t-keylist-secret-sig.Po \
./$(DEPDIR)/t-keylist-sig.Po ./$(DEPDIR)/t-keylist.Po \
./$(DEPDIR)/t-sig-notation.Po ./$(DEPDIR)/t-sign.Po \
./$(DEPDIR)/t-signers.Po \
@@ -301,14 +306,14 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = t-cancel.c t-decrypt.c t-decrypt-verify.c t-edit.c \
- t-encrypt.c t-encrypt-large.c t-encrypt-mixed.c \
+ t-edit-sign.c t-encrypt.c t-encrypt-large.c t-encrypt-mixed.c \
t-encrypt-sign.c t-encrypt-sym.c t-eventloop.c t-export.c \
t-file-name.c t-genkey.c t-gpgconf.c t-import.c t-keylist.c \
t-keylist-secret-sig.c t-keylist-sig.c t-sig-notation.c \
t-sign.c t-signers.c t-thread-keylist.c \
t-thread-keylist-verify.c t-thread1.c t-verify.c t-wait.c
DIST_SOURCES = t-cancel.c t-decrypt.c t-decrypt-verify.c t-edit.c \
- t-encrypt.c t-encrypt-large.c t-encrypt-mixed.c \
+ t-edit-sign.c t-encrypt.c t-encrypt-large.c t-encrypt-mixed.c \
t-encrypt-sign.c t-encrypt-sym.c t-eventloop.c t-export.c \
t-file-name.c t-genkey.c t-gpgconf.c t-import.c t-keylist.c \
t-keylist-secret-sig.c t-keylist-sig.c t-sig-notation.c \
@@ -578,7 +583,7 @@ c_tests = \
t-encrypt t-encrypt-sym t-encrypt-sign t-sign t-signers \
t-decrypt t-verify t-decrypt-verify t-sig-notation t-export \
t-import t-edit t-keylist t-keylist-sig t-keylist-secret-sig t-wait \
- t-encrypt-large t-file-name t-gpgconf t-encrypt-mixed \
+ t-encrypt-large t-file-name t-gpgconf t-encrypt-mixed t-edit-sign \
$(tests_unix)
CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
@@ -672,6 +677,10 @@ t-edit$(EXEEXT): $(t_edit_OBJECTS) $(t_edit_DEPENDENCIES) $(EXTRA_t_edit_DEPENDE
@rm -f t-edit$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(t_edit_OBJECTS) $(t_edit_LDADD) $(LIBS)
+t-edit-sign$(EXEEXT): $(t_edit_sign_OBJECTS) $(t_edit_sign_DEPENDENCIES) $(EXTRA_t_edit_sign_DEPENDENCIES)
+ @rm -f t-edit-sign$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(t_edit_sign_OBJECTS) $(t_edit_sign_LDADD) $(LIBS)
+
t-encrypt$(EXEEXT): $(t_encrypt_OBJECTS) $(t_encrypt_DEPENDENCIES) $(EXTRA_t_encrypt_DEPENDENCIES)
@rm -f t-encrypt$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(t_encrypt_OBJECTS) $(t_encrypt_LDADD) $(LIBS)
@@ -769,6 +778,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-cancel.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-decrypt-verify.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-decrypt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-edit-sign.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-edit.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-encrypt-large.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-encrypt-mixed.Po@am__quote@ # am--include-marker
@@ -1012,7 +1022,8 @@ all-am: Makefile $(PROGRAMS) $(HEADERS)
installdirs:
install: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-am
-install-exec: install-exec-am
+install-exec: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-am
install-data: install-data-am
uninstall: uninstall-am
@@ -1052,6 +1063,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/t-cancel.Po
-rm -f ./$(DEPDIR)/t-decrypt-verify.Po
-rm -f ./$(DEPDIR)/t-decrypt.Po
+ -rm -f ./$(DEPDIR)/t-edit-sign.Po
-rm -f ./$(DEPDIR)/t-edit.Po
-rm -f ./$(DEPDIR)/t-encrypt-large.Po
-rm -f ./$(DEPDIR)/t-encrypt-mixed.Po
@@ -1123,6 +1135,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/t-cancel.Po
-rm -f ./$(DEPDIR)/t-decrypt-verify.Po
-rm -f ./$(DEPDIR)/t-decrypt.Po
+ -rm -f ./$(DEPDIR)/t-edit-sign.Po
-rm -f ./$(DEPDIR)/t-edit.Po
-rm -f ./$(DEPDIR)/t-encrypt-large.Po
-rm -f ./$(DEPDIR)/t-encrypt-mixed.Po
@@ -1164,7 +1177,8 @@ ps-am:
uninstall-am:
-.MAKE: all check check-am install install-am install-strip
+.MAKE: all check check-am install install-am install-exec \
+ install-strip
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \
check-am clean clean-generic clean-libtool clean-local \
@@ -1205,6 +1219,8 @@ pubring-stamp: $(srcdir)/pubdemo.asc gpg-sample.stamp
gpg.conf:
# This is required for t-sig-notations.
echo no-force-v3-sigs > ./gpg.conf
+# This is required for t-edit-sign.
+ echo allow-weak-key-signatures >> ./gpg.conf
gpg-agent.conf:
# This is required for gpg2, which does not support command fd for the
diff --git a/tests/gpg/t-edit-sign.c b/tests/gpg/t-edit-sign.c
new file mode 100644
index 0000000..2f98362
--- /dev/null
+++ b/tests/gpg/t-edit-sign.c
@@ -0,0 +1,201 @@
+/* t-edit-sign.c - Regression test.
+ * Copyright (C) 2000 Werner Koch (dd9jn)
+ * Copyright (C) 2001, 2002, 2003, 2004, 2021 g10 Code GmbH
+ * Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * GPGME 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <https://gnu.org/licenses/>.
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+/* We need to include config.h so that we know whether we are building
+ with large file system (LFS) support. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <gpgme.h>
+
+#include "t-support.h"
+
+
+static void
+flush_data (gpgme_data_t dh)
+{
+ char buf[100];
+ int ret;
+
+ ret = gpgme_data_seek (dh, 0, SEEK_SET);
+ if (ret)
+ fail_if_err (gpgme_error_from_errno (errno));
+ while ((ret = gpgme_data_read (dh, buf, 100)) > 0)
+ fwrite (buf, ret, 1, stdout);
+ if (ret < 0)
+ fail_if_err (gpgme_error_from_errno (errno));
+}
+
+
+gpgme_error_t
+interact_fnc (void *opaque, const char *status, const char *args, int fd)
+{
+ const char *result = NULL;
+ gpgme_data_t out = (gpgme_data_t) opaque;
+
+ fputs ("[-- Response --]\n", stdout);
+ flush_data (out);
+
+ fprintf (stdout, "[-- Code: %s, %s --]\n", status, args);
+
+ if (fd >= 0)
+ {
+ if (!strcmp (args, "keyedit.prompt"))
+ {
+ static int step = 0;
+
+ switch (step)
+ {
+ case 0:
+ result = "fpr";
+ break;
+ case 1:
+ /* This fixes the primary user ID so the keylisting
+ tests will have predictable output. */
+ result = "1";
+ break;
+ case 2:
+ result = "sign";
+ break;
+
+ default:
+ result = "quit";
+ break;
+ }
+ step++;
+ }
+ else if (!strcmp (args, "keyedit.save.okay"))
+ result = "Y";
+ else if (!strcmp (args, "sign_uid.okay"))
+ result = "Y";
+ }
+
+ if (result)
+ {
+ gpgme_io_writen (fd, result, strlen (result));
+ gpgme_io_writen (fd, "\n", 1);
+ }
+ return 0;
+}
+
+
+int
+main (int argc, char **argv)
+{
+ gpgme_ctx_t ctx;
+ gpgme_error_t err;
+ gpgme_data_t out = NULL;
+ const char *signer_fpr = "A0FF4590BB6122EDEF6E3C542D727CC768697734"; /* Alpha Test */
+ gpgme_key_t signing_key = NULL;
+ const char *key_fpr = "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2"; /* Bravo Test */
+ gpgme_key_t key = NULL;
+ gpgme_key_t signed_key = NULL;
+ gpgme_user_id_t signed_uid = NULL;
+ gpgme_key_sig_t key_sig = NULL;
+ char *agent_info;
+ int mode;
+
+ (void)argc;
+ (void)argv;
+
+ init_gpgme (GPGME_PROTOCOL_OpenPGP);
+
+ err = gpgme_new (&ctx);
+ fail_if_err (err);
+
+ /* Sign the key */
+ agent_info = getenv("GPG_AGENT_INFO");
+ if (!(agent_info && strchr (agent_info, ':')))
+ gpgme_set_passphrase_cb (ctx, passphrase_cb, 0);
+
+ err = gpgme_get_key (ctx, signer_fpr, &signing_key, 1);
+ fail_if_err (err);
+ err = gpgme_signers_add (ctx, signing_key);
+ fail_if_err (err);
+
+ err = gpgme_set_ctx_flag (ctx, "cert-expire", "42d");
+ fail_if_err (err);
+
+ err = gpgme_get_key (ctx, key_fpr, &key, 0);
+ fail_if_err (err);
+
+ err = gpgme_data_new (&out);
+ fail_if_err (err);
+
+ err = gpgme_op_interact (ctx, key, 0, interact_fnc, out, out);
+ fail_if_err (err);
+
+ fputs ("[-- Last response --]\n", stdout);
+ flush_data (out);
+
+ gpgme_data_release (out);
+ gpgme_key_unref (key);
+ gpgme_key_unref (signing_key);
+
+ /* Verify the key signature */
+ mode = gpgme_get_keylist_mode (ctx);
+ mode |= GPGME_KEYLIST_MODE_SIGS;
+ err = gpgme_set_keylist_mode (ctx, mode);
+ fail_if_err (err);
+ err = gpgme_get_key (ctx, key_fpr, &signed_key, 0);
+ fail_if_err (err);
+
+ signed_uid = key->uids;
+ if (!signed_uid)
+ {
+ fprintf (stderr, "Signed key has no user IDs\n");
+ exit (1);
+ }
+ if (!signed_uid->signatures || !signed_uid->signatures->next)
+ {
+ fprintf (stderr, "Signed user ID has less signatures than expected\n");
+ exit (1);
+ }
+ key_sig = signed_uid->signatures->next;
+ if (strcmp ("2D727CC768697734", key_sig->keyid))
+ {
+ fprintf (stderr, "Unexpected key ID in second user ID sig: %s\n",
+ key_sig->keyid);
+ exit (1);
+ }
+ if (key_sig->expires != key_sig->timestamp + 42*86400L)
+ {
+ fprintf (stderr, "Key signature unexpectedly does not expire in 42 days\n");
+ fprintf (stderr, "signature date: %ld, expiration date: %ld\n",
+ key_sig->timestamp, key_sig->expires);
+ exit (1);
+ }
+
+ gpgme_key_unref (signed_key);
+ gpgme_release (ctx);
+
+ return 0;
+}
diff --git a/tests/gpgsm/Makefile.in b/tests/gpgsm/Makefile.in
index 8a09fac..0cd6a57 100644
--- a/tests/gpgsm/Makefile.in
+++ b/tests/gpgsm/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -816,7 +816,8 @@ all-am: Makefile $(PROGRAMS) $(HEADERS)
installdirs:
install: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-am
-install-exec: install-exec-am
+install-exec: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-am
install-data: install-data-am
uninstall: uninstall-am
@@ -936,7 +937,8 @@ ps-am:
uninstall-am:
-.MAKE: all check check-am install install-am install-strip
+.MAKE: all check check-am install install-am install-exec \
+ install-strip
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \
check-am clean clean-generic clean-libtool clean-local \
diff --git a/tests/json/Makefile.in b/tests/json/Makefile.in
index eef27a3..eae5ea7 100644
--- a/tests/json/Makefile.in
+++ b/tests/json/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -747,7 +747,8 @@ all-am: Makefile $(PROGRAMS)
installdirs:
install: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-am
-install-exec: install-exec-am
+install-exec: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-am
install-data: install-data-am
uninstall: uninstall-am
@@ -849,7 +850,8 @@ ps-am:
uninstall-am:
-.MAKE: all check check-am install install-am install-strip
+.MAKE: all check check-am install install-am install-exec \
+ install-strip
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \
check-am clean clean-generic clean-libtool clean-local \
diff --git a/tests/opassuan/Makefile.in b/tests/opassuan/Makefile.in
index 142a9f6..e1d4220 100644
--- a/tests/opassuan/Makefile.in
+++ b/tests/opassuan/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/tests/run-decrypt.c b/tests/run-decrypt.c
index f1a9fcc..cf71992 100644
--- a/tests/run-decrypt.c
+++ b/tests/run-decrypt.c
@@ -89,6 +89,8 @@ show_usage (int ex)
" --no-symkey-cache disable the use of that cache\n"
" --ignore-mdc-error allow decryption of legacy data\n"
" --unwrap remove only the encryption layer\n"
+ " --large-buffers use large I/O buffer\n"
+ " --sensitive mark data objects as sensitive\n"
" --diagnostics print diagnostics\n"
, stderr);
exit (ex);
@@ -114,6 +116,8 @@ main (int argc, char **argv)
int no_symkey_cache = 0;
int ignore_mdc_error = 0;
int raw_output = 0;
+ int large_buffers = 0;
+ int sensitive = 0;
int diagnostics = 0;
if (argc)
@@ -185,6 +189,16 @@ main (int argc, char **argv)
diagnostics = 1;
argc--; argv++;
}
+ else if (!strcmp (*argv, "--large-buffers"))
+ {
+ large_buffers = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--sensitive"))
+ {
+ sensitive = 1;
+ argc--; argv++;
+ }
else if (!strcmp (*argv, "--unwrap"))
{
flags |= GPGME_DECRYPT_UNWRAP;
@@ -288,6 +302,26 @@ main (int argc, char **argv)
gpgme_strerror (err));
exit (1);
}
+ if (large_buffers)
+ {
+ err = gpgme_data_set_flag (out, "io-buffer-size", "1000000");
+ if (err)
+ {
+ fprintf (stderr, PGM ": error setting io-buffer-size (out): %s\n",
+ gpgme_strerror (err));
+ exit (1);
+ }
+ }
+ if (sensitive)
+ {
+ err = gpgme_data_set_flag (out, "sensitive", "1");
+ if (err)
+ {
+ fprintf (stderr, PGM ": error setting sensitive flag (out): %s\n",
+ gpgme_strerror (err));
+ exit (1);
+ }
+ }
err = gpgme_op_decrypt_ext (ctx, flags, in, out);
result = gpgme_op_decrypt_result (ctx);
diff --git a/tests/run-keylist.c b/tests/run-keylist.c
index 23c6110..27cdbb2 100644
--- a/tests/run-keylist.c
+++ b/tests/run-keylist.c
@@ -272,11 +272,6 @@ main (int argc, char **argv)
int nsigs;
printf ("keyid : %s\n", key->subkeys?nonnull (key->subkeys->keyid):"?");
- printf ("fpr : %s\n", key->subkeys?nonnull (key->subkeys->fpr):"?");
- if (key->subkeys && key->subkeys->keygrip)
- printf ("grip : %s\n", key->subkeys->keygrip);
- if (key->subkeys && key->subkeys->curve)
- printf ("curve : %s\n", key->subkeys->curve);
printf ("caps : %s%s%s%s\n",
key->can_encrypt? "e":"",
key->can_sign? "s":"",
@@ -294,9 +289,7 @@ main (int argc, char **argv)
printf ("upd : %lu (%u)\n", key->last_update, key->origin);
subkey = key->subkeys;
- if (subkey)
- subkey = subkey->next;
- for (nsub=1; subkey; subkey = subkey->next, nsub++)
+ for (nsub=0; subkey; subkey = subkey->next, nsub++)
{
printf ("fpr %2d: %s\n", nsub, nonnull (subkey->fpr));
if (subkey->keygrip)
@@ -369,6 +362,9 @@ main (int argc, char **argv)
printf (" created: %s\n", isotimestr(ks->timestamp));
printf (" expires: %s\n", isotimestr(ks->expires));
printf (" class: %x\n", ks->sig_class);
+ printf (" trust depth: %u\n", ks->trust_depth);
+ printf (" trust value: %u\n", ks->trust_value);
+ printf (" trust scope: %s\n", nonnull (ks->trust_scope));
}
}
diff --git a/tests/run-keysign.c b/tests/run-keysign.c
index 57488a4..3177506 100644
--- a/tests/run-keysign.c
+++ b/tests/run-keysign.c
@@ -82,6 +82,7 @@ show_usage (int ex)
" --noexpire force no expiration\n"
" --expire EPOCH expire the signature at EPOCH\n"
" --revoke revoke the signature(s)\n"
+ " --force pass --force-sign-key option\n"
, stderr);
exit (ex);
}
@@ -149,6 +150,11 @@ main (int argc, char **argv)
keysign_flags |= GPGME_KEYSIGN_LOCAL;
argc--; argv++;
}
+ else if (!strcmp (*argv, "--force"))
+ {
+ keysign_flags |= GPGME_KEYSIGN_FORCE;
+ argc--; argv++;
+ }
else if (!strcmp (*argv, "--noexpire"))
{
keysign_flags |= GPGME_KEYSIGN_NOEXPIRE;
diff --git a/tests/run-threaded.c b/tests/run-threaded.c
index 1fe4f19..c0e033b 100644
--- a/tests/run-threaded.c
+++ b/tests/run-threaded.c
@@ -627,6 +627,7 @@ void
start_keylistings (void)
{
static struct keylist_args_s args[4];
+ int i;
args[0].proto = GPGME_PROTOCOL_OpenPGP;
args[0].secret = 0;
@@ -640,7 +641,7 @@ start_keylistings (void)
args[3].proto = GPGME_PROTOCOL_CMS;
args[3].secret = 1;
- for (int i = 0; i < 4; i++)
+ for (i = 0; i < 4; i++)
{
thread_cnt--;
create_thread (do_keylist, &args[i]);
diff --git a/tests/run-verify.c b/tests/run-verify.c
index e42eb6b..f131f49 100644
--- a/tests/run-verify.c
+++ b/tests/run-verify.c
@@ -251,6 +251,7 @@ main (int argc, char **argv)
int auto_key_retrieve = 0;
int auto_key_import = 0;
int repeats = 1;
+ int i;
if (argc)
{ argc--; argv++; }
@@ -321,7 +322,7 @@ main (int argc, char **argv)
init_gpgme (protocol);
- for (int i = 0; i < repeats; i++)
+ for (i = 0; i < repeats; i++)
{
gpgme_error_t err;
gpgme_ctx_t ctx;