Merge branch 'master' into javascript-binding
This commit is contained in:
commit
94f21d9f6b
4
AUTHORS
4
AUTHORS
@ -1,5 +1,5 @@
|
||||
Package: gpgme
|
||||
Homepage: https://gnupg.org/related_software/gpgme/
|
||||
Homepage: https://gnupg.org/software/gpgme/
|
||||
Download: https://gnupg.org/ftp/gcrypt/gpgme/
|
||||
Repository: git://git.gnupg.org/gpgme.git
|
||||
Maintainer: Werner Koch <wk@gnupg.org>
|
||||
@ -19,7 +19,7 @@ List of Copyright holders
|
||||
|
||||
Copyright (C) 1991-2013 Free Software Foundation, Inc.
|
||||
Copyright (C) 2000-2001 Werner Koch
|
||||
Copyright (C) 2001-2017 g10 Code GmbH
|
||||
Copyright (C) 2001-2018 g10 Code GmbH
|
||||
Copyright (C) 2002 Klarälvdalens Datakonsult AB
|
||||
Copyright (C) 2004-2008 Igor Belyi
|
||||
Copyright (C) 2002 John Goerzen
|
||||
|
59
Makefile.am
59
Makefile.am
@ -19,6 +19,16 @@
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
# Location of the released tarball archives. Note that this is an
|
||||
# internal archive and before uploading this to the public server,
|
||||
# manual tests should be run and the git release tat set and pushed.
|
||||
# Adjust as needed.
|
||||
RELEASE_ARCHIVE_DIR = wk@vigenere:tarballs/gpgme/
|
||||
|
||||
# The key used to sign the released sources. Adjust as needed.
|
||||
RELEASE_SIGNING_KEY = D8692123C4065DEA5E0F3AB5249B39D24F25E3B6
|
||||
|
||||
# Autoconf flags
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS =
|
||||
@ -57,9 +67,9 @@ distcheck-hook:
|
||||
esac;\
|
||||
done ) | tee $(distdir).swdb
|
||||
|
||||
.PHONY: gen-ChangeLog release sign-release
|
||||
|
||||
gen_start_date = 2011-12-01T00:00:00
|
||||
.PHONY: gen-ChangeLog
|
||||
gen-ChangeLog:
|
||||
if test -d $(top_srcdir)/.git; then \
|
||||
(cd $(top_srcdir) && \
|
||||
@ -70,3 +80,50 @@ gen-ChangeLog:
|
||||
rm -f $(distdir)/ChangeLog; \
|
||||
mv $(distdir)/cl-t $(distdir)/ChangeLog; \
|
||||
fi
|
||||
|
||||
|
||||
# Macro to help the release target.
|
||||
RELEASE_NAME = $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)
|
||||
|
||||
release:
|
||||
+(set -e;\
|
||||
if [ "$(abs_top_builddir)" = "$(abs_top_srcdir)" ]; then \
|
||||
echo "error: build directory must not be the source directory" >&2;\
|
||||
exit 2;\
|
||||
fi ;\
|
||||
echo "/* Build started at $$(date -uIseconds) */" ;\
|
||||
cd $(top_srcdir); \
|
||||
./autogen.sh --force; \
|
||||
cd $(abs_top_builddir); \
|
||||
rm -rf dist; mkdir dist ; cd dist ; \
|
||||
$(abs_top_srcdir)/configure --enable-maintainer-mode; \
|
||||
$(MAKE) distcheck TESTFLAGS=--parallel; \
|
||||
echo "/* Build finished at $$(date -uIseconds) */" ;\
|
||||
echo "/*" ;\
|
||||
echo " * Please run the final step interactivly:" ;\
|
||||
echo " * make sign-release" ;\
|
||||
echo " */" ;\
|
||||
) 2>&1 | tee "$(RELEASE_NAME).buildlog"
|
||||
|
||||
sign-release:
|
||||
+(set -e; \
|
||||
cd dist; \
|
||||
files1="$(RELEASE_NAME).tar.bz2" ;\
|
||||
files2="$(RELEASE_NAME).tar.bz2.sig \
|
||||
$(RELEASE_NAME).swdb \
|
||||
$(RELEASE_NAME).buildlog" ;\
|
||||
echo "/* Signing the source tarball ..." ;\
|
||||
gpg -sbu $(RELEASE_SIGNING_KEY) $(RELEASE_NAME).tar.bz2 ;\
|
||||
cat $(RELEASE_NAME).swdb >swdb.snippet;\
|
||||
echo >>swdb.snippet ;\
|
||||
sha1sum $${files1} >>swdb.snippet ;\
|
||||
cat "../$(RELEASE_NAME).buildlog" swdb.snippet \
|
||||
| gzip >$(RELEASE_NAME).buildlog ;\
|
||||
echo "Copying to local archive ..." ;\
|
||||
scp -p $${files1} $${files2} $(RELEASE_ARCHIVE_DIR)/ || true;\
|
||||
echo "Uploading documentation ..." ;\
|
||||
$(MAKE) -C doc online; \
|
||||
echo '/*' ;\
|
||||
echo ' * All done; for checksums see dist/swdb.snippet' ;\
|
||||
echo ' */' ;\
|
||||
)
|
||||
|
81
NEWS
81
NEWS
@ -1,13 +1,86 @@
|
||||
Noteworthy changes in version 1.10.1 (unreleased)
|
||||
Noteworthy changes in version 1.11.2 (unreleased)
|
||||
-------------------------------------------------
|
||||
|
||||
|
||||
Noteworthy changes in version 1.11.1 (2018-04-20)
|
||||
-------------------------------------------------
|
||||
|
||||
* Fixed build problems in the 1.11.0 release.
|
||||
|
||||
* Added C++ interfaces which were planned for 1.11.0.
|
||||
|
||||
* Interface changes relative to the 1.10.0 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
gpgme_import_result_t EXTENDED: New field 'skipped_v3_keys'
|
||||
cpp: Key::locate NEW.
|
||||
cpp: Data::toString NEW.
|
||||
cpp: Key::origin NEW.
|
||||
cpp: Key::lastUpdate NEW.
|
||||
cpp: UserID::origin NEW.
|
||||
cpp: UserID::lastUpdate NEW.
|
||||
|
||||
[c=C31/A20/R1 cpp=C13/A7/R0 qt=C10/A3/R2]
|
||||
|
||||
|
||||
Noteworthy changes in version 1.11.0 (2018-04-18)
|
||||
-------------------------------------------------
|
||||
|
||||
* New encryption API to support direct key specification including
|
||||
hidden recipients option and taking keys from a file. This also
|
||||
allows to enforce the use of a subkey.
|
||||
|
||||
* New encryption flag for the new API to enforce the use of plain
|
||||
mail addresses (addr-spec).
|
||||
|
||||
* The import API can now tell whether v3 keys are skipped. These old
|
||||
and basically broken keys are not anymore supported by GnuPG 2.1.
|
||||
|
||||
* The decrypt and verify API will now return the MIME flag as
|
||||
specified by RFC-4880bis.
|
||||
|
||||
* The offline mode now has an effect on gpg by disabling all network
|
||||
access. [#3831]
|
||||
|
||||
* A failed OpenPGP verification how returns the fingerprint of the
|
||||
intended key if a recent gpg version was used for signature
|
||||
creation.
|
||||
|
||||
* New tool gpgme-json as native messaging server for web browsers.
|
||||
As of now public key encryption and decryption is supported.
|
||||
Requires Libgpg-error 1.29.
|
||||
|
||||
* New context flag "request-origin" which has an effect when used
|
||||
with GnuPG 2.2.6 or later.
|
||||
|
||||
* New context flag "no-symkey-cache" which has an effect when used
|
||||
with GnuPG 2.2.7 or later.
|
||||
|
||||
* New convenience constant GPGME_KEYLIST_MODE_LOCATE.
|
||||
|
||||
* Improved the Python documentation.
|
||||
|
||||
* Fixed a potential regression with GnuPG 2.2.6 or later.
|
||||
|
||||
* Fixed a crash in the Python bindings on 32 bit platforms. [#3892]
|
||||
|
||||
* Various minor fixes.
|
||||
|
||||
* Interface changes relative to the 1.10.0 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
gpgme_op_encrypt_ext NEW.
|
||||
gpgme_op_encrypt_ext_start NEW.
|
||||
gpgme_op_encrypt_sign_ext NEW.
|
||||
gpgme_op_encrypt_sign_ext_start NEW.
|
||||
GPGME_ENCRYPT_WANT_ADDRESS NEW.
|
||||
GPGME_KEYLIST_MODE_LOCATE NEW.
|
||||
gpgme_import_result_t EXTENDED: New field 'skipped_v3_keys'.
|
||||
gpgme_decrypt_result_t EXTENDED: New field 'symkey_algo'.
|
||||
gpgme_decrypt_result_t EXTENDED: New field 'is_mime'.
|
||||
gpgme_verify_result_t EXTENDED: New field 'is_mime'.
|
||||
cpp: Key::locate NEW.
|
||||
cpp: Data::toString NEW.
|
||||
cpp: ImportResult::numV3KeysSkipped NEW.
|
||||
|
||||
[c=C31/A20/R0 cpp=C12/A6/R0 qt=C10/A3/R1]
|
||||
|
||||
|
||||
Noteworthy changes in version 1.10.0 (2017-12-12)
|
||||
-------------------------------------------------
|
||||
|
||||
|
2
README
2
README
@ -1,7 +1,7 @@
|
||||
GPGME - GnuPG Made Easy
|
||||
---------------------------
|
||||
|
||||
Copyright 2001-2017 g10 Code GmbH
|
||||
Copyright 2001-2018 g10 Code GmbH
|
||||
|
||||
This file is free software; as a special exception the author gives
|
||||
unlimited permission to copy and/or distribute it, with or without
|
||||
|
21
configure.ac
21
configure.ac
@ -1,7 +1,6 @@
|
||||
# configure.ac for GPGME
|
||||
# Copyright (C) 2000 Werner Koch (dd9jn)
|
||||
# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
|
||||
# 2009, 2010, 2011, 2012, 2013, 2014, 2015 g10 Code GmbH
|
||||
# Copyright (C) 2001-2018 g10 Code GmbH
|
||||
#
|
||||
# This file is part of GPGME.
|
||||
#
|
||||
@ -28,8 +27,8 @@ min_automake_version="1.14"
|
||||
# commit and push so that the git magic is able to work. See below
|
||||
# for the LT versions.
|
||||
m4_define(mym4_version_major, [1])
|
||||
m4_define(mym4_version_minor, [10])
|
||||
m4_define(mym4_version_micro, [1])
|
||||
m4_define(mym4_version_minor, [11])
|
||||
m4_define(mym4_version_micro, [2])
|
||||
|
||||
# Below is m4 magic to extract and compute the revision number, the
|
||||
# decimalized short revision number, a beta version string, and a flag
|
||||
@ -55,20 +54,20 @@ AC_INIT([gpgme],[mym4_full_version],[http://bugs.gnupg.org])
|
||||
# (Interfaces added: AGE++)
|
||||
# (Interfaces removed/changed: AGE=0)
|
||||
#
|
||||
LIBGPGME_LT_CURRENT=30
|
||||
LIBGPGME_LT_AGE=19
|
||||
LIBGPGME_LT_REVISION=0
|
||||
LIBGPGME_LT_CURRENT=31
|
||||
LIBGPGME_LT_AGE=20
|
||||
LIBGPGME_LT_REVISION=1
|
||||
|
||||
# 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=11
|
||||
LIBGPGMEPP_LT_AGE=5
|
||||
LIBGPGMEPP_LT_CURRENT=13
|
||||
LIBGPGMEPP_LT_AGE=7
|
||||
LIBGPGMEPP_LT_REVISION=0
|
||||
|
||||
LIBQGPGME_LT_CURRENT=10
|
||||
LIBQGPGME_LT_AGE=3
|
||||
LIBQGPGME_LT_REVISION=0
|
||||
LIBQGPGME_LT_REVISION=2
|
||||
|
||||
# If the API is changed in an incompatible way: increment the next counter.
|
||||
GPGME_CONFIG_API_VERSION=1
|
||||
@ -810,7 +809,7 @@ AH_BOTTOM([
|
||||
#define GPG_ERR_ENABLE_ERRNO_MACROS 1
|
||||
|
||||
#define CRIGHTBLURB "Copyright (C) 2000 Werner Koch\n" \
|
||||
"Copyright (C) 2001--2017 g10 Code GmbH\n"
|
||||
"Copyright (C) 2001--2018 g10 Code GmbH\n"
|
||||
])
|
||||
|
||||
|
||||
|
224
doc/gpgme.texi
224
doc/gpgme.texi
@ -2606,22 +2606,26 @@ valid pointer.
|
||||
@deftypefun void gpgme_set_offline (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{yes}})
|
||||
@since{1.6.0}
|
||||
|
||||
The function @code{gpgme_set_offline} specifies if offline mode
|
||||
should be used. By default, offline mode is not used.
|
||||
The function @code{gpgme_set_offline} specifies if offline mode should
|
||||
be used. Offline mode is disabled if @var{yes} is zero, and enabled
|
||||
otherwise. By default, offline mode is disabled.
|
||||
|
||||
The offline mode specifies if dirmngr should be used to do additional
|
||||
validation that might require connections to external services.
|
||||
(e.g. CRL / OCSP checks).
|
||||
The details of the offline mode depend on the used protocol and its
|
||||
backend engine. It may eventually be extended to be more stricter and
|
||||
for example completely disable the use of Dirmngr for any engine.
|
||||
|
||||
Offline mode only affects the keylist mode @code{GPGME_KEYLIST_MODE_VALIDATE}
|
||||
and is only relevant to the CMS crypto engine. Offline mode
|
||||
is ignored otherwise.
|
||||
For the CMS protocol the offline mode specifies whether Dirmngr shall
|
||||
be used to do additional validation that might require connecting
|
||||
external services (e.g. CRL / OCSP checks). Here the offline mode
|
||||
only affects the keylist mode @code{GPGME_KEYLIST_MODE_VALIDATE}.
|
||||
|
||||
This option may be extended in the future to completely disable
|
||||
the use of dirmngr for any engine.
|
||||
For the OpenPGP protocol offline mode entirely disables the use of the
|
||||
Dirmngr and will thus guarantee that no network connections are done
|
||||
as part of an operation on this context. It has only an effect with
|
||||
GnuPG versions 2.1.23 or later.
|
||||
|
||||
For all other protocols the offline mode is currently ignored.
|
||||
|
||||
Offline mode is disabled if @var{yes} is zero, and enabled
|
||||
otherwise.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int gpgme_get_offline (@w{gpgme_ctx_t @var{ctx}})
|
||||
@ -2765,6 +2769,11 @@ type of external source is dependent on the crypto engine used and
|
||||
whether it is combined with @code{GPGME_KEYLIST_MODE_LOCAL}. For
|
||||
example, it can be a remote keyserver or LDAP certificate server.
|
||||
|
||||
@item GPGME_KEYLIST_MODE_LOCATE
|
||||
This is a shortcut for the combination of
|
||||
@code{GPGME_KEYLIST_MODE_LOCAL} and @code{GPGME_KEYLIST_MODE_EXTERN}
|
||||
and convenient when the --locate-key feature of OpenPGP is desired.
|
||||
|
||||
@item GPGME_KEYLIST_MODE_SIGS
|
||||
The @code{GPGME_KEYLIST_MODE_SIGS} symbol specifies that the key
|
||||
signatures should be included in the listed keys.
|
||||
@ -3069,7 +3078,13 @@ the time when you verified the signature.
|
||||
The string given in @var{value} is passed to the GnuPG engines to
|
||||
request restrictions based on the origin of the request. Valid values
|
||||
are documented in the GnuPG manual and the gpg man page under the
|
||||
option ``--request-origin''.
|
||||
option ``--request-origin''. Requires at least GnuPG 2.2.6 to have an
|
||||
effect.
|
||||
|
||||
@item "no-symkey-cache"
|
||||
For OpenPGP disable the passphrase cache used for symmetrical en- and
|
||||
decryption. This cache is based on the message specific salt value.
|
||||
Requires at least GnuPG 2.2.7 to have an effect.
|
||||
|
||||
@end table
|
||||
|
||||
@ -5274,7 +5289,7 @@ if @var{cipher} or @var{plain} is not a valid pointer.
|
||||
@since{1.8.0}
|
||||
|
||||
The function @code{gpgme_op_decrypt_ext} is the same as
|
||||
@code{gpgme_op_decrypt_ext} but has an additional argument
|
||||
@code{gpgme_op_decrypt} but has an additional argument
|
||||
@var{flags}. If @var{flags} is 0 both function behave identically.
|
||||
|
||||
The value in @var{flags} is a bitwise-or combination of one or
|
||||
@ -5389,6 +5404,13 @@ You must not try to access this member of the struct unless
|
||||
or @code{gpgme_get_ctx_flag (ctx, "export-session-key")} returns true
|
||||
(non-empty string).
|
||||
|
||||
@item char *symkey_algo
|
||||
@since{1.11.0}
|
||||
|
||||
A string with the symmetric encryption algorithm and mode using the
|
||||
format "<algo>.<mode>". Note that old non-MDC encryption mode of
|
||||
OpenPGP is given as "PGPCFB".
|
||||
|
||||
@end table
|
||||
@end deftp
|
||||
|
||||
@ -6088,7 +6110,7 @@ also expect a sign command.
|
||||
|
||||
The @code{GPGME_ENCRYPT_SYMMETRIC} symbol specifies that the
|
||||
output should be additionally encrypted symmetrically even
|
||||
if recipients are provided. This feature is only supported for
|
||||
if recipients are provided. This feature is only supported
|
||||
for the OpenPGP crypto engine.
|
||||
|
||||
@item GPGME_ENCRYPT_THROW_KEYIDS
|
||||
@ -6107,6 +6129,18 @@ The @code{GPGME_ENCRYPT_WRAP} symbol specifies that the input is an
|
||||
OpenPGP message and not a plain data. This is the counterpart to
|
||||
@code{GPGME_DECRYPT_UNWRAP}.
|
||||
|
||||
@item GPGME_ENCRYPT_WANT_ADDRESS
|
||||
@since{1.11.0}
|
||||
|
||||
The @code{GPGME_ENCRYPT_WANT_ADDRESS} symbol requests that all
|
||||
supplied keys or key specifications include a syntactically valid mail
|
||||
address. If this is not the case the operation is not even tried and
|
||||
the error code @code{GPG_ERR_INV_USER_ID} is returned. Only the
|
||||
address part of the key specification is conveyed to the backend. As
|
||||
of now the key must be specified using the @var{recpstring} argument
|
||||
of the extended encrypt functions. This feature is currently only
|
||||
supported for the OpenPGP crypto engine.
|
||||
|
||||
@end table
|
||||
|
||||
If @code{GPG_ERR_UNUSABLE_PUBKEY} is returned, some recipients in
|
||||
@ -6148,6 +6182,128 @@ pointer, and @code{GPG_ERR_UNUSABLE_PUBKEY} if @var{rset} does not
|
||||
contain any valid recipients.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun gpgme_error_t gpgme_op_encrypt_ext @
|
||||
(@w{gpgme_ctx_t @var{ctx}}, @
|
||||
@w{gpgme_key_t @var{recp}[]}, @
|
||||
@w{const char *@var{recpstring}}, @
|
||||
@w{gpgme_encrypt_flags_t @var{flags}}, @
|
||||
@w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{cipher}})
|
||||
|
||||
@since{1.11.0}
|
||||
|
||||
This is an extended version of @code{gpgme_op_encrypt} with
|
||||
@var{recpstring} as additional parameter. If @var{recp} is NULL and
|
||||
@var{recpstring} is not NULL, the latter is expected to be a linefeed
|
||||
delimited string with the set of key specifications. In contrast to
|
||||
@var{recp} the keys are given directly as strings and there is no need
|
||||
to first create key objects. Leading and trailing white space is
|
||||
remove from each line in @var{recpstring}. The keys are then passed
|
||||
verbatim to the backend engine.
|
||||
|
||||
For the OpenPGP backend several special keywords are supported to
|
||||
modify the operation. These keywords are given instead of a key
|
||||
specification. The currently supported keywords are:
|
||||
|
||||
@table @code
|
||||
@item --hidden
|
||||
@itemx --no-hidden
|
||||
These keywords toggle between normal and hidden recipients for all
|
||||
following key specifications. When a hidden recipient is requested
|
||||
the gpg option @option{-R} (or @option{-F} in file mode) is used
|
||||
instead of @option{-r} (@option{-f} in file mode).
|
||||
|
||||
@item --file
|
||||
@itemx --no-file
|
||||
These keywords toggle between regular and file mode for all following
|
||||
key specification. In file mode the option @option{-f} or @option{-F}
|
||||
is passed to gpg. At least GnuPG version 2.1.14 is required to handle
|
||||
these options. The @code{GPGME_ENCRYPT_WANT_ADDRESS} flag is ignored
|
||||
in file mode.
|
||||
|
||||
@item --
|
||||
This keyword disables all keyword detection up to the end of the
|
||||
string. All keywords are treated as verbatim arguments.
|
||||
|
||||
@end table
|
||||
|
||||
To create a @var{recpstring} it is often useful to employ a strconcat
|
||||
style function. For example this function creates a string to encrypt
|
||||
to two keys:
|
||||
|
||||
@example
|
||||
char *
|
||||
xbuild_recpstring (const char *key1, const char *key2)
|
||||
@{
|
||||
char *result = gpgrt_strconcat ("--\n", key1, "\n", key2, NULL);
|
||||
if (!result)
|
||||
@{ perror ("strconcat failed"); exit (2); @}
|
||||
return result;
|
||||
@}
|
||||
@end example
|
||||
|
||||
Note the use of the double dash here; unless you want to specify a
|
||||
keyword, it is a good idea to avoid any possible trouble with key
|
||||
specifications starting with a double dash. The used strconcat
|
||||
function is available in Libgpg-error 1.28 and later; Libgpg-error
|
||||
(aka Gpgrt) is a dependency of GPGME. The number of arguments to
|
||||
@code{gpgrt_strconcat} is limited to 47 but that should always be
|
||||
sufficient. In case a larger and non-fixed number of keys are to be
|
||||
supplied the following code can be used:
|
||||
|
||||
@example
|
||||
char *
|
||||
xbuild_long_recpstring (void)
|
||||
@{
|
||||
gpgrt_stream_t memfp;
|
||||
const char *s;
|
||||
void *result;
|
||||
|
||||
memfp = gpgrt_fopenmem (0, "w+b");
|
||||
if (!memfp)
|
||||
@{ perror ("fopenmem failed"); exit (2); @}
|
||||
gpgrt_fputs ("--", memfp);
|
||||
while ((s = get_next_keyspec ()))
|
||||
@{
|
||||
gpgrt_fputc ('\n', memfp);
|
||||
gpgrt_fputs (s, memfp);
|
||||
@}
|
||||
gpgrt_fputc (0, memfp);
|
||||
if (gpgrt_ferror (memfp))
|
||||
@{ perror ("writing to memstream failed"); exit (2); @}
|
||||
if (gpgrt_fclose_snatch (memfp, &result, NULL))
|
||||
@{ perror ("fclose_snatch failed"); exit (2); @}
|
||||
return result;
|
||||
@}
|
||||
@end example
|
||||
|
||||
In this example @code{get_next_keyspec} is expected to return the next
|
||||
key to be added to the string. Please take care: Encrypting to a
|
||||
large number of recipients is often questionable due to security
|
||||
reasons and also for the technicality that all keys are currently
|
||||
passed on the command line to @command{gpg} which has as a platform
|
||||
specific length limitation.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@deftypefun gpgme_error_t gpgme_op_encrypt_ext_start @
|
||||
(@w{gpgme_ctx_t @var{ctx}}, @
|
||||
@w{gpgme_key_t @var{recp}[]}, @
|
||||
@w{const char *@var{recpstring}}, @
|
||||
@w{gpgme_encrypt_flags_t @var{flags}}, @
|
||||
@w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{cipher}})
|
||||
|
||||
@since{1.11.0}
|
||||
|
||||
This is an extended version of @code{gpgme_op_encrypt_start} with
|
||||
@var{recpstring} as additional parameter. If @var{recp} is NULL and
|
||||
@var{recpstring} is not NULL, the latter is expected to be a linefeed
|
||||
delimited string with the set of key specifications. In contrast to
|
||||
@var{recp} the keys are given directly as strings and there is no need
|
||||
to first create key objects. The keys are passed verbatim to the
|
||||
backend engine.
|
||||
|
||||
@end deftypefun
|
||||
|
||||
@deftp {Data type} {gpgme_encrypt_result_t}
|
||||
This is a pointer to a structure used to store the result of a
|
||||
@code{gpgme_op_encrypt} operation. After successfully encrypting
|
||||
@ -6197,6 +6353,44 @@ if @var{ctx}, @var{rset}, @var{plain} or @var{cipher} is not a valid
|
||||
pointer.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun gpgme_error_t gpgme_op_encrypt_sign_ext @
|
||||
(@w{gpgme_ctx_t @var{ctx}}, @
|
||||
@w{gpgme_key_t @var{recp}[]}, @
|
||||
@w{const char *@var{recpstring}}, @
|
||||
@w{gpgme_encrypt_flags_t @var{flags}}, @
|
||||
@w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{cipher}})
|
||||
|
||||
@since{1.11.0}
|
||||
|
||||
This is an extended version of @code{gpgme_op_encrypt_sign} with
|
||||
@var{recpstring} as additional parameter. If @var{recp} is NULL and
|
||||
@var{recpstring} is not NULL, the latter is expected to be a linefeed
|
||||
delimited string with the set of key specifications. In contrast to
|
||||
@var{recp} the keys are given directly as strings and there is no need
|
||||
to first create the key objects. The keys are passed verbatim to the
|
||||
backend engine.
|
||||
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun gpgme_error_t gpgme_op_encrypt_sign_ext_start @
|
||||
(@w{gpgme_ctx_t @var{ctx}}, @
|
||||
@w{gpgme_key_t @var{recp}[]}, @
|
||||
@w{const char *@var{recpstring}}, @
|
||||
@w{gpgme_encrypt_flags_t @var{flags}}, @
|
||||
@w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{cipher}})
|
||||
|
||||
@since{1.11.0}
|
||||
|
||||
This is an extended version of @code{gpgme_op_encrypt_sign_start} with
|
||||
@var{recpstring} as additional parameter. If @var{recp} is NULL and
|
||||
@var{recpstring} is not NULL, the latter is expected to be a linefeed
|
||||
delimited string with the set of key specifications. In contrast to
|
||||
@var{recp} the keys are given directly as strings and there is no need
|
||||
to first create the key objects. The keys are passed verbatim to the
|
||||
backend engine.
|
||||
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@node Miscellaneous
|
||||
@section Miscellaneous operations
|
||||
|
@ -967,6 +967,42 @@ Error UserID::revoke()
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Key::Origin gpgme_origin_to_pp_origin (const unsigned int origin)
|
||||
{
|
||||
switch (origin) {
|
||||
case GPGME_KEYORG_KS:
|
||||
return Key::OriginKS;
|
||||
case GPGME_KEYORG_DANE:
|
||||
return Key::OriginDane;
|
||||
case GPGME_KEYORG_WKD:
|
||||
return Key::OriginWKD;
|
||||
case GPGME_KEYORG_URL:
|
||||
return Key::OriginURL;
|
||||
case GPGME_KEYORG_FILE:
|
||||
return Key::OriginFile;
|
||||
case GPGME_KEYORG_SELF:
|
||||
return Key::OriginSelf;
|
||||
case GPGME_KEYORG_OTHER:
|
||||
return Key::OriginOther;
|
||||
case GPGME_KEYORG_UNKNOWN:
|
||||
default:
|
||||
return Key::OriginUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
Key::Origin UserID::origin() const
|
||||
{
|
||||
if (isNull()) {
|
||||
return Key::OriginUnknown;
|
||||
}
|
||||
return gpgme_origin_to_pp_origin(uid->origin);
|
||||
}
|
||||
|
||||
time_t UserID::lastUpdate() const
|
||||
{
|
||||
return static_cast<time_t>(uid ? uid->last_update : 0);
|
||||
}
|
||||
|
||||
Error Key::addUid(const char *uid)
|
||||
{
|
||||
if (isNull()) {
|
||||
@ -981,6 +1017,19 @@ Error Key::addUid(const char *uid)
|
||||
return ret;
|
||||
}
|
||||
|
||||
Key::Origin Key::origin() const
|
||||
{
|
||||
if (isNull()) {
|
||||
return OriginUnknown;
|
||||
}
|
||||
return gpgme_origin_to_pp_origin(key->origin);
|
||||
}
|
||||
|
||||
time_t Key::lastUpdate() const
|
||||
{
|
||||
return static_cast<time_t>(key ? key->last_update : 0);
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const UserID &uid)
|
||||
{
|
||||
os << "GpgME::UserID(";
|
||||
|
@ -178,6 +178,27 @@ public:
|
||||
*/
|
||||
static Key locate(const char *mbox);
|
||||
|
||||
/* @enum Origin
|
||||
* @brief The Origin of the key. */
|
||||
enum Origin : unsigned int {
|
||||
OriginUnknown = 0,
|
||||
OriginKS = 1,
|
||||
OriginDane = 3,
|
||||
OriginWKD = 4,
|
||||
OriginURL = 5,
|
||||
OriginFile = 6,
|
||||
OriginSelf = 7,
|
||||
OriginOther = 31,
|
||||
};
|
||||
/*! Get the origin of the key.
|
||||
*
|
||||
* @returns the Origin. */
|
||||
Origin origin() const;
|
||||
|
||||
/*! Get the last update time.
|
||||
*
|
||||
* @returns the last update time. */
|
||||
time_t lastUpdate() const;
|
||||
private:
|
||||
gpgme_key_t impl() const
|
||||
{
|
||||
@ -371,6 +392,16 @@ public:
|
||||
*
|
||||
* @returns an error on error.*/
|
||||
Error revoke();
|
||||
|
||||
/*! Get the origin of the key.
|
||||
*
|
||||
* @returns the Origin. */
|
||||
Key::Origin origin() const;
|
||||
|
||||
/*! Get the last update time.
|
||||
*
|
||||
* @returns the last update time. */
|
||||
time_t lastUpdate() const;
|
||||
private:
|
||||
shared_gpgme_key_t key;
|
||||
gpgme_user_id_t uid;
|
||||
|
@ -1,6 +1,6 @@
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
GPG - GPGME BINDINGS FOR PYTHON
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
GPG - GPGME BINDINGS FOR PYTHON
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
|
||||
Table of Contents
|
||||
@ -13,7 +13,7 @@ Table of Contents
|
||||
|
||||
|
||||
The "gpg" module is a python interface to the GPGME library:
|
||||
[https://www.gnupg.org/related_software/gpgme/]
|
||||
[https://www.gnupg.org/software/gpgme/]
|
||||
|
||||
"gpg" offers two interfaces, one is a high-level, curated, and idiomatic
|
||||
interface that is implemented as a shim on top of the low-level
|
||||
@ -36,8 +36,8 @@ functionality of the underlying library.
|
||||
2 Bugs
|
||||
══════
|
||||
|
||||
Please report bugs using our bug tracker using the category 'gpgme',
|
||||
and topic 'python': [https://bugs.gnupg.org/gnupg/]
|
||||
Please report bugs using our bug tracker [https://bugs.gnupg.org] with
|
||||
tag (aka project) 'gpgme'.
|
||||
|
||||
|
||||
3 Authors
|
||||
|
@ -1,8 +1,8 @@
|
||||
#+TITLE: gpg - GPGME bindings for Python
|
||||
|
||||
#+OPTIONS: author:nil
|
||||
|
||||
The "gpg" module is a python interface to the GPGME library:
|
||||
https://www.gnupg.org/related_software/gpgme/
|
||||
[[https://www.gnupg.org/software/gpgme/]]
|
||||
|
||||
"gpg" offers two interfaces, one is a high-level, curated, and
|
||||
idiomatic interface that is implemented as a shim on top of the
|
||||
@ -21,9 +21,8 @@ https://lists.gnupg.org/mailman/listinfo/gnupg-devel
|
||||
|
||||
* Bugs
|
||||
|
||||
Please report bugs using our bug tracker using the category 'gpgme',
|
||||
and topic 'python':
|
||||
https://bugs.gnupg.org/gnupg/
|
||||
Please report bugs using our bug tracker
|
||||
[[https://bugs.gnupg.org]] with tag (aka project) 'gpgme'.
|
||||
|
||||
* Authors
|
||||
|
||||
|
@ -152,25 +152,8 @@ class BuildExtFirstHack(build):
|
||||
sink.write(content)
|
||||
|
||||
def _generate_gpgme_h(self, source_name, sink_name):
|
||||
if up_to_date(source_name, sink_name):
|
||||
return
|
||||
|
||||
print("Using gpgme.h from {}".format(source_name))
|
||||
|
||||
deprec_func = re.compile(r'^(.*typedef.*|.*\(.*\)|[^#]+\s+.+)'
|
||||
+ r'\s*_GPGME_DEPRECATED(_OUTSIDE_GPGME)?\(.*\);\s*',
|
||||
re.S)
|
||||
line_break = re.compile(';|\\$|\\x0c|^\s*#|{')
|
||||
|
||||
with open(sink_name, "w") as sink, open(source_name) as source:
|
||||
text = ''
|
||||
for line in source:
|
||||
text += re.sub(' class ', ' _py_obsolete_class ', line)
|
||||
if line_break.search(line):
|
||||
if not deprec_func.search(text):
|
||||
sink.write(text)
|
||||
text = ''
|
||||
sink.write(text)
|
||||
shutil.copy2(source_name, sink_name)
|
||||
|
||||
def _generate_errors_i(self):
|
||||
|
||||
|
@ -104,8 +104,6 @@ gpgme_tool_LDADD = libgpgme.la @LIBASSUAN_LIBS@
|
||||
|
||||
gpgme_json_SOURCES = gpgme-json.c cJSON.c cJSON.h
|
||||
gpgme_json_LDADD = -lm libgpgme.la $(GPG_ERROR_LIBS)
|
||||
# We use -no-install temporary during development.
|
||||
gpgme_json_LDFLAGS = -no-install
|
||||
|
||||
|
||||
if HAVE_W32_SYSTEM
|
||||
|
@ -121,6 +121,9 @@ struct gpgme_context
|
||||
/* True if the option --auto-key-retrieve shall be passed to gpg. */
|
||||
unsigned int auto_key_retrieve : 1;
|
||||
|
||||
/* Do not use the symmtric encryption passphrase cache. */
|
||||
unsigned int no_symkey_cache : 1;
|
||||
|
||||
/* Flags for keylist mode. */
|
||||
gpgme_keylist_mode_t keylist_mode;
|
||||
|
||||
|
@ -575,3 +575,49 @@ _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol)
|
||||
|
||||
return algo;
|
||||
}
|
||||
|
||||
|
||||
/* Return a string with a cipher algorithm. */
|
||||
const char *
|
||||
_gpgme_cipher_algo_name (int algo, gpgme_protocol_t protocol)
|
||||
{
|
||||
if (protocol == GPGME_PROTOCOL_OPENPGP)
|
||||
{
|
||||
/* The algo is given according to OpenPGP specs. */
|
||||
switch (algo)
|
||||
{
|
||||
case 1: return "IDEA";
|
||||
case 2: return "3DES";
|
||||
case 3: return "CAST5";
|
||||
case 4: return "BLOWFISH";
|
||||
case 7: return "AES";
|
||||
case 8: return "AES192";
|
||||
case 9: return "AES256";
|
||||
case 10: return "TWOFISH";
|
||||
case 11: return "CAMELLIA128";
|
||||
case 12: return "CAMELLIA192";
|
||||
case 13: return "CAMELLIA256";
|
||||
}
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
|
||||
/* Return a string with the cipher mode. */
|
||||
const char *
|
||||
_gpgme_cipher_mode_name (int algo, gpgme_protocol_t protocol)
|
||||
{
|
||||
if (protocol == GPGME_PROTOCOL_OPENPGP)
|
||||
{
|
||||
/* The algo is given according to OpenPGP specs. */
|
||||
switch (algo)
|
||||
{
|
||||
case 0: return "CFB";
|
||||
case 1: return "EAX";
|
||||
case 2: return "OCB";
|
||||
}
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
@ -69,14 +69,10 @@ release_op_data (void *hook)
|
||||
op_data_t opd = (op_data_t) hook;
|
||||
gpgme_recipient_t recipient = opd->result.recipients;
|
||||
|
||||
if (opd->result.unsupported_algorithm)
|
||||
free (opd->result.unsupported_algorithm);
|
||||
|
||||
if (opd->result.file_name)
|
||||
free (opd->result.file_name);
|
||||
|
||||
if (opd->result.session_key)
|
||||
free (opd->result.session_key);
|
||||
free (opd->result.unsupported_algorithm);
|
||||
free (opd->result.file_name);
|
||||
free (opd->result.session_key);
|
||||
free (opd->result.symkey_algo);
|
||||
|
||||
while (recipient)
|
||||
{
|
||||
@ -104,6 +100,17 @@ gpgme_op_decrypt_result (gpgme_ctx_t ctx)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Make sure that SYMKEY_ALGO has a value. */
|
||||
if (!opd->result.symkey_algo)
|
||||
{
|
||||
opd->result.symkey_algo = strdup ("?.?");
|
||||
if (!opd->result.symkey_algo)
|
||||
{
|
||||
TRACE_SUC0 ("result=(null)");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (_gpgme_debug_trace ())
|
||||
{
|
||||
gpgme_recipient_t rcp;
|
||||
@ -263,6 +270,49 @@ parse_enc_to (char *args, gpgme_recipient_t *recp, gpgme_protocol_t protocol)
|
||||
}
|
||||
|
||||
|
||||
/* Parse the ARGS of a
|
||||
* DECRYPTION_INFO <mdc_method> <sym_algo> [<aead_algo>]
|
||||
* status. Returns 0 on success and updates the OPD.
|
||||
*/
|
||||
static gpgme_error_t
|
||||
parse_decryption_info (char *args, op_data_t opd, gpgme_protocol_t protocol)
|
||||
{
|
||||
char *field[3];
|
||||
int nfields;
|
||||
char *args2;
|
||||
int mdc, mode;
|
||||
const char *algostr, *modestr;
|
||||
|
||||
if (!args)
|
||||
return trace_gpg_error (GPG_ERR_INV_ENGINE);
|
||||
|
||||
args2 = strdup (args); /* Split modifies the input string. */
|
||||
nfields = _gpgme_split_fields (args2, field, DIM (field));
|
||||
if (nfields < 2)
|
||||
{
|
||||
free (args2);
|
||||
return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Required arg missing. */
|
||||
}
|
||||
|
||||
mdc = atoi (field[0]);
|
||||
algostr = _gpgme_cipher_algo_name (atoi (field[1]), protocol);
|
||||
mode = nfields < 3? 0 : atoi (field[2]);
|
||||
modestr = _gpgme_cipher_mode_name (mode, protocol);
|
||||
|
||||
free (args2);
|
||||
|
||||
free (opd->result.symkey_algo);
|
||||
if (!mode && mdc != 2)
|
||||
opd->result.symkey_algo = _gpgme_strconcat (algostr, ".PGPCFB", NULL);
|
||||
else
|
||||
opd->result.symkey_algo = _gpgme_strconcat (algostr, ".", modestr, NULL);
|
||||
if (!opd->result.symkey_algo)
|
||||
return gpg_error_from_syserror ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
gpgme_error_t
|
||||
_gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
|
||||
char *args)
|
||||
@ -303,7 +353,9 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
|
||||
break;
|
||||
|
||||
case GPGME_STATUS_DECRYPTION_INFO:
|
||||
/* Fixme: Provide a way to return the used symmetric algorithm. */
|
||||
err = parse_decryption_info (args, opd, ctx->protocol);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
|
||||
case GPGME_STATUS_DECRYPTION_OKAY:
|
||||
@ -357,9 +409,13 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
|
||||
break;
|
||||
|
||||
case GPGME_STATUS_PLAINTEXT:
|
||||
err = _gpgme_parse_plaintext (args, &opd->result.file_name);
|
||||
if (err)
|
||||
return err;
|
||||
{
|
||||
int mime = 0;
|
||||
err = _gpgme_parse_plaintext (args, &opd->result.file_name, &mime);
|
||||
if (err)
|
||||
return err;
|
||||
opd->result.is_mime = !!mime;
|
||||
}
|
||||
break;
|
||||
|
||||
case GPGME_STATUS_INQUIRE_MAXLEN:
|
||||
|
@ -62,6 +62,7 @@ encrypt_sym_status_handler (void *priv, gpgme_status_code_t code, char *args)
|
||||
|
||||
static gpgme_error_t
|
||||
encrypt_sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t cipher)
|
||||
{
|
||||
@ -72,7 +73,7 @@ encrypt_sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
symmetric = !recp || (flags & GPGME_ENCRYPT_SYMMETRIC);
|
||||
symmetric = (!recp && !recpstring) || (flags & GPGME_ENCRYPT_SYMMETRIC);
|
||||
|
||||
if (!plain)
|
||||
return gpg_error (GPG_ERR_NO_DATA);
|
||||
@ -103,53 +104,42 @@ encrypt_sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],
|
||||
: encrypt_sign_status_handler,
|
||||
ctx);
|
||||
|
||||
return _gpgme_engine_op_encrypt_sign (ctx->engine, recp, flags, plain,
|
||||
return _gpgme_engine_op_encrypt_sign (ctx->engine, recp, recpstring,
|
||||
flags, plain,
|
||||
cipher, ctx->use_armor,
|
||||
ctx /* FIXME */);
|
||||
}
|
||||
|
||||
|
||||
/* Encrypt plaintext PLAIN within CTX for the recipients RECP and
|
||||
store the resulting ciphertext in CIPHER. Also sign the ciphertext
|
||||
with the signers in CTX. */
|
||||
/* Old version of gpgme_op_encrypt_sign_ext_start w/o RECPSTRING. */
|
||||
gpgme_error_t
|
||||
gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t cipher)
|
||||
{
|
||||
gpgme_error_t err;
|
||||
|
||||
TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_sign_start", ctx,
|
||||
"flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher);
|
||||
|
||||
if (!ctx)
|
||||
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
|
||||
|
||||
if (_gpgme_debug_trace () && recp)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (recp[i])
|
||||
{
|
||||
TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],
|
||||
(recp[i]->subkeys && recp[i]->subkeys->fpr) ?
|
||||
recp[i]->subkeys->fpr : "invalid");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
err = encrypt_sign_start (ctx, 0, recp, flags, plain, cipher);
|
||||
return err;
|
||||
return gpgme_op_encrypt_sign_ext_start (ctx, recp, NULL,
|
||||
flags, plain, cipher);
|
||||
}
|
||||
|
||||
|
||||
/* Encrypt plaintext PLAIN within CTX for the recipients RECP and
|
||||
store the resulting ciphertext in CIPHER. Also sign the ciphertext
|
||||
with the signers in CTX. */
|
||||
/* Old version of gpgme_op_encrypt_sign_ext w/o RECPSTRING. */
|
||||
gpgme_error_t
|
||||
gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t cipher)
|
||||
{
|
||||
return gpgme_op_encrypt_sign_ext (ctx, recp, NULL, flags, plain, cipher);
|
||||
}
|
||||
|
||||
|
||||
/* Encrypt plaintext PLAIN within CTX for the recipients RECP and
|
||||
* store the resulting ciphertext in CIPHER. Also sign the ciphertext
|
||||
* with the signers in CTX. */
|
||||
gpgme_error_t
|
||||
gpgme_op_encrypt_sign_ext (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t cipher)
|
||||
{
|
||||
gpgme_error_t err;
|
||||
|
||||
@ -159,21 +149,70 @@ gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
if (!ctx)
|
||||
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
|
||||
|
||||
if (_gpgme_debug_trace () && recp)
|
||||
if (_gpgme_debug_trace () && (recp || recpstring))
|
||||
{
|
||||
int i = 0;
|
||||
if (recp)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (recp[i])
|
||||
{
|
||||
TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],
|
||||
(recp[i]->subkeys && recp[i]->subkeys->fpr) ?
|
||||
recp[i]->subkeys->fpr : "invalid");
|
||||
i++;
|
||||
}
|
||||
while (recp[i])
|
||||
{
|
||||
TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],
|
||||
(recp[i]->subkeys && recp[i]->subkeys->fpr) ?
|
||||
recp[i]->subkeys->fpr : "invalid");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_LOG1 ("recipients = '%s'", recpstring);
|
||||
}
|
||||
}
|
||||
|
||||
err = encrypt_sign_start (ctx, 1, recp, flags, plain, cipher);
|
||||
err = encrypt_sign_start (ctx, 1, recp, recpstring, flags, plain, cipher);
|
||||
if (!err)
|
||||
err = _gpgme_wait_one (ctx);
|
||||
return TRACE_ERR (err);
|
||||
}
|
||||
|
||||
|
||||
/* Encrypt plaintext PLAIN within CTX for the recipients RECP and
|
||||
store the resulting ciphertext in CIPHER. Also sign the ciphertext
|
||||
with the signers in CTX. */
|
||||
gpgme_error_t
|
||||
gpgme_op_encrypt_sign_ext_start (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t cipher)
|
||||
{
|
||||
gpgme_error_t err;
|
||||
|
||||
TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_sign_start", ctx,
|
||||
"flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher);
|
||||
|
||||
if (!ctx)
|
||||
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
|
||||
|
||||
if (_gpgme_debug_trace () && (recp || recpstring))
|
||||
{
|
||||
if (recp)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (recp[i])
|
||||
{
|
||||
TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],
|
||||
(recp[i]->subkeys && recp[i]->subkeys->fpr) ?
|
||||
recp[i]->subkeys->fpr : "invalid");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_LOG1 ("recipients = '%s'", recpstring);
|
||||
}
|
||||
}
|
||||
|
||||
err = encrypt_sign_start (ctx, 0, recp, recpstring, flags, plain, cipher);
|
||||
return err;
|
||||
}
|
||||
|
120
src/encrypt.c
120
src/encrypt.c
@ -214,6 +214,7 @@ _gpgme_op_encrypt_init_result (gpgme_ctx_t ctx)
|
||||
|
||||
static gpgme_error_t
|
||||
encrypt_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t cipher)
|
||||
{
|
||||
@ -228,13 +229,13 @@ encrypt_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
symmetric = !recp || (flags & GPGME_ENCRYPT_SYMMETRIC);
|
||||
symmetric = (!recp && !recpstring) || (flags & GPGME_ENCRYPT_SYMMETRIC);
|
||||
|
||||
if (!plain)
|
||||
return gpg_error (GPG_ERR_NO_DATA);
|
||||
if (!cipher)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
if (recp && ! *recp)
|
||||
if (recp && !*recp)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
if (symmetric && ctx->passphrase_cb)
|
||||
@ -252,48 +253,41 @@ encrypt_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],
|
||||
: encrypt_status_handler,
|
||||
ctx);
|
||||
|
||||
return _gpgme_engine_op_encrypt (ctx->engine, recp, flags, plain, cipher,
|
||||
ctx->use_armor);
|
||||
return _gpgme_engine_op_encrypt (ctx->engine, recp, recpstring,
|
||||
flags, plain, cipher, ctx->use_armor);
|
||||
}
|
||||
|
||||
|
||||
/* Old version of gpgme_op_encrypt_ext without RECPSTRING. */
|
||||
gpgme_error_t
|
||||
gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t cipher)
|
||||
{
|
||||
return gpgme_op_encrypt_ext (ctx, recp, NULL, flags, plain, cipher);
|
||||
}
|
||||
|
||||
|
||||
/* Old version of gpgme_op_encrypt_ext_start without RECPSTRING. */
|
||||
gpgme_error_t
|
||||
gpgme_op_encrypt_start (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t cipher)
|
||||
{
|
||||
gpgme_error_t err;
|
||||
|
||||
TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_start", ctx,
|
||||
"flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher);
|
||||
|
||||
if (!ctx)
|
||||
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
|
||||
|
||||
if (_gpgme_debug_trace () && recp)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (recp[i])
|
||||
{
|
||||
TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],
|
||||
(recp[i]->subkeys && recp[i]->subkeys->fpr) ?
|
||||
recp[i]->subkeys->fpr : "invalid");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
err = encrypt_start (ctx, 0, recp, flags, plain, cipher);
|
||||
return TRACE_ERR (err);
|
||||
return gpgme_op_encrypt_ext_start (ctx, recp, NULL, flags, plain, cipher);
|
||||
}
|
||||
|
||||
|
||||
/* Encrypt plaintext PLAIN within CTX for the recipients RECP and
|
||||
store the resulting ciphertext in CIPHER. */
|
||||
* store the resulting ciphertext in CIPHER. RECPSTRING can be used
|
||||
* instead of the RECP array to directly specify recipients as LF
|
||||
* delimited strings; these may be any kind of recipient specification
|
||||
* patterns as supported by the backend. */
|
||||
gpgme_error_t
|
||||
gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t cipher)
|
||||
gpgme_op_encrypt_ext (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t cipher)
|
||||
{
|
||||
gpgme_error_t err;
|
||||
|
||||
@ -303,21 +297,67 @@ gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
if (!ctx)
|
||||
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
|
||||
|
||||
if (_gpgme_debug_trace () && recp)
|
||||
if (_gpgme_debug_trace () && (recp || recpstring))
|
||||
{
|
||||
int i = 0;
|
||||
if (recp)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (recp[i])
|
||||
{
|
||||
TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],
|
||||
while (recp[i])
|
||||
{
|
||||
TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],
|
||||
(recp[i]->subkeys && recp[i]->subkeys->fpr) ?
|
||||
recp[i]->subkeys->fpr : "invalid");
|
||||
i++;
|
||||
}
|
||||
recp[i]->subkeys->fpr : "invalid");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_LOG1 ("recipients = '%s'", recpstring);
|
||||
}
|
||||
}
|
||||
|
||||
err = encrypt_start (ctx, 1, recp, flags, plain, cipher);
|
||||
err = encrypt_start (ctx, 1, recp, recpstring, flags, plain, cipher);
|
||||
if (!err)
|
||||
err = _gpgme_wait_one (ctx);
|
||||
return TRACE_ERR (err);
|
||||
}
|
||||
|
||||
|
||||
gpgme_error_t
|
||||
gpgme_op_encrypt_ext_start (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t cipher)
|
||||
{
|
||||
gpgme_error_t err;
|
||||
|
||||
TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_start", ctx,
|
||||
"flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher);
|
||||
|
||||
if (!ctx)
|
||||
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
|
||||
|
||||
if (_gpgme_debug_trace () && (recp || recpstring))
|
||||
{
|
||||
if (recp)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (recp[i])
|
||||
{
|
||||
TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],
|
||||
(recp[i]->subkeys && recp[i]->subkeys->fpr) ?
|
||||
recp[i]->subkeys->fpr : "invalid");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_LOG1 ("recipients = '%s'", recpstring);
|
||||
}
|
||||
}
|
||||
|
||||
err = encrypt_start (ctx, 0, recp, recpstring, flags, plain, cipher);
|
||||
return TRACE_ERR (err);
|
||||
}
|
||||
|
@ -72,10 +72,12 @@ struct engine_ops
|
||||
gpgme_error_t (*edit) (void *engine, int type, gpgme_key_t key,
|
||||
gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */);
|
||||
gpgme_error_t (*encrypt) (void *engine, gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t ciph,
|
||||
int use_armor);
|
||||
gpgme_error_t (*encrypt_sign) (void *engine, gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t ciph,
|
||||
int use_armor, gpgme_ctx_t ctx /* FIXME */);
|
||||
|
203
src/engine-gpg.c
203
src/engine-gpg.c
@ -43,6 +43,7 @@
|
||||
#include "sema.h"
|
||||
#include "debug.h"
|
||||
#include "data.h"
|
||||
#include "mbox-util.h"
|
||||
|
||||
#include "engine-backend.h"
|
||||
|
||||
@ -145,6 +146,11 @@ struct engine_gpg
|
||||
gpgme_pinentry_mode_t pinentry_mode;
|
||||
char request_origin[10];
|
||||
|
||||
struct {
|
||||
unsigned int no_symkey_cache : 1;
|
||||
unsigned int offline : 1;
|
||||
} flags;
|
||||
|
||||
/* NULL or the data object fed to --override_session_key-fd. */
|
||||
gpgme_data_t override_session_key;
|
||||
};
|
||||
@ -644,6 +650,12 @@ gpg_set_engine_flags (void *engine, const gpgme_ctx_t ctx)
|
||||
}
|
||||
else
|
||||
*gpg->request_origin = 0;
|
||||
|
||||
gpg->flags.no_symkey_cache = (ctx->no_symkey_cache
|
||||
&& have_gpg_version (gpg, "2.2.7"));
|
||||
|
||||
gpg->flags.offline = (ctx->offline && have_gpg_version (gpg, "2.1.23"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -875,7 +887,8 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
|
||||
argc++;
|
||||
if (!gpg->cmd.used)
|
||||
argc++; /* --batch */
|
||||
argc += 2; /* --no-sk-comments, --request-origin */
|
||||
argc += 4; /* --no-sk-comments, --request-origin, --no-symkey-cache */
|
||||
/* --disable-dirmngr */
|
||||
|
||||
argv = calloc (argc + 1, sizeof *argv);
|
||||
if (!argv)
|
||||
@ -937,6 +950,32 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
|
||||
argc++;
|
||||
}
|
||||
|
||||
if (gpg->flags.no_symkey_cache)
|
||||
{
|
||||
argv[argc] = strdup ("--no-symkey-cache");
|
||||
if (!argv[argc])
|
||||
{
|
||||
int saved_err = gpg_error_from_syserror ();
|
||||
free (fd_data_map);
|
||||
free_argv (argv);
|
||||
return saved_err;
|
||||
}
|
||||
argc++;
|
||||
}
|
||||
|
||||
if (gpg->flags.offline)
|
||||
{
|
||||
argv[argc] = strdup ("--disable-dirmngr");
|
||||
if (!argv[argc])
|
||||
{
|
||||
int saved_err = gpg_error_from_syserror ();
|
||||
free (fd_data_map);
|
||||
free_argv (argv);
|
||||
return saved_err;
|
||||
}
|
||||
argc++;
|
||||
}
|
||||
|
||||
if (gpg->pinentry_mode && have_gpg_version (gpg, "2.1.0"))
|
||||
{
|
||||
const char *s = NULL;
|
||||
@ -1871,8 +1910,70 @@ gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,
|
||||
}
|
||||
|
||||
|
||||
/* Add a single argument from a key to an -r option. */
|
||||
static gpg_error_t
|
||||
add_arg_recipient (engine_gpg_t gpg, gpgme_encrypt_flags_t flags,
|
||||
gpgme_key_t key)
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
if ((flags & GPGME_ENCRYPT_WANT_ADDRESS))
|
||||
{
|
||||
/* We have no way to figure out which mail address was
|
||||
* requested. FIXME: It would be possible to figure this out by
|
||||
* consulting the SENDER property of the context. */
|
||||
err = gpg_error (GPG_ERR_INV_USER_ID);
|
||||
}
|
||||
else
|
||||
err = add_arg (gpg, key->subkeys->fpr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Add a single argument from a USERID string to an -r option. */
|
||||
static gpg_error_t
|
||||
add_arg_recipient_string (engine_gpg_t gpg, gpgme_encrypt_flags_t flags,
|
||||
const char *userid, int useridlen)
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
if ((flags & GPGME_ENCRYPT_WANT_ADDRESS))
|
||||
{
|
||||
char *tmpstr, *mbox;
|
||||
|
||||
tmpstr = malloc (useridlen + 1);
|
||||
if (!tmpstr)
|
||||
err = gpg_error_from_syserror ();
|
||||
else
|
||||
{
|
||||
memcpy (tmpstr, userid, useridlen);
|
||||
tmpstr[useridlen] = 0;
|
||||
|
||||
mbox = _gpgme_mailbox_from_userid (tmpstr);
|
||||
if (!mbox)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
if (gpg_err_code (err) == GPG_ERR_EINVAL)
|
||||
err = gpg_error (GPG_ERR_INV_USER_ID);
|
||||
}
|
||||
else
|
||||
err = add_arg (gpg, mbox);
|
||||
|
||||
free (mbox);
|
||||
free (tmpstr);
|
||||
}
|
||||
}
|
||||
else
|
||||
err = add_arg_len (gpg, NULL, userid, useridlen);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static gpgme_error_t
|
||||
append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[])
|
||||
append_args_from_recipients (engine_gpg_t gpg, gpgme_encrypt_flags_t flags,
|
||||
gpgme_key_t recp[])
|
||||
{
|
||||
gpgme_error_t err = 0;
|
||||
int i = 0;
|
||||
@ -1884,7 +1985,7 @@ append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[])
|
||||
if (!err)
|
||||
err = add_arg (gpg, "-r");
|
||||
if (!err)
|
||||
err = add_arg (gpg, recp[i]->subkeys->fpr);
|
||||
err = add_arg_recipient (gpg, flags, recp[i]);
|
||||
if (err)
|
||||
break;
|
||||
i++;
|
||||
@ -1893,17 +1994,86 @@ append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[])
|
||||
}
|
||||
|
||||
|
||||
/* Take recipients from the LF delimited STRING and add -r args. */
|
||||
static gpg_error_t
|
||||
append_args_from_recipients_string (engine_gpg_t gpg,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
const char *string)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
gpgme_encrypt_flags_t orig_flags = flags;
|
||||
int any = 0;
|
||||
int ignore = 0;
|
||||
int hidden = 0;
|
||||
int file = 0;
|
||||
const char *s;
|
||||
int n;
|
||||
|
||||
do
|
||||
{
|
||||
/* Skip leading white space */
|
||||
while (*string == ' ' || *string == '\t')
|
||||
string++;
|
||||
if (!*string)
|
||||
break;
|
||||
|
||||
/* Look for the LF. */
|
||||
s = strchr (string, '\n');
|
||||
if (s)
|
||||
n = s - string;
|
||||
else
|
||||
n = strlen (string);
|
||||
while (n && (string[n-1] == ' ' || string[n-1] == '\t'))
|
||||
n--;
|
||||
|
||||
if (!ignore && n == 2 && !memcmp (string, "--", 2))
|
||||
ignore = 1;
|
||||
else if (!ignore && n == 8 && !memcmp (string, "--hidden", 8))
|
||||
hidden = 1;
|
||||
else if (!ignore && n == 11 && !memcmp (string, "--no-hidden", 11))
|
||||
hidden = 0;
|
||||
else if (!ignore && n == 6 && !memcmp (string, "--file", 6))
|
||||
{
|
||||
file = 1;
|
||||
/* Because the key is used as is we need to ignore this flag: */
|
||||
flags &= ~GPGME_ENCRYPT_WANT_ADDRESS;
|
||||
}
|
||||
else if (!ignore && n == 9 && !memcmp (string, "--no-file", 9))
|
||||
{
|
||||
file = 0;
|
||||
flags = orig_flags;
|
||||
}
|
||||
else if (n) /* Not empty - use it. */
|
||||
{
|
||||
err = add_arg (gpg, file? (hidden? "-F":"-f") : (hidden? "-R":"-r"));
|
||||
if (!err)
|
||||
err = add_arg_recipient_string (gpg, flags, string, n);
|
||||
if (!err)
|
||||
any = 1;
|
||||
}
|
||||
|
||||
string += n + !!s;
|
||||
}
|
||||
while (!err);
|
||||
|
||||
if (!err && !any)
|
||||
err = gpg_error (GPG_ERR_MISSING_KEY);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static gpgme_error_t
|
||||
gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
|
||||
gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
|
||||
{
|
||||
engine_gpg_t gpg = engine;
|
||||
gpgme_error_t err = 0;
|
||||
|
||||
if (recp)
|
||||
if (recp || recpstring)
|
||||
err = add_arg (gpg, "--encrypt");
|
||||
|
||||
if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp))
|
||||
if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || (!recp && !recpstring)))
|
||||
err = add_arg (gpg, "--symmetric");
|
||||
|
||||
if (!err && use_armor)
|
||||
@ -1930,7 +2100,7 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
|
||||
&& have_gpg_version (gpg, "2.1.14"))
|
||||
err = add_arg (gpg, "--mimemode");
|
||||
|
||||
if (recp)
|
||||
if (recp || recpstring)
|
||||
{
|
||||
/* If we know that all recipients are valid (full or ultimate trust)
|
||||
we can suppress further checks. */
|
||||
@ -1940,8 +2110,10 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
|
||||
if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
|
||||
err = add_arg (gpg, "--no-encrypt-to");
|
||||
|
||||
if (!err)
|
||||
err = append_args_from_recipients (gpg, recp);
|
||||
if (!err && !recp && recpstring)
|
||||
err = append_args_from_recipients_string (gpg, flags, recpstring);
|
||||
else if (!err)
|
||||
err = append_args_from_recipients (gpg, flags, recp);
|
||||
}
|
||||
|
||||
/* Tell the gpg object about the data. */
|
||||
@ -1974,6 +2146,7 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
|
||||
|
||||
static gpgme_error_t
|
||||
gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags, gpgme_data_t plain,
|
||||
gpgme_data_t ciph, int use_armor,
|
||||
gpgme_ctx_t ctx /* FIXME */)
|
||||
@ -1981,10 +2154,10 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
|
||||
engine_gpg_t gpg = engine;
|
||||
gpgme_error_t err = 0;
|
||||
|
||||
if (recp)
|
||||
if (recp || recpstring)
|
||||
err = add_arg (gpg, "--encrypt");
|
||||
|
||||
if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp))
|
||||
if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || (!recp && !recpstring)))
|
||||
err = add_arg (gpg, "--symmetric");
|
||||
|
||||
if (!err)
|
||||
@ -2002,7 +2175,7 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
|
||||
&& have_gpg_version (gpg, "2.1.14"))
|
||||
err = add_arg (gpg, "--mimemode");
|
||||
|
||||
if (recp)
|
||||
if (recp || recpstring)
|
||||
{
|
||||
/* If we know that all recipients are valid (full or ultimate trust)
|
||||
we can suppress further checks. */
|
||||
@ -2012,8 +2185,10 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
|
||||
if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
|
||||
err = add_arg (gpg, "--no-encrypt-to");
|
||||
|
||||
if (!err)
|
||||
err = append_args_from_recipients (gpg, recp);
|
||||
if (!err && !recp && recpstring)
|
||||
err = append_args_from_recipients_string (gpg, flags, recpstring);
|
||||
else if (!err)
|
||||
err = append_args_from_recipients (gpg, flags, recp);
|
||||
}
|
||||
|
||||
if (!err)
|
||||
|
@ -1327,8 +1327,57 @@ set_recipients (engine_gpgsm_t gpgsm, gpgme_key_t recp[])
|
||||
}
|
||||
|
||||
|
||||
/* Take recipients from the LF delimited STRING and send RECIPIENT
|
||||
* commands to gpgsm. */
|
||||
static gpgme_error_t
|
||||
gpgsm_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
|
||||
set_recipients_from_string (engine_gpgsm_t gpgsm, const char *string)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
char *line = NULL;
|
||||
int no_pubkey = 0;
|
||||
const char *s;
|
||||
int n;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
while (*string == ' ' || *string == '\t')
|
||||
string++;
|
||||
if (!*string)
|
||||
break;
|
||||
|
||||
s = strchr (string, '\n');
|
||||
if (s)
|
||||
n = s - string;
|
||||
else
|
||||
n = strlen (string);
|
||||
while (n && (string[n-1] == ' ' || string[n-1] == '\t'))
|
||||
n--;
|
||||
|
||||
gpgrt_free (line);
|
||||
if (gpgrt_asprintf (&line, "RECIPIENT %.*s", n, string) < 0)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
break;
|
||||
}
|
||||
string += n + !!s;
|
||||
|
||||
err = gpgsm_assuan_simple_command (gpgsm, line, gpgsm->status.fnc,
|
||||
gpgsm->status.fnc_value);
|
||||
|
||||
/* Fixme: Improve error reporting. */
|
||||
if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY)
|
||||
no_pubkey++;
|
||||
else if (err)
|
||||
break;
|
||||
}
|
||||
gpgrt_free (line);
|
||||
return err? err : no_pubkey? gpg_error (GPG_ERR_NO_PUBKEY) : 0;
|
||||
}
|
||||
|
||||
|
||||
static gpgme_error_t
|
||||
gpgsm_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
|
||||
{
|
||||
engine_gpgsm_t gpgsm = engine;
|
||||
@ -1339,7 +1388,7 @@ gpgsm_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
|
||||
if (!recp)
|
||||
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
|
||||
if (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO)
|
||||
if ((flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
|
||||
{
|
||||
err = gpgsm_assuan_simple_command (gpgsm,
|
||||
"OPTION no-encrypt-to", NULL, NULL);
|
||||
@ -1359,7 +1408,10 @@ gpgsm_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
|
||||
gpgsm_clear_fd (gpgsm, MESSAGE_FD);
|
||||
gpgsm->inline_data = NULL;
|
||||
|
||||
err = set_recipients (gpgsm, recp);
|
||||
if (!recp && recpstring)
|
||||
err = set_recipients_from_string (gpgsm, recpstring);
|
||||
else
|
||||
err = set_recipients (gpgsm, recp);
|
||||
|
||||
if (!err)
|
||||
err = start (gpgsm, "ENCRYPT");
|
||||
|
@ -1075,8 +1075,58 @@ set_recipients (engine_uiserver_t uiserver, gpgme_key_t recp[])
|
||||
}
|
||||
|
||||
|
||||
/* Take recipients from the LF delimited STRING and send RECIPIENT
|
||||
* commands to gpgsm. */
|
||||
static gpgme_error_t
|
||||
uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
|
||||
set_recipients_from_string (engine_uiserver_t uiserver, const char *string)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
char *line = NULL;
|
||||
int no_pubkey = 0;
|
||||
const char *s;
|
||||
int n;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
while (*string == ' ' || *string == '\t')
|
||||
string++;
|
||||
if (!*string)
|
||||
break;
|
||||
|
||||
s = strchr (string, '\n');
|
||||
if (s)
|
||||
n = s - string;
|
||||
else
|
||||
n = strlen (string);
|
||||
while (n && (string[n-1] == ' ' || string[n-1] == '\t'))
|
||||
n--;
|
||||
|
||||
gpgrt_free (line);
|
||||
if (gpgrt_asprintf (&line, "RECIPIENT %.*s", n, string) < 0)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
break;
|
||||
}
|
||||
string += n + !!s;
|
||||
|
||||
err = uiserver_assuan_simple_command (uiserver, line,
|
||||
uiserver->status.fnc,
|
||||
uiserver->status.fnc_value);
|
||||
|
||||
/* Fixme: Improve error reporting. */
|
||||
if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY)
|
||||
no_pubkey++;
|
||||
else if (err)
|
||||
break;
|
||||
}
|
||||
gpgrt_free (line);
|
||||
return err? err : no_pubkey? gpg_error (GPG_ERR_NO_PUBKEY) : 0;
|
||||
}
|
||||
|
||||
|
||||
static gpgme_error_t
|
||||
uiserver_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
|
||||
{
|
||||
engine_uiserver_t uiserver = engine;
|
||||
@ -1140,9 +1190,12 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
|
||||
|
||||
uiserver->inline_data = NULL;
|
||||
|
||||
if (recp)
|
||||
if (recp || recpstring)
|
||||
{
|
||||
err = set_recipients (uiserver, recp);
|
||||
if (recp)
|
||||
err = set_recipients (uiserver, recp);
|
||||
else
|
||||
err = set_recipients_from_string (uiserver, recpstring);
|
||||
if (err)
|
||||
{
|
||||
gpgrt_free (cmd);
|
||||
|
10
src/engine.c
10
src/engine.c
@ -721,6 +721,7 @@ _gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key,
|
||||
|
||||
gpgme_error_t
|
||||
_gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
|
||||
{
|
||||
@ -730,13 +731,14 @@ _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
|
||||
if (!engine->ops->encrypt)
|
||||
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
|
||||
return (*engine->ops->encrypt) (engine->engine, recp, flags, plain, ciph,
|
||||
use_armor);
|
||||
return (*engine->ops->encrypt) (engine->engine, recp, recpstring,
|
||||
flags, plain, ciph, use_armor);
|
||||
}
|
||||
|
||||
|
||||
gpgme_error_t
|
||||
_gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t ciph,
|
||||
int use_armor, gpgme_ctx_t ctx /* FIXME */)
|
||||
@ -747,8 +749,8 @@ _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
|
||||
if (!engine->ops->encrypt_sign)
|
||||
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
|
||||
return (*engine->ops->encrypt_sign) (engine->engine, recp, flags,
|
||||
plain, ciph, use_armor, ctx);
|
||||
return (*engine->ops->encrypt_sign) (engine->engine, recp, recpstring,
|
||||
flags, plain, ciph, use_armor, ctx);
|
||||
}
|
||||
|
||||
|
||||
|
@ -98,11 +98,13 @@ gpgme_error_t _gpgme_engine_op_edit (engine_t engine, int type,
|
||||
gpgme_ctx_t ctx /* FIXME */);
|
||||
gpgme_error_t _gpgme_engine_op_encrypt (engine_t engine,
|
||||
gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t ciph,
|
||||
int use_armor);
|
||||
gpgme_error_t _gpgme_engine_op_encrypt_sign (engine_t engine,
|
||||
gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain,
|
||||
gpgme_data_t ciph,
|
||||
|
592
src/gpgme-json.c
592
src/gpgme-json.c
@ -20,8 +20,7 @@
|
||||
|
||||
/* This is tool implements the Native Messaging protocol of web
|
||||
* browsers and provides the server part of it. A Javascript based
|
||||
* client can be found in lang/javascript. The used data format is
|
||||
* similar to the API of openpgpjs.
|
||||
* client can be found in lang/javascript.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@ -33,6 +32,7 @@
|
||||
#include <locale.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define GPGRT_ENABLE_ES_MACROS 1
|
||||
#define GPGRT_ENABLE_LOG_MACROS 1
|
||||
@ -48,6 +48,16 @@ int main (void){fputs ("Build with Libgpg-error >= 1.28!\n", stderr);return 1;}
|
||||
/* We don't allow a request with more than 64 MiB. */
|
||||
#define MAX_REQUEST_SIZE (64 * 1024 * 1024)
|
||||
|
||||
/* Minimal, default and maximum chunk size for returned data. The
|
||||
* first chunk is returned directly. If the "more" flag is also
|
||||
* returned, a "getmore" command needs to be used to get the next
|
||||
* chunk. Right now this value covers just the value of the "data"
|
||||
* element; so to cover for the other returned objects this values
|
||||
* needs to be lower than the maximum allowed size of the browser. */
|
||||
#define MIN_REPLY_CHUNK_SIZE 512
|
||||
#define DEF_REPLY_CHUNK_SIZE (512 * 1024)
|
||||
#define MAX_REPLY_CHUNK_SIZE (10 * 1024 * 1024)
|
||||
|
||||
|
||||
static void xoutofcore (const char *type) GPGRT_ATTR_NORETURN;
|
||||
static cjson_t error_object_v (cjson_t json, const char *message,
|
||||
@ -63,6 +73,16 @@ static int opt_interactive;
|
||||
/* True is debug mode is active. */
|
||||
static int opt_debug;
|
||||
|
||||
/* Pending data to be returned by a getmore command. */
|
||||
static struct
|
||||
{
|
||||
char *buffer; /* Malloced data or NULL if not used. */
|
||||
size_t length; /* Length of that data. */
|
||||
size_t written; /* # of already written bytes from BUFFER. */
|
||||
const char *type;/* The "type" of the data. */
|
||||
int base64; /* The "base64" flag of the data. */
|
||||
} pending_data;
|
||||
|
||||
|
||||
/*
|
||||
* Helper functions and macros
|
||||
@ -94,6 +114,19 @@ static int opt_debug;
|
||||
|
||||
#define spacep(p) (*(p) == ' ' || *(p) == '\t')
|
||||
|
||||
#ifndef HAVE_STPCPY
|
||||
static GPGRT_INLINE char *
|
||||
_my_stpcpy (char *a, const char *b)
|
||||
{
|
||||
while (*b)
|
||||
*a++ = *b++;
|
||||
*a = 0;
|
||||
return a;
|
||||
}
|
||||
#define stpcpy(a,b) _my_stpcpy ((a), (b))
|
||||
#endif /*!HAVE_STPCPY*/
|
||||
|
||||
|
||||
|
||||
static void
|
||||
xoutofcore (const char *type)
|
||||
@ -146,11 +179,12 @@ xjson_AddBoolToObject (cjson_t object, const char *name, int abool)
|
||||
return ;
|
||||
}
|
||||
|
||||
/* This is similar to cJSON_AddStringToObject but takes a gpgme DATA
|
||||
* object and adds it under NAME as a base 64 encoded string to
|
||||
* OBJECT. Ownership of DATA is transferred to this function. */
|
||||
/* This is similar to cJSON_AddStringToObject but takes (DATA,
|
||||
* DATALEN) and adds it under NAME as a base 64 encoded string to
|
||||
* OBJECT. */
|
||||
static gpg_error_t
|
||||
add_base64_to_object (cjson_t object, const char *name, gpgme_data_t data)
|
||||
add_base64_to_object (cjson_t object, const char *name,
|
||||
const void *data, size_t datalen)
|
||||
{
|
||||
#if GPGRT_VERSION_NUMBER < 0x011d00 /* 1.29 */
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
@ -160,7 +194,6 @@ add_base64_to_object (cjson_t object, const char *name, gpgme_data_t data)
|
||||
gpgrt_b64state_t state = NULL;
|
||||
cjson_t j_str = NULL;
|
||||
void *buffer = NULL;
|
||||
size_t buflen;
|
||||
|
||||
fp = es_fopenmem (0, "rwb");
|
||||
if (!fp)
|
||||
@ -175,20 +208,9 @@ add_base64_to_object (cjson_t object, const char *name, gpgme_data_t data)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
gpgme_data_write (data, "", 1); /* Make sure we have a string. */
|
||||
buffer = gpgme_data_release_and_get_mem (data, &buflen);
|
||||
data = NULL;
|
||||
if (!buffer)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = gpgrt_b64enc_write (state, buffer, buflen);
|
||||
err = gpgrt_b64enc_write (state, data, datalen);
|
||||
if (err)
|
||||
goto leave;
|
||||
xfree (buffer);
|
||||
buffer = NULL;
|
||||
|
||||
err = gpgrt_b64enc_finish (state);
|
||||
state = NULL;
|
||||
@ -226,7 +248,6 @@ add_base64_to_object (cjson_t object, const char *name, gpgme_data_t data)
|
||||
cJSON_Delete (j_str);
|
||||
gpgrt_b64enc_finish (state);
|
||||
es_fclose (fp);
|
||||
gpgme_data_release (data);
|
||||
return err;
|
||||
#endif
|
||||
}
|
||||
@ -354,18 +375,42 @@ get_protocol (cjson_t json, gpgme_protocol_t *r_protocol)
|
||||
}
|
||||
|
||||
|
||||
/* Extract the keys from the KEYS array in the JSON object. CTX is a
|
||||
* GPGME context object. On success an array with the keys is stored
|
||||
* at R_KEYS. In failure an error code is returned. */
|
||||
/* Get the chunksize from JSON and store it at R_CHUNKSIZE. */
|
||||
static gpg_error_t
|
||||
get_keys (gpgme_ctx_t ctx, cjson_t json, gpgme_key_t **r_keys)
|
||||
get_chunksize (cjson_t json, size_t *r_chunksize)
|
||||
{
|
||||
cjson_t j_item;
|
||||
|
||||
*r_chunksize = DEF_REPLY_CHUNK_SIZE;
|
||||
j_item = cJSON_GetObjectItem (json, "chunksize");
|
||||
if (!j_item)
|
||||
;
|
||||
else if (!cjson_is_number (j_item))
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
else if ((size_t)j_item->valueint < MIN_REPLY_CHUNK_SIZE)
|
||||
*r_chunksize = MIN_REPLY_CHUNK_SIZE;
|
||||
else if ((size_t)j_item->valueint > MAX_REPLY_CHUNK_SIZE)
|
||||
*r_chunksize = MAX_REPLY_CHUNK_SIZE;
|
||||
else
|
||||
*r_chunksize = (size_t)j_item->valueint;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Extract the keys from the "keys" array in the JSON object. On
|
||||
* success a string with the keys identifiers is stored at R_KEYS.
|
||||
* The keys in that string are LF delimited. On failure an error code
|
||||
* is returned. */
|
||||
static gpg_error_t
|
||||
get_keys (cjson_t json, char **r_keystring)
|
||||
{
|
||||
gpg_error_t err;
|
||||
cjson_t j_keys, j_item;
|
||||
int i, nkeys;
|
||||
gpgme_key_t *keys;
|
||||
char *p;
|
||||
size_t length;
|
||||
|
||||
*r_keys = NULL;
|
||||
*r_keystring = NULL;
|
||||
|
||||
j_keys = cJSON_GetObjectItem (json, "keys");
|
||||
if (!j_keys)
|
||||
@ -373,8 +418,15 @@ get_keys (gpgme_ctx_t ctx, cjson_t json, gpgme_key_t **r_keys)
|
||||
if (!cjson_is_array (j_keys) && !cjson_is_string (j_keys))
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
/* Fixme: We should better use a membuf like thing. */
|
||||
length = 1; /* For the EOS. */
|
||||
if (cjson_is_string (j_keys))
|
||||
nkeys = 1;
|
||||
{
|
||||
nkeys = 1;
|
||||
length += strlen (j_keys->valuestring);
|
||||
if (strchr (j_keys->valuestring, '\n'))
|
||||
return gpg_error (GPG_ERR_INV_USER_ID);
|
||||
}
|
||||
else
|
||||
{
|
||||
nkeys = cJSON_GetArraySize (j_keys);
|
||||
@ -385,43 +437,37 @@ get_keys (gpgme_ctx_t ctx, cjson_t json, gpgme_key_t **r_keys)
|
||||
j_item = cJSON_GetArrayItem (j_keys, i);
|
||||
if (!j_item || !cjson_is_string (j_item))
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
if (i)
|
||||
length++; /* Space for delimiter. */
|
||||
length += strlen (j_item->valuestring);
|
||||
if (strchr (j_item->valuestring, '\n'))
|
||||
return gpg_error (GPG_ERR_INV_USER_ID);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now allocate an array to store the gpgme key objects. */
|
||||
keys = xcalloc (nkeys + 1, sizeof *keys);
|
||||
p = *r_keystring = xtrymalloc (length);
|
||||
if (!p)
|
||||
return gpg_error_from_syserror ();
|
||||
|
||||
if (cjson_is_string (j_keys))
|
||||
{
|
||||
err = gpgme_get_key (ctx, j_keys->valuestring, &keys[0], 0);
|
||||
if (err)
|
||||
goto leave;
|
||||
strcpy (p, j_keys->valuestring);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i < nkeys; i++)
|
||||
{
|
||||
j_item = cJSON_GetArrayItem (j_keys, i);
|
||||
err = gpgme_get_key (ctx, j_item->valuestring, &keys[i], 0);
|
||||
if (err)
|
||||
goto leave;
|
||||
if (i)
|
||||
*p++ = '\n'; /* Add delimiter. */
|
||||
p = stpcpy (p, j_item->valuestring);
|
||||
}
|
||||
}
|
||||
err = 0;
|
||||
*r_keys = keys;
|
||||
keys = NULL;
|
||||
|
||||
leave:
|
||||
if (keys)
|
||||
{
|
||||
for (i=0; keys[i]; i++)
|
||||
gpgme_key_unref (keys[i]);
|
||||
xfree (keys);
|
||||
}
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* GPGME support functions.
|
||||
@ -546,10 +592,95 @@ data_from_base64_string (gpgme_data_t *r_data, cjson_t json)
|
||||
|
||||
|
||||
/*
|
||||
* Implementaion of the commands.
|
||||
* Implementation of the commands.
|
||||
*/
|
||||
|
||||
|
||||
/* Create a "data" object and the "type", "base64" and "more" flags
|
||||
* from DATA and append them to RESULT. Ownership if DATA is
|
||||
* transferred to this function. TYPE must be a fixed string.
|
||||
* CHUNKSIZE is the chunksize requested from the caller. If BASE64 is
|
||||
* -1 the need for base64 encoding is determined by the content of
|
||||
* DATA, all other values are take as rtue or false. Note that
|
||||
* op_getmore has similar code but works on PENDING_DATA which is set
|
||||
* here. */
|
||||
static gpg_error_t
|
||||
make_data_object (cjson_t result, gpgme_data_t data, size_t chunksize,
|
||||
const char *type, int base64)
|
||||
{
|
||||
gpg_error_t err;
|
||||
char *buffer;
|
||||
size_t buflen;
|
||||
int c;
|
||||
|
||||
if (!base64 || base64 == -1) /* Make sure that we really have a string. */
|
||||
gpgme_data_write (data, "", 1);
|
||||
|
||||
buffer = gpgme_data_release_and_get_mem (data, &buflen);
|
||||
data = NULL;
|
||||
if (!buffer)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (base64 == -1)
|
||||
{
|
||||
base64 = 0;
|
||||
if (!buflen)
|
||||
log_fatal ("Appended Nul byte got lost\n");
|
||||
if (memchr (buffer, 0, buflen-1))
|
||||
{
|
||||
buflen--; /* Adjust for the extra nul byte. */
|
||||
base64 = 1;
|
||||
}
|
||||
/* Fixme: We might want to do more advanced heuristics than to
|
||||
* only look for a Nul. */
|
||||
}
|
||||
|
||||
/* Adjust the chunksize if we need to do base64 conversion. */
|
||||
if (base64)
|
||||
chunksize = (chunksize / 4) * 3;
|
||||
|
||||
xjson_AddStringToObject (result, "type", type);
|
||||
xjson_AddBoolToObject (result, "base64", base64);
|
||||
|
||||
if (buflen > chunksize)
|
||||
{
|
||||
xjson_AddBoolToObject (result, "more", 1);
|
||||
|
||||
c = buffer[chunksize];
|
||||
buffer[chunksize] = 0;
|
||||
if (base64)
|
||||
err = add_base64_to_object (result, "data", buffer, chunksize);
|
||||
else
|
||||
err = cjson_AddStringToObject (result, "data", buffer);
|
||||
buffer[chunksize] = c;
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
pending_data.buffer = buffer;
|
||||
buffer = NULL;
|
||||
pending_data.length = buflen;
|
||||
pending_data.written = chunksize;
|
||||
pending_data.type = type;
|
||||
pending_data.base64 = base64;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (base64)
|
||||
err = add_base64_to_object (result, "data", buffer, buflen);
|
||||
else
|
||||
err = cjson_AddStringToObject (result, "data", buffer);
|
||||
}
|
||||
|
||||
leave:
|
||||
gpgme_free (buffer);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char hlp_encrypt[] =
|
||||
"op: \"encrypt\"\n"
|
||||
"keys: Array of strings with the fingerprints or user-ids\n"
|
||||
@ -559,14 +690,17 @@ static const char hlp_encrypt[] =
|
||||
"\n"
|
||||
"Optional parameters:\n"
|
||||
"protocol: Either \"openpgp\" (default) or \"cms\".\n"
|
||||
"chunksize: Max number of bytes in the resulting \"data\".\n"
|
||||
"\n"
|
||||
"Optional boolean flags (default is false):\n"
|
||||
"base64: Input data is base64 encoded.\n"
|
||||
"mime: Indicate that data is a MIME object.\n"
|
||||
"armor: Request output in armored format.\n"
|
||||
"always-trust: Request --always-trust option.\n"
|
||||
"no-encrypt-to: Do not use a default recipient.\n"
|
||||
"no-compress: Do not compress the plaintext first.\n"
|
||||
"throw-keyids: Request the --throw-keyids option.\n"
|
||||
"want-address: Require that the keys include a mail address.\n"
|
||||
"wrap: Assume the input is an OpenPGP message.\n"
|
||||
"\n"
|
||||
"Response on success:\n"
|
||||
@ -574,27 +708,34 @@ static const char hlp_encrypt[] =
|
||||
"data: Unless armor mode is used a Base64 encoded binary\n"
|
||||
" ciphertext. In armor mode a string with an armored\n"
|
||||
" OpenPGP or a PEM message.\n"
|
||||
"base64: Boolean indicating whether data is base64 encoded.";
|
||||
"base64: Boolean indicating whether data is base64 encoded.\n"
|
||||
"more: Optional boolean indicating that \"getmore\" is required.";
|
||||
static gpg_error_t
|
||||
op_encrypt (cjson_t request, cjson_t result)
|
||||
{
|
||||
gpg_error_t err;
|
||||
gpgme_ctx_t ctx = NULL;
|
||||
gpgme_protocol_t protocol;
|
||||
size_t chunksize;
|
||||
int opt_base64;
|
||||
gpgme_key_t *keys = NULL;
|
||||
int opt_mime;
|
||||
char *keystring = NULL;
|
||||
cjson_t j_input;
|
||||
gpgme_data_t input = NULL;
|
||||
gpgme_data_t output = NULL;
|
||||
int abool, i;
|
||||
int abool;
|
||||
gpgme_encrypt_flags_t encrypt_flags = 0;
|
||||
|
||||
if ((err = get_protocol (request, &protocol)))
|
||||
goto leave;
|
||||
ctx = get_context (protocol);
|
||||
if ((err = get_chunksize (request, &chunksize)))
|
||||
goto leave;
|
||||
|
||||
if ((err = get_boolean_flag (request, "base64", 0, &opt_base64)))
|
||||
goto leave;
|
||||
if ((err = get_boolean_flag (request, "mime", 0, &opt_mime)))
|
||||
goto leave;
|
||||
|
||||
if ((err = get_boolean_flag (request, "armor", 0, &abool)))
|
||||
goto leave;
|
||||
@ -619,10 +760,14 @@ op_encrypt (cjson_t request, cjson_t result)
|
||||
goto leave;
|
||||
if (abool)
|
||||
encrypt_flags |= GPGME_ENCRYPT_WRAP;
|
||||
if ((err = get_boolean_flag (request, "want-address", 0, &abool)))
|
||||
goto leave;
|
||||
if (abool)
|
||||
encrypt_flags |= GPGME_ENCRYPT_WANT_ADDRESS;
|
||||
|
||||
|
||||
/* Get the keys. */
|
||||
err = get_keys (ctx, request, &keys);
|
||||
err = get_keys (request, &keystring);
|
||||
if (err)
|
||||
{
|
||||
/* Provide a custom error response. */
|
||||
@ -630,6 +775,119 @@ op_encrypt (cjson_t request, cjson_t result)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Get the data. Note that INPUT is a shallow data object with the
|
||||
* storage hold in REQUEST. */
|
||||
j_input = cJSON_GetObjectItem (request, "data");
|
||||
if (!j_input)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_NO_DATA);
|
||||
goto leave;
|
||||
}
|
||||
if (!cjson_is_string (j_input))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_INV_VALUE);
|
||||
goto leave;
|
||||
}
|
||||
if (opt_base64)
|
||||
{
|
||||
err = data_from_base64_string (&input, j_input);
|
||||
if (err)
|
||||
{
|
||||
error_object (result, "Error decoding Base-64 encoded 'data': %s",
|
||||
gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err = gpgme_data_new_from_mem (&input, j_input->valuestring,
|
||||
strlen (j_input->valuestring), 0);
|
||||
if (err)
|
||||
{
|
||||
error_object (result, "Error getting 'data': %s", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
if (opt_mime)
|
||||
gpgme_data_set_encoding (input, GPGME_DATA_ENCODING_MIME);
|
||||
|
||||
|
||||
/* Create an output data object. */
|
||||
err = gpgme_data_new (&output);
|
||||
if (err)
|
||||
{
|
||||
error_object (result, "Error creating output data object: %s",
|
||||
gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Encrypt. */
|
||||
err = gpgme_op_encrypt_ext (ctx, NULL, keystring, encrypt_flags,
|
||||
input, output);
|
||||
/* encrypt_result = gpgme_op_encrypt_result (ctx); */
|
||||
if (err)
|
||||
{
|
||||
error_object (result, "Encryption failed: %s", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
gpgme_data_release (input);
|
||||
input = NULL;
|
||||
|
||||
/* We need to base64 if armoring has not been requested. */
|
||||
err = make_data_object (result, output, chunksize,
|
||||
"ciphertext", !gpgme_get_armor (ctx));
|
||||
output = NULL;
|
||||
|
||||
leave:
|
||||
xfree (keystring);
|
||||
release_context (ctx);
|
||||
gpgme_data_release (input);
|
||||
gpgme_data_release (output);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char hlp_decrypt[] =
|
||||
"op: \"decrypt\"\n"
|
||||
"data: The encrypted data.\n"
|
||||
"\n"
|
||||
"Optional parameters:\n"
|
||||
"protocol: Either \"openpgp\" (default) or \"cms\".\n"
|
||||
"chunksize: Max number of bytes in the resulting \"data\".\n"
|
||||
"\n"
|
||||
"Optional boolean flags (default is false):\n"
|
||||
"base64: Input data is base64 encoded.\n"
|
||||
"\n"
|
||||
"Response on success:\n"
|
||||
"type: \"plaintext\"\n"
|
||||
"data: The decrypted data. This may be base64 encoded.\n"
|
||||
"base64: Boolean indicating whether data is base64 encoded.\n"
|
||||
"mime: A Boolean indicating whether the data is a MIME object.\n"
|
||||
"info: An optional object with extra information.\n"
|
||||
"more: Optional boolean indicating that \"getmore\" is required.";
|
||||
static gpg_error_t
|
||||
op_decrypt (cjson_t request, cjson_t result)
|
||||
{
|
||||
gpg_error_t err;
|
||||
gpgme_ctx_t ctx = NULL;
|
||||
gpgme_protocol_t protocol;
|
||||
size_t chunksize;
|
||||
int opt_base64;
|
||||
cjson_t j_input;
|
||||
gpgme_data_t input = NULL;
|
||||
gpgme_data_t output = NULL;
|
||||
gpgme_decrypt_result_t decrypt_result;
|
||||
|
||||
if ((err = get_protocol (request, &protocol)))
|
||||
goto leave;
|
||||
ctx = get_context (protocol);
|
||||
if ((err = get_chunksize (request, &chunksize)))
|
||||
goto leave;
|
||||
|
||||
if ((err = get_boolean_flag (request, "base64", 0, &opt_base64)))
|
||||
goto leave;
|
||||
|
||||
/* Get the data. Note that INPUT is a shallow data object with the
|
||||
* storage hold in REQUEST. */
|
||||
j_input = cJSON_GetObjectItem (request, "data");
|
||||
@ -673,59 +931,118 @@ op_encrypt (cjson_t request, cjson_t result)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Encrypt. */
|
||||
err = gpgme_op_encrypt (ctx, keys, encrypt_flags, input, output);
|
||||
/* encrypt_result = gpgme_op_encrypt_result (ctx); */
|
||||
/* Decrypt. */
|
||||
err = gpgme_op_decrypt_ext (ctx, GPGME_DECRYPT_VERIFY,
|
||||
input, output);
|
||||
decrypt_result = gpgme_op_decrypt_result (ctx);
|
||||
if (err)
|
||||
{
|
||||
error_object (result, "Encryption failed: %s", gpg_strerror (err));
|
||||
error_object (result, "Decryption failed: %s", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
gpgme_data_release (input);
|
||||
input = NULL;
|
||||
|
||||
xjson_AddStringToObject (result, "type", "ciphertext");
|
||||
/* If armoring is used we do not need to base64 the output. */
|
||||
xjson_AddBoolToObject (result, "base64", !gpgme_get_armor (ctx));
|
||||
if (gpgme_get_armor (ctx))
|
||||
{
|
||||
char *buffer;
|
||||
if (decrypt_result->is_mime)
|
||||
xjson_AddBoolToObject (result, "mime", 1);
|
||||
|
||||
/* Make sure that we really have a string. */
|
||||
gpgme_data_write (output, "", 1);
|
||||
buffer = gpgme_data_release_and_get_mem (output, NULL);
|
||||
if (!buffer)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
err = cjson_AddStringToObject (result, "data", buffer);
|
||||
gpgme_free (buffer);
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = add_base64_to_object (result, "data", output);
|
||||
output = NULL;
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
err = make_data_object (result, output, chunksize, "plaintext", -1);
|
||||
output = NULL;
|
||||
|
||||
leave:
|
||||
if (keys)
|
||||
{
|
||||
for (i=0; keys[i]; i++)
|
||||
gpgme_key_unref (keys[i]);
|
||||
xfree (keys);
|
||||
}
|
||||
release_context (ctx);
|
||||
gpgme_data_release (input);
|
||||
gpgme_data_release (output);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char hlp_getmore[] =
|
||||
"op: \"getmore\"\n"
|
||||
"\n"
|
||||
"Optional parameters:\n"
|
||||
"chunksize: Max number of bytes in the \"data\" object.\n"
|
||||
"\n"
|
||||
"Response on success:\n"
|
||||
"type: Type of the pending data\n"
|
||||
"data: The next chunk of data\n"
|
||||
"base64: Boolean indicating whether data is base64 encoded\n"
|
||||
"more: Optional boolean requesting another \"getmore\".";
|
||||
static gpg_error_t
|
||||
op_getmore (cjson_t request, cjson_t result)
|
||||
{
|
||||
gpg_error_t err;
|
||||
int c;
|
||||
size_t n;
|
||||
size_t chunksize;
|
||||
|
||||
if ((err = get_chunksize (request, &chunksize)))
|
||||
goto leave;
|
||||
|
||||
/* Adjust the chunksize if we need to do base64 conversion. */
|
||||
if (pending_data.base64)
|
||||
chunksize = (chunksize / 4) * 3;
|
||||
|
||||
/* Do we have anything pending? */
|
||||
if (!pending_data.buffer)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_NO_DATA);
|
||||
error_object (result, "Operation not possible: %s", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
xjson_AddStringToObject (result, "type", pending_data.type);
|
||||
xjson_AddBoolToObject (result, "base64", pending_data.base64);
|
||||
|
||||
if (pending_data.written >= pending_data.length)
|
||||
{
|
||||
/* EOF reached. This should not happen but we return an empty
|
||||
* string once in case of client errors. */
|
||||
gpgme_free (pending_data.buffer);
|
||||
pending_data.buffer = NULL;
|
||||
xjson_AddBoolToObject (result, "more", 0);
|
||||
err = cjson_AddStringToObject (result, "data", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
n = pending_data.length - pending_data.written;
|
||||
if (n > chunksize)
|
||||
{
|
||||
n = chunksize;
|
||||
xjson_AddBoolToObject (result, "more", 1);
|
||||
}
|
||||
else
|
||||
xjson_AddBoolToObject (result, "more", 0);
|
||||
|
||||
c = pending_data.buffer[pending_data.written + n];
|
||||
pending_data.buffer[pending_data.written + n] = 0;
|
||||
if (pending_data.base64)
|
||||
err = add_base64_to_object (result, "data",
|
||||
(pending_data.buffer
|
||||
+ pending_data.written), n);
|
||||
else
|
||||
err = cjson_AddStringToObject (result, "data",
|
||||
(pending_data.buffer
|
||||
+ pending_data.written));
|
||||
pending_data.buffer[pending_data.written + n] = c;
|
||||
if (!err)
|
||||
{
|
||||
pending_data.written += n;
|
||||
if (pending_data.written >= pending_data.length)
|
||||
{
|
||||
gpgme_free (pending_data.buffer);
|
||||
pending_data.buffer = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
leave:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char hlp_help[] =
|
||||
"The tool expects a JSON object with the request and responds with\n"
|
||||
"another JSON object. Even on error a JSON object is returned. The\n"
|
||||
@ -735,6 +1052,7 @@ static const char hlp_help[] =
|
||||
"returned. To list all operations it is allowed to leave out \"op\" in\n"
|
||||
"help mode. Supported values for \"op\" are:\n\n"
|
||||
" encrypt Encrypt data.\n"
|
||||
" getmore Retrieve remaining data.\n"
|
||||
" help Help overview.";
|
||||
static gpg_error_t
|
||||
op_help (cjson_t request, cjson_t result)
|
||||
@ -757,6 +1075,10 @@ op_help (cjson_t request, cjson_t result)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Dispatcher
|
||||
*/
|
||||
|
||||
/* Process a request and return the response. The response is a newly
|
||||
* allocated string or NULL in case of an error. */
|
||||
@ -769,8 +1091,8 @@ process_request (const char *request)
|
||||
const char * const helpstr;
|
||||
} optbl[] = {
|
||||
{ "encrypt", op_encrypt, hlp_encrypt },
|
||||
|
||||
|
||||
{ "decrypt", op_decrypt, hlp_decrypt },
|
||||
{ "getmore", op_getmore, hlp_getmore },
|
||||
{ "help", op_help, hlp_help },
|
||||
{ NULL }
|
||||
};
|
||||
@ -825,6 +1147,14 @@ process_request (const char *request)
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
/* If this is not the "getmore" command and we have any
|
||||
* pending data release that data. */
|
||||
if (pending_data.buffer && optbl[idx].handler != op_getmore)
|
||||
{
|
||||
gpgme_free (pending_data.buffer);
|
||||
pending_data.buffer = NULL;
|
||||
}
|
||||
|
||||
err = optbl[idx].handler (json, response);
|
||||
if (err)
|
||||
{
|
||||
@ -839,7 +1169,6 @@ process_request (const char *request)
|
||||
|
||||
xjson_AddStringToObject (response, "op", op);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else /* Operation not supported. */
|
||||
@ -866,6 +1195,48 @@ process_request (const char *request)
|
||||
* Driver code
|
||||
*/
|
||||
|
||||
static char *
|
||||
get_file (const char *fname)
|
||||
{
|
||||
gpg_error_t err;
|
||||
estream_t fp;
|
||||
struct stat st;
|
||||
char *buf;
|
||||
size_t buflen;
|
||||
|
||||
fp = es_fopen (fname, "r");
|
||||
if (!fp)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("can't open '%s': %s\n", fname, gpg_strerror (err));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fstat (es_fileno(fp), &st))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("can't stat '%s': %s\n", fname, gpg_strerror (err));
|
||||
es_fclose (fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buflen = st.st_size;
|
||||
buf = xmalloc (buflen+1);
|
||||
if (es_fread (buf, buflen, 1, fp) != 1)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
|
||||
es_fclose (fp);
|
||||
xfree (buf);
|
||||
return NULL;
|
||||
}
|
||||
buf[buflen] = 0;
|
||||
es_fclose (fp);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/* Return a malloced line or NULL on EOF. Terminate on read
|
||||
* error. */
|
||||
static char *
|
||||
@ -929,14 +1300,39 @@ process_meta_commands (const char *request)
|
||||
request++;
|
||||
|
||||
if (!strncmp (request, "help", 4) && (spacep (request+4) || !request[4]))
|
||||
result = process_request ("{ \"op\": \"help\","
|
||||
" \"interactive_help\": "
|
||||
"\"\\nMeta commands:\\n"
|
||||
" ,help This help\\n"
|
||||
" ,quit Terminate process\""
|
||||
"}");
|
||||
{
|
||||
if (request[4])
|
||||
{
|
||||
char *buf = xstrconcat ("{ \"help\":true, \"op\":\"", request+5,
|
||||
"\" }", NULL);
|
||||
result = process_request (buf);
|
||||
xfree (buf);
|
||||
}
|
||||
else
|
||||
result = process_request ("{ \"op\": \"help\","
|
||||
" \"interactive_help\": "
|
||||
"\"\\nMeta commands:\\n"
|
||||
" ,read FNAME Process data from FILE\\n"
|
||||
" ,help CMD Print help for a command\\n"
|
||||
" ,quit Terminate process\""
|
||||
"}");
|
||||
}
|
||||
else if (!strncmp (request, "quit", 4) && (spacep (request+4) || !request[4]))
|
||||
exit (0);
|
||||
else if (!strncmp (request, "read", 4) && (spacep (request+4) || !request[4]))
|
||||
{
|
||||
if (!request[4])
|
||||
log_info ("usage: ,read FILENAME\n");
|
||||
else
|
||||
{
|
||||
char *buffer = get_file (request + 5);
|
||||
if (buffer)
|
||||
{
|
||||
result = process_request (buffer);
|
||||
xfree (buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
log_info ("invalid meta command\n");
|
||||
|
||||
|
@ -538,6 +538,10 @@ gpgme_set_ctx_flag (gpgme_ctx_t ctx, const char *name, const char *value)
|
||||
if (!ctx->request_origin)
|
||||
err = gpg_error_from_syserror ();
|
||||
}
|
||||
else if (!strcmp (name, "no-symkey-cache"))
|
||||
{
|
||||
ctx->no_symkey_cache = abool;
|
||||
}
|
||||
else
|
||||
err = gpg_error (GPG_ERR_UNKNOWN_NAME);
|
||||
|
||||
@ -583,6 +587,10 @@ gpgme_get_ctx_flag (gpgme_ctx_t ctx, const char *name)
|
||||
{
|
||||
return ctx->request_origin? ctx->request_origin : "";
|
||||
}
|
||||
else if (!strcmp (name, "no-symkey-cache"))
|
||||
{
|
||||
return ctx->no_symkey_cache? "1":"";
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
@ -267,5 +267,10 @@ EXPORTS
|
||||
|
||||
gpgme_op_conf_dir @199
|
||||
|
||||
gpgme_op_encrypt_ext @200
|
||||
gpgme_op_encrypt_ext_start @201
|
||||
gpgme_op_encrypt_sign_ext @202
|
||||
gpgme_op_encrypt_sign_ext_start @203
|
||||
|
||||
; END
|
||||
|
||||
|
384
src/gpgme.h.in
384
src/gpgme.h.in
@ -1,6 +1,6 @@
|
||||
/* gpgme.h - Public interface to GnuPG Made Easy. -*- c -*-
|
||||
* Copyright (C) 2000 Werner Koch (dd9jn)
|
||||
* Copyright (C) 2001-2017 g10 Code GmbH
|
||||
* Copyright (C) 2001-2018 g10 Code GmbH
|
||||
*
|
||||
* This file is part of GPGME.
|
||||
*
|
||||
@ -16,6 +16,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*
|
||||
* Generated from gpgme.h.in for @GPGME_CONFIG_HOST@.
|
||||
*/
|
||||
@ -37,14 +38,14 @@ extern "C" {
|
||||
|
||||
|
||||
/* The version of this header should match the one of the library. Do
|
||||
not use this symbol in your application, use gpgme_check_version
|
||||
instead. The purpose of this macro is to let autoconf (using the
|
||||
AM_PATH_GPGME macro) check that this header matches the installed
|
||||
library. */
|
||||
* not use this symbol in your application, use gpgme_check_version
|
||||
* instead. The purpose of this macro is to let autoconf (using the
|
||||
* AM_PATH_GPGME macro) check that this header matches the installed
|
||||
* library. */
|
||||
#define GPGME_VERSION "@PACKAGE_VERSION@"
|
||||
|
||||
/* The version number of this header. It may be used to handle minor
|
||||
API incompatibilities. */
|
||||
* API incompatibilities. */
|
||||
#define GPGME_VERSION_NUMBER @VERSION_NUMBER@
|
||||
|
||||
|
||||
@ -87,7 +88,7 @@ extern "C" {
|
||||
|
||||
|
||||
/* The macro _GPGME_DEPRECATED_OUTSIDE_GPGME suppresses warnings for
|
||||
fields we must access in GPGME for ABI compatibility. */
|
||||
* fields we must access in GPGME for ABI compatibility. */
|
||||
#ifdef _GPGME_IN_GPGME
|
||||
#define _GPGME_DEPRECATED_OUTSIDE_GPGME(a,b)
|
||||
#else
|
||||
@ -113,7 +114,7 @@ extern "C" {
|
||||
*/
|
||||
|
||||
/* The context holds some global state and configuration options, as
|
||||
well as the results of a crypto operation. */
|
||||
* well as the results of a crypto operation. */
|
||||
struct gpgme_context;
|
||||
typedef struct gpgme_context *gpgme_ctx_t;
|
||||
|
||||
@ -124,7 +125,8 @@ typedef struct gpgme_data *gpgme_data_t;
|
||||
|
||||
|
||||
/*
|
||||
* Wrappers for the libgpg-error library.
|
||||
* Wrappers for the libgpg-error library. They are generally not
|
||||
* needed and the gpg-error versions may be used instead.
|
||||
*/
|
||||
|
||||
typedef gpg_error_t gpgme_error_t;
|
||||
@ -140,7 +142,7 @@ gpgme_err_make (gpgme_err_source_t source, gpgme_err_code_t code)
|
||||
|
||||
|
||||
/* The user can define GPGME_ERR_SOURCE_DEFAULT before including this
|
||||
file to specify a default source for gpgme_error. */
|
||||
* file to specify a default source for gpgme_error. */
|
||||
#ifndef GPGME_ERR_SOURCE_DEFAULT
|
||||
#define GPGME_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_USER_1
|
||||
#endif
|
||||
@ -167,45 +169,46 @@ gpgme_err_source (gpgme_error_t err)
|
||||
|
||||
|
||||
/* Return a pointer to a string containing a description of the error
|
||||
code in the error value ERR. This function is not thread safe. */
|
||||
* code in the error value ERR. This function is not thread safe. */
|
||||
const char *gpgme_strerror (gpgme_error_t err);
|
||||
|
||||
/* Return the error string for ERR in the user-supplied buffer BUF of
|
||||
size BUFLEN. This function is, in contrast to gpg_strerror,
|
||||
thread-safe if a thread-safe strerror_r() function is provided by
|
||||
the system. If the function succeeds, 0 is returned and BUF
|
||||
contains the string describing the error. If the buffer was not
|
||||
large enough, ERANGE is returned and BUF contains as much of the
|
||||
beginning of the error string as fits into the buffer. */
|
||||
* size BUFLEN. This function is, in contrast to gpg_strerror,
|
||||
* thread-safe if a thread-safe strerror_r() function is provided by
|
||||
* the system. If the function succeeds, 0 is returned and BUF
|
||||
* contains the string describing the error. If the buffer was not
|
||||
* large enough, ERANGE is returned and BUF contains as much of the
|
||||
* beginning of the error string as fits into the buffer. */
|
||||
int gpgme_strerror_r (gpg_error_t err, char *buf, size_t buflen);
|
||||
|
||||
/* Return a pointer to a string containing a description of the error
|
||||
source in the error value ERR. */
|
||||
* source in the error value ERR. */
|
||||
const char *gpgme_strsource (gpgme_error_t err);
|
||||
|
||||
/* Retrieve the error code for the system error ERR. This returns
|
||||
GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report
|
||||
this). */
|
||||
* GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report
|
||||
* this). */
|
||||
gpgme_err_code_t gpgme_err_code_from_errno (int err);
|
||||
|
||||
/* Retrieve the system error for the error code CODE. This returns 0
|
||||
if CODE is not a system error code. */
|
||||
* if CODE is not a system error code. */
|
||||
int gpgme_err_code_to_errno (gpgme_err_code_t code);
|
||||
|
||||
/* Retrieve the error code directly from the ERRNO variable. This
|
||||
returns GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped
|
||||
(report this) and GPG_ERR_MISSING_ERRNO if ERRNO has the value 0. */
|
||||
* returns GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped
|
||||
* (report this) and GPG_ERR_MISSING_ERRNO if ERRNO has the value 0. */
|
||||
gpgme_err_code_t gpgme_err_code_from_syserror (void);
|
||||
|
||||
/* Set the ERRNO variable. This function is the preferred way to set
|
||||
ERRNO due to peculiarities on WindowsCE. */
|
||||
* ERRNO due to peculiarities on WindowsCE. */
|
||||
void gpgme_err_set_errno (int err);
|
||||
|
||||
/* Return an error value with the error source SOURCE and the system
|
||||
error ERR. FIXME: Should be inline. */
|
||||
* error ERR. FIXME: Should be inline. */
|
||||
gpgme_error_t gpgme_err_make_from_errno (gpgme_err_source_t source, int err);
|
||||
|
||||
/* Return an error value with the system error ERR. FIXME: Should be inline. */
|
||||
/* Return an error value with the system error ERR.
|
||||
* inline. */
|
||||
gpgme_error_t gpgme_error_from_errno (int err);
|
||||
|
||||
|
||||
@ -373,6 +376,8 @@ gpgme_protocol_t;
|
||||
#define GPGME_KEYLIST_MODE_EPHEMERAL 128
|
||||
#define GPGME_KEYLIST_MODE_VALIDATE 256
|
||||
|
||||
#define GPGME_KEYLIST_MODE_LOCATE (1|2)
|
||||
|
||||
typedef unsigned int gpgme_keylist_mode_t;
|
||||
|
||||
|
||||
@ -417,7 +422,7 @@ struct _gpgme_sig_notation
|
||||
struct _gpgme_sig_notation *next;
|
||||
|
||||
/* If NAME is a null pointer, then VALUE contains a policy URL
|
||||
rather than a notation. */
|
||||
* rather than a notation. */
|
||||
char *name;
|
||||
|
||||
/* The value of the notation data. */
|
||||
@ -632,10 +637,10 @@ struct _gpgme_key_sig
|
||||
/* Same as in gpgme_signature_t. */
|
||||
gpgme_error_t status;
|
||||
|
||||
/* Deprecated; use SIG_CLASS instead. */
|
||||
#ifdef __cplusplus
|
||||
unsigned int _obsolete_class _GPGME_DEPRECATED(0,4);
|
||||
#else
|
||||
/* Must be set to SIG_CLASS below. */
|
||||
unsigned int class _GPGME_DEPRECATED_OUTSIDE_GPGME(0,4);
|
||||
#endif
|
||||
|
||||
@ -874,10 +879,10 @@ gpgme_error_t gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t proto);
|
||||
gpgme_protocol_t gpgme_get_protocol (gpgme_ctx_t ctx);
|
||||
|
||||
/* Set the crypto protocol to be used by CTX to PROTO.
|
||||
gpgme_set_protocol actually sets the backend engine. This sets the
|
||||
crypto protocol used in engines that support more than one crypto
|
||||
prococol (for example, an UISERVER can support OpenPGP and CMS).
|
||||
This is reset to the default with gpgme_set_protocol. */
|
||||
* gpgme_set_protocol actually sets the backend engine. This sets the
|
||||
* crypto protocol used in engines that support more than one crypto
|
||||
* prococol (for example, an UISERVER can support OpenPGP and CMS).
|
||||
* This is reset to the default with gpgme_set_protocol. */
|
||||
gpgme_error_t gpgme_set_sub_protocol (gpgme_ctx_t ctx,
|
||||
gpgme_protocol_t proto);
|
||||
|
||||
@ -929,47 +934,47 @@ gpgme_error_t gpgme_set_pinentry_mode (gpgme_ctx_t ctx,
|
||||
gpgme_pinentry_mode_t gpgme_get_pinentry_mode (gpgme_ctx_t ctx);
|
||||
|
||||
/* Set the passphrase callback function in CTX to CB. HOOK_VALUE is
|
||||
passed as first argument to the passphrase callback function. */
|
||||
* passed as first argument to the passphrase callback function. */
|
||||
void gpgme_set_passphrase_cb (gpgme_ctx_t ctx,
|
||||
gpgme_passphrase_cb_t cb, void *hook_value);
|
||||
|
||||
/* Get the current passphrase callback function in *CB and the current
|
||||
hook value in *HOOK_VALUE. */
|
||||
* hook value in *HOOK_VALUE. */
|
||||
void gpgme_get_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t *cb,
|
||||
void **hook_value);
|
||||
|
||||
/* Set the progress callback function in CTX to CB. HOOK_VALUE is
|
||||
passed as first argument to the progress callback function. */
|
||||
* passed as first argument to the progress callback function. */
|
||||
void gpgme_set_progress_cb (gpgme_ctx_t c, gpgme_progress_cb_t cb,
|
||||
void *hook_value);
|
||||
|
||||
/* Get the current progress callback function in *CB and the current
|
||||
hook value in *HOOK_VALUE. */
|
||||
* hook value in *HOOK_VALUE. */
|
||||
void gpgme_get_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t *cb,
|
||||
void **hook_value);
|
||||
|
||||
/* Set the status callback function in CTX to CB. HOOK_VALUE is
|
||||
passed as first argument to the status callback function. */
|
||||
* passed as first argument to the status callback function. */
|
||||
void gpgme_set_status_cb (gpgme_ctx_t c, gpgme_status_cb_t cb,
|
||||
void *hook_value);
|
||||
|
||||
/* Get the current status callback function in *CB and the current
|
||||
hook value in *HOOK_VALUE. */
|
||||
* hook value in *HOOK_VALUE. */
|
||||
void gpgme_get_status_cb (gpgme_ctx_t ctx, gpgme_status_cb_t *cb,
|
||||
void **hook_value);
|
||||
|
||||
/* This function sets the locale for the context CTX, or the default
|
||||
locale if CTX is a null pointer. */
|
||||
* locale if CTX is a null pointer. */
|
||||
gpgme_error_t gpgme_set_locale (gpgme_ctx_t ctx, int category,
|
||||
const char *value);
|
||||
|
||||
/* Get the information about the configured engines. A pointer to the
|
||||
first engine in the statically allocated linked list is returned.
|
||||
The returned data is valid until the next gpgme_ctx_set_engine_info. */
|
||||
* first engine in the statically allocated linked list is returned.
|
||||
* The returned data is valid until the next gpgme_ctx_set_engine_info. */
|
||||
gpgme_engine_info_t gpgme_ctx_get_engine_info (gpgme_ctx_t ctx);
|
||||
|
||||
/* Set the engine info for the context CTX, protocol PROTO, to the
|
||||
file name FILE_NAME and the home directory HOME_DIR. */
|
||||
* file name FILE_NAME and the home directory HOME_DIR. */
|
||||
gpgme_error_t gpgme_ctx_set_engine_info (gpgme_ctx_t ctx,
|
||||
gpgme_protocol_t proto,
|
||||
const char *file_name,
|
||||
@ -991,10 +996,10 @@ gpgme_key_t gpgme_signers_enum (const gpgme_ctx_t ctx, int seq);
|
||||
void gpgme_sig_notation_clear (gpgme_ctx_t ctx);
|
||||
|
||||
/* Add the human-readable notation data with name NAME and value VALUE
|
||||
to the context CTX, using the flags FLAGS. If NAME is NULL, then
|
||||
VALUE should be a policy URL. The flag
|
||||
GPGME_SIG_NOTATION_HUMAN_READABLE is forced to be true for notation
|
||||
data, and false for policy URLs. */
|
||||
* to the context CTX, using the flags FLAGS. If NAME is NULL, then
|
||||
* VALUE should be a policy URL. The flag
|
||||
* GPGME_SIG_NOTATION_HUMAN_READABLE is forced to be true for notation
|
||||
* data, and false for policy URLs. */
|
||||
gpgme_error_t gpgme_sig_notation_add (gpgme_ctx_t ctx, const char *name,
|
||||
const char *value,
|
||||
gpgme_sig_notation_flags_t flags);
|
||||
@ -1018,17 +1023,17 @@ const char *gpgme_get_sender (gpgme_ctx_t ctx);
|
||||
typedef gpgme_error_t (*gpgme_io_cb_t) (void *data, int fd);
|
||||
|
||||
/* The type of a function that can register FNC as the I/O callback
|
||||
function for the file descriptor FD with direction dir (0: for writing,
|
||||
1: for reading). FNC_DATA should be passed as DATA to FNC. The
|
||||
function should return a TAG suitable for the corresponding
|
||||
gpgme_remove_io_cb_t, and an error value. */
|
||||
* function for the file descriptor FD with direction dir (0: for writing,
|
||||
* 1: for reading). FNC_DATA should be passed as DATA to FNC. The
|
||||
* function should return a TAG suitable for the corresponding
|
||||
* gpgme_remove_io_cb_t, and an error value. */
|
||||
typedef gpgme_error_t (*gpgme_register_io_cb_t) (void *data, int fd, int dir,
|
||||
gpgme_io_cb_t fnc,
|
||||
void *fnc_data, void **tag);
|
||||
|
||||
/* The type of a function that can remove a previously registered I/O
|
||||
callback function given TAG as returned by the register
|
||||
function. */
|
||||
* callback function given TAG as returned by the register
|
||||
* function. */
|
||||
typedef void (*gpgme_remove_io_cb_t) (void *tag);
|
||||
|
||||
typedef enum
|
||||
@ -1043,7 +1048,7 @@ gpgme_event_io_t;
|
||||
struct gpgme_io_event_done_data
|
||||
{
|
||||
/* A fatal IPC error or an operational error in state-less
|
||||
protocols. */
|
||||
* protocols. */
|
||||
gpgme_error_t err;
|
||||
|
||||
/* An operational errors in session-based protocols. */
|
||||
@ -1052,7 +1057,7 @@ struct gpgme_io_event_done_data
|
||||
typedef struct gpgme_io_event_done_data *gpgme_io_event_done_data_t;
|
||||
|
||||
/* The type of a function that is called when a context finished an
|
||||
operation. */
|
||||
* operation. */
|
||||
typedef void (*gpgme_event_io_cb_t) (void *data, gpgme_event_io_t type,
|
||||
void *type_data);
|
||||
|
||||
@ -1073,13 +1078,13 @@ void gpgme_set_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs);
|
||||
void gpgme_get_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs);
|
||||
|
||||
/* Wrappers around the internal I/O functions for use with
|
||||
gpgme_passphrase_cb_t and gpgme_interact_cb_t. */
|
||||
* gpgme_passphrase_cb_t and gpgme_interact_cb_t. */
|
||||
@API__SSIZE_T@ gpgme_io_read (int fd, void *buffer, size_t count);
|
||||
@API__SSIZE_T@ gpgme_io_write (int fd, const void *buffer, size_t count);
|
||||
int gpgme_io_writen (int fd, const void *buffer, size_t count);
|
||||
|
||||
/* Process the pending operation and, if HANG is non-zero, wait for
|
||||
the pending operation to finish. */
|
||||
* the pending operation to finish. */
|
||||
gpgme_ctx_t gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang);
|
||||
|
||||
gpgme_ctx_t gpgme_wait_ext (gpgme_ctx_t ctx, gpgme_error_t *status,
|
||||
@ -1098,21 +1103,21 @@ gpgme_error_t gpgme_cancel_async (gpgme_ctx_t ctx);
|
||||
*/
|
||||
|
||||
/* Read up to SIZE bytes into buffer BUFFER from the data object with
|
||||
the handle HANDLE. Return the number of characters read, 0 on EOF
|
||||
and -1 on error. If an error occurs, errno is set. */
|
||||
* the handle HANDLE. Return the number of characters read, 0 on EOF
|
||||
* and -1 on error. If an error occurs, errno is set. */
|
||||
typedef @API__SSIZE_T@ (*gpgme_data_read_cb_t) (void *handle, void *buffer,
|
||||
size_t size);
|
||||
|
||||
/* Write up to SIZE bytes from buffer BUFFER to the data object with
|
||||
the handle HANDLE. Return the number of characters written, or -1
|
||||
on error. If an error occurs, errno is set. */
|
||||
* the handle HANDLE. Return the number of characters written, or -1
|
||||
* on error. If an error occurs, errno is set. */
|
||||
typedef @API__SSIZE_T@ (*gpgme_data_write_cb_t) (void *handle, const void *buffer,
|
||||
size_t size);
|
||||
|
||||
/* Set the current position from where the next read or write starts
|
||||
in the data object with the handle HANDLE to OFFSET, relativ to
|
||||
WHENCE. Returns the new offset in bytes from the beginning of the
|
||||
data object. */
|
||||
* in the data object with the handle HANDLE to OFFSET, relativ to
|
||||
* WHENCE. Returns the new offset in bytes from the beginning of the
|
||||
* data object. */
|
||||
typedef @API__OFF_T@ (*gpgme_data_seek_cb_t) (void *handle,
|
||||
@API__OFF_T@ offset, int whence);
|
||||
|
||||
@ -1129,19 +1134,19 @@ struct gpgme_data_cbs
|
||||
typedef struct gpgme_data_cbs *gpgme_data_cbs_t;
|
||||
|
||||
/* 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
|
||||
-1 on error. If an error occurs, errno is set. */
|
||||
* the handle DH. Return the number of characters read, 0 on EOF and
|
||||
* -1 on error. If an error occurs, errno is set. */
|
||||
@API__SSIZE_T@ gpgme_data_read (gpgme_data_t dh, void *buffer, size_t size);
|
||||
|
||||
/* Write up to SIZE bytes from buffer BUFFER to the data object with
|
||||
the handle DH. Return the number of characters written, or -1 on
|
||||
error. If an error occurs, errno is set. */
|
||||
* the handle DH. Return the number of characters written, or -1 on
|
||||
* error. If an error occurs, errno is set. */
|
||||
@API__SSIZE_T@ gpgme_data_write (gpgme_data_t dh, const void *buffer, size_t size);
|
||||
|
||||
/* Set the current position from where the next read or write starts
|
||||
in the data object with the handle DH to OFFSET, relativ to WHENCE.
|
||||
Returns the new offset in bytes from the beginning of the data
|
||||
object. */
|
||||
* in the data object with the handle DH to OFFSET, relativ to WHENCE.
|
||||
* Returns the new offset in bytes from the beginning of the data
|
||||
* object. */
|
||||
@API__OFF_T@ gpgme_data_seek (gpgme_data_t dh, @API__OFF_T@ offset, int whence);
|
||||
|
||||
/* Create a new data buffer and return it in R_DH. */
|
||||
@ -1151,19 +1156,19 @@ gpgme_error_t gpgme_data_new (gpgme_data_t *r_dh);
|
||||
void gpgme_data_release (gpgme_data_t dh);
|
||||
|
||||
/* Create a new data buffer filled with SIZE bytes starting from
|
||||
BUFFER. If COPY is zero, copying is delayed until necessary, and
|
||||
the data is taken from the original location when needed. */
|
||||
* BUFFER. If COPY is zero, copying is delayed until necessary, and
|
||||
* the data is taken from the original location when needed. */
|
||||
gpgme_error_t gpgme_data_new_from_mem (gpgme_data_t *r_dh,
|
||||
const char *buffer, size_t size,
|
||||
int copy);
|
||||
|
||||
/* Destroy the data buffer DH and return a pointer to its content.
|
||||
The memory has be to released with gpgme_free() by the user. It's
|
||||
size is returned in R_LEN. */
|
||||
* The memory has be to released with gpgme_free() by the user. It's
|
||||
* size is returned in R_LEN. */
|
||||
char *gpgme_data_release_and_get_mem (gpgme_data_t dh, size_t *r_len);
|
||||
|
||||
/* Release the memory returned by gpgme_data_release_and_get_mem() and
|
||||
some other functions. */
|
||||
* some other functions. */
|
||||
void gpgme_free (void *buffer);
|
||||
|
||||
gpgme_error_t gpgme_data_new_from_cbs (gpgme_data_t *dh,
|
||||
@ -1182,11 +1187,11 @@ gpgme_error_t gpgme_data_set_encoding (gpgme_data_t dh,
|
||||
gpgme_data_encoding_t enc);
|
||||
|
||||
/* Get the file name associated with the data object with handle DH, or
|
||||
NULL if there is none. */
|
||||
* NULL if there is none. */
|
||||
char *gpgme_data_get_file_name (gpgme_data_t dh);
|
||||
|
||||
/* Set the file name associated with the data object with handle DH to
|
||||
FILE_NAME. */
|
||||
* FILE_NAME. */
|
||||
gpgme_error_t gpgme_data_set_file_name (gpgme_data_t dh,
|
||||
const char *file_name);
|
||||
|
||||
@ -1199,15 +1204,15 @@ gpgme_data_type_t gpgme_data_identify (gpgme_data_t dh, int reserved);
|
||||
|
||||
|
||||
/* Create a new data buffer filled with the content of file FNAME.
|
||||
COPY must be non-zero. For delayed read, please use
|
||||
gpgme_data_new_from_fd or gpgme_data_new_from_stream instead. */
|
||||
* COPY must be non-zero. For delayed read, please use
|
||||
* gpgme_data_new_from_fd or gpgme_data_new_from_stream instead. */
|
||||
gpgme_error_t gpgme_data_new_from_file (gpgme_data_t *r_dh,
|
||||
const char *fname,
|
||||
int copy);
|
||||
|
||||
/* Create a new data buffer filled with LENGTH bytes starting from
|
||||
OFFSET within the file FNAME or stream FP (exactly one must be
|
||||
non-zero). */
|
||||
* OFFSET within the file FNAME or stream FP (exactly one must be
|
||||
* non-zero). */
|
||||
gpgme_error_t gpgme_data_new_from_filepart (gpgme_data_t *r_dh,
|
||||
const char *fname, FILE *fp,
|
||||
@API__OFF_T@ offset, size_t length);
|
||||
@ -1222,7 +1227,7 @@ gpgme_error_t gpgme_data_rewind (gpgme_data_t dh);
|
||||
*/
|
||||
|
||||
/* Get the key with the fingerprint FPR from the crypto backend. If
|
||||
SECRET is true, get the secret key. */
|
||||
* SECRET is true, get the secret key. */
|
||||
gpgme_error_t gpgme_get_key (gpgme_ctx_t ctx, const char *fpr,
|
||||
gpgme_key_t *r_key, int secret);
|
||||
|
||||
@ -1233,7 +1238,7 @@ gpgme_error_t gpgme_key_from_uid (gpgme_key_t *key, const char *name);
|
||||
void gpgme_key_ref (gpgme_key_t key);
|
||||
|
||||
/* Release a reference to KEY. If this was the last one the key is
|
||||
destroyed. */
|
||||
* destroyed. */
|
||||
void gpgme_key_unref (gpgme_key_t key);
|
||||
void gpgme_key_release (gpgme_key_t key);
|
||||
|
||||
@ -1266,22 +1271,35 @@ typedef enum
|
||||
GPGME_ENCRYPT_NO_COMPRESS = 16,
|
||||
GPGME_ENCRYPT_SYMMETRIC = 32,
|
||||
GPGME_ENCRYPT_THROW_KEYIDS = 64,
|
||||
GPGME_ENCRYPT_WRAP = 128
|
||||
GPGME_ENCRYPT_WRAP = 128,
|
||||
GPGME_ENCRYPT_WANT_ADDRESS = 256
|
||||
}
|
||||
gpgme_encrypt_flags_t;
|
||||
|
||||
/* Encrypt plaintext PLAIN within CTX for the recipients RECP and
|
||||
store the resulting ciphertext in CIPHER. */
|
||||
* store the resulting ciphertext in CIPHER. */
|
||||
gpgme_error_t gpgme_op_encrypt_start (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t cipher);
|
||||
gpgme_data_t plain,
|
||||
gpgme_data_t cipher);
|
||||
gpgme_error_t gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t cipher);
|
||||
gpgme_data_t plain,
|
||||
gpgme_data_t cipher);
|
||||
gpgme_error_t gpgme_op_encrypt_ext_start (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain,
|
||||
gpgme_data_t cipher);
|
||||
gpgme_error_t gpgme_op_encrypt_ext (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain,
|
||||
gpgme_data_t cipher);
|
||||
|
||||
/* Encrypt plaintext PLAIN within CTX for the recipients RECP and
|
||||
store the resulting ciphertext in CIPHER. Also sign the ciphertext
|
||||
with the signers in CTX. */
|
||||
* store the resulting ciphertext in CIPHER. Also sign the ciphertext
|
||||
* with the signers in CTX. */
|
||||
gpgme_error_t gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx,
|
||||
gpgme_key_t recp[],
|
||||
gpgme_encrypt_flags_t flags,
|
||||
@ -1289,7 +1307,19 @@ gpgme_error_t gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx,
|
||||
gpgme_data_t cipher);
|
||||
gpgme_error_t gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain, gpgme_data_t cipher);
|
||||
gpgme_data_t plain,
|
||||
gpgme_data_t cipher);
|
||||
gpgme_error_t gpgme_op_encrypt_sign_ext_start (gpgme_ctx_t ctx,
|
||||
gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain,
|
||||
gpgme_data_t cipher);
|
||||
gpgme_error_t gpgme_op_encrypt_sign_ext (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
const char *recpstring,
|
||||
gpgme_encrypt_flags_t flags,
|
||||
gpgme_data_t plain,
|
||||
gpgme_data_t cipher);
|
||||
|
||||
|
||||
/*
|
||||
@ -1317,6 +1347,7 @@ struct _gpgme_recipient
|
||||
};
|
||||
typedef struct _gpgme_recipient *gpgme_recipient_t;
|
||||
|
||||
|
||||
/* An object to return results from a decryption operation.
|
||||
* This structure shall be considered read-only and an application
|
||||
* must not allocate such a structure on its own. */
|
||||
@ -1331,24 +1362,33 @@ struct _gpgme_op_decrypt_result
|
||||
* mode. */
|
||||
unsigned int is_de_vs : 1;
|
||||
|
||||
/* The message claims that the content is a MIME object. */
|
||||
unsigned int is_mime : 1;
|
||||
|
||||
/* Internal to GPGME, do not use. */
|
||||
int _unused : 30;
|
||||
int _unused : 29;
|
||||
|
||||
gpgme_recipient_t recipients;
|
||||
|
||||
/* The original file name of the plaintext message, if
|
||||
available. */
|
||||
* available. */
|
||||
char *file_name;
|
||||
|
||||
/* A textual representation of the session key used to decrypt the
|
||||
* message, if available */
|
||||
char *session_key;
|
||||
|
||||
/* A string with the symmetric encryption algorithm and mode using
|
||||
* the format "<algo>.<mode>". */
|
||||
char *symkey_algo;
|
||||
};
|
||||
typedef struct _gpgme_op_decrypt_result *gpgme_decrypt_result_t;
|
||||
|
||||
|
||||
/* Retrieve a pointer to the result of the decrypt operation. */
|
||||
gpgme_decrypt_result_t gpgme_op_decrypt_result (gpgme_ctx_t ctx);
|
||||
|
||||
|
||||
/* The valid decryption flags. */
|
||||
typedef enum
|
||||
{
|
||||
@ -1357,15 +1397,16 @@ typedef enum
|
||||
}
|
||||
gpgme_decrypt_flags_t;
|
||||
|
||||
|
||||
/* Decrypt ciphertext CIPHER within CTX and store the resulting
|
||||
plaintext in PLAIN. */
|
||||
* plaintext in PLAIN. */
|
||||
gpgme_error_t gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher,
|
||||
gpgme_data_t plain);
|
||||
gpgme_error_t gpgme_op_decrypt (gpgme_ctx_t ctx,
|
||||
gpgme_data_t cipher, gpgme_data_t plain);
|
||||
|
||||
/* Decrypt ciphertext CIPHER and make a signature verification within
|
||||
CTX and store the resulting plaintext in PLAIN. */
|
||||
* CTX and store the resulting plaintext in PLAIN. */
|
||||
gpgme_error_t gpgme_op_decrypt_verify_start (gpgme_ctx_t ctx,
|
||||
gpgme_data_t cipher,
|
||||
gpgme_data_t plain);
|
||||
@ -1407,7 +1448,7 @@ struct _gpgme_new_signature
|
||||
gpgme_hash_algo_t hash_algo;
|
||||
|
||||
/* Internal to GPGME, do not use. Must be set to the same value as
|
||||
CLASS below. */
|
||||
* CLASS below. */
|
||||
unsigned long _obsolete_class;
|
||||
|
||||
/* Signature creation time. */
|
||||
@ -1416,10 +1457,10 @@ struct _gpgme_new_signature
|
||||
/* The fingerprint of the signature. */
|
||||
char *fpr;
|
||||
|
||||
/* Deprecated; use SIG_CLASS instead. */
|
||||
#ifdef __cplusplus
|
||||
unsigned int _obsolete_class_2;
|
||||
#else
|
||||
/* Must be set to SIG_CLASS below. */
|
||||
unsigned int class _GPGME_DEPRECATED_OUTSIDE_GPGME(0,4);
|
||||
#endif
|
||||
|
||||
@ -1440,6 +1481,7 @@ struct _gpgme_op_sign_result
|
||||
};
|
||||
typedef struct _gpgme_op_sign_result *gpgme_sign_result_t;
|
||||
|
||||
|
||||
/* Retrieve a pointer to the result of the signing operation. */
|
||||
gpgme_sign_result_t gpgme_op_sign_result (gpgme_ctx_t ctx);
|
||||
|
||||
@ -1533,6 +1575,7 @@ struct _gpgme_signature
|
||||
};
|
||||
typedef struct _gpgme_signature *gpgme_signature_t;
|
||||
|
||||
|
||||
/* An object to return the results of a verify operation.
|
||||
* This structure shall be considered read-only and an application
|
||||
* must not allocate such a structure on its own. */
|
||||
@ -1543,9 +1586,16 @@ struct _gpgme_op_verify_result
|
||||
/* The original file name of the plaintext message, if
|
||||
available. */
|
||||
char *file_name;
|
||||
|
||||
/* The message claims that the content is a MIME object. */
|
||||
unsigned int is_mime : 1;
|
||||
|
||||
/* Internal to GPGME; do not use. */
|
||||
unsigned int _unused : 31;
|
||||
};
|
||||
typedef struct _gpgme_op_verify_result *gpgme_verify_result_t;
|
||||
|
||||
|
||||
/* Retrieve a pointer to the result of the verify operation. */
|
||||
gpgme_verify_result_t gpgme_op_verify_result (gpgme_ctx_t ctx);
|
||||
|
||||
@ -1590,6 +1640,7 @@ struct _gpgme_import_status
|
||||
};
|
||||
typedef struct _gpgme_import_status *gpgme_import_status_t;
|
||||
|
||||
|
||||
/* Import result object.
|
||||
* This structure shall be considered read-only and an application
|
||||
* must not allocate such a structure on its own. */
|
||||
@ -1645,6 +1696,7 @@ struct _gpgme_op_import_result
|
||||
};
|
||||
typedef struct _gpgme_op_import_result *gpgme_import_result_t;
|
||||
|
||||
|
||||
/* Retrieve a pointer to the result of the import operation. */
|
||||
gpgme_import_result_t gpgme_op_import_result (gpgme_ctx_t ctx);
|
||||
|
||||
@ -1702,6 +1754,7 @@ gpgme_error_t gpgme_op_export_keys (gpgme_ctx_t ctx,
|
||||
#define GPGME_CREATE_FORCE (1 << 12) /* Force creation. */
|
||||
#define GPGME_CREATE_NOEXPIRE (1 << 13) /* Create w/o expiration. */
|
||||
|
||||
|
||||
/* An object to return result from a key generation.
|
||||
* This structure shall be considered read-only and an application
|
||||
* must not allocate such a structure on its own. */
|
||||
@ -1732,9 +1785,10 @@ struct _gpgme_op_genkey_result
|
||||
};
|
||||
typedef struct _gpgme_op_genkey_result *gpgme_genkey_result_t;
|
||||
|
||||
|
||||
/* Generate a new keypair and add it to the keyring. PUBKEY and
|
||||
SECKEY should be null for now. PARMS specifies what keys should be
|
||||
generated. */
|
||||
* SECKEY should be null for now. PARMS specifies what keys should be
|
||||
* generated. */
|
||||
gpgme_error_t gpgme_op_genkey_start (gpgme_ctx_t ctx, const char *parms,
|
||||
gpgme_data_t pubkey, gpgme_data_t seckey);
|
||||
gpgme_error_t gpgme_op_genkey (gpgme_ctx_t ctx, const char *parms,
|
||||
@ -1800,7 +1854,7 @@ gpgme_genkey_result_t gpgme_op_genkey_result (gpgme_ctx_t ctx);
|
||||
|
||||
|
||||
/* Delete KEY from the keyring. If ALLOW_SECRET is non-zero, secret
|
||||
keys are also deleted. */
|
||||
* keys are also deleted. */
|
||||
gpgme_error_t gpgme_op_delete_start (gpgme_ctx_t ctx, const gpgme_key_t key,
|
||||
int allow_secret);
|
||||
gpgme_error_t gpgme_op_delete (gpgme_ctx_t ctx, const gpgme_key_t key,
|
||||
@ -1919,7 +1973,7 @@ gpgme_error_t gpgme_op_keylist_end (gpgme_ctx_t ctx);
|
||||
*/
|
||||
|
||||
/* Change the passphrase for KEY. FLAGS is reserved for future use
|
||||
and must be passed as 0. */
|
||||
* and must be passed as 0. */
|
||||
gpgme_error_t gpgme_op_passwd_start (gpgme_ctx_t ctx, gpgme_key_t key,
|
||||
unsigned int flags);
|
||||
gpgme_error_t gpgme_op_passwd (gpgme_ctx_t ctx, gpgme_key_t key,
|
||||
@ -1984,7 +2038,7 @@ gpgme_error_t gpgme_op_trustlist_end (gpgme_ctx_t ctx);
|
||||
void gpgme_trust_item_ref (gpgme_trust_item_t item);
|
||||
|
||||
/* Release a reference to ITEM. If this was the last one the trust
|
||||
item is destroyed. */
|
||||
* item is destroyed. */
|
||||
void gpgme_trust_item_unref (gpgme_trust_item_t item);
|
||||
|
||||
|
||||
@ -2014,8 +2068,8 @@ gpgme_error_t gpgme_op_getauditlog (gpgme_ctx_t ctx, gpgme_data_t output,
|
||||
|
||||
|
||||
/* Run the command FILE with the arguments in ARGV. Connect stdin to
|
||||
DATAIN, stdout to DATAOUT, and STDERR to DATAERR. If one the data
|
||||
streams is NULL, connect to /dev/null instead. */
|
||||
* DATAIN, stdout to DATAOUT, and STDERR to DATAERR. If one the data
|
||||
* streams is NULL, connect to /dev/null instead. */
|
||||
gpgme_error_t gpgme_op_spawn_start (gpgme_ctx_t ctx,
|
||||
const char *file, const char *argv[],
|
||||
gpgme_data_t datain,
|
||||
@ -2031,6 +2085,7 @@ gpgme_error_t gpgme_op_spawn (gpgme_ctx_t ctx,
|
||||
/*
|
||||
* Low-level Assuan protocol access.
|
||||
*/
|
||||
|
||||
typedef gpgme_error_t (*gpgme_assuan_data_cb_t)
|
||||
(void *opaque, const void *data, size_t datalen);
|
||||
|
||||
@ -2042,7 +2097,7 @@ typedef gpgme_error_t (*gpgme_assuan_status_cb_t)
|
||||
(void *opaque, const char *status, const char *args);
|
||||
|
||||
/* Send the Assuan COMMAND and return results via the callbacks.
|
||||
Asynchronous variant. */
|
||||
* Asynchronous variant. */
|
||||
gpgme_error_t gpgme_op_assuan_transact_start (gpgme_ctx_t ctx,
|
||||
const char *command,
|
||||
gpgme_assuan_data_cb_t data_cb,
|
||||
@ -2053,7 +2108,7 @@ gpgme_error_t gpgme_op_assuan_transact_start (gpgme_ctx_t ctx,
|
||||
void *stat_cb_value);
|
||||
|
||||
/* Send the Assuan COMMAND and return results via the callbacks.
|
||||
Synchronous variant. */
|
||||
* Synchronous variant. */
|
||||
gpgme_error_t gpgme_op_assuan_transact_ext (gpgme_ctx_t ctx,
|
||||
const char *command,
|
||||
gpgme_assuan_data_cb_t data_cb,
|
||||
@ -2081,8 +2136,8 @@ typedef struct _gpgme_op_vfs_mount_result *gpgme_vfs_mount_result_t;
|
||||
gpgme_vfs_mount_result_t gpgme_op_vfs_mount_result (gpgme_ctx_t ctx);
|
||||
|
||||
/* The container is automatically unmounted when the context is reset
|
||||
or destroyed. Transmission errors are returned directly,
|
||||
operational errors are returned in OP_ERR. */
|
||||
* or destroyed. Transmission errors are returned directly,
|
||||
* operational errors are returned in OP_ERR. */
|
||||
gpgme_error_t gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file,
|
||||
const char *mount_dir, unsigned int flags,
|
||||
gpgme_error_t *op_err);
|
||||
@ -2097,8 +2152,8 @@ gpgme_error_t gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[],
|
||||
*/
|
||||
|
||||
/* The expert level at which a configuration option or group of
|
||||
options should be displayed. See the gpgconf(1) documentation for
|
||||
more details. */
|
||||
* options should be displayed. See the gpgconf(1) documentation for
|
||||
* more details. */
|
||||
typedef enum
|
||||
{
|
||||
GPGME_CONF_BASIC = 0,
|
||||
@ -2111,7 +2166,7 @@ gpgme_conf_level_t;
|
||||
|
||||
|
||||
/* The data type of a configuration option argument. See the gpgconf(1)
|
||||
documentation for more details. */
|
||||
* documentation for more details. */
|
||||
typedef enum
|
||||
{
|
||||
/* Basic types. */
|
||||
@ -2135,7 +2190,7 @@ gpgme_conf_type_t;
|
||||
|
||||
|
||||
/* This represents a single argument for a configuration option.
|
||||
Which of the members of value is used depends on the ALT_TYPE. */
|
||||
* Which of the members of value is used depends on the ALT_TYPE. */
|
||||
typedef struct gpgme_conf_arg
|
||||
{
|
||||
struct gpgme_conf_arg *next;
|
||||
@ -2152,7 +2207,7 @@ typedef struct gpgme_conf_arg
|
||||
|
||||
|
||||
/* The flags of a configuration option. See the gpgconf
|
||||
documentation for details. */
|
||||
* documentation for details. */
|
||||
#define GPGME_CONF_GROUP (1 << 0)
|
||||
#define GPGME_CONF_OPTIONAL (1 << 1)
|
||||
#define GPGME_CONF_LIST (1 << 2)
|
||||
@ -2164,7 +2219,7 @@ typedef struct gpgme_conf_arg
|
||||
|
||||
|
||||
/* The representation of a single configuration option. See the
|
||||
gpg-conf documentation for details. */
|
||||
* gpg-conf documentation for details. */
|
||||
typedef struct gpgme_conf_opt
|
||||
{
|
||||
struct gpgme_conf_opt *next;
|
||||
@ -2209,7 +2264,7 @@ typedef struct gpgme_conf_opt
|
||||
|
||||
|
||||
/* The representation of a component that can be configured. See the
|
||||
gpg-conf documentation for details. */
|
||||
* gpg-conf documentation for details. */
|
||||
typedef struct gpgme_conf_comp
|
||||
{
|
||||
struct gpgme_conf_comp *next;
|
||||
@ -2232,9 +2287,9 @@ typedef struct gpgme_conf_comp
|
||||
|
||||
|
||||
/* Allocate a new gpgme_conf_arg_t. If VALUE is NULL, a "no arg
|
||||
default" is prepared. If type is a string type, VALUE should point
|
||||
to the string. Else, it should point to an unsigned or signed
|
||||
integer respectively. */
|
||||
* default" is prepared. If type is a string type, VALUE should point
|
||||
* to the string. Else, it should point to an unsigned or signed
|
||||
* integer respectively. */
|
||||
gpgme_error_t gpgme_conf_arg_new (gpgme_conf_arg_t *arg_p,
|
||||
gpgme_conf_type_t type, const void *value);
|
||||
|
||||
@ -2242,10 +2297,10 @@ gpgme_error_t gpgme_conf_arg_new (gpgme_conf_arg_t *arg_p,
|
||||
void gpgme_conf_arg_release (gpgme_conf_arg_t arg, gpgme_conf_type_t type);
|
||||
|
||||
/* Register a change for the value of OPT to ARG. If RESET is 1 (do
|
||||
not use any values but 0 or 1), ARG is ignored and the option is
|
||||
not changed (reverting a previous change). Otherwise, if ARG is
|
||||
NULL, the option is cleared or reset to its default. The change
|
||||
is done with gpgconf's --runtime option to immediately take effect. */
|
||||
* not use any values but 0 or 1), ARG is ignored and the option is
|
||||
* not changed (reverting a previous change). Otherwise, if ARG is
|
||||
* NULL, the option is cleared or reset to its default. The change
|
||||
* is done with gpgconf's --runtime option to immediately take effect. */
|
||||
gpgme_error_t gpgme_conf_opt_change (gpgme_conf_opt_t opt, int reset,
|
||||
gpgme_conf_arg_t arg);
|
||||
|
||||
@ -2336,16 +2391,17 @@ gpgme_query_swdb_result_t gpgme_op_query_swdb_result (gpgme_ctx_t ctx);
|
||||
int gpgme_set_global_flag (const char *name, const char *value);
|
||||
|
||||
/* Check that the library fulfills the version requirement. Note:
|
||||
This is here only for the case where a user takes a pointer from
|
||||
the old version of this function. The new version and macro for
|
||||
run-time checks are below. */
|
||||
* This is here only for the case where a user takes a pointer from
|
||||
* the old version of this function. The new version and macro for
|
||||
* run-time checks are below. */
|
||||
const char *gpgme_check_version (const char *req_version);
|
||||
|
||||
/* Check that the library fulfills the version requirement and check
|
||||
for struct layout mismatch involving bitfields. */
|
||||
/* Do not call this directly; use the macro below. */
|
||||
const char *gpgme_check_version_internal (const char *req_version,
|
||||
size_t offset_sig_validity);
|
||||
|
||||
/* Check that the library fulfills the version requirement and check
|
||||
* for struct layout mismatch involving bitfields. */
|
||||
#define gpgme_check_version(req_version) \
|
||||
gpgme_check_version_internal (req_version, \
|
||||
offsetof (struct _gpgme_signature, validity))
|
||||
@ -2354,19 +2410,19 @@ const char *gpgme_check_version_internal (const char *req_version,
|
||||
const char *gpgme_get_dirinfo (const char *what);
|
||||
|
||||
/* Get the information about the configured and installed engines. A
|
||||
pointer to the first engine in the statically allocated linked list
|
||||
is returned in *INFO. If an error occurs, it is returned. The
|
||||
returned data is valid until the next gpgme_set_engine_info. */
|
||||
* pointer to the first engine in the statically allocated linked list
|
||||
* is returned in *INFO. If an error occurs, it is returned. The
|
||||
* returned data is valid until the next gpgme_set_engine_info. */
|
||||
gpgme_error_t gpgme_get_engine_info (gpgme_engine_info_t *engine_info);
|
||||
|
||||
/* Set the default engine info for the protocol PROTO to the file name
|
||||
FILE_NAME and the home directory HOME_DIR. */
|
||||
* FILE_NAME and the home directory HOME_DIR. */
|
||||
gpgme_error_t gpgme_set_engine_info (gpgme_protocol_t proto,
|
||||
const char *file_name,
|
||||
const char *home_dir);
|
||||
|
||||
/* Verify that the engine implementing PROTO is installed and
|
||||
available. */
|
||||
* available. */
|
||||
gpgme_error_t gpgme_engine_check_version (gpgme_protocol_t proto);
|
||||
|
||||
|
||||
@ -2375,15 +2431,15 @@ void gpgme_result_ref (void *result);
|
||||
void gpgme_result_unref (void *result);
|
||||
|
||||
/* Return a public key algorithm string (e.g. "rsa2048"). Caller must
|
||||
free using gpgme_free. */
|
||||
* free using gpgme_free. */
|
||||
char *gpgme_pubkey_algo_string (gpgme_subkey_t subkey);
|
||||
|
||||
/* Return a statically allocated string with the name of the public
|
||||
key algorithm ALGO, or NULL if that name is not known. */
|
||||
* key algorithm ALGO, or NULL if that name is not known. */
|
||||
const char *gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo);
|
||||
|
||||
/* Return a statically allocated string with the name of the hash
|
||||
algorithm ALGO, or NULL if that name is not known. */
|
||||
* algorithm ALGO, or NULL if that name is not known. */
|
||||
const char *gpgme_hash_algo_name (gpgme_hash_algo_t algo);
|
||||
|
||||
/* Return the addr-spec from a user id. Caller must free the result
|
||||
@ -2535,7 +2591,7 @@ gpgme_error_t gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
|
||||
_GPGME_DEPRECATED(1,7);
|
||||
|
||||
/* The possible signature stati. Deprecated, use error value in sig
|
||||
status. */
|
||||
* status. */
|
||||
typedef enum
|
||||
{
|
||||
GPGME_SIG_STAT_NONE = 0,
|
||||
@ -2552,7 +2608,7 @@ _gpgme_sig_stat_t;
|
||||
typedef _gpgme_sig_stat_t gpgme_sig_stat_t _GPGME_DEPRECATED(0,4);
|
||||
|
||||
/* The available key and signature attributes. Deprecated, use the
|
||||
individual result structures instead. */
|
||||
* individual result structures instead. */
|
||||
typedef enum
|
||||
{
|
||||
GPGME_ATTR_KEYID = 1,
|
||||
@ -2592,18 +2648,18 @@ _gpgme_attr_t;
|
||||
typedef _gpgme_attr_t gpgme_attr_t _GPGME_DEPRECATED(0,4);
|
||||
|
||||
/* Retrieve the signature status of signature IDX in CTX after a
|
||||
successful verify operation in R_STAT (if non-null). The creation
|
||||
time stamp of the signature is returned in R_CREATED (if non-null).
|
||||
The function returns a string containing the fingerprint.
|
||||
Deprecated, use verify result directly. */
|
||||
* successful verify operation in R_STAT (if non-null). The creation
|
||||
* time stamp of the signature is returned in R_CREATED (if non-null).
|
||||
* The function returns a string containing the fingerprint.
|
||||
* Deprecated, use verify result directly. */
|
||||
const char *gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
|
||||
_gpgme_sig_stat_t *r_stat,
|
||||
time_t *r_created) _GPGME_DEPRECATED(0,4);
|
||||
|
||||
/* Retrieve certain attributes of a signature. IDX is the index
|
||||
number of the signature after a successful verify operation. WHAT
|
||||
is an attribute where GPGME_ATTR_EXPIRE is probably the most useful
|
||||
one. WHATIDX is to be passed as 0 for most attributes . */
|
||||
* number of the signature after a successful verify operation. WHAT
|
||||
* is an attribute where GPGME_ATTR_EXPIRE is probably the most useful
|
||||
* one. WHATIDX is to be passed as 0 for most attributes . */
|
||||
unsigned long gpgme_get_sig_ulong_attr (gpgme_ctx_t c, int idx,
|
||||
_gpgme_attr_t what, int whatidx)
|
||||
_GPGME_DEPRECATED(0,4);
|
||||
@ -2613,13 +2669,13 @@ const char *gpgme_get_sig_string_attr (gpgme_ctx_t c, int idx,
|
||||
|
||||
|
||||
/* Get the key used to create signature IDX in CTX and return it in
|
||||
R_KEY. */
|
||||
* R_KEY. */
|
||||
gpgme_error_t gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
|
||||
_GPGME_DEPRECATED(0,4);
|
||||
|
||||
/* Create a new data buffer which retrieves the data from the callback
|
||||
function READ_CB. Deprecated, please use gpgme_data_new_from_cbs
|
||||
instead. */
|
||||
* function READ_CB. Deprecated, please use gpgme_data_new_from_cbs
|
||||
* instead. */
|
||||
gpgme_error_t gpgme_data_new_with_read_cb (gpgme_data_t *r_dh,
|
||||
int (*read_cb) (void*,char *,
|
||||
size_t,size_t*),
|
||||
@ -2627,34 +2683,34 @@ gpgme_error_t gpgme_data_new_with_read_cb (gpgme_data_t *r_dh,
|
||||
_GPGME_DEPRECATED(0,4);
|
||||
|
||||
/* Return the value of the attribute WHAT of KEY, which has to be
|
||||
representable by a string. IDX specifies the sub key or user ID
|
||||
for attributes related to sub keys or user IDs. Deprecated, use
|
||||
key structure directly instead. */
|
||||
* representable by a string. IDX specifies the sub key or user ID
|
||||
* for attributes related to sub keys or user IDs. Deprecated, use
|
||||
* key structure directly instead. */
|
||||
const char *gpgme_key_get_string_attr (gpgme_key_t key, _gpgme_attr_t what,
|
||||
const void *reserved, int idx)
|
||||
_GPGME_DEPRECATED(0,4);
|
||||
|
||||
/* Return the value of the attribute WHAT of KEY, which has to be
|
||||
representable by an unsigned integer. IDX specifies the sub key or
|
||||
user ID for attributes related to sub keys or user IDs.
|
||||
Deprecated, use key structure directly instead. */
|
||||
* representable by an unsigned integer. IDX specifies the sub key or
|
||||
* user ID for attributes related to sub keys or user IDs.
|
||||
* Deprecated, use key structure directly instead. */
|
||||
unsigned long gpgme_key_get_ulong_attr (gpgme_key_t key, _gpgme_attr_t what,
|
||||
const void *reserved, int idx)
|
||||
_GPGME_DEPRECATED(0,4);
|
||||
|
||||
/* Return the value of the attribute WHAT of a signature on user ID
|
||||
UID_IDX in KEY, which has to be representable by a string. IDX
|
||||
specifies the signature. Deprecated, use key structure directly
|
||||
instead. */
|
||||
* UID_IDX in KEY, which has to be representable by a string. IDX
|
||||
* specifies the signature. Deprecated, use key structure directly
|
||||
* instead. */
|
||||
const char *gpgme_key_sig_get_string_attr (gpgme_key_t key, int uid_idx,
|
||||
_gpgme_attr_t what,
|
||||
const void *reserved, int idx)
|
||||
_GPGME_DEPRECATED(0,4);
|
||||
|
||||
/* Return the value of the attribute WHAT of a signature on user ID
|
||||
UID_IDX in KEY, which has to be representable by an unsigned
|
||||
integer string. IDX specifies the signature. Deprecated, use key
|
||||
structure directly instead. */
|
||||
* UID_IDX in KEY, which has to be representable by an unsigned
|
||||
* integer string. IDX specifies the signature. Deprecated, use key
|
||||
* structure directly instead. */
|
||||
unsigned long gpgme_key_sig_get_ulong_attr (gpgme_key_t key, int uid_idx,
|
||||
_gpgme_attr_t what,
|
||||
const void *reserved, int idx)
|
||||
@ -2665,21 +2721,21 @@ gpgme_error_t gpgme_op_import_ext (gpgme_ctx_t ctx, gpgme_data_t keydata,
|
||||
int *nr) _GPGME_DEPRECATED(0,4);
|
||||
|
||||
/* Release the trust item ITEM. Deprecated, use
|
||||
gpgme_trust_item_unref. */
|
||||
* gpgme_trust_item_unref. */
|
||||
void gpgme_trust_item_release (gpgme_trust_item_t item) _GPGME_DEPRECATED(0,4);
|
||||
|
||||
/* Return the value of the attribute WHAT of ITEM, which has to be
|
||||
representable by a string. Deprecated, use trust item structure
|
||||
directly. */
|
||||
* representable by a string. Deprecated, use trust item structure
|
||||
* directly. */
|
||||
const char *gpgme_trust_item_get_string_attr (gpgme_trust_item_t item,
|
||||
_gpgme_attr_t what,
|
||||
const void *reserved, int idx)
|
||||
_GPGME_DEPRECATED(0,4);
|
||||
|
||||
/* Return the value of the attribute WHAT of KEY, which has to be
|
||||
representable by an integer. IDX specifies a running index if the
|
||||
attribute appears more than once in the key. Deprecated, use trust
|
||||
item structure directly. */
|
||||
* representable by an integer. IDX specifies a running index if the
|
||||
* attribute appears more than once in the key. Deprecated, use trust
|
||||
* item structure directly. */
|
||||
int gpgme_trust_item_get_int_attr (gpgme_trust_item_t item, _gpgme_attr_t what,
|
||||
const void *reserved, int idx)
|
||||
_GPGME_DEPRECATED(0,4);
|
||||
|
@ -215,10 +215,15 @@ GPGME_1.0 {
|
||||
gpgme_op_edit;
|
||||
gpgme_op_edit_start;
|
||||
gpgme_op_encrypt;
|
||||
gpgme_op_encrypt_result;
|
||||
gpgme_op_encrypt_sign;
|
||||
gpgme_op_encrypt_sign_start;
|
||||
gpgme_op_encrypt_start;
|
||||
gpgme_op_encrypt_ext;
|
||||
gpgme_op_encrypt_ext_start;
|
||||
gpgme_op_encrypt_sign;
|
||||
gpgme_op_encrypt_sign_ext;
|
||||
gpgme_op_encrypt_sign_start;
|
||||
gpgme_op_encrypt_sign_ext_start;
|
||||
gpgme_op_encrypt_result;
|
||||
|
||||
gpgme_op_export;
|
||||
gpgme_op_export_ext;
|
||||
gpgme_op_export_ext_start;
|
||||
|
@ -358,7 +358,7 @@ _gpgme_parse_key_considered (const char *args,
|
||||
/* Parse the PLAINTEXT status line in ARGS and return the result in
|
||||
FILENAMEP. */
|
||||
gpgme_error_t
|
||||
_gpgme_parse_plaintext (char *args, char **filenamep)
|
||||
_gpgme_parse_plaintext (char *args, char **filenamep, int *r_mime)
|
||||
{
|
||||
char *tail;
|
||||
|
||||
@ -367,7 +367,9 @@ _gpgme_parse_plaintext (char *args, char **filenamep)
|
||||
if (*args == '\0')
|
||||
return 0;
|
||||
|
||||
/* First argument is file type. */
|
||||
/* First argument is file type (a one byte uppercase hex value). */
|
||||
if (args[0] == '6' && args[1] == 'D')
|
||||
*r_mime = 1;
|
||||
while (*args != ' ' && *args != '\0')
|
||||
args++;
|
||||
while (*args == ' ')
|
||||
@ -400,12 +402,21 @@ _gpgme_parse_plaintext (char *args, char **filenamep)
|
||||
|
||||
|
||||
/* Parse a FAILURE status line and return the error code. ARGS is
|
||||
modified to contain the location part. */
|
||||
* modified to contain the location part. Note that for now we ignore
|
||||
* failure codes with a location of gpg-exit; they are too trouble
|
||||
* some. Instead we should eventually record that error in the
|
||||
* context and provide a function to return a fuller error
|
||||
* description; this could then also show the location of the error
|
||||
* (e.g. "option- parser") to make it easier for the user to detect
|
||||
* the actual error. */
|
||||
gpgme_error_t
|
||||
_gpgme_parse_failure (char *args)
|
||||
{
|
||||
char *where, *which;
|
||||
|
||||
if (!strncmp (args, "gpg-exit", 8))
|
||||
return 0;
|
||||
|
||||
where = strchr (args, ' ');
|
||||
if (!where)
|
||||
return trace_gpg_error (GPG_ERR_INV_ENGINE);
|
||||
@ -417,7 +428,5 @@ _gpgme_parse_failure (char *args)
|
||||
if (where)
|
||||
*where = '\0';
|
||||
|
||||
where = args;
|
||||
|
||||
return atoi (which);
|
||||
}
|
||||
|
@ -68,8 +68,8 @@ gpgme_error_t _gpgme_parse_inv_recp (char *args, int for_signing,
|
||||
gpgme_invalid_key_t *key);
|
||||
|
||||
/* Parse the PLAINTEXT status line in ARGS and return the result in
|
||||
FILENAMEP. */
|
||||
gpgme_error_t _gpgme_parse_plaintext (char *args, char **filenamep);
|
||||
FILENAMEP and R_MIME. */
|
||||
gpgme_error_t _gpgme_parse_plaintext (char *args, char **filenamep,int *r_mime);
|
||||
|
||||
/* Parse a FAILURE status line and return the error code. ARGS is
|
||||
modified to contain the location part. */
|
||||
|
@ -165,10 +165,11 @@ time_t _gpgme_parse_timestamp (const char *timestamp, char **endp);
|
||||
* on error or missing timestamp. */
|
||||
unsigned long _gpgme_parse_timestamp_ul (const char *timestamp);
|
||||
|
||||
gpgme_error_t _gpgme_map_gnupg_error (char *err);
|
||||
|
||||
int _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol);
|
||||
|
||||
const char *_gpgme_cipher_algo_name (int algo, gpgme_protocol_t protocol);
|
||||
const char *_gpgme_cipher_mode_name (int algo, gpgme_protocol_t protocol);
|
||||
|
||||
|
||||
/*-- b64dec.c --*/
|
||||
|
||||
|
32
src/verify.c
32
src/verify.c
@ -284,6 +284,7 @@ parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args,
|
||||
gpgme_signature_t sig;
|
||||
char *end = strchr (args, ' ');
|
||||
char *tail;
|
||||
int got_fpr = 0;
|
||||
|
||||
if (end)
|
||||
{
|
||||
@ -370,7 +371,23 @@ parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args,
|
||||
if (!*end)
|
||||
goto parse_err_sig_fail;
|
||||
|
||||
sig->status = strtoul (end, NULL, 10);
|
||||
gpg_err_set_errno (0);
|
||||
sig->status = strtoul (end, &tail, 10);
|
||||
if (errno || end == tail || (*tail && *tail != ' '))
|
||||
goto parse_err_sig_fail;
|
||||
if (!*tail)
|
||||
goto parse_err_sig_ok;
|
||||
end = tail;
|
||||
while (*end == ' ')
|
||||
end++;
|
||||
|
||||
/* Parse the new fingerprint (from the ISSUER_FPR subpacket). */
|
||||
if (!*end || (*end == '-' && (end[1] == ' ' || !end[1])))
|
||||
goto parse_err_sig_ok; /* Okay (just trailing spaces). */
|
||||
sig->fpr = strdup (end);
|
||||
if (!sig->fpr)
|
||||
return gpg_error_from_syserror ();
|
||||
got_fpr = 1;
|
||||
goto parse_err_sig_ok;
|
||||
|
||||
parse_err_sig_fail:
|
||||
@ -382,7 +399,7 @@ parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args,
|
||||
return gpg_error (GPG_ERR_GENERAL);
|
||||
}
|
||||
|
||||
if (*args)
|
||||
if (*args && !got_fpr)
|
||||
{
|
||||
sig->fpr = strdup (args);
|
||||
if (!sig->fpr)
|
||||
@ -1074,9 +1091,14 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
|
||||
case GPGME_STATUS_PLAINTEXT:
|
||||
if (++opd->plaintext_seen > 1)
|
||||
return gpg_error (GPG_ERR_BAD_DATA);
|
||||
err = _gpgme_parse_plaintext (args, &opd->result.file_name);
|
||||
if (err)
|
||||
return err;
|
||||
{
|
||||
int mime = 0;
|
||||
err = _gpgme_parse_plaintext (args, &opd->result.file_name, &mime);
|
||||
if (err)
|
||||
return err;
|
||||
opd->result.is_mime = !!mime;
|
||||
}
|
||||
break;
|
||||
|
||||
case GPGME_STATUS_VERIFICATION_COMPLIANCE_MODE:
|
||||
PARSE_COMPLIANCE_FLAGS (args, opd->current_sig);
|
||||
|
@ -39,7 +39,7 @@ BEGIN
|
||||
VALUE "FileDescription", "GPGME - GnuPG Made Easy\0"
|
||||
VALUE "FileVersion", "@LIBGPGME_LT_CURRENT@.@LIBGPGME_LT_AGE@.@LIBGPGME_LT_REVISION@.@BUILD_REVISION@\0"
|
||||
VALUE "InternalName", "gpgme\0"
|
||||
VALUE "LegalCopyright", "Copyright © 2001-2017 g10 Code GmbH\0"
|
||||
VALUE "LegalCopyright", "Copyright © 2001-2018 g10 Code GmbH\0"
|
||||
VALUE "LegalTrademarks", "\0"
|
||||
VALUE "OriginalFilename", "gpgme.dll\0"
|
||||
VALUE "PrivateBuild", "\0"
|
||||
|
@ -31,31 +31,14 @@
|
||||
|
||||
#include <gpgme.h>
|
||||
|
||||
#define PGM "t-verify"
|
||||
#include "t-support.h"
|
||||
|
||||
|
||||
|
||||
static const char test_text1[] = "Just GNU it!\n";
|
||||
static const char test_text1f[]= "Just GNU it?\n";
|
||||
static const char test_sig1[] =
|
||||
#if 0
|
||||
"-----BEGIN PGP SIGNATURE-----\n"
|
||||
"\n"
|
||||
"iEYEABECAAYFAjoKgjIACgkQLXJ8x2hpdzQMSwCeO/xUrhysZ7zJKPf/FyXA//u1\n"
|
||||
"ZgIAn0204PBR7yxSdQx6CFxugstNqmRv\n"
|
||||
"=yku6\n"
|
||||
"-----END PGP SIGNATURE-----\n"
|
||||
#elif 0
|
||||
"-----BEGIN PGP SIGNATURE-----\n"
|
||||
"Version: GnuPG v1.0.4-2 (GNU/Linux)\n"
|
||||
"Comment: For info see http://www.gnupg.org\n"
|
||||
"\n"
|
||||
"iJcEABECAFcFAjoS8/E1FIAAAAAACAAkZm9vYmFyLjF0aGlzIGlzIGEgbm90YXRp\n"
|
||||
"b24gZGF0YSB3aXRoIDIgbGluZXMaGmh0dHA6Ly93d3cuZ3Uub3JnL3BvbGljeS8A\n"
|
||||
"CgkQLXJ8x2hpdzQLyQCbBW/fgU8ZeWSlWPM1F8umHX17bAAAoIfSNDSp5zM85XcG\n"
|
||||
"iwxMrf+u8v4r\n"
|
||||
"=88Zo\n"
|
||||
"-----END PGP SIGNATURE-----\n"
|
||||
#elif 1
|
||||
"-----BEGIN PGP SIGNATURE-----\n"
|
||||
"\n"
|
||||
"iN0EABECAJ0FAjoS+i9FFIAAAAAAAwA5YmFyw7bDpMO8w58gZGFzIHdhcmVuIFVt\n"
|
||||
@ -64,9 +47,24 @@ static const char test_sig1[] =
|
||||
"Oi8vd3d3Lmd1Lm9yZy9wb2xpY3kvAAoJEC1yfMdoaXc0JBIAoIiLlUsvpMDOyGEc\n"
|
||||
"dADGKXF/Hcb+AKCJWPphZCphduxSvrzH0hgzHdeQaA==\n"
|
||||
"=nts1\n"
|
||||
"-----END PGP SIGNATURE-----\n"
|
||||
#endif
|
||||
;
|
||||
"-----END PGP SIGNATURE-----\n";
|
||||
|
||||
/* The same as test_sig1 but with a second signature for which we do
|
||||
* not have the public key (deleted after signature creation). */
|
||||
static const char test_sig1_plus_unknown_key[] =
|
||||
"-----BEGIN PGP SIGNATURE-----\n"
|
||||
"\n"
|
||||
"iN0EABECAJ0FAjoS+i9FFIAAAAAAAwA5YmFyw7bDpMO8w58gZGFzIHdhcmVuIFVt\n"
|
||||
"bGF1dGUgdW5kIGpldHp0IGVpbiBwcm96ZW50JS1aZWljaGVuNRSAAAAAAAgAJGZv\n"
|
||||
"b2Jhci4xdGhpcyBpcyBhIG5vdGF0aW9uIGRhdGEgd2l0aCAyIGxpbmVzGhpodHRw\n"
|
||||
"Oi8vd3d3Lmd1Lm9yZy9wb2xpY3kvAAoJEC1yfMdoaXc0JBIAoIiLlUsvpMDOyGEc\n"
|
||||
"dADGKXF/Hcb+AKCJWPphZCphduxSvrzH0hgzHdeQaIh1BAAWCAAdFiEENuwqcMZC\n"
|
||||
"brD85btN+RyY8EnUIEwFAlrPR4cACgkQ+RyY8EnUIEyiuAEAm41LJTGUFDzhavRm\n"
|
||||
"jNwqUZxGGOySduW+u/X1lEfV+MYA/2lJOo75rHtD1EG+tkFVWt4Ukj0rjhR132vZ\n"
|
||||
"IOtrYAcG\n"
|
||||
"=yYwZ\n"
|
||||
"-----END PGP SIGNATURE-----\n";
|
||||
|
||||
static const char test_sig2[] =
|
||||
"-----BEGIN PGP MESSAGE-----\n"
|
||||
"\n"
|
||||
@ -91,37 +89,57 @@ static const char double_plaintext_sig[] =
|
||||
|
||||
|
||||
|
||||
/* NO_OF_SIGS is the expected number of signatures. SKIP_SKIPS is
|
||||
* which of these signatures to check (0 based). */
|
||||
static void
|
||||
check_result (gpgme_verify_result_t result, unsigned int summary,
|
||||
const char *fpr,
|
||||
check_result (gpgme_verify_result_t result, int no_of_sigs, int skip_sigs,
|
||||
unsigned int summary, const char *fpr,
|
||||
gpgme_error_t status, int notation)
|
||||
{
|
||||
gpgme_signature_t sig;
|
||||
int n;
|
||||
|
||||
sig = result->signatures;
|
||||
if (!sig || sig->next)
|
||||
for (n=0; sig; sig = sig->next)
|
||||
n++;
|
||||
if (n != no_of_sigs)
|
||||
{
|
||||
fprintf (stderr, "%s:%i: Unexpected number of signatures\n",
|
||||
__FILE__, __LINE__);
|
||||
fprintf (stderr, "%s:%i: Unexpected number of signatures"
|
||||
" (got %d expected %d)\n", PGM, __LINE__, n, no_of_sigs);
|
||||
exit (1);
|
||||
}
|
||||
if (skip_sigs >= n)
|
||||
{
|
||||
fprintf (stderr, "%s:%i: oops SKIPP_SIGS to high\n", PGM, __LINE__);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
for (n=0, sig = result->signatures; n < skip_sigs; sig = sig->next, n++)
|
||||
;
|
||||
|
||||
if (sig->summary != summary)
|
||||
{
|
||||
fprintf (stderr, "%s:%i: Unexpected signature summary: "
|
||||
fprintf (stderr, "%s:%i:sig-%d: Unexpected signature summary: "
|
||||
"want=0x%x have=0x%x\n",
|
||||
__FILE__, __LINE__, summary, sig->summary);
|
||||
PGM, __LINE__, skip_sigs, summary, sig->summary);
|
||||
exit (1);
|
||||
}
|
||||
if (strcmp (sig->fpr, fpr))
|
||||
{
|
||||
fprintf (stderr, "%s:%i: Unexpected fingerprint: %s\n",
|
||||
__FILE__, __LINE__, sig->fpr);
|
||||
exit (1);
|
||||
if (strlen (sig->fpr) == 16 && strlen (fpr) == 40
|
||||
&& !strncmp (sig->fpr, fpr + 24, 16))
|
||||
; /* okay because gnupg < 2.2.6 only shows the keyid. */
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "%s:%i:sig-%d: Unexpected fingerprint: %s\n",
|
||||
PGM, __LINE__, skip_sigs, sig->fpr);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
if (gpgme_err_code (sig->status) != status)
|
||||
{
|
||||
fprintf (stderr, "%s:%i: Unexpected signature status: %s\n",
|
||||
__FILE__, __LINE__, gpgme_strerror (sig->status));
|
||||
fprintf (stderr, "%s:%i:sig-%d: Unexpected signature status: %s\n",
|
||||
PGM, __LINE__, skip_sigs, gpgme_strerror (sig->status));
|
||||
exit (1);
|
||||
}
|
||||
if (notation)
|
||||
@ -166,8 +184,8 @@ check_result (gpgme_verify_result_t result, unsigned int summary,
|
||||
}
|
||||
if (!any)
|
||||
{
|
||||
fprintf (stderr, "%s:%i: Unexpected notation data\n",
|
||||
__FILE__, __LINE__);
|
||||
fprintf (stderr, "%s:%i:sig-%d: Unexpected notation data\n",
|
||||
PGM, __LINE__, skip_sigs);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
@ -175,28 +193,30 @@ check_result (gpgme_verify_result_t result, unsigned int summary,
|
||||
{
|
||||
if (expected_notations[i].seen != 1)
|
||||
{
|
||||
fprintf (stderr, "%s:%i: Missing or duplicate notation data\n",
|
||||
__FILE__, __LINE__);
|
||||
fprintf (stderr, "%s:%i:sig-%d: "
|
||||
"Missing or duplicate notation data\n",
|
||||
PGM, __LINE__, skip_sigs);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sig->wrong_key_usage)
|
||||
{
|
||||
fprintf (stderr, "%s:%i: Unexpectedly wrong key usage\n",
|
||||
__FILE__, __LINE__);
|
||||
fprintf (stderr, "%s:%i:sig-%d: Unexpectedly wrong key usage\n",
|
||||
PGM, __LINE__, skip_sigs);
|
||||
exit (1);
|
||||
}
|
||||
if (sig->validity != GPGME_VALIDITY_UNKNOWN)
|
||||
{
|
||||
fprintf (stderr, "%s:%i: Unexpected validity: %i\n",
|
||||
__FILE__, __LINE__, sig->validity);
|
||||
fprintf (stderr, "%s:%i:sig-%d: Unexpected validity: %i\n",
|
||||
PGM, __LINE__, skip_sigs, sig->validity);
|
||||
exit (1);
|
||||
}
|
||||
if (gpgme_err_code (sig->validity_reason) != GPG_ERR_NO_ERROR)
|
||||
{
|
||||
fprintf (stderr, "%s:%i: Unexpected validity reason: %s\n",
|
||||
__FILE__, __LINE__, gpgme_strerror (sig->validity_reason));
|
||||
fprintf (stderr, "%s:%i:sig-%d: Unexpected validity reason: %s\n",
|
||||
PGM, __LINE__, skip_sigs,
|
||||
gpgme_strerror (sig->validity_reason));
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
@ -227,7 +247,7 @@ main (int argc, char *argv[])
|
||||
err = gpgme_op_verify (ctx, sig, text, NULL);
|
||||
fail_if_err (err);
|
||||
result = gpgme_op_verify_result (ctx);
|
||||
check_result (result, 0, "A0FF4590BB6122EDEF6E3C542D727CC768697734",
|
||||
check_result (result, 1, 0, 0, "A0FF4590BB6122EDEF6E3C542D727CC768697734",
|
||||
GPG_ERR_NO_ERROR, 1);
|
||||
|
||||
/* Checking a manipulated message. */
|
||||
@ -238,9 +258,29 @@ main (int argc, char *argv[])
|
||||
err = gpgme_op_verify (ctx, sig, text, NULL);
|
||||
fail_if_err (err);
|
||||
result = gpgme_op_verify_result (ctx);
|
||||
check_result (result, GPGME_SIGSUM_RED, "2D727CC768697734",
|
||||
check_result (result, 1, 0, GPGME_SIGSUM_RED, "2D727CC768697734",
|
||||
GPG_ERR_BAD_SIGNATURE, 0);
|
||||
|
||||
/* Checking a valid message. Bu that one has a second signature
|
||||
* made by an unknown key. */
|
||||
gpgme_data_release (text);
|
||||
gpgme_data_release (sig);
|
||||
err = gpgme_data_new_from_mem (&text, test_text1, strlen (test_text1), 0);
|
||||
fail_if_err (err);
|
||||
err = gpgme_data_new_from_mem (&sig, test_sig1_plus_unknown_key,
|
||||
strlen (test_sig1_plus_unknown_key), 0);
|
||||
fail_if_err (err);
|
||||
err = gpgme_op_verify (ctx, sig, text, NULL);
|
||||
fail_if_err (err);
|
||||
result = gpgme_op_verify_result (ctx);
|
||||
check_result (result, 2, 0, 0,
|
||||
"A0FF4590BB6122EDEF6E3C542D727CC768697734",
|
||||
GPG_ERR_NO_ERROR, 1);
|
||||
check_result (result, 2, 1, GPGME_SIGSUM_KEY_MISSING,
|
||||
"36EC2A70C6426EB0FCE5BB4DF91C98F049D4204C",
|
||||
GPG_ERR_NO_PUBKEY, 0);
|
||||
|
||||
|
||||
/* Checking a normal signature. */
|
||||
gpgme_data_release (sig);
|
||||
gpgme_data_release (text);
|
||||
@ -251,7 +291,7 @@ main (int argc, char *argv[])
|
||||
err = gpgme_op_verify (ctx, sig, NULL, text);
|
||||
fail_if_err (err);
|
||||
result = gpgme_op_verify_result (ctx);
|
||||
check_result (result, 0, "A0FF4590BB6122EDEF6E3C542D727CC768697734",
|
||||
check_result (result, 1, 0, 0, "A0FF4590BB6122EDEF6E3C542D727CC768697734",
|
||||
GPG_ERR_NO_ERROR, 0);
|
||||
|
||||
|
||||
@ -267,7 +307,7 @@ main (int argc, char *argv[])
|
||||
if (gpgme_err_code (err) != GPG_ERR_BAD_DATA)
|
||||
{
|
||||
fprintf (stderr, "%s:%i: Double plaintext message not detected\n",
|
||||
__FILE__, __LINE__);
|
||||
PGM, __LINE__);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@ -278,7 +318,7 @@ main (int argc, char *argv[])
|
||||
if (!s || strcmp (s, "foo@example.org"))
|
||||
{
|
||||
fprintf (stderr, "%s:%i: gpgme_{set,get}_sender mismatch\n",
|
||||
__FILE__, __LINE__);
|
||||
PGM, __LINE__);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@ -288,7 +328,7 @@ main (int argc, char *argv[])
|
||||
if (!s || strcmp (s, "bar@example.org"))
|
||||
{
|
||||
fprintf (stderr, "%s:%i: gpgme_{set,get}_sender mismatch\n",
|
||||
__FILE__, __LINE__);
|
||||
PGM, __LINE__);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@ -298,7 +338,7 @@ main (int argc, char *argv[])
|
||||
if (!s || strcmp (s, "foo@example.org"))
|
||||
{
|
||||
fprintf (stderr, "%s:%i: gpgme_{set,get}_sender mismatch\n",
|
||||
__FILE__, __LINE__);
|
||||
PGM, __LINE__);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@ -306,7 +346,7 @@ main (int argc, char *argv[])
|
||||
if (gpgme_err_code (err) != GPG_ERR_INV_VALUE)
|
||||
{
|
||||
fprintf (stderr, "%s:%i: gpgme_set_sender didn't detect bogus address\n",
|
||||
__FILE__, __LINE__);
|
||||
PGM, __LINE__);
|
||||
exit (1);
|
||||
}
|
||||
/* (the former address should still be there.) */
|
||||
@ -314,7 +354,7 @@ main (int argc, char *argv[])
|
||||
if (!s || strcmp (s, "foo@example.org"))
|
||||
{
|
||||
fprintf (stderr, "%s:%i: gpgme_{set,get}_sender mismatch\n",
|
||||
__FILE__, __LINE__);
|
||||
PGM, __LINE__);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
@ -53,19 +53,21 @@ print_result (gpgme_decrypt_result_t result)
|
||||
gpgme_recipient_t recp;
|
||||
int count = 0;
|
||||
|
||||
printf ("Original file name: %s\n", nonnull(result->file_name));
|
||||
printf ("Wrong key usage: %i\n", result->wrong_key_usage);
|
||||
printf ("Unsupported algorithm: %s\n",
|
||||
nonnull(result->unsupported_algorithm));
|
||||
if (result->session_key)
|
||||
printf ("Session key: %s\n", result->session_key);
|
||||
printf ("Original file name .: %s\n", nonnull(result->file_name));
|
||||
printf ("Wrong key usage ....: %s\n", result->wrong_key_usage? "yes":"no");
|
||||
printf ("Compliance de-vs ...: %s\n", result->is_de_vs? "yes":"no");
|
||||
printf ("MIME flag ..........: %s\n", result->is_mime? "yes":"no");
|
||||
printf ("Unsupported algo ...: %s\n", nonnull(result->unsupported_algorithm));
|
||||
printf ("Session key ........: %s\n", nonnull (result->session_key));
|
||||
printf ("Symmetric algorithm : %s\n", result->symkey_algo);
|
||||
|
||||
for (recp = result->recipients; recp->next; recp = recp->next)
|
||||
for (recp = result->recipients; recp && recp->next; recp = recp->next)
|
||||
{
|
||||
printf ("recipient %d\n", count++);
|
||||
printf ("Recipient ...: %d\n", count++);
|
||||
printf (" status ....: %s\n", gpgme_strerror (recp->status));
|
||||
printf (" keyid: %s\n", nonnull (recp->keyid));
|
||||
printf (" algo ...: %s\n", gpgme_pubkey_algo_name (recp->pubkey_algo));
|
||||
printf (" keyid .....: %s\n", nonnull (recp->keyid));
|
||||
printf (" algo ......: %s\n",
|
||||
gpgme_pubkey_algo_name (recp->pubkey_algo));
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,6 +84,7 @@ show_usage (int ex)
|
||||
" --export-session-key show the session key\n"
|
||||
" --override-session-key STRING use STRING as session key\n"
|
||||
" --request-origin STRING use STRING as request origin\n"
|
||||
" --no-symkey-cache disable the use of that cache\n"
|
||||
" --unwrap remove only the encryption layer\n"
|
||||
, stderr);
|
||||
exit (ex);
|
||||
@ -104,6 +107,7 @@ main (int argc, char **argv)
|
||||
int export_session_key = 0;
|
||||
const char *override_session_key = NULL;
|
||||
const char *request_origin = NULL;
|
||||
int no_symkey_cache = 0;
|
||||
int raw_output = 0;
|
||||
|
||||
if (argc)
|
||||
@ -160,6 +164,11 @@ main (int argc, char **argv)
|
||||
request_origin = *argv;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--no-symkey-cache"))
|
||||
{
|
||||
no_symkey_cache = 1;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--unwrap"))
|
||||
{
|
||||
flags |= GPGME_DECRYPT_UNWRAP;
|
||||
@ -226,6 +235,17 @@ main (int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (no_symkey_cache)
|
||||
{
|
||||
err = gpgme_set_ctx_flag (ctx, "no-symkey-cache", "1");
|
||||
if (err)
|
||||
{
|
||||
fprintf (stderr, PGM ": error setting no-symkey-cache: %s\n",
|
||||
gpgme_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
err = gpgme_data_new_from_stream (&in, fp_in);
|
||||
if (err)
|
||||
{
|
||||
|
@ -37,6 +37,19 @@
|
||||
static int verbose;
|
||||
|
||||
|
||||
static char *
|
||||
xstrdup (const char *string)
|
||||
{
|
||||
char *p = strdup (string);
|
||||
if (!p)
|
||||
{
|
||||
fprintf (stderr, "strdup failed\n");
|
||||
exit (2);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static gpg_error_t
|
||||
status_cb (void *opaque, const char *keyword, const char *value)
|
||||
{
|
||||
@ -80,17 +93,19 @@ show_usage (int ex)
|
||||
{
|
||||
fputs ("usage: " PGM " [options] FILE\n\n"
|
||||
"Options:\n"
|
||||
" --verbose run in verbose mode\n"
|
||||
" --status print status lines from the backend\n"
|
||||
" --progress print progress info\n"
|
||||
" --openpgp use the OpenPGP protocol (default)\n"
|
||||
" --cms use the CMS protocol\n"
|
||||
" --uiserver use the UI server\n"
|
||||
" --loopback use a loopback pinentry\n"
|
||||
" --key NAME encrypt to key NAME\n"
|
||||
" --throw-keyids use this option\n"
|
||||
" --wrap assume input is valid OpenPGP message\n"
|
||||
" --symmetric encrypt symmetric (OpenPGP only)\n"
|
||||
" --verbose run in verbose mode\n"
|
||||
" --status print status lines from the backend\n"
|
||||
" --progress print progress info\n"
|
||||
" --openpgp use the OpenPGP protocol (default)\n"
|
||||
" --cms use the CMS protocol\n"
|
||||
" --uiserver use the UI server\n"
|
||||
" --loopback use a loopback pinentry\n"
|
||||
" --key NAME encrypt to key NAME\n"
|
||||
" --keystring NAMES encrypt to ';' delimited NAMES\n"
|
||||
" --throw-keyids use this option\n"
|
||||
" --no-symkey-cache disable the use of that cache\n"
|
||||
" --wrap assume input is valid OpenPGP message\n"
|
||||
" --symmetric encrypt symmetric (OpenPGP only)\n"
|
||||
, stderr);
|
||||
exit (ex);
|
||||
}
|
||||
@ -102,7 +117,6 @@ main (int argc, char **argv)
|
||||
int last_argc = -1;
|
||||
gpgme_error_t err;
|
||||
gpgme_ctx_t ctx;
|
||||
const char *key_string = NULL;
|
||||
gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
|
||||
gpgme_data_t in, out;
|
||||
gpgme_encrypt_result_t result;
|
||||
@ -112,9 +126,11 @@ main (int argc, char **argv)
|
||||
char *keyargs[10];
|
||||
gpgme_key_t keys[10+1];
|
||||
int keycount = 0;
|
||||
char *keystring = NULL;
|
||||
int i;
|
||||
gpgme_encrypt_flags_t flags = GPGME_ENCRYPT_ALWAYS_TRUST;
|
||||
gpgme_off_t offset;
|
||||
int no_symkey_cache = 0;
|
||||
|
||||
if (argc)
|
||||
{ argc--; argv++; }
|
||||
@ -172,6 +188,17 @@ main (int argc, char **argv)
|
||||
keyargs[keycount++] = *argv;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--keystring"))
|
||||
{
|
||||
argc--; argv++;
|
||||
if (!argc)
|
||||
show_usage (1);
|
||||
keystring = xstrdup (*argv);
|
||||
for (i=0; keystring[i]; i++)
|
||||
if (keystring[i] == ';')
|
||||
keystring[i] = '\n';
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--throw-keyids"))
|
||||
{
|
||||
flags |= GPGME_ENCRYPT_THROW_KEYIDS;
|
||||
@ -192,6 +219,11 @@ main (int argc, char **argv)
|
||||
flags |= GPGME_ENCRYPT_SYMMETRIC;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--no-symkey-cache"))
|
||||
{
|
||||
no_symkey_cache = 1;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strncmp (*argv, "--", 2))
|
||||
show_usage (1);
|
||||
|
||||
@ -200,15 +232,6 @@ main (int argc, char **argv)
|
||||
if (argc != 1)
|
||||
show_usage (1);
|
||||
|
||||
if (key_string && protocol == GPGME_PROTOCOL_UISERVER)
|
||||
{
|
||||
fprintf (stderr, PGM ": ignoring --key in UI-server mode\n");
|
||||
key_string = NULL;
|
||||
}
|
||||
|
||||
if (!key_string)
|
||||
key_string = "test";
|
||||
|
||||
init_gpgme (protocol);
|
||||
|
||||
err = gpgme_new (&ctx);
|
||||
@ -227,6 +250,16 @@ main (int argc, char **argv)
|
||||
gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
|
||||
gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
|
||||
}
|
||||
if (no_symkey_cache)
|
||||
{
|
||||
err = gpgme_set_ctx_flag (ctx, "no-symkey-cache", "1");
|
||||
if (err)
|
||||
{
|
||||
fprintf (stderr, PGM ": error setting no-symkey-cache: %s\n",
|
||||
gpgme_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i < keycount; i++)
|
||||
{
|
||||
@ -281,7 +314,8 @@ main (int argc, char **argv)
|
||||
err = gpgme_data_new (&out);
|
||||
fail_if_err (err);
|
||||
|
||||
err = gpgme_op_encrypt (ctx, keycount ? keys : NULL, flags, in, out);
|
||||
err = gpgme_op_encrypt_ext (ctx, keycount ? keys : NULL, keystring,
|
||||
flags, in, out);
|
||||
result = gpgme_op_encrypt_result (ctx);
|
||||
if (result)
|
||||
print_result (result);
|
||||
@ -301,5 +335,6 @@ main (int argc, char **argv)
|
||||
for (i=0; i < keycount; i++)
|
||||
gpgme_key_unref (keys[i]);
|
||||
gpgme_release (ctx);
|
||||
free (keystring);
|
||||
return 0;
|
||||
}
|
||||
|
@ -136,10 +136,11 @@ print_result (gpgme_verify_result_t result)
|
||||
gpgme_tofu_info_t ti;
|
||||
int count = 0;
|
||||
|
||||
printf ("Original file name: %s\n", nonnull(result->file_name));
|
||||
printf ("Original file name .: %s\n", nonnull(result->file_name));
|
||||
printf ("MIME flag ..........: %s\n", result->is_mime? "yes":"no");
|
||||
for (sig = result->signatures; sig; sig = sig->next)
|
||||
{
|
||||
printf ("Signature %d\n", count++);
|
||||
printf ("Signature ...: %d\n", count++);
|
||||
printf (" status ....: %s\n", gpgme_strerror (sig->status));
|
||||
printf (" summary ...:"); print_summary (sig->summary); putchar ('\n');
|
||||
printf (" fingerprint: %s\n", nonnull (sig->fpr));
|
||||
@ -163,17 +164,24 @@ print_result (gpgme_verify_result_t result)
|
||||
);
|
||||
for (nt = sig->notations; nt; nt = nt->next)
|
||||
{
|
||||
printf (" notation ..: '%s'\n", nt->name);
|
||||
if (strlen (nt->name) != nt->name_len)
|
||||
printf (" warning : name larger (%d)\n", nt->name_len);
|
||||
printf (" flags ...:%s%s (0x%02x)\n",
|
||||
nt->critical? " critical":"",
|
||||
nt->human_readable? " human":"",
|
||||
nt->flags);
|
||||
if (nt->value)
|
||||
printf (" value ...: '%s'\n", nt->value);
|
||||
if (nt->name)
|
||||
{
|
||||
printf (" notation ..: '%s'\n", nt->name);
|
||||
if (strlen (nt->name) != nt->name_len)
|
||||
printf (" warning .: name larger (%d)\n", nt->name_len);
|
||||
printf (" flags ...:%s%s (0x%02x)\n",
|
||||
nt->critical? " critical":"",
|
||||
nt->human_readable? " human":"",
|
||||
nt->flags);
|
||||
if (nt->value)
|
||||
printf (" value ...: '%s'\n", nt->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf (" policy ....: '%s'\n", nt->value);
|
||||
}
|
||||
if ((nt->value?strlen (nt->value):0) != nt->value_len)
|
||||
printf (" warning : value larger (%d)\n", nt->value_len);
|
||||
printf (" warning .: value larger (%d)\n", nt->value_len);
|
||||
}
|
||||
if (sig->key)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user